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, 8 years ago

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

File size: 30.5 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     running = (r_initiator_fsm.read() != M_IDLE);
80
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;
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;
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;
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;
92            else if( !read && (cell == BLOCK_DEVICE_STATUS) )     r_target_fsm = T_WRITE_STATUS;
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;
96            else if( !read && (cell == BLOCK_DEVICE_OP) )         r_target_fsm = T_WRITE_OP;
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;
99            else                                                  r_target_fsm = T_ERROR;
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 = (r_buf_address.read() & 0xFFFFFFFF00000000ULL) |
118                ((uint64_t)r_tdata.read());
119            r_target_fsm  = T_IDLE;
120        }
121        break;
122    }
123    ////////////////////////
124    case T_WRITE_BUFFER_EXT:
125    {
126        if (p_vci_target.rspack.read() )
127        {
128#if SOCLIB_MODULE_DEBUG
129std::cout << "  <BDEV_TGT WRITE_BUFFER_EXT> value = " << r_tdata.read() << std::endl;
130#endif
131            r_buf_address = (r_buf_address.read() & 0x00000000FFFFFFFFULL) |
132                ((uint64_t)r_tdata.read() << 32);
133            r_target_fsm  = T_IDLE;
134        }
135        break;
136    }
137    ///////////////////
138    case T_WRITE_COUNT:
139    {
140        if (p_vci_target.rspack.read() )
141        {
142#if SOCLIB_MODULE_DEBUG
143std::cout << "  <BDEV_TGT WRITE_COUNT> value = " << r_tdata.read() << std::endl;
144#endif
145            r_nblocks    = (uint32_t)r_tdata.read();
146            r_target_fsm = T_IDLE;
147        }
148        break;
149    }
150    /////////////////
151    case T_WRITE_LBA:
152    {
153        if (p_vci_target.rspack.read() )
154        {
155#if SOCLIB_MODULE_DEBUG
156std::cout << "  <BDEV_TGT WRITE_LBA> value = " << r_tdata.read() << std::endl;
157#endif
158            r_lba        = (uint32_t)r_tdata.read();
159            r_target_fsm = T_IDLE;
160        }
161        break;
162    }
163    ////////////////
164    case T_WRITE_OP:
165    {
166        if ( p_vci_target.rspack.read() )
167        {
168            if ( ((uint32_t)r_tdata.read() == BLOCK_DEVICE_READ) and
169                 (r_initiator_fsm.read() == M_IDLE) )
170            {
171
172#if SOCLIB_MODULE_DEBUG
173std::cout << "  <BDEV_TGT WRITE_OP> value = READ" << std::endl;
174#endif
175                r_read = true;
176                r_go   = true;
177            }
178            else if ( ((uint32_t)r_tdata.read() == BLOCK_DEVICE_WRITE) and
179                      (r_initiator_fsm.read() == M_IDLE) )
180            {
181
182#if SOCLIB_MODULE_DEBUG
183std::cout << "  <BDEV_TGT WRITE_OP> value = WRITE" << std::endl;
184#endif
185                r_read = false;
186                r_go   = true;
187            }
188            r_target_fsm = T_IDLE;
189        }
190        break;
191    }
192    ///////////////////
193    case T_WRITE_IRQEN:
194    {
195        if ( p_vci_target.rspack.read() )
196        {
197
198#if SOCLIB_MODULE_DEBUG
199std::cout << "  <BDEV_TGT WRITE_IRQEN> value = " << r_tdata.read() << std::endl;
200#endif
201            r_target_fsm = T_IDLE;
202            r_irq_enable = (r_tdata.read() != 0);
203        }
204        break;
205    }
206    ///////////////////
207    case T_READ_BUFFER:
208    case T_READ_BUFFER_EXT:
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:
214    case T_ERROR:
215    {
216        if ( p_vci_target.rspack.read() ) r_target_fsm = T_IDLE;
217        break;
218    }
219    ///////////////////
220    case T_READ_STATUS:
221    {
222        if ( p_vci_target.rspack.read() )
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    }
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    }
242    } // end switch target fsm
243
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:
248    // - If buffer aligned, all burst have the same length (m_words_per burst)
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)
251    //   and first and last burst are shorter, because all words in a burst
252    //   must be contained in a single cache line.
253    //   first burst => nwords = m_words_per_burst - offset
254    //   last  burst => nwords = offset
255    //   other burst => nwords = m_words_per_burst
256    //////////////////////////////////////////////////////////////////////////////
257
258    switch( r_initiator_fsm.read() ) {
259    ////////////
260    case M_IDLE:    // check buffer alignment to compute the number of bursts
261    {
262        if ( r_go.read() )
263        {
264            r_index         = 0;
265            r_block_count   = 0;
266            r_burst_count   = 0;
267            r_words_count   = 0;
268            r_latency_count = m_latency;
269
270            // compute r_burst_offset (zero when buffer aligned)
271            r_burst_offset = (uint32_t)((r_buf_address.read()>>2) % m_words_per_burst);
272
273            // start tranfer
274            if ( r_read.read() )    r_initiator_fsm = M_READ_BLOCK;
275            else                    r_initiator_fsm = M_WRITE_BURST;
276        }
277        break;
278    }
279    //////////////////
280    case M_READ_BLOCK:  // read one block from disk after waiting m_latency cycles
281    {
282        if ( r_latency_count.read() == 0 )
283        {
284            r_latency_count = m_latency;
285            ::lseek(m_fd, (r_lba + r_block_count)*m_words_per_block*4, SEEK_SET);
286            if( ::read(m_fd, r_local_buffer, m_words_per_block*4) < 0 )
287            {
288                r_initiator_fsm = M_READ_ERROR;
289            }
290            else
291            {
292                r_burst_count   = 0;
293                r_words_count   = 0;
294                r_initiator_fsm = M_READ_BURST;
295            }
296
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] << " ";
307        }
308        std::cout << std::endl;
309    }
310    std::cout << "**********************************************************"
311              << std::endl;
312}
313*/
314        }
315        else
316        {
317            r_latency_count = r_latency_count.read() - 1;
318        }
319        break;
320    }
321    //////////////////
322    case M_READ_BURST:  // Compute number of words and number of flits in the burst
323                        // The number of flits can be smaller than the number of words
324                        // in case of 8 bytes flits...
325    {
326        if ( r_go.read() == false )   // soft reset
327        {
328            r_initiator_fsm = M_IDLE;
329            break;
330        }
331
332        uint32_t nwords;
333        uint32_t offset = r_burst_offset.read();
334
335        if ( offset )                  // buffer not aligned
336        {
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;
340        }
341        else                           // buffer aligned
342        {
343            nwords = m_words_per_burst;
344        }
345
346        r_burst_nwords  = nwords;
347        r_initiator_fsm = M_READ_CMD;
348        break;
349    }
350    ////////////////
351    case M_READ_CMD:    // Send a multi-flits VCI WRITE command
352    {
353        if ( p_vci_initiator.cmdack.read() )
354        {
355            uint32_t nwords = r_burst_nwords.read() - r_words_count.read();
356
357            if ( vci_param::B == 4 )    // one word per flit
358            {
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;
372            }
373            else                        // 2 words per flit
374            {
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                }
384
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                }
396            }
397        }
398        break;
399    }
400    ////////////////
401    case M_READ_RSP:    // Wait a single flit VCI WRITE response
402    {
403        if ( p_vci_initiator.rspval.read() )
404        {
405            bool aligned = (r_burst_offset.read() == 0);
406
407            if ( (p_vci_initiator.rerror.read()&0x1) != 0 )
408            {
409                r_initiator_fsm = M_READ_ERROR;
410            }
411            else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or
412                      (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) )
413            {
414                if ( r_block_count.read() == (r_nblocks.read()-1) ) // last burst of last block
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                }
425            }
426            else                                                // not the last burst
427            {
428                r_burst_count = r_burst_count.read() + 1;
429                r_initiator_fsm = M_READ_BURST;
430            }
431        }
432        break;
433    }
434    ///////////////////
435    case M_READ_SUCCESS:
436    case M_READ_ERROR:
437    {
438        if( !r_go ) r_initiator_fsm = M_IDLE;
439        break;
440    }
441    ///////////////////
442    case M_WRITE_BURST:  // Compute the number of words in the burst
443    {
444        if ( r_go.read() == false )   // soft reset
445        {
446            r_initiator_fsm = M_IDLE;
447            break;
448        }
449
450        uint32_t nwords;
451        uint32_t offset = r_burst_offset.read();
452
453        if ( offset )                  // buffer not aligned
454        {
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;
458        }
459        else                           // buffer aligned
460        {
461            nwords = m_words_per_burst;
462        }
463
464        r_burst_nwords  = nwords;
465        r_initiator_fsm =  M_WRITE_CMD;
466        break;
467    }
468    /////////////////
469    case M_WRITE_CMD:   // This is actually a single flit VCI READ command
470    {
471        if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
472        break;
473    }
474    /////////////////
475    case M_WRITE_RSP:   // This is actually a multi-words VCI READ response
476    {
477        if ( p_vci_initiator.rspval.read() )
478        {
479            bool aligned = (r_burst_offset.read() == 0);
480
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
493            if ( p_vci_initiator.reop.read() )  // last flit of the burst
494            {
495                r_words_count  = 0;
496                r_buf_address = r_buf_address.read() + (r_burst_nwords.read()<<2);
497
498                if( (p_vci_initiator.rerror.read()&0x1) != 0 )
499                {
500                    r_initiator_fsm = M_WRITE_ERROR;
501                }
502                else if ( (not aligned and (r_burst_count.read() == m_bursts_per_block)) or
503                     (aligned and (r_burst_count.read() == (m_bursts_per_block-1))) ) // last burst
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                }
512            }
513            else
514            {
515                r_words_count = r_words_count.read() + 1;
516            }
517        }
518        break;
519    }
520    ///////////////////
521    case M_WRITE_BLOCK:     // write a block to disk after waiting m_latency cycles
522    {
523        if ( r_latency_count == 0 )
524        {
525
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*/
540
541            r_latency_count = m_latency;
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 )
544            {
545                r_initiator_fsm = M_WRITE_ERROR;
546            }
547            else if ( r_block_count.read() == r_nblocks.read() - 1 )
548            {
549                r_initiator_fsm = M_WRITE_SUCCESS;
550            }
551            else
552            {
553                r_burst_count    = 0;
554                r_index          = 0;
555                r_block_count    = r_block_count.read() + 1;
556                r_initiator_fsm  = M_WRITE_BURST;
557            }
558        }
559        else
560        {
561            r_latency_count = r_latency_count - 1;
562        }
563        break;
564    }
565    /////////////////////
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{
578    // p_vci_target port
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();
582    p_vci_target.reop   = true;
583
584    switch(r_target_fsm) {
585    case T_IDLE:
586        p_vci_target.cmdack = true;
587        p_vci_target.rspval = false;
588        p_vci_target.rdata  = 0;
589        break;
590    case T_READ_STATUS:
591        p_vci_target.cmdack = false;
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;
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;
599        p_vci_target.rerror = 0;
600        break;
601    case T_READ_BUFFER:
602        p_vci_target.cmdack = false;
603        p_vci_target.rspval = true;
604        p_vci_target.rdata  = (uint32_t)r_buf_address.read();
605        p_vci_target.rerror = 0;
606        break;
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);
611        p_vci_target.rerror = 0;
612        break;
613    case T_READ_COUNT:
614        p_vci_target.cmdack = false;
615        p_vci_target.rspval = true;
616        p_vci_target.rdata  = r_nblocks.read();
617        p_vci_target.rerror = 0;
618        break;
619    case T_READ_LBA:
620        p_vci_target.cmdack = false;
621        p_vci_target.rspval = true;
622        p_vci_target.rdata  = r_lba.read();
623        p_vci_target.rerror = 0;
624        break;
625    case T_READ_IRQEN:
626        p_vci_target.cmdack = false;
627        p_vci_target.rspval = true;
628        p_vci_target.rdata  = r_irq_enable.read();
629        p_vci_target.rerror = 0;
630        break;
631    case T_READ_SIZE:
632        p_vci_target.cmdack = false;
633        p_vci_target.rspval = true;
634        p_vci_target.rdata  = m_device_size;
635        p_vci_target.rerror = 0;
636        break;
637    case T_READ_BLOCK:
638        p_vci_target.cmdack = false;
639        p_vci_target.rspval = true;
640        p_vci_target.rdata  = m_words_per_block*4;
641        p_vci_target.rerror = 0;
642        break;
643    case T_ERROR:
644        p_vci_target.cmdack = false;
645        p_vci_target.rspval = true;
646        p_vci_target.rdata  = 0;
647        p_vci_target.rerror = 1;
648        break;
649    default:      // all write
650        p_vci_target.cmdack = false;
651        p_vci_target.rspval = true;
652        p_vci_target.rdata  = 0;
653        p_vci_target.rerror = 0;
654        break;
655    } // end switch target fsm
656
657    // p_vci_initiator port
658    p_vci_initiator.srcid  = (sc_dt::sc_uint<vci_param::S>)m_srcid;
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) {
667    case M_WRITE_CMD:       // It is actually a single flit VCI read command
668        p_vci_initiator.rspack  = false;
669        p_vci_initiator.cmdval  = true;
670        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
671        p_vci_initiator.cmd     = vci_param::CMD_READ;
672        p_vci_initiator.pktid   = TYPE_READ_DATA_UNC;
673        p_vci_initiator.wdata   = 0;
674        p_vci_initiator.be      = 0;
675        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
676        p_vci_initiator.eop     = true;
677        break;
678    case M_READ_CMD:        // It is actually a multi-words VCI WRITE command
679        p_vci_initiator.rspack  = false;
680        p_vci_initiator.cmdval  = true;
681        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
682        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
683        p_vci_initiator.pktid   = TYPE_WRITE;
684        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(r_burst_nwords.read()<<2);
685        if ( (vci_param::B == 8) and ((r_burst_nwords.read() - r_words_count.read()) > 1) )
686        {
687            p_vci_initiator.wdata = ((uint64_t)r_local_buffer[r_index.read()  ]) +
688                                   (((uint64_t)r_local_buffer[r_index.read()+1]) << 32);
689            p_vci_initiator.be    = 0xFF;
690            p_vci_initiator.eop   = ( (r_burst_nwords.read() - r_words_count.read()) <= 2 );
691        }
692        else
693        {
694            p_vci_initiator.wdata = r_local_buffer[r_index.read()];
695            p_vci_initiator.be    = 0xF;
696            p_vci_initiator.eop   = ( r_words_count.read() == (r_burst_nwords.read() - 1) );
697        }
698        break;
699    case M_READ_RSP:
700    case M_WRITE_RSP:
701        p_vci_initiator.rspack  = true;
702        p_vci_initiator.cmdval  = false;
703        break;
704    default:
705        p_vci_initiator.rspack  = false;
706        p_vci_initiator.cmdval  = false;
707        break;
708    }
709
710    // IRQ signal
711    if ( ((r_initiator_fsm == M_READ_SUCCESS)  ||
712          (r_initiator_fsm == M_WRITE_SUCCESS) ||
713          (r_initiator_fsm == M_READ_ERROR)    ||
714          (r_initiator_fsm == M_WRITE_ERROR) ) &&
715         r_irq_enable.read() )
716    {
717
718#if SOCLIB_MODULE_DEBUG
719        if (p_irq != true)
720            std::cout << "  <BDEV_INI send IRQ>" << std::endl;
721#endif
722        p_irq = true;
723    }
724    else
725    {
726        p_irq = false;
727    }
728} // end GenMoore()
729
730//////////////////////////////////////////////////////////////////////////////
731tmpl(/**/)::VciBlockDeviceTsar( sc_core::sc_module_name              name,
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)
739
740: caba::BaseModule(name),
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")
752{
753    std::cout << "  - Building VciBlockDeviceTsar " << name << std::endl;
754
755    SC_METHOD(transition);
756    dont_initialize();
757    sensitive << p_clk.pos();
758
759    SC_METHOD(genMoore);
760    dont_initialize();
761    sensitive << p_clk.neg();
762
763    size_t nbsegs = 0;
764    std::list<soclib::common::Segment>::iterator seg;
765    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
766    {
767        nbsegs++;
768
769        if ( (seg->baseAddress() & 0x0000003F) != 0 )
770        {
771            std::cout << "Error in component VciBlockDeviceTsar : " << name
772                      << "The base address of segment " << seg->name()
773                      << " must be multiple of 64 bytes" << std::endl;
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()
780                      << " cannot be smaller than 64 bytes" << std::endl;
781            exit(1);
782        }
783        std::cout << "    => segment " << seg->name()
784                  << " / base = " << std::hex << seg->baseAddress()
785                  << " / size = " << seg->size() << std::endl;
786    }
787
788    if( nbsegs == 0 )
789    {
790        std::cout << "Error in component VciBlockDeviceTsar : " << name
791                  << " No segment allocated" << std::endl;
792        exit(1);
793    }
794
795    if( (block_size != 128)  &&
796        (block_size != 256)  &&
797        (block_size != 512)  &&
798        (block_size != 1024) &&
799        (block_size != 2048) &&
800        (block_size != 4096) )
801    {
802        std::cout << "Error in component VciBlockDeviceTsar : " << name
803                  << " The block size must be 128, 256, 512, 1024, 2048 or 4096 bytes"
804                  << std::endl;
805        exit(1);
806    }
807
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    }
817
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    }
824
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;
833
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    }
841
842    r_local_buffer = new uint32_t[m_words_per_block];
843
844} // end constructor
845
846/////////////////////////////////
847tmpl(/**/)::~VciBlockDeviceTsar()
848{
849    ::close(m_fd);
850    delete [] r_local_buffer;
851}
852
853
854//////////////////////////
855tmpl(void)::print_trace()
856{
857    const char* initiator_str[] =
858    {
859        "INI_IDLE",
860
861        "INI_READ_BLOCK",
862        "INI_READ_BURST",
863        "INI_READ_CMD",
864        "INI_READ_RSP",
865        "INI_READ_SUCCESS",
866        "INI_READ_ERROR",
867
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[] =
876    {
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    };
895
896    std::cout << "BDEV " << name()
897              << " : " << target_str[r_target_fsm.read()]
898              << " / " << initiator_str[r_initiator_fsm.read()]
899              << " / buf = " << std::hex << r_buf_address.read()
900              << " / lba = " << std::hex << r_lba.read()
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;
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.