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

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

reconf: introducing the segment recovery mechanism in the dspin_router

  • The p_recovery_cfg port, connected through a signal to a config register in the XICU, is formatted in two fields: the 4 LSb contain the blackhole relative position and the 4 bits after contain the recovery direction.
  • A request with the blackhole cluster as destination is rerouted through the defined recovery direction.
  • Remove the reconfiguration parameter of the constructor. The p_recovery_cfg port is instantiated when the bind_recovery_port is called. This port is also connected during this function to the signal that is passed as an argument.
File size: 28.6 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>;
141        }
142        (*p_recovery_cfg)(s);
143    }
144
145    ///////////////////////////////////////////////////
146    tmpl(bool)::need_reroute( 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 = p_recovery_cfg->read() & 0xF;
192
193        // reroute the request if its destination is the blackhole (this is to
194        // implement the segment recovery mechanism)
195        if (need_reroute(xdest, ydest, bhpos)) {
196            int recovery_direction = (p_recovery_cfg->read() >> 4) & 0xF;
197            return recovery_direction;
198        }
199
200        if ( xdest > m_local_x ) {
201            if ( (bhpos == BH_NE) || (bhpos == BH_E) || (bhpos == BH_SE) ||
202                 (bhpos == BH_S) ) {
203                return REQ_EAST;
204            }
205            else if ( bhpos == BH_N ) {
206                if ( (m_local_y == 1) || (m_local_x == 0) || (ydest >= m_local_y) ||
207                     (xdest > (m_local_x + 1)) ) {
208                    return REQ_EAST;
209                }
210                else {
211                    return REQ_WEST;
212                }
213            }
214            else if ( bhpos == BH_NW ) {
215                if ( (m_local_y == 1) || (ydest >= m_local_y) ||
216                     (xdest > (m_local_x + 2)) ) {
217                    return REQ_EAST;
218                }
219                else {
220                    return REQ_SOUTH;
221                }
222            }
223            else if ( bhpos == BH_W ) {
224                if ( (m_local_y == 0) || (ydest > m_local_y)) {
225                    return REQ_NORTH;
226                }
227                else {
228                    return REQ_SOUTH;
229                }
230            }
231            else if ( bhpos == BH_SW ) {
232                if ( (ydest <= m_local_y) || (xdest > (m_local_x + 1)) ) {
233                    return REQ_EAST;
234                }
235                else {
236                    return REQ_NORTH;
237                }
238            }
239            std::cout << "error: unexpected condition in function "
240                      << __FILE__ << ":" << __func__ << " +" << __LINE__
241                      << std::endl;
242            exit(1);
243        }                    // end if (xdest > m_local_x)
244        else if ( xdest < m_local_x ) {
245            if ( (bhpos == BH_N) || (bhpos == BH_NW) || (bhpos == BH_W) ||
246                 (bhpos == BH_SW) || (bhpos == BH_S) ) {
247                return REQ_WEST;
248            }
249            else if ( bhpos == BH_NE ) {
250                if ( (xdest < (m_local_x - 1)) || (ydest >= m_local_y) ) {
251                    return REQ_WEST;
252                }
253                else {
254                    return REQ_SOUTH;
255                }
256            }
257            else if ( bhpos == BH_SE ) {
258                if ( (m_local_x == 1) && (ydest > (m_local_y + 1)) ) {
259                    return REQ_NORTH;
260                }
261                else {
262                    return REQ_WEST;
263                }
264            }
265            else if ( bhpos == BH_E ) {
266                if ( (m_local_y == 0) ||
267                    ((m_local_x == 1) && (ydest > m_local_y)) ) {
268                    return REQ_NORTH;
269                }
270                else {
271                    return REQ_SOUTH;
272                }
273            }
274            std::cout << "error: unexpected condition in function "
275                      << __FILE__ << ":" << __func__ << " +" << __LINE__
276                      << std::endl;
277            exit(1);
278        }                    // end if (xdest < m_local_x)
279        else if ( ydest > m_local_y ) {
280            if ( bhpos != BH_S ) {
281                return REQ_NORTH;
282            }
283            else if ( m_local_x != 0 ) {
284                return REQ_WEST;
285            }
286            else {
287                return REQ_EAST;
288            }
289        }                    // end if (ydest > m_local_y)
290        else if ( ydest < m_local_y ) {
291            if ( bhpos != BH_N ) {
292                return REQ_SOUTH;
293            }
294            else if ( m_local_x != 0) {
295                return REQ_WEST;
296            }
297            else {
298                return REQ_EAST;
299            }
300        }                    // end if (ydest < m_local_y)
301        return REQ_LOCAL;
302    }
303
304    ///////////////////////////////////////////////////
305    tmpl(int)::route( sc_uint<flit_width> data )
306    {
307        size_t xdest = (size_t)(data >> m_x_shift) & m_x_mask;
308        size_t ydest = (size_t)(data >> m_y_shift) & m_y_mask;
309        if ( p_recovery_cfg != NULL )
310        {
311            if ( (p_recovery_cfg->read() & 0xF) != BH_NONE )
312            {
313                return recovery_route(xdest, ydest);
314            }
315        }
316        return xfirst_route(xdest, ydest);
317    }
318
319    //////////////////////////////////////////////////////////////////////////
320    tmpl(int)::broadcast_route(int step, int source, sc_uint<flit_width> data)
321    {
322        int    sel  = REQ_NOP;
323        size_t xmin = (data >> (flit_width - 5 )) & 0x1F;
324        size_t xmax = (data >> (flit_width - 10)) & 0x1F;
325        size_t ymin = (data >> (flit_width - 15)) & 0x1F;
326        size_t ymax = (data >> (flit_width - 20)) & 0x1F;
327
328        switch(source) {
329        case REQ_LOCAL :
330            if      ( step == 1 )   sel = REQ_NORTH;
331            else if ( step == 2 )   sel = REQ_SOUTH;
332            else if ( step == 3 )   sel = REQ_EAST;
333            else if ( step == 4 )   sel = REQ_WEST;
334        break;
335        case REQ_NORTH :
336            if      ( step == 1 )   sel = REQ_SOUTH;
337            else if ( step == 2 )   sel = REQ_LOCAL;
338            else if ( step == 3 )   sel = REQ_NOP;
339            else if ( step == 4 )   sel = REQ_NOP;
340        break;
341        case REQ_SOUTH :
342            if      ( step == 1 )   sel = REQ_NORTH;
343            else if ( step == 2 )   sel = REQ_LOCAL;
344            else if ( step == 3 )   sel = REQ_NOP;
345            else if ( step == 4 )   sel = REQ_NOP;
346        break;
347        case REQ_EAST :
348            if      ( step == 1 )   sel = REQ_WEST;
349            else if ( step == 2 )   sel = REQ_NORTH;
350            else if ( step == 3 )   sel = REQ_SOUTH;
351            else if ( step == 4 )   sel = REQ_LOCAL;
352        break;
353        case REQ_WEST :
354            if      ( step == 1 )   sel = REQ_EAST;
355            else if ( step == 2 )   sel = REQ_NORTH;
356            else if ( step == 3 )   sel = REQ_SOUTH;
357            else if ( step == 4 )   sel = REQ_LOCAL;
358        break;
359        }
360        if      ( (sel == REQ_NORTH) && !(m_local_y < ymax) )   sel = REQ_NOP;
361        else if ( (sel == REQ_SOUTH) && !(m_local_y > ymin) )   sel = REQ_NOP;
362        else if ( (sel == REQ_EAST ) && !(m_local_x < xmax) )   sel = REQ_NOP;
363        else if ( (sel == REQ_WEST ) && !(m_local_x > xmin) )   sel = REQ_NOP;
364
365        return sel;
366    }
367
368    /////////////////////////////////////////////////////////
369    tmpl(inline bool)::is_broadcast(sc_uint<flit_width> data)
370    {
371        return ( (data & 0x1) != 0);
372    }
373
374    /////////////////////////
375    tmpl(void)::print_trace()
376    {
377        const char* port_name[] =
378        {
379            "N",
380            "S",
381            "E",
382            "W",
383            "L"
384        };
385
386        const char* infsm_str[] =
387        {
388            "IDLE",
389            "REQ",
390            "ALLOC",
391            "REQ_FIRST",
392            "ALLOC_FIRST",
393            "REQ_SECOND",
394            "ALLOC_SECOND",
395            "REQ_THIRD",
396            "ALLOC_THIRD",
397            "REQ_FOURTH",
398            "ALLOC_FOURTH"
399        };
400
401        std::cout << "DSPIN_ROUTER " << name();
402
403        for( size_t i = 0 ; i < 5 ; i++)  // loop on input ports
404        {
405            std::cout << " / infsm[" << port_name[i] << "] "
406                      << infsm_str[r_fsm_in[i].read()];
407        }
408
409        for ( size_t out=0 ; out<5 ; out++)  // loop on output ports
410        {
411            if ( r_alloc_out[out].read() )
412            {
413                int in = r_index_out[out];
414                std::cout << " / " << port_name[in] << " -> " << port_name[out] ;
415            }
416        }
417        std::cout << std::endl;
418    }
419
420    ////////////////////////
421    tmpl(void)::transition()
422    {
423        // Long wires connecting input and output ports
424        size_t              req_in[5];         // input ports  -> output ports
425        size_t              get_out[5];        // output ports -> input ports
426        bool                put_in[5];         // input ports  -> output ports
427        internal_flit_t     data_in[5];        // input ports  -> output ports
428
429        // control signals for the input fifos
430        bool                fifo_in_write[5];
431        bool                fifo_in_read[5];
432        internal_flit_t     fifo_in_wdata[5];
433
434        // control signals for the output fifos
435        bool                fifo_out_write[5];
436        bool                fifo_out_read[5];
437        internal_flit_t     fifo_out_wdata[5];
438
439        // Reset
440        if ( p_resetn == false )
441        {
442            for(size_t i = 0 ; i < 5 ; i++)
443            {
444                r_alloc_out[i] = false;
445                r_index_out[i] = 0;
446                r_index_in[i]  = 0;
447                r_fsm_in[i]    = INFSM_IDLE;
448                r_fifo_in[i].init();
449                r_fifo_out[i].init();
450            }
451            return;
452        }
453
454        // fifos signals default values
455        for(size_t i = 0 ; i < 5 ; i++)
456        {
457            fifo_in_read[i]        = false;
458
459            // do not write into the FIFO of disabled interfaces
460            fifo_in_write[i]       = p_in[i].write.read() &&
461                                     ((m_disable_mask & (1 << i)) == 0);
462
463            fifo_in_wdata[i].data  = p_in[i].data.read();
464            fifo_in_wdata[i].eop   = p_in[i].eop.read();
465
466            fifo_out_read[i]       = p_out[i].read.read();
467            fifo_out_write[i]      = false;
468        }
469
470        // loop on the output ports:
471        // compute get_out[j] depending on the output port state
472        // and combining fifo_out[j].wok and r_alloc_out[j]
473        for ( size_t j = 0 ; j < 5 ; j++ )
474        {
475            if( r_alloc_out[j].read() and (r_fifo_out[j].wok()) )
476            {
477                get_out[j] = r_index_out[j].read();
478            }
479            else
480            {
481                get_out[j] = 0xFFFFFFFF;
482            }
483        }
484
485        // loop on the input ports :
486        // The port state is defined by r_fsm_in[i], r_index_in[i] & r_buf_in[i]
487        // The req_in[i] computation implements the X-FIRST algorithm.
488        // data_in[i], put_in[i] and req_in[i] depend on the input port state.
489        // The fifo_in_read[i] is computed further...
490
491        for ( size_t i = 0 ; i < 5 ; i++ )
492        {
493            switch ( r_fsm_in[i].read() )
494            {
495                case INFSM_IDLE:    // no output port allocated
496                {
497                    put_in[i] = false;
498
499                    if ( r_fifo_in[i].rok() ) // packet available in input fifo
500                    {
501                        if ( is_broadcast( r_fifo_in[i].read().data ) and
502                             m_broadcast_supported )          // broadcast
503                        {
504                            fifo_in_read[i] = true;
505                            req_in[i]       = broadcast_route(1, i, r_fifo_in[i].read().data);
506                            r_buf_in[i]     = r_fifo_in[i].read();
507                            r_index_in[i]   = req_in[i];
508                            if( req_in[i] == REQ_NOP ) r_fsm_in[i] = INFSM_REQ_SECOND;
509                            else                       r_fsm_in[i] = INFSM_REQ_FIRST;
510                        }
511                        else                                  // unicast
512                        {
513                            req_in[i]       = route(r_fifo_in[i].read().data);
514                            r_index_in[i]   = req_in[i];
515                            r_fsm_in[i]     = INFSM_REQ;
516                        }
517                    }
518                    else
519                    {
520                        req_in[i] = REQ_NOP;
521                    }
522                    break;
523                }
524                case INFSM_REQ:   // not a broadcast / waiting output port allocation
525                {
526                    data_in[i]      = r_fifo_in[i].read();
527                    put_in[i]       = r_fifo_in[i].rok();
528                    req_in[i]       = r_index_in[i];
529                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
530                    if ( get_out[r_index_in[i].read()] == i ) // first flit transfered
531                    {
532                        if ( r_fifo_in[i].read().eop ) r_fsm_in[i] = INFSM_IDLE;
533                        else                           r_fsm_in[i] = INFSM_ALLOC;
534                    }
535                    break;
536                }
537                case INFSM_ALLOC:   // not a broadcast / output port allocated
538                {
539                    data_in[i]      = r_fifo_in[i].read();
540                    put_in[i]       = r_fifo_in[i].rok();
541                    req_in[i]       = REQ_NOP;                 // no request
542                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
543                    if ( r_fifo_in[i].read().eop and
544                         r_fifo_in[i].rok() and
545                         (get_out[r_index_in[i].read()] == i) ) // last flit transfered
546                    {
547                        r_fsm_in[i] = INFSM_IDLE;
548                    }
549                    break;
550                }
551                case INFSM_REQ_FIRST: // broacast / waiting first output port allocation
552                {
553                    data_in[i]    = r_buf_in[i];
554                    put_in[i]     = true;
555                    req_in[i]     = broadcast_route(1, i, r_buf_in[i].data);
556                    r_index_in[i] = req_in[i];
557                    if ( req_in[i] == REQ_NOP )   // no transfer for this step
558                    {
559                        r_fsm_in[i] = INFSM_REQ_SECOND;
560                    }
561                    else
562                    {
563                        if( get_out[req_in[i]] == i )  // header flit transfered
564                        {
565                            r_fsm_in[i] = INFSM_ALLOC_FIRST;
566                        }
567                    }
568                    break;
569                }
570                case INFSM_ALLOC_FIRST:  // broadcast / first output port allocated
571                {
572                    data_in[i] = r_fifo_in[i].read();
573                    put_in[i]  = r_fifo_in[i].rok();
574                    req_in[i]  = REQ_NOP;
575                    if( (get_out[r_index_in[i].read()] == i)
576                         and r_fifo_in[i].rok() )                 // data flit transfered
577                    {
578                        if ( not r_fifo_in[i].read().eop )
579                        {
580                            std::cout << "ERROR in DSPIN_ROUTER " << name()
581                                      << " : broadcast packet must be 2 flits" << std::endl;
582                        }
583                        r_fsm_in[i] = INFSM_REQ_SECOND;
584                    }
585                    break;
586                }
587                case INFSM_REQ_SECOND: // broacast / waiting second output port allocation
588                {
589                    data_in[i]    = r_buf_in[i];
590                    put_in[i]     = true;
591                    req_in[i]     = broadcast_route(2, i, r_buf_in[i].data);
592                    r_index_in[i] = req_in[i];
593                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
594                    {
595                        r_fsm_in[i] = INFSM_REQ_THIRD;
596                    }
597                    else
598                    {
599                        if( get_out[req_in[i]] == i ) // header flit transfered
600                        {
601                            r_fsm_in[i] = INFSM_ALLOC_SECOND;
602                        }
603                    }
604                    break;
605                }
606                case INFSM_ALLOC_SECOND:  // broadcast / second output port allocated
607                {
608                    data_in[i] = r_fifo_in[i].read();
609                    put_in[i]  = r_fifo_in[i].rok();
610                    req_in[i]  = REQ_NOP;
611                    if( (get_out[r_index_in[i].read()] == i )
612                         and r_fifo_in[i].rok() )               // data flit transfered
613                    {
614                        if ( not r_fifo_in[i].read().eop )
615                        {
616                            std::cout << "ERROR in DSPIN_ROUTER " << name()
617                                      << " : broadcast packet must be 2 flits" << std::endl;
618                        }
619                        r_fsm_in[i] = INFSM_REQ_THIRD;
620                    }
621                    break;
622                }
623                case INFSM_REQ_THIRD: // broacast / waiting third output port allocation
624                {
625                    data_in[i]    = r_buf_in[i];
626                    put_in[i]     = true;
627                    req_in[i]     = broadcast_route(3, i, r_buf_in[i].data);
628                    r_index_in[i] = req_in[i];
629                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
630                    {
631                        r_fsm_in[i] = INFSM_REQ_FOURTH;
632                    }
633                    else
634                    {
635                        if( get_out[req_in[i]] == i ) // header flit transfered
636                        {
637                            r_fsm_in[i] = INFSM_ALLOC_THIRD;
638                        }
639                    }
640                    break;
641                }
642                case INFSM_ALLOC_THIRD:  // broadcast / third output port allocated
643                {
644                    data_in[i] = r_fifo_in[i].read();
645                    put_in[i]  = r_fifo_in[i].rok();
646                    req_in[i]  = REQ_NOP;
647                    if( (get_out[r_index_in[i].read()] == i )
648                         and r_fifo_in[i].rok() )               // data flit transfered
649                    {
650                        if ( not r_fifo_in[i].read().eop )
651                        {
652                            std::cout << "ERROR in DSPIN_ROUTER " << name()
653                                      << " : broadcast packet must be 2 flits" << std::endl;
654                        }
655                        r_fsm_in[i] = INFSM_REQ_FOURTH;
656                    }
657                    break;
658                }
659                case INFSM_REQ_FOURTH: // broacast / waiting fourth output port allocation
660                {
661                    data_in[i]    = r_buf_in[i];
662                    put_in[i]     = true;
663                    req_in[i]     = broadcast_route(4, i, r_buf_in[i].data);
664                    r_index_in[i] = req_in[i];
665                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
666                    {
667                        fifo_in_read[i] = true;
668                        r_fsm_in[i]     = INFSM_IDLE;
669                    }
670                    else
671                    {
672                        if( get_out[req_in[i]] == i )  // header flit transfered
673                        {
674                            r_fsm_in[i] = INFSM_ALLOC_FOURTH;
675                        }
676                    }
677                    break;
678                }
679                case INFSM_ALLOC_FOURTH:  // broadcast / fourth output port allocated
680                {
681                    data_in[i] = r_fifo_in[i].read();
682                    put_in[i]  = r_fifo_in[i].rok();
683                    req_in[i]  = REQ_NOP;
684                    if( (get_out[r_index_in[i].read()] == i )
685                         and r_fifo_in[i].rok() )                 // data flit transfered
686                    {
687                        if ( not r_fifo_in[i].read().eop )
688                        {
689                            std::cout << "ERROR in DSPIN_ROUTER " << name()
690                                      << " : broadcast packet must be 2 flits" << std::endl;
691                        }
692                        fifo_in_read[i] = true;
693                        r_fsm_in[i]     = INFSM_IDLE;
694                    }
695                    break;
696                }
697            } // end switch
698        } // end for input ports
699
700        // loop on the output ports :
701        // The r_alloc_out[j] and r_index_out[j] computation
702        // implements the round-robin allocation policy.
703        // These two registers implement a 10 states FSM.
704        for( size_t j = 0 ; j < 5 ; j++ )
705        {
706            if( not r_alloc_out[j].read() )  // not allocated: possible new allocation
707            {
708                for( size_t k = r_index_out[j].read() + 1 ;
709                     k < (r_index_out[j] + 6) ; k++)
710                {
711                    size_t i = k % 5;
712
713                    if( req_in[i] == j )
714                    {
715                        r_alloc_out[j] = true;
716                        r_index_out[j] = i;
717                        break;
718                    }
719                } // end loop on input ports
720            }
721            else                            // allocated: possible desallocation
722            {
723                if ( data_in[r_index_out[j]].eop and
724                     r_fifo_out[j].wok() and
725                     put_in[r_index_out[j]] )
726                {
727                    r_alloc_out[j] = false;
728                }
729            }
730        } // end loop on output ports
731
732        // loop on the output ports :
733        // The fifo_out_write[j] and fifo_out_wdata[j] computation
734        // implements the output port mux.
735        for( size_t j = 0 ; j < 5 ; j++ )
736        {
737            if( r_alloc_out[j] )  // output port allocated
738            {
739                fifo_out_write[j] = put_in[r_index_out[j]] &&
740                                    ((m_disable_mask & (1 << j)) == 0);
741                fifo_out_wdata[j] = data_in[r_index_out[j]];
742            }
743        }  // end loop on the output ports
744
745        //  FIFOS update
746        for(size_t i = 0 ; i < 5 ; i++)
747        {
748            r_fifo_in[i].update(fifo_in_read[i],
749                                fifo_in_write[i],
750                                fifo_in_wdata[i]);
751            r_fifo_out[i].update(fifo_out_read[i],
752                                 fifo_out_write[i],
753                                 fifo_out_wdata[i]);
754        }
755    } // end transition
756
757    ////////////////////////////////
758    //      genMoore
759    ////////////////////////////////
760    tmpl(void)::genMoore()
761    {
762        for(size_t i = 0 ; i < 5 ; i++)
763        {
764            // input ports : READ signals
765            p_in[i].read = r_fifo_in[i].wok();
766
767            // output ports : DATA & WRITE signals
768            p_out[i].data  = r_fifo_out[i].read().data;
769            p_out[i].eop   = r_fifo_out[i].read().eop;
770            p_out[i].write = r_fifo_out[i].rok();
771        }
772    } // end genMoore
773
774}} // end namespace
775
776// Local Variables:
777// tab-width: 4
778// c-basic-offset: 4
779// c-file-offsets:((innamespace . 0)(inline-open . 0))
780// indent-tabs-mode: nil
781// End:
782
783// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.