source: branches/reconfiguration/modules/dspin_router/caba/source/src/dspin_router.cpp @ 947

Last change on this file since 947 was 947, checked in by cfuguet, 9 years ago

reconf: add new mode to the dspin_router

  • Modes are:

+ NORMAL : normal X-first routing

+ PATH_RECOVERY : create contour around the blackhole.

If the destination is the blackhole, send
packet to recovery direction, else use normal
X-first routing.

+ SEGMENT_RECOVERY: Like PATH_RECOVERY but do not create contour, only

reroute packets with the blackhole as destination.

  • Remove deprecated unitary test simple_recovery_routing_test
  • Update the simple_segment_recovery unitary test.
File size: 29.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#include "dspin_router_config.h"
44
45namespace soclib { namespace caba {
46
47using namespace soclib::common;
48using namespace soclib::caba;
49
50#define tmpl(x) template<int flit_width> x DspinRouter<flit_width>
51
52    ////////////////////////////////////////////////
53    //              constructor
54    ////////////////////////////////////////////////
55    tmpl(/**/)::DspinRouter( sc_module_name name,
56                             const size_t   x,
57                             const size_t   y,
58                             const size_t   x_width,
59                             const size_t   y_width,
60                             const size_t   in_fifo_depth,
61                             const size_t   out_fifo_depth,
62                             const bool     broadcast_supported)
63    : soclib::caba::BaseModule(name),
64
65      p_clk( "p_clk" ),
66      p_resetn( "p_resetn" ),
67      p_in( alloc_elems<DspinInput<flit_width> >("p_in", 5) ),
68      p_out( alloc_elems<DspinOutput<flit_width> >("p_out", 5) ),
69
70      r_alloc_out( alloc_elems<sc_signal<bool> >("r_alloc_out", 5)),
71      r_index_out( soclib::common::alloc_elems<sc_signal<size_t> >("r_index_out", 5)),
72      r_fsm_in( alloc_elems<sc_signal<int> >("r_fsm_in", 5)),
73      r_index_in( alloc_elems<sc_signal<size_t> >("r_index_in", 5)),
74
75      m_local_x( x ),
76      m_local_y( y ),
77      m_x_width( x_width ),
78      m_x_shift( flit_width - x_width ),
79      m_x_mask( (0x1 << x_width) - 1 ),
80      m_y_width( y_width ),
81      m_y_shift( flit_width - x_width - y_width ),
82      m_y_mask( (0x1 << y_width) - 1 ),
83      m_broadcast_supported( broadcast_supported ),
84      m_disable_mask( 0 )
85    {
86        std::cout << "  - Building DspinRouter : " << name << std::endl;
87
88        SC_METHOD (transition);
89        dont_initialize();
90        sensitive << p_clk.pos();
91
92        SC_METHOD (genMoore);
93        dont_initialize();
94        sensitive  << p_clk.neg();
95
96        r_fifo_in  = (GenericFifo<internal_flit_t>*)
97                     malloc(sizeof(GenericFifo<internal_flit_t>) * 5);
98
99        r_fifo_out = (GenericFifo<internal_flit_t>*)
100                     malloc(sizeof(GenericFifo<internal_flit_t>) * 5);
101
102        r_buf_in   = (internal_flit_t*)
103                     malloc(sizeof(internal_flit_t) * 5);
104
105        for( size_t i = 0 ; i < 5 ; i++ )
106        {
107            std::ostringstream stri;
108            stri << "r_in_fifo_" << i;
109            new(&r_fifo_in[i])
110                GenericFifo<internal_flit_t >(stri.str(), in_fifo_depth);
111
112            std::ostringstream stro;
113            stro << "r_out_fifo_" << i;
114            new(&r_fifo_out[i])
115                GenericFifo<internal_flit_t >(stro.str(), out_fifo_depth);
116        }
117
118        p_recovery_cfg = NULL;
119    } //  end constructor
120
121    ///////////////////////////////////////////////////
122    tmpl(/**/)::~DspinRouter()
123    {
124        if ( p_recovery_cfg != NULL ) delete p_recovery_cfg;
125    }
126
127    ///////////////////////////////////////////////////
128    tmpl(int)::xfirst_route( size_t xdest, size_t ydest )
129    {
130        return (xdest < m_local_x ? REQ_WEST :
131               (xdest > m_local_x ? REQ_EAST :
132               (ydest < m_local_y ? REQ_SOUTH :
133               (ydest > m_local_y ? REQ_NORTH : REQ_LOCAL))));
134    }
135
136    ///////////////////////////////////////////////////
137    tmpl(void)::bind_recovery_port( sc_core::sc_signal<uint32_t> &s )
138    {
139        if (p_recovery_cfg == NULL) {
140            p_recovery_cfg = new sc_core::sc_in<uint32_t> ("p_recovery_cfg");
141        }
142        (*p_recovery_cfg)(s);
143    }
144
145    ///////////////////////////////////////////////////
146    tmpl(bool)::is_destination_blackhole( size_t xdest, size_t ydest, int bhpos )
147    {
148        size_t xhole, yhole;
149        if (bhpos == BH_N) {
150            xhole = m_local_x;
151            yhole = m_local_y - 1;
152        }
153        else if (bhpos == BH_NW) {
154            xhole = m_local_x + 1;
155            yhole = m_local_y - 1;
156        }
157        else if (bhpos == BH_W) {
158            xhole = m_local_x + 1;
159            yhole = m_local_y;
160        }
161        else if (bhpos == BH_SW) {
162            xhole = m_local_x + 1;
163            yhole = m_local_y + 1;
164        }
165        else if (bhpos == BH_S) {
166            xhole = m_local_x;
167            yhole = m_local_y + 1;
168        }
169        else if (bhpos == BH_SE) {
170            xhole = m_local_x - 1;
171            yhole = m_local_y + 1;
172        }
173        else if (bhpos == BH_E) {
174            xhole = m_local_x - 1;
175            yhole = m_local_y;
176        }
177        else if (bhpos == BH_NE) {
178            xhole = m_local_x - 1;
179            yhole = m_local_y - 1;
180        }
181        else {
182            return false;
183        }
184
185        return ((xdest == xhole) && (ydest == yhole));
186    }
187
188    ///////////////////////////////////////////////////
189    tmpl(int)::recovery_route( size_t xdest, size_t ydest )
190    {
191        int bhpos = blackhole_position();
192
193        if ( xdest > m_local_x ) {
194            if ( (bhpos == BH_NE) || (bhpos == BH_E) || (bhpos == BH_SE) ||
195                 (bhpos == BH_S) ) {
196                return REQ_EAST;
197            }
198            else if ( bhpos == BH_N ) {
199                if ( (m_local_y == 1) || (m_local_x == 0) || (ydest >= m_local_y) ||
200                     (xdest > (m_local_x + 1)) ) {
201                    return REQ_EAST;
202                }
203                else {
204                    return REQ_WEST;
205                }
206            }
207            else if ( bhpos == BH_NW ) {
208                if ( (m_local_y == 1) || (ydest >= m_local_y) ||
209                     (xdest > (m_local_x + 2)) ) {
210                    return REQ_EAST;
211                }
212                else {
213                    return REQ_SOUTH;
214                }
215            }
216            else if ( bhpos == BH_W ) {
217                if ( (m_local_y == 0) || (ydest > m_local_y)) {
218                    return REQ_NORTH;
219                }
220                else {
221                    return REQ_SOUTH;
222                }
223            }
224            else if ( bhpos == BH_SW ) {
225                if ( (ydest <= m_local_y) || (xdest > (m_local_x + 1)) ) {
226                    return REQ_EAST;
227                }
228                else {
229                    return REQ_NORTH;
230                }
231            }
232            std::cout << "error: unexpected condition in function "
233                      << __FILE__ << ":" << __func__ << " +" << __LINE__
234                      << std::endl;
235            exit(1);
236        }                    // end if (xdest > m_local_x)
237        else if ( xdest < m_local_x ) {
238            if ( (bhpos == BH_N) || (bhpos == BH_NW) || (bhpos == BH_W) ||
239                 (bhpos == BH_SW) || (bhpos == BH_S) ) {
240                return REQ_WEST;
241            }
242            else if ( bhpos == BH_NE ) {
243                if ( (xdest < (m_local_x - 1)) || (ydest >= m_local_y) ) {
244                    return REQ_WEST;
245                }
246                else {
247                    return REQ_SOUTH;
248                }
249            }
250            else if ( bhpos == BH_SE ) {
251                if ( (m_local_x == 1) && (ydest > (m_local_y + 1)) ) {
252                    return REQ_NORTH;
253                }
254                else {
255                    return REQ_WEST;
256                }
257            }
258            else if ( bhpos == BH_E ) {
259                if ( (m_local_y == 0) ||
260                    ((m_local_x == 1) && (ydest > m_local_y)) ) {
261                    return REQ_NORTH;
262                }
263                else {
264                    return REQ_SOUTH;
265                }
266            }
267            std::cout << "error: unexpected condition in function "
268                      << __FILE__ << ":" << __func__ << " +" << __LINE__
269                      << std::endl;
270            exit(1);
271        }                    // end if (xdest < m_local_x)
272        else if ( ydest > m_local_y ) {
273            if ( bhpos != BH_S ) {
274                return REQ_NORTH;
275            }
276            else if ( m_local_x != 0 ) {
277                return REQ_WEST;
278            }
279            else {
280                return REQ_EAST;
281            }
282        }                    // end if (ydest > m_local_y)
283        else if ( ydest < m_local_y ) {
284            if ( bhpos != BH_N ) {
285                return REQ_SOUTH;
286            }
287            else if ( m_local_x != 0) {
288                return REQ_WEST;
289            }
290            else {
291                return REQ_EAST;
292            }
293        }                    // end if (ydest < m_local_y)
294        return REQ_LOCAL;
295    }
296
297    ///////////////////////////////////////////////////
298    tmpl(int)::route( sc_uint<flit_width> data )
299    {
300        size_t xdest = (size_t)(data >> m_x_shift) & m_x_mask;
301        size_t ydest = (size_t)(data >> m_y_shift) & m_y_mask;
302        if ( p_recovery_cfg != NULL )
303        {
304            if (blackhole_position() != BH_NONE )
305            {
306                // reroute the request if its destination is the blackhole (this
307                // is to implement the segment recovery mechanism)
308                if (is_destination_blackhole(xdest, ydest, blackhole_position()))
309                {
310                    int dir = migration_route();
311
312#if SOCLIB_MODULE_DEBUG
313                    std::cout << "<" << name() << "> migration: "
314                              << "route request to DIR = " << dir << std::endl;
315#endif
316                    return dir;
317                }
318
319                if (is_network_recovery_enable())
320                {
321                    int dir = recovery_route(xdest, ydest);
322
323#if SOCLIB_MODULE_DEBUG
324                    std::cout << "<" << name() << "> network recovery: "
325                              << "route request to DIR = " << dir << std::endl;
326#endif
327                    return dir;
328                }
329            }
330        }
331        return xfirst_route(xdest, ydest);
332    }
333
334    //////////////////////////////////////////////////////////////////////////
335    tmpl(int)::broadcast_route(int step, int source, sc_uint<flit_width> data)
336    {
337        int    sel  = REQ_NOP;
338        size_t xmin = (data >> (flit_width - 5 )) & 0x1F;
339        size_t xmax = (data >> (flit_width - 10)) & 0x1F;
340        size_t ymin = (data >> (flit_width - 15)) & 0x1F;
341        size_t ymax = (data >> (flit_width - 20)) & 0x1F;
342
343        switch(source) {
344        case REQ_LOCAL :
345            if      ( step == 1 )   sel = REQ_NORTH;
346            else if ( step == 2 )   sel = REQ_SOUTH;
347            else if ( step == 3 )   sel = REQ_EAST;
348            else if ( step == 4 )   sel = REQ_WEST;
349        break;
350        case REQ_NORTH :
351            if      ( step == 1 )   sel = REQ_SOUTH;
352            else if ( step == 2 )   sel = REQ_LOCAL;
353            else if ( step == 3 )   sel = REQ_NOP;
354            else if ( step == 4 )   sel = REQ_NOP;
355        break;
356        case REQ_SOUTH :
357            if      ( step == 1 )   sel = REQ_NORTH;
358            else if ( step == 2 )   sel = REQ_LOCAL;
359            else if ( step == 3 )   sel = REQ_NOP;
360            else if ( step == 4 )   sel = REQ_NOP;
361        break;
362        case REQ_EAST :
363            if      ( step == 1 )   sel = REQ_WEST;
364            else if ( step == 2 )   sel = REQ_NORTH;
365            else if ( step == 3 )   sel = REQ_SOUTH;
366            else if ( step == 4 )   sel = REQ_LOCAL;
367        break;
368        case REQ_WEST :
369            if      ( step == 1 )   sel = REQ_EAST;
370            else if ( step == 2 )   sel = REQ_NORTH;
371            else if ( step == 3 )   sel = REQ_SOUTH;
372            else if ( step == 4 )   sel = REQ_LOCAL;
373        break;
374        }
375        if      ( (sel == REQ_NORTH) && !(m_local_y < ymax) )   sel = REQ_NOP;
376        else if ( (sel == REQ_SOUTH) && !(m_local_y > ymin) )   sel = REQ_NOP;
377        else if ( (sel == REQ_EAST ) && !(m_local_x < xmax) )   sel = REQ_NOP;
378        else if ( (sel == REQ_WEST ) && !(m_local_x > xmin) )   sel = REQ_NOP;
379
380        return sel;
381    }
382
383    /////////////////////////////////////////////////////////
384    tmpl(inline bool)::is_broadcast(sc_uint<flit_width> data)
385    {
386        return ( (data & 0x1) != 0);
387    }
388
389    /////////////////////////
390    tmpl(void)::print_trace()
391    {
392        const char* port_name[] =
393        {
394            "N",
395            "S",
396            "E",
397            "W",
398            "L"
399        };
400
401        const char* infsm_str[] =
402        {
403            "IDLE",
404            "REQ",
405            "ALLOC",
406            "REQ_FIRST",
407            "ALLOC_FIRST",
408            "REQ_SECOND",
409            "ALLOC_SECOND",
410            "REQ_THIRD",
411            "ALLOC_THIRD",
412            "REQ_FOURTH",
413            "ALLOC_FOURTH"
414        };
415
416        std::cout << "DSPIN_ROUTER " << name();
417
418        for( size_t i = 0 ; i < 5 ; i++)  // loop on input ports
419        {
420            std::cout << " / infsm[" << port_name[i] << "] "
421                      << infsm_str[r_fsm_in[i].read()];
422        }
423
424        for ( size_t out=0 ; out<5 ; out++)  // loop on output ports
425        {
426            if ( r_alloc_out[out].read() )
427            {
428                int in = r_index_out[out];
429                std::cout << " / " << port_name[in] << " -> " << port_name[out] ;
430            }
431        }
432        std::cout << std::endl;
433    }
434
435    ////////////////////////
436    tmpl(void)::transition()
437    {
438        // Long wires connecting input and output ports
439        size_t              req_in[5];         // input ports  -> output ports
440        size_t              get_out[5];        // output ports -> input ports
441        bool                put_in[5];         // input ports  -> output ports
442        internal_flit_t     data_in[5];        // input ports  -> output ports
443
444        // control signals for the input fifos
445        bool                fifo_in_write[5];
446        bool                fifo_in_read[5];
447        internal_flit_t     fifo_in_wdata[5];
448
449        // control signals for the output fifos
450        bool                fifo_out_write[5];
451        bool                fifo_out_read[5];
452        internal_flit_t     fifo_out_wdata[5];
453
454        // Reset
455        if ( p_resetn == false )
456        {
457            for(size_t i = 0 ; i < 5 ; i++)
458            {
459                r_alloc_out[i] = false;
460                r_index_out[i] = 0;
461                r_index_in[i]  = 0;
462                r_fsm_in[i]    = INFSM_IDLE;
463                r_fifo_in[i].init();
464                r_fifo_out[i].init();
465            }
466            return;
467        }
468
469        // fifos signals default values
470        for(size_t i = 0 ; i < 5 ; i++)
471        {
472            fifo_in_read[i]        = false;
473
474            // do not write into the FIFO of disabled interfaces
475            fifo_in_write[i]       = p_in[i].write.read() &&
476                                     ((m_disable_mask & (1 << i)) == 0);
477
478            fifo_in_wdata[i].data  = p_in[i].data.read();
479            fifo_in_wdata[i].eop   = p_in[i].eop.read();
480
481            fifo_out_read[i]       = p_out[i].read.read();
482            fifo_out_write[i]      = false;
483        }
484
485        // loop on the output ports:
486        // compute get_out[j] depending on the output port state
487        // and combining fifo_out[j].wok and r_alloc_out[j]
488        for ( size_t j = 0 ; j < 5 ; j++ )
489        {
490            if( r_alloc_out[j].read() and (r_fifo_out[j].wok()) )
491            {
492                get_out[j] = r_index_out[j].read();
493            }
494            else
495            {
496                get_out[j] = 0xFFFFFFFF;
497            }
498        }
499
500        // loop on the input ports :
501        // The port state is defined by r_fsm_in[i], r_index_in[i] & r_buf_in[i]
502        // The req_in[i] computation implements the X-FIRST algorithm.
503        // data_in[i], put_in[i] and req_in[i] depend on the input port state.
504        // The fifo_in_read[i] is computed further...
505
506        for ( size_t i = 0 ; i < 5 ; i++ )
507        {
508            switch ( r_fsm_in[i].read() )
509            {
510                case INFSM_IDLE:    // no output port allocated
511                {
512                    put_in[i] = false;
513
514                    if ( r_fifo_in[i].rok() ) // packet available in input fifo
515                    {
516                        if ( is_broadcast( r_fifo_in[i].read().data ) and
517                             m_broadcast_supported )          // broadcast
518                        {
519                            fifo_in_read[i] = true;
520                            req_in[i]       = broadcast_route(1, i, r_fifo_in[i].read().data);
521                            r_buf_in[i]     = r_fifo_in[i].read();
522                            r_index_in[i]   = req_in[i];
523                            if( req_in[i] == REQ_NOP ) r_fsm_in[i] = INFSM_REQ_SECOND;
524                            else                       r_fsm_in[i] = INFSM_REQ_FIRST;
525                        }
526                        else                                  // unicast
527                        {
528                            req_in[i]       = route(r_fifo_in[i].read().data);
529                            r_index_in[i]   = req_in[i];
530                            r_fsm_in[i]     = INFSM_REQ;
531                        }
532                    }
533                    else
534                    {
535                        req_in[i] = REQ_NOP;
536                    }
537                    break;
538                }
539                case INFSM_REQ:   // not a broadcast / waiting output port allocation
540                {
541                    data_in[i]      = r_fifo_in[i].read();
542                    put_in[i]       = r_fifo_in[i].rok();
543                    req_in[i]       = r_index_in[i];
544                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
545                    if ( get_out[r_index_in[i].read()] == i ) // first flit transfered
546                    {
547                        if ( r_fifo_in[i].read().eop ) r_fsm_in[i] = INFSM_IDLE;
548                        else                           r_fsm_in[i] = INFSM_ALLOC;
549                    }
550                    break;
551                }
552                case INFSM_ALLOC:   // not a broadcast / output port allocated
553                {
554                    data_in[i]      = r_fifo_in[i].read();
555                    put_in[i]       = r_fifo_in[i].rok();
556                    req_in[i]       = REQ_NOP;                 // no request
557                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
558                    if ( r_fifo_in[i].read().eop and
559                         r_fifo_in[i].rok() and
560                         (get_out[r_index_in[i].read()] == i) ) // last flit transfered
561                    {
562                        r_fsm_in[i] = INFSM_IDLE;
563                    }
564                    break;
565                }
566                case INFSM_REQ_FIRST: // broacast / waiting first output port allocation
567                {
568                    data_in[i]    = r_buf_in[i];
569                    put_in[i]     = true;
570                    req_in[i]     = broadcast_route(1, i, r_buf_in[i].data);
571                    r_index_in[i] = req_in[i];
572                    if ( req_in[i] == REQ_NOP )   // no transfer for this step
573                    {
574                        r_fsm_in[i] = INFSM_REQ_SECOND;
575                    }
576                    else
577                    {
578                        if( get_out[req_in[i]] == i )  // header flit transfered
579                        {
580                            r_fsm_in[i] = INFSM_ALLOC_FIRST;
581                        }
582                    }
583                    break;
584                }
585                case INFSM_ALLOC_FIRST:  // broadcast / first output port allocated
586                {
587                    data_in[i] = r_fifo_in[i].read();
588                    put_in[i]  = r_fifo_in[i].rok();
589                    req_in[i]  = REQ_NOP;
590                    if( (get_out[r_index_in[i].read()] == i)
591                         and r_fifo_in[i].rok() )                 // data flit transfered
592                    {
593                        if ( not r_fifo_in[i].read().eop )
594                        {
595                            std::cout << "ERROR in DSPIN_ROUTER " << name()
596                                      << " : broadcast packet must be 2 flits" << std::endl;
597                        }
598                        r_fsm_in[i] = INFSM_REQ_SECOND;
599                    }
600                    break;
601                }
602                case INFSM_REQ_SECOND: // broacast / waiting second output port allocation
603                {
604                    data_in[i]    = r_buf_in[i];
605                    put_in[i]     = true;
606                    req_in[i]     = broadcast_route(2, i, r_buf_in[i].data);
607                    r_index_in[i] = req_in[i];
608                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
609                    {
610                        r_fsm_in[i] = INFSM_REQ_THIRD;
611                    }
612                    else
613                    {
614                        if( get_out[req_in[i]] == i ) // header flit transfered
615                        {
616                            r_fsm_in[i] = INFSM_ALLOC_SECOND;
617                        }
618                    }
619                    break;
620                }
621                case INFSM_ALLOC_SECOND:  // broadcast / second output port allocated
622                {
623                    data_in[i] = r_fifo_in[i].read();
624                    put_in[i]  = r_fifo_in[i].rok();
625                    req_in[i]  = REQ_NOP;
626                    if( (get_out[r_index_in[i].read()] == i )
627                         and r_fifo_in[i].rok() )               // data flit transfered
628                    {
629                        if ( not r_fifo_in[i].read().eop )
630                        {
631                            std::cout << "ERROR in DSPIN_ROUTER " << name()
632                                      << " : broadcast packet must be 2 flits" << std::endl;
633                        }
634                        r_fsm_in[i] = INFSM_REQ_THIRD;
635                    }
636                    break;
637                }
638                case INFSM_REQ_THIRD: // broacast / waiting third output port allocation
639                {
640                    data_in[i]    = r_buf_in[i];
641                    put_in[i]     = true;
642                    req_in[i]     = broadcast_route(3, i, r_buf_in[i].data);
643                    r_index_in[i] = req_in[i];
644                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
645                    {
646                        r_fsm_in[i] = INFSM_REQ_FOURTH;
647                    }
648                    else
649                    {
650                        if( get_out[req_in[i]] == i ) // header flit transfered
651                        {
652                            r_fsm_in[i] = INFSM_ALLOC_THIRD;
653                        }
654                    }
655                    break;
656                }
657                case INFSM_ALLOC_THIRD:  // broadcast / third output port allocated
658                {
659                    data_in[i] = r_fifo_in[i].read();
660                    put_in[i]  = r_fifo_in[i].rok();
661                    req_in[i]  = REQ_NOP;
662                    if( (get_out[r_index_in[i].read()] == i )
663                         and r_fifo_in[i].rok() )               // data flit transfered
664                    {
665                        if ( not r_fifo_in[i].read().eop )
666                        {
667                            std::cout << "ERROR in DSPIN_ROUTER " << name()
668                                      << " : broadcast packet must be 2 flits" << std::endl;
669                        }
670                        r_fsm_in[i] = INFSM_REQ_FOURTH;
671                    }
672                    break;
673                }
674                case INFSM_REQ_FOURTH: // broacast / waiting fourth output port allocation
675                {
676                    data_in[i]    = r_buf_in[i];
677                    put_in[i]     = true;
678                    req_in[i]     = broadcast_route(4, i, r_buf_in[i].data);
679                    r_index_in[i] = req_in[i];
680                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
681                    {
682                        fifo_in_read[i] = true;
683                        r_fsm_in[i]     = INFSM_IDLE;
684                    }
685                    else
686                    {
687                        if( get_out[req_in[i]] == i )  // header flit transfered
688                        {
689                            r_fsm_in[i] = INFSM_ALLOC_FOURTH;
690                        }
691                    }
692                    break;
693                }
694                case INFSM_ALLOC_FOURTH:  // broadcast / fourth output port allocated
695                {
696                    data_in[i] = r_fifo_in[i].read();
697                    put_in[i]  = r_fifo_in[i].rok();
698                    req_in[i]  = REQ_NOP;
699                    if( (get_out[r_index_in[i].read()] == i )
700                         and r_fifo_in[i].rok() )                 // data flit transfered
701                    {
702                        if ( not r_fifo_in[i].read().eop )
703                        {
704                            std::cout << "ERROR in DSPIN_ROUTER " << name()
705                                      << " : broadcast packet must be 2 flits" << std::endl;
706                        }
707                        fifo_in_read[i] = true;
708                        r_fsm_in[i]     = INFSM_IDLE;
709                    }
710                    break;
711                }
712            } // end switch
713        } // end for input ports
714
715        // loop on the output ports :
716        // The r_alloc_out[j] and r_index_out[j] computation
717        // implements the round-robin allocation policy.
718        // These two registers implement a 10 states FSM.
719        for( size_t j = 0 ; j < 5 ; j++ )
720        {
721            if( not r_alloc_out[j].read() )  // not allocated: possible new allocation
722            {
723                for( size_t k = r_index_out[j].read() + 1 ;
724                     k < (r_index_out[j] + 6) ; k++)
725                {
726                    size_t i = k % 5;
727
728                    if( req_in[i] == j )
729                    {
730                        r_alloc_out[j] = true;
731                        r_index_out[j] = i;
732                        break;
733                    }
734                } // end loop on input ports
735            }
736            else                            // allocated: possible desallocation
737            {
738                if ( data_in[r_index_out[j]].eop and
739                     r_fifo_out[j].wok() and
740                     put_in[r_index_out[j]] )
741                {
742                    r_alloc_out[j] = false;
743                }
744            }
745        } // end loop on output ports
746
747        // loop on the output ports :
748        // The fifo_out_write[j] and fifo_out_wdata[j] computation
749        // implements the output port mux.
750        for( size_t j = 0 ; j < 5 ; j++ )
751        {
752            if( r_alloc_out[j] )  // output port allocated
753            {
754                fifo_out_write[j] = put_in[r_index_out[j]] &&
755                                    ((m_disable_mask & (1 << j)) == 0);
756                fifo_out_wdata[j] = data_in[r_index_out[j]];
757            }
758        }  // end loop on the output ports
759
760        //  FIFOS update
761        for(size_t i = 0 ; i < 5 ; i++)
762        {
763            r_fifo_in[i].update(fifo_in_read[i],
764                                fifo_in_write[i],
765                                fifo_in_wdata[i]);
766            r_fifo_out[i].update(fifo_out_read[i],
767                                 fifo_out_write[i],
768                                 fifo_out_wdata[i]);
769        }
770    } // end transition
771
772    ////////////////////////////////
773    //      genMoore
774    ////////////////////////////////
775    tmpl(void)::genMoore()
776    {
777        for(size_t i = 0 ; i < 5 ; i++)
778        {
779            // input ports : READ signals
780            p_in[i].read = r_fifo_in[i].wok();
781
782            // output ports : DATA & WRITE signals
783            p_out[i].data  = r_fifo_out[i].read().data;
784            p_out[i].eop   = r_fifo_out[i].read().eop;
785            p_out[i].write = r_fifo_out[i].rok();
786        }
787    } // end genMoore
788
789}} // end namespace
790
791// Local Variables:
792// tab-width: 4
793// c-basic-offset: 4
794// c-file-offsets:((innamespace . 0)(inline-open . 0))
795// indent-tabs-mode: nil
796// End:
797
798// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.