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