SimpleNetwork.cc revision 10917:c38f28fad4c3
12SN/A/* 210292SAndreas.Sandberg@ARM.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 34039Sbinkertn@umich.edu * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu#include <cassert> 302665Ssaidi@eecs.umich.edu#include <numeric> 3110292SAndreas.Sandberg@ARM.com 322SN/A#include "base/cast.hh" 332SN/A#include "base/stl_helpers.hh" 344039Sbinkertn@umich.edu#include "mem/ruby/common/NetDest.hh" 354039Sbinkertn@umich.edu#include "mem/ruby/network/MessageBuffer.hh" 362SN/A#include "mem/ruby/network/simple/SimpleLink.hh" 374039Sbinkertn@umich.edu#include "mem/ruby/network/simple/SimpleNetwork.hh" 382SN/A#include "mem/ruby/network/simple/Switch.hh" 392SN/A#include "mem/ruby/network/simple/Throttle.hh" 402SN/A#include "mem/ruby/profiler/Profiler.hh" 412SN/A#include "mem/ruby/system/System.hh" 428229Snate@binkert.org 432621SN/Ausing namespace std; 442SN/Ausing m5::stl_helpers::deletePointers; 452SN/A 464039Sbinkertn@umich.eduSimpleNetwork::SimpleNetwork(const Params *p) 472SN/A : Network(p) 484039Sbinkertn@umich.edu{ 494039Sbinkertn@umich.edu m_buffer_size = p->buffer_size; 504039Sbinkertn@umich.edu m_endpoint_bandwidth = p->endpoint_bandwidth; 514039Sbinkertn@umich.edu m_adaptive_routing = p->adaptive_routing; 525756Snate@binkert.org 534039Sbinkertn@umich.edu // Note: the parent Network Object constructor is called before the 544039Sbinkertn@umich.edu // SimpleNetwork child constructor. Therefore, the member variables 554039Sbinkertn@umich.edu // used below should already be initialized. 564039Sbinkertn@umich.edu m_endpoint_switches.resize(m_nodes); 574039Sbinkertn@umich.edu 585756Snate@binkert.org // record the routers 595756Snate@binkert.org for (vector<BasicRouter*>::const_iterator i = p->routers.begin(); 609331Schander.sudanthi@arm.com i != p->routers.end(); ++i) { 614039Sbinkertn@umich.edu Switch* s = safe_cast<Switch*>(*i); 624039Sbinkertn@umich.edu m_switches.push_back(s); 634039Sbinkertn@umich.edu s->init_net_ptr(this); 644039Sbinkertn@umich.edu } 654039Sbinkertn@umich.edu} 662SN/A 675756Snate@binkert.orgvoid 685756Snate@binkert.orgSimpleNetwork::init() 695756Snate@binkert.org{ 705756Snate@binkert.org Network::init(); 715756Snate@binkert.org 725756Snate@binkert.org // The topology pointer should have already been initialized in 735756Snate@binkert.org // the parent class network constructor. 745756Snate@binkert.org assert(m_topology_ptr != NULL); 755756Snate@binkert.org m_topology_ptr->createLinks(this); 765756Snate@binkert.org} 775756Snate@binkert.org 785756Snate@binkert.orgSimpleNetwork::~SimpleNetwork() 795756Snate@binkert.org{ 802SN/A deletePointers(m_switches); 814039Sbinkertn@umich.edu deletePointers(m_buffers_to_free); 824039Sbinkertn@umich.edu} 832SN/A 845756Snate@binkert.org// From a switch to an endpoint node 855756Snate@binkert.orgvoid 865756Snate@binkert.orgSimpleNetwork::makeOutLink(SwitchID src, NodeID dest, BasicLink* link, 875756Snate@binkert.org LinkDirection direction, 885756Snate@binkert.org const NetDest& routing_table_entry) 895756Snate@binkert.org{ 905756Snate@binkert.org assert(dest < m_nodes); 915756Snate@binkert.org assert(src < m_switches.size()); 925756Snate@binkert.org assert(m_switches[src] != NULL); 935756Snate@binkert.org 945756Snate@binkert.org SimpleExtLink *simple_link = safe_cast<SimpleExtLink*>(link); 955756Snate@binkert.org 965756Snate@binkert.org m_switches[src]->addOutPort(m_fromNetQueues[dest], routing_table_entry, 975756Snate@binkert.org simple_link->m_latency, 985756Snate@binkert.org simple_link->m_bw_multiplier); 995756Snate@binkert.org 1002SN/A m_endpoint_switches[dest] = m_switches[src]; 1014039Sbinkertn@umich.edu} 1024039Sbinkertn@umich.edu 1034039Sbinkertn@umich.edu// From an endpoint node to a switch 1044039Sbinkertn@umich.eduvoid 1052SN/ASimpleNetwork::makeInLink(NodeID src, SwitchID dest, BasicLink* link, 1064039Sbinkertn@umich.edu LinkDirection direction, 1074039Sbinkertn@umich.edu const NetDest& routing_table_entry) 1084039Sbinkertn@umich.edu{ 1092SN/A assert(src < m_nodes); 1104039Sbinkertn@umich.edu m_switches[dest]->addInPort(m_toNetQueues[src]); 1114039Sbinkertn@umich.edu} 1124039Sbinkertn@umich.edu 1132SN/A// From a switch to a switch 1144039Sbinkertn@umich.eduvoid 1154039Sbinkertn@umich.eduSimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link, 1164039Sbinkertn@umich.edu LinkDirection direction, 1172SN/A const NetDest& routing_table_entry) 1184039Sbinkertn@umich.edu{ 1194039Sbinkertn@umich.edu // Create a set of new MessageBuffers 1204039Sbinkertn@umich.edu std::vector<MessageBuffer*> queues(m_virtual_networks); 1212SN/A 1222SN/A for (int i = 0; i < m_virtual_networks; i++) { 1232SN/A // allocate a buffer 1244039Sbinkertn@umich.edu MessageBuffer* buffer_ptr = new MessageBuffer; 1252SN/A buffer_ptr->setOrdering(true); 1262SN/A 1277811Ssteve.reinhardt@amd.com if (m_buffer_size > 0) { 1284039Sbinkertn@umich.edu buffer_ptr->resize(m_buffer_size); 12910292SAndreas.Sandberg@ARM.com } 13010292SAndreas.Sandberg@ARM.com 13110292SAndreas.Sandberg@ARM.com queues[i] = buffer_ptr; 13210292SAndreas.Sandberg@ARM.com // remember to deallocate it 13310292SAndreas.Sandberg@ARM.com m_buffers_to_free.push_back(buffer_ptr); 1344039Sbinkertn@umich.edu } 13510292SAndreas.Sandberg@ARM.com 13610292SAndreas.Sandberg@ARM.com // Connect it to the two switches 13710292SAndreas.Sandberg@ARM.com SimpleIntLink *simple_link = safe_cast<SimpleIntLink*>(link); 13810292SAndreas.Sandberg@ARM.com 13910292SAndreas.Sandberg@ARM.com m_switches[dest]->addInPort(queues); 14010292SAndreas.Sandberg@ARM.com m_switches[src]->addOutPort(queues, routing_table_entry, 14110292SAndreas.Sandberg@ARM.com simple_link->m_latency, 14210292SAndreas.Sandberg@ARM.com simple_link->m_bw_multiplier); 14310292SAndreas.Sandberg@ARM.com} 14410292SAndreas.Sandberg@ARM.com 14510292SAndreas.Sandberg@ARM.comvoid 14610292SAndreas.Sandberg@ARM.comSimpleNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num) 1472SN/A{ 1484039Sbinkertn@umich.edu assert(id < m_nodes); 14910292SAndreas.Sandberg@ARM.com assert(network_num < m_virtual_networks); 15010292SAndreas.Sandberg@ARM.com 1512SN/A if (ordered) { 1522SN/A m_ordered[network_num] = true; 15310292SAndreas.Sandberg@ARM.com } 15410292SAndreas.Sandberg@ARM.com m_in_use[network_num] = true; 15510292SAndreas.Sandberg@ARM.com} 1564039Sbinkertn@umich.edu 15710292SAndreas.Sandberg@ARM.comvoid 1584039Sbinkertn@umich.eduSimpleNetwork::setToNetQueue(NodeID id, bool ordered, int network_num, 1592SN/A std::string vnet_type, MessageBuffer *b) 16010292SAndreas.Sandberg@ARM.com{ 16110292SAndreas.Sandberg@ARM.com checkNetworkAllocation(id, ordered, network_num); 1624039Sbinkertn@umich.edu while (m_toNetQueues[id].size() <= network_num) { 1634039Sbinkertn@umich.edu m_toNetQueues[id].push_back(nullptr); 16410292SAndreas.Sandberg@ARM.com } 1654039Sbinkertn@umich.edu m_toNetQueues[id][network_num] = b; 1664039Sbinkertn@umich.edu} 1674039Sbinkertn@umich.edu 1684039Sbinkertn@umich.eduvoid 1694039Sbinkertn@umich.eduSimpleNetwork::setFromNetQueue(NodeID id, bool ordered, int network_num, 1704039Sbinkertn@umich.edu std::string vnet_type, MessageBuffer *b) 1714039Sbinkertn@umich.edu{ 1724039Sbinkertn@umich.edu checkNetworkAllocation(id, ordered, network_num); 17310292SAndreas.Sandberg@ARM.com while (m_fromNetQueues[id].size() <= network_num) { 17410292SAndreas.Sandberg@ARM.com m_fromNetQueues[id].push_back(nullptr); 1754039Sbinkertn@umich.edu } 17610292SAndreas.Sandberg@ARM.com m_fromNetQueues[id][network_num] = b; 1774039Sbinkertn@umich.edu} 1782SN/A 17910292SAndreas.Sandberg@ARM.comvoid 18010292SAndreas.Sandberg@ARM.comSimpleNetwork::regStats() 1814039Sbinkertn@umich.edu{ 18210292SAndreas.Sandberg@ARM.com for (MessageSizeType type = MessageSizeType_FIRST; 1834039Sbinkertn@umich.edu type < MessageSizeType_NUM; ++type) { 1842SN/A m_msg_counts[(unsigned int) type] 18510292SAndreas.Sandberg@ARM.com .name(name() + ".msg_count." + MessageSizeType_to_string(type)) 18610292SAndreas.Sandberg@ARM.com .flags(Stats::nozero) 1874039Sbinkertn@umich.edu ; 18810292SAndreas.Sandberg@ARM.com m_msg_bytes[(unsigned int) type] 1892SN/A .name(name() + ".msg_byte." + MessageSizeType_to_string(type)) 1902SN/A .flags(Stats::nozero) 1912SN/A ; 192 193 // Now state what the formula is. 194 for (int i = 0; i < m_switches.size(); i++) { 195 m_msg_counts[(unsigned int) type] += 196 sum(m_switches[i]->getMsgCount(type)); 197 } 198 199 m_msg_bytes[(unsigned int) type] = 200 m_msg_counts[(unsigned int) type] * Stats::constant( 201 Network::MessageSizeType_to_int(type)); 202 } 203} 204 205void 206SimpleNetwork::collateStats() 207{ 208 for (int i = 0; i < m_switches.size(); i++) { 209 m_switches[i]->collateStats(); 210 } 211} 212 213void 214SimpleNetwork::print(ostream& out) const 215{ 216 out << "[SimpleNetwork]"; 217} 218 219SimpleNetwork * 220SimpleNetworkParams::create() 221{ 222 return new SimpleNetwork(this); 223} 224 225/* 226 * The simple network has an array of switches. These switches have buffers 227 * that need to be accessed for functional reads and writes. Also the links 228 * between different switches have buffers that need to be accessed. 229 */ 230bool 231SimpleNetwork::functionalRead(Packet *pkt) 232{ 233 for (unsigned int i = 0; i < m_switches.size(); i++) { 234 if (m_switches[i]->functionalRead(pkt)) { 235 return true; 236 } 237 } 238 239 for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) { 240 if (m_buffers_to_free[i]->functionalRead(pkt)) { 241 return true; 242 } 243 } 244 245 return false; 246} 247 248uint32_t 249SimpleNetwork::functionalWrite(Packet *pkt) 250{ 251 uint32_t num_functional_writes = 0; 252 253 for (unsigned int i = 0; i < m_switches.size(); i++) { 254 num_functional_writes += m_switches[i]->functionalWrite(pkt); 255 } 256 257 for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) { 258 num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt); 259 } 260 return num_functional_writes; 261} 262