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

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

Improvement in vci_mem_cache component:

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