diff options
Diffstat (limited to 'src/mem/ruby/network/simple')
-rw-r--r-- | src/mem/ruby/network/simple/CustomTopology.cc | 140 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/CustomTopology.hh | 17 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/HierarchicalSwitchTopology.cc | 66 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/HierarchicalSwitchTopology.hh | 17 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/PerfectSwitch.cc | 12 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/PtToPtTopology.cc | 82 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/PtToPtTopology.hh | 17 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/SimpleNetwork.cc | 58 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/SimpleNetwork.hh | 8 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Switch.cc | 5 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Switch.hh | 2 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Throttle.cc | 13 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Throttle.hh | 5 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Topology.cc | 485 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Topology.hh | 21 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Torus2DTopology.cc | 84 | ||||
-rw-r--r-- | src/mem/ruby/network/simple/Torus2DTopology.hh | 17 |
17 files changed, 637 insertions, 412 deletions
diff --git a/src/mem/ruby/network/simple/CustomTopology.cc b/src/mem/ruby/network/simple/CustomTopology.cc new file mode 100644 index 000000000..829086f31 --- /dev/null +++ b/src/mem/ruby/network/simple/CustomTopology.cc @@ -0,0 +1,140 @@ + +#include "mem/ruby/network/simple/CustomTopology.hh" +#include "mem/protocol/MachineType.hh" + +static const int INFINITE_LATENCY = 10000; // Yes, this is a big hack +static const int DEFAULT_BW_MULTIPLIER = 1; // Just to be consistent with above :) + +// make a network as described by the networkFile +void CustomTopology::construct() +{ + + Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file + Vector<int> latencies; // link latencies for each link extracted + Vector<int> bw_multis; // bw multipliers for each link extracted + Vector<int> weights; // link weights used to enfore e-cube deadlock free routing + Vector< SwitchID > int_network_switches; // internal switches extracted from the file + Vector<bool> endpointConnectionExist; // used to ensure all endpoints are connected to the network + + endpointConnectionExist.setSize(m_nodes); + + // initialize endpoint check vector + for (int k = 0; k < endpointConnectionExist.size(); k++) { + endpointConnectionExist[k] = false; + } + + stringstream networkFile( m_connections ); + + string line = ""; + + while (!networkFile.eof()) { + + Vector < SwitchID > nodes; + nodes.setSize(2); + int latency = -1; // null latency + int weight = -1; // null weight + int bw_multiplier = DEFAULT_BW_MULTIPLIER; // default multiplier incase the network file doesn't define it + int i = 0; // node pair index + int varsFound = 0; // number of varsFound on the line + int internalNodes = 0; // used to determine if the link is between 2 internal nodes + std::getline(networkFile, line, '\n'); + string varStr = string_split(line, ' '); + + // parse the current line in the file + while (varStr != "") { + string label = string_split(varStr, ':'); + + // valid node labels + if (label == "ext_node" || label == "int_node") { + ASSERT(i < 2); // one link between 2 switches per line + varsFound++; + bool isNewIntSwitch = true; + if (label == "ext_node") { // input link to node + MachineType machine = string_to_MachineType(string_split(varStr, ':')); + string nodeStr = string_split(varStr, ':'); + nodes[i] = MachineType_base_number(machine) + + atoi(nodeStr.c_str()); + + // in nodes should be numbered 0 to m_nodes-1 + ASSERT(nodes[i] >= 0 && nodes[i] < m_nodes); + isNewIntSwitch = false; + endpointConnectionExist[nodes[i]] = true; + } + if (label == "int_node") { // interior node + nodes[i] = atoi((string_split(varStr, ':')).c_str())+m_nodes*2; + // in nodes should be numbered >= m_nodes*2 + ASSERT(nodes[i] >= m_nodes*2); + for (int k = 0; k < int_network_switches.size(); k++) { + if (int_network_switches[k] == nodes[i]) { + isNewIntSwitch = false; + } + } + if (isNewIntSwitch) { // if internal switch + m_number_of_switches++; + int_network_switches.insertAtBottom(nodes[i]); + } + internalNodes++; + } + i++; + } else if (label == "link_latency") { + latency = atoi((string_split(varStr, ':')).c_str()); + varsFound++; + } else if (label == "bw_multiplier") { // not necessary, defaults to DEFAULT_BW_MULTIPLIER + bw_multiplier = atoi((string_split(varStr, ':')).c_str()); + } else if (label == "link_weight") { // not necessary, defaults to link_latency + weight = atoi((string_split(varStr, ':')).c_str()); + } else { + cerr << "Error: Unexpected Identifier: " << label << endl; + exit(1); + } + varStr = string_split(line, ' '); + } + if (varsFound == 3) { // all three necessary link variables where found so add the link + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + if (weight != -1) { + weights.insertAtBottom(weight); + } else { + weights.insertAtBottom(latency); + } + bw_multis.insertAtBottom(bw_multiplier); + Vector < SwitchID > otherDirectionNodes; + otherDirectionNodes.setSize(2); + otherDirectionNodes[0] = nodes[1]; + if (internalNodes == 2) { // this is an internal link + otherDirectionNodes[1] = nodes[0]; + } else { + otherDirectionNodes[1] = nodes[0]+m_nodes; + } + nodePairs.insertAtBottom(otherDirectionNodes); + latencies.insertAtBottom(latency); + if (weight != -1) { + weights.insertAtBottom(weight); + } else { + weights.insertAtBottom(latency); + } + bw_multis.insertAtBottom(bw_multiplier); + } else { + if (varsFound != 0) { // if this is not a valid link, then no vars should have been found + cerr << "Error in line: " << line << endl; + exit(1); + } + } + } // end of file + + // makes sure all enpoints are connected in the soon to be created network + for (int k = 0; k < endpointConnectionExist.size(); k++) { + if (endpointConnectionExist[k] == false) { + cerr << "Error: Unconnected Endpoint: " << k << endl; + exit(1); + } + } + + ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size() && latencies.size() == weights.size()) + for (int k = 0; k < nodePairs.size(); k++) { + ASSERT(nodePairs[k].size() == 2); + addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k], weights[k]); + } + + // networkFile.close(); +} diff --git a/src/mem/ruby/network/simple/CustomTopology.hh b/src/mem/ruby/network/simple/CustomTopology.hh new file mode 100644 index 000000000..6c44eb049 --- /dev/null +++ b/src/mem/ruby/network/simple/CustomTopology.hh @@ -0,0 +1,17 @@ + +#ifndef CUSTOMTOPOLOGY_H +#define CUSTOMTOPOLOGY_H + +#include "mem/ruby/network/simple/Topology.hh" + +class CustomTopology : public Topology +{ +public: + CustomTopology(const string & name); + void init(const vector<string> & argv); + +protected: + void construct(); +}; + +#endif diff --git a/src/mem/ruby/network/simple/HierarchicalSwitchTopology.cc b/src/mem/ruby/network/simple/HierarchicalSwitchTopology.cc new file mode 100644 index 000000000..c0190e789 --- /dev/null +++ b/src/mem/ruby/network/simple/HierarchicalSwitchTopology.cc @@ -0,0 +1,66 @@ + +#include "mem/ruby/network/simple/HierarchicalSwitchTopology.hh" + +// hierarchical switch topology +void Topology::construct(int fan_out_degree) +{ + // Make a row of switches with only one input. This extra row makes + // sure the links out of the nodes have latency and limited + // bandwidth. + + // number of inter-chip switches, i.e. the last row of switches + Vector<SwitchID> last_level; + for (int i=0; i<m_nodes; i++) { + SwitchID new_switch = newSwitchID(); // internal switch id # + addLink(i, new_switch, m_network_ptr->getLinkLatency()); + last_level.insertAtBottom(new_switch); + } + + // Create Hierarchical Switches + + // start from the bottom level and work up to root + Vector<SwitchID> next_level; + while(last_level.size() > 1) { + for (int i=0; i<last_level.size(); i++) { + if ((i % fan_out_degree) == 0) { + next_level.insertAtBottom(newSwitchID()); + } + // Add this link to the last switch we created + addLink(last_level[i], next_level[next_level.size()-1], m_network_ptr->getLinkLatency()); + } + + // Make the current level the last level to get ready for next + // iteration + last_level = next_level; + next_level.clear(); + } + + SwitchID root_switch = last_level[0]; + + Vector<SwitchID> out_level; + for (int i=0; i<m_nodes; i++) { + out_level.insertAtBottom(m_nodes+i); + } + + // Build the down network from the endpoints to the root + while(out_level.size() != 1) { + + // A level of switches + for (int i=0; i<out_level.size(); i++) { + if ((i % fan_out_degree) == 0) { + if (out_level.size() > fan_out_degree) { + next_level.insertAtBottom(newSwitchID()); + } else { + next_level.insertAtBottom(root_switch); + } + } + // Add this link to the last switch we created + addLink(next_level[next_level.size()-1], out_level[i], m_network_ptr->getLinkLatency()); + } + + // Make the current level the last level to get ready for next + // iteration + out_level = next_level; + next_level.clear(); + } +} diff --git a/src/mem/ruby/network/simple/HierarchicalSwitchTopology.hh b/src/mem/ruby/network/simple/HierarchicalSwitchTopology.hh new file mode 100644 index 000000000..0c2c84ef8 --- /dev/null +++ b/src/mem/ruby/network/simple/HierarchicalSwitchTopology.hh @@ -0,0 +1,17 @@ + +#ifndef HIERARCHICALSWITCHTOPOLOGY_H +#define HIERARCHICALSWITCHTOPOLOGY_H + +#include "mem/ruby/network/simple/Topology.hh" + +class HierarchicalSwitchTopology : public Topology +{ +public: + HierarchicalSwitchTopology(const string & name); + void init(const vector<string> & argv); + +protected: + void construct(); +}; + +#endif diff --git a/src/mem/ruby/network/simple/PerfectSwitch.cc b/src/mem/ruby/network/simple/PerfectSwitch.cc index b561b69e2..4fd9af3eb 100644 --- a/src/mem/ruby/network/simple/PerfectSwitch.cc +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc @@ -55,7 +55,7 @@ bool operator<(const LinkOrder& l1, const LinkOrder& l2) { PerfectSwitch::PerfectSwitch(SwitchID sid, SimpleNetwork* network_ptr) { - m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; // FIXME - pass me as a parameter? + m_virtual_networks = network_ptr->getNumberOfVirtualNetworks(); m_switch_id = sid; m_round_robin_start = 0; m_network_ptr = network_ptr; @@ -88,9 +88,9 @@ void PerfectSwitch::addOutPort(const Vector<MessageBuffer*>& out, const NetDest& m_out.insertAtBottom(out); m_routing_table.insertAtBottom(routing_table_entry); - if (g_PRINT_TOPOLOGY) { + // if (RubyConfig::getPrintTopology()) { m_out_link_vec.insertAtBottom(out); - } + // } } void PerfectSwitch::clearRoutingTables() @@ -134,6 +134,7 @@ void PerfectSwitch::wakeup() int highest_prio_vnet = m_virtual_networks-1; int lowest_prio_vnet = 0; int decrementer = 1; + bool schedule_wakeup = false; NetworkMessage* net_msg_ptr = NULL; // invert priorities to avoid starvation seen in the component network @@ -186,8 +187,9 @@ void PerfectSwitch::wakeup() assert(m_link_order.size() == m_routing_table.size()); assert(m_link_order.size() == m_out.size()); - - if (g_adaptive_routing) { +//changed by SS +// if (RubyConfig::getAdaptiveRouting()) { + if (m_network_ptr->getAdaptiveRouting()) { if (m_network_ptr->isVNetOrdered(vnet)) { // Don't adaptively route for (int outlink=0; outlink<m_out.size(); outlink++) { diff --git a/src/mem/ruby/network/simple/PtToPtTopology.cc b/src/mem/ruby/network/simple/PtToPtTopology.cc new file mode 100644 index 000000000..9d178dbcc --- /dev/null +++ b/src/mem/ruby/network/simple/PtToPtTopology.cc @@ -0,0 +1,82 @@ + +#include "mem/protocol/MachineType.hh" +#include "mem/ruby/network/simple/PtToPtTopology.hh" + +// one internal node per chip, point to point links between chips +void PtToPtTopology::construct() +{ + Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file + Vector<int> latencies; // link latencies for each link extracted + Vector<int> bw_multis; // bw multipliers for each link extracted + + Vector < SwitchID > nodes; + nodes.setSize(2); + + // number of inter-chip switches + int numberOfChipSwitches = m_nodes/MachineType_base_level(MachineType_NUM); + // two switches per machine node grouping + // one intra-chip switch and one inter-chip switch per chip + for(int i=0; i<numberOfChipSwitches; i++){ + SwitchID new_switch = newSwitchID(); + new_switch = newSwitchID(); + } + + makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfChipSwitches); + + // connect intra-chip switch to inter-chip switch + for (int chip = 0; chip < RubyConfig::getNumberOfChips(); chip++) { + + int latency = m_network_ptr->getOnChipLinkLatency(); // internal link latency + int bw_multiplier = 10; // external link bw multiplier of the global bandwidth + + nodes[0] = chip+m_nodes*2; + nodes[1] = chip+m_nodes*2+RubyConfig::getNumberOfChips(); + + // insert link + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + + // opposite direction link + Vector < SwitchID > otherDirectionNodes; + otherDirectionNodes.setSize(2); + otherDirectionNodes[0] = nodes[1]; + otherDirectionNodes[1] = nodes[0]; + nodePairs.insertAtBottom(otherDirectionNodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + } + + // point-to-point network between chips + for (int chip = 0; chip < RubyConfig::getNumberOfChips(); chip++) { + for (int other_chip = chip+1; other_chip < RubyConfig::getNumberOfChips(); other_chip++) { + + int latency = m_network_ptr->getOffChipLinkLatency(); // external link latency + int bw_multiplier = 1; // external link bw multiplier of the global bandwidth + + nodes[0] = chip+m_nodes*2+RubyConfig::getNumberOfChips(); + nodes[1] = other_chip+m_nodes*2+RubyConfig::getNumberOfChips(); + + // insert link + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + + // opposite direction link + Vector < SwitchID > otherDirectionNodes; + otherDirectionNodes.setSize(2); + otherDirectionNodes[0] = nodes[1]; + otherDirectionNodes[1] = nodes[0]; + nodePairs.insertAtBottom(otherDirectionNodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + } + } + + // add links + ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size()) + for (int k = 0; k < nodePairs.size(); k++) { + ASSERT(nodePairs[k].size() == 2); + addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]); + } +} diff --git a/src/mem/ruby/network/simple/PtToPtTopology.hh b/src/mem/ruby/network/simple/PtToPtTopology.hh new file mode 100644 index 000000000..f15fa5956 --- /dev/null +++ b/src/mem/ruby/network/simple/PtToPtTopology.hh @@ -0,0 +1,17 @@ + +#ifndef PTTOPTTOPOLOGY_H +#define PTTOPTTOPOLOGY_H + +#include "mem/ruby/network/simple/Topology.hh" + +class PtToPtTopology : public Topology +{ +public: + PtToPtTopology(const string & name); + void init(const vector<string> & argv); + +protected: + void construct(); +}; + +#endif diff --git a/src/mem/ruby/network/simple/SimpleNetwork.cc b/src/mem/ruby/network/simple/SimpleNetwork.cc index 1d0567b6e..1a3b876bf 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.cc +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc @@ -59,11 +59,55 @@ Network* Network::createNetwork(int nodes) } */ +SimpleNetwork::SimpleNetwork(const string & name) + : Network(name) +{ + m_virtual_networks = 0; + m_topology_ptr = NULL; +} + +void SimpleNetwork::init(const vector<string> & argv) +{ + + Network::init(argv); + + m_endpoint_switches.setSize(m_nodes); + + m_in_use.setSize(m_virtual_networks); + m_ordered.setSize(m_virtual_networks); + for (int i = 0; i < m_virtual_networks; i++) { + m_in_use[i] = false; + m_ordered[i] = false; + } + + // Allocate to and from queues + m_toNetQueues.setSize(m_nodes); + m_fromNetQueues.setSize(m_nodes); + for (int node = 0; node < m_nodes; node++) { + m_toNetQueues[node].setSize(m_virtual_networks); + m_fromNetQueues[node].setSize(m_virtual_networks); + for (int j = 0; j < m_virtual_networks; j++) { + cerr << "Creating new MessageBuffer for " << node << " " << j << endl; + m_toNetQueues[node][j] = new MessageBuffer; + m_fromNetQueues[node][j] = new MessageBuffer; + } + } + + // Setup the network switches + // m_topology_ptr = new Topology(this, m_nodes); + m_topology_ptr->makeTopology(); + int number_of_switches = m_topology_ptr->numSwitches(); + for (int i=0; i<number_of_switches; i++) { + m_switch_ptr_vector.insertAtBottom(new Switch(i, this)); + } + m_topology_ptr->createLinks(false); // false because this isn't a reconfiguration +} +/* SimpleNetwork::SimpleNetwork(int nodes) { m_nodes = MachineType_base_number(MachineType_NUM); - m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; + m_virtual_networks = RubyConfig::getNumberOfVirtualNetworks(); m_endpoint_switches.setSize(m_nodes); m_in_use.setSize(m_virtual_networks); @@ -93,7 +137,7 @@ SimpleNetwork::SimpleNetwork(int nodes) } m_topology_ptr->createLinks(false); // false because this isn't a reconfiguration } - +*/ void SimpleNetwork::reset() { for (int node = 0; node < m_nodes; node++) { @@ -154,8 +198,8 @@ void SimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, const NetDest& // allocate a buffer MessageBuffer* buffer_ptr = new MessageBuffer; buffer_ptr->setOrdering(true); - if(FINITE_BUFFERING) { - buffer_ptr->setSize(FINITE_BUFFER_SIZE); + if (m_buffer_size > 0) { + buffer_ptr->setSize(m_buffer_size); } queues.insertAtBottom(buffer_ptr); // remember to deallocate it @@ -225,7 +269,7 @@ void SimpleNetwork::printConfig(ostream& out) const out << "Network Configuration" << endl; out << "---------------------" << endl; out << "network: SIMPLE_NETWORK" << endl; - out << "topology: " << g_NETWORK_TOPOLOGY << endl; + out << "topology: " << m_topology_ptr->getName() << endl; out << endl; for (int i = 0; i < m_virtual_networks; i++) { @@ -246,9 +290,7 @@ void SimpleNetwork::printConfig(ostream& out) const m_switch_ptr_vector[i]->printConfig(out); } - if (g_PRINT_TOPOLOGY) { - m_topology_ptr->printConfig(out); - } + m_topology_ptr->printConfig(out); } void SimpleNetwork::print(ostream& out) const diff --git a/src/mem/ruby/network/simple/SimpleNetwork.hh b/src/mem/ruby/network/simple/SimpleNetwork.hh index 39ee2c095..9ffd862d3 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.hh +++ b/src/mem/ruby/network/simple/SimpleNetwork.hh @@ -83,11 +83,14 @@ class Topology; class SimpleNetwork : public Network { public: // Constructors - SimpleNetwork(int nodes); + // SimpleNetwork(int nodes); + SimpleNetwork(const string & name); // Destructor ~SimpleNetwork(); + void init(const vector<string> & argv); + // Public Methods void printStats(ostream& out) const; void clearStats(); @@ -130,14 +133,11 @@ private: Vector<Vector<MessageBuffer*> > m_toNetQueues; Vector<Vector<MessageBuffer*> > m_fromNetQueues; - int m_nodes; - int m_virtual_networks; Vector<bool> m_in_use; Vector<bool> m_ordered; Vector<Switch*> m_switch_ptr_vector; Vector<MessageBuffer*> m_buffers_to_free; Vector<Switch*> m_endpoint_switches; - Topology* m_topology_ptr; }; // Output operator declaration diff --git a/src/mem/ruby/network/simple/Switch.cc b/src/mem/ruby/network/simple/Switch.cc index 192520e85..e3420ddae 100644 --- a/src/mem/ruby/network/simple/Switch.cc +++ b/src/mem/ruby/network/simple/Switch.cc @@ -82,8 +82,9 @@ void Switch::addOutPort(const Vector<MessageBuffer*>& out, const NetDest& routin MessageBuffer* buffer_ptr = new MessageBuffer; // Make these queues ordered buffer_ptr->setOrdering(true); - if(FINITE_BUFFERING) { - buffer_ptr->setSize(FINITE_BUFFER_SIZE); + Network* net_ptr = RubySystem::getNetwork(); + if(net_ptr->getBufferSize() > 0) { + buffer_ptr->setSize(net_ptr->getBufferSize()); } intermediateBuffers.insertAtBottom(buffer_ptr); m_buffers_to_free.insertAtBottom(buffer_ptr); diff --git a/src/mem/ruby/network/simple/Switch.hh b/src/mem/ruby/network/simple/Switch.hh index 58bde05ea..193898928 100644 --- a/src/mem/ruby/network/simple/Switch.hh +++ b/src/mem/ruby/network/simple/Switch.hh @@ -52,6 +52,7 @@ class PerfectSwitch; class NetDest; class SimpleNetwork; class Throttle; +class Network; class Switch { public: @@ -83,6 +84,7 @@ private: // Data Members (m_ prefix) PerfectSwitch* m_perfect_switch_ptr; + Network* m_network_ptr; Vector<Throttle*> m_throttles; Vector<MessageBuffer*> m_buffers_to_free; SwitchID m_switch_id; diff --git a/src/mem/ruby/network/simple/Throttle.cc b/src/mem/ruby/network/simple/Throttle.cc index f91bbdb30..1cfe88987 100644 --- a/src/mem/ruby/network/simple/Throttle.cc +++ b/src/mem/ruby/network/simple/Throttle.cc @@ -103,9 +103,9 @@ void Throttle::addLinks(const Vector<MessageBuffer*>& in_vec, const Vector<Messa } } - if (g_PRINT_TOPOLOGY) { + // if (RubyConfig::getPrintTopology()) { m_out_link_vec.insertAtBottom(out_vec); - } + // } } void Throttle::addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr) @@ -206,13 +206,8 @@ void Throttle::wakeup() while ((current_time - m_last_bandwidth_sample) > ADJUST_INTERVAL) { double utilization = m_bandwidth_since_sample/double(ADJUST_INTERVAL * getLinkBandwidth()); - if (utilization > g_bash_bandwidth_adaptive_threshold) { - // Used more bandwidth - m_bash_counter++; - } else { - // Used less bandwidth - m_bash_counter--; - } + // Used less bandwidth + m_bash_counter--; // Make sure we don't overflow m_bash_counter = min(HIGH_RANGE, m_bash_counter); diff --git a/src/mem/ruby/network/simple/Throttle.hh b/src/mem/ruby/network/simple/Throttle.hh index 067c7af5f..7b6d04353 100644 --- a/src/mem/ruby/network/simple/Throttle.hh +++ b/src/mem/ruby/network/simple/Throttle.hh @@ -46,7 +46,8 @@ #include "mem/gems_common/Vector.hh" #include "mem/ruby/common/Consumer.hh" #include "mem/ruby/system/NodeID.hh" -#include "mem/ruby/config/RubyConfig.hh" +#include "mem/ruby/system/System.hh" +#include "mem/ruby/network/Network.hh" class MessageBuffer; @@ -68,7 +69,7 @@ public: void clearStats(); void printConfig(ostream& out) const; double getUtilization() const; // The average utilization (a percent) since last clearStats() - int getLinkBandwidth() const { return g_endpoint_bandwidth * m_link_bandwidth_multiplier; } + int getLinkBandwidth() const { return RubySystem::getNetwork()->getEndpointBandwidth() * m_link_bandwidth_multiplier; } int getLatency() const { return m_link_latency; } const Vector<Vector<int> >& getCounters() const { return m_message_counters; } diff --git a/src/mem/ruby/network/simple/Topology.cc b/src/mem/ruby/network/simple/Topology.cc index f887f2a04..742bfe3cd 100644 --- a/src/mem/ruby/network/simple/Topology.cc +++ b/src/mem/ruby/network/simple/Topology.cc @@ -40,10 +40,11 @@ #include "mem/ruby/common/NetDest.hh" #include "mem/ruby/network/Network.hh" #include "mem/protocol/TopologyType.hh" -#include "mem/ruby/config/RubyConfig.hh" +//#include "mem/ruby/config/RubyConfig.hh" #include "mem/gems_common/util.hh" #include "mem/protocol/MachineType.hh" #include "mem/protocol/Protocol.hh" +#include "mem/ruby/system/System.hh" #include <string> static const int INFINITE_LATENCY = 10000; // Yes, this is a big hack @@ -57,359 +58,45 @@ static const int DEFAULT_BW_MULTIPLIER = 1; // Just to be consistent with above // of the network. // Helper functions based on chapter 29 of Cormen et al. -static void extend_shortest_path(Matrix& current_dist, Matrix& latencies, Matrix& inter_switches); +static Matrix extend_shortest_path(const Matrix& current_dist, Matrix& latencies, Matrix& inter_switches); static Matrix shortest_path(const Matrix& weights, Matrix& latencies, Matrix& inter_switches); static bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, const Matrix& weights, const Matrix& dist); static NetDest shortest_path_to_node(SwitchID src, SwitchID next, const Matrix& weights, const Matrix& dist); - -Topology::Topology(Network* network_ptr, int number_of_nodes) +Topology::Topology(const string & name) + : m_name(name) { - m_network_ptr = network_ptr; - m_nodes = number_of_nodes; + m_network_ptr = NULL; + m_nodes = MachineType_base_number(MachineType_NUM); m_number_of_switches = 0; - init(); -} - -void Topology::init() -{ - if (m_nodes == 1) { - SwitchID id = newSwitchID(); - addLink(0, id, NETWORK_LINK_LATENCY); - addLink(id, 1, NETWORK_LINK_LATENCY); - return; - } - - // topology-specific set-up - TopologyType topology = string_to_TopologyType(g_NETWORK_TOPOLOGY); - switch (topology) { - case TopologyType_TORUS_2D: - make2DTorus(); - break; - case TopologyType_HIERARCHICAL_SWITCH: - makeHierarchicalSwitch(FAN_OUT_DEGREE); - break; - case TopologyType_CROSSBAR: - makeHierarchicalSwitch(1024); - break; - case TopologyType_PT_TO_PT: - makePtToPt(); - break; - case TopologyType_FILE_SPECIFIED: - makeFileSpecified(); - break; - default: - ERROR_MSG("Unexpected typology type") - } - - // initialize component latencies record - m_component_latencies.setSize(0); - m_component_inter_switches.setSize(0); -} - -void Topology::makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChipSwitches) -{ - - Vector < SwitchID > nodes; // temporary buffer - nodes.setSize(2); - - Vector<bool> endpointConnectionExist; // used to ensure all endpoints are connected to the network - endpointConnectionExist.setSize(m_nodes); - // initialize endpoint check vector - for (int k = 0; k < endpointConnectionExist.size(); k++) { - endpointConnectionExist[k] = false; - } - - Vector<int> componentCount; - componentCount.setSize(MachineType_NUM); - for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { - componentCount[mType] = 0; - } - - // components to/from network links - for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) { - for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { - for (int component = 0; component < MachineType_chip_count(mType, chip); component++) { - - int latency = -1; - int bw_multiplier = -1; // internal link bw multiplier of the global bandwidth - if (mType != MachineType_Directory) { - latency = ON_CHIP_LINK_LATENCY; // internal link latency - bw_multiplier = 10; // internal link bw multiplier of the global bandwidth - } else { - latency = NETWORK_LINK_LATENCY; // local memory latency - bw_multiplier = 1; // local memory link bw multiplier of the global bandwidth - } - nodes[0] = MachineType_base_number(mType)+componentCount[mType]; - nodes[1] = chip+m_nodes*2; // this is the chip's internal switch id # - - // insert link - nodePairs.insertAtBottom(nodes); - latencies.insertAtBottom(latency); - //bw_multis.insertAtBottom(bw_multiplier); - bw_multis.insertAtBottom(componentCount[mType]+MachineType_base_number((MachineType)mType)); - - // opposite direction link - Vector < SwitchID > otherDirectionNodes; - otherDirectionNodes.setSize(2); - otherDirectionNodes[0] = nodes[1]; - otherDirectionNodes[1] = nodes[0]+m_nodes; - nodePairs.insertAtBottom(otherDirectionNodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - - assert(!endpointConnectionExist[nodes[0]]); - endpointConnectionExist[nodes[0]] = true; - componentCount[mType]++; - } - } - } - - // make sure all enpoints are connected in the soon to be created network - for (int k = 0; k < endpointConnectionExist.size(); k++) { - if (endpointConnectionExist[k] == false) { - cerr << "Error: Unconnected Endpoint: " << k << endl; - exit(1); - } - } - - // secondary check to ensure we saw the correct machine counts - for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { - assert(componentCount[mType] == MachineType_base_count((MachineType)mType)); - } - -} - -// 2D torus topology - -void Topology::make2DTorus() -{ - Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file - Vector<int> latencies; // link latencies for each link extracted - Vector<int> bw_multis; // bw multipliers for each link extracted - - Vector < SwitchID > nodes; // temporary buffer - nodes.setSize(2); - - // number of inter-chip switches - int numberOfTorusSwitches = m_nodes/MachineType_base_level(MachineType_NUM); - // one switch per machine node grouping - Vector<SwitchID> torusSwitches; - for(int i=0; i<numberOfTorusSwitches; i++){ - SwitchID new_switch = newSwitchID(); - torusSwitches.insertAtBottom(new_switch); - } - - makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfTorusSwitches); - - int lengthOfSide = (int)sqrt((double)numberOfTorusSwitches); - - // Now connect the inter-chip torus links - - int latency = NETWORK_LINK_LATENCY; // external link latency - int bw_multiplier = 1; // external link bw multiplier of the global bandwidth - - for(int i=0; i<numberOfTorusSwitches; i++){ - nodes[0] = torusSwitches[i]; // current switch - - // left - if(nodes[0]%lengthOfSide == 0){ // determine left neighbor - nodes[1] = nodes[0] - 1 + lengthOfSide; - } else { - nodes[1] = nodes[0] - 1; - } - nodePairs.insertAtBottom(nodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - - // right - if((nodes[0] + 1)%lengthOfSide == 0){ // determine right neighbor - nodes[1] = nodes[0] + 1 - lengthOfSide; - } else { - nodes[1] = nodes[0] + 1; - } - nodePairs.insertAtBottom(nodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - - // top - if(nodes[0] - lengthOfSide < 2*m_nodes){ // determine if node is on the top - nodes[1] = nodes[0] - lengthOfSide + (lengthOfSide*lengthOfSide); - } else { - nodes[1] = nodes[0] - lengthOfSide; - } - nodePairs.insertAtBottom(nodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - - // bottom - if(nodes[0] + lengthOfSide >= 2*m_nodes+numberOfTorusSwitches){ // determine if node is on the bottom - // sorin: bad bug if this is a > instead of a >= - nodes[1] = nodes[0] + lengthOfSide - (lengthOfSide*lengthOfSide); - } else { - nodes[1] = nodes[0] + lengthOfSide; - } - nodePairs.insertAtBottom(nodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - - } - - // add links - ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size()) - for (int k = 0; k < nodePairs.size(); k++) { - ASSERT(nodePairs[k].size() == 2); - addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]); - } - } -// hierarchical switch topology -void Topology::makeHierarchicalSwitch(int fan_out_degree) +void Topology::init(const vector<string> & argv) { - // Make a row of switches with only one input. This extra row makes - // sure the links out of the nodes have latency and limited - // bandwidth. - - // number of inter-chip switches, i.e. the last row of switches - Vector<SwitchID> last_level; - for (int i=0; i<m_nodes; i++) { - SwitchID new_switch = newSwitchID(); // internal switch id # - addLink(i, new_switch, NETWORK_LINK_LATENCY); - last_level.insertAtBottom(new_switch); - } - - // Create Hierarchical Switches - - // start from the bottom level and work up to root - Vector<SwitchID> next_level; - while(last_level.size() > 1) { - for (int i=0; i<last_level.size(); i++) { - if ((i % fan_out_degree) == 0) { - next_level.insertAtBottom(newSwitchID()); - } - // Add this link to the last switch we created - addLink(last_level[i], next_level[next_level.size()-1], NETWORK_LINK_LATENCY); - } - - // Make the current level the last level to get ready for next - // iteration - last_level = next_level; - next_level.clear(); - } - - SwitchID root_switch = last_level[0]; - - Vector<SwitchID> out_level; - for (int i=0; i<m_nodes; i++) { - out_level.insertAtBottom(m_nodes+i); - } - - // Build the down network from the endpoints to the root - while(out_level.size() != 1) { - - // A level of switches - for (int i=0; i<out_level.size(); i++) { - if ((i % fan_out_degree) == 0) { - if (out_level.size() > fan_out_degree) { - next_level.insertAtBottom(newSwitchID()); - } else { - next_level.insertAtBottom(root_switch); - } - } - // Add this link to the last switch we created - addLink(next_level[next_level.size()-1], out_level[i], NETWORK_LINK_LATENCY); + for (size_t i=0; i<argv.size(); i+=2) { + if (argv[i] == "network") + m_network_ptr = RubySystem::getNetwork(); + else if (argv[i] == "connections") + m_connections = argv[i+1]; + else if (argv[i] == "print_config") { + m_print_config = string_to_bool(argv[i+1]); + cerr << "print config: " << m_print_config << endl; } - - // Make the current level the last level to get ready for next - // iteration - out_level = next_level; - next_level.clear(); } + assert(m_network_ptr != NULL); } -// one internal node per chip, point to point links between chips -void Topology::makePtToPt() +void Topology::makeTopology() { - Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file - Vector<int> latencies; // link latencies for each link extracted - Vector<int> bw_multis; // bw multipliers for each link extracted - - Vector < SwitchID > nodes; - nodes.setSize(2); - - // number of inter-chip switches - int numberOfChipSwitches = m_nodes/MachineType_base_level(MachineType_NUM); - // two switches per machine node grouping - // one intra-chip switch and one inter-chip switch per chip - for(int i=0; i<numberOfChipSwitches; i++){ - SwitchID new_switch = newSwitchID(); - new_switch = newSwitchID(); - } - - makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfChipSwitches); - - // connect intra-chip switch to inter-chip switch - for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) { - - int latency = ON_CHIP_LINK_LATENCY; // internal link latency - int bw_multiplier = 10; // external link bw multiplier of the global bandwidth - - nodes[0] = chip+m_nodes*2; - nodes[1] = chip+m_nodes*2+RubyConfig::numberOfChips(); - - // insert link - nodePairs.insertAtBottom(nodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - - // opposite direction link - Vector < SwitchID > otherDirectionNodes; - otherDirectionNodes.setSize(2); - otherDirectionNodes[0] = nodes[1]; - otherDirectionNodes[1] = nodes[0]; - nodePairs.insertAtBottom(otherDirectionNodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - } - - // point-to-point network between chips - for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) { - for (int other_chip = chip+1; other_chip < RubyConfig::numberOfChips(); other_chip++) { - - int latency = NETWORK_LINK_LATENCY; // external link latency - int bw_multiplier = 1; // external link bw multiplier of the global bandwidth - - nodes[0] = chip+m_nodes*2+RubyConfig::numberOfChips(); - nodes[1] = other_chip+m_nodes*2+RubyConfig::numberOfChips(); - - // insert link - nodePairs.insertAtBottom(nodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - - // opposite direction link - Vector < SwitchID > otherDirectionNodes; - otherDirectionNodes.setSize(2); - otherDirectionNodes[0] = nodes[1]; - otherDirectionNodes[1] = nodes[0]; - nodePairs.insertAtBottom(otherDirectionNodes); - latencies.insertAtBottom(latency); - bw_multis.insertAtBottom(bw_multiplier); - } - } - - // add links - ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size()) - for (int k = 0; k < nodePairs.size(); k++) { - ASSERT(nodePairs[k].size() == 2); - addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]); + /* + if (m_nodes == 1) { + SwitchID id = newSwitchID(); + addLink(0, id, m_network_ptr->getOffChipLinkLatency()); + addLink(id, 1, m_network_ptr->getOffChipLinkLatency()); + return; } -} - -// make a network as described by the networkFile -void Topology::makeFileSpecified() -{ + */ + assert(m_nodes > 1); Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file Vector<int> latencies; // link latencies for each link extracted @@ -425,21 +112,7 @@ void Topology::makeFileSpecified() endpointConnectionExist[k] = false; } - string filename = "network/simple/Network_Files/"; - filename = filename+g_CACHE_DESIGN - +"_Procs-"+int_to_string(RubyConfig::numberOfProcessors()) - +"_ProcsPerChip-"+int_to_string(RubyConfig::numberOfProcsPerChip()) - +"_L2Banks-"+int_to_string(RubyConfig::numberOfL2Cache()) - +"_Memories-"+int_to_string(RubyConfig::numberOfMemories()) - +".txt"; - - ifstream networkFile( filename.c_str() , ios::in); - if (!networkFile.is_open()) { - cerr << "Error: Could not open network file: " << filename << endl; - cerr << "Probably no network file exists for " << RubyConfig::numberOfProcessors() - << " processors and " << RubyConfig::numberOfProcsPerChip() << " procs per chip " << endl; - exit(1); - } + stringstream networkFile( m_connections ); string line = ""; @@ -468,14 +141,9 @@ void Topology::makeFileSpecified() if (label == "ext_node") { // input link to node MachineType machine = string_to_MachineType(string_split(varStr, ':')); string nodeStr = string_split(varStr, ':'); - if (string_split(varStr, ':') == "bank") { - nodes[i] = MachineType_base_number(machine) - + atoi(nodeStr.c_str()) - + atoi((string_split(varStr, ':')).c_str())*RubyConfig::numberOfChips(); - } else { - nodes[i] = MachineType_base_number(machine) - + atoi(nodeStr.c_str()); - } + nodes[i] = MachineType_base_number(machine) + + atoi(nodeStr.c_str()); + // in nodes should be numbered 0 to m_nodes-1 ASSERT(nodes[i] >= 0 && nodes[i] < m_nodes); isNewIntSwitch = false; @@ -504,16 +172,6 @@ void Topology::makeFileSpecified() bw_multiplier = atoi((string_split(varStr, ':')).c_str()); } else if (label == "link_weight") { // not necessary, defaults to link_latency weight = atoi((string_split(varStr, ':')).c_str()); - } else if (label == "processors") { - ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfProcessors()); - } else if (label == "bw_unit") { - ASSERT(atoi((string_split(varStr, ':')).c_str()) == g_endpoint_bandwidth); - } else if (label == "procs_per_chip") { - ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfProcsPerChip()); - } else if (label == "L2banks") { - ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfL2Cache()); - } else if (label == "memories") { - ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfMemories()); } else { cerr << "Error: Unexpected Identifier: " << label << endl; exit(1); @@ -567,9 +225,12 @@ void Topology::makeFileSpecified() addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k], weights[k]); } - networkFile.close(); + // initialize component latencies record + m_component_latencies.setSize(0); + m_component_inter_switches.setSize(0); } + void Topology::createLinks(bool isReconfiguration) { // Find maximum switchID @@ -633,6 +294,82 @@ void Topology::createLinks(bool isReconfiguration) } } } +/* +void Topology::makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChipSwitches) +{ + + Vector < SwitchID > nodes; // temporary buffer + nodes.setSize(2); + + Vector<bool> endpointConnectionExist; // used to ensure all endpoints are connected to the network + endpointConnectionExist.setSize(m_nodes); + // initialize endpoint check vector + for (int k = 0; k < endpointConnectionExist.size(); k++) { + endpointConnectionExist[k] = false; + } + + Vector<int> componentCount; + componentCount.setSize(MachineType_NUM); + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { + componentCount[mType] = 0; + } + + // components to/from network links + // TODO: drh5: bring back chips!!! + for (int chip = 0; chip < RubyConfig::getNumberOfChips(); chip++) { + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { + for (int component = 0; component < MachineType_base_count(mType); component++) { + + int latency = -1; + int bw_multiplier = -1; // internal link bw multiplier of the global bandwidth + if (mType != MachineType_Directory) { + latency = RubyConfig::getOnChipLinkLatency(); // internal link latency + bw_multiplier = 10; // internal link bw multiplier of the global bandwidth + } else { + latency = RubyConfig::getNetworkLinkLatency(); // local memory latency + bw_multiplier = 1; // local memory link bw multiplier of the global bandwidth + } + nodes[0] = MachineType_base_number(mType)+componentCount[mType]; + nodes[1] = chip+m_nodes*2; // this is the chip's internal switch id # + + // insert link + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + //bw_multis.insertAtBottom(componentCount[mType]+MachineType_base_number((MachineType)mType)); + + // opposite direction link + Vector < SwitchID > otherDirectionNodes; + otherDirectionNodes.setSize(2); + otherDirectionNodes[0] = nodes[1]; + otherDirectionNodes[1] = nodes[0]+m_nodes; + nodePairs.insertAtBottom(otherDirectionNodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + + assert(!endpointConnectionExist[nodes[0]]); + endpointConnectionExist[nodes[0]] = true; + componentCount[mType]++; + } + } + } + + // make sure all enpoints are connected in the soon to be created network + for (int k = 0; k < endpointConnectionExist.size(); k++) { + if (endpointConnectionExist[k] == false) { + cerr << "Error: Unconnected Endpoint: " << k << endl; + exit(1); + } + } + + // secondary check to ensure we saw the correct machine counts + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { + assert(componentCount[mType] == MachineType_base_count((MachineType)mType)); + } + +} +*/ + SwitchID Topology::newSwitchID() { @@ -680,6 +417,8 @@ void Topology::makeLink(SwitchID src, SwitchID dest, const NetDest& routing_tabl void Topology::printConfig(ostream& out) const { + if (m_print_config == false) return; + assert(m_component_latencies.size() > 0); out << "--- Begin Topology Print ---" << endl; diff --git a/src/mem/ruby/network/simple/Topology.hh b/src/mem/ruby/network/simple/Topology.hh index cb6c36f17..0f8cdff3b 100644 --- a/src/mem/ruby/network/simple/Topology.hh +++ b/src/mem/ruby/network/simple/Topology.hh @@ -59,21 +59,26 @@ typedef Vector < Vector <int> > Matrix; class Topology { public: // Constructors - Topology(Network* network_ptr, int number_of_nodes); + // Topology(Network* network_ptr, int number_of_nodes); + Topology(const string & name); // Destructor - ~Topology() {} + virtual ~Topology() {} + + virtual void init(const vector<string> & argv); // Public Methods + void makeTopology(); int numSwitches() const { return m_number_of_switches; } void createLinks(bool isReconfiguration); + const string getName() { return m_name; } void printStats(ostream& out) const {} void clearStats() {} void printConfig(ostream& out) const; void print(ostream& out) const { out << "[Topology]"; } -private: +protected: // Private Methods void init(); SwitchID newSwitchID(); @@ -82,12 +87,7 @@ private: void addLink(SwitchID src, SwitchID dest, int link_latency, int bw_multiplier, int link_weight); void makeLink(SwitchID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency, int weight, int bw_multiplier, bool isReconfiguration); - void makeHierarchicalSwitch(int fan_out_degree); - void make2DTorus(); - void makePtToPt(); - void makeFileSpecified(); - - void makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChips); + // void makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChips); string getDesignStr(); // Private copy constructor and assignment operator @@ -95,7 +95,10 @@ private: Topology& operator=(const Topology& obj); // Data Members (m_ prefix) + string m_name; + bool m_print_config; Network* m_network_ptr; + string m_connections; NodeID m_nodes; int m_number_of_switches; diff --git a/src/mem/ruby/network/simple/Torus2DTopology.cc b/src/mem/ruby/network/simple/Torus2DTopology.cc new file mode 100644 index 000000000..e66c6dc0b --- /dev/null +++ b/src/mem/ruby/network/simple/Torus2DTopology.cc @@ -0,0 +1,84 @@ + +// 2D torus topology + +void Torus2DTopology::construct() +{ + Vector< Vector < SwitchID > > nodePairs; // node pairs extracted from the file + Vector<int> latencies; // link latencies for each link extracted + Vector<int> bw_multis; // bw multipliers for each link extracted + + Vector < SwitchID > nodes; // temporary buffer + nodes.setSize(2); + + // number of inter-chip switches + int numberOfTorusSwitches = m_nodes/MachineType_base_level(MachineType_NUM); + // one switch per machine node grouping + Vector<SwitchID> torusSwitches; + for(int i=0; i<numberOfTorusSwitches; i++){ + SwitchID new_switch = newSwitchID(); + torusSwitches.insertAtBottom(new_switch); + } + + makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfTorusSwitches); + + int lengthOfSide = (int)sqrt((double)numberOfTorusSwitches); + + // Now connect the inter-chip torus links + + int latency = m_network_ptr->getLinkLatency(); // external link latency + int bw_multiplier = 1; // external link bw multiplier of the global bandwidth + + for(int i=0; i<numberOfTorusSwitches; i++){ + nodes[0] = torusSwitches[i]; // current switch + + // left + if(nodes[0]%lengthOfSide == 0){ // determine left neighbor + nodes[1] = nodes[0] - 1 + lengthOfSide; + } else { + nodes[1] = nodes[0] - 1; + } + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + + // right + if((nodes[0] + 1)%lengthOfSide == 0){ // determine right neighbor + nodes[1] = nodes[0] + 1 - lengthOfSide; + } else { + nodes[1] = nodes[0] + 1; + } + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + + // top + if(nodes[0] - lengthOfSide < 2*m_nodes){ // determine if node is on the top + nodes[1] = nodes[0] - lengthOfSide + (lengthOfSide*lengthOfSide); + } else { + nodes[1] = nodes[0] - lengthOfSide; + } + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + + // bottom + if(nodes[0] + lengthOfSide >= 2*m_nodes+numberOfTorusSwitches){ // determine if node is on the bottom + // sorin: bad bug if this is a > instead of a >= + nodes[1] = nodes[0] + lengthOfSide - (lengthOfSide*lengthOfSide); + } else { + nodes[1] = nodes[0] + lengthOfSide; + } + nodePairs.insertAtBottom(nodes); + latencies.insertAtBottom(latency); + bw_multis.insertAtBottom(bw_multiplier); + + } + + // add links + ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size()) + for (int k = 0; k < nodePairs.size(); k++) { + ASSERT(nodePairs[k].size() == 2); + addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]); + } + +} diff --git a/src/mem/ruby/network/simple/Torus2DTopology.hh b/src/mem/ruby/network/simple/Torus2DTopology.hh new file mode 100644 index 000000000..83a314e94 --- /dev/null +++ b/src/mem/ruby/network/simple/Torus2DTopology.hh @@ -0,0 +1,17 @@ + +#ifndef TORUS2DTOPOLOGY_H +#define TORUS2DTOPOLOGY_H + +#include "mem/ruby/network/simple/Topology.hh" + +class Torus2DTopology : public Topology +{ +public: + Torus2DTopology(const string & name); + void init(const vector<string> & argv); + +protected: + void construct(); +}; + +#endif |