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

Last change on this file since 920 was 898, checked in by cfuguet, 10 years ago

trunk: modify vci_block_device_tsar controller

  • The block device sends a VCI error response when a configuration command arrives and there is a pending transaction. This is to avoid a deadlock.

Until now, if a configuration command arrived, the TARGET FSM was
blocked until the previous transaction was finished and
acknowledged. If a processor tries to configure the block device
without acknowledging first a previous transaction, a dead-lock
situation was created.

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