source: branches/reconfiguration/modules/vci_local_crossbar/caba/source/src/vci_local_crossbar.cpp @ 932

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

reconf: introduce a vci_local_crossbar which support the segment
recovery mechanism.

File size: 16.4 KB
RevLine 
[932]1/*
2 * SOCLIB_LGPL_HEADER_BEGIN
3 *
4 * This file is part of SoCLib, GNU LGPLv2.1.
5 *
6 * SoCLib is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; version 2.1 of the License.
9 *
10 * SoCLib is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with SoCLib; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 * SOCLIB_LGPL_HEADER_END
21 *
22 * Copyright (c) UPMC, Lip6, Asim
23           Alain Greiner <alain.greiner@lip6.fr> 2005
24 *         Nicolas Pouillon <nipo@ssji.net>, 2008
25 *
26 * Maintainers: alain
27 */
28
29///////////////////////////////////////////////////////////////////////////
30// Implementation Note :
31// This component is implemented as two independant combinational
32// crossbars, for VCI commands and VCI responses respectively.
33// - The CMD crossbar has NI local plus one global input
34// ports. It has NT local + one global output ports.
35// - The RSP crossbar has NT local plus one global input
36// ports. It has NI local + one global output ports.
37// For each generic crossbar, the input and output ports are impemented
38// as arrays of ports, and the last port (i.e. the largest index value)
39// is the port connected to the global interconnect.
40//
41// This component does not contain FIFOs, and behaves as a Mealy FSM.
42//
43// It supportsi single flit VCI broadcast commands : If the
44// two lsb bits of the VCI ADDRESS are non zero, the corresponding
45// command is considered as a broadcast.
46// For a broadcast, the single VCI flit is SEQUENCIALLY transmitted
47// to the (NT+1) output ports, but not to the requesting input port.
48// For each transmitted flit to a given output port, the standard
49// round-robin allocation policy is respected.
50// As the broadcast command arriving on input port (i) should not be
51// transmitted to the requester, it is not transmitted on output port (i).
52// Therefore, in case of broadcast, NI & NT must be equal, and all
53// connected components mus have the same index for input & output ports.
54///////////////////////////////////////////////////////////////////////////
55
56#include <systemc>
57#include <cassert>
58#include "vci_buffers.h"
59#include "../include/vci_local_crossbar.h"
60#include "alloc_elems.h"
61
62namespace soclib { namespace caba {
63
64using soclib::common::alloc_elems;
65using soclib::common::dealloc_elems;
66
67using namespace sc_core;
68
69////////////////////////////////////////////////
70template<typename pkt_t> 
71class SimpleCrossbar
72////////////////////////////////////////////////
73{   
74    const size_t                    m_cluster_id;   // cluster index
75    const size_t                    m_in_size;          // total number of inputs (local + global)
76    const size_t                    m_out_size;         // total number of outputs (local + global)
77    const void*             m_rt;           // routing table if cmd  / masking table if rsp
78    const void*                 m_lt;           // locality table if cmd / id_locality table if rsp
79    const bool              m_is_cmd;       // cmd crossbar when true
80
81    sc_signal<bool>*            r_allocated;    // for each output port: allocation state
82    sc_signal<size_t>*          r_origin;               // for each output port: input port index
83    sc_signal<bool>*            r_bc_state;             // for each input port: broadcast requested
84    sc_signal<size_t>*          r_bc_count;             // for each input port: requested output index
85
86public:
87    ////////////////////////////////
88    SimpleCrossbar( size_t  cluster_id,     // cluster index
89                    size_t  in_size,        // number of inputs
90                    size_t  out_size,       // number of outputs
91                        void*   rt,             // routing table
92                        void*   lt,             // locality table
93                    bool    is_cmd )
94        : m_cluster_id( cluster_id ),
95      m_in_size( in_size ),
96          m_out_size( out_size ),
97          m_rt( rt ),
98          m_lt( lt ),
99      m_is_cmd( is_cmd )
100        {
101            r_allocated = new sc_signal<bool>[out_size];
102            r_origin    = new sc_signal<size_t>[out_size];
103        r_bc_state      = new sc_signal<bool>[in_size];
104            r_bc_count  = new sc_signal<size_t>[in_size];
105        } // end constructor
106
107    ////////////
108    void reset()
109    {
110            for (size_t i=0; i<m_out_size; ++i) 
111        {
112                r_origin[i]    = 0;
113                r_allocated[i] = false;
114            }
115            for (size_t i=0; i<m_in_size; ++i) 
116        {
117                r_bc_state[i] = false;
118                r_bc_count[i] = 0;
119            }
120    } // end reset()
121
122    //////////////////
123    void print_trace()
124    {
125        for( size_t out=0 ; out<m_out_size ; out++)
126        {
127            if( r_allocated[out].read() ) 
128            {
129                if( m_is_cmd ) std::cout << std::dec
130                                         << "initiator " << r_origin[out].read()
131                                         << " =>  target " << out;
132                else           std::cout << std::dec
133                                         << "target " << r_origin[out].read()
134                                         << " => initiator " << out; 
135            }
136        }
137        for ( size_t in=0 ; in<m_in_size ; in++)
138        {
139            if( r_bc_state[in].read() )
140            {
141                if( m_is_cmd ) std::cout << " broadcast request from initiator " << in
142                                         << " requesting target " 
143                                         << r_bc_count[in].read();
144                else           std::cout << " broadcast request from target " << in
145                                         << " requesting initiator " 
146                                         << r_bc_count[in].read();
147            }
148        }
149    } // end print_trace()
150
151    //////////////////////////
152    size_t route( pkt_t flit )
153    {
154        if( m_is_cmd )  // we use a 64 bits AddressDecodingTable for ADDRESS
155        {
156            soclib::common::AddressDecodingTable<uint64_t, size_t>* rt =
157                   (soclib::common::AddressDecodingTable<uint64_t, size_t>*)m_rt;
158            return rt->get_value( (uint64_t)(flit.dest()) );
159        }
160        else            // we use a 32 bits AddressDecodingTable for SRCID
161        {
162            soclib::common::AddressDecodingTable<uint32_t, size_t>* rt =
163                   (soclib::common::AddressDecodingTable<uint32_t, size_t>*)m_rt;
164            return rt->get_value( (uint32_t)(flit.dest()) );
165        } 
166    } // end route()
167
168    ///////////////////////////
169    bool is_local( pkt_t flit )
170    {
171        if( m_is_cmd )  // we use a 64 bits AddressDecoding Table for ADDRESS
172        {
173            soclib::common::AddressDecodingTable<uint64_t, bool>* lt =
174                   (soclib::common::AddressDecodingTable<uint64_t, bool>*)m_lt;
175            return lt->get_value( (uint64_t)(flit.dest()) );
176        }
177        else            // we use a 32 bits AddressDecodingTable for SRCID
178        {
179            soclib::common::AddressDecodingTable<uint32_t, bool>* lt =
180                   (soclib::common::AddressDecodingTable<uint32_t, bool>*)m_lt;
181            return lt->get_value( (uint32_t)(flit.dest()) );
182        }
183    } // end is_local()
184
185    //////////////////////////////////////////////////////////////
186    void transition( typename pkt_t::input_port_t   **input_port, 
187                     typename pkt_t::output_port_t  **output_port )
188    {
189        // loop on the input ports to handle r_bc_state[in] and r_bc_count[in]
190        for( size_t in = 0 ; in < m_in_size ; in++ )
191        {
192            if ( input_port[in]->getVal() )
193            {
194                if ( r_bc_state[in].read() )    // pending broadcast
195                {
196                    size_t out = r_bc_count[in];
197                    if ( ( r_allocated[out].read() ) &&
198                         ( r_origin[out].read() == in ) &&
199                         ( output_port[out]->toPeerEnd() ) )    // successfully transmitted
200                    {
201                        // the broadcast should not be sent to the requester...
202                        if ( (out == 0) || ((out == 1) && (in == 0)) )  r_bc_state[in] = false;
203                        else if ( (out-1) != in )       r_bc_count[in] = out-1;
204                        else                        r_bc_count[in] = out-2;
205                    }
206                }
207                else                            // no pending proadcast
208                {
209                    pkt_t tmp;
210                    tmp.readFrom(*input_port[in]);
211                    if ( tmp.is_broadcast() )           // broadcast request
212                    {
213                        assert( input_port[in]->eop && 
214                        "error in vci_local_crossbar : VCI broacast packet must be one flit");
215
216                        r_bc_state[in] = true;
217                        // the broadcast should not be sent to the requester...
218                        if ( in == m_in_size-1 ) r_bc_count[in] = m_out_size-2; 
219                        else                     r_bc_count[in] = m_out_size-1; 
220                    }
221                }
222            }
223        }
224
225        // loop on the output ports to handle r_allocated[out] and r_origin[out]
226        for ( size_t out = 0; out < m_out_size; out++) 
227        {
228            //  de-allocation if the last flit is accepted
229            if ( r_allocated[out] ) 
230            {
231                if ( output_port[out]->toPeerEnd() )   r_allocated[out] = false;
232            } 
233            // allocation respecting round-robin priority (even for broadcast)
234            else 
235            {
236                for(size_t _in = 0; _in < m_in_size; _in++) 
237                {
238                    size_t in = (_in + r_origin[out] + 1) % m_in_size;
239                    if ( input_port[in]->getVal() )
240                    {
241                        pkt_t tmp;
242                        tmp.readFrom(*input_port[in]);
243                        if ( (tmp.is_broadcast() and
244                              r_bc_state[in].read() and
245                              (r_bc_count[in].read() == out))   or   // broadcast request
246                             (not tmp.is_broadcast() and
247                              not is_local( tmp ) and
248                              (out == m_out_size-1))            or   // to global network
249                             (not tmp.is_broadcast() and
250                              is_local( tmp ) and
251                              (out == route( tmp )) ) )              // to local component
252                        {
253                            r_allocated[out] = true;
254                            r_origin[out] = in;
255                            break;
256                        }
257                    }
258                }
259            }
260        }
261    } // end transition
262
263    /////////////////////////////////////////////////////////////
264    void genMealy( typename pkt_t::input_port_t   **input_port, 
265                   typename pkt_t::output_port_t  **output_port )
266    {
267        bool ack[m_in_size];
268        for( size_t in = 0; in < m_in_size; in++) ack[in] = false;
269
270        // transmit flits on output ports
271        for( size_t out = 0; out < m_out_size; out++) 
272        {
273            if (r_allocated[out]) 
274            {
275                        size_t in = r_origin[out];
276                pkt_t tmp;
277                tmp.readFrom(*input_port[in]);
278                tmp.writeTo(*output_port[out]);
279                ack[in] = output_port[out]->getAck();
280                if ( r_bc_state[in].read() )                    // its a broacast
281                {
282                    // in case of broadcast, the flit must be consumed only
283                    // if it is the last output port ...
284                    ack[in] = ack[in] && ( (out == 0) || ((out == 1) && (in == 0)) );
285                }
286            } 
287            else 
288            {
289                output_port[out]->setVal( false );
290            }
291        }
292
293        // Send acknowledges on input ports
294        for( size_t in = 0; in < m_in_size; in++) input_port[in]->setAck( ack[in] );
295    } // en genmealy
296
297}; // end class SimpleCrossbar
298
299#define tmpl(x) template<typename vci_param> x VciLocalCrossbar<vci_param>
300
301/////////////////////////
302tmpl(void)::print_trace()
303{
304    std::cout << "LOCAL_CROSSBAR " << name() << " / ";
305    m_cmd_crossbar->print_trace();
306    m_rsp_crossbar->print_trace(); 
307    std::cout << std::endl;
308}
309
310////////////////////////
311tmpl(void)::transition()
312{
313    if ( ! p_resetn.read() ) 
314    {
315        m_cmd_crossbar->reset();
316        m_rsp_crossbar->reset();
317        return;
318    }
319
320    m_cmd_crossbar->transition( m_ports_to_initiator, m_ports_to_target );
321    m_rsp_crossbar->transition( m_ports_to_target, m_ports_to_initiator );
322}
323
324//////////////////////
325tmpl(void)::genMealy()
326{
327    m_cmd_crossbar->genMealy( m_ports_to_initiator, m_ports_to_target );
328    m_rsp_crossbar->genMealy( m_ports_to_target, m_ports_to_initiator );
329}
330
331///////////////////////////////////////////////////////////////////////
332tmpl(/**/)::VciLocalCrossbar( sc_core::sc_module_name            name,
333                              const soclib::common::MappingTable &mt,
334                              const size_t                       cluster_id,
335                                  const size_t                       nb_attached_initiators,
336                                  const size_t                       nb_attached_targets,
337                              const size_t                       default_target_id )
338       : BaseModule(name),
339       p_clk("clk"),
340       p_resetn("resetn"),
341           p_to_target(soclib::common::alloc_elems<VciInitiator<vci_param> >(
342                           "to_target", nb_attached_targets)),
343           p_to_initiator(soclib::common::alloc_elems<VciTarget<vci_param> >(
344                           "to_initiator", nb_attached_initiators)),
345       p_target_to_up("target_to_up"),
346       p_initiator_to_up("initiator_to_up"),
347       m_nb_attached_initiators(nb_attached_initiators),
348       m_nb_attached_targets(nb_attached_targets),
349       m_cmd_rt ( mt.getLocalIndexFromAddress( cluster_id, default_target_id ) ),
350       m_cmd_lt ( mt.getLocalMatchFromAddress( cluster_id ) ),
351       m_rsp_rt ( mt.getLocalIndexFromSrcid( cluster_id ) ),
352       m_rsp_lt ( mt.getLocalMatchFromSrcid( cluster_id ) )
353{
354    std::cout << "  - Building VciLocalCrossbar " << name << std::dec << std::endl
355              << "    => cluster_id     = " << cluster_id << std::endl
356              << "    => targets        = " << nb_attached_targets << std::endl
357              << "    => initiators     = " << nb_attached_initiators << std::endl
358              << "    => default target = " << default_target_id << std::endl;
359
360    SC_METHOD(transition);
361    dont_initialize();
362    sensitive << p_clk.pos();
363
364    SC_METHOD(genMealy);
365    dont_initialize();
366    sensitive << p_clk.neg();
367
368        for ( size_t i=0; i<nb_attached_initiators; ++i )
369                sensitive << p_to_initiator[i];
370        for ( size_t i=0; i<nb_attached_targets; ++i )
371                sensitive << p_to_target[i];
372
373    sensitive << p_target_to_up
374              << p_initiator_to_up;
375
376    // building cmd and rsp crossbars
377        m_cmd_crossbar = new SimpleCrossbar<VciCmdBuffer<vci_param> >(
378                         cluster_id,
379                         nb_attached_initiators+1, 
380                                 nb_attached_targets+1,
381                         (void*)(&m_cmd_rt),
382                         (void*)(&m_cmd_lt),
383                         true );
384
385        m_rsp_crossbar = new SimpleCrossbar<VciRspBuffer<vci_param> >(
386                                 cluster_id,
387                         nb_attached_targets+1, 
388                                 nb_attached_initiators+1,
389                         (void*)(&m_rsp_rt),
390                         (void*)(&m_rsp_lt),
391                         false );
392
393    m_ports_to_initiator = new VciTarget<vci_param>*[nb_attached_initiators+1];
394    for (size_t i=0; i<nb_attached_initiators; ++i)
395        m_ports_to_initiator[i] = &p_to_initiator[i];
396    m_ports_to_initiator[nb_attached_initiators] = &p_target_to_up;
397
398    m_ports_to_target = new VciInitiator<vci_param>*[nb_attached_targets+1];
399    for (size_t i=0; i<nb_attached_targets; ++i)
400        m_ports_to_target[i] = &p_to_target[i];
401    m_ports_to_target[nb_attached_targets] = &p_initiator_to_up;
402}
403
404///////////////////////////////
405tmpl(/**/)::~VciLocalCrossbar()
406{
407    soclib::common::dealloc_elems(p_to_initiator, m_nb_attached_initiators);
408    soclib::common::dealloc_elems(p_to_target, m_nb_attached_targets);
409}
410
411}}
412
413// Local Variables:
414// tab-width: 4
415// c-basic-offset: 4
416// c-file-offsets:((innamespace . 0)(inline-open . 0))
417// indent-tabs-mode: nil
418// End:
419
420// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.