routerVcMP.cc

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

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