source: trunk/modules/dspin_router_tsar/caba/source/src/dspin_router_tsar.cpp @ 578

Last change on this file since 578 was 578, checked in by alain, 10 years ago

Fixing a bug in the dspin_router_tsar component
(in the modified routing function)

File size: 13.2 KB
RevLine 
[549]1/* -*- c++ -*-
2  *
3  * File : dspin_router_tsar.cpp
4  * Copyright (c) UPMC, Lip6
5  * Authors : Alain Greiner, Abbas Sheibanyrad, Ivan Miro, Zhen Zhang
6  *
7  * SOCLIB_LGPL_HEADER_BEGIN
8  *
9  * This file is part of SoCLib, GNU LGPLv2.1.
10  *
11  * SoCLib is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License as published
13  * by the Free Software Foundation; version 2.1 of the License.
14  *
15  * SoCLib is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with SoCLib; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  *
25  * SOCLIB_LGPL_HEADER_END
26  *
27  */
28
29////////////////////////////////////////////////////////////////////////////////
30// This component implements a variant of the standard (SocLib)  DSPIN router:
31// The routing function has been modified to handle the special case of
32// cluster_iob0 (containing component IOB0) and cluster_iob1 (containing
33// component IOB1). In those two cluster, the response router must decode
34// both the SRCID global bits AND the SRCID local bits to distinguish
35// between the IOB and MEMC initiators.
36// This component contains the following modifications:
[578]37// - 4 new constructor arguments
[549]38// - 6 new member variables
39// - a modified routing function
40////////////////////////////////////////////////////////////////////////////////
41
42#include "../include/dspin_router_tsar.h"
43
44namespace soclib { namespace caba {
45
46using namespace soclib::common;
47using namespace soclib::caba;
48
49#define tmpl(x) template<int flit_width> x DspinRouterTsar<flit_width>
50
51    ////////////////////////////////////////////////
52    //              constructor
53    ////////////////////////////////////////////////
54    tmpl(/**/)::DspinRouterTsar( 
55                sc_module_name name, 
56                const size_t   x,              // x coordinate
57                const size_t   y,              // y cordinate
58                const size_t   x_width,        // x field width in first flit
59                const size_t   y_width,        // y field width in first flit
60                const size_t   in_fifo_depth,  // input fifo depth
61                const size_t   out_fifo_depth, // output fifo depth
[578]62
63                const bool     is_iob0,        // cluster contains iob0
64                const bool     is_iob1,        // cluster contains iob1
65                const bool     is_rsp,         // only response router is modified
66                const size_t   l_width)        // local field srcid width
[549]67        : soclib::caba::BaseModule(name),
68
69      p_clk( "p_clk" ),
70      p_resetn( "p_resetn" ),
71      p_in( alloc_elems<DspinInput<flit_width> >("p_in", 5) ),
72      p_out( alloc_elems<DspinOutput<flit_width> >("p_out", 5) ),
73
74          r_alloc_out( alloc_elems<sc_signal<bool> >("r_alloc_out", 5)),
75          r_index_out( soclib::common::alloc_elems<sc_signal<size_t> >("r_index_out", 5)),
76          r_fsm_in( alloc_elems<sc_signal<int> >("r_fsm_in", 5)),
77          r_index_in( alloc_elems<sc_signal<size_t> >("r_index_in", 5)),
78
79      m_local_x( x ),
80      m_local_y( y ),
81
82      m_x_width( x_width ),
83      m_x_shift( flit_width - x_width ),
84      m_x_mask( (0x1 << x_width) - 1 ),
85
86      m_y_width( y_width ),
87      m_y_shift( flit_width - x_width - y_width ),
88      m_y_mask( (0x1 << y_width) - 1 ),
89
90      m_l_width( l_width ),
91      m_l_shift( flit_width - x_width - y_width - l_width ),
92      m_l_mask( (0x1 << l_width) - 1 ),
93
[578]94      m_is_iob0( is_iob0 ),
95      m_is_iob1( is_iob1 ),
96      m_is_rsp( is_rsp )
[549]97
98    {
99        std::cout << "  - Building DspinRouterTsar : " << name << std::endl;
100
101            SC_METHOD (transition);
102            dont_initialize();
103            sensitive << p_clk.pos();
104
105            SC_METHOD (genMoore);
106            dont_initialize();
107            sensitive  << p_clk.neg();
108
109            r_fifo_in  = (GenericFifo<internal_flit_t>*)
110                         malloc(sizeof(GenericFifo<internal_flit_t>)*5);
111            r_fifo_out = (GenericFifo<internal_flit_t>*)
112                         malloc(sizeof(GenericFifo<internal_flit_t>)*5);
113
114            for( size_t i = 0 ; i < 5 ; i++ )
115        {
116                    std::ostringstream stri;
117                    stri << "r_in_fifo_" << i;
118                new(&r_fifo_in[i]) 
119                GenericFifo<internal_flit_t >(stri.str(), in_fifo_depth);
120
121                    std::ostringstream stro;
122                    stro << "r_out_fifo_" << i;
123                new(&r_fifo_out[i]) 
124                GenericFifo<internal_flit_t >(stro.str(), out_fifo_depth);
125            }
126    } //  end constructor
127
128    //////////////////////////////////////////////////
129    tmpl(size_t)::route( sc_uint<flit_width> data )
130    {
131        size_t xdest = (size_t)(data >> m_x_shift) & m_x_mask;
132        size_t ydest = (size_t)(data >> m_y_shift) & m_y_mask;
133        size_t ldest = (size_t)(data >> m_l_shift) & m_l_mask;
134
135        if      (xdest < m_local_x ) return DSPIN_WEST;
136        else if (xdest > m_local_x ) return DSPIN_EAST; 
137        else if (ydest < m_local_y ) return DSPIN_SOUTH;
138        else if (ydest > m_local_y ) return DSPIN_NORTH;
139        else    // handling IOB0 & IOB1 special cases
140        {
[578]141            if      (m_is_rsp and m_is_iob0 and (ldest > 0xA)) return DSPIN_WEST;
142            else if (m_is_rsp and m_is_iob1 and (ldest > 0xA)) return DSPIN_EAST;
143            else                                               return DSPIN_LOCAL;
[549]144        }
145    } // end route()
146
147    /////////////////////////
148    tmpl(void)::print_trace()
149    {
150        const char* port_name[] = {"NORTH","SOUTH","EAST ","WEST ","LOCAL"};
151
152        std::cout << "DSPIN_ROUTER " << name() << std::hex; 
153        for ( size_t out=0 ; out<5 ; out++)  // loop on output ports
154        {
155            if ( r_alloc_out[out].read() )
156            {
157                int in = r_index_out[out];
158                std::cout << " / " << port_name[in] << " -> " << port_name[out] ;
159            }   
160        }
161        std::cout << std::endl;
162    }
163
164    ////////////////////////
165    tmpl(void)::transition()
166    {
167        // Long wires connecting input and output ports
168        size_t              req_in[5];         // input ports  -> output ports
169        size_t              get_out[5];        // output ports -> input ports
170        bool                put_in[5];         // input ports  -> output ports
171        internal_flit_t     flit_in[5];        // input ports  -> output ports
172
173        // control signals for the input fifos
174            bool                fifo_in_write[5];
175            bool                fifo_in_read[5];       
176            internal_flit_t     fifo_in_wdata[5];
177
178        // control signals for the output fifos
179            bool                fifo_out_write[5];
180            bool                fifo_out_read[5];
181            internal_flit_t     fifo_out_wdata[5];
182
183            // Reset
184            if ( p_resetn == false ) 
185        {
186                for(size_t i = 0 ; i < 5 ; i++) 
187            {
188                        r_alloc_out[i] = false;
189                        r_index_out[i] = 0;
190                        r_index_in[i]  = 0;
191                        r_fsm_in[i]    = INFSM_IDLE;
192                        r_fifo_in[i].init();
193                        r_fifo_out[i].init();
194                }
195            return;
196        }
197
198            // fifos signals default values
199            for(size_t i = 0 ; i < 5 ; i++) 
200        {
201                    fifo_in_read[i]        = false;
202                    fifo_in_write[i]       = p_in[i].write.read();
203                    fifo_in_wdata[i].data  = p_in[i].data.read();
204                    fifo_in_wdata[i].eop   = p_in[i].eop.read();
205         
206                    fifo_out_read[i]       = p_out[i].read.read();
207                    fifo_out_write[i]      = false;
208            }
209
210        // loop on the output ports:
211        // compute get_out[j] depending on the output port state
212        // and combining fifo_out[j].wok and r_alloc_out[j]
213        for ( size_t j = 0 ; j < 5 ; j++ )
214        {
215                    if( r_alloc_out[j].read() and (r_fifo_out[j].wok()) ) 
216            {
217                get_out[j] = r_index_out[j].read();
218            }
219            else
220            {                       
221                get_out[j] = 0xFFFFFFFF; 
222            }
223        }
224
225        // loop on the input ports :
226        // The port state is defined by r_fsm_in[i], r_index_in[i]
227        // The req_in[i] computation implements the X-FIRST algorithm.
228        // Both put_in[i] and req_in[i] depend on the input port state.
229
230        for ( size_t i = 0 ; i < 5 ; i++ )
231        {
232            switch ( r_fsm_in[i].read() )
233            {
234                case INFSM_IDLE:    // no output port allocated
235                {
236                    put_in[i] = false;
237                    if ( r_fifo_in[i].rok() ) // packet available in input fifo
238                    {
239                        req_in[i]       = route( r_fifo_in[i].read().data );
240                        r_index_in[i]   = req_in[i];
241                        r_fsm_in[i]     = INFSM_REQ;
242                    }
243                    else
244                    {
245                        req_in[i] = 0xFFFFFFFF;  // no request
246                    }
247                    break;
248                }
249                case INFSM_REQ:   // waiting output port allocation
250                {
251                    flit_in[i] = r_fifo_in[i].read();
252                    put_in[i]  = r_fifo_in[i].rok();
253                    req_in[i]  = r_index_in[i];
254                    if ( get_out[r_index_in[i].read()] == i ) // first flit transfered
255                    {
256                        if ( r_fifo_in[i].read().eop ) r_fsm_in[i] = INFSM_IDLE;
257                        else                           r_fsm_in[i] = INFSM_ALLOC;
258                    }
259                    break;
260                }
261                case INFSM_ALLOC:  // output port allocated
262                {
263                    flit_in[i] = r_fifo_in[i].read();
264                    put_in[i] = r_fifo_in[i].rok();
265                    req_in[i] = 0xFFFFFFFF;                 // no request
266                    if ( r_fifo_in[i].read().eop and r_fifo_in[i].rok() and
267                         (get_out[r_index_in[i].read()] == i) ) // last flit transfered
268                    {
269                        r_fsm_in[i] = INFSM_IDLE;
270                    }
271                    break;
272                }
273            } // end switch
274        } // end for input ports
275                                   
276        // loop on the output ports :
277            // The r_alloc_out[j] and r_index_out[j] computation
278        // implements the round-robin allocation policy.
279        // These two registers implement a 10 states FSM.
280            for( size_t j = 0 ; j < 5 ; j++ ) 
281        {
282                    if( not r_alloc_out[j].read() )  // not allocated: possible new allocation
283            {
284                        for( size_t k = r_index_out[j].read() + 1 ; 
285                     k < (r_index_out[j] + 6) ; k++) 
286                { 
287                                size_t i = k % 5;
288
289                                if( req_in[i] == j ) 
290                    {
291                                    r_alloc_out[j] = true;
292                                    r_index_out[j] = i;
293                        break;
294                    }
295                        } // end loop on input ports
296                    } 
297            else                            // allocated: possible desallocation
298            {
299                        if ( flit_in[r_index_out[j]].eop and
300                     r_fifo_out[j].wok() and
301                     put_in[r_index_out[j]] ) 
302                {
303                                r_alloc_out[j] = false;
304                }
305                    }
306                } // end loop on output ports
307
308        // loop on input ports :
309            // fifo_in_read[i] computation (get data from fifo_in[i]
310        // (computed here because it depends on get_out[])
311            for( size_t i = 0 ; i < 5 ; i++ ) 
312        {
313                    if ( r_fsm_in[i].read() != INFSM_IDLE ) 
314            {
315                fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
316            }
317            else
318            {
319                fifo_in_read[i] = false;
320            }
321            }  // end loop on input ports
322
323        // loop on the output ports :
324        // The fifo_out_write[j] and fifo_out_wdata[j] computation
325        // implements the output port mux.
326            for( size_t j = 0 ; j < 5 ; j++ ) 
327        {
328                    if( r_alloc_out[j] )  // output port allocated
329            {
330                        fifo_out_write[j] = put_in[r_index_out[j]];
331                        fifo_out_wdata[j]  = flit_in[r_index_out[j]];
332            }
333        }  // end loop on the output ports
334
335            //  FIFOS update
336            for(size_t i = 0 ; i < 5 ; i++) 
337        {
338                    r_fifo_in[i].update(fifo_in_read[i],
339                                fifo_in_write[i],
340                                fifo_in_wdata[i]);
341                    r_fifo_out[i].update(fifo_out_read[i],
342                                 fifo_out_write[i],
343                                 fifo_out_wdata[i]);
344            }
345    } // end transition
346
347    ////////////////////////////////
348    //      genMoore
349    ////////////////////////////////
350    tmpl(void)::genMoore()
351    {
352        for(size_t i = 0 ; i < 5 ; i++) 
353        { 
354            // input ports : READ signals
355                p_in[i].read = r_fifo_in[i].wok();
356     
357            // output ports : DATA & WRITE signals
358                p_out[i].data  = r_fifo_out[i].read().data; 
359                p_out[i].eop   = r_fifo_out[i].read().eop; 
360                p_out[i].write = r_fifo_out[i].rok();
361        }
362    } // end genMoore
363
364}} // end namespace
365
366// Local Variables:
367// tab-width: 4
368// c-basic-offset: 4
369// c-file-offsets:((innamespace . 0)(inline-open . 0))
370// indent-tabs-mode: nil
371// End:
372
373// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.