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, 9 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.