source: branches/fault_tolerance/module/network_component/dspin_router/caba/source/src/dspin_router.cpp @ 647

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

Creating branch for fault tolerance support on the TSAR architecture.

Some components from the SOCLIB repository which will be modified has
been copied in this branch.

File size: 22.1 KB
Line 
1/* -*- c++ -*-
2  *
3  * File : dspin_router.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    // Implementation Note :
31    // The xfirst_route(), broadcast_route() and is_broadcast() functions
32    // defined below are used to decode the DSPIN first flit format:
33    // - In case of a non-broadcast packet :
34    //  |   X     |   Y     |---------------------------------------|BC |
35    //  | x_width | y_width |  flit_width - (x_width + y_width + 2) | 0 |
36    //
37    //  - In case of a broacast
38    //  |  XMIN   |  XMAX   |  YMIN   |  YMAX   |-------------------|BC |
39    //  |   5     |   5     |   5     |   5     | flit_width - 22   | 1 |
40    ///////////////////////////////////////////////////////////////////////////
41
42#include "../include/dspin_router.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 DspinRouter<flit_width>
50
51    ////////////////////////////////////////////////
52    //              constructor
53    ////////////////////////////////////////////////
54    tmpl(/**/)::DspinRouter( sc_module_name name, 
55                             const size_t   x,
56                             const size_t   y,
57                             const size_t   x_width,
58                             const size_t   y_width,
59                             const size_t   in_fifo_depth,
60                             const size_t   out_fifo_depth,
61                             const bool     broadcast_supported )
62        : soclib::caba::BaseModule(name),
63
64      p_clk( "p_clk" ),
65      p_resetn( "p_resetn" ),
66      p_in( alloc_elems<DspinInput<flit_width> >("p_in", 5) ),
67      p_out( alloc_elems<DspinOutput<flit_width> >("p_out", 5) ),
68
69          r_alloc_out( alloc_elems<sc_signal<bool> >("r_alloc_out", 5)),
70          r_index_out( soclib::common::alloc_elems<sc_signal<size_t> >("r_index_out", 5)),
71          r_fsm_in( alloc_elems<sc_signal<int> >("r_fsm_in", 5)),
72          r_index_in( alloc_elems<sc_signal<size_t> >("r_index_in", 5)),
73
74      m_local_x( x ),
75      m_local_y( y ),
76      m_x_width( x_width ),
77      m_x_shift( flit_width - x_width ),
78      m_x_mask( (0x1 << x_width) - 1 ),
79      m_y_width( y_width ),
80      m_y_shift( flit_width - x_width - y_width ),
81      m_y_mask( (0x1 << y_width) - 1 ),
82      m_broadcast_supported( broadcast_supported )
83    {
84        std::cout << "  - Building DspinRouter : " << name << std::endl;
85
86            SC_METHOD (transition);
87            dont_initialize();
88            sensitive << p_clk.pos();
89
90            SC_METHOD (genMoore);
91            dont_initialize();
92            sensitive  << p_clk.neg();
93
94            r_fifo_in  = (GenericFifo<internal_flit_t>*)
95                         malloc(sizeof(GenericFifo<internal_flit_t>) * 5);
96
97            r_fifo_out = (GenericFifo<internal_flit_t>*)
98                         malloc(sizeof(GenericFifo<internal_flit_t>) * 5);
99
100        r_buf_in   = (internal_flit_t*)
101                     malloc(sizeof(internal_flit_t) * 5);
102
103            for( size_t i = 0 ; i < 5 ; i++ )
104        {
105                    std::ostringstream stri;
106                    stri << "r_in_fifo_" << i;
107                new(&r_fifo_in[i]) 
108                GenericFifo<internal_flit_t >(stri.str(), in_fifo_depth);
109
110                    std::ostringstream stro;
111                    stro << "r_out_fifo_" << i;
112                new(&r_fifo_out[i]) 
113                GenericFifo<internal_flit_t >(stro.str(), out_fifo_depth);
114            }
115    } //  end constructor
116
117    ///////////////////////////////////////////////////
118    tmpl(int)::xfirst_route( sc_uint<flit_width> data )
119    {
120        size_t xdest = (size_t)(data >> m_x_shift) & m_x_mask;
121        size_t ydest = (size_t)(data >> m_y_shift) & m_y_mask;
122        return (xdest < m_local_x ? REQ_WEST : 
123               (xdest > m_local_x ? REQ_EAST : 
124               (ydest < m_local_y ? REQ_SOUTH : 
125               (ydest > m_local_y ? REQ_NORTH : REQ_LOCAL))));
126    }
127
128    //////////////////////////////////////////////////////////////////////////
129    tmpl(int)::broadcast_route(int step, int source, sc_uint<flit_width> data)
130    {
131        int    sel  = REQ_NOP;
132        size_t xmin = (data >> (flit_width - 5 )) & 0x1F;
133        size_t xmax = (data >> (flit_width - 10)) & 0x1F;
134        size_t ymin = (data >> (flit_width - 15)) & 0x1F;
135        size_t ymax = (data >> (flit_width - 20)) & 0x1F;
136
137        switch(source) {
138        case REQ_LOCAL :
139            if      ( step == 1 )       sel = REQ_NORTH;
140            else if ( step == 2 )       sel = REQ_SOUTH;
141            else if ( step == 3 )       sel = REQ_EAST;
142            else if ( step == 4 )       sel = REQ_WEST;
143        break;
144        case REQ_NORTH :
145            if      ( step == 1 )       sel = REQ_SOUTH;
146            else if ( step == 2 )       sel = REQ_LOCAL;
147            else if ( step == 3 )       sel = REQ_NOP;
148            else if ( step == 4 )       sel = REQ_NOP;
149        break;
150        case REQ_SOUTH :
151            if      ( step == 1 )       sel = REQ_NORTH;
152            else if ( step == 2 )       sel = REQ_LOCAL;
153            else if ( step == 3 )       sel = REQ_NOP;
154            else if ( step == 4 )       sel = REQ_NOP;
155        break;
156        case REQ_EAST :
157            if      ( step == 1 )       sel = REQ_WEST;
158            else if ( step == 2 )       sel = REQ_NORTH;
159            else if ( step == 3 )       sel = REQ_SOUTH;
160            else if ( step == 4 )       sel = REQ_LOCAL;
161        break;
162        case REQ_WEST :
163            if      ( step == 1 )       sel = REQ_EAST;
164            else if ( step == 2 )       sel = REQ_NORTH;
165            else if ( step == 3 )       sel = REQ_SOUTH;
166            else if ( step == 4 )       sel = REQ_LOCAL;
167        break;
168        }
169        if      ( (sel == REQ_NORTH) && !(m_local_y < ymax) )   sel = REQ_NOP;
170        else if ( (sel == REQ_SOUTH) && !(m_local_y > ymin) )   sel = REQ_NOP;
171        else if ( (sel == REQ_EAST ) && !(m_local_x < xmax) )   sel = REQ_NOP;
172        else if ( (sel == REQ_WEST ) && !(m_local_x > xmin) )   sel = REQ_NOP;
173
174        return sel;
175    }
176
177    /////////////////////////////////////////////////////////
178    tmpl(inline bool)::is_broadcast(sc_uint<flit_width> data)
179    {
180        return ( (data & 0x1) != 0);
181    }
182
183    /////////////////////////
184    tmpl(void)::print_trace()
185    {
186        const char* port_name[] = 
187        {
188            "N",
189            "S",
190            "E",
191            "W",
192            "L"
193        };
194
195        const char* infsm_str[] =
196        {
197            "IDLE",
198            "REQ",
199            "ALLOC",
200            "REQ_FIRST",
201            "ALLOC_FIRST",
202            "REQ_SECOND",
203            "ALLOC_SECOND",
204            "REQ_THIRD",
205            "ALLOC_THIRD",
206            "REQ_FOURTH",
207            "ALLOC_FOURTH"
208        };
209
210        std::cout << "DSPIN_ROUTER " << name();
211
212        for( size_t i = 0 ; i < 5 ; i++)  // loop on input ports
213        {
214            std::cout << " / infsm[" << port_name[i] << "] "
215                      << infsm_str[r_fsm_in[i].read()];
216        }
217
218        for ( size_t out=0 ; out<5 ; out++)  // loop on output ports
219        {
220            if ( r_alloc_out[out].read() )
221            {
222                int in = r_index_out[out];
223                std::cout << " / " << port_name[in] << " -> " << port_name[out] ;
224            }   
225        }
226        std::cout << std::endl;
227    }
228
229    ////////////////////////
230    tmpl(void)::transition()
231    {
232        // Long wires connecting input and output ports
233        size_t              req_in[5];         // input ports  -> output ports
234        size_t              get_out[5];        // output ports -> input ports
235        bool                put_in[5];         // input ports  -> output ports
236        internal_flit_t     data_in[5];        // input ports  -> output ports
237
238        // control signals for the input fifos
239            bool                fifo_in_write[5];
240            bool                fifo_in_read[5];       
241            internal_flit_t     fifo_in_wdata[5];
242
243        // control signals for the output fifos
244            bool                fifo_out_write[5];
245            bool                fifo_out_read[5];
246            internal_flit_t     fifo_out_wdata[5];
247
248            // Reset
249            if ( p_resetn == false ) 
250        {
251                for(size_t i = 0 ; i < 5 ; i++) 
252            {
253                        r_alloc_out[i] = false;
254                        r_index_out[i] = 0;
255                        r_index_in[i]  = 0;
256                        r_fsm_in[i]    = INFSM_IDLE;
257                        r_fifo_in[i].init();
258                        r_fifo_out[i].init();
259                }
260            return;
261        }
262
263            // fifos signals default values
264            for(size_t i = 0 ; i < 5 ; i++) 
265        {
266                    fifo_in_read[i]        = false;
267                    fifo_in_write[i]       = p_in[i].write.read();
268                    fifo_in_wdata[i].data  = p_in[i].data.read();
269                    fifo_in_wdata[i].eop   = p_in[i].eop.read();
270         
271                    fifo_out_read[i]       = p_out[i].read.read();
272                    fifo_out_write[i]      = false;
273            }
274
275        // loop on the output ports:
276        // compute get_out[j] depending on the output port state
277        // and combining fifo_out[j].wok and r_alloc_out[j]
278        for ( size_t j = 0 ; j < 5 ; j++ )
279        {
280                    if( r_alloc_out[j].read() and (r_fifo_out[j].wok()) ) 
281            {
282                get_out[j] = r_index_out[j].read();
283            }
284            else
285            {                       
286                get_out[j] = 0xFFFFFFFF; 
287            }
288        }
289
290        // loop on the input ports :
291        // The port state is defined by r_fsm_in[i], r_index_in[i] & r_buf_in[i]
292        // The req_in[i] computation implements the X-FIRST algorithm.
293        // data_in[i], put_in[i] and req_in[i] depend on the input port state.
294        // The fifo_in_read[i] is computed further...
295
296        for ( size_t i = 0 ; i < 5 ; i++ )
297        {
298            switch ( r_fsm_in[i].read() )
299            {
300                case INFSM_IDLE:    // no output port allocated
301                {
302                    put_in[i] = false;
303                    if ( r_fifo_in[i].rok() ) // packet available in input fifo
304                    {
305                        if ( is_broadcast( r_fifo_in[i].read().data ) and
306                             m_broadcast_supported )          // broadcast
307                        { 
308                            fifo_in_read[i] = true;
309                            req_in[i]       = broadcast_route(1, i, r_fifo_in[i].read().data);
310                            r_buf_in[i]     = r_fifo_in[i].read();
311                            r_index_in[i]   = req_in[i];
312                            if( req_in[i] == REQ_NOP ) r_fsm_in[i] = INFSM_REQ_SECOND;
313                            else                       r_fsm_in[i] = INFSM_REQ_FIRST;
314                        }
315                        else                                  // unicast
316                        {
317                            req_in[i]       = xfirst_route(r_fifo_in[i].read().data);
318                            r_index_in[i]   = req_in[i];
319                            r_fsm_in[i]     = INFSM_REQ;
320                        }
321                    }
322                    else
323                    {
324                        req_in[i] = REQ_NOP;
325                    }
326                    break;
327                }
328                case INFSM_REQ:   // not a broadcast / waiting output port allocation
329                {
330                    data_in[i]      = r_fifo_in[i].read();
331                    put_in[i]       = r_fifo_in[i].rok();
332                    req_in[i]       = r_index_in[i];
333                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
334                    if ( get_out[r_index_in[i].read()] == i ) // first flit transfered
335                    {
336                        if ( r_fifo_in[i].read().eop ) r_fsm_in[i] = INFSM_IDLE;
337                        else                           r_fsm_in[i] = INFSM_ALLOC;
338                    }
339                    break;
340                }
341                case INFSM_ALLOC:   // not a broadcast / output port allocated
342                {
343                    data_in[i]      = r_fifo_in[i].read();
344                    put_in[i]       = r_fifo_in[i].rok();
345                    req_in[i]       = REQ_NOP;                 // no request
346                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
347                    if ( r_fifo_in[i].read().eop and
348                         r_fifo_in[i].rok() and
349                         (get_out[r_index_in[i].read()] == i) ) // last flit transfered
350                    {
351                        r_fsm_in[i] = INFSM_IDLE;
352                    }
353                    break;
354                }
355                case INFSM_REQ_FIRST: // broacast / waiting first output port allocation
356                {
357                    data_in[i]    = r_buf_in[i];
358                    put_in[i]     = true;
359                    req_in[i]     = broadcast_route(1, i, r_buf_in[i].data);
360                    r_index_in[i] = req_in[i];
361                    if ( req_in[i] == REQ_NOP )   // no transfer for this step
362                    {
363                        r_fsm_in[i] = INFSM_REQ_SECOND;
364                    }
365                    else
366                    {
367                        if( get_out[req_in[i]] == i )  // header flit transfered
368                        {
369                            r_fsm_in[i] = INFSM_ALLOC_FIRST;
370                        }
371                    }
372                    break;
373                }
374                case INFSM_ALLOC_FIRST:  // broadcast / first output port allocated
375                {
376                    data_in[i] = r_fifo_in[i].read();
377                    put_in[i]  = r_fifo_in[i].rok();
378                    req_in[i]  = REQ_NOP;
379                    if( (get_out[r_index_in[i].read()] == i) 
380                         and r_fifo_in[i].rok() )                 // data flit transfered
381                    {
382                        if ( not r_fifo_in[i].read().eop )
383                        {
384                            std::cout << "ERROR in DSPIN_ROUTER " << name()
385                                      << " : broadcast packet must be 2 flits" << std::endl;
386                        }
387                        r_fsm_in[i] = INFSM_REQ_SECOND;
388                    }
389                    break;
390                }
391                case INFSM_REQ_SECOND: // broacast / waiting second output port allocation
392                {
393                    data_in[i]    = r_buf_in[i];
394                    put_in[i]     = true;
395                    req_in[i]     = broadcast_route(2, i, r_buf_in[i].data);
396                    r_index_in[i] = req_in[i];
397                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
398                    {
399                        r_fsm_in[i] = INFSM_REQ_THIRD;
400                    }
401                    else
402                    {
403                        if( get_out[req_in[i]] == i ) // header flit transfered
404                        {
405                            r_fsm_in[i] = INFSM_ALLOC_SECOND;
406                        }
407                    }
408                    break;
409                }
410                case INFSM_ALLOC_SECOND:  // broadcast / second output port allocated
411                {
412                    data_in[i] = r_fifo_in[i].read();
413                    put_in[i]  = r_fifo_in[i].rok();
414                    req_in[i]  = REQ_NOP;
415                    if( (get_out[r_index_in[i].read()] == i ) 
416                         and r_fifo_in[i].rok() )               // data flit transfered
417                    {
418                        if ( not r_fifo_in[i].read().eop )
419                        {
420                            std::cout << "ERROR in DSPIN_ROUTER " << name()
421                                      << " : broadcast packet must be 2 flits" << std::endl;
422                        }
423                        r_fsm_in[i] = INFSM_REQ_THIRD;
424                    }
425                    break;
426                }
427                case INFSM_REQ_THIRD: // broacast / waiting third output port allocation
428                {
429                    data_in[i]    = r_buf_in[i];
430                    put_in[i]     = true;
431                    req_in[i]     = broadcast_route(3, i, r_buf_in[i].data);
432                    r_index_in[i] = req_in[i];
433                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
434                    {
435                        r_fsm_in[i] = INFSM_REQ_FOURTH;
436                    }
437                    else
438                    {
439                        if( get_out[req_in[i]] == i ) // header flit transfered
440                        {
441                            r_fsm_in[i] = INFSM_ALLOC_THIRD;
442                        }
443                    }
444                    break;
445                }
446                case INFSM_ALLOC_THIRD:  // broadcast / third output port allocated
447                {
448                    data_in[i] = r_fifo_in[i].read();
449                    put_in[i]  = r_fifo_in[i].rok();
450                    req_in[i]  = REQ_NOP;
451                    if( (get_out[r_index_in[i].read()] == i ) 
452                         and r_fifo_in[i].rok() )               // data flit transfered
453                    {
454                        if ( not r_fifo_in[i].read().eop )
455                        {
456                            std::cout << "ERROR in DSPIN_ROUTER " << name()
457                                      << " : broadcast packet must be 2 flits" << std::endl;
458                        }
459                        r_fsm_in[i] = INFSM_REQ_FOURTH;
460                    }
461                    break;
462                }
463                case INFSM_REQ_FOURTH: // broacast / waiting fourth output port allocation
464                {
465                    data_in[i]    = r_buf_in[i];
466                    put_in[i]     = true;
467                    req_in[i]     = broadcast_route(4, i, r_buf_in[i].data);
468                    r_index_in[i] = req_in[i];
469                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
470                    {
471                        fifo_in_read[i] = true;
472                        r_fsm_in[i]     = INFSM_IDLE;
473                    }
474                    else
475                    {
476                        if( get_out[req_in[i]] == i )  // header flit transfered
477                        {
478                            r_fsm_in[i] = INFSM_ALLOC_FOURTH;
479                        }
480                    }
481                    break;
482                }
483                case INFSM_ALLOC_FOURTH:  // broadcast / fourth output port allocated
484                {
485                    data_in[i] = r_fifo_in[i].read();
486                    put_in[i]  = r_fifo_in[i].rok();
487                    req_in[i]  = REQ_NOP;
488                    if( (get_out[r_index_in[i].read()] == i ) 
489                         and r_fifo_in[i].rok() )                 // data flit transfered
490                    {
491                        if ( not r_fifo_in[i].read().eop )
492                        {
493                            std::cout << "ERROR in DSPIN_ROUTER " << name()
494                                      << " : broadcast packet must be 2 flits" << std::endl;
495                        }
496                        fifo_in_read[i] = true;
497                        r_fsm_in[i]     = INFSM_IDLE;
498                    }
499                    break;
500                }
501            } // end switch
502        } // end for input ports
503                                   
504        // loop on the output ports :
505            // The r_alloc_out[j] and r_index_out[j] computation
506        // implements the round-robin allocation policy.
507        // These two registers implement a 10 states FSM.
508            for( size_t j = 0 ; j < 5 ; j++ ) 
509        {
510                    if( not r_alloc_out[j].read() )  // not allocated: possible new allocation
511            {
512                        for( size_t k = r_index_out[j].read() + 1 ; 
513                     k < (r_index_out[j] + 6) ; k++) 
514                { 
515                                size_t i = k % 5;
516
517                                if( req_in[i] == j ) 
518                    {
519                                    r_alloc_out[j] = true;
520                                    r_index_out[j] = i;
521                        break;
522                    }
523                        } // end loop on input ports
524                    } 
525            else                            // allocated: possible desallocation
526            {
527                        if ( data_in[r_index_out[j]].eop and
528                     r_fifo_out[j].wok() and
529                     put_in[r_index_out[j]] ) 
530                {
531                                r_alloc_out[j] = false;
532                }
533                    }
534                } // end loop on output ports
535
536        // loop on the output ports :
537        // The fifo_out_write[j] and fifo_out_wdata[j] computation
538        // implements the output port mux.
539            for( size_t j = 0 ; j < 5 ; j++ ) 
540        {
541                    if( r_alloc_out[j] )  // output port allocated
542            {
543                        fifo_out_write[j] = put_in[r_index_out[j]];
544                        fifo_out_wdata[j] = data_in[r_index_out[j]];
545            }
546        }  // end loop on the output ports
547
548            //  FIFOS update
549            for(size_t i = 0 ; i < 5 ; i++) 
550        {
551                    r_fifo_in[i].update(fifo_in_read[i],
552                                fifo_in_write[i],
553                                fifo_in_wdata[i]);
554                    r_fifo_out[i].update(fifo_out_read[i],
555                                 fifo_out_write[i],
556                                 fifo_out_wdata[i]);
557            }
558    } // end transition
559
560    ////////////////////////////////
561    //      genMoore
562    ////////////////////////////////
563    tmpl(void)::genMoore()
564    {
565        for(size_t i = 0 ; i < 5 ; i++) 
566        { 
567            // input ports : READ signals
568                p_in[i].read = r_fifo_in[i].wok();
569     
570            // output ports : DATA & WRITE signals
571                p_out[i].data  = r_fifo_out[i].read().data; 
572                p_out[i].eop   = r_fifo_out[i].read().eop; 
573                p_out[i].write = r_fifo_out[i].rok();
574        }
575    } // end genMoore
576
577}} // end namespace
578
579// Local Variables:
580// tab-width: 4
581// c-basic-offset: 4
582// c-file-offsets:((innamespace . 0)(inline-open . 0))
583// indent-tabs-mode: nil
584// End:
585
586// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.