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

Last change on this file since 522 was 522, checked in by bouyer, 11 years ago

We can't read wdata after we sent cmdack, so read and store wdata when
we get the command, and use the this saved value when we need it later.
While there, add a few SOCLIB_MODULE_DEBUG outputs.

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