SimpleNetwork.cc revision 8485:7a9a7f2a3d46
1/* 2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <cassert> 30#include <numeric> 31 32#include "base/stl_helpers.hh" 33#include "mem/protocol/MachineType.hh" 34#include "mem/protocol/TopologyType.hh" 35#include "mem/ruby/buffers/MessageBuffer.hh" 36#include "mem/ruby/common/NetDest.hh" 37#include "mem/ruby/network/BasicLink.hh" 38#include "mem/ruby/network/simple/SimpleLink.hh" 39#include "mem/ruby/network/simple/SimpleNetwork.hh" 40#include "mem/ruby/network/simple/Switch.hh" 41#include "mem/ruby/network/simple/Throttle.hh" 42#include "mem/ruby/network/Topology.hh" 43#include "mem/ruby/profiler/Profiler.hh" 44#include "mem/ruby/system/System.hh" 45 46using namespace std; 47using m5::stl_helpers::deletePointers; 48 49#if 0 50// ***BIG HACK*** - This is actually code that _should_ be in Network.cc 51 52// Note: Moved to Princeton Network 53// calls new to abstract away from the network 54Network* 55Network::createNetwork(int nodes) 56{ 57 return new SimpleNetwork(nodes); 58} 59#endif 60 61SimpleNetwork::SimpleNetwork(const Params *p) 62 : Network(p) 63{ 64 m_buffer_size = p->buffer_size; 65 m_endpoint_bandwidth = p->endpoint_bandwidth; 66 m_adaptive_routing = p->adaptive_routing; 67 68 // Note: the parent Network Object constructor is called before the 69 // SimpleNetwork child constructor. Therefore, the member variables 70 // used below should already be initialized. 71 72 m_endpoint_switches.resize(m_nodes); 73 74 m_in_use.resize(m_virtual_networks); 75 m_ordered.resize(m_virtual_networks); 76 for (int i = 0; i < m_virtual_networks; i++) { 77 m_in_use[i] = false; 78 m_ordered[i] = false; 79 } 80 81 // Allocate to and from queues 82 m_toNetQueues.resize(m_nodes); 83 m_fromNetQueues.resize(m_nodes); 84 for (int node = 0; node < m_nodes; node++) { 85 m_toNetQueues[node].resize(m_virtual_networks); 86 m_fromNetQueues[node].resize(m_virtual_networks); 87 for (int j = 0; j < m_virtual_networks; j++) { 88 m_toNetQueues[node][j] = 89 new MessageBuffer(csprintf("toNet node %d j %d", node, j)); 90 m_fromNetQueues[node][j] = 91 new MessageBuffer(csprintf("fromNet node %d j %d", node, j)); 92 } 93 } 94} 95 96void 97SimpleNetwork::init() 98{ 99 Network::init(); 100 101 // The topology pointer should have already been initialized in 102 // the parent class network constructor. 103 assert(m_topology_ptr != NULL); 104 int number_of_switches = m_topology_ptr->numSwitches(); 105 for (int i = 0; i < number_of_switches; i++) { 106 m_switch_ptr_vector.push_back(new Switch(i, this)); 107 } 108 109 // false because this isn't a reconfiguration 110 m_topology_ptr->createLinks(this, false); 111} 112 113void 114SimpleNetwork::reset() 115{ 116 for (int node = 0; node < m_nodes; node++) { 117 for (int j = 0; j < m_virtual_networks; j++) { 118 m_toNetQueues[node][j]->clear(); 119 m_fromNetQueues[node][j]->clear(); 120 } 121 } 122 123 for(int i = 0; i < m_switch_ptr_vector.size(); i++){ 124 m_switch_ptr_vector[i]->clearBuffers(); 125 } 126} 127 128SimpleNetwork::~SimpleNetwork() 129{ 130 for (int i = 0; i < m_nodes; i++) { 131 deletePointers(m_toNetQueues[i]); 132 deletePointers(m_fromNetQueues[i]); 133 } 134 deletePointers(m_switch_ptr_vector); 135 deletePointers(m_buffers_to_free); 136 // delete m_topology_ptr; 137} 138 139// From a switch to an endpoint node 140void 141SimpleNetwork::makeOutLink(SwitchID src, NodeID dest, BasicLink* link, 142 LinkDirection direction, 143 const NetDest& routing_table_entry, 144 bool isReconfiguration) 145{ 146 assert(dest < m_nodes); 147 assert(src < m_switch_ptr_vector.size()); 148 assert(m_switch_ptr_vector[src] != NULL); 149 150 if (isReconfiguration) { 151 m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry); 152 return; 153 } 154 155 SimpleExtLink *simple_link = safe_cast<SimpleExtLink*>(link); 156 157 m_switch_ptr_vector[src]->addOutPort(m_fromNetQueues[dest], 158 routing_table_entry, 159 simple_link->m_latency, 160 simple_link->m_bw_multiplier); 161 162 m_endpoint_switches[dest] = m_switch_ptr_vector[src]; 163} 164 165// From an endpoint node to a switch 166void 167SimpleNetwork::makeInLink(NodeID src, SwitchID dest, BasicLink* link, 168 LinkDirection direction, 169 const NetDest& routing_table_entry, 170 bool isReconfiguration) 171{ 172 assert(src < m_nodes); 173 if (isReconfiguration) { 174 // do nothing 175 return; 176 } 177 178 m_switch_ptr_vector[dest]->addInPort(m_toNetQueues[src]); 179} 180 181// From a switch to a switch 182void 183SimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link, 184 LinkDirection direction, 185 const NetDest& routing_table_entry, 186 bool isReconfiguration) 187{ 188 if (isReconfiguration) { 189 m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry); 190 return; 191 } 192 193 // Create a set of new MessageBuffers 194 std::vector<MessageBuffer*> queues; 195 for (int i = 0; i < m_virtual_networks; i++) { 196 // allocate a buffer 197 MessageBuffer* buffer_ptr = new MessageBuffer; 198 buffer_ptr->setOrdering(true); 199 if (m_buffer_size > 0) { 200 buffer_ptr->resize(m_buffer_size); 201 } 202 queues.push_back(buffer_ptr); 203 // remember to deallocate it 204 m_buffers_to_free.push_back(buffer_ptr); 205 } 206 // Connect it to the two switches 207 SimpleIntLink *simple_link = safe_cast<SimpleIntLink*>(link); 208 209 m_switch_ptr_vector[dest]->addInPort(queues); 210 m_switch_ptr_vector[src]->addOutPort(queues, routing_table_entry, 211 simple_link->m_latency, 212 simple_link->m_bw_multiplier); 213} 214 215void 216SimpleNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num) 217{ 218 assert(id < m_nodes); 219 assert(network_num < m_virtual_networks); 220 221 if (ordered) { 222 m_ordered[network_num] = true; 223 } 224 m_in_use[network_num] = true; 225} 226 227MessageBuffer* 228SimpleNetwork::getToNetQueue(NodeID id, bool ordered, int network_num, 229 std::string vnet_type) 230{ 231 checkNetworkAllocation(id, ordered, network_num); 232 return m_toNetQueues[id][network_num]; 233} 234 235MessageBuffer* 236SimpleNetwork::getFromNetQueue(NodeID id, bool ordered, int network_num, 237 std::string vnet_type) 238{ 239 checkNetworkAllocation(id, ordered, network_num); 240 return m_fromNetQueues[id][network_num]; 241} 242 243const std::vector<Throttle*>* 244SimpleNetwork::getThrottles(NodeID id) const 245{ 246 assert(id >= 0); 247 assert(id < m_nodes); 248 assert(m_endpoint_switches[id] != NULL); 249 return m_endpoint_switches[id]->getThrottles(); 250} 251 252void 253SimpleNetwork::printStats(ostream& out) const 254{ 255 out << endl; 256 out << "Network Stats" << endl; 257 out << "-------------" << endl; 258 out << endl; 259 260 // 261 // Determine total counts before printing out each switch's stats 262 // 263 std::vector<uint64> total_msg_counts; 264 total_msg_counts.resize(MessageSizeType_NUM); 265 for (MessageSizeType type = MessageSizeType_FIRST; 266 type < MessageSizeType_NUM; 267 ++type) { 268 total_msg_counts[type] = 0; 269 } 270 271 for (int i = 0; i < m_switch_ptr_vector.size(); i++) { 272 const std::vector<Throttle*>* throttles = 273 m_switch_ptr_vector[i]->getThrottles(); 274 275 for (int p = 0; p < throttles->size(); p++) { 276 277 const std::vector<std::vector<int> >& message_counts = 278 ((*throttles)[p])->getCounters(); 279 280 for (MessageSizeType type = MessageSizeType_FIRST; 281 type < MessageSizeType_NUM; 282 ++type) { 283 284 const std::vector<int> &mct = message_counts[type]; 285 int sum = accumulate(mct.begin(), mct.end(), 0); 286 total_msg_counts[type] += uint64(sum); 287 } 288 } 289 } 290 uint64 total_msgs = 0; 291 uint64 total_bytes = 0; 292 for (MessageSizeType type = MessageSizeType_FIRST; 293 type < MessageSizeType_NUM; 294 ++type) { 295 296 if (total_msg_counts[type] > 0) { 297 out << "total_msg_count_" << type << ": " << total_msg_counts[type] 298 << " " << total_msg_counts[type] * 299 uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type)) 300 << endl; 301 302 total_msgs += total_msg_counts[type]; 303 304 total_bytes += total_msg_counts[type] * 305 uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type)); 306 307 } 308 } 309 310 out << "total_msgs: " << total_msgs 311 << " total_bytes: " << total_bytes << endl; 312 313 out << endl; 314 for (int i = 0; i < m_switch_ptr_vector.size(); i++) { 315 m_switch_ptr_vector[i]->printStats(out); 316 } 317 m_topology_ptr->printStats(out); 318} 319 320void 321SimpleNetwork::clearStats() 322{ 323 for (int i = 0; i < m_switch_ptr_vector.size(); i++) { 324 m_switch_ptr_vector[i]->clearStats(); 325 } 326 m_topology_ptr->clearStats(); 327} 328 329void 330SimpleNetwork::printConfig(ostream& out) const 331{ 332 out << endl; 333 out << "Network Configuration" << endl; 334 out << "---------------------" << endl; 335 out << "network: SIMPLE_NETWORK" << endl; 336 out << "topology: " << m_topology_ptr->getName() << endl; 337 out << endl; 338 339 for (int i = 0; i < m_virtual_networks; i++) { 340 out << "virtual_net_" << i << ": "; 341 if (m_in_use[i]) { 342 out << "active, "; 343 if (m_ordered[i]) { 344 out << "ordered" << endl; 345 } else { 346 out << "unordered" << endl; 347 } 348 } else { 349 out << "inactive" << endl; 350 } 351 } 352 out << endl; 353 354 for(int i = 0; i < m_switch_ptr_vector.size(); i++) { 355 m_switch_ptr_vector[i]->printConfig(out); 356 } 357 358 m_topology_ptr->printConfig(out); 359} 360 361void 362SimpleNetwork::print(ostream& out) const 363{ 364 out << "[SimpleNetwork]"; 365} 366 367 368SimpleNetwork * 369SimpleNetworkParams::create() 370{ 371 return new SimpleNetwork(this); 372} 373