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

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

improve debug messages

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