📄 trouter.cpp
字号:
/***************************************************************************** TRouter.cpp -- Router implementation*****************************************************************************//* Copyright 2005-2007 Fabrizio Fazzino <fabrizio.fazzino@diit.unict.it> Maurizio Palesi <mpalesi@diit.unict.it> Davide Patti <dpatti@diit.unict.it> * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "TRouter.h"//---------------------------------------------------------------------------//---------------------------------------------------------------------------void TRouter::rxProcess(){ if(reset.read()) { // Clear outputs and indexes of receiving protocol for(int i=0; i<DIRECTIONS+1; i++) { ack_rx[i].write(0); current_level_rx[i] = 0; } reservation_table.clear(); routed_flits = 0; local_drained = 0; } else { // For each channel decide if a new flit can be accepted // // This process simply sees a flow of incoming flits. All arbitration // and wormhole related issues are addressed in the txProcess() for(int i=0; i<DIRECTIONS+1; i++) { // To accept a new flit, the following conditions must match: // // 1) there is an incoming request // 2) there is a free slot in the input buffer of direction i if ( (req_rx[i].read()==1-current_level_rx[i]) && !buffer[i].IsFull() ) { TFlit received_flit = flit_rx[i].read(); if(TGlobalParams::verbose_mode > VERBOSE_OFF) { cout << sc_time_stamp().to_double()/1000 << ": Router[" << local_id <<"], Input[" << i << "], Received flit: " << received_flit << endl; } // Store the incoming flit in the circular buffer buffer[i].Push(received_flit); // Negate the old value for Alternating Bit Protocol (ABP) current_level_rx[i] = 1-current_level_rx[i]; // Incoming flit stats.power.Incoming(); } ack_rx[i].write(current_level_rx[i]); } } stats.power.Standby();}//---------------------------------------------------------------------------void TRouter::txProcess(){ if (reset.read()) { // Clear outputs and indexes of transmitting protocol for(int i=0; i<DIRECTIONS+1; i++) { req_tx[i].write(0); current_level_tx[i] = 0; } } else { // 1st phase: Reservation for(int j=0; j<DIRECTIONS+1; j++) { int i = (start_from_port + j) % (DIRECTIONS + 1); if ( !buffer[i].IsEmpty() ) { TFlit flit = buffer[i].Front(); if (flit.flit_type==FLIT_TYPE_HEAD) { // prepare data for routing TRouteData route_data; route_data.current_id = local_id; route_data.src_id = flit.src_id; route_data.dst_id = flit.dst_id; route_data.dir_in = i; int o = route(route_data); if (reservation_table.isAvailable(o)) { reservation_table.reserve(i, o); if(TGlobalParams::verbose_mode > VERBOSE_OFF) { cout << sc_time_stamp().to_double()/1000 << ": Router[" << local_id << "], Input[" << i << "] (" << buffer[i].Size() << " flits)" << ", reserved Output[" << o << "], flit: " << flit << endl; } } } } } start_from_port++; // 2nd phase: Forwarding for(int i=0; i<DIRECTIONS+1; i++) { if ( !buffer[i].IsEmpty() ) { TFlit flit = buffer[i].Front(); int o = reservation_table.getOutputPort(i); if (o != NOT_RESERVED) { if ( current_level_tx[o] == ack_tx[o].read() ) { if(TGlobalParams::verbose_mode > VERBOSE_OFF) { cout << sc_time_stamp().to_double()/1000 << ": Router[" << local_id << "], Input[" << i << "] forward to Output[" << o << "], flit: " << flit << endl; } flit_tx[o].write(flit); current_level_tx[o] = 1 - current_level_tx[o]; req_tx[o].write(current_level_tx[o]); buffer[i].Pop(); stats.power.Forward(); if (flit.flit_type == FLIT_TYPE_TAIL) reservation_table.release(o); // Update stats if (o == DIRECTION_LOCAL) { stats.receivedFlit(sc_time_stamp().to_double()/1000, flit); if (TGlobalParams::max_volume_to_be_drained) { if (drained_volume >= TGlobalParams::max_volume_to_be_drained) sc_stop(); else { drained_volume++; local_drained++; } } } else if (i != DIRECTION_LOCAL) { // Increment routed flits counter routed_flits++; } } } } } } // else stats.power.Standby();}//---------------------------------------------------------------------------TNoP_data TRouter::getCurrentNoPData() const { TNoP_data NoP_data; for (int j=0; j<DIRECTIONS; j++) { NoP_data.channel_status_neighbor[j].free_slots = free_slots_neighbor[j].read(); NoP_data.channel_status_neighbor[j].available = (reservation_table.isAvailable(j)); } NoP_data.sender_id = local_id; return NoP_data;}//---------------------------------------------------------------------------void TRouter::bufferMonitor(){ if (reset.read()) { for (int i=0; i<DIRECTIONS+1; i++) free_slots[i].write(buffer[i].GetMaxBufferSize()); } else { if (TGlobalParams::selection_strategy==SEL_BUFFER_LEVEL || TGlobalParams::selection_strategy==SEL_NOP) { // update current input buffers level to neighbors for (int i=0; i<DIRECTIONS+1; i++) free_slots[i].write(buffer[i].getCurrentFreeSlots()); // NoP selection: send neighbor info to each direction 'i' TNoP_data current_NoP_data = getCurrentNoPData(); for (int i=0; i<DIRECTIONS; i++) NoP_data_out[i].write(current_NoP_data); if (TGlobalParams::verbose_mode == -57) NoP_report(); } }}//---------------------------------------------------------------------------vector<int> TRouter::routingFunction(const TRouteData& route_data) { TCoord position = id2Coord(route_data.current_id); TCoord src_coord = id2Coord(route_data.src_id); TCoord dst_coord = id2Coord(route_data.dst_id); int dir_in = route_data.dir_in; switch (TGlobalParams::routing_algorithm) { case ROUTING_XY: return routingXY(position, dst_coord); case ROUTING_WEST_FIRST: return routingWestFirst(position, dst_coord); case ROUTING_NORTH_LAST: return routingNorthLast(position, dst_coord); case ROUTING_NEGATIVE_FIRST: return routingNegativeFirst(position, dst_coord); case ROUTING_ODD_EVEN: return routingOddEven(position, src_coord, dst_coord); case ROUTING_DYAD: return routingDyAD(position, src_coord, dst_coord); case ROUTING_FULLY_ADAPTIVE: return routingFullyAdaptive(position, dst_coord); case ROUTING_TABLE_BASED: return routingTableBased(dir_in, position, dst_coord); default: assert(false); } // something weird happened, you shouldn't be here return (vector<int>)(0);}//---------------------------------------------------------------------------int TRouter::route(const TRouteData& route_data){ stats.power.Routing(); if (route_data.dst_id == local_id) return DIRECTION_LOCAL; vector<int> candidate_channels = routingFunction(route_data); return selectionFunction(candidate_channels,route_data);}//---------------------------------------------------------------------------void TRouter::NoP_report() const{ TNoP_data NoP_tmp; cout << sc_time_stamp().to_double()/1000 << ": Router[" << local_id << "] NoP report: " << endl; for (int i=0;i<DIRECTIONS; i++) { NoP_tmp = NoP_data_in[i].read(); if (NoP_tmp.sender_id!=NOT_VALID) cout << NoP_tmp; }}//---------------------------------------------------------------------------int TRouter::NoPScore(const TNoP_data& nop_data, const vector<int>& nop_channels) const{ int score = 0; if (TGlobalParams::verbose_mode==-58) { cout << nop_data; cout << " On-Path channels: " << endl; } for (unsigned int i=0;i<nop_channels.size();i++) { int available; if (nop_data.channel_status_neighbor[nop_channels[i]].available) available = 1; else available = 0; int free_slots = nop_data.channel_status_neighbor[nop_channels[i]].free_slots; if (TGlobalParams::verbose_mode==-58) { cout << " channel " << nop_channels[i] << " -> score: "; cout << " + " << available << " * (" << free_slots << ")" << endl; } score += available*free_slots; } return score;}//---------------------------------------------------------------------------int TRouter::selectionNoP(const vector<int>& directions, const TRouteData& route_data){ vector<int> neighbors_on_path; vector<int> score; int direction_selected = NOT_VALID; int current_id = route_data.current_id; if (TGlobalParams::verbose_mode==-58) { cout << endl; cout << sc_time_stamp().to_double()/1000 << ": Router[" << local_id << "] NoP SELECTION ----------------" << endl; cout << " Packet: " << route_data.src_id << " --> " << route_data.dst_id << endl; } for (uint i=0; i<directions.size(); i++) { // get id of adjacent candidate int candidate_id = getNeighborId(current_id,directions[i]); // apply routing function to the adjacent candidate node TRouteData tmp_route_data; tmp_route_data.current_id = candidate_id; tmp_route_data.src_id = route_data.src_id; tmp_route_data.dst_id = route_data.dst_id; tmp_route_data.dir_in = reflexDirection(directions[i]); if (TGlobalParams::verbose_mode==-58) { cout << "\n -> Adjacent candidate: " << candidate_id << " (direction " << directions[i] << ")" << endl; } vector<int> next_candidate_channels = routingFunction(tmp_route_data); // select useful data from Neighbor-on-Path input TNoP_data nop_tmp = NoP_data_in[directions[i]].read(); // store the score of node in the direction[i] score.push_back(NoPScore(nop_tmp,next_candidate_channels)); } // check for direction with higher score int max_direction = directions[0]; int max = score[0]; for (unsigned int i = 0;i<directions.size();i++) { if (score[i]>max) { max_direction = directions[i]; max = score[i]; } } // if multiple direction have the same score = max, choose randomly. vector<int> equivalent_directions; for (unsigned int i = 0;i<directions.size();i++) if (score[i]==max) equivalent_directions.push_back(directions[i]); direction_selected = equivalent_directions[rand() % equivalent_directions.size()]; if (TGlobalParams::verbose_mode==-58) { if (equivalent_directions.size()>1) { cout << "\n equivalent directions found! : "; for (unsigned int i =0;i<equivalent_directions.size();i++) cout << " " << equivalent_directions[i]; } cout << "\n CHOICE: node " << getNeighborId(current_id,direction_selected) << " (direction " << direction_selected << ")" << endl; } return direction_selected; }//---------------------------------------------------------------------------int TRouter::selectionBufferLevel(const vector<int>& directions){ vector<int> best_dirs; int max_free_slots = 0; for (unsigned int i=0; i<directions.size(); i++) { int free_slots = free_slots_neighbor[directions[i]].read(); bool available = reservation_table.isAvailable(directions[i]); if (available) { if (free_slots > max_free_slots) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -