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

Last change on this file since 1017 was 1017, checked in by alain, 9 years ago

Introduce a soft reset, caused by a write in BLOCK_DEVICE_STATUS register.

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