routerReqReply.cc

Go to the documentation of this file.
00001 
00022 #ifndef  _routerReqReply_cc_INC
00023 #define  _routerReqReply_cc_INC
00024 
00025 #include        "routerReqReply.h"
00026 using namespace std;
00027 
00028 RouterReqReply::RouterReqReply ()
00029 {
00030     name = "RouterReqReply" ;
00031     ticking = false;
00032 }  /* -----  end of method RouterReqReply::RouterReqReply  (constructor)  ----- */
00033 
00034 RouterReqReply::~RouterReqReply()
00035 {
00036 }
00037 
00038 void
00039 RouterReqReply::init (uint p, uint v, uint cr, uint bs)
00040 {
00041     ports =p;
00042     vcs =v;
00043     credits =cr;
00044     buffer_size = bs;
00045 
00046     address = myId();
00047 
00048     /*  set_input_ports(ports); */
00049     in_buffers.resize(ports);
00050     decoders.resize(ports);
00051     input_buffer_state.resize(ports*vcs);
00052     sw_alloc.resize(ports);
00053     downstream_credits.resize(ports);
00054     cr_time.resize(ports);
00055     request_op.resize(ports);
00056     vca.set_no_msg_classes(no_msg_classes);
00057     vca.init(ports, vcs );
00058 
00059     /*Resize per port stats */
00060     stat_packet_out.resize(ports);
00061     stat_flit_out.resize(ports);
00062 
00063 
00064     /* All decoders and vc arbiters need to know the node_ip for routing */
00065     for(uint i=0; i<ports; i++)
00066     {
00067         decoders[i].node_ip = node_ip;
00068         decoders[i].address = address;
00069         stat_packet_out[i].resize(ports);
00070         stat_flit_out[i].resize(ports);
00071     }
00072 
00073     /*  set_no_virtual_channels(vcs); */
00074     for(uint i=0; i<ports; i++)
00075     {
00076         downstream_credits[i].resize(vcs);
00077         cr_time[i].resize(vcs);
00078         in_buffers[i].resize( vcs, buffer_size );
00079         decoders[i].resize( vcs );
00080     }
00081 
00082     for(uint i=0; i<ports; i++)
00083         for(uint j=0; j<vcs; j++)
00084         {
00085             downstream_credits[i][j] = credits;
00086             cr_time[i][j] = -1;
00087             input_buffer_state[i*vcs+j].pipe_stage = EMPTY;
00088         }
00089 
00090     /* init the countes */
00091     stat_packets = 0;
00092     stat_flits = 0;
00093     stat_total_packet_latency = 0;
00094     stat_buffer_occupancy = 0;
00095     stat_swa_fail_msg_ratio = 0;
00096     stat_swa_load = 0;
00097     stat_vca_fail_msg_ratio = 0;
00098     stat_vca_load = 0;
00099     stat_ib_cycles = 0;
00100     stat_rc_cycles = 0;
00101     stat_vca_cycles = 0;
00102     stat_swa_cycles = 0;
00103     stat_st_cycles = 0;
00104 
00105     /* 
00106     std::ostringstream buffer;
00107     buffer << "debug/router_";
00108     buffer << node_ip;
00109     string debug_log_string= buffer.str();
00110     debug_log.open(debug_log_string.c_str());
00111 
00112      * */
00113     IrisEvent* event = new IrisEvent();
00114     event->type = DETECT_DEADLOCK_EVENT;
00115     Simulator::Schedule( floor(Simulator::Now())+1, &NetworkComponent::process_event, this, event);
00116 
00117     return ;
00118 }               /* -----  end of function RouterReqReply::init  ----- */
00119 
00122 void
00123 RouterReqReply::set_no_nodes( uint nodes )
00124 {
00125     for ( uint i=0; i<decoders.size(); i++)
00126     {
00127         decoders[i].grid_xloc.resize(nodes);
00128         decoders[i].grid_yloc.resize(nodes);
00129     }
00130 }
00131 
00132 void
00133 RouterReqReply::set_grid_x_location( uint port, uint x_node, uint value)
00134 {
00135     decoders[port].grid_xloc[x_node]= value;
00136 }
00137 
00138 void
00139 RouterReqReply::set_grid_y_location( uint port, uint y_node, uint value)
00140 {
00141     decoders[port].grid_yloc[y_node]= value;
00142 }
00143 
00144 /*  End of DOR grid location functions */
00145 
00146 void
00147 RouterReqReply::process_event ( IrisEvent* e )
00148 {
00149     switch(e->type)
00150     {
00151         case LINK_ARRIVAL_EVENT:
00152             handle_link_arrival_event(e);
00153             break;
00154         case TICK_EVENT:
00155             handle_tick_event(e);
00156             break;
00157         case DETECT_DEADLOCK_EVENT:
00158             handle_detect_deadlock_event(e);
00159             break;
00160         default:
00161             _DBG("RouterReqReply:: Unk event exception %d", e->type);
00162             break;
00163     }
00164     return ;
00165 }               /* -----  end of function RouterReqReply::process_event  ----- */
00166 
00167 void 
00168 RouterReqReply::handle_detect_deadlock_event(IrisEvent* e )
00169 {
00170     for ( uint i=0; i<ports; i++)
00171         for ( uint j=0; j<vcs; j++)
00172         {
00173             if( cr_time[i][j] != -1)
00174             {
00175                 cr_time[i][j]++;
00176                 if( cr_time[i][j] > 10000 )
00177                 {
00178                     _DBG_NOARG("************ KILLING SIMULATION *************");
00179                     cout << "\ndeadlock detected op:"<< i << " ovc: " << j <<  endl;
00180                     cout << "\ndeadlock mssg:"<< endl;
00181                     cout << "ip\tic\top\toc\taddr:"<< endl;
00182                     for ( uint ii=0; ii<ports*vcs; ii++)
00183                         if(input_buffer_state[ii].output_port == i && input_buffer_state[ii].output_channel == j)
00184                         {
00185                             cout << dec << input_buffer_state[ii].input_port;
00186                             cout << dec << "\t" << input_buffer_state[ii].input_channel;
00187                             cout << dec << "\t" << input_buffer_state[ii].output_port;
00188                             cout << dec << "\t" << input_buffer_state[ii].output_channel;
00189                             cout << hex << "\t" << input_buffer_state[ii].address << endl;
00190                         }
00191                     cout << "*************************" << endl;
00192 
00193                     //                    print_state_at_deadlock();
00194                     exit(1);
00195                 }
00196             }
00197         }
00198 
00199     e->type = DETECT_DEADLOCK_EVENT;
00200     Simulator::Schedule( floor(Simulator::Now())+50, &NetworkComponent::process_event, this, e);
00201 }
00202 
00203 void 
00204 RouterReqReply::dump_buffer_state()
00205 {
00206     for ( uint i=0; i<ports*vcs; i++)
00207         if(input_buffer_state[i].pipe_stage != EMPTY && input_buffer_state[i].pipe_stage != INVALID)
00208         {
00209             cout << " Router[" << node_ip << "]->buff["<<i<<"] " << input_buffer_state[i].toString() << endl;
00210         }
00211     cout << endl;
00212 
00213     return;
00214 }
00215 
00216 string
00217 RouterReqReply::print_stats()
00218 {
00219     stringstream str;
00220     str << name ;
00221     str << "\n router[" << node_ip << "] packet latency: " << stat_total_packet_latency
00222         << "\n router[" << node_ip << "] flits/packet: " << (stat_flits+0.0)/(stat_packets)
00223         << "\n router[" << node_ip << "] average packet latency: " << (stat_total_packet_latency+0.0)/stat_packets
00224         << "\n router[" << node_ip << "] last_flit_out_cycle: " << last_flit_out_cycle
00225         << "\n router[" << node_ip << "] stat_buffer_occupancy: " << stat_buffer_occupancy 
00226         << "\n router[" << node_ip << "] stat_swa_fail_msg_ratio: " << stat_swa_fail_msg_ratio
00227         << "\n router[" << node_ip << "] stat_swa_load: " << stat_swa_load
00228         << "\n router[" << node_ip << "] stat_vca_fail_msg_ratio: " << stat_vca_fail_msg_ratio
00229         << "\n router[" << node_ip << "] stat_vca_load: " << stat_vca_load
00230         << "\n router[" << node_ip << "] packets: " << stat_packets
00231         << "\n router[" << node_ip << "] flits: " << stat_flits
00232         << "\n router[" << node_ip << "] stat_ib_cycles: " << stat_ib_cycles
00233         << "\n router[" << node_ip << "] stat_rc_cycles: " << stat_rc_cycles
00234         << "\n router[" << node_ip << "] stat_vca_cycles: " << stat_vca_cycles
00235         << "\n router[" << node_ip << "] stat_swa_cycles: " << stat_swa_cycles
00236         << "\n router[" << node_ip << "] stat_st_cycles: " << stat_st_cycles
00237         << " ";
00238 
00239     str << "\n router[" << node_ip << "] out_port_links_utilization: ";
00240     for( uint i=0; i<ports; i++)
00241         str << static_cast<GenericLink*>(output_connections[i])->flits_passed*1.0/max_sim_time << " ";
00242     str << endl;
00243 
00244     if( stat_print_level > 2 )
00245     {
00246         for( uint i=0; i<ports; i++)
00247             for ( uint j=0; j<ports; j++)
00248             {
00249                 string in_port = "Inv";
00250                 switch( i )
00251                 {
00252                     case 0 : 
00253                         in_port = "Inj";
00254                         break;
00255                     case 1:
00256                         in_port = 'E';
00257                         break;
00258                     case 2:
00259                         in_port = 'W';
00260                         break;
00261                     case 3:
00262                         in_port = 'S';
00263                         break;
00264                     case 4:
00265                         in_port = 'N';
00266                         break;
00267                     default:
00268                         in_port = "Invalid";
00269                         break;
00270                 }
00271 
00272                 string out_port = "Inv";
00273                 switch( j )
00274                 {
00275                     case 0 : 
00276                         out_port = "Ejection";
00277                         break;
00278                     case 1:
00279                         out_port = 'W';
00280                         break;
00281                     case 2:
00282                         out_port = 'E';
00283                         break;
00284                     case 3:
00285                         out_port = 'N';
00286                         break;
00287                     case 4:
00288                         out_port = 'S';
00289                         break;
00290                     default:
00291                         out_port = "Invalid";
00292                         break;
00293                 }
00294                 if ( i != j) 
00295                 {
00296                     str << "\n    router[" << node_ip << "] Packets out " << in_port 
00297                         << " going " << out_port << " : " << stat_packet_out[i][j];
00298                     str << "\n    router[" << node_ip << "] Flits out " << in_port 
00299                         << " going " << out_port << " : " << stat_flit_out[i][j];
00300                 }
00301 
00302             }
00303     }
00304 
00305 
00306     return str.str();
00307 }
00308 
00310 void
00311 RouterReqReply::handle_link_arrival_event ( IrisEvent* e )
00312 {
00313     LinkArrivalData* data = static_cast<LinkArrivalData*>(e->event_data.at(0));
00314     if(data->type == FLIT_ID)
00315     {
00316 
00317         /*Find the port the flit came in on */
00318         bool found = false;
00319         uint port = -1;
00320         /*  Need to check for null here as there may be null links to corner routers */
00321         for ( uint i=0 ; i< ports ; i++ )
00322             if(static_cast<GenericLink*>(input_connections[i])->input_connection) 
00323                 if( e->src_id == static_cast<GenericLink*>(input_connections[i])->input_connection->address)
00324                 {
00325                     found = true;
00326                     port = i;
00327                     break;
00328                 }
00329 
00330         /* Throw and exception if it was not found */
00331         if( !found )
00332         {
00333             _DBG(" Input port not found src_addr: %d", e->src_id);
00334         }
00335 
00336         /* Push the flit into the buffer */
00337         in_buffers[port].change_push_channel(data->vc);
00338         in_buffers[port].push(data->ptr);
00339 
00340         /* counting ib for body/teail can be complicated as the msg state
00341          * could have progressed to some other stage. Hence counting it at
00342          * link arrival makes it easy. */
00343         if(data->ptr->type !=HEAD)
00344         {
00345             istat->stat_router[node_ip]->ib_cycles++;
00346             stat_ib_cycles++;
00347         }
00348 
00349         _DBG(" handle_link_arrival_event: port %d vc %d ft %d ps:%d ", port, data->vc, data->ptr->type, input_buffer_state[port].pipe_stage);
00350         if(data->ptr->type == HEAD)
00351         {
00352             cout        << static_cast<HeadFlit*>(data->ptr)->addr<< endl;
00353         }
00354     }
00355     else if ( data->type == CREDIT_ID)
00356     {
00357         /* Find the corresponding output port */
00358         bool found = false;
00359         uint port = -1;
00360         for ( uint i=0 ; ports ; i++ )
00361             if(static_cast<GenericLink*>(output_connections[i])->output_connection) /* Some links of corner routers may be null */
00362                 if( static_cast<GenericLink*>(output_connections[i])->output_connection->address == e->src_id)
00363                 {
00364                     port = i;
00365                     found = true;
00366                     break;
00367                 }
00368         if(!found)
00369         {
00370             _DBG(" Output port not found src_addr: %d", e->src_id);
00371         }
00372 
00373         downstream_credits[port][data->vc]++;
00374         cr_time[port][data->vc] = -1;
00375 
00376 #ifdef _DEBUG_ROUTER
00377         _DBG(" Got a credit port:%d vc:%d  ", port, data->vc, downstream_credits[port][data->vc]);
00378         vector < uint > pending_ops ;
00379         vector < uint > pending_ips ;
00380         for( uint i=0; i<ports*vcs; i++)
00381             if(input_buffer_state[i].output_port == port && input_buffer_state[i].output_channel == data->vc)
00382             {
00383                 pending_ops.push_back(port*vcs+data->vc);
00384                 pending_ips.push_back(i);
00385             }
00386 
00387         cout << " Can send msgs (i-o): " ;
00388         for( uint i=0; i<pending_ops.size(); i++)
00389             cout << pending_ips[i] <<"-" << pending_ops[i] << " occ/" << in_buffers[(int)(pending_ops[i]/vcs)].get_occupancy(pending_ops[i]%vcs)
00390                 <<" bst:"<<input_buffer_state[i].pipe_stage << " ";
00391         pending_ops.clear();
00392         pending_ips.clear();
00393 #endif
00394 
00395     }
00396     else
00397     {
00398         _DBG( "handle_link_arrival_event Unk data type %d ", data->type);
00399     }
00400 
00401     /* Tick since you update a credit or flit */
00402     if(!ticking)
00403     {
00404         ticking = true;
00405         IrisEvent* event = new IrisEvent();
00406         event->type = TICK_EVENT;
00407         event->vc = e->vc;
00408         Simulator::Schedule( floor(Simulator::Now())+1, &NetworkComponent::process_event, this, event);
00409     }
00410 
00411     delete data;
00412     delete e;
00413     return ;
00414 }               /* -----  end of function RouterReqReply::handle_link_arrival_event  ----- */
00415 
00416 void
00417 RouterReqReply::do_input_buffering()
00418 {
00419     for( uint i=0; i<ports*vcs; i++)
00420     {
00421         uint inport = (uint)(i/vcs);
00422         uint invc = (uint)(i%vcs);
00423         if( input_buffer_state[i].pipe_stage == FULL || input_buffer_state[i].pipe_stage == EMPTY )
00424         {
00425             if( in_buffers[inport].get_occupancy(invc) > 0)
00426             {
00427 
00428                 in_buffers[inport].change_pull_channel(invc);
00429                 Flit* f = in_buffers[inport].peek();
00430                 //                _DBG(" do_input_buffering %d ft%d",inport*vcs+invc, f->type);
00431 
00432                 if( f->type == HEAD )
00433                 {
00434                     HeadFlit* hf = static_cast<HeadFlit*>(f);
00435                     /*  Update stats for head */
00436                     istat->stat_router[node_ip]->ib_cycles++;
00437                     stat_ib_cycles++;
00438                     //_DBG(" HEAD IN %d %lld",f->type, hf->addr);
00439 
00440                     input_buffer_state[inport*vcs+f->vc].input_port = inport;
00441                     hf->inport = inport;
00442                     decoders[inport].push(f,f->vc);
00443                     input_buffer_state[inport*vcs+f->vc].input_channel = f->vc;
00444                     input_buffer_state[inport*vcs+f->vc].address= hf->addr;
00445                     input_buffer_state[inport*vcs+f->vc].destination= hf->dst_address;
00446                     input_buffer_state[inport*vcs+f->vc].pipe_stage = IB;
00447                     input_buffer_state[inport*vcs+f->vc].msg_class = hf->msg_class;
00448                     input_buffer_state[inport*vcs+f->vc].possible_oports.clear(); 
00449                     input_buffer_state[inport*vcs+f->vc].possible_ovcs.clear(); 
00450                     uint no_adaptive_ports = decoders[inport].no_adaptive_ports(f->vc);
00451                     uint no_adaptive_vcs = decoders[inport].no_adaptive_vcs(f->vc);
00452                     istat->stat_router[node_ip]->rc_cycles++;
00453                     stat_rc_cycles++;
00454 
00455                     for ( uint i=0; i<no_adaptive_ports; i++ )
00456                     {
00457                         uint rc_port = decoders[inport].get_output_port(f->vc);
00458                         if( static_cast<GenericLink*>(output_connections[rc_port])->output_connection != NULL )
00459                             input_buffer_state[inport*vcs+f->vc].possible_oports.push_back(rc_port);
00460                     } 
00461 
00462                     for ( uint i=0; i<no_adaptive_vcs; i++ )
00463                     {
00464                         uint rc_vc = decoders[inport].get_virtual_channel(f->vc);
00465                         input_buffer_state[inport*vcs+f->vc].possible_ovcs.push_back(rc_vc);
00466                     } 
00467 
00468                     assert ( input_buffer_state[inport*vcs+f->vc].possible_oports.size() > 0);
00469                     assert ( input_buffer_state[inport*vcs+f->vc].possible_ovcs.size() > 0);
00470 
00471                     input_buffer_state[inport*vcs+f->vc].length= hf->length;
00472                     input_buffer_state[inport*vcs+f->vc].credits_sent= hf->length;
00473                     input_buffer_state[inport*vcs+f->vc].arrival_time= Simulator::Now();
00474                     input_buffer_state[inport*vcs+f->vc].clear_message= false;
00475                 }
00476                 /* Dont need this only heads go thru RC
00477                    else
00478                    {
00479                 // Body flits are pushed thru the decoder but
00480                 // they dont do anything. Tail flits clear the state
00481                 decoders[inport].push(f,f->vc);
00482                 input_buffer_state[inport*vcs+f->vc].flits_in_ib++;
00483                 cout  << "came here " << endl;
00484 
00485                 }
00486                  * */
00487                 ticking =true;
00488             }
00489         }
00490     }
00491 
00492     /* Body and tail flits get written in link arrival and since the message
00493      * state may already been pushed to ST because of the header we want to
00494      * ensure that all flits go thru an IB and ST stage. Hence ST is done on
00495      * the flits_in_ib information and not buffer occupancy. 
00496      for( uint i=0; i<(ports*vcs); i++)
00497      {
00498      uint ip = input_buffer_state[i].input_port;
00499      uint ic = input_buffer_state[i].input_channel;
00500 
00501      if (input_buffer_state[i].pipe_stage == VCA_COMPLETE || input_buffer_state[i].pipe_stage == SWA_REQUESTED 
00502      || input_buffer_state[i].pipe_stage == SW_TRAVERSAL)
00503      {
00504      in_buffers[ip].change_pull_channel(ic);
00505      Flit* f = in_buffers[ip].peek();
00506      if( f->type != HEAD && (input_buffer_state[i].flits_in_ib < in_buffers[ip].get_occupancy(ic)))
00507      {
00508      input_buffer_state[i].flits_in_ib++;
00509      ticking=true;
00510      }
00511      }
00512 
00513      }
00514      * */
00515 }
00516 
00517 void
00518 RouterReqReply::do_switch_traversal()
00519 {
00520     for( uint i=0; i<(ports*vcs); i++)
00521         if( input_buffer_state[i].pipe_stage == SW_TRAVERSAL)
00522         {
00523             uint op = input_buffer_state[i].output_port;
00524             uint oc = input_buffer_state[i].output_channel;
00525             uint ip = input_buffer_state[i].input_port;
00526             uint ic= input_buffer_state[i].input_channel;
00527             if( in_buffers[ip].get_occupancy(ic)> 0
00528                 && downstream_credits[op][oc]>0 )
00529             {
00530                 in_buffers[ip].change_pull_channel(ic);
00531                 Flit* f = in_buffers[ip].pull();
00532                 f->vc = oc;
00533 
00534                 if(f->type != TAIL && !f->is_single_flit_pkt)
00535                 {
00536                     cout << " resetting ";
00537                     input_buffer_state[i].pipe_stage = VCA_COMPLETE;
00538                     request_switch_allocation();
00539                     ticking = true;
00540                 }
00541 
00542                 /* stats */
00543                 last_flit_out_cycle = Simulator::Now();
00544                 stat_flit_out[ip][op]++;
00545                 stat_flits++;
00546                 static_cast<GenericLink*>(output_connections[op])->flits_passed++;
00547                 istat->stat_link[static_cast<GenericLink*>(output_connections[op])->link_id]->flits_transferred++;
00548 
00549                 /* For energy computation: the per access energy reported is
00550                  * for one flit traversing the crossbar. Unlike arbiter access
00551                  * energy which is for multiple digraph matching in one
00552                  * access. This count may also be used as the local link
00553                  * access count if the ST and LT are considered as the same
00554                  * stage for very short wire lengths. */
00555                 istat->stat_router[node_ip]->st_cycles++;
00556                 stat_st_cycles++;
00557 
00558 
00559                 LinkArrivalData* data = new LinkArrivalData();
00560                 data->type = FLIT_ID;
00561                 data->vc = oc;
00562                 data->ptr = f;
00563 
00564                 _DBG(" Fout %d=%d %d",ip*vcs+ic,op*vcs+oc, f->type);
00565 
00566                 /*  Updating all pkt stats in the head irrespective of msg
00567                  *  class. Assuming all pkts do have a head. However latency
00568                  *  for determining switch throughput is to be determined when
00569                  *  the tail exits.
00570                  *  */
00571                 if( f->type == HEAD)
00572                 {
00573                     HeadFlit* hf = static_cast<HeadFlit*>(f);
00574                     hf->hop_count++;
00575                     _DBG(" Fout %d %d %d %d %d %d addr:%lld ",ip,ic,op,oc,hf->src_address, hf->dst_address, hf->addr);
00576                     cout << f->is_single_flit_pkt;
00577                     //                    cout << "  " << hf->addr;
00578                 }
00579                 if( f->type == TAIL || f->is_single_flit_pkt )
00580                 {
00581                     /* Update packet level stats */
00582                     uint lat = Simulator::Now() - input_buffer_state[i].arrival_time + 1;
00583                     stat_total_packet_latency += lat;
00584                     stat_packets++;
00585 
00586                     if( f->type == HEAD)
00587                     {
00588                         HeadFlit* hf = static_cast<HeadFlit*>(f);
00589                         hf->avg_network_latency += lat;
00590                     }
00591                     else
00592                     {
00593                         TailFlit* tf = static_cast<TailFlit*>(f);
00594                         tf->avg_network_latency += lat;
00595                     }
00596 
00597                     stat_packet_out[ip][op]++;
00598 
00599                     input_buffer_state[i].clear_message = true;
00600                     if(in_buffers[ip].get_occupancy(ic) > 0)
00601                         input_buffer_state[i].pipe_stage = FULL;
00602                     else
00603                         input_buffer_state[i].pipe_stage = EMPTY;
00604 
00605                     vca.clear_winner(ip*vcs+ic, oc );
00606                     input_buffer_state[i].possible_oports.clear();
00607                     input_buffer_state[i].possible_ovcs.clear();
00608                     input_buffer_state[i].output_port = -1;
00609                     input_buffer_state[i].output_channel = -1;
00610                 }
00611 
00612                 cr_time[op][oc] = 0;
00613                 IrisEvent* event = new IrisEvent();
00614                 event->type = LINK_ARRIVAL_EVENT;
00615                 event->event_data.push_back(data);
00616                 event->src_id = address;
00617                 event->dst_id = output_connections[op]->address;
00618                 event->vc = data->vc;
00619 
00620                 Simulator::Schedule( Simulator::Now()+0.75,
00621                                      &NetworkComponent::process_event,
00622                                      static_cast<GenericLink*>(output_connections[op])->output_connection,event);
00623 
00626                 send_credit_back(i);
00627                 downstream_credits[op][oc]--;
00628 
00629             }
00630         }
00631     return;
00632 }
00633 
00634 void
00635 RouterReqReply::do_switch_allocation()
00636 {
00637     bool was_swa_active = false; /* flag to make sure swa accesses are not double counted */
00638     uint tot_swa_req = 0;
00639     uint swa_won=0;
00640 
00641     /*  Take the first response as the winner. If no response take the head */
00642     /* 
00643        for( uint i=0; i<ports; i++)
00644        for( uint j=0; j< sw_alloc[i].size();j++ )
00645        if ( input_buffer_state[sw_alloc[i][j]].msg_class == RESPONSE_PKT )
00646        {
00647        winner_op = j;
00648        break;
00649        }
00650      * */
00651 
00652     for( uint i=0; i<ports; i++)
00653     {
00654         if(  sw_alloc[i].size() )
00655         {
00656             uint winner_op = 0;
00657 
00658             /* Since only one msg can win. counting failure cycles here as a
00659              * measure of congestion. */
00660             swa_won++;
00661             tot_swa_req += sw_alloc[i].size();
00662 
00663             uint msg_id = sw_alloc[i][winner_op];
00664             uint ip = input_buffer_state[msg_id].input_port;
00665             uint ic = input_buffer_state[msg_id].input_channel;
00666             uint op = input_buffer_state[msg_id].output_port;
00667             uint oc = input_buffer_state[msg_id].output_channel;
00668             assert(op == i);
00669             vector<uint>::iterator it = find (sw_alloc[i].begin(), sw_alloc[i].end(), msg_id);;
00670             if( input_buffer_state[msg_id].pipe_stage == SWA_REQUESTED /*  && downstream_credits[op][oc]*/)
00671             {
00672                 sw_alloc[i].erase(it);
00673                 input_buffer_state[msg_id].pipe_stage = SW_TRAVERSAL;
00674 _DBG(" SW_TRAV %d=%d cr:%d occ:%d",ip*vcs+ic,op*vcs+oc,downstream_credits[op][oc], in_buffers[ip].get_occupancy(ic));
00675                 ticking = true;
00676                 was_swa_active = true;
00677             }
00678         }
00679     }
00680     if( tot_swa_req )
00681     {
00682         stat_swa_fail_msg_ratio += ((tot_swa_req - swa_won+0.0)/tot_swa_req);
00683         stat_swa_fail_msg_ratio = stat_swa_fail_msg_ratio/2;
00684         stat_swa_load += ((tot_swa_req+0.0)/(ports*vcs));
00685         stat_swa_load = stat_swa_load/2;
00686     }
00687 
00688     if( was_swa_active )
00689     {
00690         istat->stat_router[node_ip]->sa_cycles++;
00691         stat_swa_cycles++;
00692     }
00693 
00694     return;
00695 }
00696 
00697 void
00698 RouterReqReply::do_virtual_channel_allocation()
00699 {
00700     /* flag to count accesses. Multiple winners
00701      * can be chosen for one access of the arbiter */
00702     bool was_vca_active = false; 
00703     uint tot_vca_req = vca.get_no_requestors();
00704 
00705     for( uint i=0; i<(ports*vcs); i++)
00706         if( input_buffer_state[i].pipe_stage == VCA_REQUESTED)
00707         {
00708             uint op=input_buffer_state[i].output_port; 
00709             uint ip=input_buffer_state[i].input_port; 
00710             uint ic=input_buffer_state[i].input_channel; 
00711             uint mc=input_buffer_state[i].msg_class; 
00712             uint at=input_buffer_state[i].arrival_time; 
00713             uint mid=0;
00714 
00715             if( do_request_reply_network)
00716                 if( mc == ONE_FLIT_REQ || mc == REQUEST_PKT )
00717                     mid = 1;
00718 
00719             vca.request(op, mid, ip*vcs+ic, at);
00720 //            _DBG(" VCA REQ %d=%d",ip*vcs+ic,op);
00721         }
00722     uint vca_won = 0;
00723     vca_won = vca.pick_winners();
00724 
00725     for( uint i=0; i<no_msg_classes; i++)
00726         for( uint j=0; j<ports; j++)
00727         {
00728             map<uint ,uint>::iterator iter;
00729             for( iter = vca.winners[i][j].begin(); iter != vca.winners[i][j].end(); ++iter ) 
00730                 {
00731                     uint msg_index = iter->first;
00732                     uint msg_oc = iter->second;
00733                     if( input_buffer_state[msg_index].pipe_stage == VCA_REQUESTED /* && downstream_credits[op][oc] > 0 */) 
00734                     {
00735                         uint op = input_buffer_state[msg_index].output_port; 
00736                         uint ip = input_buffer_state[msg_index].input_port;
00737                         uint ic = input_buffer_state[msg_index].input_channel;
00738                         assert( op == j);
00739                         /* can request only if there are credits improving 
00740                          * chances of winning for other pkts that can actually 
00741                          * exit the router */
00742                         //                    _DBG(" VCA COMP %d=%d",ip*vcs+ic,op*vcs+oc);
00743                         _DBG(" VCA COMP %d %d %lld",op,msg_oc, input_buffer_state[msg_index].address);
00744                         input_buffer_state[msg_index].output_channel = msg_oc;
00745                         input_buffer_state[msg_index].pipe_stage = VCA_COMPLETE;
00746                         ticking = true;
00747                     }
00748                 }
00749         }
00750 
00751     if( vca_won && tot_vca_req )
00752     {
00753         istat->stat_router[node_ip]->vca_cycles++;
00754         stat_vca_cycles++;
00755         stat_vca_fail_msg_ratio += ((tot_vca_req - vca_won+0.0)/tot_vca_req);
00756         stat_vca_fail_msg_ratio = stat_vca_fail_msg_ratio/2;
00757         stat_vca_load += ((tot_vca_req+0.0)/(ports*vcs));
00758         stat_vca_load = stat_vca_load/2;
00759     } 
00760 
00761     request_switch_allocation();
00762 }
00763 
00764 /* This is called from two places. First when head completes vca and requests
00765  * for swa. Second when flit goes out and msg requests for swa again as long
00766  * as there the tail goes out*/
00767 void
00768 RouterReqReply::request_switch_allocation()
00769 {
00770     for( uint i=0; i<(ports*vcs); i++)
00771         if( input_buffer_state[i].pipe_stage == VCA_COMPLETE)
00772         {
00773             uint ip = input_buffer_state[i].input_port;
00774             uint ic = input_buffer_state[i].input_channel;
00775             uint op = input_buffer_state[i].output_port;
00776             uint oc = input_buffer_state[i].output_channel;
00777 
00778             /* Can skip this and speculatively request sa. May end up wasting
00779              * an st cycle during wrong speculation. */
00780             if(in_buffers[ip].get_occupancy(ic) )
00781             {
00782                 //                _DBG(" SWA_REQ %d=%d",ip*vcs+ic,op*vcs+oc);
00783                 sw_alloc[op].push_back(i);
00784                 input_buffer_state[i].pipe_stage = SWA_REQUESTED;
00785                 ticking = true;
00786             }
00787         }
00788     return;
00789 }
00790 
00792 void
00793 RouterReqReply::handle_tick_event ( IrisEvent* e )
00794 {
00795     ticking = false;
00796     do_switch_traversal();
00797     do_switch_allocation();
00798     do_virtual_channel_allocation();
00799 
00805     do_input_buffering();
00806 
00807     /*  In case of adaptive routing need some selection function to pick from
00808      *  available output ports before requesting
00809      *  */
00810 
00812     for( uint i=0; i<(ports*vcs); i++)
00813         if( input_buffer_state[i].pipe_stage == IB )
00814         {
00815             uint ip = input_buffer_state[i].input_port;
00816             uint ic = input_buffer_state[i].input_channel;
00817             uint op = input_buffer_state[i].possible_oports[0];
00818             //            if( downstream_credits[op][oc]>0)
00819             {
00820                 input_buffer_state[i].pipe_stage = VCA_REQUESTED;
00821                 input_buffer_state[i].output_port = op;
00822                 //                _DBG(" VCA REQ1 %d=%d(op)",ip*vcs+ic,op);
00823                 ticking = true;
00824             }
00825         }
00826 
00827     /*Per cycle router stats */
00828     for( uint i=0; i<ports; i++)
00829         for( uint j=0; j<vcs; j++)
00830             if(in_buffers[i].get_occupancy(j) )
00831             {
00832                 double buff_occ =(in_buffers[i].get_occupancy(j)+0.0)/credits;
00833                 stat_buffer_occupancy += buff_occ;
00834                 stat_buffer_occupancy = stat_buffer_occupancy/2;
00835             }
00836 
00837 
00844     if(ticking)
00845     {
00846         ticking = true;
00847         IrisEvent* event = new IrisEvent();
00848         event->type = TICK_EVENT;
00849         event->vc = e->vc;
00850         Simulator::Schedule(Simulator::Now()+1, &NetworkComponent::process_event, this, event);
00851     }
00852 
00853     delete e;
00854     return;
00855 
00856 }               /* -----  end of function RouterReqReply::handle_input_arbitration_event  ----- */
00857 
00858 string
00859 RouterReqReply::toString() const
00860 {
00861     stringstream str;
00862     str << "RouterReqReply"
00863         << "\t addr: " << address
00864         << " node_ip: " << node_ip
00865         << "\n Input buffers: " << in_buffers.size() << " ";
00866     if( in_buffers.size() > 0)
00867         str << in_buffers[0].toString();
00868 
00869     str << "\n decoders: " << decoders.size() << " ";
00870     if( decoders.size() > 0)
00871         str << decoders[0].toString();
00872 
00873     return str.str();
00874 }
00875 
00876 void
00877 RouterReqReply::send_credit_back(uint i)
00878 {
00879     input_buffer_state[i].credits_sent--;
00880     LinkArrivalData* data = new LinkArrivalData();
00881     uint port = input_buffer_state[i].input_port;
00882     data->type = CREDIT_ID;
00883     data->vc = input_buffer_state[i].input_channel;
00884     IrisEvent* event = new IrisEvent();
00885     event->type = LINK_ARRIVAL_EVENT;
00886     event->event_data.push_back(data);
00887     event->src_id = address;
00888     event->vc = data->vc; 
00889     Simulator::Schedule(Simulator::Now()+0.75, &NetworkComponent::process_event,
00890                         static_cast<GenericLink*>(input_connections[port])->input_connection, event);
00891 
00892     static_cast<GenericLink*>(input_connections[port])->credits_passed++;
00893     istat->stat_link[static_cast<GenericLink*>(input_connections[port])->link_id]->credits_transferred++;
00894 }
00895 
00896 #endif   /* ----- #ifndef _routerReqReply_cc_INC  ----- */
00897 

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