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

Last change on this file since 580 was 580, checked in by alain, 10 years ago

Fixing a bug in target FSM when using 64 bits data width.

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