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

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

bugfix in vci_block_device_tsar:

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