Topology.cc revision 6154
16657Snate@binkert.org 26657Snate@binkert.org/* 36657Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 46657Snate@binkert.org * All rights reserved. 56657Snate@binkert.org * 66657Snate@binkert.org * Redistribution and use in source and binary forms, with or without 76657Snate@binkert.org * modification, are permitted provided that the following conditions are 86657Snate@binkert.org * met: redistributions of source code must retain the above copyright 96657Snate@binkert.org * notice, this list of conditions and the following disclaimer; 106657Snate@binkert.org * redistributions in binary form must reproduce the above copyright 116657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 126657Snate@binkert.org * documentation and/or other materials provided with the distribution; 136657Snate@binkert.org * neither the name of the copyright holders nor the names of its 146657Snate@binkert.org * contributors may be used to endorse or promote products derived from 156657Snate@binkert.org * this software without specific prior written permission. 166657Snate@binkert.org * 176657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216657Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286999Snate@binkert.org */ 296657Snate@binkert.org 306657Snate@binkert.org/* 316657Snate@binkert.org * Topology.C 326657Snate@binkert.org * 338189SLisa.Hsu@amd.com * Description: See Topology.h 346657Snate@binkert.org * 359499Snilay@cs.wisc.edu * $Id$ 369499Snilay@cs.wisc.edu * 379364Snilay@cs.wisc.edu * */ 387055Snate@binkert.org 396882SBrad.Beckmann@amd.com#include "mem/ruby/network/simple/Topology.hh" 406882SBrad.Beckmann@amd.com#include "mem/ruby/common/NetDest.hh" 418191SLisa.Hsu@amd.com#include "mem/ruby/network/Network.hh" 426882SBrad.Beckmann@amd.com#include "mem/protocol/TopologyType.hh" 436882SBrad.Beckmann@amd.com#include "mem/ruby/config/RubyConfig.hh" 449102SNuwan.Jayasena@amd.com#include "mem/gems_common/util.hh" 459366Snilay@cs.wisc.edu#include "mem/protocol/MachineType.hh" 469499Snilay@cs.wisc.edu#include "mem/protocol/Protocol.hh" 479499Snilay@cs.wisc.edu#include <string> 489499Snilay@cs.wisc.edu 496882SBrad.Beckmann@amd.comstatic const int INFINITE_LATENCY = 10000; // Yes, this is a big hack 506657Snate@binkert.orgstatic const int DEFAULT_BW_MULTIPLIER = 1; // Just to be consistent with above :) 516657Snate@binkert.org 526657Snate@binkert.org// Note: In this file, we use the first 2*m_nodes SwitchIDs to 536657Snate@binkert.org// represent the input and output endpoint links. These really are 546657Snate@binkert.org// not 'switches', as they will not have a Switch object allocated for 559366Snilay@cs.wisc.edu// them. The first m_nodes SwitchIDs are the links into the network, 567839Snilay@cs.wisc.edu// the second m_nodes set of SwitchIDs represent the the output queues 576657Snate@binkert.org// of the network. 586882SBrad.Beckmann@amd.com 596882SBrad.Beckmann@amd.com// Helper functions based on chapter 29 of Cormen et al. 606882SBrad.Beckmann@amd.comstatic Matrix extend_shortest_path(const Matrix& current_dist, Matrix& latencies, Matrix& inter_switches); 616882SBrad.Beckmann@amd.comstatic Matrix shortest_path(const Matrix& weights, Matrix& latencies, Matrix& inter_switches); 626882SBrad.Beckmann@amd.comstatic bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, const Matrix& weights, const Matrix& dist); 636882SBrad.Beckmann@amd.comstatic NetDest shortest_path_to_node(SwitchID src, SwitchID next, const Matrix& weights, const Matrix& dist); 646657Snate@binkert.org 659366Snilay@cs.wisc.edu 669366Snilay@cs.wisc.eduTopology::Topology(Network* network_ptr, int number_of_nodes) 676657Snate@binkert.org{ 686657Snate@binkert.org m_network_ptr = network_ptr; 696657Snate@binkert.org m_nodes = number_of_nodes; 706657Snate@binkert.org m_number_of_switches = 0; 719104Shestness@cs.utexas.edu init(); 726657Snate@binkert.org} 736657Snate@binkert.org 746657Snate@binkert.orgvoid Topology::init() 756657Snate@binkert.org{ 767839Snilay@cs.wisc.edu if (m_nodes == 1) { 777839Snilay@cs.wisc.edu SwitchID id = newSwitchID(); 786657Snate@binkert.org addLink(0, id, NETWORK_LINK_LATENCY); 796657Snate@binkert.org addLink(id, 1, NETWORK_LINK_LATENCY); 806657Snate@binkert.org return; 816657Snate@binkert.org } 826657Snate@binkert.org 836657Snate@binkert.org // topology-specific set-up 846657Snate@binkert.org TopologyType topology = string_to_TopologyType(g_NETWORK_TOPOLOGY); 856657Snate@binkert.org switch (topology) { 866657Snate@binkert.org case TopologyType_TORUS_2D: 876657Snate@binkert.org make2DTorus(); 886657Snate@binkert.org break; 896657Snate@binkert.org case TopologyType_HIERARCHICAL_SWITCH: 906657Snate@binkert.org makeHierarchicalSwitch(FAN_OUT_DEGREE); 916657Snate@binkert.org break; 926657Snate@binkert.org case TopologyType_CROSSBAR: 936657Snate@binkert.org makeHierarchicalSwitch(1024); 946657Snate@binkert.org break; 956657Snate@binkert.org case TopologyType_PT_TO_PT: 966779SBrad.Beckmann@amd.com makePtToPt(); 976657Snate@binkert.org break; 986657Snate@binkert.org case TopologyType_FILE_SPECIFIED: 996657Snate@binkert.org makeFileSpecified(); 1006657Snate@binkert.org break; 1016657Snate@binkert.org default: 1026657Snate@binkert.org ERROR_MSG("Unexpected typology type") 1036657Snate@binkert.org } 1046657Snate@binkert.org 1056657Snate@binkert.org // initialize component latencies record 1069104Shestness@cs.utexas.edu m_component_latencies.setSize(0); 1079104Shestness@cs.utexas.edu m_component_inter_switches.setSize(0); 1089104Shestness@cs.utexas.edu} 1099104Shestness@cs.utexas.edu 1106657Snate@binkert.orgvoid Topology::makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChipSwitches) 1116657Snate@binkert.org{ 1126657Snate@binkert.org 1136657Snate@binkert.org Vector < SwitchID > nodes; // temporary buffer 1146657Snate@binkert.org nodes.setSize(2); 1156657Snate@binkert.org 1166657Snate@binkert.org Vector<bool> endpointConnectionExist; // used to ensure all endpoints are connected to the network 1176657Snate@binkert.org endpointConnectionExist.setSize(m_nodes); 1186657Snate@binkert.org // initialize endpoint check vector 1196657Snate@binkert.org for (int k = 0; k < endpointConnectionExist.size(); k++) { 1206657Snate@binkert.org endpointConnectionExist[k] = false; 1216657Snate@binkert.org } 1226657Snate@binkert.org 1236657Snate@binkert.org Vector<int> componentCount; 1246657Snate@binkert.org componentCount.setSize(MachineType_NUM); 1257839Snilay@cs.wisc.edu for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { 1267839Snilay@cs.wisc.edu componentCount[mType] = 0; 1277839Snilay@cs.wisc.edu } 1287839Snilay@cs.wisc.edu 1297839Snilay@cs.wisc.edu // components to/from network links 1307839Snilay@cs.wisc.edu for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) { 1317839Snilay@cs.wisc.edu for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { 1327839Snilay@cs.wisc.edu for (int component = 0; component < MachineType_chip_count(mType, chip); component++) { 1337839Snilay@cs.wisc.edu 1347839Snilay@cs.wisc.edu int latency = -1; 1357839Snilay@cs.wisc.edu int bw_multiplier = -1; // internal link bw multiplier of the global bandwidth 1367839Snilay@cs.wisc.edu if (mType != MachineType_Directory) { 1377839Snilay@cs.wisc.edu latency = ON_CHIP_LINK_LATENCY; // internal link latency 1387839Snilay@cs.wisc.edu bw_multiplier = 10; // internal link bw multiplier of the global bandwidth 1397839Snilay@cs.wisc.edu } else { 1406657Snate@binkert.org latency = NETWORK_LINK_LATENCY; // local memory latency 1416657Snate@binkert.org bw_multiplier = 1; // local memory link bw multiplier of the global bandwidth 1426657Snate@binkert.org } 1436657Snate@binkert.org nodes[0] = MachineType_base_number(mType)+componentCount[mType]; 1446657Snate@binkert.org nodes[1] = chip+m_nodes*2; // this is the chip's internal switch id # 1456657Snate@binkert.org 1466657Snate@binkert.org // insert link 1476657Snate@binkert.org nodePairs.insertAtBottom(nodes); 1486657Snate@binkert.org latencies.insertAtBottom(latency); 1496657Snate@binkert.org //bw_multis.insertAtBottom(bw_multiplier); 1506657Snate@binkert.org bw_multis.insertAtBottom(componentCount[mType]+MachineType_base_number((MachineType)mType)); 1516657Snate@binkert.org 1526657Snate@binkert.org // opposite direction link 1536657Snate@binkert.org Vector < SwitchID > otherDirectionNodes; 1546657Snate@binkert.org otherDirectionNodes.setSize(2); 1556657Snate@binkert.org otherDirectionNodes[0] = nodes[1]; 1566657Snate@binkert.org otherDirectionNodes[1] = nodes[0]+m_nodes; 1576657Snate@binkert.org nodePairs.insertAtBottom(otherDirectionNodes); 1586657Snate@binkert.org latencies.insertAtBottom(latency); 1596657Snate@binkert.org bw_multis.insertAtBottom(bw_multiplier); 1606657Snate@binkert.org 1616657Snate@binkert.org assert(!endpointConnectionExist[nodes[0]]); 1626657Snate@binkert.org endpointConnectionExist[nodes[0]] = true; 1636657Snate@binkert.org componentCount[mType]++; 1646657Snate@binkert.org } 1656657Snate@binkert.org } 1666657Snate@binkert.org } 1676657Snate@binkert.org 1686657Snate@binkert.org // make sure all enpoints are connected in the soon to be created network 1696657Snate@binkert.org for (int k = 0; k < endpointConnectionExist.size(); k++) { 1709219Spower.jg@gmail.com if (endpointConnectionExist[k] == false) { 1716877Ssteve.reinhardt@amd.com cerr << "Error: Unconnected Endpoint: " << k << endl; 1726657Snate@binkert.org exit(1); 1739219Spower.jg@gmail.com } 1746657Snate@binkert.org } 1759219Spower.jg@gmail.com 1766657Snate@binkert.org // secondary check to ensure we saw the correct machine counts 1776877Ssteve.reinhardt@amd.com for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { 1786999Snate@binkert.org assert(componentCount[mType] == MachineType_base_count((MachineType)mType)); 1796877Ssteve.reinhardt@amd.com } 1806877Ssteve.reinhardt@amd.com 1816877Ssteve.reinhardt@amd.com} 1826877Ssteve.reinhardt@amd.com 1836877Ssteve.reinhardt@amd.com// 2D torus topology 1846877Ssteve.reinhardt@amd.com 1856877Ssteve.reinhardt@amd.comvoid Topology::make2DTorus() 1866877Ssteve.reinhardt@amd.com{ 1876877Ssteve.reinhardt@amd.com Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file 1886877Ssteve.reinhardt@amd.com Vector<int> latencies; // link latencies for each link extracted 1899338SAndreas.Sandberg@arm.com Vector<int> bw_multis; // bw multipliers for each link extracted 1906877Ssteve.reinhardt@amd.com 1916877Ssteve.reinhardt@amd.com Vector < SwitchID > nodes; // temporary buffer 1926877Ssteve.reinhardt@amd.com nodes.setSize(2); 1936877Ssteve.reinhardt@amd.com 1946877Ssteve.reinhardt@amd.com // number of inter-chip switches 1956877Ssteve.reinhardt@amd.com int numberOfTorusSwitches = m_nodes/MachineType_base_level(MachineType_NUM); 1966882SBrad.Beckmann@amd.com // one switch per machine node grouping 1976882SBrad.Beckmann@amd.com Vector<SwitchID> torusSwitches; 1986882SBrad.Beckmann@amd.com for(int i=0; i<numberOfTorusSwitches; i++){ 1996882SBrad.Beckmann@amd.com SwitchID new_switch = newSwitchID(); 2006882SBrad.Beckmann@amd.com torusSwitches.insertAtBottom(new_switch); 2016882SBrad.Beckmann@amd.com } 2026882SBrad.Beckmann@amd.com 2036877Ssteve.reinhardt@amd.com makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfTorusSwitches); 2046877Ssteve.reinhardt@amd.com 2056877Ssteve.reinhardt@amd.com int lengthOfSide = (int)sqrt((double)numberOfTorusSwitches); 2066877Ssteve.reinhardt@amd.com 2076657Snate@binkert.org // Now connect the inter-chip torus links 2086657Snate@binkert.org 2096999Snate@binkert.org int latency = NETWORK_LINK_LATENCY; // external link latency 2106657Snate@binkert.org int bw_multiplier = 1; // external link bw multiplier of the global bandwidth 2116657Snate@binkert.org 2126657Snate@binkert.org for(int i=0; i<numberOfTorusSwitches; i++){ 2136657Snate@binkert.org nodes[0] = torusSwitches[i]; // current switch 2147007Snate@binkert.org 2156657Snate@binkert.org // left 2166657Snate@binkert.org if(nodes[0]%lengthOfSide == 0){ // determine left neighbor 2176657Snate@binkert.org nodes[1] = nodes[0] - 1 + lengthOfSide; 2186657Snate@binkert.org } else { 2196657Snate@binkert.org nodes[1] = nodes[0] - 1; 2207007Snate@binkert.org } 2217007Snate@binkert.org nodePairs.insertAtBottom(nodes); 2226657Snate@binkert.org latencies.insertAtBottom(latency); 2237002Snate@binkert.org bw_multis.insertAtBottom(bw_multiplier); 2247002Snate@binkert.org 2257002Snate@binkert.org // right 2267002Snate@binkert.org if((nodes[0] + 1)%lengthOfSide == 0){ // determine right neighbor 2276657Snate@binkert.org nodes[1] = nodes[0] + 1 - lengthOfSide; 2286657Snate@binkert.org } else { 2298229Snate@binkert.org nodes[1] = nodes[0] + 1; 2308229Snate@binkert.org } 2318229Snate@binkert.org nodePairs.insertAtBottom(nodes); 2328229Snate@binkert.org latencies.insertAtBottom(latency); 2336657Snate@binkert.org bw_multis.insertAtBottom(bw_multiplier); 2346657Snate@binkert.org 2356657Snate@binkert.org // top 2369595Snilay@cs.wisc.edu if(nodes[0] - lengthOfSide < 2*m_nodes){ // determine if node is on the top 2376657Snate@binkert.org nodes[1] = nodes[0] - lengthOfSide + (lengthOfSide*lengthOfSide); 2386793SBrad.Beckmann@amd.com } else { 2396657Snate@binkert.org nodes[1] = nodes[0] - lengthOfSide; 2409595Snilay@cs.wisc.edu } 2419595Snilay@cs.wisc.edu nodePairs.insertAtBottom(nodes); 2426657Snate@binkert.org latencies.insertAtBottom(latency); 2436657Snate@binkert.org bw_multis.insertAtBottom(bw_multiplier); 2446657Snate@binkert.org 2456657Snate@binkert.org // bottom 2467002Snate@binkert.org if(nodes[0] + lengthOfSide >= 2*m_nodes+numberOfTorusSwitches){ // determine if node is on the bottom 2476657Snate@binkert.org // sorin: bad bug if this is a > instead of a >= 2487007Snate@binkert.org nodes[1] = nodes[0] + lengthOfSide - (lengthOfSide*lengthOfSide); 2497007Snate@binkert.org } else { 2509271Snilay@cs.wisc.edu nodes[1] = nodes[0] + lengthOfSide; 2516877Ssteve.reinhardt@amd.com } 2526877Ssteve.reinhardt@amd.com nodePairs.insertAtBottom(nodes); 2536657Snate@binkert.org latencies.insertAtBottom(latency); 2546877Ssteve.reinhardt@amd.com bw_multis.insertAtBottom(bw_multiplier); 2556657Snate@binkert.org 2566657Snate@binkert.org } 2577002Snate@binkert.org 2587002Snate@binkert.org // add links 2596881SBrad.Beckmann@amd.com ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size()) 2609745Snilay@cs.wisc.edu for (int k = 0; k < nodePairs.size(); k++) { 2617002Snate@binkert.org ASSERT(nodePairs[k].size() == 2); 2626657Snate@binkert.org addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]); 2637002Snate@binkert.org } 2646902SBrad.Beckmann@amd.com 2659745Snilay@cs.wisc.edu} 2669745Snilay@cs.wisc.edu 2679745Snilay@cs.wisc.edu// hierarchical switch topology 2686863Sdrh5@cs.wisc.eduvoid Topology::makeHierarchicalSwitch(int fan_out_degree) 2696863Sdrh5@cs.wisc.edu{ 2708683Snilay@cs.wisc.edu // Make a row of switches with only one input. This extra row makes 2718683Snilay@cs.wisc.edu // sure the links out of the nodes have latency and limited 2727007Snate@binkert.org // bandwidth. 2739302Snilay@cs.wisc.edu 2749302Snilay@cs.wisc.edu // number of inter-chip switches, i.e. the last row of switches 2759302Snilay@cs.wisc.edu Vector<SwitchID> last_level; 2769745Snilay@cs.wisc.edu for (int i=0; i<m_nodes; i++) { 2779745Snilay@cs.wisc.edu SwitchID new_switch = newSwitchID(); // internal switch id # 2789745Snilay@cs.wisc.edu addLink(i, new_switch, NETWORK_LINK_LATENCY); 2799745Snilay@cs.wisc.edu last_level.insertAtBottom(new_switch); 2809745Snilay@cs.wisc.edu } 2819745Snilay@cs.wisc.edu 2826657Snate@binkert.org // Create Hierarchical Switches 2836657Snate@binkert.org 2846657Snate@binkert.org // start from the bottom level and work up to root 2856657Snate@binkert.org Vector<SwitchID> next_level; 2866657Snate@binkert.org while(last_level.size() > 1) { 2876657Snate@binkert.org for (int i=0; i<last_level.size(); i++) { 2886882SBrad.Beckmann@amd.com if ((i % fan_out_degree) == 0) { 2896882SBrad.Beckmann@amd.com next_level.insertAtBottom(newSwitchID()); 2906882SBrad.Beckmann@amd.com } 2916882SBrad.Beckmann@amd.com // Add this link to the last switch we created 2926657Snate@binkert.org addLink(last_level[i], next_level[next_level.size()-1], NETWORK_LINK_LATENCY); 2936657Snate@binkert.org } 2947007Snate@binkert.org 2957839Snilay@cs.wisc.edu // Make the current level the last level to get ready for next 2967839Snilay@cs.wisc.edu // iteration 2977839Snilay@cs.wisc.edu last_level = next_level; 2987839Snilay@cs.wisc.edu next_level.clear(); 2997839Snilay@cs.wisc.edu } 3007839Snilay@cs.wisc.edu 3017839Snilay@cs.wisc.edu SwitchID root_switch = last_level[0]; 3027839Snilay@cs.wisc.edu 3037839Snilay@cs.wisc.edu Vector<SwitchID> out_level; 3047839Snilay@cs.wisc.edu for (int i=0; i<m_nodes; i++) { 3057839Snilay@cs.wisc.edu out_level.insertAtBottom(m_nodes+i); 3067839Snilay@cs.wisc.edu } 3077007Snate@binkert.org 3087007Snate@binkert.org // Build the down network from the endpoints to the root 3097007Snate@binkert.org while(out_level.size() != 1) { 3107007Snate@binkert.org 3117007Snate@binkert.org // A level of switches 3127839Snilay@cs.wisc.edu for (int i=0; i<out_level.size(); i++) { 3137839Snilay@cs.wisc.edu if ((i % fan_out_degree) == 0) { 3147839Snilay@cs.wisc.edu if (out_level.size() > fan_out_degree) { 3157839Snilay@cs.wisc.edu next_level.insertAtBottom(newSwitchID()); 3167839Snilay@cs.wisc.edu } else { 3177839Snilay@cs.wisc.edu next_level.insertAtBottom(root_switch); 3187839Snilay@cs.wisc.edu } 3197839Snilay@cs.wisc.edu } 3207839Snilay@cs.wisc.edu // Add this link to the last switch we created 3217839Snilay@cs.wisc.edu addLink(next_level[next_level.size()-1], out_level[i], NETWORK_LINK_LATENCY); 3227839Snilay@cs.wisc.edu } 3237839Snilay@cs.wisc.edu 3247007Snate@binkert.org // Make the current level the last level to get ready for next 3257007Snate@binkert.org // iteration 3269745Snilay@cs.wisc.edu out_level = next_level; 3279745Snilay@cs.wisc.edu next_level.clear(); 3289745Snilay@cs.wisc.edu } 3299745Snilay@cs.wisc.edu} 3309745Snilay@cs.wisc.edu 3319745Snilay@cs.wisc.edu// one internal node per chip, point to point links between chips 3326657Snate@binkert.orgvoid Topology::makePtToPt() 3337007Snate@binkert.org{ 3346657Snate@binkert.org Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file 3356657Snate@binkert.org Vector<int> latencies; // link latencies for each link extracted 3366657Snate@binkert.org Vector<int> bw_multis; // bw multipliers for each link extracted 3376657Snate@binkert.org 3386657Snate@binkert.org Vector < SwitchID > nodes; 3396657Snate@binkert.org nodes.setSize(2); 3406657Snate@binkert.org 3416657Snate@binkert.org // number of inter-chip switches 3429595Snilay@cs.wisc.edu int numberOfChipSwitches = m_nodes/MachineType_base_level(MachineType_NUM); 3439595Snilay@cs.wisc.edu // two switches per machine node grouping 3447839Snilay@cs.wisc.edu // one intra-chip switch and one inter-chip switch per chip 3457839Snilay@cs.wisc.edu for(int i=0; i<numberOfChipSwitches; i++){ 3467839Snilay@cs.wisc.edu SwitchID new_switch = newSwitchID(); 3477839Snilay@cs.wisc.edu new_switch = newSwitchID(); 3487839Snilay@cs.wisc.edu } 3497839Snilay@cs.wisc.edu 3507839Snilay@cs.wisc.edu makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfChipSwitches); 3517839Snilay@cs.wisc.edu 3527839Snilay@cs.wisc.edu // connect intra-chip switch to inter-chip switch 3537839Snilay@cs.wisc.edu for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) { 3547839Snilay@cs.wisc.edu 3557839Snilay@cs.wisc.edu int latency = ON_CHIP_LINK_LATENCY; // internal link latency 3567839Snilay@cs.wisc.edu int bw_multiplier = 10; // external link bw multiplier of the global bandwidth 3577839Snilay@cs.wisc.edu 3587839Snilay@cs.wisc.edu nodes[0] = chip+m_nodes*2; 3597839Snilay@cs.wisc.edu nodes[1] = chip+m_nodes*2+RubyConfig::numberOfChips(); 3606657Snate@binkert.org 3616657Snate@binkert.org // insert link 3626657Snate@binkert.org nodePairs.insertAtBottom(nodes); 3636657Snate@binkert.org latencies.insertAtBottom(latency); 3647839Snilay@cs.wisc.edu bw_multis.insertAtBottom(bw_multiplier); 3657839Snilay@cs.wisc.edu 3667839Snilay@cs.wisc.edu // opposite direction link 3677839Snilay@cs.wisc.edu Vector < SwitchID > otherDirectionNodes; 3687839Snilay@cs.wisc.edu otherDirectionNodes.setSize(2); 3697839Snilay@cs.wisc.edu otherDirectionNodes[0] = nodes[1]; 3707839Snilay@cs.wisc.edu otherDirectionNodes[1] = nodes[0]; 3717839Snilay@cs.wisc.edu nodePairs.insertAtBottom(otherDirectionNodes); 3727839Snilay@cs.wisc.edu latencies.insertAtBottom(latency); 3737839Snilay@cs.wisc.edu bw_multis.insertAtBottom(bw_multiplier); 3747839Snilay@cs.wisc.edu } 3757839Snilay@cs.wisc.edu 3767839Snilay@cs.wisc.edu // point-to-point network between chips 3777839Snilay@cs.wisc.edu for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) { 3787839Snilay@cs.wisc.edu for (int other_chip = chip+1; other_chip < RubyConfig::numberOfChips(); other_chip++) { 3797839Snilay@cs.wisc.edu 3806657Snate@binkert.org int latency = NETWORK_LINK_LATENCY; // external link latency 3816657Snate@binkert.org int bw_multiplier = 1; // external link bw multiplier of the global bandwidth 3826657Snate@binkert.org 3836657Snate@binkert.org nodes[0] = chip+m_nodes*2+RubyConfig::numberOfChips(); 3847007Snate@binkert.org nodes[1] = other_chip+m_nodes*2+RubyConfig::numberOfChips(); 3856657Snate@binkert.org 3866657Snate@binkert.org // insert link 3879273Snilay@cs.wisc.edu nodePairs.insertAtBottom(nodes); 3886657Snate@binkert.org latencies.insertAtBottom(latency); 3896657Snate@binkert.org bw_multis.insertAtBottom(bw_multiplier); 3906657Snate@binkert.org 3916657Snate@binkert.org // opposite direction link 3927007Snate@binkert.org Vector < SwitchID > otherDirectionNodes; 3936657Snate@binkert.org otherDirectionNodes.setSize(2); 3946657Snate@binkert.org otherDirectionNodes[0] = nodes[1]; 3959219Spower.jg@gmail.com otherDirectionNodes[1] = nodes[0]; 3966657Snate@binkert.org nodePairs.insertAtBottom(otherDirectionNodes); 3976657Snate@binkert.org latencies.insertAtBottom(latency); 3986999Snate@binkert.org bw_multis.insertAtBottom(bw_multiplier); 3996657Snate@binkert.org } 4006657Snate@binkert.org } 4019595Snilay@cs.wisc.edu 4026657Snate@binkert.org // add links 4036657Snate@binkert.org ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size()) 4047007Snate@binkert.org for (int k = 0; k < nodePairs.size(); k++) { 4056657Snate@binkert.org ASSERT(nodePairs[k].size() == 2); 4066657Snate@binkert.org addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]); 4076657Snate@binkert.org } 4086657Snate@binkert.org} 4096657Snate@binkert.org 4108946Sandreas.hansson@arm.com// make a network as described by the networkFile 4118946Sandreas.hansson@arm.comvoid Topology::makeFileSpecified() 4128946Sandreas.hansson@arm.com{ 4137832Snate@binkert.org 4147002Snate@binkert.org Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file 4157002Snate@binkert.org Vector<int> latencies; // link latencies for each link extracted 4167002Snate@binkert.org Vector<int> bw_multis; // bw multipliers for each link extracted 4178641Snate@binkert.org Vector<int> weights; // link weights used to enfore e-cube deadlock free routing 4187056Snate@binkert.org Vector< SwitchID > int_network_switches; // internal switches extracted from the file 4198232Snate@binkert.org Vector<bool> endpointConnectionExist; // used to ensure all endpoints are connected to the network 4208232Snate@binkert.org 4216657Snate@binkert.org endpointConnectionExist.setSize(m_nodes); 4228229Snate@binkert.org 4236657Snate@binkert.org // initialize endpoint check vector 4246657Snate@binkert.org for (int k = 0; k < endpointConnectionExist.size(); k++) { 4257056Snate@binkert.org endpointConnectionExist[k] = false; 4266657Snate@binkert.org } 4279219Spower.jg@gmail.com 4289219Spower.jg@gmail.com string filename = "network/simple/Network_Files/"; 4299219Spower.jg@gmail.com filename = filename+g_CACHE_DESIGN 4309219Spower.jg@gmail.com +"_Procs-"+int_to_string(RubyConfig::numberOfProcessors()) 4319219Spower.jg@gmail.com +"_ProcsPerChip-"+int_to_string(RubyConfig::numberOfProcsPerChip()) 4327002Snate@binkert.org +"_L2Banks-"+int_to_string(RubyConfig::numberOfL2Cache()) 4337002Snate@binkert.org +"_Memories-"+int_to_string(RubyConfig::numberOfMemories()) 4346657Snate@binkert.org +".txt"; 4356657Snate@binkert.org 4366657Snate@binkert.org ifstream networkFile( filename.c_str() , ios::in); 4376657Snate@binkert.org if (!networkFile.is_open()) { 4386657Snate@binkert.org cerr << "Error: Could not open network file: " << filename << endl; 4396793SBrad.Beckmann@amd.com cerr << "Probably no network file exists for " << RubyConfig::numberOfProcessors() 4406657Snate@binkert.org << " processors and " << RubyConfig::numberOfProcsPerChip() << " procs per chip " << endl; 4416657Snate@binkert.org exit(1); 4426657Snate@binkert.org } 4436657Snate@binkert.org 4446877Ssteve.reinhardt@amd.com string line = ""; 4456877Ssteve.reinhardt@amd.com 4466877Ssteve.reinhardt@amd.com while (!networkFile.eof()) { 4476877Ssteve.reinhardt@amd.com 4486877Ssteve.reinhardt@amd.com Vector < SwitchID > nodes; 4496877Ssteve.reinhardt@amd.com nodes.setSize(2); 4506657Snate@binkert.org int latency = -1; // null latency 4519745Snilay@cs.wisc.edu int weight = -1; // null weight 4529745Snilay@cs.wisc.edu int bw_multiplier = DEFAULT_BW_MULTIPLIER; // default multiplier incase the network file doesn't define it 4536657Snate@binkert.org int i = 0; // node pair index 4547007Snate@binkert.org int varsFound = 0; // number of varsFound on the line 4556657Snate@binkert.org int internalNodes = 0; // used to determine if the link is between 2 internal nodes 4566657Snate@binkert.org std::getline(networkFile, line, '\n'); 4577007Snate@binkert.org string varStr = string_split(line, ' '); 4586657Snate@binkert.org 4596877Ssteve.reinhardt@amd.com // parse the current line in the file 4606877Ssteve.reinhardt@amd.com while (varStr != "") { 4616657Snate@binkert.org string label = string_split(varStr, ':'); 4628532SLisa.Hsu@amd.com 4636657Snate@binkert.org // valid node labels 4647567SBrad.Beckmann@amd.com if (label == "ext_node" || label == "int_node") { 4657567SBrad.Beckmann@amd.com ASSERT(i < 2); // one link between 2 switches per line 4667567SBrad.Beckmann@amd.com varsFound++; 4677567SBrad.Beckmann@amd.com bool isNewIntSwitch = true; 4687567SBrad.Beckmann@amd.com if (label == "ext_node") { // input link to node 4697567SBrad.Beckmann@amd.com MachineType machine = string_to_MachineType(string_split(varStr, ':')); 4706657Snate@binkert.org string nodeStr = string_split(varStr, ':'); 4716882SBrad.Beckmann@amd.com if (string_split(varStr, ':') == "bank") { 4726882SBrad.Beckmann@amd.com nodes[i] = MachineType_base_number(machine) 4736882SBrad.Beckmann@amd.com + atoi(nodeStr.c_str()) 4746882SBrad.Beckmann@amd.com + atoi((string_split(varStr, ':')).c_str())*RubyConfig::numberOfChips(); 4756882SBrad.Beckmann@amd.com } else { 4766882SBrad.Beckmann@amd.com nodes[i] = MachineType_base_number(machine) 4776882SBrad.Beckmann@amd.com + atoi(nodeStr.c_str()); 4788189SLisa.Hsu@amd.com } 4798189SLisa.Hsu@amd.com // in nodes should be numbered 0 to m_nodes-1 4806877Ssteve.reinhardt@amd.com ASSERT(nodes[i] >= 0 && nodes[i] < m_nodes); 4818189SLisa.Hsu@amd.com isNewIntSwitch = false; 4828189SLisa.Hsu@amd.com endpointConnectionExist[nodes[i]] = true; 4838189SLisa.Hsu@amd.com } 4848189SLisa.Hsu@amd.com if (label == "int_node") { // interior node 4856882SBrad.Beckmann@amd.com nodes[i] = atoi((string_split(varStr, ':')).c_str())+m_nodes*2; 4866882SBrad.Beckmann@amd.com // in nodes should be numbered >= m_nodes*2 4876882SBrad.Beckmann@amd.com ASSERT(nodes[i] >= m_nodes*2); 4886882SBrad.Beckmann@amd.com for (int k = 0; k < int_network_switches.size(); k++) { 4896882SBrad.Beckmann@amd.com if (int_network_switches[k] == nodes[i]) { 4906882SBrad.Beckmann@amd.com isNewIntSwitch = false; 4916882SBrad.Beckmann@amd.com } 4926882SBrad.Beckmann@amd.com } 4936882SBrad.Beckmann@amd.com if (isNewIntSwitch) { // if internal switch 4949597Snilay@cs.wisc.edu m_number_of_switches++; 4959597Snilay@cs.wisc.edu int_network_switches.insertAtBottom(nodes[i]); 4968938SLisa.Hsu@amd.com } 4978938SLisa.Hsu@amd.com internalNodes++; 4988938SLisa.Hsu@amd.com } 4996888SBrad.Beckmann@amd.com i++; 5006888SBrad.Beckmann@amd.com } else if (label == "link_latency") { 5016888SBrad.Beckmann@amd.com latency = atoi((string_split(varStr, ':')).c_str()); 5026888SBrad.Beckmann@amd.com varsFound++; 5036888SBrad.Beckmann@amd.com } else if (label == "bw_multiplier") { // not necessary, defaults to DEFAULT_BW_MULTIPLIER 5048189SLisa.Hsu@amd.com bw_multiplier = atoi((string_split(varStr, ':')).c_str()); 5056888SBrad.Beckmann@amd.com } else if (label == "link_weight") { // not necessary, defaults to link_latency 5066888SBrad.Beckmann@amd.com weight = atoi((string_split(varStr, ':')).c_str()); 5076657Snate@binkert.org } else if (label == "processors") { 5086888SBrad.Beckmann@amd.com ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfProcessors()); 5096888SBrad.Beckmann@amd.com } else if (label == "bw_unit") { 5106888SBrad.Beckmann@amd.com ASSERT(atoi((string_split(varStr, ':')).c_str()) == g_endpoint_bandwidth); 5116888SBrad.Beckmann@amd.com } else if (label == "procs_per_chip") { 5126657Snate@binkert.org ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfProcsPerChip()); 5136657Snate@binkert.org } else if (label == "L2banks") { 5146657Snate@binkert.org ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfL2Cache()); 5159508Snilay@cs.wisc.edu } else if (label == "memories") { 5169508Snilay@cs.wisc.edu ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfMemories()); 5179508Snilay@cs.wisc.edu } else { 5189508Snilay@cs.wisc.edu cerr << "Error: Unexpected Identifier: " << label << endl; 5199595Snilay@cs.wisc.edu exit(1); 5209595Snilay@cs.wisc.edu } 5219595Snilay@cs.wisc.edu varStr = string_split(line, ' '); 5229595Snilay@cs.wisc.edu } 5239595Snilay@cs.wisc.edu if (varsFound == 3) { // all three necessary link variables where found so add the link 5249595Snilay@cs.wisc.edu nodePairs.insertAtBottom(nodes); 5259595Snilay@cs.wisc.edu latencies.insertAtBottom(latency); 5269595Snilay@cs.wisc.edu if (weight != -1) { 5279595Snilay@cs.wisc.edu weights.insertAtBottom(weight); 5286657Snate@binkert.org } else { 5299595Snilay@cs.wisc.edu weights.insertAtBottom(latency); 5309595Snilay@cs.wisc.edu } 5319595Snilay@cs.wisc.edu bw_multis.insertAtBottom(bw_multiplier); 5329745Snilay@cs.wisc.edu Vector < SwitchID > otherDirectionNodes; 5339745Snilay@cs.wisc.edu otherDirectionNodes.setSize(2); 5349745Snilay@cs.wisc.edu otherDirectionNodes[0] = nodes[1]; 5359745Snilay@cs.wisc.edu if (internalNodes == 2) { // this is an internal link 5369745Snilay@cs.wisc.edu otherDirectionNodes[1] = nodes[0]; 5379745Snilay@cs.wisc.edu } else { 5389745Snilay@cs.wisc.edu otherDirectionNodes[1] = nodes[0]+m_nodes; 5399745Snilay@cs.wisc.edu } 5409745Snilay@cs.wisc.edu nodePairs.insertAtBottom(otherDirectionNodes); 5419745Snilay@cs.wisc.edu latencies.insertAtBottom(latency); 5429595Snilay@cs.wisc.edu if (weight != -1) { 5436657Snate@binkert.org weights.insertAtBottom(weight); 5446657Snate@binkert.org } else { 5456657Snate@binkert.org weights.insertAtBottom(latency); 5466657Snate@binkert.org } 5477007Snate@binkert.org bw_multis.insertAtBottom(bw_multiplier); 5487007Snate@binkert.org } else { 5496657Snate@binkert.org if (varsFound != 0) { // if this is not a valid link, then no vars should have been found 5509745Snilay@cs.wisc.edu cerr << "Error in line: " << line << endl; 5519745Snilay@cs.wisc.edu exit(1); 5527007Snate@binkert.org } 5536657Snate@binkert.org } 5546657Snate@binkert.org } // end of file 5556657Snate@binkert.org 5567007Snate@binkert.org // makes sure all enpoints are connected in the soon to be created network 5577007Snate@binkert.org for (int k = 0; k < endpointConnectionExist.size(); k++) { 5586657Snate@binkert.org if (endpointConnectionExist[k] == false) { 5596657Snate@binkert.org cerr << "Error: Unconnected Endpoint: " << k << endl; 5606657Snate@binkert.org exit(1); 5616657Snate@binkert.org } 5626657Snate@binkert.org } 5636657Snate@binkert.org 5646657Snate@binkert.org ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size() && latencies.size() == weights.size()) 5656657Snate@binkert.org for (int k = 0; k < nodePairs.size(); k++) { 5666657Snate@binkert.org ASSERT(nodePairs[k].size() == 2); 5676657Snate@binkert.org addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k], weights[k]); 5686657Snate@binkert.org } 5696657Snate@binkert.org 5706657Snate@binkert.org networkFile.close(); 5716657Snate@binkert.org} 5729595Snilay@cs.wisc.edu 5739273Snilay@cs.wisc.eduvoid Topology::createLinks(bool isReconfiguration) 5746657Snate@binkert.org{ 5756657Snate@binkert.org // Find maximum switchID 5766657Snate@binkert.org 5779364Snilay@cs.wisc.edu SwitchID max_switch_id = 0; 5787007Snate@binkert.org for (int i=0; i<m_links_src_vector.size(); i++) { 5796657Snate@binkert.org max_switch_id = max(max_switch_id, m_links_src_vector[i]); 5806657Snate@binkert.org max_switch_id = max(max_switch_id, m_links_dest_vector[i]); 5816657Snate@binkert.org } 5826657Snate@binkert.org 5837007Snate@binkert.org // Initialize weight vector 5846657Snate@binkert.org Matrix topology_weights; 5857007Snate@binkert.org Matrix topology_latency; 5867007Snate@binkert.org Matrix topology_bw_multis; 5876657Snate@binkert.org int num_switches = max_switch_id+1; 5886657Snate@binkert.org topology_weights.setSize(num_switches); 5899508Snilay@cs.wisc.edu topology_latency.setSize(num_switches); 5906657Snate@binkert.org topology_bw_multis.setSize(num_switches); 5916657Snate@binkert.org m_component_latencies.setSize(num_switches); // FIXME setting the size of a member variable here is a HACK! 5926657Snate@binkert.org m_component_inter_switches.setSize(num_switches); // FIXME setting the size of a member variable here is a HACK! 5936657Snate@binkert.org for(int i=0; i<topology_weights.size(); i++) { 5946657Snate@binkert.org topology_weights[i].setSize(num_switches); 5956657Snate@binkert.org topology_latency[i].setSize(num_switches); 5966657Snate@binkert.org topology_bw_multis[i].setSize(num_switches); 5976657Snate@binkert.org m_component_latencies[i].setSize(num_switches); 5986657Snate@binkert.org m_component_inter_switches[i].setSize(num_switches); // FIXME setting the size of a member variable here is a HACK! 5999508Snilay@cs.wisc.edu for(int j=0; j<topology_weights[i].size(); j++) { 6006657Snate@binkert.org topology_weights[i][j] = INFINITE_LATENCY; 6017566SBrad.Beckmann@amd.com topology_latency[i][j] = -1; // initialize to an invalid value 6029508Snilay@cs.wisc.edu topology_bw_multis[i][j] = -1; // initialize to an invalid value 6039508Snilay@cs.wisc.edu m_component_latencies[i][j] = -1; // initialize to an invalid value 6049508Snilay@cs.wisc.edu m_component_inter_switches[i][j] = 0; // initially assume direct connections / no intermediate switches between components 6059508Snilay@cs.wisc.edu } 6069508Snilay@cs.wisc.edu } 6079508Snilay@cs.wisc.edu 6089604Snilay@cs.wisc.edu // Set identity weights to zero 6099604Snilay@cs.wisc.edu for(int i=0; i<topology_weights.size(); i++) { 6109604Snilay@cs.wisc.edu topology_weights[i][i] = 0; 6119508Snilay@cs.wisc.edu } 6126657Snate@binkert.org 6136657Snate@binkert.org // Fill in the topology weights and bandwidth multipliers 6146657Snate@binkert.org for (int i=0; i<m_links_src_vector.size(); i++) { 6156657Snate@binkert.org topology_weights[m_links_src_vector[i]][m_links_dest_vector[i]] = m_links_weight_vector[i]; 6166657Snate@binkert.org topology_latency[m_links_src_vector[i]][m_links_dest_vector[i]] = m_links_latency_vector[i]; 6179595Snilay@cs.wisc.edu m_component_latencies[m_links_src_vector[i]][m_links_dest_vector[i]] = m_links_latency_vector[i]; // initialize to latency vector 6189595Snilay@cs.wisc.edu topology_bw_multis[m_links_src_vector[i]][m_links_dest_vector[i]] = m_bw_multiplier_vector[i]; 6199595Snilay@cs.wisc.edu } 6209595Snilay@cs.wisc.edu 6219595Snilay@cs.wisc.edu // Walk topology and hookup the links 6229595Snilay@cs.wisc.edu Matrix dist = shortest_path(topology_weights, m_component_latencies, m_component_inter_switches); 6238308Stushar@csail.mit.edu for(int i=0; i<topology_weights.size(); i++) { 6249595Snilay@cs.wisc.edu for(int j=0; j<topology_weights[i].size(); j++) { 6256657Snate@binkert.org int weight = topology_weights[i][j]; 6266657Snate@binkert.org int bw_multiplier = topology_bw_multis[i][j]; 6279595Snilay@cs.wisc.edu int latency = topology_latency[i][j]; 6289595Snilay@cs.wisc.edu if (weight > 0 && weight != INFINITE_LATENCY) { 6299595Snilay@cs.wisc.edu NetDest destination_set = shortest_path_to_node(i, j, topology_weights, dist); 6309595Snilay@cs.wisc.edu assert(latency != -1); 6319595Snilay@cs.wisc.edu makeLink(i, j, destination_set, latency, weight, bw_multiplier, isReconfiguration); 6329508Snilay@cs.wisc.edu } 6336657Snate@binkert.org } 6346657Snate@binkert.org } 6356657Snate@binkert.org} 6366657Snate@binkert.org 6376657Snate@binkert.orgSwitchID Topology::newSwitchID() 6386657Snate@binkert.org{ 6396657Snate@binkert.org m_number_of_switches++; 6406657Snate@binkert.org return m_number_of_switches-1+m_nodes+m_nodes; 6418187SLisa.Hsu@amd.com} 6426657Snate@binkert.org 6436657Snate@binkert.orgvoid Topology::addLink(SwitchID src, SwitchID dest, int link_latency) 6446657Snate@binkert.org{ 6456657Snate@binkert.org addLink(src, dest, link_latency, DEFAULT_BW_MULTIPLIER, link_latency); 6466657Snate@binkert.org} 6476657Snate@binkert.org 6486657Snate@binkert.orgvoid Topology::addLink(SwitchID src, SwitchID dest, int link_latency, int bw_multiplier) 6496657Snate@binkert.org{ 6506657Snate@binkert.org addLink(src, dest, link_latency, bw_multiplier, link_latency); 6517454Snate@binkert.org} 6526657Snate@binkert.org 6536657Snate@binkert.orgvoid Topology::addLink(SwitchID src, SwitchID dest, int link_latency, int bw_multiplier, int link_weight) 6546657Snate@binkert.org{ 6556657Snate@binkert.org ASSERT(src <= m_number_of_switches+m_nodes+m_nodes); 6567007Snate@binkert.org ASSERT(dest <= m_number_of_switches+m_nodes+m_nodes); 6577056Snate@binkert.org m_links_src_vector.insertAtBottom(src); 6587007Snate@binkert.org m_links_dest_vector.insertAtBottom(dest); 6597007Snate@binkert.org m_links_latency_vector.insertAtBottom(link_latency); 6606657Snate@binkert.org m_links_weight_vector.insertAtBottom(link_weight); 6617566SBrad.Beckmann@amd.com m_bw_multiplier_vector.insertAtBottom(bw_multiplier); 6627566SBrad.Beckmann@amd.com} 6639499Snilay@cs.wisc.edu 6649499Snilay@cs.wisc.eduvoid Topology::makeLink(SwitchID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration) 6657566SBrad.Beckmann@amd.com{ 6667566SBrad.Beckmann@amd.com // Make sure we're not trying to connect two end-point nodes directly together 6677566SBrad.Beckmann@amd.com assert((src >= 2*m_nodes) || (dest >= 2*m_nodes)); 6689366Snilay@cs.wisc.edu 6699366Snilay@cs.wisc.edu if (src < m_nodes) { 6709366Snilay@cs.wisc.edu m_network_ptr->makeInLink(src, dest-(2*m_nodes), routing_table_entry, link_latency, bw_multiplier, isReconfiguration); 6719366Snilay@cs.wisc.edu } else if (dest < 2*m_nodes) { 6727566SBrad.Beckmann@amd.com assert(dest >= m_nodes); 6737672Snate@binkert.org NodeID node = dest-m_nodes; 6746657Snate@binkert.org m_network_ptr->makeOutLink(src-(2*m_nodes), node, routing_table_entry, link_latency, link_weight, bw_multiplier, isReconfiguration); 6759465Snilay@cs.wisc.edu } else { 6766657Snate@binkert.org assert((src >= 2*m_nodes) && (dest >= 2*m_nodes)); 6779465Snilay@cs.wisc.edu m_network_ptr->makeInternalLink(src-(2*m_nodes), dest-(2*m_nodes), routing_table_entry, link_latency, link_weight, bw_multiplier, isReconfiguration); 6787056Snate@binkert.org } 6796657Snate@binkert.org} 6806657Snate@binkert.org 6817672Snate@binkert.orgvoid Topology::printConfig(ostream& out) const 6826657Snate@binkert.org{ 6836657Snate@binkert.org assert(m_component_latencies.size() > 0); 6846657Snate@binkert.org 6856657Snate@binkert.org out << "--- Begin Topology Print ---" << endl; 6866657Snate@binkert.org out << endl; 6876657Snate@binkert.org out << "Topology print ONLY indicates the _NETWORK_ latency between two machines" << endl; 6886657Snate@binkert.org out << "It does NOT include the latency within the machines" << endl; 6896657Snate@binkert.org out << endl; 6906657Snate@binkert.org for (int m=0; m<MachineType_NUM; m++) { 6916657Snate@binkert.org for (int i=0; i<MachineType_base_count((MachineType)m); i++) { 6926657Snate@binkert.org MachineID cur_mach = {(MachineType)m, i}; 6939745Snilay@cs.wisc.edu out << cur_mach << " Network Latencies" << endl; 6946657Snate@binkert.org for (int n=0; n<MachineType_NUM; n++) { 6956657Snate@binkert.org for (int j=0; j<MachineType_base_count((MachineType)n); j++) { 6969496Snilay@cs.wisc.edu MachineID dest_mach = {(MachineType)n, j}; 6979496Snilay@cs.wisc.edu if (cur_mach != dest_mach) { 6989496Snilay@cs.wisc.edu int link_latency = m_component_latencies[MachineType_base_number((MachineType)m)+i][MachineType_base_number(MachineType_NUM)+MachineType_base_number((MachineType)n)+j]; 6999496Snilay@cs.wisc.edu int intermediate_switches = m_component_inter_switches[MachineType_base_number((MachineType)m)+i][MachineType_base_number(MachineType_NUM)+MachineType_base_number((MachineType)n)+j]; 7009496Snilay@cs.wisc.edu out << " " << cur_mach << " -> " << dest_mach << " net_lat: " 7016657Snate@binkert.org << link_latency+intermediate_switches << endl; // NOTE switches are assumed to have single cycle latency 7026657Snate@binkert.org } 7036657Snate@binkert.org } 7046657Snate@binkert.org } 7056657Snate@binkert.org out << endl; 7066657Snate@binkert.org } 7076657Snate@binkert.org } 7086657Snate@binkert.org 7096657Snate@binkert.org out << "--- End Topology Print ---" << endl; 7106657Snate@binkert.org} 7116657Snate@binkert.org 7128683Snilay@cs.wisc.edu/**************************************************************************/ 7138683Snilay@cs.wisc.edu 7148683Snilay@cs.wisc.edu// The following all-pairs shortest path algorithm is based on the 7158683Snilay@cs.wisc.edu// discussion from Cormen et al., Chapter 26.1. 7168683Snilay@cs.wisc.edu 7178683Snilay@cs.wisc.edustatic void extend_shortest_path(Matrix& current_dist, Matrix& latencies, Matrix& inter_switches) 7186657Snate@binkert.org{ 7199745Snilay@cs.wisc.edu bool change = true; 7209745Snilay@cs.wisc.edu int nodes = current_dist.size(); 7219745Snilay@cs.wisc.edu 7229745Snilay@cs.wisc.edu while (change) { 7239745Snilay@cs.wisc.edu change = false; 7249745Snilay@cs.wisc.edu for (int i=0; i<nodes; i++) { 7259745Snilay@cs.wisc.edu for (int j=0; j<nodes; j++) { 7269745Snilay@cs.wisc.edu int minimum = current_dist[i][j]; 7279745Snilay@cs.wisc.edu int previous_minimum = minimum; 7289745Snilay@cs.wisc.edu int intermediate_switch = -1; 7299745Snilay@cs.wisc.edu for (int k=0; k<nodes; k++) { 7309745Snilay@cs.wisc.edu minimum = min(minimum, current_dist[i][k] + current_dist[k][j]); 7319745Snilay@cs.wisc.edu if (previous_minimum != minimum) { 7329745Snilay@cs.wisc.edu intermediate_switch = k; 7339745Snilay@cs.wisc.edu inter_switches[i][j] = inter_switches[i][k] + inter_switches[k][j] + 1; 7349745Snilay@cs.wisc.edu } 7359745Snilay@cs.wisc.edu previous_minimum = minimum; 7369745Snilay@cs.wisc.edu } 7379745Snilay@cs.wisc.edu if (current_dist[i][j] != minimum) { 7389745Snilay@cs.wisc.edu change = true; 7399745Snilay@cs.wisc.edu current_dist[i][j] = minimum; 7409745Snilay@cs.wisc.edu assert(intermediate_switch >= 0); 7419745Snilay@cs.wisc.edu assert(intermediate_switch < latencies[i].size()); 7429745Snilay@cs.wisc.edu latencies[i][j] = latencies[i][intermediate_switch] + latencies[intermediate_switch][j]; 7439745Snilay@cs.wisc.edu } 7449745Snilay@cs.wisc.edu } 7459745Snilay@cs.wisc.edu } 7469745Snilay@cs.wisc.edu } 7479745Snilay@cs.wisc.edu} 7489745Snilay@cs.wisc.edu 7499745Snilay@cs.wisc.edustatic Matrix shortest_path(const Matrix& weights, Matrix& latencies, Matrix& inter_switches) 7509745Snilay@cs.wisc.edu{ 7519745Snilay@cs.wisc.edu Matrix dist = weights; 7529745Snilay@cs.wisc.edu extend_shortest_path(dist, latencies, inter_switches); 7539745Snilay@cs.wisc.edu return dist; 7549745Snilay@cs.wisc.edu} 7559745Snilay@cs.wisc.edu 7569745Snilay@cs.wisc.edustatic bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, 7579745Snilay@cs.wisc.edu const Matrix& weights, const Matrix& dist) 7589745Snilay@cs.wisc.edu{ 7599745Snilay@cs.wisc.edu return (weights[src][next] + dist[next][final] == dist[src][final]); 7609745Snilay@cs.wisc.edu} 7619745Snilay@cs.wisc.edu 7629745Snilay@cs.wisc.edustatic NetDest shortest_path_to_node(SwitchID src, SwitchID next, 7639745Snilay@cs.wisc.edu const Matrix& weights, const Matrix& dist) 7649745Snilay@cs.wisc.edu{ 7659745Snilay@cs.wisc.edu NetDest result; 7669745Snilay@cs.wisc.edu int d = 0; 7679745Snilay@cs.wisc.edu int machines; 7689745Snilay@cs.wisc.edu int max_machines; 7699745Snilay@cs.wisc.edu 7709745Snilay@cs.wisc.edu machines = MachineType_NUM; 7719745Snilay@cs.wisc.edu max_machines = MachineType_base_number(MachineType_NUM); 7729745Snilay@cs.wisc.edu 7739745Snilay@cs.wisc.edu for (int m=0; m<machines; m++) { 7749745Snilay@cs.wisc.edu for (int i=0; i<MachineType_base_count((MachineType)m); i++) { 7759745Snilay@cs.wisc.edu // we use "d+max_machines" below since the "destination" switches for the machines are numbered 7769745Snilay@cs.wisc.edu // [MachineType_base_number(MachineType_NUM)...2*MachineType_base_number(MachineType_NUM)-1] 7779745Snilay@cs.wisc.edu // for the component network 7789745Snilay@cs.wisc.edu if (link_is_shortest_path_to_node(src, next, 7799745Snilay@cs.wisc.edu d+max_machines, 7809745Snilay@cs.wisc.edu weights, dist)) { 7819745Snilay@cs.wisc.edu MachineID mach = {(MachineType)m, i}; 7829745Snilay@cs.wisc.edu result.add(mach); 7839745Snilay@cs.wisc.edu } 7849745Snilay@cs.wisc.edu d++; 7859745Snilay@cs.wisc.edu } 7869745Snilay@cs.wisc.edu } 7879745Snilay@cs.wisc.edu 7889745Snilay@cs.wisc.edu DEBUG_MSG(NETWORK_COMP, MedPrio, "returning shortest path"); 7899745Snilay@cs.wisc.edu DEBUG_EXPR(NETWORK_COMP, MedPrio, (src-(2*max_machines))); 7909745Snilay@cs.wisc.edu DEBUG_EXPR(NETWORK_COMP, MedPrio, (next-(2*max_machines))); 7919745Snilay@cs.wisc.edu DEBUG_EXPR(NETWORK_COMP, MedPrio, src); 7929745Snilay@cs.wisc.edu DEBUG_EXPR(NETWORK_COMP, MedPrio, next); 7939745Snilay@cs.wisc.edu DEBUG_EXPR(NETWORK_COMP, MedPrio, result); 7949745Snilay@cs.wisc.edu DEBUG_NEWLINE(NETWORK_COMP, MedPrio); 7959745Snilay@cs.wisc.edu 7969745Snilay@cs.wisc.edu return result; 7979745Snilay@cs.wisc.edu} 7989745Snilay@cs.wisc.edu 7999745Snilay@cs.wisc.edu