Switch.cc revision 6285
16145Snate@binkert.org 26145Snate@binkert.org/* 36145Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 46145Snate@binkert.org * All rights reserved. 56145Snate@binkert.org * 66145Snate@binkert.org * Redistribution and use in source and binary forms, with or without 76145Snate@binkert.org * modification, are permitted provided that the following conditions are 86145Snate@binkert.org * met: redistributions of source code must retain the above copyright 96145Snate@binkert.org * notice, this list of conditions and the following disclaimer; 106145Snate@binkert.org * redistributions in binary form must reproduce the above copyright 116145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 126145Snate@binkert.org * documentation and/or other materials provided with the distribution; 136145Snate@binkert.org * neither the name of the copyright holders nor the names of its 146145Snate@binkert.org * contributors may be used to endorse or promote products derived from 156145Snate@binkert.org * this software without specific prior written permission. 166145Snate@binkert.org * 176145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286145Snate@binkert.org */ 296145Snate@binkert.org 306145Snate@binkert.org/* 316284Snate@binkert.org * Switch.cc 326145Snate@binkert.org * 336284Snate@binkert.org * Description: See Switch.hh 346145Snate@binkert.org * 356145Snate@binkert.org * $Id$ 366145Snate@binkert.org * 376145Snate@binkert.org */ 386145Snate@binkert.org 396145Snate@binkert.org 406154Snate@binkert.org#include "mem/ruby/network/simple/Switch.hh" 416154Snate@binkert.org#include "mem/ruby/network/simple/PerfectSwitch.hh" 426154Snate@binkert.org#include "mem/ruby/buffers/MessageBuffer.hh" 436154Snate@binkert.org#include "mem/ruby/network/simple/Throttle.hh" 446154Snate@binkert.org#include "mem/protocol/MessageSizeType.hh" 456154Snate@binkert.org#include "mem/ruby/network/Network.hh" 466154Snate@binkert.org#include "mem/protocol/Protocol.hh" 476145Snate@binkert.org 486145Snate@binkert.orgSwitch::Switch(SwitchID sid, SimpleNetwork* network_ptr) 496145Snate@binkert.org{ 506145Snate@binkert.org m_perfect_switch_ptr = new PerfectSwitch(sid, network_ptr); 516145Snate@binkert.org m_switch_id = sid; 526145Snate@binkert.org m_throttles.setSize(0); 536145Snate@binkert.org} 546145Snate@binkert.org 556145Snate@binkert.orgSwitch::~Switch() 566145Snate@binkert.org{ 576145Snate@binkert.org delete m_perfect_switch_ptr; 586145Snate@binkert.org 596145Snate@binkert.org // Delete throttles (one per output port) 606145Snate@binkert.org m_throttles.deletePointers(); 616145Snate@binkert.org 626145Snate@binkert.org // Delete MessageBuffers 636145Snate@binkert.org m_buffers_to_free.deletePointers(); 646145Snate@binkert.org} 656145Snate@binkert.org 666145Snate@binkert.orgvoid Switch::addInPort(const Vector<MessageBuffer*>& in) 676145Snate@binkert.org{ 686145Snate@binkert.org m_perfect_switch_ptr->addInPort(in); 696145Snate@binkert.org} 706145Snate@binkert.org 716145Snate@binkert.orgvoid Switch::addOutPort(const Vector<MessageBuffer*>& out, const NetDest& routing_table_entry, int link_latency, int bw_multiplier) 726145Snate@binkert.org{ 736145Snate@binkert.org Throttle* throttle_ptr = NULL; 746145Snate@binkert.org 756145Snate@binkert.org // Create a throttle 766145Snate@binkert.org throttle_ptr = new Throttle(m_switch_id, m_throttles.size(), link_latency, bw_multiplier); 776145Snate@binkert.org m_throttles.insertAtBottom(throttle_ptr); 786145Snate@binkert.org 796145Snate@binkert.org // Create one buffer per vnet (these are intermediaryQueues) 806145Snate@binkert.org Vector<MessageBuffer*> intermediateBuffers; 816145Snate@binkert.org for (int i=0; i<out.size(); i++) { 826145Snate@binkert.org MessageBuffer* buffer_ptr = new MessageBuffer; 836145Snate@binkert.org // Make these queues ordered 846145Snate@binkert.org buffer_ptr->setOrdering(true); 856285Snate@binkert.org Network* net_ptr = RubySystem::getNetwork(); 866285Snate@binkert.org if(net_ptr->getBufferSize() > 0) { 876285Snate@binkert.org buffer_ptr->setSize(net_ptr->getBufferSize()); 886145Snate@binkert.org } 896145Snate@binkert.org intermediateBuffers.insertAtBottom(buffer_ptr); 906145Snate@binkert.org m_buffers_to_free.insertAtBottom(buffer_ptr); 916145Snate@binkert.org } 926145Snate@binkert.org 936145Snate@binkert.org // Hook the queues to the PerfectSwitch 946145Snate@binkert.org m_perfect_switch_ptr->addOutPort(intermediateBuffers, routing_table_entry); 956145Snate@binkert.org 966145Snate@binkert.org // Hook the queues to the Throttle 976145Snate@binkert.org throttle_ptr->addLinks(intermediateBuffers, out); 986145Snate@binkert.org 996145Snate@binkert.org} 1006145Snate@binkert.org 1016145Snate@binkert.orgvoid Switch::clearRoutingTables() 1026145Snate@binkert.org{ 1036145Snate@binkert.org m_perfect_switch_ptr->clearRoutingTables(); 1046145Snate@binkert.org} 1056145Snate@binkert.org 1066145Snate@binkert.orgvoid Switch::clearBuffers() 1076145Snate@binkert.org{ 1086145Snate@binkert.org m_perfect_switch_ptr->clearBuffers(); 1096145Snate@binkert.org for (int i=0; i<m_throttles.size(); i++) { 1106145Snate@binkert.org if (m_throttles[i] != NULL) { 1116145Snate@binkert.org m_throttles[i]->clear(); 1126145Snate@binkert.org } 1136145Snate@binkert.org } 1146145Snate@binkert.org} 1156145Snate@binkert.org 1166145Snate@binkert.orgvoid Switch::reconfigureOutPort(const NetDest& routing_table_entry) 1176145Snate@binkert.org{ 1186145Snate@binkert.org m_perfect_switch_ptr->reconfigureOutPort(routing_table_entry); 1196145Snate@binkert.org} 1206145Snate@binkert.org 1216145Snate@binkert.orgconst Throttle* Switch::getThrottle(LinkID link_number) const 1226145Snate@binkert.org{ 1236145Snate@binkert.org assert(m_throttles[link_number] != NULL); 1246145Snate@binkert.org return m_throttles[link_number]; 1256145Snate@binkert.org} 1266145Snate@binkert.org 1276145Snate@binkert.orgconst Vector<Throttle*>* Switch::getThrottles() const 1286145Snate@binkert.org{ 1296145Snate@binkert.org return &m_throttles; 1306145Snate@binkert.org} 1316145Snate@binkert.org 1326145Snate@binkert.orgvoid Switch::printStats(ostream& out) const 1336145Snate@binkert.org{ 1346145Snate@binkert.org out << "switch_" << m_switch_id << "_inlinks: " << m_perfect_switch_ptr->getInLinks() << endl; 1356145Snate@binkert.org out << "switch_" << m_switch_id << "_outlinks: " << m_perfect_switch_ptr->getOutLinks() << endl; 1366145Snate@binkert.org 1376145Snate@binkert.org // Average link utilizations 1386145Snate@binkert.org double average_utilization = 0.0; 1396145Snate@binkert.org int throttle_count = 0; 1406145Snate@binkert.org 1416145Snate@binkert.org for (int i=0; i<m_throttles.size(); i++) { 1426145Snate@binkert.org Throttle* throttle_ptr = m_throttles[i]; 1436145Snate@binkert.org if (throttle_ptr != NULL) { 1446145Snate@binkert.org average_utilization += throttle_ptr->getUtilization(); 1456145Snate@binkert.org throttle_count++; 1466145Snate@binkert.org } 1476145Snate@binkert.org } 1486145Snate@binkert.org average_utilization = (throttle_count == 0) ? 0 : average_utilization / float(throttle_count); 1496145Snate@binkert.org 1506145Snate@binkert.org // Individual link utilizations 1516145Snate@binkert.org out << "links_utilized_percent_switch_" << m_switch_id << ": " << average_utilization << endl; 1526145Snate@binkert.org for (int link=0; link<m_throttles.size(); link++) { 1536145Snate@binkert.org Throttle* throttle_ptr = m_throttles[link]; 1546145Snate@binkert.org if (throttle_ptr != NULL) { 1556145Snate@binkert.org out << " links_utilized_percent_switch_" << m_switch_id << "_link_" << link << ": " 1566145Snate@binkert.org << throttle_ptr->getUtilization() << " bw: " << throttle_ptr->getLinkBandwidth() 1576145Snate@binkert.org << " base_latency: " << throttle_ptr->getLatency() << endl; 1586145Snate@binkert.org } 1596145Snate@binkert.org } 1606145Snate@binkert.org out << endl; 1616145Snate@binkert.org 1626145Snate@binkert.org // Traffic breakdown 1636145Snate@binkert.org for (int link=0; link<m_throttles.size(); link++) { 1646145Snate@binkert.org Throttle* throttle_ptr = m_throttles[link]; 1656145Snate@binkert.org if (throttle_ptr != NULL) { 1666145Snate@binkert.org const Vector<Vector<int> >& message_counts = throttle_ptr->getCounters(); 1676145Snate@binkert.org for (int int_type=0; int_type<MessageSizeType_NUM; int_type++) { 1686145Snate@binkert.org MessageSizeType type = MessageSizeType(int_type); 1696145Snate@binkert.org int sum = message_counts[type].sum(); 1706145Snate@binkert.org if (sum != 0) { 1716145Snate@binkert.org out << " outgoing_messages_switch_" << m_switch_id << "_link_" << link << "_" << type 1726145Snate@binkert.org << ": " << sum << " " << sum * MessageSizeType_to_int(type) 1736145Snate@binkert.org << " " << message_counts[type] << " base_latency: " << throttle_ptr->getLatency() << endl; 1746145Snate@binkert.org } 1756145Snate@binkert.org } 1766145Snate@binkert.org } 1776145Snate@binkert.org } 1786145Snate@binkert.org out << endl; 1796145Snate@binkert.org} 1806145Snate@binkert.org 1816145Snate@binkert.orgvoid Switch::clearStats() 1826145Snate@binkert.org{ 1836145Snate@binkert.org m_perfect_switch_ptr->clearStats(); 1846145Snate@binkert.org for (int i=0; i<m_throttles.size(); i++) { 1856145Snate@binkert.org if (m_throttles[i] != NULL) { 1866145Snate@binkert.org m_throttles[i]->clearStats(); 1876145Snate@binkert.org } 1886145Snate@binkert.org } 1896145Snate@binkert.org} 1906145Snate@binkert.org 1916145Snate@binkert.orgvoid Switch::printConfig(ostream& out) const 1926145Snate@binkert.org{ 1936145Snate@binkert.org m_perfect_switch_ptr->printConfig(out); 1946145Snate@binkert.org for (int i=0; i<m_throttles.size(); i++) { 1956145Snate@binkert.org if (m_throttles[i] != NULL) { 1966145Snate@binkert.org m_throttles[i]->printConfig(out); 1976145Snate@binkert.org } 1986145Snate@binkert.org } 1996145Snate@binkert.org} 2006145Snate@binkert.org 2016145Snate@binkert.orgvoid Switch::print(ostream& out) const 2026145Snate@binkert.org{ 2036145Snate@binkert.org // FIXME printing 2046145Snate@binkert.org out << "[Switch]"; 2056145Snate@binkert.org} 2066145Snate@binkert.org 207