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

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

reconf: introducing a hardware barrier in the global-local interface of
the local interconnects.

  • This barrier is controlled by a port (barrier enable) in the dspin and vci local interconnects.
  • The barrier enable port is connected to a configuration register of the XICU component to allow the software to control this barrier. The barrier is enabled when the barrier enable port value is different of 0xFFFFFFFF. As the configuration register of the XICU component are reset to 0, this barrier is enabled by default.
  • This barrier allows to isolate the cluster from the rest of the architecture and only if it self-diagnoses as functional, it release the barrier to communicate with the others.
  • The same barrier enable signal is connected to the five local interconnects. Therefore, either all are released or all are disabled.
  • If a local initiator or an external initiator sends a packet out or into the cluster respectively, and the barrier is enabled, the packet is dropped.
File size: 18.5 KB
Line 
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    bool                    m_barrier;      // barrier in the global interface is enabled
81
82    sc_signal<bool>*            r_allocated;    // for each output port: allocation state
83    sc_signal<size_t>*          r_origin;               // for each output port: input port index
84    sc_signal<bool>*            r_bc_state;             // for each input port: broadcast requested
85    sc_signal<size_t>*          r_bc_count;             // for each input port: requested output index
86
87public:
88    ////////////////////////////////
89    SimpleCrossbar( size_t  cluster_id,     // cluster index
90                    size_t  in_size,        // number of inputs
91                    size_t  out_size,       // number of outputs
92                        void*   rt,             // routing table
93                        void*   lt,             // locality table
94                    bool    is_cmd )
95        : m_cluster_id( cluster_id ),
96      m_in_size( in_size ),
97          m_out_size( out_size ),
98          m_rt( rt ),
99          m_lt( lt ),
100      m_is_cmd( is_cmd ),
101      m_barrier( false )
102        {
103            r_allocated = new sc_signal<bool>[out_size];
104            r_origin    = new sc_signal<size_t>[out_size];
105        r_bc_state      = new sc_signal<bool>[in_size];
106            r_bc_count  = new sc_signal<size_t>[in_size];
107        } // end constructor
108
109    //////////////////////////////////
110    void setBarrier(const bool &value)
111    {
112        m_barrier = value;
113    }
114
115    ////////////
116    void reset()
117    {
118            for (size_t i=0; i<m_out_size; ++i) 
119        {
120                r_origin[i]    = 0;
121                r_allocated[i] = false;
122            }
123            for (size_t i=0; i<m_in_size; ++i) 
124        {
125                r_bc_state[i] = false;
126                r_bc_count[i] = 0;
127            }
128    } // end reset()
129
130    //////////////////
131    void print_trace()
132    {
133        for( size_t out=0 ; out<m_out_size ; out++)
134        {
135            if( r_allocated[out].read() ) 
136            {
137                if( m_is_cmd ) std::cout << std::dec
138                                         << "initiator " << r_origin[out].read()
139                                         << " =>  target " << out;
140                else           std::cout << std::dec
141                                         << "target " << r_origin[out].read()
142                                         << " => initiator " << out; 
143            }
144        }
145        for ( size_t in=0 ; in<m_in_size ; in++)
146        {
147            if( r_bc_state[in].read() )
148            {
149                if( m_is_cmd ) std::cout << " broadcast request from initiator " << in
150                                         << " requesting target " 
151                                         << r_bc_count[in].read();
152                else           std::cout << " broadcast request from target " << in
153                                         << " requesting initiator " 
154                                         << r_bc_count[in].read();
155            }
156        }
157        std::cout << " / barrier enable = " << m_barrier;
158    } // end print_trace()
159
160    //////////////////////////
161    size_t route( pkt_t flit )
162    {
163        if( m_is_cmd )  // we use a 64 bits AddressDecodingTable for ADDRESS
164        {
165            soclib::common::AddressDecodingTable<uint64_t, size_t>* rt =
166                   (soclib::common::AddressDecodingTable<uint64_t, size_t>*)m_rt;
167            return rt->get_value( (uint64_t)(flit.dest()) );
168        }
169        else            // we use a 32 bits AddressDecodingTable for SRCID
170        {
171            soclib::common::AddressDecodingTable<uint32_t, size_t>* rt =
172                   (soclib::common::AddressDecodingTable<uint32_t, size_t>*)m_rt;
173            return rt->get_value( (uint32_t)(flit.dest()) );
174        } 
175    } // end route()
176
177    ///////////////////////////
178    bool is_local( pkt_t flit )
179    {
180        if( m_is_cmd )  // we use a 64 bits AddressDecoding Table for ADDRESS
181        {
182            soclib::common::AddressDecodingTable<uint64_t, bool>* lt =
183                   (soclib::common::AddressDecodingTable<uint64_t, bool>*)m_lt;
184            return lt->get_value( (uint64_t)(flit.dest()) );
185        }
186        else            // we use a 32 bits AddressDecodingTable for SRCID
187        {
188            soclib::common::AddressDecodingTable<uint32_t, bool>* lt =
189                   (soclib::common::AddressDecodingTable<uint32_t, bool>*)m_lt;
190            return lt->get_value( (uint32_t)(flit.dest()) );
191        }
192    } // end is_local()
193
194    //////////////////////////////////////////////////////////////
195    void transition( typename pkt_t::input_port_t   **input_port, 
196                     typename pkt_t::output_port_t  **output_port )
197    {
198        // loop on the input ports to handle r_bc_state[in] and r_bc_count[in]
199        for( size_t in = 0 ; in < m_in_size ; in++ )
200        {
201            /* drop global-to-local packets when the barrier is enabled */
202            bool write = input_port[in]->getVal();
203            if ( in == (m_in_size - 1) )
204                write = write && !m_barrier;
205
206            if ( write )
207            {
208                if ( r_bc_state[in].read() )    // pending broadcast
209                {
210                    size_t out = r_bc_count[in];
211                    if ( ( r_allocated[out].read() ) &&
212                         ( r_origin[out].read() == in ) &&
213                         ( output_port[out]->toPeerEnd() ) )    // successfully transmitted
214                    {
215                        // the broadcast should not be sent to the requester...
216                        if ( (out == 0) || ((out == 1) && (in == 0)) )  r_bc_state[in] = false;
217                        else if ( (out-1) != in )       r_bc_count[in] = out-1;
218                        else                        r_bc_count[in] = out-2;
219                    }
220                }
221                else                            // no pending proadcast
222                {
223                    pkt_t tmp;
224                    tmp.readFrom(*input_port[in]);
225                    if ( tmp.is_broadcast() )           // broadcast request
226                    {
227                        assert( input_port[in]->eop && 
228                        "error in vci_local_crossbar : VCI broacast packet must be one flit");
229
230                        r_bc_state[in] = true;
231                        // the broadcast should not be sent to the requester...
232                        if ( in == m_in_size-1 ) r_bc_count[in] = m_out_size-2; 
233                        else                     r_bc_count[in] = m_out_size-1; 
234                    }
235                }
236            }
237        }
238
239        // loop on the output ports to handle r_allocated[out] and r_origin[out]
240        for ( size_t out = 0; out < m_out_size; out++) 
241        {
242            //  de-allocation if the last flit is accepted
243            if ( r_allocated[out] ) 
244            {
245                if ( output_port[out]->toPeerEnd() )   r_allocated[out] = false;
246            } 
247            // allocation respecting round-robin priority (even for broadcast)
248            else 
249            {
250                for(size_t _in = 0; _in < m_in_size; _in++) 
251                {
252                    size_t in = (_in + r_origin[out] + 1) % m_in_size;
253
254                    /* drop global-to-local packets when the barrier is enabled */
255                    bool write = input_port[in]->getVal();
256                    if ( in == (m_in_size - 1) )
257                        write = write && !m_barrier;
258
259                    if ( write )
260                    {
261                        pkt_t tmp;
262                        tmp.readFrom(*input_port[in]);
263
264                        // broadcast request
265                        bool bc_req = tmp.is_broadcast() and
266                                      r_bc_state[in].read() and (r_bc_count[in].read() == out);
267
268                        // to global request
269                        bool gl_req = not tmp.is_broadcast() and (out == m_out_size-1) and
270                                      not is_local( tmp ) and (in != m_in_size-1);
271
272                        // to local request
273                        bool lc_req = not tmp.is_broadcast() and (out == route( tmp )) and
274                                      is_local( tmp );
275
276                        // to migrated segment request (to local)
277                        bool mg_req = not tmp.is_broadcast() and (out == route( tmp )) and
278                                      not is_local( tmp ) and (in == m_in_size-1);
279
280                        if ( bc_req or gl_req or lc_req or mg_req )
281                        {
282                            r_allocated[out] = true;
283                            r_origin[out] = in;
284                            break;
285                        }
286                    }
287                }
288            }
289        }
290    } // end transition
291
292    /////////////////////////////////////////////////////////////
293    void genMealy( typename pkt_t::input_port_t   **input_port, 
294                   typename pkt_t::output_port_t  **output_port )
295    {
296        bool ack[m_in_size];
297        for( size_t in = 0; in < m_in_size; in++) ack[in] = false;
298
299        // transmit flits on output ports
300        for( size_t out = 0; out < m_out_size; out++) 
301        {
302            if (r_allocated[out]) 
303            {
304                        size_t in = r_origin[out];
305                pkt_t tmp;
306                tmp.readFrom(*input_port[in]);
307
308                // if the hardware barrier is activated, drop all
309                // local-to-global packets. This is done by consuming every
310                // incoming packet (send the acknowledgement to the input port)
311                // and resetting the cmdval signal to the upper network level.
312                bool read = output_port[out]->getAck();
313                if (out == (m_out_size - 1)) {
314                    read = read || m_barrier;
315                    tmp.set_val(tmp.val() && !m_barrier);
316                }
317
318                ack[in] = read;
319                tmp.writeTo(*output_port[out]);
320
321                if ( r_bc_state[in].read() )                    // its a broacast
322                {
323                    // in case of broadcast, the flit must be consumed only
324                    // if it is the last output port ...
325                    ack[in] = ack[in] && ( (out == 0) || ((out == 1) && (in == 0)) );
326                }
327            } 
328            else 
329            {
330                output_port[out]->setVal( false );
331            }
332        }
333        // Drop all global-to-local packets when the hardware barrier is enabled
334        ack[m_in_size - 1] = ack[m_in_size - 1] || m_barrier;
335
336        // Send acknowledges on input ports
337        for( size_t in = 0; in < m_in_size; in++) input_port[in]->setAck( ack[in] );
338    } // en genmealy
339
340}; // end class SimpleCrossbar
341
342#define tmpl(x) template<typename vci_param> x VciLocalCrossbar<vci_param>
343
344/////////////////////////
345tmpl(void)::print_trace()
346{
347    std::cout << "LOCAL_CROSSBAR " << name() << " / ";
348    m_cmd_crossbar->print_trace();
349    std::cout << " / ";
350    m_rsp_crossbar->print_trace();
351    std::cout << std::endl;
352}
353
354////////////////////////
355tmpl(void)::transition()
356{
357    if ( ! p_resetn.read() ) 
358    {
359        m_cmd_crossbar->reset();
360        m_rsp_crossbar->reset();
361        return;
362    }
363
364    if (p_barrier_enable != NULL)
365    {
366        const bool enable = (p_barrier_enable->read() != 0xFFFFFFFF);
367        m_cmd_crossbar->setBarrier(enable);
368        m_rsp_crossbar->setBarrier(enable);
369    }
370    m_cmd_crossbar->transition( m_ports_to_initiator, m_ports_to_target );
371    m_rsp_crossbar->transition( m_ports_to_target, m_ports_to_initiator );
372}
373
374//////////////////////
375tmpl(void)::genMealy()
376{
377    m_cmd_crossbar->genMealy( m_ports_to_initiator, m_ports_to_target );
378    m_rsp_crossbar->genMealy( m_ports_to_target, m_ports_to_initiator );
379}
380
381///////////////////////////////////////////////////////////////////////
382tmpl(/**/)::VciLocalCrossbar( sc_core::sc_module_name            name,
383                              const soclib::common::MappingTable &mt,
384                              const size_t                       cluster_id,
385                                  const size_t                       nb_attached_initiators,
386                                  const size_t                       nb_attached_targets,
387                              const size_t                       default_target_id,
388                              const bool                         hardware_barrier )
389       : BaseModule(name),
390       p_clk("clk"),
391       p_resetn("resetn"),
392           p_to_target(soclib::common::alloc_elems<VciInitiator<vci_param> >(
393                           "to_target", nb_attached_targets)),
394           p_to_initiator(soclib::common::alloc_elems<VciTarget<vci_param> >(
395                           "to_initiator", nb_attached_initiators)),
396       p_target_to_up("target_to_up"),
397       p_initiator_to_up("initiator_to_up"),
398       m_nb_attached_initiators(nb_attached_initiators),
399       m_nb_attached_targets(nb_attached_targets),
400       m_cmd_rt ( mt.getLocalIndexFromAddress( cluster_id, default_target_id ) ),
401       m_cmd_lt ( mt.getLocalMatchFromAddress( cluster_id ) ),
402       m_rsp_rt ( mt.getLocalIndexFromSrcid( cluster_id ) ),
403       m_rsp_lt ( mt.getLocalMatchFromSrcid( cluster_id ) )
404{
405    std::cout << "  - Building VciLocalCrossbar " << name << std::dec << std::endl
406              << "    => cluster_id     = " << cluster_id << std::endl
407              << "    => targets        = " << nb_attached_targets << std::endl
408              << "    => initiators     = " << nb_attached_initiators << std::endl
409              << "    => default target = " << default_target_id << std::endl;
410
411    SC_METHOD(transition);
412    dont_initialize();
413    sensitive << p_clk.pos();
414
415    SC_METHOD(genMealy);
416    dont_initialize();
417    sensitive << p_clk.neg();
418
419        for ( size_t i=0; i<nb_attached_initiators; ++i )
420                sensitive << p_to_initiator[i];
421        for ( size_t i=0; i<nb_attached_targets; ++i )
422                sensitive << p_to_target[i];
423
424    sensitive << p_target_to_up
425              << p_initiator_to_up;
426
427    // building cmd and rsp crossbars
428        m_cmd_crossbar = new SimpleCrossbar<VciCmdBuffer<vci_param> >(
429                         cluster_id,
430                         nb_attached_initiators+1, 
431                                 nb_attached_targets+1,
432                         (void*)(&m_cmd_rt),
433                         (void*)(&m_cmd_lt),
434                         true );
435
436        m_rsp_crossbar = new SimpleCrossbar<VciRspBuffer<vci_param> >(
437                                 cluster_id,
438                         nb_attached_targets+1, 
439                                 nb_attached_initiators+1,
440                         (void*)(&m_rsp_rt),
441                         (void*)(&m_rsp_lt),
442                         false );
443
444    m_ports_to_initiator = new VciTarget<vci_param>*[nb_attached_initiators+1];
445    for (size_t i=0; i<nb_attached_initiators; ++i)
446        m_ports_to_initiator[i] = &p_to_initiator[i];
447    m_ports_to_initiator[nb_attached_initiators] = &p_target_to_up;
448
449    m_ports_to_target = new VciInitiator<vci_param>*[nb_attached_targets+1];
450    for (size_t i=0; i<nb_attached_targets; ++i)
451        m_ports_to_target[i] = &p_to_target[i];
452    m_ports_to_target[nb_attached_targets] = &p_initiator_to_up;
453
454    if (hardware_barrier)
455        p_barrier_enable = new sc_in<uint32_t>("p_barrier_enable");
456    else
457        p_barrier_enable = NULL;
458}
459
460///////////////////////////////
461tmpl(/**/)::~VciLocalCrossbar()
462{
463    soclib::common::dealloc_elems(p_to_initiator, m_nb_attached_initiators);
464    soclib::common::dealloc_elems(p_to_target, m_nb_attached_targets);
465}
466
467}}
468
469// Local Variables:
470// tab-width: 4
471// c-basic-offset: 4
472// c-file-offsets:((innamespace . 0)(inline-open . 0))
473// indent-tabs-mode: nil
474// End:
475
476// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.