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

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

reconf: vci_local_crossbar: locality of packets coming from the
global network is not checked.

  • This is to allow a physical address space segment to be migrated from a faulty cluster to one of its neighbors. However, when this guess segment is accessed by a core of the host cluster, the request must go to the global network which will immediately return it.
File size: 16.7 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]);
[933]243
244                        // broadcast request
245                        bool bc_req = tmp.is_broadcast() and
246                                      r_bc_state[in].read() and (r_bc_count[in].read() == out);
247
248                        // to global request
249                        bool gl_req = not tmp.is_broadcast() and (out == m_out_size-1) and
250                                      not is_local( tmp ) and (in != m_in_size-1);
251
252                        // to local request
253                        bool lc_req = not tmp.is_broadcast() and (out == route( tmp )) and
254                                      is_local( tmp );
255
256                        // to migrated segment request (to local)
257                        bool mg_req = not tmp.is_broadcast() and (out == route( tmp )) and
258                                      not is_local( tmp ) and (in == m_in_size-1);
259
260                        if ( bc_req or gl_req or lc_req or mg_req )
[932]261                        {
262                            r_allocated[out] = true;
263                            r_origin[out] = in;
264                            break;
265                        }
266                    }
267                }
268            }
269        }
270    } // end transition
271
272    /////////////////////////////////////////////////////////////
273    void genMealy( typename pkt_t::input_port_t   **input_port, 
274                   typename pkt_t::output_port_t  **output_port )
275    {
276        bool ack[m_in_size];
277        for( size_t in = 0; in < m_in_size; in++) ack[in] = false;
278
279        // transmit flits on output ports
280        for( size_t out = 0; out < m_out_size; out++) 
281        {
282            if (r_allocated[out]) 
283            {
284                        size_t in = r_origin[out];
285                pkt_t tmp;
286                tmp.readFrom(*input_port[in]);
287                tmp.writeTo(*output_port[out]);
288                ack[in] = output_port[out]->getAck();
289                if ( r_bc_state[in].read() )                    // its a broacast
290                {
291                    // in case of broadcast, the flit must be consumed only
292                    // if it is the last output port ...
293                    ack[in] = ack[in] && ( (out == 0) || ((out == 1) && (in == 0)) );
294                }
295            } 
296            else 
297            {
298                output_port[out]->setVal( false );
299            }
300        }
301
302        // Send acknowledges on input ports
303        for( size_t in = 0; in < m_in_size; in++) input_port[in]->setAck( ack[in] );
304    } // en genmealy
305
306}; // end class SimpleCrossbar
307
308#define tmpl(x) template<typename vci_param> x VciLocalCrossbar<vci_param>
309
310/////////////////////////
311tmpl(void)::print_trace()
312{
313    std::cout << "LOCAL_CROSSBAR " << name() << " / ";
314    m_cmd_crossbar->print_trace();
315    m_rsp_crossbar->print_trace(); 
316    std::cout << std::endl;
317}
318
319////////////////////////
320tmpl(void)::transition()
321{
322    if ( ! p_resetn.read() ) 
323    {
324        m_cmd_crossbar->reset();
325        m_rsp_crossbar->reset();
326        return;
327    }
328
329    m_cmd_crossbar->transition( m_ports_to_initiator, m_ports_to_target );
330    m_rsp_crossbar->transition( m_ports_to_target, m_ports_to_initiator );
331}
332
333//////////////////////
334tmpl(void)::genMealy()
335{
336    m_cmd_crossbar->genMealy( m_ports_to_initiator, m_ports_to_target );
337    m_rsp_crossbar->genMealy( m_ports_to_target, m_ports_to_initiator );
338}
339
340///////////////////////////////////////////////////////////////////////
341tmpl(/**/)::VciLocalCrossbar( sc_core::sc_module_name            name,
342                              const soclib::common::MappingTable &mt,
343                              const size_t                       cluster_id,
344                                  const size_t                       nb_attached_initiators,
345                                  const size_t                       nb_attached_targets,
346                              const size_t                       default_target_id )
347       : BaseModule(name),
348       p_clk("clk"),
349       p_resetn("resetn"),
350           p_to_target(soclib::common::alloc_elems<VciInitiator<vci_param> >(
351                           "to_target", nb_attached_targets)),
352           p_to_initiator(soclib::common::alloc_elems<VciTarget<vci_param> >(
353                           "to_initiator", nb_attached_initiators)),
354       p_target_to_up("target_to_up"),
355       p_initiator_to_up("initiator_to_up"),
356       m_nb_attached_initiators(nb_attached_initiators),
357       m_nb_attached_targets(nb_attached_targets),
358       m_cmd_rt ( mt.getLocalIndexFromAddress( cluster_id, default_target_id ) ),
359       m_cmd_lt ( mt.getLocalMatchFromAddress( cluster_id ) ),
360       m_rsp_rt ( mt.getLocalIndexFromSrcid( cluster_id ) ),
361       m_rsp_lt ( mt.getLocalMatchFromSrcid( cluster_id ) )
362{
363    std::cout << "  - Building VciLocalCrossbar " << name << std::dec << std::endl
364              << "    => cluster_id     = " << cluster_id << std::endl
365              << "    => targets        = " << nb_attached_targets << std::endl
366              << "    => initiators     = " << nb_attached_initiators << std::endl
367              << "    => default target = " << default_target_id << std::endl;
368
369    SC_METHOD(transition);
370    dont_initialize();
371    sensitive << p_clk.pos();
372
373    SC_METHOD(genMealy);
374    dont_initialize();
375    sensitive << p_clk.neg();
376
377        for ( size_t i=0; i<nb_attached_initiators; ++i )
378                sensitive << p_to_initiator[i];
379        for ( size_t i=0; i<nb_attached_targets; ++i )
380                sensitive << p_to_target[i];
381
382    sensitive << p_target_to_up
383              << p_initiator_to_up;
384
385    // building cmd and rsp crossbars
386        m_cmd_crossbar = new SimpleCrossbar<VciCmdBuffer<vci_param> >(
387                         cluster_id,
388                         nb_attached_initiators+1, 
389                                 nb_attached_targets+1,
390                         (void*)(&m_cmd_rt),
391                         (void*)(&m_cmd_lt),
392                         true );
393
394        m_rsp_crossbar = new SimpleCrossbar<VciRspBuffer<vci_param> >(
395                                 cluster_id,
396                         nb_attached_targets+1, 
397                                 nb_attached_initiators+1,
398                         (void*)(&m_rsp_rt),
399                         (void*)(&m_rsp_lt),
400                         false );
401
402    m_ports_to_initiator = new VciTarget<vci_param>*[nb_attached_initiators+1];
403    for (size_t i=0; i<nb_attached_initiators; ++i)
404        m_ports_to_initiator[i] = &p_to_initiator[i];
405    m_ports_to_initiator[nb_attached_initiators] = &p_target_to_up;
406
407    m_ports_to_target = new VciInitiator<vci_param>*[nb_attached_targets+1];
408    for (size_t i=0; i<nb_attached_targets; ++i)
409        m_ports_to_target[i] = &p_to_target[i];
410    m_ports_to_target[nb_attached_targets] = &p_initiator_to_up;
411}
412
413///////////////////////////////
414tmpl(/**/)::~VciLocalCrossbar()
415{
416    soclib::common::dealloc_elems(p_to_initiator, m_nb_attached_initiators);
417    soclib::common::dealloc_elems(p_to_target, m_nb_attached_targets);
418}
419
420}}
421
422// Local Variables:
423// tab-width: 4
424// c-basic-offset: 4
425// c-file-offsets:((innamespace . 0)(inline-open . 0))
426// indent-tabs-mode: nil
427// End:
428
429// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.