source: branches/reconfiguration/modules/dspin_local_crossbar/caba/source/src/dspin_local_crossbar.cpp @ 976

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

reconf: introduce the dspin_local_crossbar component in reconfiguration
branch

  • This component will be modified to introduce the support for segment reallocation.
File size: 20.7 KB
Line 
1/* -*- c++ -*-
2  *
3  * File : dspin_local_crossbar.cpp
4  * Copyright (c) UPMC, Lip6
5  * Authors : Alain Greiner
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#include "../include/dspin_local_crossbar.h"
30
31namespace soclib { namespace caba {
32
33using namespace soclib::common;
34using namespace soclib::caba;
35
36#define tmpl(x) template<size_t flit_width> x DspinLocalCrossbar<flit_width>
37
38//////////////////////////////////////////////////////////
39//                  constructor
40//////////////////////////////////////////////////////////
41tmpl(/**/)::DspinLocalCrossbar( sc_module_name       name, 
42                                const MappingTable   &mt,
43                                const size_t         x,
44                                const size_t         y,
45                                const size_t         x_width,
46                                const size_t         y_width,
47                                const size_t         l_width,
48                                const size_t         nb_local_inputs,
49                                const size_t         nb_local_outputs,
50                                const size_t         in_fifo_depth,
51                                const size_t         out_fifo_depth,
52                                const bool           is_cmd,
53                                const bool           use_routing_table,
54                                const bool           broadcast_supported)
55    : BaseModule(name),
56
57      p_clk("p_clk"),
58      p_resetn("p_resetn"),
59      p_global_in("p_global_in"),
60      p_global_out("p_global_out"),
61
62      r_alloc_out(alloc_elems<sc_signal<bool> > ("r_alloc_out", nb_local_outputs + 1)),
63      r_index_out(alloc_elems<sc_signal<size_t> > ("r_index_out", nb_local_outputs + 1)),
64      r_fsm_in(alloc_elems<sc_signal<int> > ("r_fsm_in", nb_local_inputs + 1)),
65      r_index_in(alloc_elems<sc_signal<size_t> > ("r_index_in", nb_local_inputs + 1)),
66
67      m_local_x( x ),
68      m_local_y( y ),
69      m_x_width( x_width ),
70      m_x_shift( flit_width - x_width ),
71      m_x_mask( (0x1 << x_width) - 1 ),
72      m_y_width( y_width ),
73      m_y_shift( flit_width - x_width - y_width ),
74      m_y_mask( (0x1 << y_width) - 1 ),
75      m_l_width( l_width ),
76      m_l_shift( flit_width - x_width - y_width - l_width ),
77      m_l_mask( (0x1 << l_width) - 1 ),
78      m_local_inputs( nb_local_inputs ),
79      m_local_outputs( nb_local_outputs ),
80      m_addr_width( mt.getAddressWidth() ),
81      m_is_cmd( is_cmd ),
82      m_use_routing_table( use_routing_table ),
83      m_broadcast_supported( broadcast_supported )
84    {
85        std::cout << "  - Building DspinLocalCrossbar : " << name << std::endl;
86
87        SC_METHOD (transition);
88        dont_initialize();
89        sensitive << p_clk.pos();
90
91        SC_METHOD (genMoore);
92        dont_initialize();
93        sensitive  << p_clk.neg();
94
95        r_buf_in = new internal_flit_t[nb_local_inputs + 1];
96
97        // build routing table
98        if ( ( m_local_outputs > 0 ) and use_routing_table )
99        {
100            size_t cluster_id = (x << y_width) + y;
101            if ( is_cmd )
102            {
103                m_cmd_rt = mt.getLocalIndexFromAddress( cluster_id );
104            }
105            else
106            {
107                m_rsp_rt = mt.getLocalIndexFromSrcid( cluster_id );
108            }
109        }
110
111        if ( m_local_inputs > 0 )
112        {
113            p_local_in = alloc_elems<DspinInput<flit_width> >(
114                    "p_local_in", nb_local_inputs );
115        }
116        if ( m_local_outputs > 0 )
117        {
118            p_local_out = alloc_elems<DspinOutput<flit_width> >(
119                    "p_local_out", nb_local_outputs );
120        }
121
122        // construct FIFOs
123        r_fifo_in  = (GenericFifo<internal_flit_t>*)
124        malloc(sizeof(GenericFifo<internal_flit_t>) * (m_local_inputs + 1));
125       
126        r_fifo_out = (GenericFifo<internal_flit_t>*)
127        malloc(sizeof(GenericFifo<internal_flit_t>) * (m_local_outputs + 1));
128
129        for (size_t i = 0; i <= m_local_inputs; i++)
130        {
131            std::ostringstream stri;
132            stri << "r_in_fifo_" << i;
133            new(&r_fifo_in[i])  GenericFifo<internal_flit_t>(stri.str(), in_fifo_depth);
134        }
135
136        for (size_t j = 0; j <= m_local_outputs; j++)
137        {
138            std::ostringstream stro;
139            stro << "r_out_fifo_" << j;
140            new(&r_fifo_out[j]) GenericFifo<internal_flit_t>(stro.str(), out_fifo_depth);
141        }
142
143        assert( (flit_width >= x_width + y_width + l_width) and
144        "ERROR in DSPIN_LOCAL_CROSSBAR: flit_width < x_width + y_width + l_width");
145
146    } //  end constructor
147
148
149    tmpl(/**/)::~DspinLocalCrossbar() {
150        for (size_t i = 0; i <= m_local_inputs; i++)
151        {
152            r_fifo_in[i].~GenericFifo<internal_flit_t>();
153        }
154
155        for (size_t j = 0; j <= m_local_outputs; j++)
156        {
157            r_fifo_out[j].~GenericFifo<internal_flit_t>();
158        }
159
160        free(r_fifo_in);
161        free(r_fifo_out);
162
163        if ( m_local_inputs > 0 )
164        {
165            dealloc_elems<DspinInput<flit_width> >(p_local_in, m_local_inputs);
166        }
167        if ( m_local_outputs > 0 )
168        {
169            dealloc_elems<DspinOutput<flit_width> >(p_local_out, m_local_outputs);
170        }
171        dealloc_elems<sc_signal<bool> >(r_alloc_out, m_local_outputs + 1);
172        dealloc_elems<sc_signal<size_t> >(r_index_out, m_local_outputs + 1);
173        dealloc_elems<sc_signal<int> >(r_fsm_in, m_local_inputs + 1);
174        dealloc_elems<sc_signal<size_t> >(r_index_in, m_local_inputs + 1);
175        delete [] r_buf_in;
176    }
177
178
179    ////////////////////////////////////////////////////////////////////////////
180    tmpl(size_t)::route( sc_uint<flit_width> data,     // first flit
181                         size_t              input )   // input port index
182    {
183        size_t   output;   // selected output port
184        size_t   x_dest  = (size_t)(data >> m_x_shift) & m_x_mask;
185        size_t   y_dest  = (size_t)(data >> m_y_shift) & m_y_mask;
186
187        if ( (x_dest == m_local_x) and (y_dest == m_local_y) and
188             (m_local_outputs > 0) )          // local dest
189        {
190            if ( m_use_routing_table )
191            {
192                // address (for CMD) or srcid (for RSP) must be right-aligned
193                if ( m_is_cmd )
194                {
195                    uint64_t address;
196                    if (flit_width >= m_addr_width) 
197                        address = data>>(flit_width - m_addr_width);
198                    else                         
199                        address = data<<(m_addr_width - flit_width);
200                    output = m_cmd_rt[ address ];
201                }
202                else
203                {   
204                    uint32_t srcid = data >> m_l_shift;
205                    output = m_rsp_rt[ srcid ];
206                }
207            }
208            else
209            {
210                output = (size_t)(data >> m_l_shift) & m_l_mask;
211 
212                if ( output >= m_local_outputs )
213                {
214                    std::cout << "ERROR in DSPIN_LOCAL_CROSSBAR: " << name()
215                              << " illegal local destination" << std::endl;
216                    exit(0);
217                }
218            }
219        }
220        else                                                            // global dest
221        {
222            if ( input  == m_local_inputs )
223            {
224                std::cout << "ERROR in DSPIN_LOCAL_CROSSBAR: " << name()
225                          << " illegal global to global request" << std::endl;
226                exit(0);
227            }
228
229            output = m_local_outputs;
230        }
231        return output;
232    }
233
234    /////////////////////////////////////////////////////////
235    tmpl(inline bool)::is_broadcast(sc_uint<flit_width> data)
236    {
237        return ( (data & 0x1) != 0);
238    }
239
240    /////////////////////////
241    tmpl(void)::print_trace()
242    {
243        const char* infsm_str[] = { "IDLE", "REQ", "ALLOC", "REQ_BC", "ALLOC_BC" };
244
245        std::cout << "DSPIN_LOCAL_CROSSBAR " << name() << std::hex; 
246
247        for( size_t i = 0 ; i <= m_local_inputs ; i++)  // loop on input ports
248        {
249            std::cout << " / infsm[" << std::dec << i
250                      << "] = " << infsm_str[r_fsm_in[i].read()];
251        }
252
253        for( size_t out = 0 ; out <= m_local_outputs ; out++)  // loop on output ports
254        {
255            if ( r_alloc_out[out].read() )
256            {
257                size_t in = r_index_out[out];
258                std::cout << " / in[" << in << "] -> out[" << out << "]";
259            }   
260        }
261        std::cout << std::endl;
262    }
263
264    /////////////////////////
265    tmpl(void)::transition()
266    {
267        // Long wires connecting input and output ports
268        size_t              req_in[m_local_inputs+1];   // input ports  -> output ports
269        size_t              get_out[m_local_outputs+1]; // output ports -> input ports
270        bool                put_in[m_local_inputs+1];   // input ports  -> output ports
271        internal_flit_t     data_in[m_local_inputs+1];  // input ports  -> output ports
272
273        // control signals for the input fifos
274        bool                fifo_in_write[m_local_inputs+1];
275        bool                fifo_in_read[m_local_inputs+1];   
276        internal_flit_t     fifo_in_wdata[m_local_inputs+1];
277
278        // control signals for the output fifos
279        bool                fifo_out_write[m_local_outputs+1];
280        bool                fifo_out_read[m_local_outputs+1];
281        internal_flit_t     fifo_out_wdata[m_local_outputs+1];
282
283        // reset
284        if ( p_resetn.read() == false ) 
285        {
286            for(size_t j = 0 ; j <= m_local_outputs ; j++) 
287            {
288                r_alloc_out[j] = false;
289                r_index_out[j] = 0;
290                r_fifo_out[j].init();
291            }
292            for(size_t i = 0 ; i <= m_local_inputs ; i++) 
293            {
294                r_index_in[i]  = 0;
295                r_fsm_in[i]    = INFSM_IDLE;
296                r_fifo_in[i].init();
297            }
298            return;
299        }
300
301        // fifo_in signals default values
302        for(size_t i = 0 ; i < m_local_inputs ; i++) 
303        {
304            fifo_in_read[i]        = false;   
305            fifo_in_write[i]       = p_local_in[i].write.read();
306            fifo_in_wdata[i].data  = p_local_in[i].data.read();
307            fifo_in_wdata[i].eop   = p_local_in[i].eop.read();
308        }
309        fifo_in_read[m_local_inputs]       = false; // default value
310        fifo_in_write[m_local_inputs]      = p_global_in.write.read();
311        fifo_in_wdata[m_local_inputs].data = p_global_in.data.read();
312        fifo_in_wdata[m_local_inputs].eop  = p_global_in.eop.read();
313
314        // fifo_out signals default values
315        for(size_t j = 0 ; j < m_local_outputs ; j++) 
316        {
317            fifo_out_read[j]  = p_local_out[j].read.read();
318            fifo_out_write[j] = false; 
319        }
320        fifo_out_read[m_local_outputs]  = p_global_out.read.read();
321        fifo_out_write[m_local_outputs] = false;     
322
323        // loop on the output ports:
324        // compute get_out[j] depending on the output port state
325        // and combining fifo_out_wok[j] and r_alloc_out[j]
326        for ( size_t j = 0 ; j <= m_local_outputs ; j++ )
327        {
328            if( r_alloc_out[j].read() and (r_fifo_out[j].wok()) ) 
329            {
330                get_out[j] = r_index_out[j].read();
331            }
332            else
333            {                       
334                get_out[j] = 0xFFFFFFFF; 
335            }
336        }
337
338        // loop on the input ports (including global input port,
339        // with the convention index[global] = m_local_inputs)
340        // The port state is defined by r_fsm_in[i], r_index_in[i]
341        // The req_in[i] computation uses the route() function.
342        // Both put_in[i] and req_in[i] depend on the input port state.
343
344        for ( size_t i = 0 ; i <= m_local_inputs ; i++ )
345        {
346            switch ( r_fsm_in[i].read() )
347            {
348                case INFSM_IDLE:    // no output port allocated
349                {
350                    put_in[i] = false;
351                    if ( r_fifo_in[i].rok() ) // packet available in input fifo
352                    {
353                        if ( is_broadcast(r_fifo_in[i].read().data ) and
354                             m_broadcast_supported )   // broadcast required
355                        {
356                            r_buf_in[i] = r_fifo_in[i].read();
357
358                            if ( i == m_local_inputs ) // global input port
359                            {
360                                req_in[i]     = m_local_outputs - 1;
361                            }
362                            else                       // local input port
363                            {
364                                req_in[i]     = m_local_outputs;
365                            }
366                            r_index_in[i] = req_in[i];
367                            r_fsm_in[i]   = INFSM_REQ_BC;
368                        }
369                        else                           // unicast routing
370                        {
371                            req_in[i]     = route( r_fifo_in[i].read().data, i );
372                            r_index_in[i] = req_in[i];
373                            r_fsm_in[i]   = INFSM_REQ;
374                        }
375                    }
376                    else
377                    {
378                        req_in[i]     = 0xFFFFFFFF;  // no request
379                    }
380                    break;
381                }
382                case INFSM_REQ:   // waiting output port allocation
383                {
384                    data_in[i] = r_fifo_in[i].read();
385                    put_in[i]  = r_fifo_in[i].rok();
386                    req_in[i]  = r_index_in[i];
387                    if ( get_out[r_index_in[i].read()] == i ) // first flit transfered
388                    {
389                        if ( r_fifo_in[i].read().eop )  r_fsm_in[i] = INFSM_IDLE;
390                        else                            r_fsm_in[i] = INFSM_ALLOC;
391                    }
392                    break;
393                }
394                case INFSM_ALLOC:  // output port allocated
395                {
396                    data_in[i] = r_fifo_in[i].read();
397                    put_in[i]  = r_fifo_in[i].rok();
398                    req_in[i]  = 0xFFFFFFFF;                // no request
399                    if ( r_fifo_in[i].read().eop and
400                         r_fifo_in[i].rok() and
401                         (get_out[r_index_in[i].read()] == i) )  // last flit transfered
402                    {
403                        r_fsm_in[i] = INFSM_IDLE;
404                    }
405                    break;
406                }
407                case INFSM_REQ_BC:  // waiting output port allocation
408                {
409                    data_in[i] = r_buf_in[i];
410                    put_in[i]  = true;
411                    req_in[i]  = r_index_in[i];
412                    if ( get_out[r_index_in[i].read()] == i ) // first flit transfered
413                    {
414                        r_fsm_in[i] = INFSM_ALLOC_BC;
415                    }
416                    break;
417                }
418                case INFSM_ALLOC_BC:  // output port allocated         
419                {
420                    data_in[i] = r_fifo_in[i].read();
421                    put_in[i]  = r_fifo_in[i].rok();
422                    req_in[i]  = 0xFFFFFFFF;                // no request
423
424                    if ( r_fifo_in[i].rok() and
425                         get_out[r_index_in[i].read()] == i )  // last flit transfered
426                    {
427                        if ( not r_fifo_in[i].read().eop ) 
428                        {
429                            std::cout << "ERROR in DSPIN_LOCAL_CROSSBAR " << name()
430                                      << " : broadcast packets must have 2 flits" << std::endl;
431                        }
432                        if ( r_index_in[i].read() == 0 ) r_fsm_in[i] = INFSM_IDLE;
433                        else                             r_fsm_in[i] = INFSM_REQ_BC;
434                        r_index_in[i] = r_index_in[i].read() - 1;
435                    }
436                    break;
437                }
438            } // end switch
439        } // end for input ports
440                                   
441        // loop on the output ports (including global output port,
442        // with the convention index[global] = m_local_outputs)
443        // The r_alloc_out[j] and r_index_out[j] computation
444        // implements the round-robin allocation policy.
445        // These two registers implement a 2*N states FSM.
446        for( size_t j = 0 ; j <= m_local_outputs ; j++ ) 
447        {
448            if( not r_alloc_out[j].read() )  // not allocated: possible new allocation
449            {
450                for( size_t k = r_index_out[j].read() + 1 ; 
451                     k <= (r_index_out[j].read() + m_local_inputs + 1) ; 
452                     k++ ) 
453                { 
454                    size_t i = k % (m_local_inputs + 1);
455
456                    if( req_in[i] == j ) 
457                    {
458                        r_alloc_out[j] = true;
459                        r_index_out[j] = i;
460                        break;
461                    }
462                } // end loop on input ports
463            } 
464            else                            // allocated: possible desallocation
465            {
466                if ( data_in[r_index_out[j]].eop and
467                     r_fifo_out[j].wok() and
468                     put_in[r_index_out[j]] ) 
469                {
470                    r_alloc_out[j] = false;
471                }
472            }
473        } // end loop on output ports
474
475        // loop on input ports :
476        // fifo_in_read[i] computation
477        // (computed here because it depends on get_out[])
478        for( size_t i = 0 ; i <= m_local_inputs ; i++ ) 
479        {
480            if ( (r_fsm_in[i].read() == INFSM_REQ) or
481                 (r_fsm_in[i].read() == INFSM_ALLOC) or
482                 ((r_fsm_in[i].read() == INFSM_ALLOC_BC) and (r_index_in[i].read() == 0)))
483            {
484                fifo_in_read[i] = (get_out[r_index_in[i].read()] == i);
485            }
486            if ( (r_fsm_in[i].read() == INFSM_IDLE) and
487                 is_broadcast( r_fifo_in[i].read().data ) and
488                 m_broadcast_supported )   
489            {
490                fifo_in_read[i] = true;
491            }
492        }  // end loop on input ports
493
494        // loop on the output ports :
495        // The fifo_out_write[j] and fifo_out_wdata[j] computation
496        // implements the output port mux
497        for( size_t j = 0 ; j <= m_local_outputs ; j++ ) 
498        {
499            if( r_alloc_out[j] )  // output port allocated
500            {
501                fifo_out_write[j] = put_in[r_index_out[j]];
502                fifo_out_wdata[j] = data_in[r_index_out[j]];
503            }
504        }  // end loop on the output ports
505
506        //  input FIFOs update
507        for(size_t i = 0 ; i <= m_local_inputs ; i++) 
508        {
509            r_fifo_in[i].update(fifo_in_read[i],
510                                fifo_in_write[i],
511                                fifo_in_wdata[i]);
512        }
513
514        //  output FIFOs update
515        for(size_t j = 0 ; j <= m_local_outputs ; j++)
516        { 
517            r_fifo_out[j].update(fifo_out_read[j],
518                                 fifo_out_write[j],
519                                 fifo_out_wdata[j]);
520        }
521    } // end transition
522
523    ///////////////////////
524    tmpl(void)::genMoore()
525    {
526        // input ports
527        for(size_t i = 0 ; i < m_local_inputs ; i++) 
528        {
529            p_local_in[i].read = r_fifo_in[i].wok();
530        }
531        p_global_in.read = r_fifo_in[m_local_inputs].wok();
532
533        // output ports
534        for(size_t j = 0 ; j < m_local_outputs ; j++) 
535        {
536            p_local_out[j].write = r_fifo_out[j].rok();
537            p_local_out[j].data  = r_fifo_out[j].read().data;
538            p_local_out[j].eop   = r_fifo_out[j].read().eop;
539        }
540        p_global_out.write = r_fifo_out[m_local_outputs].rok();
541        p_global_out.data  = r_fifo_out[m_local_outputs].read().data;
542        p_global_out.eop   = r_fifo_out[m_local_outputs].read().eop;
543
544    } // end genMoore
545
546}} // end namespace
547
548// Local Variables:
549// tab-width: 4
550// c-basic-offset: 4
551// c-file-offsets:((innamespace . 0)(inline-open . 0))
552// indent-tabs-mode: nil
553// End:
554
555// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.