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

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

reconf: dspin_router

  • improve the code readability of the dspin_router model.
  • update the unitary tests of the dspin_router to support the local gateway hardware barrier, and the memory cache scratchpad mode.
File size: 32.4 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        int bhpos = NORMAL;
324        bool recovery = false;
325        if (is_reconfigurable()) {
326            bhpos    = blackhole_position();
327            recovery = is_recovery_routing_enabled();
328        }
329
330        const bool is_n  = recovery and (bhpos == N_OF_X);
331        const bool is_s  = recovery and (bhpos == S_OF_X);
332        const bool is_w  = recovery and (bhpos == W_OF_X);
333        const bool is_e  = recovery and (bhpos == E_OF_X);
334        const bool is_nw = recovery and (bhpos == NW_OF_X);
335        const bool is_ne = recovery and (bhpos == NE_OF_X);
336        const bool is_sw = recovery and (bhpos == SW_OF_X);
337        const bool is_se = recovery and (bhpos == SE_OF_X);
338
339        const bool special = ((data & 0x2) != 0) and recovery;
340
341        int sel = REQ_NOP;
342        switch(source) {
343        case REQ_LOCAL :
344            if      ( step == 1 ) sel = REQ_NORTH;
345            else if ( step == 2 ) sel = REQ_SOUTH;
346            else if ( step == 3 ) {
347                if ( is_n && (lx != 0) && (ly != 1) )
348                    sel = REQ_NOP;
349                else
350                    sel = REQ_EAST;
351            }
352            else if ( step == 4 ) {
353                if ( is_ne && (lx != 1) && (ly != 1) )
354                    sel = REQ_NOP;
355                else
356                    sel = REQ_WEST;
357            }
358        break;
359        case REQ_NORTH :
360            if      ( step == 1 ) sel = REQ_SOUTH;
361            else if ( step == 2 ) sel = REQ_LOCAL;
362            else if ( step == 3 ) {
363                if ( is_sw )
364                    sel = REQ_EAST;
365                else
366                    sel = REQ_NOP;
367            }
368            else if ( step == 4 ) {
369                if ( is_se && (!special || (lx == 1)))
370                    sel = REQ_WEST;
371                else
372                    sel = REQ_NOP;
373            }
374        break;
375        case REQ_SOUTH :
376            if      ( step == 1 ) sel = REQ_NORTH;
377            else if ( step == 2 ) sel = REQ_LOCAL;
378            else if ( step == 3 ) {
379                if ( is_nw )
380                    sel = REQ_EAST;
381                else if ( is_ne && ((lx == 1) || (ly == 1)) )
382                    sel = REQ_WEST;
383                else
384                    sel = REQ_NOP;
385            }
386            else if ( step == 4 ) sel = REQ_NOP;
387        break;
388        case REQ_EAST :
389            if ( step == 1 ) {
390                if ( is_ne && (lx != 1) && (ly != 1) )
391                    sel = REQ_NOP;
392                else
393                    sel = REQ_WEST;
394            }
395            else if ( step == 2 ) sel = REQ_NORTH;
396            else if ( step == 3 ) sel = REQ_SOUTH;
397            else if ( step == 4 ) sel = REQ_LOCAL;
398        break;
399        case REQ_WEST :
400            if ( step == 1 ) {
401                if ( is_n && (ly != 1) )
402                    sel = REQ_NOP;
403                else if ( is_s && special )
404                    sel = REQ_NOP;
405                else
406                    sel = REQ_EAST;
407            }
408            else if ( step == 2 ) sel = REQ_NORTH;
409            else if ( step == 3 ) sel = REQ_SOUTH;
410            else if ( step == 4 ) sel = REQ_LOCAL;
411        break;
412        }
413
414        // inhibit requests to the blackhole or beyond the mesh boundaries.
415        if      ( (sel == REQ_NORTH) && (!(ly < ymax) || is_s)) sel = REQ_NOP;
416        else if ( (sel == REQ_SOUTH) && (!(ly > ymin) || is_n)) sel = REQ_NOP;
417        else if ( (sel == REQ_EAST ) && (!(lx < xmax) || is_w)) sel = REQ_NOP;
418        else if ( (sel == REQ_WEST ) && (!(lx > xmin) || is_e)) sel = REQ_NOP;
419
420        return sel;
421    }
422
423    /////////////////////////////////////////////////////////
424    tmpl(bool)::is_broadcast(sc_uint<flit_width> data)
425    {
426        return ( (data & 0x1) != 0);
427    }
428
429    /////////////////////////////////////////////////////////
430    tmpl(typename DspinRouter<flit_width>::internal_flit_t)::
431    compute_broadcast_header(int source)
432    {
433        const int bhpos = blackhole_position();
434
435        const int is_nw = (bhpos == NW_OF_X);
436        const int is_ne = (bhpos == NE_OF_X);
437
438        internal_flit_t header;
439        header.eop = false;
440        header.data = r_fifo_in[source].read().data;
441
442        const int SPECIAL = 0x2;
443        switch (source) {
444            case REQ_NORTH:
445                if ( is_nw || is_ne ) header.data |= SPECIAL;
446                break;
447
448            /* Make sure that broadcast transactions do not enter the DSPIN
449             * network with the special bit set. This can arrive if an initiator
450             * or a local interconnect uses the broadcast header reserved bits
451             * internally */
452            case REQ_LOCAL:
453                header.data &= ~SPECIAL;
454                break;
455        }
456        return header;
457    }
458
459    /////////////////////////
460    tmpl(void)::print_trace()
461    {
462        const char* port_name[] =
463        {
464            "N",
465            "S",
466            "E",
467            "W",
468            "L"
469        };
470
471        const char* infsm_str[] =
472        {
473            "IDLE",
474            "REQ",
475            "ALLOC",
476            "REQ_FIRST",
477            "ALLOC_FIRST",
478            "REQ_SECOND",
479            "ALLOC_SECOND",
480            "REQ_THIRD",
481            "ALLOC_THIRD",
482            "REQ_FOURTH",
483            "ALLOC_FOURTH"
484        };
485
486        const char* bh_str[] =
487        {
488            "N_OF_X",
489            "NE_OF_X",
490            "E_OF_X",
491            "SE_OF_X",
492            "S_OF_X",
493            "SW_OF_X",
494            "W_OF_X",
495            "NW_OF_X"
496        };
497
498        std::cout << "DSPIN_ROUTER " << name();
499
500        if ( is_reconfigurable() ) {
501            std::cout << " / bh = " << bh_str[blackhole_position()];
502            if (is_recovery_routing_enabled())
503                std::cout << " / recovery_routing ";
504            if (is_reallocation_enabled())
505                std::cout << " / reallocation dir = "
506                          << port_name[reallocation_route()];
507        }
508
509
510        for( size_t i = 0 ; i < 5 ; i++)  // loop on input ports
511        {
512            std::cout << " / infsm[" << port_name[i] << "] "
513                      << infsm_str[r_fsm_in[i].read()];
514        }
515
516        for ( size_t out=0 ; out<5 ; out++)  // loop on output ports
517        {
518            if ( r_alloc_out[out].read() )
519            {
520                int in = r_index_out[out];
521                std::cout << " / " << port_name[in] << " -> " << port_name[out] ;
522            }
523        }
524        std::cout << std::endl;
525    }
526
527    ////////////////////////
528    tmpl(void)::transition()
529    {
530        // Long wires connecting input and output ports
531        size_t              req_in[5];         // input ports  -> output ports
532        size_t              get_out[5];        // output ports -> input ports
533        bool                put_in[5];         // input ports  -> output ports
534        internal_flit_t     data_in[5];        // input ports  -> output ports
535
536        // control signals for the input fifos
537        bool                fifo_in_write[5];
538        bool                fifo_in_read[5];
539        internal_flit_t     fifo_in_wdata[5];
540
541        // control signals for the output fifos
542        bool                fifo_out_write[5];
543        bool                fifo_out_read[5];
544        internal_flit_t     fifo_out_wdata[5];
545
546        // Reset
547        if ( p_resetn == false )
548        {
549            for(size_t i = 0 ; i < 5 ; i++)
550            {
551                r_alloc_out[i] = false;
552                r_index_out[i] = 0;
553                r_index_in[i]  = 0;
554                r_fsm_in[i]    = INFSM_IDLE;
555                r_fifo_in[i].init();
556                r_fifo_out[i].init();
557            }
558            return;
559        }
560
561        // fifos signals default values
562        for(size_t i = 0 ; i < 5 ; i++)
563        {
564            fifo_in_read[i]        = false;
565
566            // do not write into the FIFO of disabled interfaces
567            fifo_in_write[i]       = p_in[i].write.read() &&
568                (((m_disable_mask >> i) & 1) == 0);
569
570            fifo_in_wdata[i].data  = p_in[i].data.read();
571            fifo_in_wdata[i].eop   = p_in[i].eop.read();
572
573            fifo_out_read[i]       = p_out[i].read.read() ||
574                (((m_disable_mask >> i) & 1) == 1);
575            fifo_out_write[i]      = false;
576        }
577
578        // loop on the output ports:
579        // compute get_out[j] depending on the output port state
580        // and combining fifo_out[j].wok and r_alloc_out[j]
581        for ( size_t j = 0 ; j < 5 ; j++ )
582        {
583            if( r_alloc_out[j].read() and (r_fifo_out[j].wok()) )
584            {
585                get_out[j] = r_index_out[j].read();
586            }
587            else
588            {
589                get_out[j] = 0xFFFFFFFF;
590            }
591        }
592
593        // loop on the input ports :
594        // The port state is defined by r_fsm_in[i], r_index_in[i] & r_buf_in[i]
595        // The req_in[i] computation implements the X-FIRST algorithm.
596        // data_in[i], put_in[i] and req_in[i] depend on the input port state.
597        // The fifo_in_read[i] is computed further...
598
599        for ( size_t i = 0 ; i < 5 ; i++ )
600        {
601            switch ( r_fsm_in[i].read() )
602            {
603                case INFSM_IDLE:    // no output port allocated
604                {
605                    put_in[i] = false;
606
607                    if ( r_fifo_in[i].rok() ) // packet available in input fifo
608                    {
609                        if ( is_broadcast( r_fifo_in[i].read().data ) and
610                             m_broadcast_supported )          // broadcast
611                        {
612                            if ( r_fifo_in[i].read().eop )
613                            {
614                                std::cout << "ERROR in DSPIN_ROUTER " << name()
615                                          << " : broadcast packet must be 2 flits"
616                                          << std::endl;
617                                exit(1);
618                            }
619
620                            const internal_flit_t& header = compute_broadcast_header(i);
621
622                            fifo_in_read[i] = true;
623                            req_in[i]       = broadcast_route(1, i, header.data);
624                            r_buf_in[i]     = header;
625                            r_index_in[i]   = req_in[i];
626                            if ( req_in[i] == REQ_NOP ) r_fsm_in[i] = INFSM_REQ_SECOND;
627                            else                        r_fsm_in[i] = INFSM_REQ_FIRST;
628                        }
629                        else                                  // unicast
630                        {
631                            req_in[i]       = route(r_fifo_in[i].read().data);
632                            r_index_in[i]   = req_in[i];
633                            r_fsm_in[i]     = INFSM_REQ;
634                        }
635                    }
636                    else
637                    {
638                        req_in[i] = REQ_NOP;
639                    }
640                    break;
641                }
642                case INFSM_REQ:   // not a broadcast / waiting output port allocation
643                {
644                    data_in[i]      = r_fifo_in[i].read();
645                    put_in[i]       = r_fifo_in[i].rok();
646                    req_in[i]       = r_index_in[i];
647                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
648                    if ( get_out[r_index_in[i].read()] == i ) // first flit transfered
649                    {
650                        if ( r_fifo_in[i].read().eop ) r_fsm_in[i] = INFSM_IDLE;
651                        else                           r_fsm_in[i] = INFSM_ALLOC;
652                    }
653                    break;
654                }
655                case INFSM_ALLOC:   // not a broadcast / output port allocated
656                {
657                    data_in[i]      = r_fifo_in[i].read();
658                    put_in[i]       = r_fifo_in[i].rok();
659                    req_in[i]       = REQ_NOP;                 // no request
660                    fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
661                    if ( r_fifo_in[i].read().eop and
662                         r_fifo_in[i].rok() and
663                         (get_out[r_index_in[i].read()] == i) ) // last flit transfered
664                    {
665                        r_fsm_in[i] = INFSM_IDLE;
666                    }
667                    break;
668                }
669                case INFSM_REQ_FIRST: // broacast / waiting first output port allocation
670                {
671                    data_in[i]    = r_buf_in[i];
672                    put_in[i]     = true;
673                    req_in[i]     = broadcast_route(1, i, r_buf_in[i].data);
674                    r_index_in[i] = req_in[i];
675                    if ( req_in[i] == REQ_NOP )   // no transfer for this step
676                    {
677                        r_fsm_in[i] = INFSM_REQ_SECOND;
678                    }
679                    else
680                    {
681                        if( get_out[req_in[i]] == i )  // header flit transfered
682                        {
683                            r_fsm_in[i] = INFSM_ALLOC_FIRST;
684                        }
685                    }
686                    break;
687                }
688                case INFSM_ALLOC_FIRST:  // broadcast / first output port allocated
689                {
690                    data_in[i] = r_fifo_in[i].read();
691                    put_in[i]  = r_fifo_in[i].rok();
692                    req_in[i]  = REQ_NOP;
693                    if( (get_out[r_index_in[i].read()] == i)
694                         and r_fifo_in[i].rok() )                 // data flit transfered
695                    {
696                        if ( not r_fifo_in[i].read().eop )
697                        {
698                            std::cout << "ERROR in DSPIN_ROUTER " << name()
699                                      << " : broadcast packet must be 2 flits" << std::endl;
700                        }
701                        r_fsm_in[i] = INFSM_REQ_SECOND;
702                    }
703                    break;
704                }
705                case INFSM_REQ_SECOND: // broacast / waiting second output port allocation
706                {
707                    data_in[i]    = r_buf_in[i];
708                    put_in[i]     = true;
709                    req_in[i]     = broadcast_route(2, i, r_buf_in[i].data);
710                    r_index_in[i] = req_in[i];
711                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
712                    {
713                        r_fsm_in[i] = INFSM_REQ_THIRD;
714                    }
715                    else
716                    {
717                        if( get_out[req_in[i]] == i ) // header flit transfered
718                        {
719                            r_fsm_in[i] = INFSM_ALLOC_SECOND;
720                        }
721                    }
722                    break;
723                }
724                case INFSM_ALLOC_SECOND:  // broadcast / second output port allocated
725                {
726                    data_in[i] = r_fifo_in[i].read();
727                    put_in[i]  = r_fifo_in[i].rok();
728                    req_in[i]  = REQ_NOP;
729                    if( (get_out[r_index_in[i].read()] == i )
730                         and r_fifo_in[i].rok() )               // data flit transfered
731                    {
732                        if ( not r_fifo_in[i].read().eop )
733                        {
734                            std::cout << "ERROR in DSPIN_ROUTER " << name()
735                                      << " : broadcast packet must be 2 flits" << std::endl;
736                        }
737                        r_fsm_in[i] = INFSM_REQ_THIRD;
738                    }
739                    break;
740                }
741                case INFSM_REQ_THIRD: // broacast / waiting third output port allocation
742                {
743                    data_in[i]    = r_buf_in[i];
744                    put_in[i]     = true;
745                    req_in[i]     = broadcast_route(3, i, r_buf_in[i].data);
746                    r_index_in[i] = req_in[i];
747                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
748                    {
749                        r_fsm_in[i] = INFSM_REQ_FOURTH;
750                    }
751                    else
752                    {
753                        if( get_out[req_in[i]] == i ) // header flit transfered
754                        {
755                            r_fsm_in[i] = INFSM_ALLOC_THIRD;
756                        }
757                    }
758                    break;
759                }
760                case INFSM_ALLOC_THIRD:  // broadcast / third output port allocated
761                {
762                    data_in[i] = r_fifo_in[i].read();
763                    put_in[i]  = r_fifo_in[i].rok();
764                    req_in[i]  = REQ_NOP;
765                    if( (get_out[r_index_in[i].read()] == i )
766                         and r_fifo_in[i].rok() )               // data flit transfered
767                    {
768                        if ( not r_fifo_in[i].read().eop )
769                        {
770                            std::cout << "ERROR in DSPIN_ROUTER " << name()
771                                      << " : broadcast packet must be 2 flits" << std::endl;
772                        }
773                        r_fsm_in[i] = INFSM_REQ_FOURTH;
774                    }
775                    break;
776                }
777                case INFSM_REQ_FOURTH: // broacast / waiting fourth output port allocation
778                {
779                    data_in[i]    = r_buf_in[i];
780                    put_in[i]     = true;
781                    req_in[i]     = broadcast_route(4, i, r_buf_in[i].data);
782                    r_index_in[i] = req_in[i];
783                    if ( req_in[i] == REQ_NOP )  // no transfer for this step
784                    {
785                        fifo_in_read[i] = true;
786                        r_fsm_in[i]     = INFSM_IDLE;
787                    }
788                    else
789                    {
790                        if( get_out[req_in[i]] == i )  // header flit transfered
791                        {
792                            r_fsm_in[i] = INFSM_ALLOC_FOURTH;
793                        }
794                    }
795                    break;
796                }
797                case INFSM_ALLOC_FOURTH:  // broadcast / fourth output port allocated
798                {
799                    data_in[i] = r_fifo_in[i].read();
800                    put_in[i]  = r_fifo_in[i].rok();
801                    req_in[i]  = REQ_NOP;
802                    if( (get_out[r_index_in[i].read()] == i )
803                         and r_fifo_in[i].rok() )                 // data flit transfered
804                    {
805                        if ( not r_fifo_in[i].read().eop )
806                        {
807                            std::cout << "ERROR in DSPIN_ROUTER " << name()
808                                      << " : broadcast packet must be 2 flits" << std::endl;
809                        }
810                        fifo_in_read[i] = true;
811                        r_fsm_in[i]     = INFSM_IDLE;
812                    }
813                    break;
814                }
815            } // end switch
816        } // end for input ports
817
818        // loop on the output ports :
819        // The r_alloc_out[j] and r_index_out[j] computation
820        // implements the round-robin allocation policy.
821        // These two registers implement a 10 states FSM.
822        for( size_t j = 0 ; j < 5 ; j++ )
823        {
824            if( not r_alloc_out[j].read() )  // not allocated: possible new allocation
825            {
826                for( size_t k = r_index_out[j].read() + 1 ;
827                     k < (r_index_out[j] + 6) ; k++)
828                {
829                    size_t i = k % 5;
830
831                    if( req_in[i] == j )
832                    {
833                        r_alloc_out[j] = true;
834                        r_index_out[j] = i;
835                        break;
836                    }
837                } // end loop on input ports
838            }
839            else                            // allocated: possible desallocation
840            {
841                if ( data_in[r_index_out[j]].eop and
842                     r_fifo_out[j].wok() and
843                     put_in[r_index_out[j]] )
844                {
845                    r_alloc_out[j] = false;
846                }
847            }
848        } // end loop on output ports
849
850        // loop on the output ports :
851        // The fifo_out_write[j] and fifo_out_wdata[j] computation
852        // implements the output port mux.
853        for( size_t j = 0 ; j < 5 ; j++ )
854        {
855            if( r_alloc_out[j] )  // output port allocated
856            {
857                fifo_out_write[j] = put_in[r_index_out[j]];
858                fifo_out_wdata[j] = data_in[r_index_out[j]];
859            }
860        }  // end loop on the output ports
861
862        //  FIFOS update
863        for(size_t i = 0 ; i < 5 ; i++)
864        {
865            r_fifo_in[i].update(fifo_in_read[i],
866                                fifo_in_write[i],
867                                fifo_in_wdata[i]);
868            r_fifo_out[i].update(fifo_out_read[i],
869                                 fifo_out_write[i],
870                                 fifo_out_wdata[i]);
871        }
872    } // end transition
873
874    ////////////////////////////////
875    //      genMoore
876    ////////////////////////////////
877    tmpl(void)::genMoore()
878    {
879        for(size_t i = 0 ; i < 5 ; i++)
880        {
881            // input ports : READ signals
882            p_in[i].read = r_fifo_in[i].wok() ||
883                (((m_disable_mask >> i) & 1) == 1);
884
885            // output ports : DATA & WRITE signals
886            p_out[i].data  = r_fifo_out[i].read().data;
887            p_out[i].eop   = r_fifo_out[i].read().eop;
888            p_out[i].write = r_fifo_out[i].rok() &&
889                (((m_disable_mask >> i) & 1) == 0);
890        }
891    } // end genMoore
892
893}} // end namespace
894
895// Local Variables:
896// tab-width: 4
897// c-basic-offset: 4
898// c-file-offsets:((innamespace . 0)(inline-open . 0))
899// indent-tabs-mode: nil
900// End:
901
902// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.