Switch.cc revision 7454
11689SN/A/* 22329SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 291689SN/A#include <numeric> 301689SN/A 311858SN/A#include "base/stl_helpers.hh" 321717SN/A#include "mem/protocol/MessageSizeType.hh" 331060SN/A#include "mem/protocol/Protocol.hh" 342292SN/A#include "mem/ruby/buffers/MessageBuffer.hh" 352292SN/A#include "mem/ruby/network/Network.hh" 361061SN/A#include "mem/ruby/network/simple/PerfectSwitch.hh" 372292SN/A#include "mem/ruby/network/simple/Switch.hh" 382292SN/A#include "mem/ruby/network/simple/Throttle.hh" 392292SN/A 401060SN/Ausing namespace std; 411060SN/Ausing m5::stl_helpers::deletePointers; 421060SN/Ausing m5::stl_helpers::operator<<; 432292SN/A 442292SN/ASwitch::Switch(SwitchID sid, SimpleNetwork* network_ptr) 451060SN/A{ 462292SN/A m_perfect_switch_ptr = new PerfectSwitch(sid, network_ptr); 472292SN/A m_switch_id = sid; 482292SN/A} 492292SN/A 502292SN/ASwitch::~Switch() 512292SN/A{ 522292SN/A delete m_perfect_switch_ptr; 532292SN/A 542292SN/A // Delete throttles (one per output port) 552292SN/A deletePointers(m_throttles); 562292SN/A 572292SN/A // Delete MessageBuffers 582292SN/A deletePointers(m_buffers_to_free); 592292SN/A} 602292SN/A 612292SN/Avoid 622292SN/ASwitch::addInPort(const vector<MessageBuffer*>& in) 632292SN/A{ 642292SN/A m_perfect_switch_ptr->addInPort(in); 652292SN/A} 662292SN/A 672292SN/Avoid 682292SN/ASwitch::addOutPort(const vector<MessageBuffer*>& out, 692292SN/A const NetDest& routing_table_entry, int link_latency, int bw_multiplier) 702292SN/A{ 712292SN/A Throttle* throttle_ptr = NULL; 722292SN/A 732292SN/A // Create a throttle 742292SN/A throttle_ptr = new Throttle(m_switch_id, m_throttles.size(), link_latency, 752292SN/A bw_multiplier); 762292SN/A m_throttles.push_back(throttle_ptr); 772292SN/A 782292SN/A // Create one buffer per vnet (these are intermediaryQueues) 792292SN/A vector<MessageBuffer*> intermediateBuffers; 802292SN/A for (int i = 0; i < out.size(); i++) { 812292SN/A MessageBuffer* buffer_ptr = new MessageBuffer; 822292SN/A // Make these queues ordered 832292SN/A buffer_ptr->setOrdering(true); 842292SN/A Network* net_ptr = RubySystem::getNetwork(); 852292SN/A if (net_ptr->getBufferSize() > 0) { 862292SN/A buffer_ptr->resize(net_ptr->getBufferSize()); 872292SN/A } 882292SN/A intermediateBuffers.push_back(buffer_ptr); 892292SN/A m_buffers_to_free.push_back(buffer_ptr); 902292SN/A } 912292SN/A 922292SN/A // Hook the queues to the PerfectSwitch 932292SN/A m_perfect_switch_ptr->addOutPort(intermediateBuffers, routing_table_entry); 942292SN/A 952292SN/A // Hook the queues to the Throttle 962292SN/A throttle_ptr->addLinks(intermediateBuffers, out); 972292SN/A} 982292SN/A 991060SN/Avoid 1001060SN/ASwitch::clearRoutingTables() 1011061SN/A{ 1021060SN/A m_perfect_switch_ptr->clearRoutingTables(); 1032733Sktlim@umich.edu} 1041060SN/A 1051060SN/Avoid 1061060SN/ASwitch::clearBuffers() 1072292SN/A{ 1082292SN/A m_perfect_switch_ptr->clearBuffers(); 1092292SN/A for (int i = 0; i < m_throttles.size(); i++) { 1102292SN/A if (m_throttles[i] != NULL) { 1111060SN/A m_throttles[i]->clear(); 1122292SN/A } 1132292SN/A } 1142292SN/A} 1152292SN/A 1162292SN/Avoid 1172292SN/ASwitch::reconfigureOutPort(const NetDest& routing_table_entry) 1182292SN/A{ 1192292SN/A m_perfect_switch_ptr->reconfigureOutPort(routing_table_entry); 1202292SN/A} 1212292SN/A 1222292SN/Aconst Throttle* 1232292SN/ASwitch::getThrottle(LinkID link_number) const 1242292SN/A{ 1252292SN/A assert(m_throttles[link_number] != NULL); 1262307SN/A return m_throttles[link_number]; 1272307SN/A} 1282307SN/A 1292307SN/Aconst vector<Throttle*>* 1302307SN/ASwitch::getThrottles() const 1312307SN/A{ 1322307SN/A return &m_throttles; 1332307SN/A} 1342307SN/A 1352307SN/Avoid 1362307SN/ASwitch::printStats(std::ostream& out) const 1372307SN/A{ 1382307SN/A ccprintf(out, "switch_%d_inlinks: %d\n", m_switch_id, 1392307SN/A m_perfect_switch_ptr->getInLinks()); 1402307SN/A ccprintf(out, "switch_%d_outlinks: %d\n", m_switch_id, 1412307SN/A m_perfect_switch_ptr->getOutLinks()); 1422307SN/A 1432307SN/A // Average link utilizations 1442307SN/A double average_utilization = 0.0; 1452307SN/A int throttle_count = 0; 1462307SN/A 1472307SN/A for (int i = 0; i < m_throttles.size(); i++) { 1482307SN/A Throttle* throttle_ptr = m_throttles[i]; 1492307SN/A if (throttle_ptr) { 1502307SN/A average_utilization += throttle_ptr->getUtilization(); 1512292SN/A throttle_count++; 1522292SN/A } 1532292SN/A } 1542292SN/A average_utilization = 1552292SN/A throttle_count == 0 ? 0 : average_utilization / throttle_count; 1562292SN/A 1572292SN/A // Individual link utilizations 1582292SN/A out << "links_utilized_percent_switch_" << m_switch_id << ": " 1592292SN/A << average_utilization << endl; 1602292SN/A 1612292SN/A for (int link = 0; link < m_throttles.size(); link++) { 1622292SN/A Throttle* throttle_ptr = m_throttles[link]; 1632292SN/A if (throttle_ptr != NULL) { 1642292SN/A out << " links_utilized_percent_switch_" << m_switch_id 1652292SN/A << "_link_" << link << ": " 1662292SN/A << throttle_ptr->getUtilization() << " bw: " 1672292SN/A << throttle_ptr->getLinkBandwidth() 1682292SN/A << " base_latency: " << throttle_ptr->getLatency() << endl; 1692292SN/A } 1702292SN/A } 1712292SN/A out << endl; 1722292SN/A 1732292SN/A // Traffic breakdown 1742292SN/A for (int link = 0; link < m_throttles.size(); link++) { 1752292SN/A Throttle* throttle_ptr = m_throttles[link]; 1762292SN/A if (!throttle_ptr) 1772292SN/A continue; 1782292SN/A 1792292SN/A const vector<vector<int> >& message_counts = 1802292SN/A throttle_ptr->getCounters(); 1811060SN/A for (int int_type = 0; int_type < MessageSizeType_NUM; int_type++) { 1821060SN/A MessageSizeType type = MessageSizeType(int_type); 1831061SN/A const vector<int> &mct = message_counts[type]; 1841060SN/A int sum = accumulate(mct.begin(), mct.end(), 0); 1851060SN/A if (sum == 0) 1861060SN/A continue; 1872292SN/A 1881061SN/A out << " outgoing_messages_switch_" << m_switch_id 1892292SN/A << "_link_" << link << "_" << type << ": " << sum << " " 1902292SN/A << sum * RubySystem::getNetwork()->MessageSizeType_to_int(type) 1911060SN/A << " "; 1922292SN/A out << mct; 1932292SN/A out << " base_latency: " 1941060SN/A << throttle_ptr->getLatency() << endl; 1952292SN/A } 1962292SN/A } 1972292SN/A out << endl; 1982292SN/A} 1992292SN/A 2001060SN/Avoid 2011060SN/ASwitch::clearStats() 2021061SN/A{ 2031060SN/A m_perfect_switch_ptr->clearStats(); 2041061SN/A for (int i = 0; i < m_throttles.size(); i++) { 2051060SN/A if (m_throttles[i] != NULL) 2062292SN/A m_throttles[i]->clearStats(); 2071060SN/A } 2081060SN/A} 2092292SN/A 2101060SN/Avoid 2111060SN/ASwitch::printConfig(std::ostream& out) const 2121060SN/A{ 2132292SN/A m_perfect_switch_ptr->printConfig(out); 2141060SN/A for (int i = 0; i < m_throttles.size(); i++) { 2152292SN/A if (m_throttles[i] != NULL) 2162292SN/A m_throttles[i]->printConfig(out); 2172292SN/A } 2182292SN/A} 2192292SN/A 2202292SN/Avoid 2211060SN/ASwitch::print(std::ostream& out) const 2221060SN/A{ 2232292SN/A // FIXME printing 2242292SN/A out << "[Switch]"; 2252292SN/A} 2262292SN/A 2272292SN/A