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

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

reconf: improving dspin_router transition function.

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