source: trunk/modules/vci_synthetic_target/caba/source/src/vci_synthetic_target.cpp @ 181

Last change on this file since 181 was 181, checked in by choichil, 12 years ago

Adding synthetic target made from vci_simple_ram

File size: 15.0 KB
Line 
1/*
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 <alain.greiner@lip6.fr>, 2008
25 *         Christophe Choichillon <choichillon.christophe@gmail.com>, 2011
26 *
27 * Maintainers: alain, Christophe Choichillon
28 */
29
30/////////////////////////////////////////////////////////////////////////
31//  This component is a multi-segments Ram controller.
32//
33//  It supports only the compact VCI packets defined
34//  in the VCI advanced specification:
35//  - A READ burst command packet (such a cache line request)
36//    contains one single flit.
37//    The response packet length is defined by the PLEN field.
38//    The zero value for the PLEN field is not supported.
39//    An ERROR response packets contain one single flit,
40//  - WRITE burst command packets at consecutive addresses are supported.
41//    The zero value for the PLEN field is not supported.
42//    Write response packets contain always one single flit.
43//  - The LL & SC command packets are supported, but the packet
44//    must contain one single flit.
45//  The RAM latency is a parameter, that can have a zero value.
46////////////////////////////////////////////////////////////////////////
47//  Implementation note: This component does not contain any FIFO,
48//  and is controlled by a single FSM.
49//  The latency counter is decremented in the IDLE state.
50//  The VCI command is analysed and checked in the CMD_GET state.
51//  - For read, ll or sc commands, the command is acknowledged in
52//  the CMD_STATE. It is executed and the response is sent in the
53//  RSP_READ, RSP_LL or RSP_SC states.
54//  - For write commands, the command is acknowledged in the CMD_STATE,
55//  or in the CMD_WRITE & CMD_ERROR states in case of bursts.
56//  The command is executed in the CMD_WRITE state, or in the RSP_WRITE
57//  state for the last flit of a burst. The response packet is sent
58//  in the RSP_WRITE state.
59/////////////////////////////////////////////////////////////////////////
60
61#include <iostream>
62#include <cstring>
63#include "vci_synthetic_target.h"
64
65namespace soclib {
66namespace caba {
67
68using namespace soclib;
69
70#define tmpl(x) template<typename vci_param> x VciSyntheticTarget<vci_param>
71
72//////////////////////////
73tmpl(/**/)::VciSyntheticTarget(
74    sc_module_name insname,
75    const soclib::common::IntTab index,
76    const soclib::common::MappingTable &mt,
77    const soclib::common::Loader &loader,
78    const uint32_t latency)
79        : caba::BaseModule(insname),
80      m_loader(loader),
81      m_seglist(mt.getSegmentList(index)),
82      m_latency(latency),
83
84      r_llsc_buf((size_t)(1<<vci_param::S)),
85
86      r_fsm_state("r_fsm_state"),
87      r_flit_count("r_flit_count"),
88      r_seg_index("r_seg_index"),
89      r_address("r_address"),
90      r_wdata("r_wdata"),
91      r_be("r_be"),
92      r_srcid("r_srcid"),
93      r_trdid("r_trdid"),
94      r_pktid("r_pktid"),
95      r_contig("r_contig"),
96      r_latency_count("r_latency_count"),
97
98      m_nbseg(0),
99
100      p_resetn("p_resetn"),
101      p_clk("p_clk"),
102      p_vci("p_vci")
103{
104    SC_METHOD(transition);
105    dont_initialize();
106    sensitive << p_clk.pos();
107
108    SC_METHOD(genMoore);
109    dont_initialize();
110    sensitive << p_clk.neg();
111
112    std::list<soclib::common::Segment>::iterator seg;
113    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )  m_nbseg++;
114 
115    m_ram = new ram_t*[m_nbseg];
116    m_seg = new soclib::common::Segment*[m_nbseg];
117
118    size_t i = 0;
119    size_t word_size = vci_param::B; // B is VCI's cell size
120    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
121    { 
122        m_ram[i] = new ram_t[(seg->size()+word_size-1)/word_size];
123        m_seg[i] = &(*seg);
124        i++;
125    }
126}
127
128///////////////////////////
129tmpl(/**/)::~VciSyntheticTarget()
130{
131    for (size_t i=0 ; i<m_nbseg ; ++i) delete [] m_ram[i];
132    delete [] m_ram;
133    delete [] m_seg;
134}
135
136/////////////////////
137tmpl(void)::reload()
138{
139    for ( size_t i=0 ; i<m_nbseg ; ++i ) 
140    {
141        m_loader.load(&m_ram[i][0], m_seg[i]->baseAddress(), m_seg[i]->size());
142        for ( size_t addr = 0 ; addr < m_seg[i]->size()/vci_param::B ; ++addr )
143            m_ram[i][addr] = le_to_machine(m_ram[i][addr]);
144    }
145}
146
147////////////////////
148tmpl(void)::reset()
149{
150    for ( size_t i=0 ; i<m_nbseg ; ++i ) std::memset(&m_ram[i][0], 0, m_seg[i]->size()); 
151    m_cpt_read = 0;
152    m_cpt_write = 0;
153    if (m_latency) {
154        r_fsm_state = FSM_IDLE;
155        r_latency_count = m_latency - 1;
156    } else {
157        r_fsm_state = FSM_CMD_GET;
158        r_latency_count = 0;
159    }
160    r_llsc_buf.clearAll();
161}
162
163/////////////////////////////////////////////////////////////////////////////
164tmpl(bool)::write(size_t seg, vci_addr_t addr, vci_data_t wdata, vci_be_t be)
165{
166    if ( m_seg[seg]->contains(addr) ) 
167    {
168        size_t index = (size_t)((addr - m_seg[seg]->baseAddress()) / vci_param::B);
169        vci_data_t cur = m_ram[seg][index];
170        vci_data_t mask = vci_param::be2mask(be);
171        m_ram[seg][index] = (cur & ~mask) | (wdata & mask);
172        m_cpt_write++;
173        return true;
174    } 
175    return false;
176}
177
178/////////////////////////////////////////////////////////////////
179tmpl(bool)::read(size_t seg, vci_addr_t addr, vci_data_t &rdata )
180{
181    if ( m_seg[seg]->contains(addr) ) 
182    {
183        size_t index = (size_t)((addr - m_seg[seg]->baseAddress()) / vci_param::B);
184        rdata = m_ram[seg][index];
185        m_cpt_read++;
186        return true;
187    }
188    return false;
189}
190
191//////////////////////////
192tmpl(void)::print_trace()
193{
194    const char* state_str[] = { "IDLE", 
195                                "CMD_GET",
196                                "CMD_WRITE",
197                                "CMD_ERROR",
198                                "RSP_READ",
199                                "RSP_WRITE",
200                                "RSP_LL",
201                                "RSP_SC",
202                                "RSP_ERROR" };
203    std::cout << "Simple_ram " << name() 
204              << " : state = " << state_str[r_fsm_state] 
205              << " / latency_count = " << r_latency_count
206              << " / flit_count = " << r_flit_count << std::endl;
207}
208
209/////////////////////////
210tmpl(void)::transition()
211{
212    if (!p_resetn) 
213    {
214        reset();
215        reload();
216        return;
217    }
218
219#ifdef SOCLIB_MODULE_DEBUG
220std::cout << "Synthetic_target : " << name() << std::endl;
221std::cout << " fsm_state = " << r_fsm_state
222          << " latency_count = " << r_latency_count << std::endl;
223#endif
224
225    switch ( r_fsm_state ) {
226    case FSM_IDLE:      // unreachable state if m_latency == 0
227    {
228        if ( p_vci.cmdval.read() ) 
229        {
230            if (r_latency_count.read() == 0) 
231            {
232                r_fsm_state = FSM_CMD_GET;
233                r_latency_count = m_latency - 1;
234            } 
235            else 
236            {
237                r_latency_count = r_latency_count.read() - 1;
238            }
239        }                                 
240        break;
241    }
242    case FSM_CMD_GET:
243    {
244        if ( !p_vci.cmdval.read() ) break;
245
246        vci_addr_t   address = p_vci.address.read();
247        bool         error = true;
248        for ( size_t index = 0 ; index<m_nbseg  && error ; ++index) 
249        {
250            if(address & 0x3){
251                    error = false;
252            } else {
253                if ( (m_seg[index]->contains(address)) &&
254                     (m_seg[index]->contains(address + p_vci.plen.read() - vci_param::B)) ) 
255                {
256                    error = false;
257                    r_seg_index = index;
258                }
259            }
260        } 
261
262        r_address    = address;
263        r_be         = p_vci.be.read();
264        r_wdata      = p_vci.wdata.read();
265        r_srcid      = p_vci.srcid.read();
266        r_trdid      = p_vci.trdid.read();
267        r_pktid      = p_vci.pktid.read();
268
269        if ( error ) 
270        {
271            if( p_vci.eop.read() )      r_fsm_state = FSM_RSP_ERROR;
272            else                        r_fsm_state = FSM_CMD_ERROR;
273        }
274        else
275        {
276            assert( (p_vci.plen.read() != 0) && "VCI command packets should have plen != 0");
277            if ( p_vci.cmd.read() == vci_param::CMD_WRITE ) 
278            {
279                r_contig     = p_vci.contig.read();
280                if( p_vci.eop.read() )  r_fsm_state = FSM_RSP_WRITE;
281                else                    r_fsm_state = FSM_CMD_WRITE;
282            }
283            else if ( p_vci.cmd.read() == vci_param::CMD_READ )
284            {
285                r_flit_count = p_vci.plen.read()/vci_param::B;
286                r_contig     = p_vci.contig.read();
287                r_fsm_state = FSM_RSP_READ;
288                assert( p_vci.eop.read() && "VCI read command packets should be one flit");
289            }
290            else if ( p_vci.cmd.read() == vci_param::CMD_STORE_COND )
291            {
292                r_fsm_state = FSM_RSP_SC;
293                assert( p_vci.eop.read() && "VCI sc command packets should be one flit");
294            }
295            else if ( p_vci.cmd.read() == vci_param::CMD_LOCKED_READ )
296            {
297                r_fsm_state = FSM_RSP_LL;
298                assert( p_vci.eop.read() && "VCI ll command packets should be one flit");
299            }
300        }
301        break;
302    }
303    case FSM_CMD_WRITE:
304    {
305        assert( write (r_seg_index, r_address , r_wdata, r_be ) && "out of bounds access in a write burst" );
306        if ( p_vci.cmdval.read() ) 
307        {
308            vci_addr_t next_address = r_address.read() + (vci_addr_t)vci_param::B;
309            assert( ((r_contig && (next_address == p_vci.address.read())) ||
310                     (!r_contig && (r_address.read() == p_vci.address.read()))) &&
311                        "addresses must be contiguous or constant in a VCI write burst" );
312            r_address   = p_vci.address.read();
313            r_be        = p_vci.be.read();
314            r_wdata     = p_vci.wdata.read();
315            if ( p_vci.eop.read() )      r_fsm_state = FSM_RSP_WRITE;
316        }
317        break;
318    }
319    case FSM_RSP_WRITE:
320    {
321        if (r_address.read() != 0x3)
322            assert( write (r_seg_index, r_address , r_wdata, r_be ) && "out of bounds access in a write burst" );
323        if( p_vci.rspack.read() )
324        { 
325            if( m_latency )     r_fsm_state = FSM_IDLE;
326            else                r_fsm_state = FSM_CMD_GET;
327        }
328        break;
329    }
330    case FSM_RSP_READ:
331    {
332        if ( p_vci.rspack.read() )
333        {
334            r_flit_count = r_flit_count - 1;
335            if ( r_contig )     r_address  = r_address.read() + vci_param::B;
336            if ( r_flit_count == 1)     // last flit
337            {
338                if( m_latency ) r_fsm_state = FSM_IDLE;
339                else            r_fsm_state = FSM_CMD_GET;
340            }
341        }
342        break;
343    }
344    case FSM_CMD_ERROR:
345    {
346        if ( p_vci.cmdval.read() && p_vci.eop.read() )
347        {
348            r_fsm_state = FSM_RSP_ERROR;
349        }
350        break;
351    }
352    case FSM_RSP_ERROR:
353    {
354        if ( p_vci.rspack.read() ) 
355        {
356            if( m_latency )     r_fsm_state = FSM_IDLE;
357            else                r_fsm_state = FSM_CMD_GET;
358        }
359        break;
360    }
361    case FSM_RSP_LL:
362    {
363        if ( p_vci.rspack.read() ) 
364        {   
365            r_llsc_buf.doLoadLinked(r_address.read(), r_srcid.read());
366            if( m_latency )     r_fsm_state = FSM_IDLE;
367            else                r_fsm_state = FSM_CMD_GET;
368        }
369        break;
370    }
371    case FSM_RSP_SC:
372    {
373        if ( p_vci.rspack.read() ) 
374        {   
375            if ( r_llsc_buf.isAtomic(r_address.read(), r_srcid.read()) ) 
376            {
377                r_llsc_buf.accessDone(r_address.read());
378                write (r_seg_index, r_address , r_wdata, r_be);
379            }
380            if( m_latency )     r_fsm_state = FSM_IDLE;
381            else                r_fsm_state = FSM_CMD_GET;
382        }
383        break;
384    }
385    } // end switch fsm_state
386
387} // end transition()
388
389///////////////////////
390tmpl(void)::genMoore()
391{
392    switch ( r_fsm_state ) {
393    case FSM_IDLE:
394    {
395        p_vci.cmdack  = false;
396        p_vci.rspval  = false;
397        p_vci.rdata   = 0;
398        p_vci.rsrcid  = 0;
399        p_vci.rtrdid  = 0;
400        p_vci.rpktid  = 0;
401        p_vci.rerror  = 0;
402        p_vci.reop    = false;
403        break;
404    }
405    case FSM_CMD_GET:
406    case FSM_CMD_WRITE:
407    case FSM_CMD_ERROR:
408    {
409        p_vci.cmdack  = true;
410        p_vci.rspval  = false;
411        p_vci.rdata   = 0;
412        p_vci.rsrcid  = 0;
413        p_vci.rtrdid  = 0;
414        p_vci.rpktid  = 0;
415        p_vci.rerror  = 0;
416        p_vci.reop    = false;
417        break;
418    }
419    case FSM_RSP_WRITE:
420    {
421        p_vci.cmdack  = false;
422        p_vci.rspval  = true;
423        p_vci.rdata   = 0;
424        p_vci.rsrcid  = r_srcid.read();
425        p_vci.rtrdid  = r_trdid.read();
426        p_vci.rpktid  = r_pktid.read();
427        p_vci.rerror  = vci_param::ERR_NORMAL;
428        p_vci.reop    = true;
429        break;
430    }
431    case FSM_RSP_READ:
432    {
433        vci_data_t   rdata;
434        assert( read(r_seg_index, r_address, rdata) && "out of bounds access in a read burst" );
435        p_vci.cmdack = false;
436        p_vci.rspval = true;
437        p_vci.rdata  = rdata;
438        p_vci.rsrcid = r_srcid.read();
439        p_vci.rtrdid = r_trdid.read();
440        p_vci.rpktid = r_pktid.read();
441        p_vci.rerror = vci_param::ERR_NORMAL;
442        p_vci.reop   = (r_flit_count.read() == 1);
443        break;
444    }
445    case FSM_RSP_LL:
446    {
447        vci_data_t   rdata;
448        assert( read(r_seg_index, r_address, rdata) && "out of bounds access in a ll access" );
449        p_vci.cmdack = false;
450        p_vci.rspval = true;
451        p_vci.rdata  = rdata;
452        p_vci.rsrcid = r_srcid.read();
453        p_vci.rtrdid = r_trdid.read();
454        p_vci.rpktid = r_pktid.read();
455        p_vci.rerror = vci_param::ERR_NORMAL;
456        p_vci.reop   = true;
457        break;
458    }
459    case FSM_RSP_SC:
460    {
461        p_vci.cmdack = false;
462        p_vci.rspval = true;
463        if ( r_llsc_buf.isAtomic(r_address.read(), r_srcid.read()) ) p_vci.rdata = 0;
464        else                                                         p_vci.rdata = 1;
465        p_vci.rsrcid = r_srcid.read();
466        p_vci.rtrdid = r_trdid.read();
467        p_vci.rpktid = r_pktid.read();
468        p_vci.rerror = vci_param::ERR_NORMAL;
469        p_vci.reop   = true;
470        break;
471    }
472    case FSM_RSP_ERROR:
473    {
474        p_vci.cmdack  = false;
475        p_vci.rspval  = true;
476        p_vci.rdata   = 0;
477        p_vci.rsrcid  = r_srcid.read();
478        p_vci.rtrdid  = r_trdid.read();
479        p_vci.rpktid  = r_pktid.read();
480        p_vci.rerror  = vci_param::ERR_GENERAL_DATA_ERROR;
481        p_vci.reop    = true;
482        break;
483    }
484    } // end switch fsm_state
485} // end genMoore()
486
487}} 
488
489
Note: See TracBrowser for help on using the repository browser.