1/* 2 * Copyright (c) 2008 Princeton University 3 * Copyright (c) 2016 Georgia Institute of Technology 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Niket Agarwal 30 * Tushar Krishna 31 */ 32 33 34#include "mem/ruby/network/garnet2.0/Router.hh" 35 36#include "base/stl_helpers.hh" 37#include "debug/RubyNetwork.hh" 38#include "mem/ruby/network/garnet2.0/CreditLink.hh" 39#include "mem/ruby/network/garnet2.0/CrossbarSwitch.hh" 40#include "mem/ruby/network/garnet2.0/GarnetNetwork.hh" 41#include "mem/ruby/network/garnet2.0/InputUnit.hh" 42#include "mem/ruby/network/garnet2.0/NetworkLink.hh" 43#include "mem/ruby/network/garnet2.0/OutputUnit.hh" 44#include "mem/ruby/network/garnet2.0/RoutingUnit.hh" 45#include "mem/ruby/network/garnet2.0/SwitchAllocator.hh" 46 47using namespace std; 48using m5::stl_helpers::deletePointers; 49 50Router::Router(const Params *p) 51 : BasicRouter(p), Consumer(this) 52{ 53 m_latency = p->latency; 54 m_virtual_networks = p->virt_nets; 55 m_vc_per_vnet = p->vcs_per_vnet; 56 m_num_vcs = m_virtual_networks * m_vc_per_vnet; 57 58 m_routing_unit = new RoutingUnit(this); 59 m_sw_alloc = new SwitchAllocator(this); 60 m_switch = new CrossbarSwitch(this); 61 62 m_input_unit.clear(); 63 m_output_unit.clear(); 64} 65 66Router::~Router() 67{ 68 deletePointers(m_input_unit); 69 deletePointers(m_output_unit); 70 delete m_routing_unit; 71 delete m_sw_alloc; 72 delete m_switch; 73} 74 75void 76Router::init() 77{ 78 BasicRouter::init(); 79 80 m_sw_alloc->init(); 81 m_switch->init(); 82} 83 84void 85Router::wakeup() 86{ 87 DPRINTF(RubyNetwork, "Router %d woke up\n", m_id); 88 89 // check for incoming flits 90 for (int inport = 0; inport < m_input_unit.size(); inport++) { 91 m_input_unit[inport]->wakeup(); 92 } 93 94 // check for incoming credits 95 // Note: the credit update is happening before SA 96 // buffer turnaround time = 97 // credit traversal (1-cycle) + SA (1-cycle) + Link Traversal (1-cycle) 98 // if we want the credit update to take place after SA, this loop should 99 // be moved after the SA request 100 for (int outport = 0; outport < m_output_unit.size(); outport++) { 101 m_output_unit[outport]->wakeup(); 102 } 103 104 // Switch Allocation 105 m_sw_alloc->wakeup(); 106 107 // Switch Traversal 108 m_switch->wakeup(); 109} 110 111void 112Router::addInPort(PortDirection inport_dirn, 113 NetworkLink *in_link, CreditLink *credit_link) 114{ 115 int port_num = m_input_unit.size(); 116 InputUnit *input_unit = new InputUnit(port_num, inport_dirn, this); 117 118 input_unit->set_in_link(in_link); 119 input_unit->set_credit_link(credit_link); 120 in_link->setLinkConsumer(this); 121 credit_link->setSourceQueue(input_unit->getCreditQueue()); 122 123 m_input_unit.push_back(input_unit); 124 125 m_routing_unit->addInDirection(inport_dirn, port_num); 126} 127 128void 129Router::addOutPort(PortDirection outport_dirn, 130 NetworkLink *out_link, 131 const NetDest& routing_table_entry, int link_weight, 132 CreditLink *credit_link) 133{ 134 int port_num = m_output_unit.size(); 135 OutputUnit *output_unit = new OutputUnit(port_num, outport_dirn, this); 136 137 output_unit->set_out_link(out_link); 138 output_unit->set_credit_link(credit_link); 139 credit_link->setLinkConsumer(this); 140 out_link->setSourceQueue(output_unit->getOutQueue()); 141 142 m_output_unit.push_back(output_unit); 143 144 m_routing_unit->addRoute(routing_table_entry); 145 m_routing_unit->addWeight(link_weight); 146 m_routing_unit->addOutDirection(outport_dirn, port_num); 147} 148 149PortDirection 150Router::getOutportDirection(int outport) 151{ 152 return m_output_unit[outport]->get_direction(); 153} 154 155PortDirection 156Router::getInportDirection(int inport) 157{ 158 return m_input_unit[inport]->get_direction(); 159} 160 161int 162Router::route_compute(RouteInfo route, int inport, PortDirection inport_dirn) 163{ 164 return m_routing_unit->outportCompute(route, inport, inport_dirn); 165} 166 167void 168Router::grant_switch(int inport, flit *t_flit) 169{ 170 m_switch->update_sw_winner(inport, t_flit); 171} 172 173void 174Router::schedule_wakeup(Cycles time) 175{ 176 // wake up after time cycles 177 scheduleEvent(time); 178} 179 180std::string 181Router::getPortDirectionName(PortDirection direction) 182{ 183 // PortDirection is actually a string 184 // If not, then this function should add a switch 185 // statement to convert direction to a string 186 // that can be printed out 187 return direction; 188} 189 190void 191Router::regStats() 192{ 193 BasicRouter::regStats(); 194 195 m_buffer_reads 196 .name(name() + ".buffer_reads") 197 .flags(Stats::nozero) 198 ; 199 200 m_buffer_writes 201 .name(name() + ".buffer_writes") 202 .flags(Stats::nozero) 203 ; 204 205 m_crossbar_activity 206 .name(name() + ".crossbar_activity") 207 .flags(Stats::nozero) 208 ; 209 210 m_sw_input_arbiter_activity 211 .name(name() + ".sw_input_arbiter_activity") 212 .flags(Stats::nozero) 213 ; 214 215 m_sw_output_arbiter_activity 216 .name(name() + ".sw_output_arbiter_activity") 217 .flags(Stats::nozero) 218 ; 219} 220 221void 222Router::collateStats() 223{ 224 for (int j = 0; j < m_virtual_networks; j++) { 225 for (int i = 0; i < m_input_unit.size(); i++) { 226 m_buffer_reads += m_input_unit[i]->get_buf_read_activity(j); 227 m_buffer_writes += m_input_unit[i]->get_buf_write_activity(j); 228 } 229 } 230 231 m_sw_input_arbiter_activity = m_sw_alloc->get_input_arbiter_activity(); 232 m_sw_output_arbiter_activity = m_sw_alloc->get_output_arbiter_activity(); 233 m_crossbar_activity = m_switch->get_crossbar_activity(); 234} 235 236void 237Router::resetStats() 238{ 239 for (int j = 0; j < m_virtual_networks; j++) { 240 for (int i = 0; i < m_input_unit.size(); i++) { 241 m_input_unit[i]->resetStats(); 242 } 243 } 244 245 m_switch->resetStats(); 246 m_sw_alloc->resetStats(); 247} 248 249void 250Router::printFaultVector(ostream& out) 251{ 252 int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS; 253 int num_fault_types = m_network_ptr->fault_model->number_of_fault_types; 254 float fault_vector[num_fault_types]; 255 get_fault_vector(temperature_celcius, fault_vector); 256 out << "Router-" << m_id << " fault vector: " << endl; 257 for (int fault_type_index = 0; fault_type_index < num_fault_types; 258 fault_type_index++) { 259 out << " - probability of ("; 260 out << 261 m_network_ptr->fault_model->fault_type_to_string(fault_type_index); 262 out << ") = "; 263 out << fault_vector[fault_type_index] << endl; 264 } 265} 266 267void 268Router::printAggregateFaultProbability(std::ostream& out) 269{ 270 int temperature_celcius = BASELINE_TEMPERATURE_CELCIUS; 271 float aggregate_fault_prob; 272 get_aggregate_fault_probability(temperature_celcius, 273 &aggregate_fault_prob); 274 out << "Router-" << m_id << " fault probability: "; 275 out << aggregate_fault_prob << endl; 276} 277 278uint32_t 279Router::functionalWrite(Packet *pkt) 280{ 281 uint32_t num_functional_writes = 0; 282 num_functional_writes += m_switch->functionalWrite(pkt); 283 284 for (uint32_t i = 0; i < m_input_unit.size(); i++) { 285 num_functional_writes += m_input_unit[i]->functionalWrite(pkt); 286 } 287 288 for (uint32_t i = 0; i < m_output_unit.size(); i++) { 289 num_functional_writes += m_output_unit[i]->functionalWrite(pkt); 290 } 291 292 return num_functional_writes; 293} 294 295Router * 296GarnetRouterParams::create() 297{ 298 return new Router(this); 299} 300