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

Last change on this file since 514 was 514, checked in by meunier, 11 years ago

More memory cleaning for valgrind (generic_llsc_global_table, vci_block_device_tsar)

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