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

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

reconf: modify the broadcast routing function to support holes in the
mesh.

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