source: trunk/modules/vci_block_device_tsar/caba/source/src/vci_block_device_tsar.cpp @ 895

Last change on this file since 895 was 895, checked in by porquet, 9 years ago

vci_block_device: display IRQ once when in debug mode and close diskfile
properly

File size: 30.4 KB
RevLine 
[151]1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6, Asim
24 *         alain.greiner@lip6.fr april 2011
25 *
26 * Maintainers: alain
27 */
28
29#include <stdint.h>
30#include <iostream>
31#include <fcntl.h>
[374]32#include "vci_block_device_tsar.h"
[599]33#include "block_device_tsar.h"
[151]34
[580]35#define DEBUG_BDEV   0
36
[151]37namespace soclib { namespace caba {
38
[374]39#define tmpl(t) template<typename vci_param> t VciBlockDeviceTsar<vci_param>
[151]40
41using namespace soclib::caba;
42using namespace soclib::common;
43
44////////////////////////
45tmpl(void)::transition()
46{
47    if(p_resetn.read() == false) 
48    {
[392]49        r_initiator_fsm   = M_IDLE;
50        r_target_fsm      = T_IDLE;
51        r_irq_enable      = true;
52        r_go              = false;
[260]53        return;
[151]54    } 
55
56    //////////////////////////////////////////////////////////////////////////////
57    // The Target FSM controls the following registers:
58    // r_target_fsm, r_irq_enable, r_nblocks, r_buf adress, r_lba, r_go, r_read
59    //////////////////////////////////////////////////////////////////////////////
60
61    switch(r_target_fsm) {
[260]62    ////////////
[151]63    case T_IDLE:
64    {
65        if ( p_vci_target.cmdval.read() ) 
66        { 
67            r_srcid = p_vci_target.srcid.read();
68            r_trdid = p_vci_target.trdid.read();
69            r_pktid = p_vci_target.pktid.read();
[260]70            sc_dt::sc_uint<vci_param::N> address = p_vci_target.address.read();
[408]71
72            bool found = false;
73            std::list<soclib::common::Segment>::iterator seg;
74            for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
75            {
76                if ( seg->contains(address) ) found = true;
77            }
78 
[151]79            bool                  read    = (p_vci_target.cmd.read() == vci_param::CMD_READ);
[392]80            uint32_t              cell    = (uint32_t)((address & 0x3F)>>2);
[151]81
[408]82            if     ( !read && not found )                         r_target_fsm = T_WRITE_ERROR;
83            else if(  read && not found )                         r_target_fsm = T_READ_ERROR;
84            else if( !read && not p_vci_target.eop.read() )       r_target_fsm = T_WRITE_ERROR;
85            else if(  read && not p_vci_target.eop.read() )       r_target_fsm = T_READ_ERROR;
[260]86            else if( !read && (cell == BLOCK_DEVICE_BUFFER) )     r_target_fsm = T_WRITE_BUFFER;
87            else if(  read && (cell == BLOCK_DEVICE_BUFFER) )     r_target_fsm = T_READ_BUFFER;
[392]88            else if( !read && (cell == BLOCK_DEVICE_BUFFER_EXT) ) r_target_fsm = T_WRITE_BUFFER_EXT;
89            else if(  read && (cell == BLOCK_DEVICE_BUFFER_EXT) ) r_target_fsm = T_READ_BUFFER_EXT;
[260]90            else if( !read && (cell == BLOCK_DEVICE_COUNT) )      r_target_fsm = T_WRITE_COUNT;
91            else if(  read && (cell == BLOCK_DEVICE_COUNT) )      r_target_fsm = T_READ_COUNT;
92            else if( !read && (cell == BLOCK_DEVICE_LBA) )        r_target_fsm = T_WRITE_LBA;
93            else if(  read && (cell == BLOCK_DEVICE_LBA) )        r_target_fsm = T_READ_LBA;
94            else if( !read && (cell == BLOCK_DEVICE_OP) )         r_target_fsm = T_WRITE_OP;
95            else if(  read && (cell == BLOCK_DEVICE_STATUS) )     r_target_fsm = T_READ_STATUS;
96            else if( !read && (cell == BLOCK_DEVICE_IRQ_ENABLE) ) r_target_fsm = T_WRITE_IRQEN;
97            else if(  read && (cell == BLOCK_DEVICE_IRQ_ENABLE) ) r_target_fsm = T_READ_IRQEN;
98            else if(  read && (cell == BLOCK_DEVICE_SIZE) )       r_target_fsm = T_READ_SIZE;
99            else if(  read && (cell == BLOCK_DEVICE_BLOCK_SIZE) ) r_target_fsm = T_READ_BLOCK;
[580]100
101            // get write data value for both 32 bits and 64 bits data width
102            if( (vci_param::B == 8) and (p_vci_target.be.read() == 0xF0) ) 
103                r_tdata = (uint32_t)(p_vci_target.wdata.read()>>32);
104            else
105                r_tdata = p_vci_target.wdata.read();
[151]106        }
107        break;
108    }
[260]109    ////////////////////
[151]110    case T_WRITE_BUFFER:
111    {
[580]112            if (p_vci_target.rspack.read() ) 
113        {
[522]114            if (r_initiator_fsm.read() == M_IDLE)
115            {
[580]116
117#if DEBUG_BDEV
118std::cout << "  <BDEV_TGT WRITE_BUFFER> value = " << r_tdata.read() << std::endl;
119#endif
[522]120                r_buf_address = (uint64_t)r_tdata.read();
121                r_target_fsm  = T_IDLE;
[580]122                }
[392]123        }
[151]124        break;
125    }
[392]126    ////////////////////////
127    case T_WRITE_BUFFER_EXT:
128    {
[580]129        if (p_vci_target.rspack.read() ) 
130        {
[522]131            if (r_initiator_fsm.read() == M_IDLE)
132            {
[580]133
134#if DEBUG_BDEV
135std::cout << "  <BDEV_TGT WRITE_BUFFER_EXT> value = " << r_tdata.read() << std::endl;
136#endif
137                r_buf_address = r_buf_address.read() + (((uint64_t)r_tdata.read())<<32);
[522]138                r_target_fsm  = T_IDLE;
[580]139            }
[392]140        }
141        break;
142    }
[260]143    ///////////////////
[151]144    case T_WRITE_COUNT:
145    {
[580]146        if (p_vci_target.rspack.read() ) 
147        {
[522]148            if (r_initiator_fsm.read() == M_IDLE)
149            {
[580]150
151#if DEBUG_BDEV
152std::cout << "  <BDEV_TGT WRITE_COUNT> value = " << r_tdata.read() << std::endl;
153#endif
[522]154                r_nblocks    = (uint32_t)r_tdata.read();
155                r_target_fsm = T_IDLE;
156            }
[580]157        }
[151]158        break;
159    }
[260]160    /////////////////
[151]161    case T_WRITE_LBA:
162    {
[580]163        if (p_vci_target.rspack.read() ) 
164        {
165            if (r_initiator_fsm.read() == M_IDLE) 
166            {
167
168#if DEBUG_BDEV
169std::cout << "  <BDEV_TGT WRITE_LBA> value = " << r_tdata.read() << std::endl;
[522]170#endif
171                r_lba        = (uint32_t)r_tdata.read();
172                r_target_fsm = T_IDLE;
173            }
[580]174        }
[151]175        break;
176    }
[260]177    ////////////////
[151]178    case T_WRITE_OP:
179    {
[392]180        if ( p_vci_target.rspack.read() ) 
[151]181        {
[522]182            if ( ((uint32_t)r_tdata.read() == BLOCK_DEVICE_READ) and
[392]183                 (r_initiator_fsm.read() == M_IDLE) )
[151]184            {
[580]185
186#if DEBUG_BDEV
[848]187std::cout << "  <BDEV_TGT WRITE_OP> value = READ" << std::endl;
[580]188#endif
[151]189                r_read = true;
[392]190                r_go   = true;
[151]191            }
[522]192            else if ( ((uint32_t)r_tdata.read() == BLOCK_DEVICE_WRITE) and
[392]193                      (r_initiator_fsm.read() == M_IDLE) )
[151]194            {
[580]195
196#if DEBUG_BDEV
[848]197std::cout << "  <BDEV_TGT WRITE_OP> value = WRITE" << std::endl;
[580]198#endif
[151]199                r_read = false;
[392]200                r_go   = true;
[151]201            }
[392]202            else
203            {
[580]204
205#if DEBUG_BDEV
[848]206std::cout << "  <BDEV_TGT WRITE_OP> value = SOFT RESET" << std::endl;
[580]207#endif
[392]208                r_go   = false;
209            }
210            r_target_fsm = T_IDLE;
[151]211        }
212        break;
213    }
[260]214    ///////////////////
[151]215    case T_WRITE_IRQEN:
216    {
[392]217        if ( p_vci_target.rspack.read() ) 
218        {
[580]219
220#if DEBUG_BDEV
221std::cout << "  <BDEV_TGT WRITE_IRQEN> value = " << r_tdata.read() << std::endl;
[522]222#endif
[392]223            r_target_fsm = T_IDLE;
[522]224            r_irq_enable = (r_tdata.read() != 0);
[392]225        }
[151]226        break;
227    }
[260]228    ///////////////////
[151]229    case T_READ_BUFFER:
[392]230    case T_READ_BUFFER_EXT:
[151]231    case T_READ_COUNT:
232    case T_READ_LBA:
233    case T_READ_IRQEN:
234    case T_READ_SIZE:
235    case T_READ_BLOCK:
236    case T_READ_ERROR:
237    case T_WRITE_ERROR:
238    {
239        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
240        break;
241    }
[260]242    ///////////////////
[151]243    case T_READ_STATUS:
244    {
245        if ( p_vci_target.rspack.read() ) 
246        {
247            r_target_fsm = T_IDLE;
248            if( (r_initiator_fsm == M_READ_SUCCESS ) ||
249                (r_initiator_fsm == M_READ_ERROR   ) ||
250                (r_initiator_fsm == M_WRITE_SUCCESS) ||
251                (r_initiator_fsm == M_WRITE_ERROR  ) ) r_go = false;
252        }
253        break;
254    }
255    } // end switch target fsm
256       
[260]257    //////////////////////////////////////////////////////////////////////////////
258    // The initiator FSM executes a loop, transfering one block per iteration.
259    // Each block is split in bursts, and the number of bursts depends
260    // on the memory buffer alignment on a burst boundary:
[400]261    // - If buffer aligned, all burst have the same length (m_words_per burst)
[260]262    //   and the number of bursts is (m_bursts_per_block).
263    // - If buffer not aligned, the number of bursts is (m_bursts_per_block + 1)
[400]264    //   and first and last burst are shorter, because all words in a burst
[260]265    //   must be contained in a single cache line.
[400]266    //   first burst => nwords = m_words_per_burst - offset
267    //   last  burst => nwords = offset
268    //   other burst => nwords = m_words_per_burst
[260]269    //////////////////////////////////////////////////////////////////////////////
270
271    switch( r_initiator_fsm.read() ) {
272    ////////////
273    case M_IDLE:        // check buffer alignment to compute the number of bursts
[151]274    {
[260]275        if ( r_go.read() ) 
[151]276        {
[260]277            r_index         = 0;
[151]278            r_block_count   = 0;
279            r_burst_count   = 0;
[433]280            r_words_count   = 0;
[151]281            r_latency_count = m_latency;
282
[260]283            // compute r_burst_offset (zero when buffer aligned)
[400]284            r_burst_offset = (uint32_t)((r_buf_address.read()>>2) % m_words_per_burst);
[260]285
286            // start tranfer
287            if ( r_read.read() )        r_initiator_fsm = M_READ_BLOCK;
288            else                    r_initiator_fsm = M_WRITE_BURST;
[151]289        }
290        break;
[260]291    } 
292    //////////////////
[228]293    case M_READ_BLOCK:  // read one block from disk after waiting m_latency cycles
[151]294    {
[260]295        if ( r_latency_count.read() == 0 )
[151]296        {
297            r_latency_count = m_latency;
[400]298            ::lseek(m_fd, (r_lba + r_block_count)*m_words_per_block*4, SEEK_SET);
299            if( ::read(m_fd, r_local_buffer, m_words_per_block*4) < 0 ) 
[151]300            {
[260]301                r_initiator_fsm = M_READ_ERROR;
[151]302            }
303            else   
304            {
[260]305                r_burst_count   = 0;
[580]306                r_words_count   = 0;
[260]307                r_initiator_fsm = M_READ_BURST;
[151]308            }
[608]309
310////////////////////////////////////////////////////////////////////////////////////////
311//std::cout << "***** Block content after read for lba "
312//          << std::hex << r_lba.read() << " **************" << std::endl;
313//for ( size_t line=0 ; line<16 ; line++ )
314//{
315//    for ( size_t word=0 ; word<8 ; word++ )
316//    {
317//        std::cout << std::hex << r_local_buffer[line*8 + word] << " ";
318//    }
319//    std::cout << std::endl;
320//}
321//std::cout << "**********************************************************" << std::endl;
322////////////////////////////////////////////////////////////////////////////////////////
323
[151]324        }
325        else
326        {
[260]327            r_latency_count = r_latency_count.read() - 1;
[151]328        }
329        break;
330    }
[260]331    //////////////////
[400]332    case M_READ_BURST:  // Compute the number of words and the number of flits in the burst
333                        // The number of flits can be smaller than the number of words
334                        // in case of 8 bytes flits...
[151]335    {
[400]336        uint32_t nwords;
[260]337        uint32_t offset = r_burst_offset.read();
338
339        if ( offset )                  // buffer not aligned
340        {
[400]341            if ( r_burst_count.read() == 0 ) nwords = m_words_per_burst - offset;
342            else if ( r_burst_count.read() == m_bursts_per_block ) nwords = offset;
343            else nwords = m_words_per_burst;
[260]344        }
345        else                           // buffer aligned
346        {
[400]347            nwords = m_words_per_burst;
[260]348        }
[400]349
350        r_burst_nwords  = nwords;
351        r_initiator_fsm = M_READ_CMD;
[260]352        break;
353    }
354    ////////////////
355    case M_READ_CMD:    // Send a multi-flits VCI WRITE command
356    {
[151]357        if ( p_vci_initiator.cmdack.read() )
358        {
[400]359            uint32_t nwords = r_burst_nwords.read() - r_words_count.read();
360
361            if ( vci_param::B == 4 )    // one word per flit
[151]362            {
[400]363                if ( nwords <= 1 )      // last flit
364                {
365                    r_initiator_fsm = M_READ_RSP;
366                    r_words_count = 0;
367                }
368                else                    // not the last flit
369                {
370                    r_words_count = r_words_count.read() + 1;
371                }
372
373                // compute next word address and next local buffer index
374                r_buf_address = r_buf_address.read() + 4;
375                r_index       = r_index.read() + 1;
[151]376            }
[400]377            else                        // 2 words per flit
[151]378            {
[400]379                if ( nwords <= 2 )      // last flit
380                {
381                    r_initiator_fsm = M_READ_RSP;
382                    r_words_count = 0;
383                }
384                else                    // not the last flit
385                {
386                    r_words_count = r_words_count.read() + 2;
387                }
388                   
389                // compute next word address and next local buffer index
390                if ( nwords == 1 )
391                {
392                    r_buf_address = r_buf_address.read() + 4;
393                    r_index       = r_index.read() + 1;
394                }
395                else
396                {
397                    r_buf_address = r_buf_address.read() + 8;
398                    r_index       = r_index.read() + 2;
399                }
[151]400            }
401        }
402        break;
403    }
[260]404    ////////////////
405    case M_READ_RSP:    // Wait a single flit VCI WRITE response
[151]406    {
407        if ( p_vci_initiator.rspval.read() )
408        {
[260]409            bool aligned = (r_burst_offset.read() == 0);
410
411            if ( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
[151]412            {
[260]413                r_initiator_fsm = M_READ_ERROR;
[151]414            }
[260]415            else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or
416                      (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) )
[151]417            {
[260]418                if ( r_block_count.read() == (r_nblocks.read()-1) ) // last burst of last block
419                {
420                    r_initiator_fsm = M_READ_SUCCESS;
421                }
422                else                                              // last burst not last block
423                {
424                    r_index          = 0;
425                    r_burst_count    = 0;
426                    r_block_count    = r_block_count.read() + 1;
427                    r_initiator_fsm  = M_READ_BLOCK;
428                }
[151]429            }
[260]430            else                                                // not the last burst
431            {
432                r_burst_count = r_burst_count.read() + 1;
433                r_initiator_fsm = M_READ_BURST;
434            }
[151]435        }
436        break;
437    }
[260]438    ///////////////////
[151]439    case M_READ_SUCCESS:
[260]440    case M_READ_ERROR:
[151]441    {
442        if( !r_go ) r_initiator_fsm = M_IDLE;
443        break;
444    }
[260]445    ///////////////////
[400]446    case M_WRITE_BURST:  // Compute the number of words in the burst
[151]447    {
[400]448        uint32_t nwords;
[260]449        uint32_t offset = r_burst_offset.read();
450
451        if ( offset )                  // buffer not aligned
452        {
[400]453            if ( r_burst_count.read() == 0 ) nwords = m_words_per_burst - offset;
454            else if ( r_burst_count.read() == m_bursts_per_block ) nwords = offset;
455            else nwords = m_words_per_burst;
[260]456        }
457        else                           // buffer aligned
458        {
[400]459            nwords = m_words_per_burst;
[260]460        }
[400]461
462        r_burst_nwords  = nwords;
[260]463        r_initiator_fsm =  M_WRITE_CMD;
[151]464        break;
465    }
[260]466    /////////////////
[151]467    case M_WRITE_CMD:   // This is actually a single flit VCI READ command
468    {
[228]469            if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
[151]470        break;
471    }
[260]472    /////////////////
[400]473    case M_WRITE_RSP:   // This is actually a multi-words VCI READ response
[151]474    {
475        if ( p_vci_initiator.rspval.read() )
476        {
[400]477            bool aligned = (r_burst_offset.read() == 0);
[260]478
[400]479            if ( (vci_param::B == 8) and (r_burst_nwords.read() > 1) )
480            {
481                r_local_buffer[r_index.read()]   = (uint32_t)p_vci_initiator.rdata.read();
482                r_local_buffer[r_index.read()+1] = (uint32_t)(p_vci_initiator.rdata.read()>>32);
483                r_index = r_index.read() + 2;
484            }
485            else
486            {
487                r_local_buffer[r_index.read()]   = (uint32_t)p_vci_initiator.rdata.read();
488                r_index = r_index.read() + 1;
489            }
490
[260]491            if ( p_vci_initiator.reop.read() )  // last flit of the burst
[151]492            {
[400]493                    r_words_count  = 0;
494                r_buf_address = r_buf_address.read() + (r_burst_nwords.read()<<2); 
[260]495
[392]496                    if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
[260]497                {
498                    r_initiator_fsm = M_WRITE_ERROR;
499                }
500                else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or
[400]501                     (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) ) // last burst
[260]502                {
503                    r_initiator_fsm  = M_WRITE_BLOCK;
504                }
505                else                                          // not the last burst
506                {
507                    r_burst_count = r_burst_count.read() + 1;
508                    r_initiator_fsm = M_WRITE_BURST;
509                }
[151]510            }
511            else
512            {
[400]513                    r_words_count = r_words_count.read() + 1;
[151]514            }
515        }
516        break;
517    }
[260]518    ///////////////////
[151]519    case M_WRITE_BLOCK:         // write a block to disk after waiting m_latency cycles
520    {
521        if ( r_latency_count == 0 )
522        {
[608]523
524////////////////////////////////////////////////////////////////////////////////////////
525//std::cout << "***** Block content before write for lba "
526//          << std::hex << r_lba.read() << " ***********" << std::endl;
527//for ( size_t line=0 ; line<16 ; line++ )
528//{
529//    for ( size_t word=0 ; word<8 ; word++ )
530//    {
531//        std::cout << std::hex << r_local_buffer[line*8 + word] << " ";
532//    }
533//    std::cout << std::endl;
534//}
535//std::cout << "**********************************************************" << std::endl;
536////////////////////////////////////////////////////////////////////////////////////////
537
[151]538            r_latency_count = m_latency;
[581]539            ::lseek(m_fd, (r_lba + r_block_count)*m_words_per_block*4, SEEK_SET);
540            if( ::write(m_fd, r_local_buffer, m_words_per_block*4) < 0 )
[151]541            {
542                r_initiator_fsm = M_WRITE_ERROR; 
543            }
[272]544            else if ( r_block_count.read() == r_nblocks.read() - 1 ) 
[151]545            {
546                r_initiator_fsm = M_WRITE_SUCCESS; 
547            }
548            else
549            {
[272]550                r_burst_count    = 0;
[400]551                r_index          = 0;
[272]552                r_block_count    = r_block_count.read() + 1;
[400]553                r_initiator_fsm  = M_WRITE_BURST;
[151]554            }
555        } 
556        else
557        {
558            r_latency_count = r_latency_count - 1;
559        }
560        break;
561    }
[260]562    /////////////////////
[151]563    case M_WRITE_SUCCESS:
564    case M_WRITE_ERROR:
565    {
566        if( !r_go ) r_initiator_fsm = M_IDLE;
567        break;
568    }
569    } // end switch r_initiator_fsm
570}  // end transition
571
572//////////////////////
573tmpl(void)::genMoore()
574{
575    // p_vci_target port   
[164]576    p_vci_target.rsrcid = (sc_dt::sc_uint<vci_param::S>)r_srcid.read();
577    p_vci_target.rtrdid = (sc_dt::sc_uint<vci_param::T>)r_trdid.read();
578    p_vci_target.rpktid = (sc_dt::sc_uint<vci_param::P>)r_pktid.read();
[151]579    p_vci_target.reop   = true;
580
581    switch(r_target_fsm) {
582    case T_IDLE:
583        p_vci_target.cmdack = true;
[260]584        p_vci_target.rspval = false;
[514]585        p_vci_target.rdata  = 0;
[151]586        break;
587    case T_READ_STATUS:
588        p_vci_target.cmdack = false;
[260]589        p_vci_target.rspval = true;
590        if     (r_initiator_fsm == M_IDLE)          p_vci_target.rdata = BLOCK_DEVICE_IDLE;
591        else if(r_initiator_fsm == M_READ_SUCCESS)  p_vci_target.rdata = BLOCK_DEVICE_READ_SUCCESS;
592        else if(r_initiator_fsm == M_WRITE_SUCCESS) p_vci_target.rdata = BLOCK_DEVICE_WRITE_SUCCESS;
[151]593        else if(r_initiator_fsm == M_READ_ERROR)        p_vci_target.rdata = BLOCK_DEVICE_READ_ERROR;
594        else if(r_initiator_fsm == M_WRITE_ERROR)       p_vci_target.rdata = BLOCK_DEVICE_WRITE_ERROR;
595        else                                            p_vci_target.rdata = BLOCK_DEVICE_BUSY;
596        p_vci_target.rerror = VCI_READ_OK;
597        break;
598    case T_READ_BUFFER:
599        p_vci_target.cmdack = false;
[260]600        p_vci_target.rspval = true;
601        p_vci_target.rdata  = (uint32_t)r_buf_address.read();
[151]602        p_vci_target.rerror = VCI_READ_OK;
603        break;
[392]604    case T_READ_BUFFER_EXT:
605        p_vci_target.cmdack = false;
606        p_vci_target.rspval = true;
607        p_vci_target.rdata  = (uint32_t)(r_buf_address.read()>>32);
608        p_vci_target.rerror = VCI_READ_OK;
609        break;
[151]610    case T_READ_COUNT:
611        p_vci_target.cmdack = false;
[260]612        p_vci_target.rspval = true;
[400]613        p_vci_target.rdata  = r_nblocks.read();
[151]614        p_vci_target.rerror = VCI_READ_OK;
615        break;
616    case T_READ_LBA:
617        p_vci_target.cmdack = false;
[260]618        p_vci_target.rspval = true;
[400]619        p_vci_target.rdata  = r_lba.read();
[151]620        p_vci_target.rerror = VCI_READ_OK;
621        break;
622    case T_READ_IRQEN:
623        p_vci_target.cmdack = false;
[260]624        p_vci_target.rspval = true;
[400]625        p_vci_target.rdata  = r_irq_enable.read();
[151]626        p_vci_target.rerror = VCI_READ_OK;
627        break;
628    case T_READ_SIZE:
629        p_vci_target.cmdack = false;
[260]630        p_vci_target.rspval = true;
[400]631        p_vci_target.rdata  = m_device_size;
[151]632        p_vci_target.rerror = VCI_READ_OK;
633        break;
634    case T_READ_BLOCK:
635        p_vci_target.cmdack = false;
[260]636        p_vci_target.rspval = true;
[451]637        p_vci_target.rdata  = m_words_per_block*4;
[151]638        p_vci_target.rerror = VCI_READ_OK;
639        break;
640    case T_READ_ERROR:
641        p_vci_target.cmdack = false;
[260]642        p_vci_target.rspval = true;
[400]643        p_vci_target.rdata  = 0;
[151]644        p_vci_target.rerror = VCI_READ_ERROR;
645        break;
646    case T_WRITE_ERROR:
647        p_vci_target.cmdack = false;
[260]648        p_vci_target.rspval = true;
[400]649        p_vci_target.rdata  = 0;
[151]650        p_vci_target.rerror = VCI_WRITE_ERROR;
651        break;
652    default:
653        p_vci_target.cmdack = false;
654        p_vci_target.rspval = true;
[400]655        p_vci_target.rdata  = 0;
[151]656        p_vci_target.rerror = VCI_WRITE_OK;
657        break;
658    } // end switch target fsm
659
660    // p_vci_initiator port
[164]661    p_vci_initiator.srcid  = (sc_dt::sc_uint<vci_param::S>)m_srcid;
[151]662    p_vci_initiator.trdid  = 0;
663    p_vci_initiator.contig = true;
664    p_vci_initiator.cons   = false;
665    p_vci_initiator.wrap   = false;
666    p_vci_initiator.cfixed = false;
667    p_vci_initiator.clen   = 0;
668
669    switch (r_initiator_fsm) {
[401]670    case M_WRITE_CMD:           // It is actually a single flit VCI read command
[151]671        p_vci_initiator.rspack  = false;
672        p_vci_initiator.cmdval  = true;
[260]673        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
[151]674        p_vci_initiator.cmd     = vci_param::CMD_READ;
[401]675        p_vci_initiator.pktid   = TYPE_READ_DATA_UNC; 
[151]676        p_vci_initiator.wdata   = 0;
[401]677        p_vci_initiator.be      = 0;
[400]678        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
[151]679        p_vci_initiator.eop     = true;
680        break;
[400]681    case M_READ_CMD:            // It is actually a multi-words VCI WRITE command
[151]682        p_vci_initiator.rspack  = false;
683        p_vci_initiator.cmdval  = true;
[260]684        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read(); 
[151]685        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
[284]686        p_vci_initiator.pktid   = TYPE_WRITE;
[400]687        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
[401]688        if ( (vci_param::B == 8) and ((r_burst_nwords.read() - r_words_count.read()) > 1) ) 
689        {
[424]690            p_vci_initiator.wdata = ((uint64_t)r_local_buffer[r_index.read()  ]) +
691                                   (((uint64_t)r_local_buffer[r_index.read()+1]) << 32); 
[401]692            p_vci_initiator.be    = 0xFF;
[433]693            p_vci_initiator.eop   = ( (r_burst_nwords.read() - r_words_count.read()) <= 2 );
[401]694        }
695        else
696        {
697            p_vci_initiator.wdata = r_local_buffer[r_index.read()];
698            p_vci_initiator.be    = 0xF;
[433]699            p_vci_initiator.eop   = ( r_words_count.read() == (r_burst_nwords.read() - 1) );
[401]700        }
[151]701        break;
702    case M_READ_RSP:
703    case M_WRITE_RSP:
704        p_vci_initiator.rspack  = true;
705        p_vci_initiator.cmdval  = false;
[260]706        break;
[151]707    default:
[260]708        p_vci_initiator.rspack  = false;
709        p_vci_initiator.cmdval  = false;
710        break;
[151]711    }
712
713    // IRQ signal
[433]714    if ( ((r_initiator_fsm == M_READ_SUCCESS)  ||
715              (r_initiator_fsm == M_WRITE_SUCCESS) ||
716          (r_initiator_fsm == M_READ_ERROR)    ||
717          (r_initiator_fsm == M_WRITE_ERROR) ) && 
[580]718         r_irq_enable.read() ) 
719    {
720
721#if DEBUG_BDEV
[895]722        if (p_irq != true)
723            std::cout << "  <BDEV_INI send IRQ>" << std::endl;
[522]724#endif
725                p_irq = true;
[580]726    } 
727    else 
728    {
729        p_irq = false;
730    }
[151]731} // end GenMoore()
732
733//////////////////////////////////////////////////////////////////////////////
[374]734tmpl(/**/)::VciBlockDeviceTsar( sc_core::sc_module_name              name, 
[400]735                                const soclib::common::MappingTable   &mt,
736                                const soclib::common::IntTab         &srcid,
737                                const soclib::common::IntTab         &tgtid,
738                                const std::string                    &filename,
739                                const uint32_t                       block_size,
740                                const uint32_t                       burst_size,
741                                const uint32_t                       latency)
[151]742
743: caba::BaseModule(name),
[408]744        m_seglist(mt.getSegmentList(tgtid)),
[151]745        m_srcid(mt.indexForId(srcid)),
[400]746        m_words_per_block(block_size/4),
747        m_words_per_burst(burst_size/4),
[151]748        m_bursts_per_block(block_size/burst_size),
749        m_latency(latency),
750        p_clk("p_clk"),
751        p_resetn("p_resetn"),
752        p_vci_initiator("p_vci_initiator"),
753        p_vci_target("p_vci_target"),
754        p_irq("p_irq") 
755{
[433]756    std::cout << "  - Building VciBlockDeviceTsar " << name << std::endl;
757
[151]758        SC_METHOD(transition);
[381]759    dont_initialize();
760    sensitive << p_clk.pos();
[151]761
762        SC_METHOD(genMoore);
[381]763    dont_initialize();
764    sensitive << p_clk.neg();
[151]765
[409]766    size_t nbsegs = 0;
[408]767    std::list<soclib::common::Segment>::iterator seg;
768    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
769    {
[409]770        nbsegs++;
[408]771       
772            if ( (seg->baseAddress() & 0x0000003F) != 0 ) 
773            {
774                    std::cout << "Error in component VciBlockDeviceTsar : " << name
775                              << "The base address of segment " << seg->name()
776                      << " must be multiple of 64 bytes" << std::endl;
777                    exit(1);
778            }
779            if ( seg->size() < 64 ) 
780            {
781                    std::cout << "Error in component VciBlockDeviceTsar : " << name
782                          << "The size of segment " << seg->name()
783                      << " cannot be smaller than 64 bytes" << std::endl;
784                    exit(1);
785            }
[433]786        std::cout << "    => segment " << seg->name()
787                  << " / base = " << std::hex << seg->baseAddress()
788                  << " / size = " << seg->size() << std::endl; 
[408]789    }
790
[409]791    if( nbsegs == 0 )
[408]792    {
793                std::cout << "Error in component VciBlockDeviceTsar : " << name
794                          << " No segment allocated" << std::endl;
795                exit(1);
796    }
797
[400]798    if( (block_size != 128)  && 
[256]799        (block_size != 256)  && 
800        (block_size != 512)  && 
801        (block_size != 1024) &&
802        (block_size != 2048) && 
803        (block_size != 4096) )
[151]804        {
[408]805                std::cout << "Error in component VciBlockDeviceTsar : " << name
806                          << " The block size must be 128, 256, 512, 1024, 2048 or 4096 bytes"
807                  << std::endl;
[151]808                exit(1);
809        }
[408]810
[433]811    if( (burst_size != 8 ) && 
[260]812                (burst_size != 16) && 
813                (burst_size != 32) && 
814                (burst_size != 64) )
815        {
[408]816                std::cout << "Error in component VciBlockDeviceTsar : " << name
[433]817                          << " The burst size must be 8, 16, 32 or 64 bytes" << std::endl;
[260]818                exit(1);
819        }
[408]820
[400]821        if ( (vci_param::B != 4) and (vci_param::B != 8) )
[151]822        {
[408]823                std::cout << "Error in component VciBlockDeviceTsar : " << name             
824                          << " The VCI data fields must have 32 bits or 64 bits" << std::endl;
[151]825                exit(1);
826        }
[408]827
[151]828        m_fd = ::open(filename.c_str(), O_RDWR);
829        if ( m_fd < 0 ) 
830        {
[408]831                std::cout << "Error in component VciBlockDeviceTsar : " << name
832                          << " Unable to open file " << filename << std::endl;
[151]833                exit(1);
834        }
835        m_device_size = lseek(m_fd, 0, SEEK_END) / block_size;
[408]836
837        if ( m_device_size > ((uint64_t)1<<vci_param::N ) ) 
[151]838        {
[408]839                std::cout << "Error in component VciBlockDeviceTsar" << name
840                          << " The file " << filename
841                          << " has more blocks than addressable with the VCI address" << std::endl;
842                exit(1);
[151]843        }
844
[400]845        r_local_buffer = new uint32_t[m_words_per_block];
[260]846
[151]847} // end constructor
848
[580]849/////////////////////////////////
[514]850tmpl(/**/)::~VciBlockDeviceTsar()
851{
[895]852    ::close(m_fd);
[514]853    delete [] r_local_buffer;
854}
855
856
[151]857//////////////////////////
858tmpl(void)::print_trace()
859{
[500]860        const char* initiator_str[] = 
861    {
[580]862                "INI_IDLE",
[260]863
[580]864                "INI_READ_BLOCK",
865                "INI_READ_BURST",
866                "INI_READ_CMD",
867                "INI_READ_RSP",
868                "INI_READ_SUCCESS",
869                "INI_READ_ERROR",
[260]870
[580]871                "INI_WRITE_BURST",
872                "INI_WRITE_CMD",
873                "INI_WRITE_RSP",
874                "INI_WRITE_BLOCK",
875                "INI_WRITE_SUCCESS",
876                "INI_WRITE_ERROR",
[151]877        };
[500]878        const char* target_str[] = 
879    {
[580]880                "TGT_IDLE",
881                "TGT_WRITE_BUFFER",
882                "TGT_READ_BUFFER",
883                "TGT_WRITE_BUFFER_EXT",
884                "TGT_READ_BUFFER_EXT",
885                "TGT_WRITE_COUNT",
886                "TGT_READ_COUNT",
887                "TGT_WRITE_LBA",
888                "TGT_READ_LBA",
889                "TGT_WRITE_OP",
890                "TGT_READ_STATUS",
891                "TGT_WRITE_IRQEN",
892                "TGT_READ_IRQEN",
893                "TGT_READ_SIZE",
894                "TGT_READ_BLOCK",
895                "TGT_READ_ERROR",
896                "TGT_WRITE_ERROR ",
[151]897        };
898
[580]899        std::cout << "BDEV " << name()
900              << " : " << target_str[r_target_fsm.read()] 
901                      << " / " << initiator_str[r_initiator_fsm.read()] 
902              << " / buf = " << std::hex << r_buf_address.read()
903              << " / lba = " << std::hex << r_lba.read()
904                      << " / block_count = " << std::dec << r_block_count.read() 
905                      << " / burst_count = " << r_burst_count.read() 
906                      << " / word_count = " << r_words_count.read() <<std::endl; 
[151]907}
908
909}} // end namespace
910
911// Local Variables:
912// tab-width: 4
913// c-basic-offset: 4
914// c-file-offsets:((innamespace . 0)(inline-open . 0))
915// indent-tabs-mode: nil
916// End:
917
918// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
919
Note: See TracBrowser for help on using the repository browser.