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

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

trunk: modify vci_block_device_tsar controller

  • The block device sends a VCI error response when a configuration command arrives and there is a pending transaction. This is to avoid a deadlock.

Until now, if a configuration command arrived, the TARGET FSM was
blocked until the previous transaction was finished and
acknowledged. If a processor tries to configure the block device
without acknowledging first a previous transaction, a dead-lock
situation was created.

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