source: trunk/modules/vci_iox_network/caba/source/src/vci_iox_network.cpp @ 716

Last change on this file since 716 was 716, checked in by cfuguet, 10 years ago

vci_iox_network:

  • Erasing extra spaces
File size: 12.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> 2013
24 *
25 * Maintainers: alain
26 */
27
28////////////////////////////////////////////////////////////////////////////////
29// This component emulates an external IO bus such as PCIe or Hypertransport,
30// but respect the VCI protocol. It can be attached to one OR SEVERAL clusters,
31// using a vci_io_bridge component.
32// It is considered as a local interconnect, for the ADDRESS or SRCID
33// decoding tables:
34// - the CMD routing_table decodes the local field of the VCI ADDRESS
35//   to return the local target port
36// - The RSP routing_table decodes the local field of the VCI SRCID
37//   to return the initator port
38// It is implemented as two independant crossbars, for VCI commands and
39// VCI responses respectively.
40// - The CMD crossbar has nb_ini input ports, and nb_tgt output ports,
41//   including the ports to the vci_io_bridge component(s).
42// - The RSP crossbar has nb_tgt input ports, and nb_ini output ports.
43//   including the ports to the vci_io_bridge component(s).
44// For both crossbars, output ports allocation policy is round robin.
45////////////////////////////////////////////////////////////////////////////////
46
47#include <systemc>
48#include <cassert>
49#include "vci_buffers.h"
50#include "../include/vci_iox_network.h"
51#include "alloc_elems.h"
52
53namespace soclib { namespace caba {
54
55using soclib::common::alloc_elems;
56using soclib::common::dealloc_elems;
57
58using namespace sc_core;
59
60///////////////////////////////////////////////////////////////////////////////////
61// The IoXbar class is instanciated twice, to implement the CMD & RSP XBARs
62///////////////////////////////////////////////////////////////////////////////////
63template<typename pkt_t> class IoXbar
64{
65    // pkt_t type must be VciCmdBuffer<vci_param> or VciRspBuffer<vci_param>
66    // the two following types can be found in these two classes
67
68    typedef typename pkt_t::input_port_t    input_port_t;
69    typedef typename pkt_t::output_port_t   output_port_t;
70
71    const bool            m_is_cmd;         // CMD XBAR if true
72    const size_t          m_inputs;         // number of inputs
73    const size_t          m_outputs;        // number of outputs
74    void*                 m_rt;             // pointer on routing table (CMD or RSP)
75
76    sc_signal<bool>*      r_out_allocated;  // for each output: allocation state
77    sc_signal<size_t>*    r_out_origin;     // for each output: input port index
78    sc_signal<bool>*      r_in_allocated;   // for each input: allocation state
79    sc_signal<size_t>*    r_in_dest;        // for each input: output port index
80
81public:
82    ///////////////////////
83    IoXbar( bool   is_cmd, 
84            size_t nb_inputs,
85            size_t nb_outputs,
86            void*  rt )
87    : m_is_cmd( is_cmd ),
88      m_inputs( nb_inputs ),
89      m_outputs( nb_outputs ),
90      m_rt ( rt )
91    {
92        r_out_allocated = new sc_signal<bool>[nb_outputs];
93        r_out_origin    = new sc_signal<size_t>[nb_outputs];
94        r_in_allocated  = new sc_signal<bool>[nb_inputs];
95        r_in_dest       = new sc_signal<size_t>[nb_inputs];
96    }
97
98    ////////////
99    void reset()
100    {
101        for (size_t i=0 ; i<m_outputs ; ++i) 
102        {
103            r_out_origin[i]    = 0;
104            r_out_allocated[i] = false;
105        }
106        for (size_t i=0 ; i<m_inputs ; ++i) 
107        {
108            r_in_dest[i]      = 0;
109            r_in_allocated[i] = false;
110        }
111    }
112
113    //////////////////
114    void print_trace()
115    {
116        if ( m_is_cmd )
117        {
118            std::cout << "IOX_CMD_XBAR : " << std::dec;
119            for( size_t out=0 ; out<m_outputs ; out++)
120            {
121                if( r_out_allocated[out].read() ) 
122                {
123                    std::cout << "ini " << r_out_origin[out].read() 
124                              << " => tgt " << out << " | ";
125                }
126            }
127        }
128        else
129        {
130            std::cout << "IOX_RSP_XBAR : " << std::dec;
131            for( size_t out=0 ; out<m_outputs ; out++)
132            {
133                if( r_out_allocated[out].read() ) 
134                {
135                    std::cout << "tgt " << r_out_origin[out].read() 
136                              << " => ini " << out << " | ";
137                }
138            }
139        }
140        std::cout << std::endl;
141    }
142
143    ///////////////////////////////////////////
144    void transition( input_port_t  **input_port, 
145                     output_port_t **output_port )
146    {
147        // loop on the output ports
148        for ( size_t out = 0; out < m_outputs; out++) 
149        {
150            if ( r_out_allocated[out].read() )          // possible desallocation
151            {
152                if ( output_port[out]->toPeerEnd() )   
153                {
154                    size_t in = r_out_origin[out].read();
155                    r_out_allocated[out] = false;
156                    r_in_allocated[in]   = false;
157                }
158            } 
159            else                                        // possible allocation
160            {
161                // loop on the intput ports
162                bool found = false;
163                for(size_t x = 0 ; (x < m_inputs) and not found ; x++) 
164                {
165                    size_t in = (x + r_out_origin[out] + 1) % m_inputs;
166                    if ( input_port[in]->getVal() )
167                    {
168                        size_t req;       // requested output port index
169                        if ( m_is_cmd ) 
170                        {
171                            AddressDecodingTable<uint64_t, size_t>* rt = 
172                               (AddressDecodingTable<uint64_t, size_t>*)m_rt;
173                            req = rt->get_value((uint64_t)(input_port[in]->address.read())); 
174                        }
175                        else           
176                        {
177                            AddressDecodingTable<uint32_t, size_t>* rt = 
178                               (AddressDecodingTable<uint32_t, size_t>*)m_rt;
179                            req = rt->get_value((uint32_t)(input_port[in]->rsrcid.read())); 
180                        }
181                        // allocate the output port if requested
182                        if ( out == req )
183                        {
184                            r_out_allocated[out] = true;
185                            r_in_allocated[in]   = true;
186                            r_out_origin[out]    = in;
187                            r_in_dest[in]        = out;
188                            found                = true;
189                        }
190                    }
191                }  // end loop inputs
192            }
193        }  // end loop outputs
194    } // end transition
195
196    //////////////////////////////////////////////
197    void genMealy_ack( input_port_t  **input_port,
198                       output_port_t **output_port )
199    {
200        for ( size_t in = 0 ; in < m_inputs ; in++ )
201        {
202            size_t out = r_in_dest[in].read();
203            bool   ack = r_in_allocated[in].read() and output_port[out]->getAck();
204            input_port[in]->setAck(ack);
205        }
206    }
207
208    ///////////////////////////////////////////////////////////////////////
209    void genMealy_val( input_port_t  **input_port, 
210                       output_port_t **output_port )
211    {
212        for( size_t out = 0 ; out < m_outputs ; out++) 
213        {
214            if (r_out_allocated[out]) 
215            {
216                size_t in = r_out_origin[out];
217                pkt_t tmp;
218                tmp.readFrom(*input_port[in]);
219                tmp.writeTo(*output_port[out]);
220            } 
221            else 
222            {
223                output_port[out]->setVal(false);
224            }
225        }
226    } 
227
228}; // end class IoXbar
229
230
231///////////////////////////////////////////////////////////////////////////////////
232#define tmpl(x) template<typename vci_param> x VciIoxNetwork<vci_param>
233///////////////////////////////////////////////////////////////////////////////////
234
235/////////////////////////
236tmpl(void)::print_trace()
237{
238    m_cmd_xbar->print_trace();
239    m_rsp_xbar->print_trace();
240}
241
242////////////////////////
243tmpl(void)::transition()
244{
245    if ( ! p_resetn.read() ) 
246    {
247        m_cmd_xbar->reset();
248        m_rsp_xbar->reset();
249        return;
250    }
251
252    m_cmd_xbar->transition( m_ports_to_initiator, m_ports_to_target );
253    m_rsp_xbar->transition( m_ports_to_target, m_ports_to_initiator );
254}
255
256//////////////////////////////
257tmpl(void)::genMealy_cmd_val()
258{
259    m_cmd_xbar->genMealy_val( m_ports_to_initiator, m_ports_to_target );
260}
261
262//////////////////////////////
263tmpl(void)::genMealy_cmd_ack()
264{
265    m_cmd_xbar->genMealy_ack( m_ports_to_initiator, m_ports_to_target );
266}
267
268//////////////////////////////
269tmpl(void)::genMealy_rsp_val()
270{
271    m_rsp_xbar->genMealy_val( m_ports_to_target, m_ports_to_initiator );
272}
273
274//////////////////////////////
275tmpl(void)::genMealy_rsp_ack()
276{
277    m_rsp_xbar->genMealy_ack( m_ports_to_target, m_ports_to_initiator );
278}
279
280///////////////////////////////////////////////////////////////////////////
281tmpl(/**/)::VciIoxNetwork( sc_core::sc_module_name             name,
282                           const soclib::common::MappingTable  &mt,
283                           size_t                              nb_tgt,
284                           size_t                              nb_ini )
285           : BaseModule(name),
286           p_clk("clk"),
287           p_resetn("resetn"),
288           p_to_tgt(soclib::common::alloc_elems<VciInitiator<vci_param> >(
289                          "p_to_tgt", nb_tgt)),
290           p_to_ini(soclib::common::alloc_elems<VciTarget<vci_param> >(
291                          "p_to_ini", nb_ini)),
292
293           m_nb_tgt( nb_tgt ),
294           m_nb_ini( nb_ini ),
295
296           m_cmd_rt( mt.getLocalIndexFromAddress(0) ),
297           m_rsp_rt( mt.getLocalIndexFromSrcid(0) )
298{
299    std::cout << "    Building VciIoxNetwork : " << name << std::endl;
300
301    SC_METHOD(transition);
302    dont_initialize();
303    sensitive << p_clk.pos();
304
305    SC_METHOD(genMealy_cmd_val);        // controls to targets CMDVAL
306    dont_initialize();
307    sensitive << p_clk.neg();
308    for ( size_t i=0; i<nb_ini; ++i )   sensitive << p_to_ini[i];
309
310    SC_METHOD(genMealy_cmd_ack);        // controls to intiators CMDACK
311    dont_initialize();
312    sensitive << p_clk.neg();
313    for ( size_t i=0; i<nb_tgt; ++i )   sensitive << p_to_tgt[i];
314
315    SC_METHOD(genMealy_rsp_val);        // controls to initiators RSPVAL
316    dont_initialize();
317    sensitive << p_clk.neg();
318    for ( size_t i=0; i<nb_tgt; ++i )   sensitive << p_to_tgt[i];
319
320    SC_METHOD(genMealy_rsp_ack);        // controls to targets RSPACK
321    dont_initialize();
322    sensitive << p_clk.neg();
323    for ( size_t i=0; i<nb_ini; ++i )   sensitive << p_to_ini[i];
324
325    // constructing CMD & RSP XBARs
326    m_rsp_xbar = new rsp_xbar_t( false,         // RSP XBAR
327                                 nb_tgt,
328                                 nb_ini,
329                                 &m_rsp_rt );
330
331    m_cmd_xbar = new cmd_xbar_t( true,          // CMD XBAR
332                                 nb_ini,
333                                 nb_tgt,
334                                 &m_cmd_rt );
335
336    // constructing  CMD & RSP XBARs input & output ports (pointers)
337    m_ports_to_initiator = new VciTarget<vci_param>*[nb_ini];
338    for (size_t g = 0 ; g < nb_ini ; g++) m_ports_to_initiator[g] = &p_to_ini[g];
339
340    m_ports_to_target = new VciInitiator<vci_param>*[nb_tgt];
341    for (size_t g = 0 ; g < nb_tgt ; g++) m_ports_to_target[g] = &p_to_tgt[g];
342}
343
344////////////////////////////
345tmpl(/**/)::~VciIoxNetwork()
346{
347    soclib::common::dealloc_elems(p_to_ini, m_nb_ini);
348    soclib::common::dealloc_elems(p_to_tgt, m_nb_tgt);
349}
350
351}}
352
353// Local Variables:
354// tab-width: 4
355// c-basic-offset: 4
356// c-file-offsets:((innamespace . 0)(inline-open . 0))
357// indent-tabs-mode: nil
358// End:
359
360// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.