genericRouterPhy.cc

Go to the documentation of this file.
00001 /*
00002  * =====================================================================================
00003  *
00004  *       Filename:  genericRouterPhy.cc
00005  *
00006  *       Description: Implementing a generic input buffered physical router model
00007  *
00008  *        Version:  1.0
00009  *        Created:  03/11/2010 09:20:54 PM
00010  *       Revision:  none
00011  *       Compiler:  gcc
00012  *
00013  *         Author:  Mitchelle Rasquinha (), mitchelle.rasquinha@gatech.edu
00014  *        Company:  Georgia Institute of Technology
00015  *
00016  * =====================================================================================
00017  */
00018 
00019 #ifndef  _genericRouterPhy_cc_INC
00020 #define  _genericRouterPhy_cc_INC
00021 
00022 #include        "genericRouterPhy.h"
00023 using namespace std;
00024 
00025 GenericRouterPhy::GenericRouterPhy ()
00026 {
00027     name = "Router" ;
00028     ticking = false;
00029 }  /* -----  end of method GenericRouterPhy::GenericRouterPhy  (constructor)  ----- */
00030 
00031 GenericRouterPhy::~GenericRouterPhy()
00032 {
00033 }
00034 
00035 void
00036 GenericRouterPhy::init (uint p, uint v, uint cr, uint bs)
00037 {
00038     ports =p;
00039     vcs =v;
00040     credits =cr;
00041     buffer_size = bs;
00042 
00043     address = myId();
00044 
00045     /*  set_input_ports(ports); */
00046     in_buffers.resize(ports);
00047     decoders.resize(ports);
00048     input_buffer_state.resize(ports*vcs);
00049     swa.resize(ports);
00050     xbar.setup(ports,vcs);
00051     downstream_credits.resize(ports);
00052 
00053     /*Resize per port stats */
00054     stat_packet_out.resize(ports);
00055     stat_flit_out.resize(ports);
00056 
00057     /* All decoders and vc arbiters need to know the node_ip for routing */
00058     for(uint i=0; i<ports; i++)
00059     {
00060         decoders[i].node_ip = node_ip;  // decoders need to know what node this router is located at
00061         decoders[i].address = address;  // this is for debugging
00062         stat_packet_out[i].resize(ports); // stat variables
00063         stat_flit_out[i].resize(ports);
00064     }
00065     swa.node_ip = node_ip;
00066     swa.address = address;
00067 
00068     /*  set_no_virtual_channels(vcs); */
00069     /* This picks the number of virtual channel mentioned in the config file and
00070      * configures the credits, buffers and decoders */
00071     for(uint i=0; i<ports; i++)
00072     {
00073         downstream_credits[i].resize(vcs);
00074         in_buffers[i].resize( vcs, buffer_size );
00075         decoders[i].resize( vcs );
00076     }
00077 
00078     /* Since this is the init phase you can safetly set the
00079      * downstream_credits to the number of credits. You know there are
00080      * no packets injected yet so all buffers are empty. Also the
00081      * input_buffer_state is set to empty.*/
00082     for(uint i=0; i<ports; i++)
00083         for(uint j=0; j<vcs; j++)
00084         {
00085             downstream_credits[i][j] = credits;
00086             input_buffer_state[i*vcs+j].pipe_stage = EMPTY;
00087         }
00088 
00089     /* init the countes */
00090     packets = 0;
00091     flits = 0;
00092     total_packet_latency = 0;
00093 
00094     return ;
00095 }               /* -----  end of function GenericRouterPhy::init  ----- */
00096 
00099 void
00100 GenericRouterPhy::set_no_nodes( uint nodes )
00101 {
00102     for ( uint i=0; i<decoders.size(); i++)
00103     {
00104         decoders[i].grid_xloc.resize(nodes);
00105         decoders[i].grid_yloc.resize(nodes);
00106     }
00107 }
00108 
00109 void
00110 GenericRouterPhy::set_grid_x_location( uint port, uint x_node, uint value)
00111 {
00112     decoders[port].grid_xloc[x_node]= value;
00113 }
00114 
00115 void
00116 GenericRouterPhy::set_grid_y_location( uint port, uint y_node, uint value)
00117 {
00118     decoders[port].grid_yloc[y_node]= value;
00119 }
00120 
00121 /*  End of DOR grid location functions */
00122 
00123 void
00124 GenericRouterPhy::process_event ( IrisEvent* e )
00125 {
00126     switch(e->type)
00127     {
00128         case LINK_ARRIVAL_EVENT:
00129           /* This is the event that comes into the router when a flit
00130            * is delivered to it. It is an external event in the sense
00131            * it gets handed to it from the GenericLink component */
00132             handle_link_arrival_event(e);
00133             break;
00134         case TICK_EVENT:
00135             /* This is an event that updates router state based on
00136              * packets in the router. ( Basically walk the pipe stage
00137              * in backward order */
00138             handle_tick_event(e);
00139             break;
00140         default:
00141             /* There should be no other events that are delivered to
00142              * the component. If this happens then you either set the
00143              * wrong pointer when sending the event. Or check your
00144              * topology */
00145             _DBG("GenericRouterPhy:: Unk event exception %d", e->type);
00146             break;
00147     }
00148     return ;
00149 }               /* -----  end of function GenericRouterPhy::process_event  ----- */
00150 
00157 string
00158 GenericRouterPhy::print_stats()
00159 {
00160     stringstream str;
00161     str << "\n router[" << node_ip << "] packet latency: " << total_packet_latency
00162         << "\n router[" << node_ip << "] flits/packets: " << (flits+0.0)/(packets)
00163         << "\n router[" << node_ip << "] average packet latency: " << (total_packet_latency+0.0)/packets
00164         << "\n router[" << node_ip << "] last_flit_out_cycle: " << last_flit_out_cycle
00165         << " ";
00166     str << "\n router[" << node_ip << "] packets: " << packets
00167         << "\n router[" << node_ip << "] flits: " << flits;
00168     if( stat_print_level > 2 )
00169     {
00170         for( uint i=0; i<ports; i++)
00171             for ( uint j=0; j<ports; j++)
00172             {
00173                 string in_port = "Inv";
00174                 switch( i )
00175                 {
00176                     case 0 : 
00177                         in_port = "Inj";
00178                         break;
00179                     case 1:
00180                         in_port = 'E';
00181                         break;
00182                     case 2:
00183                         in_port = 'W';
00184                         break;
00185                     case 3:
00186                         in_port = 'S';
00187                         break;
00188                     case 4:
00189                         in_port = 'N';
00190                         break;
00191                     default:
00192                         in_port = "Invalid";
00193                         break;
00194                 }
00195 
00196                 string out_port = "Inv";
00197                 switch( j )
00198                 {
00199                     case 0 : 
00200                         out_port = "Ejection";
00201                         break;
00202                     case 1:
00203                         out_port = 'W';
00204                         break;
00205                     case 2:
00206                         out_port = 'E';
00207                         break;
00208                     case 3:
00209                         out_port = 'N';
00210                         break;
00211                     case 4:
00212                         out_port = 'S';
00213                         break;
00214                     default:
00215                         out_port = "Invalid";
00216                         break;
00217                 }
00218                 if ( i!=j)
00219                 {
00220                     str << "\n    router[" << node_ip << "] Packets out " << in_port 
00221                         << " going " << out_port << " : " << stat_packet_out[i][j];
00222                     str << "\n    router[" << node_ip << "] Flits out " << in_port 
00223                         << " going " << out_port << " : " << stat_flit_out[i][j];
00224                 }
00225 
00226             }
00227     }
00228 
00229 
00230     return str.str();
00231 }
00232 
00234 void
00235 GenericRouterPhy::handle_link_arrival_event ( IrisEvent* e )
00236 {
00237     LinkArrivalData* data = static_cast<LinkArrivalData*>(e->event_data.at(0));
00238     /* this data pointer has a type field which indicates if it is a
00239      * flit or credit. If you have other types that can be passed on
00240      * the link add it as a type in
00241      * source/util/simIrisComponentHeader.h.
00242      * When the configuration is as follows
00243      *  ROUTER --------> ROUTER 
00244      *          Link
00245      *  The previous router would have set the type to FLIT_ID in the
00246      *  switch traversal stage in this example or watever is the last
00247      *  stage before the flit leaves the packet. When coming from an
00248      *  interface. The interface sets it.
00249      */
00250     if(data->type == FLIT_ID)
00251     {
00252         /*  Update stats */
00253         flits++;
00254         if( data->ptr->type == TAIL || data->ptr->is_single_flit_pkt )
00255             packets++;
00256 
00257         /*Find the port the flit came in on */
00258         bool found = false;
00259         uint port = -1;
00260         /*  Need to check for null here as there may be null links to corner routers */
00261         for ( uint i=0 ; i< ports ; i++ )
00262             if(static_cast<GenericLink*>(input_connections[i])->input_connection) 
00263                 if( e->src_id == static_cast<GenericLink*>(input_connections[i])->input_connection->address)
00264                 {
00265                     found = true;
00266                     port = i;
00267                     break;
00268                 }
00269 
00270         /* Throw and exception if it was not found */
00271         if( !found )
00272         {
00273             _DBG(" Input port not found src_addr: %d", e->src_id);
00274         }
00275 
00276         /* Push the flit into the buffer */
00277         in_buffers[port].change_push_channel(data->vc);
00278         in_buffers[port].push(data->ptr);
00279         decoders[port].push(data->ptr,data->vc);
00280         /* If this flit type is HEAD init the input_buffer_state as a
00281          * new message is come in. input_buffer_state is a good
00282          * structure to use for debugging the router as you can update
00283          * it to hold state from different pipeline stages in the
00284          * router.
00285          */
00286         if( data->ptr->type == HEAD )
00287         {
00288             HeadFlit* hf = static_cast<HeadFlit*>(data->ptr);
00289             input_buffer_state[port*vcs+data->vc].input_port = port;
00290             input_buffer_state[port*vcs+data->vc].input_channel = data->vc;
00291             input_buffer_state[port*vcs+data->vc].pipe_stage = FULL;
00292             /* The possible output ports vector is used by the RC
00293              * stage because RC does no determine the output port in
00294              * all cases. RC returns a set of output ports that the
00295              * packet can take and the arbiters decide which ones to
00296              * request for. Eg: Say you have north-last routing and
00297              * the destination is west. You can have more than one
00298              * output ports that will take you to the destination.
00299              * Hence RC will return all possible output ports and you
00300              * may at the point where you request switch allocation
00301              * based on buffer occupancy or some other metric request
00302              * only a few. However is strict DOR (xy) routing there is
00303              * only one output port that the packet can take.
00304              * Similarly for vcs. In cases where packets are allowed
00305              * only some virtual channels to take. RC will fill out
00306              * the possible_ovcs with the correct set of vcs. 
00307              * With stric DOR routing possible_vcs should have vc0 to vc(n-1)
00308              * where n is the number of vcs in the system. This is to
00309              * indicate that the vcs are just use to improve system
00310              * throughput/ better link utilization
00311              */
00312             input_buffer_state[port*vcs+data->vc].possible_oports.clear(); 
00313             input_buffer_state[port*vcs+data->vc].possible_ovcs.clear(); 
00314             input_buffer_state[port*vcs+data->vc].possible_oports.resize(1); 
00315             input_buffer_state[port*vcs+data->vc].possible_ovcs.resize(1); 
00316             input_buffer_state[port*vcs+data->vc].possible_oports[0] = decoders[port].get_output_port(data->vc);
00317             input_buffer_state[port*vcs+data->vc].possible_ovcs[0] = 0;
00318             input_buffer_state[port*vcs+data->vc].length= hf->length;
00319             input_buffer_state[port*vcs+data->vc].credits_sent= hf->length;
00320             input_buffer_state[port*vcs+data->vc].arrival_time= ceil(Simulator::Now());
00321             input_buffer_state[port*vcs+data->vc].clear_message= false;
00322             input_buffer_state[port*vcs+data->vc].flits_in_ib = 0;
00323 
00324         }
00325         else
00326         {
00327             istat->stat_router[node_ip]->ib_cycles++;
00328 #ifdef _DEBUG_ROUTER
00329             _DBG(" BW inport:%d invc:%d oport:%d ovc:%d ft:%d", port, data->vc,
00330                  input_buffer_state[port*vcs+data->vc].output_port, input_buffer_state[port*vcs+data->vc].output_channel, data->ptr->type);
00331 #endif
00332 
00333         }
00334 
00335     }
00336     /* If a credit comes in update the downstream_credit vector. This
00337      * means a buffer was emptied on the router you sent a flit to. 
00338      * Notice credit signal get propagated backwards */
00339     else if ( data->type == CREDIT_ID)
00340     {
00341         /* Find the corresponding output port */
00342         bool found = false;
00343         uint port = -1;
00344         for ( uint i=0 ; ports ; i++ )
00345             if(static_cast<GenericLink*>(output_connections[i])->output_connection) /* Some links of corner routers may be null */
00346                 if( static_cast<GenericLink*>(output_connections[i])->output_connection->address == e->src_id)
00347                 {
00348                     port = i;
00349                     found = true;
00350                     break;
00351                 }
00352         if(!found)
00353         {
00354             _DBG(" Output port not found src_addr: %d", e->src_id);
00355         }
00356 
00357         downstream_credits[port][data->vc]++;
00358 #ifdef _DEBUG_ROUTER
00359         /* This is a good macro to use if you are debugging it prints
00360          * out the routers component address node_id and the msg
00361          * How do component address work??
00362          * a node is combination of a processor+interface+router so
00363          * these 3 components share a node_id
00364          * But since they are different components they also have
00365          * unique addresses.
00366          */
00367         _DBG(" Got a credit port:%d vc:%d in_buffers[port][vc]:%d ", port, data->vc, downstream_credits[port][data->vc]);
00368 #endif
00369 
00370     }
00371     else
00372     {
00373         _DBG( "handle_link_arrival_event Unk data type %d ", data->type);
00374     }
00375 
00376     /* Tick since you update a credit or flit. This router
00377      * component is not running time stepped and hence it stops
00378      * ticking when it has no packets. This is to wake it up */
00379     if(!ticking)
00380     {
00381         ticking = true;
00382         IrisEvent* event = new IrisEvent();
00383         event->type = TICK_EVENT;
00384         event->vc = e->vc;
00385         Simulator::Schedule( floor(Simulator::Now())+1, &NetworkComponent::process_event, this, event);
00386     }
00387 
00388     delete data;
00389     delete e;
00390     return ;
00391 }               /* -----  end of function GenericRouterPhy::handle_link_arrival_event  ----- */
00392 
00393 void
00394 GenericRouterPhy::do_switch_traversal()
00395 {
00396     /* Switch traversal:
00397      * Main steps 
00398      * 1. Check the crossbar (empty or not)
00399      * 2. Pull from it ad send the flit out
00400      * 3. If tail free locked resources
00401      * 4. For every flit update state and send credits back*/
00402     for( uint i=0; i<ports*vcs; i++)
00403         if( input_buffer_state[i].pipe_stage == SW_TRAVERSAL)
00404         {
00405             uint oport = input_buffer_state[i].output_port;
00406             uint iport = input_buffer_state[i].input_port;
00407             ticking = true;
00408             if( !xbar.is_empty(oport,0) 
00409                 && input_buffer_state[i].flits_in_ib > 0
00410                 && downstream_credits[oport][0]>0 )
00411             {
00412                 istat->stat_router[node_ip]->st_cycles++;
00413                 in_buffers[iport].change_pull_channel(0);
00414                 Flit* f = in_buffers[iport].pull();
00415                 input_buffer_state[i].flits_in_ib--;
00416 
00417                 last_flit_out_cycle = Simulator::Now();
00418 
00419                 LinkArrivalData* data = new LinkArrivalData();
00420                 data->type = FLIT_ID;
00421                 data->vc = 0;
00422                 data->ptr = f;
00423 
00424                 stat_flit_out[iport][oport]++;
00425 #ifdef _DEEP_DEBUG
00426                 _DBG(" FLIT OUT ftype: %d ", f->type);
00427                 switch( f->type)
00428                 {
00429                     case HEAD:
00430                         cout << static_cast<HeadFlit*>(f)->toString();
00431                         break;
00432                     case BODY:
00433                         cout << static_cast<BodyFlit*>(f)->toString();
00434                         break;
00435                     case TAIL:
00436                         cout << static_cast<TailFlit*>(f)->toString();
00437                         break;
00438                 }
00439 #endif
00440                 IrisEvent* event = new IrisEvent();
00441                 event->type = LINK_ARRIVAL_EVENT;
00442                 event->event_data.push_back(data);
00443                 event->src_id = address;
00444                 event->dst_id = output_connections[oport]->address;
00445                 event->vc = data->vc;
00446                 Simulator::Schedule( Simulator::Now()+0.75,
00447                                      &NetworkComponent::process_event,
00448                                      static_cast<GenericLink*>(output_connections[oport])->output_connection,event);
00449                 static_cast<GenericLink*>(output_connections[oport])->flits_passed++;
00450                 downstream_credits[oport][0]--;
00451                 if( f->type == TAIL || f->is_single_flit_pkt )
00452                 {
00453                     /* Update packet stats */
00454                     double lat;
00455                     if(do_two_stage_router)
00456                         lat = Simulator::Now() - input_buffer_state[i].arrival_time;
00457                     else
00458                         lat = (Simulator::Now() - input_buffer_state[i].arrival_time)+1;
00459 
00460                     total_packet_latency+= lat;
00461                     if( f->type == HEAD)
00462                     {
00463                         HeadFlit* hf = static_cast<HeadFlit*>(f);
00464                         hf->avg_network_latency += lat;
00465                         hf->hop_count++;
00466                     }
00467                     else
00468                     {
00469                         TailFlit* tf = static_cast<TailFlit*>(f);
00470                         tf->avg_network_latency += lat;
00471                         tf->hop_count++;
00472                     }
00473                     stat_packet_out[iport][oport]++;
00474 
00475                     /* Clear locked resources. This is at a
00476                      * message level */
00477                     input_buffer_state[i].clear_message = true;
00478                     input_buffer_state[i].pipe_stage = EMPTY;
00479                     swa.clear_winner(input_buffer_state[i].output_port, input_buffer_state[i].input_port);
00480                     xbar.pull(input_buffer_state[i].output_port,input_buffer_state[i].output_channel);
00481 #ifdef _DEBUG_ROUTER
00482                     _DBG(" Tail FO clear pkt for inport %d oport %d ", iport, oport);
00483 #endif
00484                 }
00485                 else
00486                 {
00487 #ifdef _DEBUG_ROUTER
00488                     _DBG(" Flit out for inport %d oport %d fty: %d ", iport, oport, f->type);
00489 #endif
00490                 }
00491 
00492                 /* Safe to send credits here as the flit is sure to empty
00493                  * the buffer. */
00494                 //                    if(!send_early_credit)
00495                 send_credit_back(i);
00496 
00497             }
00498         }
00499 
00500 }
00501 
00502 void
00503 GenericRouterPhy::do_switch_allocation()
00504 {
00505     /* Switch Allocation */
00506     bool sa_active = false;
00507     for( uint i=0; i<ports*vcs; i++)
00508         if( input_buffer_state[i].pipe_stage == SWA_REQUESTED)
00509         {
00510             if ( !swa.is_empty())
00511             {
00512                 uint oport = -1;
00513                 SA_unit vca_winner;
00514                 uint iport = input_buffer_state[i].input_port;
00515                 for ( uint j=0; j<input_buffer_state[i].possible_oports.size(); j++)
00516                 {
00517                     oport = input_buffer_state[i].possible_oports[j];
00518                     vca_winner = swa.pick_winner(oport);
00519                     sa_active = true;
00520                 }
00521 
00522                 if( vca_winner.port == iport )
00523                 {
00524                     input_buffer_state[i].pipe_stage = SW_TRAVERSAL;
00525                     input_buffer_state[i].output_port = oport;
00526                     input_buffer_state[i].output_channel = 0;
00527                     xbar.configure_crossbar(iport,oport,0);
00528                     /* The crossbar is a physical crossbar but
00529                      * needs to know the virtual channel as well. So that it pulls
00530                      * from the correct place. This need not always be
00531                      * and other crossbar designs may not require this.
00532                      * */
00533                     xbar.push(oport,0);
00534 
00535 #ifdef _DEBUG_ROUTER
00536                     _DBG(" SWA won for inport %d oport %d ", iport, oport);
00537 #endif
00538                 }
00539                 else
00540                 {
00541 #ifdef _DEBUG_ROUTER
00542                     _DBG(" Dint win for inport %d SWA winner was inport %d for oport %d "
00543                          ,iport, vca_winner.port, oport);
00544 #endif
00545                     swa.clear_requested(oport, iport);
00546                     input_buffer_state[i].pipe_stage = FULL;
00547                     input_buffer_state[i].flits_in_ib--;
00548 
00549                 }
00550                 ticking = true;
00551             }
00552             else
00553             {
00554                 cout << "ERROR SWA was requested but the switch allocator has no requests" << endl;
00555             }
00556         }
00557 
00558         if(sa_active)
00559             istat->stat_router[node_ip]->sa_cycles++;
00560 }
00561 
00562 void
00563 GenericRouterPhy::do_input_buffering()
00564 {
00565     /*  Input buffering 
00566      *  Flits are pushed into the input buffer in the link arrival handler
00567      *  itself. To ensure the pipeline stages are executed in reverse pipe
00568      *  order IB is done here and all link_traversals have higher priority and get done before
00569      *  tick. Head/Body and Tail flits go thru the IB stage.*/
00570     for( uint i=0; i<(ports*vcs); i++)
00571         if( input_buffer_state[i].pipe_stage == FULL )
00572         {
00573 #ifdef _DEBUG_ROUTER
00574             _DBG(" IB + RC inport:%d oport:%d length:%d arrival_time: %f", input_buffer_state[i].input_port,
00575                  input_buffer_state[i].output_port, input_buffer_state[i].length, Simulator::Now());
00576 #endif
00577             input_buffer_state[i].pipe_stage = IB;
00578             input_buffer_state[i].flits_in_ib++;
00579             ticking = true;
00580             istat->stat_router[node_ip]->ib_cycles++;
00581         }
00582 
00587     for( uint i=0; i<(ports*vcs); i++)
00588     {
00589         uint iport = input_buffer_state[i].input_port;
00590         uint oport = input_buffer_state[i].output_port ;
00591 
00592         /* The head could have advanced to switch traversal or
00593          * still be in ib when the body comes in. Notice buffer
00594          * state is maintained per packet and hence its the head
00595          * that is controlling it
00596          * */
00597         if ((input_buffer_state[i].pipe_stage == SW_TRAVERSAL || input_buffer_state[i].pipe_stage == IB )
00598             || input_buffer_state[i].pipe_stage == SWA_REQUESTED 
00599             && (input_buffer_state[i].flits_in_ib < in_buffers[iport].get_occupancy(0)))
00600         { 
00601             input_buffer_state[i].flits_in_ib++;
00602             ticking = true;
00603 #ifdef _DEBUG_ROUTER
00604             _DBG(" IB for BODY/TAIL for inport %d oport %d ", iport, oport);
00605 #endif
00606         }
00607     }
00608 
00609     return;
00610 }
00611 
00618 void
00619 GenericRouterPhy::handle_tick_event ( IrisEvent* e )
00620 {
00621 
00622 #ifdef _DEEP_DEBUG
00623     _DBG_NOARG("input_buffer_state matrix\n");
00624     for( uint i=0; i<ports*vcs; i++)
00625         cout <<i<<" "<< input_buffer_state[i].toString()<< " buff_occ:" <<in_buffers[input_buffer_state[i].
00626             input_port].get_occupancy(input_buffer_state[i].input_channel) << endl;
00627 #endif
00628 
00629     ticking = false;
00630 
00631     do_switch_traversal();
00632     do_switch_allocation();
00633     /* Fos this router it can also be 
00634      * do_switch_allocation();
00635      * do_switch_traversal()
00636      * which then makes both take one cycle as oposed to each
00637      * taking one cycle.
00638      * Need to examine dependencies carefully for things like this.
00639      * */
00640 
00641     do_input_buffering();
00642 
00643     /* Request Switch Allocation. At the end of IB all packets can ask
00644      * for SA. In the SA stage you pick a winner and move forward. 
00645      * */
00646     for( uint i=0; i<(ports*vcs); i++)
00647     {
00648         if( input_buffer_state[i].pipe_stage == IB )
00649         {
00650             uint iport = input_buffer_state[i].input_port;
00651             uint oport = input_buffer_state[i].possible_oports[0];
00652             //input_buffer_state[i].pipe_stage = ROUTED;
00653             if( !swa.is_requested(oport,iport) 
00654                 && downstream_credits[oport][0] == credits)
00655             {
00656                 swa.request(oport, iport);
00657                 input_buffer_state[i].pipe_stage = SWA_REQUESTED;
00658                 ticking = true;
00659             }
00660         }
00661     }
00662 
00663     if(ticking)
00664     {
00665         ticking = true;
00666         IrisEvent* event = new IrisEvent();
00667         event->type = TICK_EVENT;
00668         event->vc = e->vc;
00669         Simulator::Schedule(Simulator::Now()+1, &NetworkComponent::process_event, this, event);
00670     }
00671 
00672     delete e;
00673     return;
00674 
00675 }               /* -----  end of function GenericRouterPhy::handle_input_arbitration_event  ----- */
00676 
00677 string
00678 GenericRouterPhy::toString() const
00679 {
00680     stringstream str;
00681     str << "GenericRouterPhy"
00682         << "\t addr: " << address
00683         << " node_ip: " << node_ip
00684         << "\n Input buffers: " << in_buffers.size() << " ";
00685     if( in_buffers.size() > 0)
00686         str << in_buffers[0].toString();
00687 
00688     str << "\n SWA: " << swa.toString();
00689 
00690     str << "\n decoders: " << decoders.size() << " ";
00691     if( decoders.size() > 0)
00692         str << decoders[0].toString();
00693 
00694     str << "\n Xbar ";
00695     str << xbar.toString();
00696 
00697     return str.str();
00698 }
00699 
00700 /* Credits in this router are sent at a per flit basis
00701  * FLIT_LEVEL_FLOW_CONTROL
00702  * */
00703 void
00704 GenericRouterPhy::send_credit_back(uint i)
00705 {
00706     input_buffer_state[i].credits_sent--;
00707     LinkArrivalData* data = new LinkArrivalData();
00708     uint port = input_buffer_state[i].input_port;
00709     data->type = CREDIT_ID;
00710     data->vc = input_buffer_state[i].input_channel;
00711     IrisEvent* event = new IrisEvent();
00712     event->type = LINK_ARRIVAL_EVENT;
00713     event->event_data.push_back(data);
00714     event->src_id = address;
00715     event->vc = data->vc; 
00716     Simulator::Schedule(Simulator::Now()+0.75, &NetworkComponent::process_event,
00717                         static_cast<GenericLink*>(input_connections[port])->input_connection, event);
00718 
00719 #ifdef _DEBUG_ROUTER
00720     _DBG(" Credit back for inport %d inch %d ", port, data->vc);
00721 #endif
00722 }
00723 
00724 
00725 #endif   /* ----- #ifndef _genericRouterPhy_cc_INC  ----- */
00726 

Generated on Tue Oct 19 17:22:00 2010 for IRIS by  doxygen 1.5.8