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

Last change on this file since 973 was 973, checked in by cfuguet, 9 years ago

improve debug messages

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