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

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

bugfix in vci_block_device_tsar:

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