diff options
Diffstat (limited to 'src/mem/ruby/network')
37 files changed, 851 insertions, 531 deletions
diff --git a/src/mem/ruby/network/Network.cc b/src/mem/ruby/network/Network.cc new file mode 100644 index 000000000..cb3507471 --- /dev/null +++ b/src/mem/ruby/network/Network.cc @@ -0,0 +1,34 @@ + +#include "mem/protocol/MachineType.hh" +#include "mem/ruby/network/Network.hh" + +Network::Network(const string & name) + : m_name(name) +{ + m_virtual_networks = 0; + m_topology_ptr = NULL; +} + +void Network::init(const vector<string> & argv) +{ + m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network + + for (size_t i=0; i<argv.size(); i+=2) { + if (argv[i] == "number_of_virtual_networks") + m_virtual_networks = atoi(argv[i+1].c_str()); + else if (argv[i] == "topology") + m_topology_ptr = RubySystem::getTopology(argv[i+1]); + else if (argv[i] == "buffer_size") + m_buffer_size = atoi(argv[i+1].c_str()); + else if (argv[i] == "endpoint_bandwidth") + m_endpoint_bandwidth = atoi(argv[i+1].c_str()); + else if (argv[i] == "adaptive_routing") + m_adaptive_routing = (argv[i+1]=="true"); + else if (argv[i] == "link_latency") + m_link_latency = atoi(argv[i+1].c_str()); + + } + assert(m_virtual_networks != 0); + assert(m_topology_ptr != NULL); +// printf ("HERE \n"); +} diff --git a/src/mem/ruby/network/Network.hh b/src/mem/ruby/network/Network.hh index d3bfa59da..5730d6591 100644 --- a/src/mem/ruby/network/Network.hh +++ b/src/mem/ruby/network/Network.hh @@ -49,22 +49,29 @@ #include "mem/ruby/common/Global.hh" #include "mem/ruby/system/NodeID.hh" #include "mem/protocol/MessageSizeType.hh" +#include "mem/ruby/system/System.hh" +#include "mem/ruby/config/RubyConfig.hh" class NetDest; class MessageBuffer; class Throttle; +class Topology; class Network { public: // Constructors - Network() {} + Network(const string & name); + virtual void init(const vector<string> & argv); // Destructor virtual ~Network() {} // Public Methods - - static Network* createNetwork(int nodes); + int getBufferSize() { return m_buffer_size; } + int getNumberOfVirtualNetworks() { return m_virtual_networks; } + int getEndpointBandwidth() { return m_endpoint_bandwidth; } + bool getAdaptiveRouting() {return m_adaptive_routing; } + int getLinkLatency() { return m_link_latency; } // returns the queue requested for the given component virtual MessageBuffer* getToNetQueue(NodeID id, bool ordered, int netNumber) = 0; @@ -84,7 +91,7 @@ public: virtual void printConfig(ostream& out) const = 0; virtual void print(ostream& out) const = 0; -private: +protected: // Private Methods // Private copy constructor and assignment operator @@ -92,6 +99,15 @@ private: Network& operator=(const Network& obj); // Data Members (m_ prefix) +protected: + const string m_name; + int m_nodes; + int m_virtual_networks; + int m_buffer_size; + int m_endpoint_bandwidth; + Topology* m_topology_ptr; + bool m_adaptive_routing; + int m_link_latency; }; // Output operator declaration @@ -110,7 +126,7 @@ ostream& operator<<(ostream& out, const Network& obj) // Code to map network message size types to an integer number of bytes const int CONTROL_MESSAGE_SIZE = 8; -const int DATA_MESSAGE_SIZE = (64+8); +const int DATA_MESSAGE_SIZE = (RubySystem::getBlockSizeBytes()+8); extern inline int MessageSizeType_to_int(MessageSizeType size_type) diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh index 5e68198cc..387ed0bc1 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh @@ -11,7 +11,7 @@ class CreditLink_d : public NetworkLink_d { public: - CreditLink_d(int id):NetworkLink_d(id) {} + CreditLink_d(int id, int link_latency, GarnetNetwork_d *net_ptr):NetworkLink_d(id, link_latency, net_ptr) {} }; #endif diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc index 988b634ce..51393b576 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc @@ -43,10 +43,19 @@ #include "mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh" #include "mem/ruby/common/NetDest.hh" -GarnetNetwork_d::GarnetNetwork_d(int nodes) +GarnetNetwork_d::GarnetNetwork_d(const string & name) + : Network(name) { - m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network - m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; // Number of virtual networks = number of message classes in the coherence protocol +} + +void GarnetNetwork_d::init(const vector<string> & argv) +{ + Network::init(argv); + + //added by SS + m_network_config_ptr = new NetworkConfig; + m_network_config_ptr->init(argv); + m_ruby_start = 0; m_flits_recieved = 0; m_flits_injected = 0; @@ -80,7 +89,7 @@ GarnetNetwork_d::GarnetNetwork_d(int nodes) } // Setup the network switches - m_topology_ptr = new Topology(this, m_nodes); + m_topology_ptr->makeTopology(); int number_of_routers = m_topology_ptr->numSwitches(); for (int i=0; i<number_of_routers; i++) { @@ -138,7 +147,7 @@ void GarnetNetwork_d::makeInLink(NodeID src, SwitchID dest, const NetDest& routi if(!isReconfiguration) { NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this); - CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size()); + CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size(), link_latency, this); m_link_ptr_vector.insertAtBottom(net_link); m_creditlink_ptr_vector.insertAtBottom(credit_link); @@ -167,7 +176,7 @@ void GarnetNetwork_d::makeOutLink(SwitchID src, NodeID dest, const NetDest& rout if(!isReconfiguration) { NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this); - CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size()); + CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size(), link_latency, this); m_link_ptr_vector.insertAtBottom(net_link); m_creditlink_ptr_vector.insertAtBottom(credit_link); @@ -190,7 +199,7 @@ void GarnetNetwork_d::makeInternalLink(SwitchID src, SwitchID dest, const NetDes if(!isReconfiguration) { NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this); - CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size()); + CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size(), link_latency, this); m_link_ptr_vector.insertAtBottom(net_link); m_creditlink_ptr_vector.insertAtBottom(credit_link); @@ -241,9 +250,9 @@ Time GarnetNetwork_d::getRubyStartTime() void GarnetNetwork_d::printStats(ostream& out) const { double average_link_utilization = 0; Vector<double > average_vc_load; - average_vc_load.setSize(m_virtual_networks*NetworkConfig::getVCsPerClass()); + average_vc_load.setSize(m_virtual_networks*m_network_config_ptr->getVCsPerClass()); - for(int i = 0; i < m_virtual_networks*NetworkConfig::getVCsPerClass(); i++) + for(int i = 0; i < m_virtual_networks*m_network_config_ptr->getVCsPerClass(); i++) { average_vc_load[i] = 0; } @@ -259,7 +268,7 @@ void GarnetNetwork_d::printStats(ostream& out) const Vector<int > vc_load = m_link_ptr_vector[i]->getVcLoad(); for(int j = 0; j < vc_load.size(); j++) { - assert(vc_load.size() == NetworkConfig::getVCsPerClass()*m_virtual_networks); + assert(vc_load.size() == m_network_config_ptr->getVCsPerClass()*m_virtual_networks); average_vc_load[j] += vc_load[j]; } } @@ -267,7 +276,7 @@ void GarnetNetwork_d::printStats(ostream& out) const out << "Average Link Utilization :: " << average_link_utilization << " flits/cycle" << endl; out << "-------------" << endl; - for(int i = 0; i < NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS; i++) + for(int i = 0; i < m_network_config_ptr->getVCsPerClass()*m_virtual_networks; i++) { average_vc_load[i] = (double(average_vc_load[i]) / (double(g_eventQueue_ptr->getTime()) - m_ruby_start)); out << "Average VC Load [" << i << "] = " << average_vc_load[i] << " flits/cycle " << endl; @@ -304,7 +313,7 @@ void GarnetNetwork_d::printConfig(ostream& out) const out << "Network Configuration" << endl; out << "---------------------" << endl; out << "network: GarnetNetwork_d" << 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++) @@ -337,10 +346,7 @@ void GarnetNetwork_d::printConfig(ostream& out) const { m_router_ptr_vector[i]->printConfig(out); } - if (g_PRINT_TOPOLOGY) - { - m_topology_ptr->printConfig(out); - } + m_topology_ptr->printConfig(out); } void GarnetNetwork_d::print(ostream& out) const diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh index e0f7aebd9..f4b809443 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh @@ -51,10 +51,15 @@ class CreditLink_d; class GarnetNetwork_d : public Network{ public: - GarnetNetwork_d(int nodes); + GarnetNetwork_d(const string & name); ~GarnetNetwork_d(); + void init(const vector<string> & argv); + + //added by SS + NetworkConfig* getNetworkConfig() { return m_network_config_ptr; } + int getNumNodes(){ return m_nodes;} // returns the queue requested for the given component @@ -99,6 +104,8 @@ public: void makeInternalLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration); private: + NetworkConfig* m_network_config_ptr; + void checkNetworkAllocation(NodeID id, bool ordered, int network_num); // Private copy constructor and assignment operator @@ -106,8 +113,8 @@ private: GarnetNetwork_d& operator=(const GarnetNetwork_d& obj); /***********Data Members*************/ - int m_virtual_networks; - int m_nodes; +// int m_virtual_networks; +// int m_nodes; int m_flits_recieved, m_flits_injected; double m_network_latency, m_queueing_latency; @@ -122,7 +129,7 @@ private: Vector<CreditLink_d *> m_creditlink_ptr_vector; // All links in the network Vector<NetworkInterface_d *> m_ni_ptr_vector; // All NI's in Network - Topology* m_topology_ptr; +// Topology* m_topology_ptr; Time m_ruby_start; }; diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc index 77857b1f8..f75997757 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc @@ -43,7 +43,7 @@ NetworkInterface_d::NetworkInterface_d(int id, int virtual_networks, GarnetNetwo m_id = id; m_net_ptr = network_ptr; m_virtual_networks = virtual_networks; - m_vc_per_vnet = NetworkConfig::getVCsPerClass(); + m_vc_per_vnet = m_net_ptr->getNetworkConfig()->getVCsPerClass(); m_num_vcs = m_vc_per_vnet*m_virtual_networks; m_vc_round_robin = 0; @@ -66,7 +66,7 @@ NetworkInterface_d::NetworkInterface_d(int id, int virtual_networks, GarnetNetwo for(int i = 0; i < m_num_vcs; i++) { - m_out_vc_state.insertAtBottom(new OutVcState_d(i)); + m_out_vc_state.insertAtBottom(new OutVcState_d(i, m_net_ptr)); m_out_vc_state[i]->setState(IDLE_, g_eventQueue_ptr->getTime()); } } @@ -114,7 +114,7 @@ bool NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet) NetDest net_msg_dest = net_msg_ptr->getInternalDestination(); Vector<NodeID> dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message. - int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/NetworkConfig::getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size + int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/m_net_ptr->getNetworkConfig()->getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size for(int ctr = 0; ctr < dest_nodes.size(); ctr++) // loop because we will be converting all multicast messages into unicast messages { @@ -221,7 +221,7 @@ void NetworkInterface_d::wakeup() if(t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) { free_signal = true; - if(!NetworkConfig::isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers + if(!m_net_ptr->getNetworkConfig()->isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers { outNode_ptr[t_flit->get_vnet()]->enqueue(t_flit->get_msg_ptr(), 1); // enqueueing for protocol buffer. This is not required when doing network only testing } @@ -307,7 +307,7 @@ void NetworkInterface_d::scheduleOutputLink() int NetworkInterface_d::get_vnet(int vc) { - for(int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++) + for(int i = 0; i < m_net_ptr->getNumberOfVirtualNetworks(); i++) { if(vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) { diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc index 94f721646..8382d331f 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc @@ -37,6 +37,7 @@ #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh" #include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh" +/* NetworkLink_d::NetworkLink_d(int id) { m_id = id; @@ -45,12 +46,12 @@ NetworkLink_d::NetworkLink_d(int id) linkBuffer = new flitBuffer_d(); m_link_utilized = 0; - m_vc_load.setSize(NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS); + m_vc_load.setSize(NetworkConfig::getVCsPerClass()*RubySystem::getNetwork()->getNumberOfVirtualNetworks()); - for(int i = 0; i < NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS; i++) + for(int i = 0; i < NetworkConfig::getVCsPerClass()*RubySystem::getNetwork()->getNumberOfVirtualNetworks(); i++) m_vc_load[i] = 0; } - +*/ NetworkLink_d::NetworkLink_d(int id, int link_latency, GarnetNetwork_d *net_ptr) { m_net_ptr = net_ptr; @@ -58,9 +59,9 @@ NetworkLink_d::NetworkLink_d(int id, int link_latency, GarnetNetwork_d *net_ptr) m_latency = link_latency; linkBuffer = new flitBuffer_d(); m_link_utilized = 0; - m_vc_load.setSize(NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS); + m_vc_load.setSize(m_net_ptr->getNetworkConfig()->getVCsPerClass()*net_ptr->getNumberOfVirtualNetworks()); - for(int i = 0; i < NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS; i++) + for(int i = 0; i < m_net_ptr->getNetworkConfig()->getVCsPerClass()*net_ptr->getNumberOfVirtualNetworks(); i++) m_vc_load[i] = 0; } diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh index 1e81a565b..90fb9f6dc 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh @@ -46,7 +46,7 @@ class GarnetNetwork_d; class NetworkLink_d : public Consumer { public: - NetworkLink_d(int id); + //NetworkLink_d(int id); ~NetworkLink_d(); NetworkLink_d(int id, int link_latency, GarnetNetwork_d *net_ptr); diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc index 4fd040099..69e3ae377 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc @@ -27,7 +27,7 @@ */ /* - * OutVCState_d.C + * OutVCState_d.cc * * Niket Agarwal, Princeton University * @@ -37,10 +37,11 @@ #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh" -OutVcState_d::OutVcState_d(int id) +OutVcState_d::OutVcState_d(int id, GarnetNetwork_d *network_ptr) { + m_network_ptr = network_ptr; m_id = id; m_vc_state = IDLE_; m_time = g_eventQueue_ptr->getTime(); - m_credit_count = NetworkConfig::getBufferSize(); + m_credit_count = m_network_ptr->getNetworkConfig()->getBufferSize(); } diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh index 959a3d643..dc64b8504 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh +++ b/src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh @@ -37,10 +37,11 @@ #define OUT_VC_STATE_D_H #include "mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh" +#include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh" class OutVcState_d { public: - OutVcState_d(int id); + OutVcState_d(int id, GarnetNetwork_d *network_ptr); int get_inport() {return m_in_port; } int get_invc() { return m_in_vc; } @@ -75,6 +76,7 @@ public: } private: + GarnetNetwork_d *m_network_ptr; int m_id ; Time m_time; VC_state_type m_vc_state; diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc index 1b8b8097b..eb2450897 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc @@ -27,7 +27,7 @@ */ /* - * OutputUnit_d.C + * OutputUnit_d.cc * * Niket Agarwal, Princeton University * @@ -46,7 +46,7 @@ OutputUnit_d::OutputUnit_d(int id, Router_d *router) for(int i = 0; i < m_num_vcs; i++) { - m_outvc_state.insertAtBottom(new OutVcState_d(i)); + m_outvc_state.insertAtBottom(new OutVcState_d(i, m_router->get_net_ptr())); } } diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc index c59805b48..161e6ecff 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc @@ -48,10 +48,10 @@ Router_d::Router_d(int id, GarnetNetwork_d *network_ptr) { m_id = id; m_network_ptr = network_ptr; - m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; - m_vc_per_vnet = NetworkConfig::getVCsPerClass(); + m_virtual_networks = network_ptr->getNumberOfVirtualNetworks(); + m_vc_per_vnet = m_network_ptr->getNetworkConfig()->getVCsPerClass(); m_num_vcs = m_virtual_networks*m_vc_per_vnet; - m_flit_width = NetworkConfig::getFlitSize(); + m_flit_width = m_network_ptr->getNetworkConfig()->getFlitSize(); m_routing_unit = new RoutingUnit_d(this); m_vc_alloc = new VCallocator_d(this); diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc index 7ca74244e..dd0378305 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc @@ -207,7 +207,7 @@ void SWallocator_d::check_for_wakeup() int SWallocator_d::get_vnet(int invc) { - for(int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++) + for(int i = 0; i < RubySystem::getNetwork()->getNumberOfVirtualNetworks(); i++) { if(invc >= (i*m_vc_per_vnet) && invc < ((i+1)*m_vc_per_vnet)) { diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc index 6f13ba14f..810aea175 100644 --- a/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc +++ b/src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc @@ -244,7 +244,7 @@ void VCallocator_d::arbitrate_outvcs() int VCallocator_d::get_vnet(int invc) { - for(int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++) + for(int i = 0; i < RubySystem::getNetwork()->getNumberOfVirtualNetworks(); i++) { if(invc >= (i*m_vc_per_vnet) && invc < ((i+1)*m_vc_per_vnet)) { diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc index 2496cd30f..e56f5b5e8 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc @@ -44,26 +44,22 @@ #include "mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh" #include "mem/ruby/common/NetDest.hh" -// calls new to abstract away from the network -Network* Network::createNetwork(int nodes) +GarnetNetwork::GarnetNetwork(const string & name) + : Network(name) { - NetworkConfig::readNetConfig(); - // Instantiate a network depending on what kind of network is requested - if(NetworkConfig::isGarnetNetwork()) - { - if(NetworkConfig::isDetailNetwork()) - return new GarnetNetwork_d(nodes); - else - return new GarnetNetwork(nodes); - } - else - return new SimpleNetwork(nodes); } -GarnetNetwork::GarnetNetwork(int nodes) +void GarnetNetwork::init(const vector<string> & argv) { - m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network - m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; // Number of virtual networks = number of message classes in the coherence protocol +// printf("hello\n"); + Network::init(argv); +//added by SS +// assert (m_topology_ptr!=NULL); + + m_network_config_ptr = new NetworkConfig; + + m_network_config_ptr->init(argv); + m_ruby_start = 0; // Allocate to and from queues @@ -91,7 +87,8 @@ GarnetNetwork::GarnetNetwork(int nodes) } // Setup the network switches - m_topology_ptr = new Topology(this, m_nodes); + assert (m_topology_ptr!=NULL); + m_topology_ptr->makeTopology(); int number_of_routers = m_topology_ptr->numSwitches(); for (int i=0; i<number_of_routers; i++) { @@ -188,6 +185,7 @@ void GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, const NetDest& void GarnetNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num) { + printf ("id = %i, m_nodes = %i \n", id, m_nodes); ASSERT(id < m_nodes); ASSERT(network_num < m_virtual_networks); @@ -223,9 +221,9 @@ Time GarnetNetwork::getRubyStartTime() void GarnetNetwork::printStats(ostream& out) const { double average_link_utilization = 0; Vector<double > average_vc_load; - average_vc_load.setSize(m_virtual_networks*NetworkConfig::getVCsPerClass()); + average_vc_load.setSize(m_virtual_networks*m_network_config_ptr->getVCsPerClass()); - for(int i = 0; i < m_virtual_networks*NetworkConfig::getVCsPerClass(); i++) + for(int i = 0; i < m_virtual_networks*m_network_config_ptr->getVCsPerClass(); i++) { average_vc_load[i] = 0; } @@ -240,7 +238,7 @@ void GarnetNetwork::printStats(ostream& out) const Vector<int > vc_load = m_link_ptr_vector[i]->getVcLoad(); for(int j = 0; j < vc_load.size(); j++) { - assert(vc_load.size() == NetworkConfig::getVCsPerClass()*m_virtual_networks); + assert(vc_load.size() == m_network_config_ptr->getVCsPerClass()*m_virtual_networks); average_vc_load[j] += vc_load[j]; } } @@ -248,7 +246,7 @@ void GarnetNetwork::printStats(ostream& out) const out << "Average Link Utilization :: " << average_link_utilization << " flits/cycle" <<endl; out << "-------------" << endl; - for(int i = 0; i < NetworkConfig::getVCsPerClass()*m_virtual_networks; i++) + for(int i = 0; i < m_network_config_ptr->getVCsPerClass()*m_virtual_networks; i++) { average_vc_load[i] = (double(average_vc_load[i]) / (double(g_eventQueue_ptr->getTime()) - m_ruby_start)); out << "Average VC Load [" << i << "] = " << average_vc_load[i] << " flits/cycle" << endl; @@ -262,7 +260,7 @@ void GarnetNetwork::printConfig(ostream& out) const out << "Network Configuration" << endl; out << "---------------------" << endl; out << "network: GARNET_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++) @@ -295,10 +293,7 @@ void GarnetNetwork::printConfig(ostream& out) const { m_router_ptr_vector[i]->printConfig(out); } - if (g_PRINT_TOPOLOGY) - { - m_topology_ptr->printConfig(out); - } + m_topology_ptr->printConfig(out); } void GarnetNetwork::print(ostream& out) const diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh index 27de3de07..194fef778 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh @@ -50,10 +50,15 @@ class NetworkLink; class GarnetNetwork : public Network{ public: - GarnetNetwork(int nodes); + GarnetNetwork(const string & name); ~GarnetNetwork(); + void init(const vector<string> & argv); + + //added by SS + NetworkConfig* getNetworkConfig() { return m_network_config_ptr; } + // returns the queue requested for the given component MessageBuffer* getToNetQueue(NodeID id, bool ordered, int network_num); MessageBuffer* getFromNetQueue(NodeID id, bool ordered, int network_num); @@ -83,9 +88,10 @@ private: GarnetNetwork(const GarnetNetwork& obj); GarnetNetwork& operator=(const GarnetNetwork& obj); + /***********Data Members*************/ - int m_virtual_networks; - int m_nodes; +// int m_virtual_networks; +// int m_nodes; Vector<bool> m_in_use; Vector<bool> m_ordered; @@ -97,8 +103,10 @@ private: Vector<NetworkLink *> m_link_ptr_vector; // All links in the network Vector<NetworkInterface *> m_ni_ptr_vector; // All NI's in Network - Topology* m_topology_ptr; +// Topology* m_topology_ptr; Time m_ruby_start; + + NetworkConfig* m_network_config_ptr; }; // Output operator declaration diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh index 270fd6429..33af28a7e 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh @@ -43,14 +43,35 @@ #include "mem/ruby/config/RubyConfig.hh" class NetworkConfig { + private: + int m_flit_size; + int m_number_of_pipe_stages; + int m_vcs_per_class; + int m_buffer_size; + bool m_using_network_testing; public: - static bool isGarnetNetwork() {return g_GARNET_NETWORK; } - static bool isDetailNetwork() {return g_DETAIL_NETWORK; } - static int isNetworkTesting() {return g_NETWORK_TESTING; } - static int getFlitSize() {return g_FLIT_SIZE; } - static int getNumPipeStages() {return g_NUM_PIPE_STAGES; } - static int getVCsPerClass() {return g_VCS_PER_CLASS; } - static int getBufferSize() {return g_BUFFER_SIZE; } + NetworkConfig(){} + void init(const vector<string> & argv) { + for (size_t i=0; i<argv.size(); i+=2) { + if (argv[i] == "flit_size") + m_flit_size = atoi(argv[i+1].c_str()); + else if (argv[i] == "number_of_pipe_stages") + m_number_of_pipe_stages = atoi(argv[i+1].c_str()); + else if (argv[i] == "vcs_per_class") + m_vcs_per_class = atoi(argv[i+1].c_str()); + else if (argv[i] == "buffer_size") + m_buffer_size = atoi(argv[i+1].c_str()); + else if (argv[i] == "using_network_testing") + m_using_network_testing = atoi(argv[i+1].c_str()); + } + } +// static bool isGarnetNetwork() {return RubyConfig::getUsingGarnetNetwork(); } +// static bool isDetailNetwork() {return RubyConfig::getUsingDetailNetwork(); } + bool isNetworkTesting() {return m_using_network_testing; } + int getFlitSize() {return m_flit_size; } + int getNumPipeStages() {return m_number_of_pipe_stages; } + int getVCsPerClass() {return m_vcs_per_class; } + int getBufferSize() {return m_buffer_size; } // This is no longer used. See config/rubyconfig.defaults to set Garnet parameters. static void readNetConfig() { @@ -58,6 +79,9 @@ class NetworkConfig { string filename = "network/garnet-flexible-pipeline/"; filename += NETCONFIG_DEFAULTS; + if (g_SIMICS) { + filename = "../../../ruby/"+filename; + } ifstream NetconfigFile( filename.c_str(), ios::in); if(!NetconfigFile.is_open()) { @@ -73,19 +97,19 @@ class NetworkConfig { getline(NetconfigFile, line, '\n'); string var = string_split(line, ':'); - if(!var.compare("g_GARNET_NETWORK")) + if(!var.compare("RubyConfig::getUsingGarnetNetwork()")) { if(!line.compare("true")) - g_GARNET_NETWORK = true; + RubyConfig::getUsingGarnetNetwork() = true; else - g_GARNET_NETWORK = false; + RubyConfig::getUsingGarnetNetwork() = false; } - if(!var.compare("g_DETAIL_NETWORK")) + if(!var.compare("RubyConfig::getUsingDetailNetwork()")) { if(!line.compare("true")) - g_DETAIL_NETWORK = true; + RubyConfig::getUsingDetailNetwork() = true; else - g_DETAIL_NETWORK = false; + RubyConfig::getUsingDetailNetwork() = false; } if(!var.compare("g_NETWORK_TESTING")) { @@ -94,27 +118,28 @@ class NetworkConfig { else g_NETWORK_TESTING = false; } - if(!var.compare("g_FLIT_SIZE")) - g_FLIT_SIZE = atoi(line.c_str()); - if(!var.compare("g_NUM_PIPE_STAGES")) - g_NUM_PIPE_STAGES = atoi(line.c_str()); - if(!var.compare("g_VCS_PER_CLASS")) - g_VCS_PER_CLASS = atoi(line.c_str()); - if(!var.compare("g_BUFFER_SIZE")) - g_BUFFER_SIZE = atoi(line.c_str()); + if(!var.compare("RubyConfig::getFlitSize()")) + RubyConfig::getFlitSize() = atoi(line.c_str()); + if(!var.compare("RubyConfig::getNumberOfPipeStages()")) + RubyConfig::getNumberOfPipeStages() = atoi(line.c_str()); + if(!var.compare("RubyConfig::getVCSPerClass()")) + RubyConfig::getVCSPerClass() = atoi(line.c_str()); + if(!var.compare("RubyConfig::getBufferSize()")) + RubyConfig::getBufferSize() = atoi(line.c_str()); } NetconfigFile.close(); */ /* - cout << "g_GARNET_NETWORK = " << g_GARNET_NETWORK << endl; - cout << "g_DETAIL_NETWORK = " << g_DETAIL_NETWORK << endl; + cout << "RubyConfig::getUsingGarnetNetwork() = " << RubyConfig::getUsingGarnetNetwork() << endl; + cout << "RubyConfig::getUsingDetailNetwork() = " << RubyConfig::getUsingDetailNetwork() << endl; cout << "g_NETWORK_TESTING = " << g_NETWORK_TESTING << endl; - cout << "g_FLIT_SIZE = " << g_FLIT_SIZE << endl; - cout << "g_NUM_PIPE_STAGES = " << g_NUM_PIPE_STAGES << endl; - cout << "g_VCS_PER_CLASS= " << g_VCS_PER_CLASS << endl; - cout << "g_BUFFER_SIZE = " << g_BUFFER_SIZE << endl; + cout << "RubyConfig::getFlitSize() = " << RubyConfig::getFlitSize() << endl; + cout << "RubyConfig::getNumberOfPipeStages() = " << RubyConfig::getNumberOfPipeStages() << endl; + cout << "RubyConfig::getVCSPerClass()= " << RubyConfig::getVCSPerClass() << endl; + cout << "RubyConfig::getBufferSize() = " << RubyConfig::getBufferSize() << endl; */ } }; + #endif diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc index b7bd2393c..119f064d3 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc @@ -27,7 +27,7 @@ */ /* - * NetworkInterface.C + * NetworkInterface.cc * * Niket Agarwal, Princeton University * @@ -43,7 +43,7 @@ NetworkInterface::NetworkInterface(int id, int virtual_networks, GarnetNetwork * m_id = id; m_net_ptr = network_ptr; m_virtual_networks = virtual_networks; - m_vc_per_vnet = NetworkConfig::getVCsPerClass(); + m_vc_per_vnet = m_net_ptr->getNetworkConfig()->getVCsPerClass(); m_num_vcs = m_vc_per_vnet*m_virtual_networks; m_vc_round_robin = 0; @@ -109,7 +109,7 @@ bool NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet) NetworkMessage *net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref()); NetDest net_msg_dest = net_msg_ptr->getInternalDestination(); Vector<NodeID> dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message. - int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/NetworkConfig::getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size + int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/m_net_ptr->getNetworkConfig()->getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size for(int ctr = 0; ctr < dest_nodes.size(); ctr++) // loop because we will be converting all multicast messages into unicast messages { @@ -236,7 +236,7 @@ void NetworkInterface::wakeup() DEBUG_EXPR(NETWORK_COMP, HighPrio, m_id); DEBUG_MSG(NETWORK_COMP, HighPrio, "Message got delivered"); DEBUG_EXPR(NETWORK_COMP, HighPrio, g_eventQueue_ptr->getTime()); - if(!NetworkConfig::isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers + if(!m_net_ptr->getNetworkConfig()->isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers { outNode_ptr[t_flit->get_vnet()]->enqueue(t_flit->get_msg_ptr(), 1); // enqueueing for protocol buffer. This is not required when doing network only testing } diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc index 90177cbec..ddc92d44c 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc @@ -46,8 +46,8 @@ NetworkLink::NetworkLink(int id, int latency, GarnetNetwork *net_ptr) m_link_utilized = 0; m_net_ptr = net_ptr; m_latency = latency; - int num_net = NUMBER_OF_VIRTUAL_NETWORKS; - int num_vc = NetworkConfig::getVCsPerClass(); + int num_net = net_ptr->getNumberOfVirtualNetworks(); + int num_vc = m_net_ptr->getNetworkConfig()->getVCsPerClass(); m_vc_load.setSize(num_net*num_vc); for(int i = 0; i < num_net*num_vc; i++) diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc b/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc index 1def6f9c3..ea32e938d 100644 --- a/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc +++ b/src/mem/ruby/network/garnet-flexible-pipeline/Router.cc @@ -43,8 +43,8 @@ Router::Router(int id, GarnetNetwork *network_ptr) { m_id = id; m_net_ptr = network_ptr; - m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; - m_vc_per_vnet = NetworkConfig::getVCsPerClass(); + m_virtual_networks = m_net_ptr->getNumberOfVirtualNetworks(); + m_vc_per_vnet = m_net_ptr->getNetworkConfig()->getVCsPerClass(); m_round_robin_inport = 0; m_round_robin_start = 0; m_num_vcs = m_vc_per_vnet*m_virtual_networks; @@ -103,7 +103,7 @@ void Router::addOutPort(NetworkLink *out_link, const NetDest& routing_table_entr Vector<flitBuffer *> intermediateQueues; for(int i = 0; i < m_num_vcs; i++) { - intermediateQueues.insertAtBottom(new flitBuffer(NetworkConfig::getBufferSize())); + intermediateQueues.insertAtBottom(new flitBuffer(m_net_ptr->getNetworkConfig()->getBufferSize())); } m_router_buffers.insertAtBottom(intermediateQueues); @@ -246,17 +246,17 @@ void Router::routeCompute(flit *m_flit, int inport) int outport = m_in_vc_state[inport][invc]->get_outport(); int outvc = m_in_vc_state[inport][invc]->get_outvc(); - assert(NetworkConfig::getNumPipeStages() >= 1); - m_flit->set_time(g_eventQueue_ptr->getTime() + (NetworkConfig::getNumPipeStages() - 1)); // Becasuse 1 cycle will be consumed in scheduling the output link + assert(m_net_ptr->getNetworkConfig()->getNumPipeStages() >= 1); + m_flit->set_time(g_eventQueue_ptr->getTime() + (m_net_ptr->getNetworkConfig()->getNumPipeStages() - 1)); // Becasuse 1 cycle will be consumed in scheduling the output link m_flit->set_vc(outvc); m_router_buffers[outport][outvc]->insert(m_flit); - if(NetworkConfig::getNumPipeStages() > 1) - g_eventQueue_ptr->scheduleEvent(this, NetworkConfig::getNumPipeStages() -1 ); + if(m_net_ptr->getNetworkConfig()->getNumPipeStages() > 1) + g_eventQueue_ptr->scheduleEvent(this, m_net_ptr->getNetworkConfig()->getNumPipeStages() -1 ); if((m_flit->get_type() == HEAD_) || (m_flit->get_type() == HEAD_TAIL_)) { NetDest destination = dynamic_cast<NetworkMessage*>(m_flit->get_msg_ptr().ref())->getInternalDestination(); - if(NetworkConfig::getNumPipeStages() > 1) + if(m_net_ptr->getNetworkConfig()->getNumPipeStages() > 1) { m_out_vc_state[outport][outvc]->setState(VC_AB_, g_eventQueue_ptr->getTime() + 1); m_out_link[outport]->request_vc_link(outvc, destination, g_eventQueue_ptr->getTime() + 1); 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 |