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

Last change on this file was 1013, checked in by cfuguet, 8 years ago

reconf: bugfix in reconf:vci_local_crossbar regarding the hardware
barrier.

Release the barrier if there is no pending global-to-local
request.

This avoid a race condition between a global-to-local request, and the
release of the barrier. In such situation, for multi-flit packets,
some flits may be dropped and others not. Therefore, a packet must be
consumed completely before the barrier release.

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