diff -r be4990a2c764 -r 0315c934bbfc SConstruct --- a/SConstruct Thu Feb 02 04:51:13 2012 -0500 +++ b/SConstruct Mon Mar 12 18:17:19 2012 +0100 @@ -889,6 +889,10 @@ main.SConscript('ext/gzstream/SConscript', variant_dir = joinpath(build_root, 'gzstream')) +# topaz build is shared across all configs in the build root. +main.SConscript('ext/TOPAZ/SConscript', + variant_dir = joinpath(build_root, 'topaz')) + ################################################### # # This function is used to set up a directory with switching headers diff -r be4990a2c764 -r 0315c934bbfc TPZSimul.ini --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TPZSimul.ini Mon Mar 12 18:17:19 2012 +0100 @@ -0,0 +1,3 @@ + + + diff -r be4990a2c764 -r 0315c934bbfc build_opts/ALPHA_MOESI_CMP_directory --- a/build_opts/ALPHA_MOESI_CMP_directory Thu Feb 02 04:51:13 2012 -0500 +++ b/build_opts/ALPHA_MOESI_CMP_directory Mon Mar 12 18:17:19 2012 +0100 @@ -1,3 +1,4 @@ SS_COMPATIBLE_FP = 1 CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' PROTOCOL = 'MOESI_CMP_directory' +USE_TOPAZ = True diff -r 0315c934bbfc -r 81a9c05b8495 build_opts/ALPHA_MOESI_CMP_directory --- a/build_opts/ALPHA_MOESI_CMP_directory Mon Mar 12 18:17:19 2012 +0100 +++ b/build_opts/ALPHA_MOESI_CMP_directory Mon Mar 19 19:34:15 2012 +0100 @@ -1,4 +1,3 @@ SS_COMPATIBLE_FP = 1 CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' PROTOCOL = 'MOESI_CMP_directory' -USE_TOPAZ = True diff -r be4990a2c764 -r 0315c934bbfc build_opts/ALPHA_Network_Topaz_test --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_opts/ALPHA_Network_Topaz_test Mon Mar 12 18:17:19 2012 +0100 @@ -0,0 +1,4 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'Network_test' +USE_TOPAZ = True diff -r be4990a2c764 -r 0315c934bbfc build_opts/ALPHA_Network_test --- a/build_opts/ALPHA_Network_test Thu Feb 02 04:51:13 2012 -0500 +++ b/build_opts/ALPHA_Network_test Mon Mar 12 18:17:19 2012 +0100 @@ -1,3 +1,4 @@ SS_COMPATIBLE_FP = 1 CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' PROTOCOL = 'Network_test' + diff -r 0315c934bbfc -r 81a9c05b8495 build_opts/ALPHA_Network_test --- a/build_opts/ALPHA_Network_test Mon Mar 12 18:17:19 2012 +0100 +++ b/build_opts/ALPHA_Network_test Mon Mar 19 19:34:15 2012 +0100 @@ -1,4 +1,3 @@ SS_COMPATIBLE_FP = 1 CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' PROTOCOL = 'Network_test' - diff -r be4990a2c764 -r 0315c934bbfc build_opts/ALPHA_directory_topaz --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_opts/ALPHA_directory_topaz Mon Mar 12 18:17:19 2012 +0100 @@ -0,0 +1,5 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MOESI_CMP_directory' +USE_TOPAZ = True +USE_TOPAZ = True diff -r be4990a2c764 -r 0315c934bbfc build_opts/ALPHA_token_topaz --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_opts/ALPHA_token_topaz Mon Mar 12 18:17:19 2012 +0100 @@ -0,0 +1,4 @@ +SS_COMPATIBLE_FP = 1 +CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' +PROTOCOL = 'MOESI_CMP_token' +USE_TOPAZ = True diff -r be4990a2c764 -r 0315c934bbfc configs/ruby/Ruby.py --- a/configs/ruby/Ruby.py Thu Feb 02 04:51:13 2012 -0500 +++ b/configs/ruby/Ruby.py Mon Mar 12 18:17:19 2012 +0100 @@ -72,6 +72,22 @@ parser.add_option("--ruby_stats", type="string", default="ruby.stats") + #TOPAZ options + parser.add_option("--topaz-init-file", type = "string", default="./TPZSimul.ini", + help="TOPAZ: File that declares .sgm, .sgm and .sgm" ) + + parser.add_option("--topaz-network", type = "string", default=False, + help="TOPAZ: simulation listed in .sgm to be used by TOPAZ" ) + + parser.add_option("--topaz-flit-size", type="int", default=16, + help="TOPAZ: Number of bytes per physical router-to-router wire") + + parser.add_option("--topaz-clock-ratio", type="int", default=1, + help="TOPAZ: memory-network clock multiplier") + + parser.add_option("--topaz-adaptive-interface-threshold", type = "int", default=0, + help="TOPAZ: Number of messages that has to be transmitted before to activate TOPAZ" ) + protocol = buildEnv['PROTOCOL'] exec "import %s" % protocol eval("%s.define_options(parser)" % protocol) @@ -142,13 +158,29 @@ print "Error: could not create topology %s" % options.topology raise - if options.network_fault_model: - assert(options.garnet_network == "fixed") - fault_model = FaultModel() - network = NetworkClass(ruby_system = ruby, topology = net_topology,\ - enable_fault_model=True, fault_model = fault_model) + + # + # TOPAZ parameters + # + # TOPAZ relies on Simple network, therefore is incompatible with garnet" + assert(not(options.garnet_network !=None and options.topaz_network!=None)) + if options.topaz_network!=None: + assert (not(options.garnet_network !=None)) # TOPAZ relies on SimpleNetwork, therefore is incompatible with garnet" + network = NetworkClass(ruby_system = ruby, topology = net_topology, \ + topaz_network = options.topaz_network,\ + topaz_flit_size = options.topaz_flit_size,\ + topaz_clock_ratio = options.topaz_clock_ratio, \ + topaz_adaptive_interface_threshold = options.topaz_adaptive_interface_threshold, \ + topaz_init_file =options.topaz_init_file ) else: - network = NetworkClass(ruby_system = ruby, topology = net_topology) + if options.network_fault_model: + assert(options.garnet_network == "fixed") + fault_model = FaultModel() + network = NetworkClass(ruby_system = ruby, topology = net_topology,\ + enable_fault_model=True, fault_model = fault_model) + else: + network = NetworkClass(ruby_system = ruby, topology = net_topology) + # # Loop through the directory controlers. diff -r 0315c934bbfc -r 81a9c05b8495 configs/ruby/Ruby.py --- a/configs/ruby/Ruby.py Mon Mar 12 18:17:19 2012 +0100 +++ b/configs/ruby/Ruby.py Mon Mar 19 19:34:15 2012 +0100 @@ -138,6 +138,11 @@ class IntLinkClass(GarnetIntLink): pass class ExtLinkClass(GarnetExtLink): pass class RouterClass(GarnetRouter): pass + elif options.topaz_network: + class NetworkClass(TopazNetwork): pass + class IntLinkClass(SimpleIntLink): pass + class ExtLinkClass(SimpleExtLink): pass + class RouterClass(BasicRouter): pass else: class NetworkClass(SimpleNetwork): pass class IntLinkClass(SimpleIntLink): pass @@ -159,13 +164,14 @@ raise - # - # TOPAZ parameters - # - # TOPAZ relies on Simple network, therefore is incompatible with garnet" - assert(not(options.garnet_network !=None and options.topaz_network!=None)) - if options.topaz_network!=None: - assert (not(options.garnet_network !=None)) # TOPAZ relies on SimpleNetwork, therefore is incompatible with garnet" + if options.network_fault_model: + assert(options.garnet_network == "fixed") + fault_model = FaultModel() + network = NetworkClass(ruby_system = ruby, topology = net_topology,\ + enable_fault_model=True, fault_model = fault_model) + elif options.topaz_network: + #Garnet and Topaz are explusive + assert (not(options.garnet_network !=None)) network = NetworkClass(ruby_system = ruby, topology = net_topology, \ topaz_network = options.topaz_network,\ topaz_flit_size = options.topaz_flit_size,\ @@ -173,13 +179,7 @@ topaz_adaptive_interface_threshold = options.topaz_adaptive_interface_threshold, \ topaz_init_file =options.topaz_init_file ) else: - if options.network_fault_model: - assert(options.garnet_network == "fixed") - fault_model = FaultModel() - network = NetworkClass(ruby_system = ruby, topology = net_topology,\ - enable_fault_model=True, fault_model = fault_model) - else: - network = NetworkClass(ruby_system = ruby, topology = net_topology) + network = NetworkClass(ruby_system = ruby, topology = net_topology) # diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/SConscript --- a/src/mem/ruby/SConscript Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/SConscript Mon Mar 12 18:17:19 2012 +0100 @@ -43,6 +43,9 @@ if env['PROTOCOL'] == 'None': Return() +if env['USE_TOPAZ'] == True: + env.Append(CPPDEFINES = ['USE_TOPAZ']) + def do_embed_text(target, source, env): """convert a text file into a file that can be embedded in C using an #include statement, that defines a \"const char *\" pointing diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/SConscript --- a/src/mem/ruby/SConscript Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/SConscript Mon Mar 19 19:34:15 2012 +0100 @@ -43,9 +43,6 @@ if env['PROTOCOL'] == 'None': Return() -if env['USE_TOPAZ'] == True: - env.Append(CPPDEFINES = ['USE_TOPAZ']) - def do_embed_text(target, source, env): """convert a text file into a file that can be embedded in C using an #include statement, that defines a \"const char *\" pointing diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/SConsopts --- a/src/mem/ruby/SConsopts Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/SConsopts Mon Mar 12 18:17:19 2012 +0100 @@ -37,3 +37,8 @@ export_vars += [ 'NO_VECTOR_BOUNDS_CHECKS' ] +sticky_vars.AddVariables( + BoolVariable('USE_TOPAZ',"Replace Ruby Network with TOPAZ", False), + ) + +export_vars += [ 'USE_TOPAZ' ] diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/SConsopts --- a/src/mem/ruby/SConsopts Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/SConsopts Mon Mar 19 19:34:15 2012 +0100 @@ -37,8 +37,3 @@ export_vars += [ 'NO_VECTOR_BOUNDS_CHECKS' ] -sticky_vars.AddVariables( - BoolVariable('USE_TOPAZ',"Replace Ruby Network with TOPAZ", False), - ) - -export_vars += [ 'USE_TOPAZ' ] diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/buffers/MessageBuffer.hh --- a/src/mem/ruby/buffers/MessageBuffer.hh Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/buffers/MessageBuffer.hh Mon Mar 12 18:17:19 2012 +0100 @@ -41,6 +41,9 @@ #include #include +#ifdef USE_TOPAZ +#include "mem/ruby/network/simple/SimpleNetwork.hh" +#endif #include "mem/ruby/buffers/MessageBufferNode.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Consumer.hh" @@ -138,6 +141,17 @@ int getSize(); void setRandomization(bool random_flag) { m_randomization = random_flag; } +#ifdef USE_TOPAZ + void setNetwork(SimpleNetwork* network) { m_net_ptr = network; } + void setOutPort() { m_out_port = true; } + void setInPort() { m_in_port = true; } + void setOutSwitchPort() { m_out_switch_port = true; } + void setVNet(int vnet) { m_vnet = vnet; } + bool isOutPort() { return m_out_port; } + bool isInPort() { return m_in_port; } + bool isOutSwitchPort() { return m_out_switch_port; } +#endif + void clear(); void print(std::ostream& out) const; @@ -192,6 +206,15 @@ int m_input_link_id; int m_vnet_id; + +#ifdef USE_TOPAZ + //Support adaptive Topaz + SimpleNetwork* m_net_ptr; + bool m_out_port; + bool m_in_port; + bool m_out_switch_port; + int m_vnet; +#endif }; inline std::ostream& diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/buffers/MessageBuffer.hh --- a/src/mem/ruby/buffers/MessageBuffer.hh Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/buffers/MessageBuffer.hh Mon Mar 19 19:34:15 2012 +0100 @@ -41,9 +41,6 @@ #include #include -#ifdef USE_TOPAZ -#include "mem/ruby/network/simple/SimpleNetwork.hh" -#endif #include "mem/ruby/buffers/MessageBufferNode.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Consumer.hh" @@ -141,17 +138,6 @@ int getSize(); void setRandomization(bool random_flag) { m_randomization = random_flag; } -#ifdef USE_TOPAZ - void setNetwork(SimpleNetwork* network) { m_net_ptr = network; } - void setOutPort() { m_out_port = true; } - void setInPort() { m_in_port = true; } - void setOutSwitchPort() { m_out_switch_port = true; } - void setVNet(int vnet) { m_vnet = vnet; } - bool isOutPort() { return m_out_port; } - bool isInPort() { return m_in_port; } - bool isOutSwitchPort() { return m_out_switch_port; } -#endif - void clear(); void print(std::ostream& out) const; @@ -160,6 +146,11 @@ void setIncomingLink(int link_id) { m_input_link_id = link_id; } void setVnet(int net) { m_vnet_id = net; } + //REquired by TOPAZ adaptive interface + bool isToNet() {return m_toNet;} + void toNet() { m_toNet = true; } + bool isFromNet() { return m_fromNet; } + void fromNet() { m_fromNet = true; } private: //added by SS @@ -206,15 +197,8 @@ int m_input_link_id; int m_vnet_id; - -#ifdef USE_TOPAZ - //Support adaptive Topaz - SimpleNetwork* m_net_ptr; - bool m_out_port; - bool m_in_port; - bool m_out_switch_port; - int m_vnet; -#endif + bool m_toNet; + bool m_fromNet; }; inline std::ostream& diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/buffers/MessageBuffer.cc --- a/src/mem/ruby/buffers/MessageBuffer.cc Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/buffers/MessageBuffer.cc Mon Mar 12 18:17:19 2012 +0100 @@ -57,7 +57,11 @@ m_not_avail_count = 0; m_priority_rank = 0; m_name = name; - +#ifdef USE_TOPAZ + m_out_port = false; + m_in_port = false; + m_out_switch_port = false; +#endif m_stall_msg_map.clear(); m_input_link_id = 0; m_vnet_id = 0; @@ -233,6 +237,21 @@ } else { panic("No consumer: %s name: %s\n", *this, m_name); } +#ifdef USE_TOPAZ + //Gets the number of messages in ruby network for adaptive TOPAZ deactivation + if (m_in_port) + { + assert(m_net_ptr != NULL); + assert(!m_out_port); + const NetworkMessage* net_msg_ptr = static_cast(message.get()); + m_net_ptr->increaseNumMsg(net_msg_ptr->getInternalDestination().count()); + } + else if (m_out_port) + { + assert(m_net_ptr != NULL); + m_net_ptr->decreaseNumMsg(m_vnet); + } +#endif } int diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/buffers/MessageBuffer.cc --- a/src/mem/ruby/buffers/MessageBuffer.cc Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/buffers/MessageBuffer.cc Mon Mar 19 19:34:15 2012 +0100 @@ -57,14 +57,11 @@ m_not_avail_count = 0; m_priority_rank = 0; m_name = name; -#ifdef USE_TOPAZ - m_out_port = false; - m_in_port = false; - m_out_switch_port = false; -#endif m_stall_msg_map.clear(); m_input_link_id = 0; m_vnet_id = 0; + m_toNet = false; + m_fromNet = false; } int @@ -237,21 +234,6 @@ } else { panic("No consumer: %s name: %s\n", *this, m_name); } -#ifdef USE_TOPAZ - //Gets the number of messages in ruby network for adaptive TOPAZ deactivation - if (m_in_port) - { - assert(m_net_ptr != NULL); - assert(!m_out_port); - const NetworkMessage* net_msg_ptr = static_cast(message.get()); - m_net_ptr->increaseNumMsg(net_msg_ptr->getInternalDestination().count()); - } - else if (m_out_port) - { - assert(m_net_ptr != NULL); - m_net_ptr->decreaseNumMsg(m_vnet); - } -#endif } int diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/Network.hh --- a/src/mem/ruby/network/Network.hh Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/Network.hh Mon Mar 12 18:17:19 2012 +0100 @@ -95,6 +95,12 @@ virtual void printConfig(std::ostream& out) const = 0; virtual void print(std::ostream& out) const = 0; +#ifdef USE_TOPAZ + virtual void enableTopaz() =0; + virtual void disableTopaz()=0; + virtual void setTopazMapping (SwitchID node0, SwitchID node1)=0; +#endif + protected: // Private copy constructor and assignment operator Network(const Network& obj); diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/Network.hh --- a/src/mem/ruby/network/Network.hh Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/Network.hh Mon Mar 19 19:34:15 2012 +0100 @@ -95,11 +95,8 @@ virtual void printConfig(std::ostream& out) const = 0; virtual void print(std::ostream& out) const = 0; -#ifdef USE_TOPAZ - virtual void enableTopaz() =0; - virtual void disableTopaz()=0; - virtual void setTopazMapping (SwitchID node0, SwitchID node1)=0; -#endif + //Required to let Topaz be aware of ruby node mapping + virtual void setTopazMapping (SwitchID node0, SwitchID node1) {return;}; protected: // Private copy constructor and assignment operator diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/Topology.cc --- a/src/mem/ruby/network/Topology.cc Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/Topology.cc Mon Mar 12 18:17:19 2012 +0100 @@ -34,7 +34,11 @@ #include "mem/ruby/common/NetDest.hh" #include "mem/ruby/network/BasicLink.hh" #include "mem/ruby/network/BasicRouter.hh" +#ifdef USE_TOPAZ +#include "mem/ruby/network/simple/SimpleNetwork.hh" +#else #include "mem/ruby/network/Network.hh" +#endif #include "mem/ruby/network/Topology.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" @@ -244,11 +248,15 @@ src_dest.second = dest; link_entry = m_link_map[src_dest]; net->makeInLink(src, dest - (2 * m_nodes), link_entry.link, - link_entry.direction, + link_entry.direction, routing_table_entry, isReconfiguration); } else if (dest < 2*m_nodes) { assert(dest >= m_nodes); +#ifdef USE_TOPAZ + //The point to add information in SimpleNetwork file for TOPAZ. + net->setTopazMapping(dest-m_nodes, src); +#endif NodeID node = dest - m_nodes; src_dest.first = src; src_dest.second = dest; diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/Topology.cc --- a/src/mem/ruby/network/Topology.cc Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/Topology.cc Mon Mar 19 19:34:15 2012 +0100 @@ -34,11 +34,7 @@ #include "mem/ruby/common/NetDest.hh" #include "mem/ruby/network/BasicLink.hh" #include "mem/ruby/network/BasicRouter.hh" -#ifdef USE_TOPAZ -#include "mem/ruby/network/simple/SimpleNetwork.hh" -#else #include "mem/ruby/network/Network.hh" -#endif #include "mem/ruby/network/Topology.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" @@ -253,10 +249,6 @@ isReconfiguration); } else if (dest < 2*m_nodes) { assert(dest >= m_nodes); -#ifdef USE_TOPAZ - //The point to add information in SimpleNetwork file for TOPAZ. - net->setTopazMapping(dest-m_nodes, src); -#endif NodeID node = dest - m_nodes; src_dest.first = src; src_dest.second = dest; @@ -265,6 +257,12 @@ link_entry.direction, routing_table_entry, isReconfiguration); + //REquired to make TOPAZ aware of ruby Mapping + //This should be done here in order to + //have the reay in Topology Builder + //I'm unable to circunvent this. It is the only + //change done in RUBY outside the network/topaz + net->setTopazMapping(dest-m_nodes, src); } else { assert((src >= 2 * m_nodes) && (dest >= 2 * m_nodes)); src_dest.first = src; diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/garnet/BaseGarnetNetwork.hh --- a/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh Mon Mar 12 18:17:19 2012 +0100 @@ -54,6 +54,12 @@ bool isFaultModelEnabled() {return m_enable_fault_model;} FaultModel* fault_model; +#ifdef USE_TOPAZ + void enableTopaz(){return;} + void disableTopaz(){return;} + void setTopazMapping (SwitchID node0, SwitchID node1){return;} +#endif + protected: int m_ni_flit_size; int m_vcs_per_vnet; diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/garnet/BaseGarnetNetwork.hh --- a/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/garnet/BaseGarnetNetwork.hh Mon Mar 19 19:34:15 2012 +0100 @@ -54,12 +54,6 @@ bool isFaultModelEnabled() {return m_enable_fault_model;} FaultModel* fault_model; -#ifdef USE_TOPAZ - void enableTopaz(){return;} - void disableTopaz(){return;} - void setTopazMapping (SwitchID node0, SwitchID node1){return;} -#endif - protected: int m_ni_flit_size; int m_vcs_per_vnet; diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/simple/PerfectSwitch.hh --- a/src/mem/ruby/network/simple/PerfectSwitch.hh Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/simple/PerfectSwitch.hh Mon Mar 12 18:17:19 2012 +0100 @@ -72,8 +72,16 @@ int getOutLinks() const { return m_out.size(); } void wakeup(); + void wakeupVnet(int vnet); void storeEventInfo(int info); - +#ifdef USE_TOPAZ + int getUnicastDestination(NetDest destinations); + unsigned long long getMulticastDestination(NetDest& destinations); + void filterZeroDistanceMessages(MsgPtr& msg_ptr, int vnet, NetDest& destinations); + NetDest getConsumerDestinations(int switch_id, NetDest& mensaje); + void wakeUpTopaz(); + void addOutNetPort(const std::vector& out, const NetDest& routing_table_entry); +#endif void printStats(std::ostream& out) const; void clearStats(); void printConfig(std::ostream& out) const; @@ -96,6 +104,10 @@ int m_round_robin_start; int m_wakeups_wo_switch; SimpleNetwork* m_network_ptr; +#ifdef USE_TOPAZ + long unsigned m_ruby_start; + long unsigned m_minimunTimeAgain; +#endif std::vector m_pending_message_count; }; diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/simple/PerfectSwitch.hh --- a/src/mem/ruby/network/simple/PerfectSwitch.hh Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/simple/PerfectSwitch.hh Mon Mar 19 19:34:15 2012 +0100 @@ -72,16 +72,8 @@ int getOutLinks() const { return m_out.size(); } void wakeup(); - void wakeupVnet(int vnet); void storeEventInfo(int info); -#ifdef USE_TOPAZ - int getUnicastDestination(NetDest destinations); - unsigned long long getMulticastDestination(NetDest& destinations); - void filterZeroDistanceMessages(MsgPtr& msg_ptr, int vnet, NetDest& destinations); - NetDest getConsumerDestinations(int switch_id, NetDest& mensaje); - void wakeUpTopaz(); - void addOutNetPort(const std::vector& out, const NetDest& routing_table_entry); -#endif + void printStats(std::ostream& out) const; void clearStats(); void printConfig(std::ostream& out) const; @@ -104,10 +96,6 @@ int m_round_robin_start; int m_wakeups_wo_switch; SimpleNetwork* m_network_ptr; -#ifdef USE_TOPAZ - long unsigned m_ruby_start; - long unsigned m_minimunTimeAgain; -#endif std::vector m_pending_message_count; }; diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/simple/PerfectSwitch.cc --- a/src/mem/ruby/network/simple/PerfectSwitch.cc Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc Mon Mar 12 18:17:19 2012 +0100 @@ -27,6 +27,7 @@ */ #include +#include #include "base/cast.hh" #include "debug/RubyNetwork.hh" @@ -37,6 +38,13 @@ #include "mem/ruby/slicc_interface/NetworkMessage.hh" #include "mem/ruby/system/System.hh" +#ifdef USE_TOPAZ +#include +#include + +#include //Main simulator include +#endif + using namespace std; const int PRIORITY_SWITCH_LIMIT = 128; @@ -55,7 +63,9 @@ m_round_robin_start = 0; m_network_ptr = network_ptr; m_wakeups_wo_switch = 0; - +#ifdef USE_TOPAZ + m_ruby_start=0; +#endif for(int i = 0;i < m_virtual_networks;++i) { m_pending_message_count.push_back(0); @@ -96,6 +106,25 @@ m_routing_table.push_back(routing_table_entry); } +#ifdef USE_TOPAZ +void +PerfectSwitch::addOutNetPort(const vector& out, const NetDest& routing_table_entry){ + assert(out.size() == m_virtual_networks); + // Setup link order + LinkOrder l; + l.m_value = 0; + l.m_link = m_out.size(); + m_link_order.push_back(l); + // Add to routing table + m_out.push_back(out); + m_routing_table.push_back(routing_table_entry); + for (int j = 0; j < m_virtual_networks; j++) { + m_out[l.m_link][j]->setOutSwitchPort(); + m_out[l.m_link][j]->setNetwork(m_network_ptr); + m_out[l.m_link][j]->setVNet(j); + } +} +#endif void PerfectSwitch::clearRoutingTables() { @@ -128,18 +157,222 @@ { } -void -PerfectSwitch::wakeup() +#ifdef USE_TOPAZ +//****************************************************************************** +// Function in charge of calculating the destination of an Unicast message +//****************************************************************************** +int PerfectSwitch::getUnicastDestination(NetDest destinations) { + int this_id; + int m_queue=0; + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { + int limit = MachineType_base_count(mType); + for (int component = 0; component < limit; component++) { + MachineID mach = {mType, component}; + if (destinations.elementAt(mach)==1) { + this_id=m_network_ptr->getSwitch(m_queue+component); + return this_id; + } + } + m_queue += MachineType_base_count(mType); + } + assert(m_queue!=0); + return 1; +} + +//****************************************************************************** +// Function in charge of calculating the mask of a Multicast message +//****************************************************************************** +unsigned long long PerfectSwitch::getMulticastDestination(NetDest& destinations) { + unsigned long long routers = 0; + int node_number = 0; + for (MachineType m = MachineType_FIRST; m < MachineType_NUM; ++m) { + for (int c=0; cgetSwitch(node_number)); + routers = routers | mask; + } + node_number++; + } + } + return routers; +} + +//****************************************************************************** +// Function in charge of filtering messages with src=dst +// this kind of messages are not routed through TOPAZ network +//****************************************************************************** +void PerfectSwitch :: filterZeroDistanceMessages( MsgPtr& msg_ptr, int vnet, NetDest& destinations) { + int source=m_switch_id; + int destination; + bool isOrdered= m_network_ptr->isVNetOrdered(vnet); + int m_queue=0; + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType){ + int limit = MachineType_base_count(mType); + for (int component = 0; component < limit; component++) { + MachineID mach = {mType, component}; + if(destinations.elementAt(mach)==1) { + destination=m_network_ptr->getSwitch(m_queue+component); + if (source == destination){ + MessageBuffer* outputQueue=m_network_ptr->getFromSimNetQueue(component+m_queue, isOrdered, vnet); + MsgPtr unaMas=msg_ptr->clone(); + outputQueue->enqueue(unaMas); + destinations.remove(mach); // Here destinations are modified + } + } + } + m_queue += MachineType_base_count(mType); + } +} + +//****************************************************************************** +// This function returns a NetDest vector result of the following operation +// msg_destinations & Router_mask +// where Router_mask indicates which components are reachable through a certain +// switch +//****************************************************************************** +NetDest PerfectSwitch::getConsumerDestinations(int switch_id, NetDest& dest) { + NetDest consumers = m_network_ptr->getMachines(switch_id); + return consumers.AND(dest); +} + +//****************************************************************************** +// Function in charge of deciding which network must be used, GEMS or TOPAZ +//****************************************************************************** +void PerfectSwitch::wakeup() { + m_wakeups_wo_switch++; + int highest_prio_vnet = m_virtual_networks-1; + int source=m_switch_id; + for (int vnet = highest_prio_vnet; vnet >= 0; vnet--) { + //If we are in warmup or the adaptive interface is used and then network is lightly loadad we may ruby network + if (m_network_ptr->useGemsNetwork(vnet)) { + wakeupVnet(vnet); + } + //Otherwise, use topaz + else{ + if(m_pending_message_count[vnet]>0) + for(int incoming=0;incomingisReady()){ + MsgPtr msg_ptr = m_in[incoming][vnet]->peekMsgPtr(); + NetworkMessage *net_msg_ptr = dynamic_cast(msg_ptr.get()); + NetDest msg_destinations = net_msg_ptr->getInternalDestination(); + int topaz_size=m_network_ptr->getMessageSizeTopaz(net_msg_ptr->getMessageSize()); + assert(topaz_size); + filterZeroDistanceMessages( msg_ptr, vnet, msg_destinations); + if ( msg_destinations.count() !=0) { + TPZMessage msg; + TPZPosition origen; + TPZPosition destino; + MessageTopaz* copia=new MessageTopaz; + copia->message=msg_ptr->clone(); + copia->vnet=vnet; + copia->destinations=msg_destinations.count(); + // TOPAZ message generation + msg.setExternalInfo(static_cast(copia)); + msg.setGenerationTime(TPZSIMULATOR()->getSimulation(1)->getCurrentTime()); + origen=TPZSIMULATOR()->getSimulation(1)->getNetwork()->CreatePosition(source); //source is current switch + msg.setSource(origen); + msg.setVnet(vnet+1); + msg.setMessageSize(1); //Topaz supports 1-flit packets now. 2010-02 + msg.setPacketSize(topaz_size); + if (m_network_ptr->isVNetOrdered(vnet)){ + msg.setOrdered(); + m_network_ptr->increaseNumTopazOrderedMsg(msg_destinations.count()); + } + if (msg_destinations.count()==1) { + msg.clearMulticast(); + int componente = getUnicastDestination(msg_destinations); + destino=TPZSIMULATOR()->getSimulation(1)->getNetwork()->CreatePosition(componente); + msg.setDestiny(destino); + } + else { + msg.setMulticast(); + // This destination is necessary because topaz checks the existence of src and destination routers + // this destination is only used for this purpose, no messages will arrive to it. + msg.setDestiny(origen); + unsigned long long msgMask=getMulticastDestination(msg_destinations); + msg.setMsgmask(msgMask); + } + // Send the message to the network + DPRINTF(RubyNetwork, "Send at switch: [%d] vnet: [%d] time: [%d].\n", m_switch_id, vnet, g_eventQueue_ptr->getTime()); + TPZSIMULATOR()->getSimulation(1)->getNetwork()->sendMessage(msg); + m_network_ptr->increaseNumTopazMsg(msg_destinations.count()); + } + m_in[incoming][vnet]->pop(); + m_pending_message_count[vnet]--; + } + } + } + } + if (m_network_ptr->inWarmup()) return; //just a prewarmed simulation + if (m_network_ptr->getTriggerSwitch() == ~0) { + m_network_ptr->setTriggerSwitch(m_switch_id); + } + //Only first switch run and implement consumption. + if ( m_switch_id != m_network_ptr->getTriggerSwitch() ) return; + wakeUpTopaz(); +} + +//****************************************************************************** +// This function is in charge of running TOPAZ and collecting the messages +// to send then back to GEMS queues +//****************************************************************************** +void PerfectSwitch::wakeUpTopaz() { + long unsigned current_time = static_cast(g_eventQueue_ptr->getTime()) - m_ruby_start; + int procesorNetRatio=m_network_ptr->getProcRouterRatio(); + int messagesOnNets=0; + long diff_time = current_time - TPZSIMULATOR()->getSimulation(1)->getCurrentTime()*procesorNetRatio; + if (diff_time > 0) { + TPZSIMULATOR()->getSimulation(1)->setCurrentTime((current_time/procesorNetRatio)-1); + TPZSIMULATOR()->getSimulation(1)->run(1); + for (int consumer=0;consumergetSimulation(1)->getNetwork()->Number_of_nodes();consumer++) { + TPZPosition position_f=TPZSIMULATOR()->getSimulation(1)->getNetwork()->CreatePosition(consumer); + void* ptr =( TPZSIMULATOR()->getSimulation(1)->getExternalInfoAt(position_f)); + if (ptr!=NULL) { + MessageTopaz* topaz_message = static_cast(ptr); + assert (topaz_message->destinations>0); + MsgPtr localCopy = (topaz_message->message); + NetworkMessage* net_msg_ptr = dynamic_cast(localCopy.get()); + int vvnet=topaz_message->vnet; + int isOrdered= m_network_ptr->isVNetOrdered(vvnet); + NetDest ConsDestinations = getConsumerDestinations(consumer, net_msg_ptr->getInternalDestination()); + DPRINTF(RubyNetwork, "Arrival at switch: [%d] vnet: [%d] time: [%d].\n", consumer, vvnet, g_eventQueue_ptr->getTime()); + int m_queue=0; + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { + int limit = MachineType_base_count(mType); + for (int component = 0; component < limit; component++) { + MachineID mach = {mType, component}; + if(ConsDestinations.elementAt(mach)==1) { + MsgPtr unaMas = localCopy->clone(); + MessageBuffer* outputQueue=m_network_ptr->getFromSimNetQueue(component+m_queue, isOrdered, vvnet); + outputQueue->enqueue(unaMas); + topaz_message->destinations=topaz_message->destinations-1; + m_network_ptr->decreaseNumTopazMsg(vvnet); + } + } + m_queue += MachineType_base_count(mType); + } + int pendientes=topaz_message->destinations; + if (pendientes==0) delete topaz_message; + } + } + messagesOnNets=m_network_ptr->getTopazMessages(); + } + if ( messagesOnNets!=0) + g_eventQueue_ptr->scheduleEvent(this, 1); +} + +#else +void PerfectSwitch::wakeup() { - MsgPtr msg_ptr; - + DEBUG_EXPR(NETWORK_COMP, MedPrio, m_switch_id); // Give the highest numbered link priority most of the time m_wakeups_wo_switch++; int highest_prio_vnet = m_virtual_networks-1; int lowest_prio_vnet = 0; int decrementer = 1; - NetworkMessage* net_msg_ptr = NULL; - // invert priorities to avoid starvation seen in the component network if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) { m_wakeups_wo_switch = 0; @@ -147,19 +380,22 @@ lowest_prio_vnet = m_virtual_networks-1; decrementer = -1; } + for (int vnet = highest_prio_vnet; (vnet*decrementer) >= (decrementer*lowest_prio_vnet); vnet -= decrementer) { + // For all components incoming queues + wakeupVnet(vnet); + } +} +#endif //USE_TOPAZ - // For all components incoming queues - for (int vnet = highest_prio_vnet; - (vnet * decrementer) >= (decrementer * lowest_prio_vnet); - vnet -= decrementer) { - - // This is for round-robin scheduling +void PerfectSwitch::wakeupVnet(int vnet) { + NetworkMessage* net_msg_ptr; + MsgPtr msg_ptr; + // This is for round-robin scheduling int incoming = m_round_robin_start; m_round_robin_start++; if (m_round_robin_start >= m_in.size()) { m_round_robin_start = 0; } - if(m_pending_message_count[vnet] > 0) { // for all input ports, use round robin scheduling for (int counter = 0; counter < m_in.size(); counter++) { @@ -168,32 +404,34 @@ if (incoming >= m_in.size()) { incoming = 0; } - // temporary vectors to store the routing results vector output_links; vector output_link_destinations; - // Is there a message waiting? while (m_in[incoming][vnet]->isReady()) { DPRINTF(RubyNetwork, "incoming: %d\n", incoming); - // Peek at message msg_ptr = m_in[incoming][vnet]->peekMsgPtr(); net_msg_ptr = safe_cast(msg_ptr.get()); DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); - +#ifdef USE_TOPAZ + // Keeping track of messeges through GEMS + if( m_in[incoming][vnet]->isInPort()) { + if (m_network_ptr->isVNetOrdered(vnet)) { + m_network_ptr->increaseNumOrderedMsg(net_msg_ptr->getInternalDestination().count()); + } + m_network_ptr->increaseTotalMsg(net_msg_ptr->getInternalDestination().count()); + } +#endif output_links.clear(); output_link_destinations.clear(); NetDest msg_dsts = net_msg_ptr->getInternalDestination(); - // Unfortunately, the token-protocol sends some // zero-destination messages, so this assert isn't valid // assert(msg_dsts.count() > 0); - assert(m_link_order.size() == m_routing_table.size()); assert(m_link_order.size() == m_out.size()); - if (m_network_ptr->getAdaptiveRouting()) { if (m_network_ptr->isVNetOrdered(vnet)) { // Don't adaptively route @@ -218,7 +456,6 @@ sort(m_link_order.begin(), m_link_order.end()); } } - for (int i = 0; i < m_routing_table.size(); i++) { // pick the next link to look at int link = m_link_order[i].m_link; @@ -304,7 +541,16 @@ "inport[%d][%d] to outport [%d][%d].\n", incoming, vnet, outgoing, vnet); - m_out[outgoing][vnet]->enqueue(msg_ptr); + //m_out[outgoing][vnet]->enqueue(msg_ptr); + int spooling_delay=1; + +#ifdef USE_TOPAZ + if (m_out[outgoing][vnet]->isOutSwitchPort()) { + net_msg_ptr = safe_cast(msg_ptr.get()); + spooling_delay += m_network_ptr->getMessageSizeTopaz(net_msg_ptr->getMessageSize()); + } +#endif + m_out[outgoing][vnet]->enqueue(msg_ptr,spooling_delay); } // Dequeue msg @@ -314,7 +560,7 @@ } } } -} + void PerfectSwitch::storeEventInfo(int info) @@ -322,25 +568,22 @@ m_pending_message_count[info]++; } -void -PerfectSwitch::printStats(std::ostream& out) const + +void PerfectSwitch::printStats(std::ostream& out) const { - out << "PerfectSwitch printStats" << endl; + out << "PerfectSwitch printStats" << endl; } -void -PerfectSwitch::clearStats() +void PerfectSwitch::clearStats() { } -void -PerfectSwitch::printConfig(std::ostream& out) const +void PerfectSwitch::printConfig(std::ostream& out) const { } -void -PerfectSwitch::print(std::ostream& out) const +void PerfectSwitch::print(std::ostream& out) const { - out << "[PerfectSwitch " << m_switch_id << "]"; + out << "[PerfectSwitch " << m_switch_id << "]"; } diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/simple/PerfectSwitch.cc --- a/src/mem/ruby/network/simple/PerfectSwitch.cc Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc Mon Mar 19 19:34:15 2012 +0100 @@ -27,7 +27,6 @@ */ #include -#include #include "base/cast.hh" #include "debug/RubyNetwork.hh" @@ -38,13 +37,6 @@ #include "mem/ruby/slicc_interface/NetworkMessage.hh" #include "mem/ruby/system/System.hh" -#ifdef USE_TOPAZ -#include -#include - -#include //Main simulator include -#endif - using namespace std; const int PRIORITY_SWITCH_LIMIT = 128; @@ -63,9 +55,7 @@ m_round_robin_start = 0; m_network_ptr = network_ptr; m_wakeups_wo_switch = 0; -#ifdef USE_TOPAZ - m_ruby_start=0; -#endif + for(int i = 0;i < m_virtual_networks;++i) { m_pending_message_count.push_back(0); @@ -106,25 +96,6 @@ m_routing_table.push_back(routing_table_entry); } -#ifdef USE_TOPAZ -void -PerfectSwitch::addOutNetPort(const vector& out, const NetDest& routing_table_entry){ - assert(out.size() == m_virtual_networks); - // Setup link order - LinkOrder l; - l.m_value = 0; - l.m_link = m_out.size(); - m_link_order.push_back(l); - // Add to routing table - m_out.push_back(out); - m_routing_table.push_back(routing_table_entry); - for (int j = 0; j < m_virtual_networks; j++) { - m_out[l.m_link][j]->setOutSwitchPort(); - m_out[l.m_link][j]->setNetwork(m_network_ptr); - m_out[l.m_link][j]->setVNet(j); - } -} -#endif void PerfectSwitch::clearRoutingTables() { @@ -157,222 +128,18 @@ { } -#ifdef USE_TOPAZ -//****************************************************************************** -// Function in charge of calculating the destination of an Unicast message -//****************************************************************************** -int PerfectSwitch::getUnicastDestination(NetDest destinations) { - int this_id; - int m_queue=0; - for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { - int limit = MachineType_base_count(mType); - for (int component = 0; component < limit; component++) { - MachineID mach = {mType, component}; - if (destinations.elementAt(mach)==1) { - this_id=m_network_ptr->getSwitch(m_queue+component); - return this_id; - } - } - m_queue += MachineType_base_count(mType); - } - assert(m_queue!=0); - return 1; -} +void +PerfectSwitch::wakeup() +{ + MsgPtr msg_ptr; -//****************************************************************************** -// Function in charge of calculating the mask of a Multicast message -//****************************************************************************** -unsigned long long PerfectSwitch::getMulticastDestination(NetDest& destinations) { - unsigned long long routers = 0; - int node_number = 0; - for (MachineType m = MachineType_FIRST; m < MachineType_NUM; ++m) { - for (int c=0; cgetSwitch(node_number)); - routers = routers | mask; - } - node_number++; - } - } - return routers; -} - -//****************************************************************************** -// Function in charge of filtering messages with src=dst -// this kind of messages are not routed through TOPAZ network -//****************************************************************************** -void PerfectSwitch :: filterZeroDistanceMessages( MsgPtr& msg_ptr, int vnet, NetDest& destinations) { - int source=m_switch_id; - int destination; - bool isOrdered= m_network_ptr->isVNetOrdered(vnet); - int m_queue=0; - for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType){ - int limit = MachineType_base_count(mType); - for (int component = 0; component < limit; component++) { - MachineID mach = {mType, component}; - if(destinations.elementAt(mach)==1) { - destination=m_network_ptr->getSwitch(m_queue+component); - if (source == destination){ - MessageBuffer* outputQueue=m_network_ptr->getFromSimNetQueue(component+m_queue, isOrdered, vnet); - MsgPtr unaMas=msg_ptr->clone(); - outputQueue->enqueue(unaMas); - destinations.remove(mach); // Here destinations are modified - } - } - } - m_queue += MachineType_base_count(mType); - } -} - -//****************************************************************************** -// This function returns a NetDest vector result of the following operation -// msg_destinations & Router_mask -// where Router_mask indicates which components are reachable through a certain -// switch -//****************************************************************************** -NetDest PerfectSwitch::getConsumerDestinations(int switch_id, NetDest& dest) { - NetDest consumers = m_network_ptr->getMachines(switch_id); - return consumers.AND(dest); -} - -//****************************************************************************** -// Function in charge of deciding which network must be used, GEMS or TOPAZ -//****************************************************************************** -void PerfectSwitch::wakeup() { - m_wakeups_wo_switch++; - int highest_prio_vnet = m_virtual_networks-1; - int source=m_switch_id; - for (int vnet = highest_prio_vnet; vnet >= 0; vnet--) { - //If we are in warmup or the adaptive interface is used and then network is lightly loadad we may ruby network - if (m_network_ptr->useGemsNetwork(vnet)) { - wakeupVnet(vnet); - } - //Otherwise, use topaz - else{ - if(m_pending_message_count[vnet]>0) - for(int incoming=0;incomingisReady()){ - MsgPtr msg_ptr = m_in[incoming][vnet]->peekMsgPtr(); - NetworkMessage *net_msg_ptr = dynamic_cast(msg_ptr.get()); - NetDest msg_destinations = net_msg_ptr->getInternalDestination(); - int topaz_size=m_network_ptr->getMessageSizeTopaz(net_msg_ptr->getMessageSize()); - assert(topaz_size); - filterZeroDistanceMessages( msg_ptr, vnet, msg_destinations); - if ( msg_destinations.count() !=0) { - TPZMessage msg; - TPZPosition origen; - TPZPosition destino; - MessageTopaz* copia=new MessageTopaz; - copia->message=msg_ptr->clone(); - copia->vnet=vnet; - copia->destinations=msg_destinations.count(); - // TOPAZ message generation - msg.setExternalInfo(static_cast(copia)); - msg.setGenerationTime(TPZSIMULATOR()->getSimulation(1)->getCurrentTime()); - origen=TPZSIMULATOR()->getSimulation(1)->getNetwork()->CreatePosition(source); //source is current switch - msg.setSource(origen); - msg.setVnet(vnet+1); - msg.setMessageSize(1); //Topaz supports 1-flit packets now. 2010-02 - msg.setPacketSize(topaz_size); - if (m_network_ptr->isVNetOrdered(vnet)){ - msg.setOrdered(); - m_network_ptr->increaseNumTopazOrderedMsg(msg_destinations.count()); - } - if (msg_destinations.count()==1) { - msg.clearMulticast(); - int componente = getUnicastDestination(msg_destinations); - destino=TPZSIMULATOR()->getSimulation(1)->getNetwork()->CreatePosition(componente); - msg.setDestiny(destino); - } - else { - msg.setMulticast(); - // This destination is necessary because topaz checks the existence of src and destination routers - // this destination is only used for this purpose, no messages will arrive to it. - msg.setDestiny(origen); - unsigned long long msgMask=getMulticastDestination(msg_destinations); - msg.setMsgmask(msgMask); - } - // Send the message to the network - DPRINTF(RubyNetwork, "Send at switch: [%d] vnet: [%d] time: [%d].\n", m_switch_id, vnet, g_eventQueue_ptr->getTime()); - TPZSIMULATOR()->getSimulation(1)->getNetwork()->sendMessage(msg); - m_network_ptr->increaseNumTopazMsg(msg_destinations.count()); - } - m_in[incoming][vnet]->pop(); - m_pending_message_count[vnet]--; - } - } - } - } - if (m_network_ptr->inWarmup()) return; //just a prewarmed simulation - if (m_network_ptr->getTriggerSwitch() == ~0) { - m_network_ptr->setTriggerSwitch(m_switch_id); - } - //Only first switch run and implement consumption. - if ( m_switch_id != m_network_ptr->getTriggerSwitch() ) return; - wakeUpTopaz(); -} - -//****************************************************************************** -// This function is in charge of running TOPAZ and collecting the messages -// to send then back to GEMS queues -//****************************************************************************** -void PerfectSwitch::wakeUpTopaz() { - long unsigned current_time = static_cast(g_eventQueue_ptr->getTime()) - m_ruby_start; - int procesorNetRatio=m_network_ptr->getProcRouterRatio(); - int messagesOnNets=0; - long diff_time = current_time - TPZSIMULATOR()->getSimulation(1)->getCurrentTime()*procesorNetRatio; - if (diff_time > 0) { - TPZSIMULATOR()->getSimulation(1)->setCurrentTime((current_time/procesorNetRatio)-1); - TPZSIMULATOR()->getSimulation(1)->run(1); - for (int consumer=0;consumergetSimulation(1)->getNetwork()->Number_of_nodes();consumer++) { - TPZPosition position_f=TPZSIMULATOR()->getSimulation(1)->getNetwork()->CreatePosition(consumer); - void* ptr =( TPZSIMULATOR()->getSimulation(1)->getExternalInfoAt(position_f)); - if (ptr!=NULL) { - MessageTopaz* topaz_message = static_cast(ptr); - assert (topaz_message->destinations>0); - MsgPtr localCopy = (topaz_message->message); - NetworkMessage* net_msg_ptr = dynamic_cast(localCopy.get()); - int vvnet=topaz_message->vnet; - int isOrdered= m_network_ptr->isVNetOrdered(vvnet); - NetDest ConsDestinations = getConsumerDestinations(consumer, net_msg_ptr->getInternalDestination()); - DPRINTF(RubyNetwork, "Arrival at switch: [%d] vnet: [%d] time: [%d].\n", consumer, vvnet, g_eventQueue_ptr->getTime()); - int m_queue=0; - for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { - int limit = MachineType_base_count(mType); - for (int component = 0; component < limit; component++) { - MachineID mach = {mType, component}; - if(ConsDestinations.elementAt(mach)==1) { - MsgPtr unaMas = localCopy->clone(); - MessageBuffer* outputQueue=m_network_ptr->getFromSimNetQueue(component+m_queue, isOrdered, vvnet); - outputQueue->enqueue(unaMas); - topaz_message->destinations=topaz_message->destinations-1; - m_network_ptr->decreaseNumTopazMsg(vvnet); - } - } - m_queue += MachineType_base_count(mType); - } - int pendientes=topaz_message->destinations; - if (pendientes==0) delete topaz_message; - } - } - messagesOnNets=m_network_ptr->getTopazMessages(); - } - if ( messagesOnNets!=0) - g_eventQueue_ptr->scheduleEvent(this, 1); -} - -#else -void PerfectSwitch::wakeup() -{ - DEBUG_EXPR(NETWORK_COMP, MedPrio, m_switch_id); // Give the highest numbered link priority most of the time m_wakeups_wo_switch++; int highest_prio_vnet = m_virtual_networks-1; int lowest_prio_vnet = 0; int decrementer = 1; + NetworkMessage* net_msg_ptr = NULL; + // invert priorities to avoid starvation seen in the component network if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) { m_wakeups_wo_switch = 0; @@ -380,22 +147,19 @@ lowest_prio_vnet = m_virtual_networks-1; decrementer = -1; } - for (int vnet = highest_prio_vnet; (vnet*decrementer) >= (decrementer*lowest_prio_vnet); vnet -= decrementer) { - // For all components incoming queues - wakeupVnet(vnet); - } -} -#endif //USE_TOPAZ -void PerfectSwitch::wakeupVnet(int vnet) { - NetworkMessage* net_msg_ptr; - MsgPtr msg_ptr; - // This is for round-robin scheduling + // For all components incoming queues + for (int vnet = highest_prio_vnet; + (vnet * decrementer) >= (decrementer * lowest_prio_vnet); + vnet -= decrementer) { + + // This is for round-robin scheduling int incoming = m_round_robin_start; m_round_robin_start++; if (m_round_robin_start >= m_in.size()) { m_round_robin_start = 0; } + if(m_pending_message_count[vnet] > 0) { // for all input ports, use round robin scheduling for (int counter = 0; counter < m_in.size(); counter++) { @@ -404,34 +168,32 @@ if (incoming >= m_in.size()) { incoming = 0; } + // temporary vectors to store the routing results vector output_links; vector output_link_destinations; + // Is there a message waiting? while (m_in[incoming][vnet]->isReady()) { DPRINTF(RubyNetwork, "incoming: %d\n", incoming); + // Peek at message msg_ptr = m_in[incoming][vnet]->peekMsgPtr(); net_msg_ptr = safe_cast(msg_ptr.get()); DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); -#ifdef USE_TOPAZ - // Keeping track of messeges through GEMS - if( m_in[incoming][vnet]->isInPort()) { - if (m_network_ptr->isVNetOrdered(vnet)) { - m_network_ptr->increaseNumOrderedMsg(net_msg_ptr->getInternalDestination().count()); - } - m_network_ptr->increaseTotalMsg(net_msg_ptr->getInternalDestination().count()); - } -#endif + output_links.clear(); output_link_destinations.clear(); NetDest msg_dsts = net_msg_ptr->getInternalDestination(); + // Unfortunately, the token-protocol sends some // zero-destination messages, so this assert isn't valid // assert(msg_dsts.count() > 0); + assert(m_link_order.size() == m_routing_table.size()); assert(m_link_order.size() == m_out.size()); + if (m_network_ptr->getAdaptiveRouting()) { if (m_network_ptr->isVNetOrdered(vnet)) { // Don't adaptively route @@ -456,6 +218,7 @@ sort(m_link_order.begin(), m_link_order.end()); } } + for (int i = 0; i < m_routing_table.size(); i++) { // pick the next link to look at int link = m_link_order[i].m_link; @@ -541,16 +304,7 @@ "inport[%d][%d] to outport [%d][%d].\n", incoming, vnet, outgoing, vnet); - //m_out[outgoing][vnet]->enqueue(msg_ptr); - int spooling_delay=1; - -#ifdef USE_TOPAZ - if (m_out[outgoing][vnet]->isOutSwitchPort()) { - net_msg_ptr = safe_cast(msg_ptr.get()); - spooling_delay += m_network_ptr->getMessageSizeTopaz(net_msg_ptr->getMessageSize()); - } -#endif - m_out[outgoing][vnet]->enqueue(msg_ptr,spooling_delay); + m_out[outgoing][vnet]->enqueue(msg_ptr); } // Dequeue msg @@ -560,7 +314,7 @@ } } } - +} void PerfectSwitch::storeEventInfo(int info) @@ -568,22 +322,25 @@ m_pending_message_count[info]++; } - -void PerfectSwitch::printStats(std::ostream& out) const +void +PerfectSwitch::printStats(std::ostream& out) const { - out << "PerfectSwitch printStats" << endl; + out << "PerfectSwitch printStats" << endl; } -void PerfectSwitch::clearStats() +void +PerfectSwitch::clearStats() { } -void PerfectSwitch::printConfig(std::ostream& out) const +void +PerfectSwitch::printConfig(std::ostream& out) const { } -void PerfectSwitch::print(std::ostream& out) const +void +PerfectSwitch::print(std::ostream& out) const { - out << "[PerfectSwitch " << m_switch_id << "]"; + out << "[PerfectSwitch " << m_switch_id << "]"; } diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/simple/SimpleNetwork.hh --- a/src/mem/ruby/network/simple/SimpleNetwork.hh Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/simple/SimpleNetwork.hh Mon Mar 12 18:17:19 2012 +0100 @@ -37,6 +37,25 @@ #include "params/SimpleNetwork.hh" #include "sim/sim_object.hh" +#ifdef USE_TOPAZ +#include +#include + +#include //Main simulator include + +#include "mem/ruby/slicc_interface/NetworkMessage.hh" +struct MessageTopaz{ + MsgPtr message; + int vnet; + int queue; + int destinations; + int bcast; + int id; + //added para multicast + std::vector > Vector_aux; +}; +#endif + class NetDest; class MessageBuffer; class Throttle; @@ -60,6 +79,41 @@ void clearStats(); void printConfig(std::ostream& out) const; +#ifdef USE_TOPAZ + int getNumberOfNodes()const {return m_nodes;}; + unsigned getProcRouterRatio() const { return m_processorClockRatio;} + unsigned getFlitSize() const { return m_flitSize;} + unsigned getUnifiy() { return m_unify; } + // returns the number of switches in the network + int getNetSize() { return m_switch_ptr_vector.size(); } + int getMessageSizeTopaz(MessageSizeType size_type) const; + int getTriggerSwitch() const { return m_firstTrigger; } + void setTriggerSwitch(int router) { m_firstTrigger=router; } + bool inWarmup() { return m_in_warmup; } + bool useGemsNetwork(int vnet); + void enableTopaz(); + void disableTopaz(); + void increaseNumMsg(int num); + void decreaseNumMsg(int vnet); + void increaseNumOrderedMsg(int num); + void increaseNumTopazOrderedMsg (int num); + void increaseNumTopazMsg(int num); + void decreaseNumTopazMsg (int vnet); + int getTopazMessages() { return m_number_topaz_messages; } + void increaseTotalMsg (int num) { m_totalNetMsg+=num; } + int getTotalMsg () { return m_totalNetMsg; } + int getTotalTopazMsg() { return m_totalTopazMsg; } + const unsigned numberOfMessages() { return m_number_messages; } + const unsigned numberOfOrderedMessages() { return m_number_ordered_messages; } + const unsigned numberOfTopazOrderedMessages() { return m_number_topaz_ordered_messages; } + const unsigned numberOfTopazMessages() { return m_number_topaz_messages; } + void setTopazMapping (SwitchID node0, SwitchID node1); + SwitchID getSwitch(int ext_node) { return m_forward_mapping[ext_node]; } + NetDest getMachines(SwitchID sid) { return m_reverse_mapping[sid]; } + MessageBuffer* getToSimNetQueue(NodeID id, bool ordered, int network_num); + MessageBuffer* getFromSimNetQueue(NodeID id, bool ordered, int network_num); +#endif //USE_TOPAZ + void reset(); // returns the queue requested for the given component @@ -97,6 +151,27 @@ void makeTopology(); void linkTopology(); +#ifdef USE_TOPAZ + unsigned m_processorClockRatio; + unsigned m_flitSize; + unsigned m_unify; + int m_firstTrigger; + bool m_in_warmup; + unsigned m_permanentDisable; + int m_number_messages; + int m_number_ordered_messages; + int m_number_topaz_ordered_messages; + int m_number_topaz_messages; + SwitchID *m_forward_mapping; //maps each MachineID to the internal node it is connected to. + std::vector m_reverse_mapping; //maps each internal node to the MachineIDs it connects. + int m_totalNetMsg; + int m_totalTopazMsg; + TPZString m_simulName; + TPZString m_topazInitFile; + unsigned m_block_size; + unsigned m_topaz_adaptive_interface_threshold; +#endif + // Private copy constructor and assignment operator SimpleNetwork(const SimpleNetwork& obj); SimpleNetwork& operator=(const SimpleNetwork& obj); diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/simple/SimpleNetwork.hh --- a/src/mem/ruby/network/simple/SimpleNetwork.hh Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/simple/SimpleNetwork.hh Mon Mar 19 19:34:15 2012 +0100 @@ -37,25 +37,6 @@ #include "params/SimpleNetwork.hh" #include "sim/sim_object.hh" -#ifdef USE_TOPAZ -#include -#include - -#include //Main simulator include - -#include "mem/ruby/slicc_interface/NetworkMessage.hh" -struct MessageTopaz{ - MsgPtr message; - int vnet; - int queue; - int destinations; - int bcast; - int id; - //added para multicast - std::vector > Vector_aux; -}; -#endif - class NetDest; class MessageBuffer; class Throttle; @@ -79,41 +60,6 @@ void clearStats(); void printConfig(std::ostream& out) const; -#ifdef USE_TOPAZ - int getNumberOfNodes()const {return m_nodes;}; - unsigned getProcRouterRatio() const { return m_processorClockRatio;} - unsigned getFlitSize() const { return m_flitSize;} - unsigned getUnifiy() { return m_unify; } - // returns the number of switches in the network - int getNetSize() { return m_switch_ptr_vector.size(); } - int getMessageSizeTopaz(MessageSizeType size_type) const; - int getTriggerSwitch() const { return m_firstTrigger; } - void setTriggerSwitch(int router) { m_firstTrigger=router; } - bool inWarmup() { return m_in_warmup; } - bool useGemsNetwork(int vnet); - void enableTopaz(); - void disableTopaz(); - void increaseNumMsg(int num); - void decreaseNumMsg(int vnet); - void increaseNumOrderedMsg(int num); - void increaseNumTopazOrderedMsg (int num); - void increaseNumTopazMsg(int num); - void decreaseNumTopazMsg (int vnet); - int getTopazMessages() { return m_number_topaz_messages; } - void increaseTotalMsg (int num) { m_totalNetMsg+=num; } - int getTotalMsg () { return m_totalNetMsg; } - int getTotalTopazMsg() { return m_totalTopazMsg; } - const unsigned numberOfMessages() { return m_number_messages; } - const unsigned numberOfOrderedMessages() { return m_number_ordered_messages; } - const unsigned numberOfTopazOrderedMessages() { return m_number_topaz_ordered_messages; } - const unsigned numberOfTopazMessages() { return m_number_topaz_messages; } - void setTopazMapping (SwitchID node0, SwitchID node1); - SwitchID getSwitch(int ext_node) { return m_forward_mapping[ext_node]; } - NetDest getMachines(SwitchID sid) { return m_reverse_mapping[sid]; } - MessageBuffer* getToSimNetQueue(NodeID id, bool ordered, int network_num); - MessageBuffer* getFromSimNetQueue(NodeID id, bool ordered, int network_num); -#endif //USE_TOPAZ - void reset(); // returns the queue requested for the given component @@ -151,27 +97,6 @@ void makeTopology(); void linkTopology(); -#ifdef USE_TOPAZ - unsigned m_processorClockRatio; - unsigned m_flitSize; - unsigned m_unify; - int m_firstTrigger; - bool m_in_warmup; - unsigned m_permanentDisable; - int m_number_messages; - int m_number_ordered_messages; - int m_number_topaz_ordered_messages; - int m_number_topaz_messages; - SwitchID *m_forward_mapping; //maps each MachineID to the internal node it is connected to. - std::vector m_reverse_mapping; //maps each internal node to the MachineIDs it connects. - int m_totalNetMsg; - int m_totalTopazMsg; - TPZString m_simulName; - TPZString m_topazInitFile; - unsigned m_block_size; - unsigned m_topaz_adaptive_interface_threshold; -#endif - // Private copy constructor and assignment operator SimpleNetwork(const SimpleNetwork& obj); SimpleNetwork& operator=(const SimpleNetwork& obj); diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/simple/SimpleNetwork.cc --- a/src/mem/ruby/network/simple/SimpleNetwork.cc Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc Mon Mar 12 18:17:19 2012 +0100 @@ -31,14 +31,15 @@ #include "base/cast.hh" #include "base/stl_helpers.hh" +#include "debug/RubyNetwork.hh" #include "mem/protocol/TopologyType.hh" #include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/common/NetDest.hh" -#include "mem/ruby/network/BasicLink.hh" #include "mem/ruby/network/simple/SimpleLink.hh" #include "mem/ruby/network/simple/SimpleNetwork.hh" #include "mem/ruby/network/simple/Switch.hh" #include "mem/ruby/network/simple/Throttle.hh" +#include "mem/ruby/network/BasicLink.hh" #include "mem/ruby/network/Topology.hh" #include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/system/System.hh" @@ -65,20 +66,50 @@ m_in_use[i] = false; m_ordered[i] = false; } - +#ifdef USE_TOPAZ + m_number_messages=0; + m_number_ordered_messages=0; + m_number_topaz_ordered_messages=0; + m_number_topaz_messages=0; + m_totalNetMsg=0; + m_totalTopazMsg=0; + m_forward_mapping = new SwitchID[m_nodes]; + m_reverse_mapping.resize(m_nodes); +#endif // Allocate to and from queues m_toNetQueues.resize(m_nodes); m_fromNetQueues.resize(m_nodes); for (int node = 0; node < m_nodes; node++) { - m_toNetQueues[node].resize(m_virtual_networks); - m_fromNetQueues[node].resize(m_virtual_networks); - for (int j = 0; j < m_virtual_networks; j++) { - m_toNetQueues[node][j] = - new MessageBuffer(csprintf("toNet node %d j %d", node, j)); - m_fromNetQueues[node][j] = - new MessageBuffer(csprintf("fromNet node %d j %d", node, j)); + m_toNetQueues[node].resize(m_virtual_networks); + m_fromNetQueues[node].resize(m_virtual_networks); + for (int j = 0; j < m_virtual_networks; j++) { + m_toNetQueues[node][j] = new MessageBuffer(csprintf("toNet node %d j %d", node, j)); +#ifdef USE_TOPAZ + m_toNetQueues[node][j]->setInPort(); + m_toNetQueues[node][j]->setNetwork(this); + m_toNetQueues[node][j]->setVNet(j); +#endif + m_fromNetQueues[node][j] = new MessageBuffer(csprintf("fromNet node %d j %d", node, j)); +#ifdef USE_TOPAZ + m_fromNetQueues[node][j]->setOutPort(); + m_fromNetQueues[node][j]->setNetwork(this); + m_fromNetQueues[node][j]->setVNet(j); +#endif } } +#ifdef USE_TOPAZ + m_flitSize=p->topaz_flit_size; + m_processorClockRatio=p->topaz_clock_ratio; + m_simulName = (p->topaz_network).c_str(); + m_topazInitFile = (p->topaz_init_file).c_str(); + m_topaz_adaptive_interface_threshold = p->topaz_adaptive_interface_threshold; +#else + //die if you want to use topaz without compiling it before. + if(p->topaz_network){ + cerr<<"You have to compile GEM5 with topaz support in order to use it"<createLinks(this, false); + // + // TOPAZ INITIALIZATION AND INSTALLERS + // + // +#ifdef USE_TOPAZ + //Support for CMP or SMP but not SMP of CMP + //if( g_PROCS_PER_CHIP > 1 && g_NUM_PROCESSORS > g_PROCS_PER_CHIP ){ + // cerr< Feature not implemented. Only CMP or non-CMP SMPs "< Topaz will be disabled we run only with a ideal Network "< If this is not intended, you should UNSET Crossbar as top. "< Can't open topaz init file :: " << m_topazInitFile << endl; + cerr<<" That file must have the route to Router, Network & Simulation SGML"<< endl; + cerr<<" you can declare it with --topaz-init-file"<"<createSimulation(initString); + //Simulated networks go from 1,2... (Watch out! is +1 than slicc's vnets) + if (TPZSIMULATOR()->getSimulation(1)->needToUnify()) { + m_unify=1; + break; + } + else { + m_unify=m_virtual_networks; + } + } + if (m_flitSize == 0) { //Not specified by ruby con + m_flitSize=TPZSIMULATOR()->getSimulation(1)->getFlitSize(); + cerr<<"Warning:topaz_flit was not specified in in Ruby.py options. It will be get from SGML specification."< FLITSIZE must be specified in simulation sgml file as " << endl; + assert(0); + } + + for (unsigned i = 1; i <= m_unify; i++) + TPZSIMULATOR()->getSimulation(i)->setPacketLength(getMessageSizeTopaz(MessageSizeType_Data)); //VCT applied. Largest packet + //Clock ratio + if (m_processorClockRatio == 0 ) { + m_processorClockRatio=int(TPZSIMULATOR()->getSimulation(1)->getNetworkClockRatioSGML()); + } + //Network cant be faster than memory + assert(m_processorClockRatio>=1); + + this->enableTopaz(); //If some one need to run with topaz (recorder ... vgr... should disable + //srandom(p->random_seed); //Topaz may try to adjust random seed in initialization. Do it again for variab + //srand(p->random_seed); +#endif } +#ifdef USE_TOPAZ +int SimpleNetwork::getMessageSizeTopaz(MessageSizeType size_type) const { + //Padding last flit + return (int) ceil((double) RubySystem::getNetwork()-> MessageSizeType_to_int( + size_type)/m_flitSize); +} + + +bool SimpleNetwork::useGemsNetwork(int vnet) { + // During warmup we use GEMS' network + if (inWarmup()) return true; + // Messages in order must go all through the same network. If this is an + // ordered virtual network, send the message through the network where you + // find any message. + if (isVNetOrdered(vnet)) { + if (numberOfOrderedMessages() > 0) { + assert(numberOfTopazOrderedMessages() == 0); + return true; + } + else if (numberOfTopazOrderedMessages() > 0) { + return false; + } + } + const int messages_in_ruby = numberOfMessages(); + if (m_number_topaz_messages < 0) { + static bool warn_topaz_count_is_wrong = true; + if (warn_topaz_count_is_wrong) { + DPRINTF(RubyNetwork,"Topaz is not counting messages correctly, ignoring g_MAX_MESSAGES_THROUGH_GEMS."); + DPRINTF(RubyNetwork,"Please, fix topaz if you want to use this parameter."); + warn_topaz_count_is_wrong = false; + } + return false; + } + // If the total number of messages is small (less than m_topaz_adaptive_interface_threshold), we can use the simplistic GEMS network + if ((messages_in_ruby + m_number_topaz_messages) < m_topaz_adaptive_interface_threshold) + return true; + else + return false; +} + +void SimpleNetwork::enableTopaz(){ + if( m_permanentDisable ){ + cout<<"TOPAZ PERMANETLY DISABLED"< +++++++ Topaz Enabled! +++++++ "< ******* Topaz DISABLED! ******* "<"<getSimulation(currentVnet)->writeSimulationStatus(out); + cerr<<"Messages in :"<"<< + m_number_topaz_messages<getSimulation(currentVnet)->getNetwork()->writeComponentStatus(out); + } + out<<""<printStats(out); } m_topology_ptr->printStats(out); +#endif } void @@ -352,6 +535,52 @@ out << "[SimpleNetwork]"; } +#ifdef USE_TOPAZ +void SimpleNetwork::increaseNumMsg(int num){ + m_number_messages+=num; +} + +void SimpleNetwork::increaseNumTopazMsg(int num){ + m_number_topaz_messages+=num; + m_totalTopazMsg+=num; +} + +void SimpleNetwork::decreaseNumMsg(int vnet){ + m_number_messages--; + assert(m_number_messages >= 0); + if (m_ordered[vnet]){ + if ( numberOfOrderedMessages() > 0 ){ + assert(!(numberOfTopazOrderedMessages()>0)); + m_number_ordered_messages--; + } + } +} + +void SimpleNetwork::decreaseNumTopazMsg (int vnet){ + m_number_topaz_messages--; + assert(m_number_messages >= 0); + if ( m_ordered[vnet] ){ + assert(!(numberOfOrderedMessages()>0)); + m_number_topaz_ordered_messages--; + } +} + +void SimpleNetwork::increaseNumOrderedMsg(int num){ + m_number_ordered_messages+=num; +} + +void SimpleNetwork::increaseNumTopazOrderedMsg(int num){ + m_number_topaz_ordered_messages+=num; +} + +void SimpleNetwork::setTopazMapping (SwitchID ext_node, SwitchID int_node) { + int_node -= 2*m_nodes; + MachineID machine = nodeNumber_to_MachineID(ext_node); + m_forward_mapping[ext_node] = int_node; + m_reverse_mapping[int_node].add(machine); +} + +#endif SimpleNetwork * SimpleNetworkParams::create() diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/simple/SimpleNetwork.cc --- a/src/mem/ruby/network/simple/SimpleNetwork.cc Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc Mon Mar 19 19:34:15 2012 +0100 @@ -31,15 +31,14 @@ #include "base/cast.hh" #include "base/stl_helpers.hh" -#include "debug/RubyNetwork.hh" #include "mem/protocol/TopologyType.hh" #include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/common/NetDest.hh" +#include "mem/ruby/network/BasicLink.hh" #include "mem/ruby/network/simple/SimpleLink.hh" #include "mem/ruby/network/simple/SimpleNetwork.hh" #include "mem/ruby/network/simple/Switch.hh" #include "mem/ruby/network/simple/Throttle.hh" -#include "mem/ruby/network/BasicLink.hh" #include "mem/ruby/network/Topology.hh" #include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/system/System.hh" @@ -66,50 +65,20 @@ m_in_use[i] = false; m_ordered[i] = false; } -#ifdef USE_TOPAZ - m_number_messages=0; - m_number_ordered_messages=0; - m_number_topaz_ordered_messages=0; - m_number_topaz_messages=0; - m_totalNetMsg=0; - m_totalTopazMsg=0; - m_forward_mapping = new SwitchID[m_nodes]; - m_reverse_mapping.resize(m_nodes); -#endif + // Allocate to and from queues m_toNetQueues.resize(m_nodes); m_fromNetQueues.resize(m_nodes); for (int node = 0; node < m_nodes; node++) { - m_toNetQueues[node].resize(m_virtual_networks); - m_fromNetQueues[node].resize(m_virtual_networks); - for (int j = 0; j < m_virtual_networks; j++) { - m_toNetQueues[node][j] = new MessageBuffer(csprintf("toNet node %d j %d", node, j)); -#ifdef USE_TOPAZ - m_toNetQueues[node][j]->setInPort(); - m_toNetQueues[node][j]->setNetwork(this); - m_toNetQueues[node][j]->setVNet(j); -#endif - m_fromNetQueues[node][j] = new MessageBuffer(csprintf("fromNet node %d j %d", node, j)); -#ifdef USE_TOPAZ - m_fromNetQueues[node][j]->setOutPort(); - m_fromNetQueues[node][j]->setNetwork(this); - m_fromNetQueues[node][j]->setVNet(j); -#endif + m_toNetQueues[node].resize(m_virtual_networks); + m_fromNetQueues[node].resize(m_virtual_networks); + for (int j = 0; j < m_virtual_networks; j++) { + m_toNetQueues[node][j] = + new MessageBuffer(csprintf("toNet node %d j %d", node, j)); + m_fromNetQueues[node][j] = + new MessageBuffer(csprintf("fromNet node %d j %d", node, j)); } } -#ifdef USE_TOPAZ - m_flitSize=p->topaz_flit_size; - m_processorClockRatio=p->topaz_clock_ratio; - m_simulName = (p->topaz_network).c_str(); - m_topazInitFile = (p->topaz_init_file).c_str(); - m_topaz_adaptive_interface_threshold = p->topaz_adaptive_interface_threshold; -#else - //die if you want to use topaz without compiling it before. - if(p->topaz_network){ - cerr<<"You have to compile GEM5 with topaz support in order to use it"<createLinks(this, false); - // - // TOPAZ INITIALIZATION AND INSTALLERS - // - // -#ifdef USE_TOPAZ - //Support for CMP or SMP but not SMP of CMP - //if( g_PROCS_PER_CHIP > 1 && g_NUM_PROCESSORS > g_PROCS_PER_CHIP ){ - // cerr< Feature not implemented. Only CMP or non-CMP SMPs "< Topaz will be disabled we run only with a ideal Network "< If this is not intended, you should UNSET Crossbar as top. "< Can't open topaz init file :: " << m_topazInitFile << endl; - cerr<<" That file must have the route to Router, Network & Simulation SGML"<< endl; - cerr<<" you can declare it with --topaz-init-file"<"<createSimulation(initString); - //Simulated networks go from 1,2... (Watch out! is +1 than slicc's vnets) - if (TPZSIMULATOR()->getSimulation(1)->needToUnify()) { - m_unify=1; - break; - } - else { - m_unify=m_virtual_networks; - } - } - if (m_flitSize == 0) { //Not specified by ruby con - m_flitSize=TPZSIMULATOR()->getSimulation(1)->getFlitSize(); - cerr<<"Warning:topaz_flit was not specified in in Ruby.py options. It will be get from SGML specification."< FLITSIZE must be specified in simulation sgml file as " << endl; - assert(0); - } - - for (unsigned i = 1; i <= m_unify; i++) - TPZSIMULATOR()->getSimulation(i)->setPacketLength(getMessageSizeTopaz(MessageSizeType_Data)); //VCT applied. Largest packet - //Clock ratio - if (m_processorClockRatio == 0 ) { - m_processorClockRatio=int(TPZSIMULATOR()->getSimulation(1)->getNetworkClockRatioSGML()); - } - //Network cant be faster than memory - assert(m_processorClockRatio>=1); - - this->enableTopaz(); //If some one need to run with topaz (recorder ... vgr... should disable - //srandom(p->random_seed); //Topaz may try to adjust random seed in initialization. Do it again for variab - //srand(p->random_seed); -#endif } -#ifdef USE_TOPAZ -int SimpleNetwork::getMessageSizeTopaz(MessageSizeType size_type) const { - //Padding last flit - return (int) ceil((double) RubySystem::getNetwork()-> MessageSizeType_to_int( - size_type)/m_flitSize); -} - - -bool SimpleNetwork::useGemsNetwork(int vnet) { - // During warmup we use GEMS' network - if (inWarmup()) return true; - // Messages in order must go all through the same network. If this is an - // ordered virtual network, send the message through the network where you - // find any message. - if (isVNetOrdered(vnet)) { - if (numberOfOrderedMessages() > 0) { - assert(numberOfTopazOrderedMessages() == 0); - return true; - } - else if (numberOfTopazOrderedMessages() > 0) { - return false; - } - } - const int messages_in_ruby = numberOfMessages(); - if (m_number_topaz_messages < 0) { - static bool warn_topaz_count_is_wrong = true; - if (warn_topaz_count_is_wrong) { - DPRINTF(RubyNetwork,"Topaz is not counting messages correctly, ignoring g_MAX_MESSAGES_THROUGH_GEMS."); - DPRINTF(RubyNetwork,"Please, fix topaz if you want to use this parameter."); - warn_topaz_count_is_wrong = false; - } - return false; - } - // If the total number of messages is small (less than m_topaz_adaptive_interface_threshold), we can use the simplistic GEMS network - if ((messages_in_ruby + m_number_topaz_messages) < m_topaz_adaptive_interface_threshold) - return true; - else - return false; -} - -void SimpleNetwork::enableTopaz(){ - if( m_permanentDisable ){ - cout<<"TOPAZ PERMANETLY DISABLED"< +++++++ Topaz Enabled! +++++++ "< ******* Topaz DISABLED! ******* "<"<getSimulation(currentVnet)->writeSimulationStatus(out); - cerr<<"Messages in :"<"<< - m_number_topaz_messages<getSimulation(currentVnet)->getNetwork()->writeComponentStatus(out); - } - out<<""<printStats(out); } m_topology_ptr->printStats(out); -#endif } void @@ -535,52 +352,6 @@ out << "[SimpleNetwork]"; } -#ifdef USE_TOPAZ -void SimpleNetwork::increaseNumMsg(int num){ - m_number_messages+=num; -} - -void SimpleNetwork::increaseNumTopazMsg(int num){ - m_number_topaz_messages+=num; - m_totalTopazMsg+=num; -} - -void SimpleNetwork::decreaseNumMsg(int vnet){ - m_number_messages--; - assert(m_number_messages >= 0); - if (m_ordered[vnet]){ - if ( numberOfOrderedMessages() > 0 ){ - assert(!(numberOfTopazOrderedMessages()>0)); - m_number_ordered_messages--; - } - } -} - -void SimpleNetwork::decreaseNumTopazMsg (int vnet){ - m_number_topaz_messages--; - assert(m_number_messages >= 0); - if ( m_ordered[vnet] ){ - assert(!(numberOfOrderedMessages()>0)); - m_number_topaz_ordered_messages--; - } -} - -void SimpleNetwork::increaseNumOrderedMsg(int num){ - m_number_ordered_messages+=num; -} - -void SimpleNetwork::increaseNumTopazOrderedMsg(int num){ - m_number_topaz_ordered_messages+=num; -} - -void SimpleNetwork::setTopazMapping (SwitchID ext_node, SwitchID int_node) { - int_node -= 2*m_nodes; - MachineID machine = nodeNumber_to_MachineID(ext_node); - m_forward_mapping[ext_node] = int_node; - m_reverse_mapping[int_node].add(machine); -} - -#endif SimpleNetwork * SimpleNetworkParams::create() diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/simple/SimpleNetwork.py --- a/src/mem/ruby/network/simple/SimpleNetwork.py Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/simple/SimpleNetwork.py Mon Mar 12 18:17:19 2012 +0100 @@ -36,3 +36,8 @@ "default buffer size; 0 indicates infinite buffering"); endpoint_bandwidth = Param.Int(1000, "bandwidth adjustment factor"); adaptive_routing = Param.Bool(False, "enable adaptive routing"); + topaz_init_file = Param.String("./TPZSimul,ini", "File that declares .sgm, .sgm and .sgm"); + topaz_network =Param.String (None, "TOPAZ: simulation listed in .sgm to be used by TOPAZ"); + topaz_flit_size = Param.Int(0, "Number of bytes per physical router-to-router wire"); + topaz_clock_ratio = Param.Int(1,"memory-network clock multiplier"); + topaz_adaptive_interface_threshold = Param.Int(0,"Number of messages that has to be transmitted before to activate TOPAZ"); diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/simple/SimpleNetwork.py --- a/src/mem/ruby/network/simple/SimpleNetwork.py Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/simple/SimpleNetwork.py Mon Mar 19 19:34:15 2012 +0100 @@ -36,8 +36,3 @@ "default buffer size; 0 indicates infinite buffering"); endpoint_bandwidth = Param.Int(1000, "bandwidth adjustment factor"); adaptive_routing = Param.Bool(False, "enable adaptive routing"); - topaz_init_file = Param.String("./TPZSimul,ini", "File that declares .sgm, .sgm and .sgm"); - topaz_network =Param.String (None, "TOPAZ: simulation listed in .sgm to be used by TOPAZ"); - topaz_flit_size = Param.Int(0, "Number of bytes per physical router-to-router wire"); - topaz_clock_ratio = Param.Int(1,"memory-network clock multiplier"); - topaz_adaptive_interface_threshold = Param.Int(0,"Number of messages that has to be transmitted before to activate TOPAZ"); diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/simple/Switch.hh --- a/src/mem/ruby/network/simple/Switch.hh Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/simple/Switch.hh Mon Mar 12 18:17:19 2012 +0100 @@ -71,6 +71,9 @@ void printConfig(std::ostream& out) const; void print(std::ostream& out) const; +#ifdef USE_TOPAZ + void addOutNetPort(const std::vector& out, const NetDest& routing_table_entry, int link_latency, int bw_multiplier); +#endif private: // Private copy constructor and assignment operator diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/simple/Switch.hh --- a/src/mem/ruby/network/simple/Switch.hh Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/simple/Switch.hh Mon Mar 19 19:34:15 2012 +0100 @@ -71,9 +71,6 @@ void printConfig(std::ostream& out) const; void print(std::ostream& out) const; -#ifdef USE_TOPAZ - void addOutNetPort(const std::vector& out, const NetDest& routing_table_entry, int link_latency, int bw_multiplier); -#endif private: // Private copy constructor and assignment operator diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/network/simple/Switch.cc --- a/src/mem/ruby/network/simple/Switch.cc Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/network/simple/Switch.cc Mon Mar 12 18:17:19 2012 +0100 @@ -97,14 +97,37 @@ throttle_ptr->addLinks(intermediateBuffers, out); } -void -Switch::clearRoutingTables() +#ifdef USE_TOPAZ +void Switch::addOutNetPort(const vector& out, const NetDest& routing_table_entry, int link_latency, int bw_multiplier) +{ + Throttle* throttle_ptr = NULL; + // + // Create a throttle + throttle_ptr = new Throttle(m_switch_id, m_throttles.size(), link_latency, bw_multiplier); + m_throttles.push_back(throttle_ptr); + // + // Create one buffer per vnet (these are intermediaryQueues) + vector intermediateBuffers; + for (int i=0; isetOrdering(false); + intermediateBuffers.push_back(buffer_ptr); + m_buffers_to_free.push_back(buffer_ptr); + } + // Hook the queues to the PerfectSwitch + m_perfect_switch_ptr->addOutNetPort(intermediateBuffers, routing_table_entry); + // Hook the queues to the Throttle + throttle_ptr->addLinks(intermediateBuffers, out); +} +#endif + +void Switch::clearRoutingTables() { m_perfect_switch_ptr->clearRoutingTables(); } -void -Switch::clearBuffers() +void Switch::clearBuffers() { m_perfect_switch_ptr->clearBuffers(); for (int i = 0; i < m_throttles.size(); i++) { diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/simple/Switch.cc --- a/src/mem/ruby/network/simple/Switch.cc Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/network/simple/Switch.cc Mon Mar 19 19:34:15 2012 +0100 @@ -97,37 +97,14 @@ throttle_ptr->addLinks(intermediateBuffers, out); } -#ifdef USE_TOPAZ -void Switch::addOutNetPort(const vector& out, const NetDest& routing_table_entry, int link_latency, int bw_multiplier) -{ - Throttle* throttle_ptr = NULL; - // - // Create a throttle - throttle_ptr = new Throttle(m_switch_id, m_throttles.size(), link_latency, bw_multiplier); - m_throttles.push_back(throttle_ptr); - // - // Create one buffer per vnet (these are intermediaryQueues) - vector intermediateBuffers; - for (int i=0; isetOrdering(false); - intermediateBuffers.push_back(buffer_ptr); - m_buffers_to_free.push_back(buffer_ptr); - } - // Hook the queues to the PerfectSwitch - m_perfect_switch_ptr->addOutNetPort(intermediateBuffers, routing_table_entry); - // Hook the queues to the Throttle - throttle_ptr->addLinks(intermediateBuffers, out); -} -#endif - -void Switch::clearRoutingTables() +void +Switch::clearRoutingTables() { m_perfect_switch_ptr->clearRoutingTables(); } -void Switch::clearBuffers() +void +Switch::clearBuffers() { m_perfect_switch_ptr->clearBuffers(); for (int i = 0; i < m_throttles.size(); i++) { diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/SConscript --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/SConscript Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,44 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Pablo Abad +# Valentin Puente + +Import('*') + +if env['PROTOCOL'] == 'None': + Return() + +if env['USE_TOPAZ'] == 'None': + Return() + +SimObject('TopazNetwork.py') + +Source('TopazNetwork.cc') +Source('TopazSwitchFlow.cc') +Source('TopazSwitch.cc') diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/SConsopts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/SConsopts Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,44 @@ +# -*- mode:python -*- + +# Copyright (c) 2009 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Valentin Puente +# Pablo Abad +Import('*') + +toOpts = [ + 'True', + 'None' + ] + + +sticky_vars.AddVariables( + EnumVariable('USE_TOPAZ',"Replace Ruby Network with TOPAZ", 'None', + toOpts), + ) + +export_vars += [ 'USE_TOPAZ' ] diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/TopazNetwork.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/TopazNetwork.hh Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MEM_RUBY_NETWORK_SIMPLE_TOPAZNETWORK_HH__ +#define __MEM_RUBY_NETWORK_SIMPLE_TOPAZNETWORK_HH__ + +#include +#include + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/network/Network.hh" +#include "params/TopazNetwork.hh" +#include "sim/sim_object.hh" + +//BEGIN TOPAZ +#include +#include + +//Main simulator include. Download simulator from +//http://www.atc.unican.es/topaz/ and follow the guide +#include + +#include "mem/ruby/slicc_interface/NetworkMessage.hh" +struct MessageTopaz{ + MsgPtr message; + int vnet; + int queue; + int destinations; + int bcast; + int id; + //multicast support + std::vector > Vector_aux; +}; +//END TOPAZ + +class NetDest; +class MessageBuffer; +class Throttle; +class TopazSwitch; +class Topology; + +class TopazNetwork : public Network +{ + public: + typedef TopazNetworkParams Params; + TopazNetwork(const Params *p); + ~TopazNetwork(); + + void init(); + + int getBufferSize() { return m_buffer_size; } + int getEndpointBandwidth() { return m_endpoint_bandwidth; } + bool getAdaptiveRouting() {return m_adaptive_routing; } + + void printStats(std::ostream& out) const; + void clearStats(); + void printConfig(std::ostream& out) const; + +//BEGIN TOPAZ + int getNumberOfNodes()const {return m_nodes;}; + unsigned getProcRouterRatio() const { return m_processorClockRatio;} + unsigned getFlitSize() const { return m_flitSize;} + unsigned getUnifiy() { return m_unify; } + int getNetSize() { return m_switch_ptr_vector.size(); } + int getMessageSizeTopaz(MessageSizeType size_type) const; + int getTriggerSwitch() const { return m_firstTrigger; } + void setTriggerSwitch(int router) { m_firstTrigger=router; } + bool inWarmup() { return m_in_warmup; } + bool useGemsNetwork(int vnet); + void enableTopaz(); + void disableTopaz(); + void increaseNumMsg(int num); + void decreaseNumMsg(int vnet); + void increaseNumOrderedMsg(int num); + void increaseNumTopazOrderedMsg (int num); + void increaseNumTopazMsg(int num); + void decreaseNumTopazMsg (int vnet); + int getTopazMessages() { return m_number_topaz_messages; } + void increaseTotalMsg (int num) { m_totalNetMsg+=num; } + int getTotalMsg () { return m_totalNetMsg; } + int getTotalTopazMsg() { return m_totalTopazMsg; } + const unsigned numberOfMessages() { return m_number_messages; } + const unsigned numberOfOrderedMessages() { return m_number_ordered_messages; } + const unsigned numberOfTopazOrderedMessages() { return m_number_topaz_ordered_messages; } + const unsigned numberOfTopazMessages() { return m_number_topaz_messages; } + void setTopazMapping (SwitchID node0, SwitchID node1); + SwitchID getSwitch(int ext_node) { return m_forward_mapping[ext_node]; } + NetDest getMachines(SwitchID sid) { return m_reverse_mapping[sid]; } + MessageBuffer* getToSimNetQueue(NodeID id, bool ordered, int network_num); + MessageBuffer* getFromSimNetQueue(NodeID id, bool ordered, int network_num); +//TOPAZ + + void reset(); + + // returns the queue requested for the given component + MessageBuffer* getToNetQueue(NodeID id, bool ordered, int network_num, std::string vnet_type); + MessageBuffer* getFromNetQueue(NodeID id, bool ordered, int network_num, std::string vnet_type); + virtual const std::vector* getThrottles(NodeID id) const; + + bool isVNetOrdered(int vnet) { return m_ordered[vnet]; } + bool validVirtualNetwork(int vnet) { return m_in_use[vnet]; } + + int getNumNodes() {return m_nodes; } + + // Methods used by Topology to setup the network + void makeOutLink(SwitchID src, NodeID dest, BasicLink* link, + LinkDirection direction, + const NetDest& routing_table_entry, + bool isReconfiguration); + void makeInLink(NodeID src, SwitchID dest, BasicLink* link, + LinkDirection direction, + const NetDest& routing_table_entry, + bool isReconfiguration); + void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link, + LinkDirection direction, + const NetDest& routing_table_entry, + bool isReconfiguration); + + void print(std::ostream& out) const; + + private: + void checkNetworkAllocation(NodeID id, bool ordered, int network_num); + void addLink(SwitchID src, SwitchID dest, int link_latency); + void makeLink(SwitchID src, SwitchID dest, + const NetDest& routing_table_entry, int link_latency); + SwitchID createSwitch(); + void makeTopology(); + void linkTopology(); + +//BEGIN TOPAZ + unsigned m_processorClockRatio; + unsigned m_flitSize; + unsigned m_unify; + int m_firstTrigger; + bool m_in_warmup; + unsigned m_permanentDisable; + int m_number_messages; + int m_number_ordered_messages; + int m_number_topaz_ordered_messages; + int m_number_topaz_messages; + //maps each MachineID to the internal node it is connected to + SwitchID *m_forward_mapping; + //maps each internal node to the MachineIDs it connects. + std::vector m_reverse_mapping; + int m_totalNetMsg; + int m_totalTopazMsg; + TPZString m_simulName; + TPZString m_topazInitFile; + unsigned m_block_size; + unsigned m_topaz_adaptive_interface_threshold; +//END TOPAZ + + // Private copy constructor and assignment operator + TopazNetwork(const TopazNetwork& obj); + TopazNetwork& operator=(const TopazNetwork& obj); + + // vector of queues from the components + std::vector > m_toNetQueues; + std::vector > m_fromNetQueues; + + std::vector m_in_use; + std::vector m_ordered; + std::vector m_switch_ptr_vector; + std::vector m_buffers_to_free; + std::vector m_endpoint_switches; + + int m_buffer_size; + int m_endpoint_bandwidth; + bool m_adaptive_routing; +}; + +inline std::ostream& +operator<<(std::ostream& out, const TopazNetwork& obj) +{ + obj.print(out); + out << std::flush; + return out; +} + +#endif // __MEM_RUBY_NETWORK_SIMPLE_TOPAZNETWORK_HH__ diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/TopazNetwork.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/TopazNetwork.cc Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,612 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "base/cast.hh" +#include "base/stl_helpers.hh" +#include "debug/RubyNetwork.hh" +#include "mem/protocol/MachineType.hh" +#include "mem/protocol/TopologyType.hh" +#include "mem/ruby/buffers/MessageBuffer.hh" +#include "mem/ruby/common/NetDest.hh" +#include "mem/ruby/network/simple/SimpleLink.hh" +#include "mem/ruby/network/simple/Throttle.hh" +#include "mem/ruby/network/topaz/TopazNetwork.hh" +#include "mem/ruby/network/topaz/TopazSwitch.hh" +#include "mem/ruby/network/topaz/TopazSwitchFlow.hh" +#include "mem/ruby/network/BasicLink.hh" +#include "mem/ruby/network/Topology.hh" +#include "mem/ruby/profiler/Profiler.hh" +#include "mem/ruby/system/System.hh" + +using namespace std; +using m5::stl_helpers::deletePointers; + +//BEGIN TOPAZ +// Helper for Ruby-Topaz Mapping +// Example for 8 L1s, 32 L2s and 8 memories. +// +// 0 -------- 7 8 -------- 39 40 -------- 47 -> node number received +// L1_0 -- L1_7 L2_0 -- L2_31 Mem_0 -- Mem_7 -> MachineID returned + +extern inline +MachineID _nodeNumber_to_MachineID(SwitchID node) { + for (MachineType m = MachineType_FIRST; m < MachineType_NUM; ++m) { + int num_machines = MachineType_base_count(m); + if (node < num_machines) { + MachineID mid = {m, node}; + return mid; + } + else { + node = node - num_machines; + } + } + MachineType merror = MachineType_FIRST; + MachineID error = {merror,node}; + return error; +} +//END TOPAZ + +TopazNetwork::TopazNetwork(const Params *p) + : Network(p) +{ + m_buffer_size = p->buffer_size; + m_endpoint_bandwidth = p->endpoint_bandwidth; + m_adaptive_routing = p->adaptive_routing; + + // Note: the parent Network Object constructor is called before the + // TopazNetwork child constructor. Therefore, the member variables + // used below should already be initialized. + + m_endpoint_switches.resize(m_nodes); + + m_in_use.resize(m_virtual_networks); + m_ordered.resize(m_virtual_networks); + for (int i = 0; i < m_virtual_networks; i++) { + m_in_use[i] = false; + m_ordered[i] = false; + } + //BEGIN TOPAZ + m_number_messages=0; + m_number_ordered_messages=0; + m_number_topaz_ordered_messages=0; + m_number_topaz_messages=0; + m_totalNetMsg=0; + m_totalTopazMsg=0; + m_forward_mapping = new SwitchID[m_nodes]; + m_reverse_mapping.resize(m_nodes); + //ENDTOPAZ + + // Allocate to and from queues + m_toNetQueues.resize(m_nodes); + m_fromNetQueues.resize(m_nodes); + for (int node = 0; node < m_nodes; node++) { + m_toNetQueues[node].resize(m_virtual_networks); + m_fromNetQueues[node].resize(m_virtual_networks); + for (int j = 0; j < m_virtual_networks; j++) { + m_toNetQueues[node][j] = new + MessageBuffer(csprintf("toNet node %d j %d", node, j)); + m_toNetQueues[node][j]->toNet(); + m_fromNetQueues[node][j] = new + MessageBuffer(csprintf("fromNet node %d j %d", node, j)); + m_fromNetQueues[node][j]->fromNet(); + } + } + //BEGIN TOPAZ + m_flitSize=p->topaz_flit_size; + m_processorClockRatio=p->topaz_clock_ratio; + m_simulName = (p->topaz_network).c_str(); + m_topazInitFile = (p->topaz_init_file).c_str(); + m_topaz_adaptive_interface_threshold = p->topaz_adaptive_interface_threshold; + //END TOPAZ +} + +void +TopazNetwork::init() +{ + Network::init(); + + // The topology pointer should have already been initialized in + // the parent class network constructor. + assert(m_topology_ptr != NULL); + int number_of_switches = m_topology_ptr->numSwitches(); + for (int i = 0; i < number_of_switches; i++) { + m_switch_ptr_vector.push_back(new TopazSwitch(i, this)); + } + + // false because this isn't a reconfiguration + m_topology_ptr->createLinks(this, false); + //BEGIN TOPAZ + // + // TOPAZ INITIALIZATION AND INSTALLERS + // + // + m_permanentDisable=false; + //TOPAZ initialization file is here? + //(otherwise segment.fault) + ifstream own(m_topazInitFile); + if( ! own.good() ){ + cerr << " Can't open topaz init file :: " << m_topazInitFile << endl; + cerr<<" That file must have the route to Router, Network & Simulation SGML"<< endl; + cerr<<" you can declare it with --topaz-init-file"<"<createSimulation(initString); + //Simulated networks go from 1,2... (Watch out! is +1 than slicc's vnets) + if (TPZSIMULATOR()->getSimulation(1)->needToUnify()) { + m_unify=1; + break; + } + else { + m_unify=m_virtual_networks; + } + } + if (m_flitSize == 0) { //Not specified by ruby con + m_flitSize=TPZSIMULATOR()->getSimulation(1)->getFlitSize(); + cerr<<"Warning:topaz_flit was not specified in in Ruby.py options."; + cerr<<" It will be get from SGML specification."< FLITSIZE must be specified in simulation sgml file as"; + cerr<<" " << endl; + assert(0); + } + + for (unsigned i = 1; i <= m_unify; i++) + TPZSIMULATOR()->getSimulation(i)->setPacketLength( + getMessageSizeTopaz(MessageSizeType_Data)); + //Clock ratio + if (m_processorClockRatio == 0 ) { + m_processorClockRatio=int(TPZSIMULATOR()-> + getSimulation(1)->getNetworkClockRatioSGML()); + } + //Network cant be faster than memory + assert(m_processorClockRatio>=1); + + this->enableTopaz(); + //Grab rubys seed and re-set it + //(Topaz may internally redefine seed if it is defined in SGM + srandom(g_system_ptr->getRandomSeed()); + //END TOPAZ +} + +int TopazNetwork::getMessageSizeTopaz(MessageSizeType size_type) const { + //Padding last flit + return (int) ceil((double) RubySystem::getNetwork()-> MessageSizeType_to_int( + size_type)/m_flitSize); +} + + +bool TopazNetwork::useGemsNetwork(int vnet) { + bool useGems = false; + // During warmup we use GEMS' network + if (inWarmup()) useGems = true; + // Messages in order must go all through the same network. If this is an + // ordered virtual network, send the message through the network where you + // find any message. + if (isVNetOrdered(vnet)) { + if (numberOfOrderedMessages() > 0) { + assert(numberOfTopazOrderedMessages() == 0); + useGems = true; + } + else if (numberOfTopazOrderedMessages() > 0) { + useGems = false; + } + } + const int messages_in_ruby = numberOfMessages(); + if (m_number_topaz_messages < 0) { + static bool warn_topaz_count_is_wrong = true; + if (warn_topaz_count_is_wrong) { + DPRINTF(RubyNetwork,"Topaz is not counting messages correctly,"); + DPRINTF(RubyNetwork," ignoring g_MAX_MESSAGES_THROUGH_GEMS."); + DPRINTF(RubyNetwork,"Please, fix topaz if you want to use this parameter."); + warn_topaz_count_is_wrong = false; + } + useGems = false; + } + // If the total number of messages is small + //(less than m_topaz_adaptive_interface_threshold), we can use SimpleNetwor + if ((messages_in_ruby + m_number_topaz_messages) < + m_topaz_adaptive_interface_threshold) + useGems = true; + else + useGems = false; + return useGems; +} + +void TopazNetwork::enableTopaz(){ + if( m_permanentDisable ){ + cout<<"TOPAZ PERMANETLY DISABLED"< +++++++ Topaz Enabled! +++++++ "< ******* Topaz DISABLED! ******* "<clear(); + m_fromNetQueues[node][j]->clear(); + } + } + + for(int i = 0; i < m_switch_ptr_vector.size(); i++){ + m_switch_ptr_vector[i]->clearBuffers(); + } +} + +TopazNetwork::~TopazNetwork() +{ + for (int i = 0; i < m_nodes; i++) { + deletePointers(m_toNetQueues[i]); + deletePointers(m_fromNetQueues[i]); + } + deletePointers(m_switch_ptr_vector); + deletePointers(m_buffers_to_free); + // delete m_topology_ptr; +} + +// From a switch to an endpoint node +void +TopazNetwork::makeOutLink(SwitchID src, NodeID dest, BasicLink* link, + LinkDirection direction, + const NetDest& routing_table_entry, + bool isReconfiguration) +{ + assert(dest < m_nodes); + assert(src < m_switch_ptr_vector.size()); + assert(m_switch_ptr_vector[src] != NULL); + + if (isReconfiguration) { + m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry); + return; + } + + SimpleExtLink *simple_link = safe_cast(link); + + m_switch_ptr_vector[src]->addOutPort(m_fromNetQueues[dest], + routing_table_entry, + simple_link->m_latency, + simple_link->m_bw_multiplier); + + m_endpoint_switches[dest] = m_switch_ptr_vector[src]; +} + +// From an endpoint node to a switch +void +TopazNetwork::makeInLink(NodeID src, SwitchID dest, BasicLink* link, + LinkDirection direction, + const NetDest& routing_table_entry, + bool isReconfiguration) +{ + assert(src < m_nodes); + if (isReconfiguration) { + // do nothing + return; + } + + m_switch_ptr_vector[dest]->addInPort(m_toNetQueues[src]); +} + +// From a switch to a switch +void +TopazNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link, + LinkDirection direction, + const NetDest& routing_table_entry, + bool isReconfiguration) +{ + if (isReconfiguration) { + m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry); + return; + } + + // Create a set of new MessageBuffers + std::vector queues; + for (int i = 0; i < m_virtual_networks; i++) { + // allocate a buffer + MessageBuffer* buffer_ptr = new MessageBuffer; + buffer_ptr->setOrdering(true); + if (m_buffer_size > 0) { + buffer_ptr->resize(m_buffer_size); + } + queues.push_back(buffer_ptr); + // remember to deallocate it + m_buffers_to_free.push_back(buffer_ptr); + } + // Connect it to the two switches + SimpleIntLink *simple_link = safe_cast(link); + + m_switch_ptr_vector[dest]->addInPort(queues); + m_switch_ptr_vector[src]->addOutPort(queues, routing_table_entry, + simple_link->m_latency, + simple_link->m_bw_multiplier); +} + +void +TopazNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num) +{ + assert(id < m_nodes); + assert(network_num < m_virtual_networks); + + if (ordered) { + m_ordered[network_num] = true; + } + m_in_use[network_num] = true; +} + +MessageBuffer* +TopazNetwork::getToNetQueue(NodeID id, bool ordered, int network_num, + std::string vnet_type) +{ + checkNetworkAllocation(id, ordered, network_num); + return m_toNetQueues[id][network_num]; +} + +MessageBuffer* +TopazNetwork::getFromNetQueue(NodeID id, bool ordered, int network_num, + std::string vnet_type) +{ + checkNetworkAllocation(id, ordered, network_num); + return m_fromNetQueues[id][network_num]; +} + +const std::vector* +TopazNetwork::getThrottles(NodeID id) const +{ + assert(id >= 0); + assert(id < m_nodes); + assert(m_endpoint_switches[id] != NULL); + return m_endpoint_switches[id]->getThrottles(); +} + +void +TopazNetwork::printStats(ostream& out) const +{ + out<<""<getSimulation(currentVnet)->writeSimulationStatus(out); + TPZSIMULATOR()->getSimulation(currentVnet)-> + getNetwork()->writeComponentStatus(out); + } + out << endl; + TopazNetwork* net=static_cast(g_system_ptr->getNetwork()); + long int Topaz_messages=net->getTotalTopazMsg(); + int percent = 100*Topaz_messages/(Topaz_messages+net->getTotalMsg()+1); + out << "TOPAZ NETWORK USAGE" << endl; + out << "Usage TOPAZ network: " << percent << "%" << endl; + out << "Total TOPAZ messages: " << Topaz_messages << endl; + out << "Total Number of messages: " << Topaz_messages+net->getTotalMsg() << endl; + out << endl; + out <<""< total_msg_counts; + total_msg_counts.resize(MessageSizeType_NUM); + for (MessageSizeType type = MessageSizeType_FIRST; + type < MessageSizeType_NUM; + ++type) { + total_msg_counts[type] = 0; + } + + for (int i = 0; i < m_switch_ptr_vector.size(); i++) { + const std::vector* throttles = + m_switch_ptr_vector[i]->getThrottles(); + + for (int p = 0; p < throttles->size(); p++) { + + const std::vector >& message_counts = + ((*throttles)[p])->getCounters(); + + for (MessageSizeType type = MessageSizeType_FIRST; + type < MessageSizeType_NUM; + ++type) { + + const std::vector &mct = message_counts[type]; + int sum = accumulate(mct.begin(), mct.end(), 0); + total_msg_counts[type] += uint64(sum); + } + } + } + uint64 total_msgs = 0; + uint64 total_bytes = 0; + for (MessageSizeType type = MessageSizeType_FIRST; + type < MessageSizeType_NUM; + ++type) { + + if (total_msg_counts[type] > 0) { + out << "total_msg_count_" << type << ": " << total_msg_counts[type] + << " " << total_msg_counts[type] * + uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type)) + << endl; + + total_msgs += total_msg_counts[type]; + + total_bytes += total_msg_counts[type] * + uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type)); + + } + } + + out << "total_msgs: " << total_msgs + << " total_bytes: " << total_bytes << endl; + + out << endl; + for (int i = 0; i < m_switch_ptr_vector.size(); i++) { + m_switch_ptr_vector[i]->printStats(out); + } + m_topology_ptr->printStats(out); +} + +void +TopazNetwork::clearStats() +{ + for (int i = 0; i < m_switch_ptr_vector.size(); i++) { + m_switch_ptr_vector[i]->clearStats(); + } + m_topology_ptr->clearStats(); +} + +void +TopazNetwork::printConfig(ostream& out) const +{ + out << endl; + out << "Network Configuration" << endl; + out << "---------------------" << endl; + out << "network: SIMPLE_NETWORK" << endl; + out << "topology: " << m_topology_ptr->getName() << endl; + out << endl; + + for (int i = 0; i < m_virtual_networks; i++) { + out << "virtual_net_" << i << ": "; + if (m_in_use[i]) { + out << "active, "; + if (m_ordered[i]) { + out << "ordered" << endl; + } else { + out << "unordered" << endl; + } + } else { + out << "inactive" << endl; + } + } + out << endl; + + for(int i = 0; i < m_switch_ptr_vector.size(); i++) { + m_switch_ptr_vector[i]->printConfig(out); + } + + m_topology_ptr->printConfig(out); +} + +void +TopazNetwork::print(ostream& out) const +{ + out << "[TopazNetwork]"; +} + +//BEGIN TOPAZ +void TopazNetwork::increaseNumMsg(int num){ + m_number_messages+=num; +} + +void TopazNetwork::increaseNumTopazMsg(int num){ + m_number_topaz_messages+=num; + m_totalTopazMsg+=num; +} + +void TopazNetwork::decreaseNumMsg(int vnet){ + m_number_messages--; + assert(m_number_messages >= 0); + if (m_ordered[vnet]){ + if ( numberOfOrderedMessages() > 0 ){ + assert(!(numberOfTopazOrderedMessages()>0)); + m_number_ordered_messages--; + } + } +} + +void TopazNetwork::decreaseNumTopazMsg (int vnet){ + m_number_topaz_messages--; + assert(m_number_messages >= 0); + if ( m_ordered[vnet] ){ + assert(!(numberOfOrderedMessages()>0)); + m_number_topaz_ordered_messages--; + } +} + +void TopazNetwork::increaseNumOrderedMsg(int num){ + m_number_ordered_messages+=num; +} + +void TopazNetwork::increaseNumTopazOrderedMsg(int num){ + m_number_topaz_ordered_messages+=num; +} + +void TopazNetwork::setTopazMapping (SwitchID ext_node, SwitchID int_node) { + int_node -= 2*m_nodes; + MachineID machine = _nodeNumber_to_MachineID(ext_node); + m_forward_mapping[ext_node] = int_node; + m_reverse_mapping[int_node].add(machine); +} +//END TOPAZ + +TopazNetwork * +TopazNetworkParams::create() +{ + return new TopazNetwork(this); +} diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/TopazNetwork.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/TopazNetwork.py Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,18 @@ +# +# Authors:Pablo Abad +# Valentin Puente + +from m5.params import * +from Network import RubyNetwork + +class TopazNetwork(RubyNetwork): + type = 'TopazNetwork' + buffer_size = Param.Int(0, + "default buffer size; 0 indicates infinite buffering"); + endpoint_bandwidth = Param.Int(1000, "bandwidth adjustment factor"); + adaptive_routing = Param.Bool(False, "enable adaptive routing"); + topaz_init_file = Param.String("./TPZSimul__ini", "File that declares .sgm, .sgm and .sgm"); + topaz_network =Param.String (None, "TOPAZ: simulation listed in .sgm to be used by TOPAZ"); + topaz_flit_size = Param.Int(0, "Number of bytes per physical router-to-router wire"); + topaz_clock_ratio = Param.Int(1,"memory-network clock multiplier"); + topaz_adaptive_interface_threshold = Param.Int(0,"Number of messages that has to be transmitted before to activate TOPAZ"); diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/TopazSwitch.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/TopazSwitch.hh Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The actual modelled switch. It use the perfect switch and a + * Throttle object to control and bandwidth and timing *only for the + * output port*. So here we have un-realistic modelling, since the + * order of PerfectSwitch and Throttle objects get woke up affect the + * message timing. A more accurate model would be having two set of + * system states, one for this cycle, one for next cycle. And on the + * cycle boundary swap the two set of states. + */ + +#ifndef __MEM_RUBY_NETWORK_TOPAZSWITCH_HH__ +#define __MEM_RUBY_NETWORK_TOPAZSWITCH_HH__ + +#include +#include + +#include "mem/ruby/common/Global.hh" + +class MessageBuffer; +class TopazSwitchFlow; +class NetDest; +class TopazNetwork; +class Throttle; + +class TopazSwitch +{ + public: + TopazSwitch(SwitchID sid, TopazNetwork* network_ptr); + ~TopazSwitch(); + + void addInPort(const std::vector& in); + void addOutPort(const std::vector& out, + const NetDest& routing_table_entry, int link_latency, + int bw_multiplier); + const Throttle* getThrottle(LinkID link_number) const; + const std::vector* getThrottles() const; + void clearRoutingTables(); + void clearBuffers(); + void reconfigureOutPort(const NetDest& routing_table_entry); + + void printStats(std::ostream& out) const; + void clearStats(); + void printConfig(std::ostream& out) const; + + void print(std::ostream& out) const; +//BEGIN TOPAZ + void addOutNetPort(const std::vector& out, + const NetDest& routing_table_entry, + int link_latency, + int bw_multiplier); +//END TOPAZ + + private: + // Private copy constructor and assignment operator + TopazSwitch(const TopazSwitch& obj); + TopazSwitch& operator=(const TopazSwitch& obj); + + TopazSwitchFlow* m_perfect_switch_ptr; + TopazNetwork* m_network_ptr; + std::vector m_throttles; + std::vector m_buffers_to_free; + SwitchID m_switch_id; +}; + +inline std::ostream& +operator<<(std::ostream& out, const TopazSwitch& obj) +{ + obj.print(out); + out << std::flush; + return out; +} + +#endif // __MEM_RUBY_NETWORK_SIMPLE_SWITCH_HH__ diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/TopazSwitch.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/TopazSwitch.cc Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,257 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "base/cast.hh" +#include "base/stl_helpers.hh" +#include "mem/protocol/MessageSizeType.hh" +#include "mem/ruby/buffers/MessageBuffer.hh" +#include "mem/ruby/network/simple/Throttle.hh" +#include "mem/ruby/network/topaz/TopazNetwork.hh" +#include "mem/ruby/network/topaz/TopazSwitch.hh" +#include "mem/ruby/network/topaz/TopazSwitchFlow.hh" + +using namespace std; +using m5::stl_helpers::deletePointers; +using m5::stl_helpers::operator<<; + +TopazSwitch::TopazSwitch(SwitchID sid, TopazNetwork* network_ptr) +{ + m_perfect_switch_ptr = new TopazSwitchFlow(sid, network_ptr); + m_switch_id = sid; +} + +TopazSwitch::~TopazSwitch() +{ + delete m_perfect_switch_ptr; + + // Delete throttles (one per output port) + deletePointers(m_throttles); + + // Delete MessageBuffers + deletePointers(m_buffers_to_free); +} + +void +TopazSwitch::addInPort(const vector& in) +{ + m_perfect_switch_ptr->addInPort(in); +} + +void +TopazSwitch::addOutPort(const vector& out, + const NetDest& routing_table_entry, int link_latency, int bw_multiplier) +{ + Throttle* throttle_ptr = NULL; + TopazNetwork* net_ptr = + safe_cast(RubySystem::getNetwork()); + + // Create a throttle + throttle_ptr = new Throttle(m_switch_id, m_throttles.size(), link_latency, + bw_multiplier, net_ptr->getEndpointBandwidth()); + m_throttles.push_back(throttle_ptr); + + // Create one buffer per vnet (these are intermediaryQueues) + vector intermediateBuffers; + for (int i = 0; i < out.size(); i++) { + MessageBuffer* buffer_ptr = new MessageBuffer; + // Make these queues ordered + buffer_ptr->setOrdering(true); + if (net_ptr->getBufferSize() > 0) { + buffer_ptr->resize(net_ptr->getBufferSize()); + } + intermediateBuffers.push_back(buffer_ptr); + m_buffers_to_free.push_back(buffer_ptr); + } + + // Hook the queues to the PerfectSwitch + m_perfect_switch_ptr->addOutPort(intermediateBuffers, routing_table_entry); + + // Hook the queues to the Throttle + throttle_ptr->addLinks(intermediateBuffers, out); +} + +//BEGIN TOPAZ +void TopazSwitch::addOutNetPort(const vector& out, + const NetDest& routing_table_entry, + int link_latency, + int bw_multiplier) +{ + Throttle* throttle_ptr = NULL; + // + // Create a throttle + throttle_ptr = new Throttle(m_switch_id, + m_throttles.size(), + link_latency, + bw_multiplier); + m_throttles.push_back(throttle_ptr); + // + // Create one buffer per vnet (these are intermediaryQueues) + vector intermediateBuffers; + for (int i=0; isetOrdering(false); + intermediateBuffers.push_back(buffer_ptr); + m_buffers_to_free.push_back(buffer_ptr); + } + // Hook the queues to the PerfectSwitch + m_perfect_switch_ptr->addOutNetPort(intermediateBuffers, routing_table_entry); + // Hook the queues to the Throttle + throttle_ptr->addLinks(intermediateBuffers, out); +} +//END TOPAZ + +void +TopazSwitch::clearRoutingTables() +{ + m_perfect_switch_ptr->clearRoutingTables(); +} + +void +TopazSwitch::clearBuffers() +{ + m_perfect_switch_ptr->clearBuffers(); + for (int i = 0; i < m_throttles.size(); i++) { + if (m_throttles[i] != NULL) { + m_throttles[i]->clear(); + } + } +} + +void +TopazSwitch::reconfigureOutPort(const NetDest& routing_table_entry) +{ + m_perfect_switch_ptr->reconfigureOutPort(routing_table_entry); +} + +const Throttle* +TopazSwitch::getThrottle(LinkID link_number) const +{ + assert(m_throttles[link_number] != NULL); + return m_throttles[link_number]; +} + +const vector* +TopazSwitch::getThrottles() const +{ + return &m_throttles; +} + +void +TopazSwitch::printStats(std::ostream& out) const +{ + ccprintf(out, "switch_%d_inlinks: %d\n", m_switch_id, + m_perfect_switch_ptr->getInLinks()); + ccprintf(out, "switch_%d_outlinks: %d\n", m_switch_id, + m_perfect_switch_ptr->getOutLinks()); + + // Average link utilizations + double average_utilization = 0.0; + int throttle_count = 0; + + for (int i = 0; i < m_throttles.size(); i++) { + Throttle* throttle_ptr = m_throttles[i]; + if (throttle_ptr) { + average_utilization += throttle_ptr->getUtilization(); + throttle_count++; + } + } + average_utilization = + throttle_count == 0 ? 0 : average_utilization / throttle_count; + + // Individual link utilizations + out << "links_utilized_percent_switch_" << m_switch_id << ": " + << average_utilization << endl; + + for (int link = 0; link < m_throttles.size(); link++) { + Throttle* throttle_ptr = m_throttles[link]; + if (throttle_ptr != NULL) { + out << " links_utilized_percent_switch_" << m_switch_id + << "_link_" << link << ": " + << throttle_ptr->getUtilization() << " bw: " + << throttle_ptr->getLinkBandwidth() + << " base_latency: " << throttle_ptr->getLatency() << endl; + } + } + out << endl; + + // Traffic breakdown + for (int link = 0; link < m_throttles.size(); link++) { + Throttle* throttle_ptr = m_throttles[link]; + if (!throttle_ptr) + continue; + + const vector >& message_counts = + throttle_ptr->getCounters(); + for (int int_type = 0; int_type < MessageSizeType_NUM; int_type++) { + MessageSizeType type = MessageSizeType(int_type); + const vector &mct = message_counts[type]; + int sum = accumulate(mct.begin(), mct.end(), 0); + if (sum == 0) + continue; + + out << " outgoing_messages_switch_" << m_switch_id + << "_link_" << link << "_" << type << ": " << sum << " " + << sum * RubySystem::getNetwork()->MessageSizeType_to_int(type) + << " "; + out << mct; + out << " base_latency: " + << throttle_ptr->getLatency() << endl; + } + } + out << endl; +} + +void +TopazSwitch::clearStats() +{ + m_perfect_switch_ptr->clearStats(); + for (int i = 0; i < m_throttles.size(); i++) { + if (m_throttles[i] != NULL) + m_throttles[i]->clearStats(); + } +} + +void +TopazSwitch::printConfig(std::ostream& out) const +{ + m_perfect_switch_ptr->printConfig(out); + for (int i = 0; i < m_throttles.size(); i++) { + if (m_throttles[i] != NULL) + m_throttles[i]->printConfig(out); + } +} + +void +TopazSwitch::print(std::ostream& out) const +{ + out << "[Switch]"; +} + diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/TopazSwitchFlow.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/TopazSwitchFlow.hh Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Perfect switch, of course it is perfect and no latency or what so + * ever. Every cycle it is woke up and perform all the necessary + * routings that must be done. Note, this switch also has number of + * input ports/output ports and has a routing table as well. + */ + +#ifndef __MEM_RUBY_NETWORK_SIMPLE_TOPAZSWITCHFLOW_HH__ +#define __MEM_RUBY_NETWORK_SIMPLE_TOPAZSWITCHFLOW_HH__ + +#include +#include +#include + +#include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/common/Global.hh" + +class MessageBuffer; +class NetDest; +class TopazNetwork; + +struct LinkOrder +{ + int m_link; + int m_value; +}; + +class TopazSwitchFlow : public Consumer +{ + public: + TopazSwitchFlow(SwitchID sid, TopazNetwork* network_ptr); + ~TopazSwitchFlow(); + + std::string name() + { return csprintf("TopazSwitch-%i", m_switch_id); } + + void addInPort(const std::vector& in); + void addOutPort(const std::vector& out, + const NetDest& routing_table_entry); + void clearRoutingTables(); + void clearBuffers(); + void reconfigureOutPort(const NetDest& routing_table_entry); + int getInLinks() const { return m_in.size(); } + int getOutLinks() const { return m_out.size(); } + + void wakeup(); + void wakeupVnet(int vnet); + void storeEventInfo(int info); + //BEGIN TOPAZ + int getUnicastDestination(NetDest destinations); + unsigned long long getMulticastDestination(NetDest& destinations); + void filterZeroDistanceMessages(MsgPtr& msg_ptr, int vnet, NetDest& destinations); + NetDest getConsumerDestinations(int switch_id, NetDest& mensaje); + void wakeUpTopaz(); + void addOutNetPort(const std::vector& out, + const NetDest& routing_table_entry); + //END TOPAZ + void printStats(std::ostream& out) const; + void clearStats(); + void printConfig(std::ostream& out) const; + + void print(std::ostream& out) const; + + private: + // Private copy constructor and assignment operator + TopazSwitchFlow(const TopazSwitchFlow& obj); + TopazSwitchFlow& operator=(const TopazSwitchFlow& obj); + + SwitchID m_switch_id; + + // vector of queues from the components + std::vector > m_in; + std::vector > m_out; + std::vector m_routing_table; + std::vector m_link_order; + int m_virtual_networks; + int m_round_robin_start; + int m_wakeups_wo_switch; + TopazNetwork* m_network_ptr; + //BEGIN TOPAZ + long unsigned m_ruby_start; + long unsigned m_minimunTimeAgain; + //END TOPAZ + std::vector m_pending_message_count; +}; + +inline std::ostream& +operator<<(std::ostream& out, const TopazSwitchFlow& obj) +{ + obj.print(out); + out << std::flush; + return out; +} + +#endif // __MEM_RUBY_NETWORK_SIMPLE_TOPAZSWITCH_HH__ diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/network/topaz/TopazSwitchFlow.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mem/ruby/network/topaz/TopazSwitchFlow.cc Mon Mar 19 19:34:15 2012 +0100 @@ -0,0 +1,616 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "base/cast.hh" +#include "debug/RubyNetwork.hh" +#include "mem/ruby/buffers/MessageBuffer.hh" +#include "mem/ruby/network/topaz/TopazNetwork.hh" +#include "mem/ruby/network/topaz/TopazSwitchFlow.hh" +#include "mem/ruby/profiler/Profiler.hh" +#include "mem/ruby/slicc_interface/NetworkMessage.hh" +#include "mem/ruby/system/System.hh" +//BEGIN TOPAZ +#include +#include + +#include +//END TOPAZ + +using namespace std; + +const int PRIORITY_SWITCH_LIMIT = 128; + +// helpr for STL vector sorting +bool +predicateToSort (const LinkOrder& l1, const LinkOrder& l2) +{ + return (l1.m_value < l2.m_value); +} + +TopazSwitchFlow::TopazSwitchFlow(SwitchID sid, TopazNetwork* network_ptr) +{ + m_virtual_networks = network_ptr->getNumberOfVirtualNetworks(); + m_switch_id = sid; + m_round_robin_start = 0; + m_network_ptr = network_ptr; + m_wakeups_wo_switch = 0; + //BEGIN TOPAZ + m_ruby_start=0; + //END TOPAZ + for(int i = 0;i < m_virtual_networks;++i) + { + m_pending_message_count.push_back(0); + } +} + +void +TopazSwitchFlow::addInPort(const vector& in) +{ + assert(in.size() == m_virtual_networks); + NodeID port = m_in.size(); + m_in.push_back(in); + + for (int j = 0; j < m_virtual_networks; j++) { + m_in[port][j]->setConsumer(this); + string desc = csprintf("[Queue from port %s %s %s to TopazSwitchFlow]", + to_string(m_switch_id), to_string(port), to_string(j)); + m_in[port][j]->setDescription(desc); + m_in[port][j]->setIncomingLink(port); + m_in[port][j]->setVnet(j); + } +} + +void +TopazSwitchFlow::addOutPort(const vector& out, + const NetDest& routing_table_entry) +{ + assert(out.size() == m_virtual_networks); + + // Setup link order + LinkOrder l; + l.m_value = 0; + l.m_link = m_out.size(); + m_link_order.push_back(l); + + // Add to routing table + m_out.push_back(out); + m_routing_table.push_back(routing_table_entry); +} + +//BEGIN TOPAZ +void +TopazSwitchFlow::addOutNetPort(const vector& out, + const NetDest& routing_table_entry){ + assert(out.size() == m_virtual_networks); + // Setup link order + LinkOrder l; + l.m_value = 0; + l.m_link = m_out.size(); + m_link_order.push_back(l); + // Add to routing table + m_out.push_back(out); + m_routing_table.push_back(routing_table_entry); + /*VPVFIX + for (int j = 0; j < m_virtual_networks; j++) { + m_out[l.m_link][j]->setOutSwitchPort(); + m_out[l.m_link][j]->setNetwork(m_network_ptr); + m_out[l.m_link][j]->setVNet(j); + }*/ +} +//END TOPAZ + +void +TopazSwitchFlow::clearRoutingTables() +{ + m_routing_table.clear(); +} + +void +TopazSwitchFlow::clearBuffers() +{ + for (int i = 0; i < m_in.size(); i++){ + for(int vnet = 0; vnet < m_virtual_networks; vnet++) { + m_in[i][vnet]->clear(); + } + } + + for (int i = 0; i < m_out.size(); i++){ + for(int vnet = 0; vnet < m_virtual_networks; vnet++) { + m_out[i][vnet]->clear(); + } + } +} + +void +TopazSwitchFlow::reconfigureOutPort(const NetDest& routing_table_entry) +{ + m_routing_table.push_back(routing_table_entry); +} + +TopazSwitchFlow::~TopazSwitchFlow() +{ +} + +//BEGIN TOPAZ +//****************************************************************************** +// Function in charge of calculating the destination of an Unicast message +//****************************************************************************** +int TopazSwitchFlow::getUnicastDestination(NetDest destinations) { + int this_id; + int m_queue=0; + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { + int limit = MachineType_base_count(mType); + for (int component = 0; component < limit; component++) { + MachineID mach = {mType, component}; + if (destinations.elementAt(mach)==1) { + this_id=m_network_ptr->getSwitch(m_queue+component); + return this_id; + } + } + m_queue += MachineType_base_count(mType); + } + assert(m_queue!=0); + return 1; +} + +//****************************************************************************** +// Function in charge of calculating the mask of a Multicast message +//****************************************************************************** +unsigned long long +TopazSwitchFlow::getMulticastDestination(NetDest& destinations) { + unsigned long long routers = 0; + int node_number = 0; + for (MachineType m = MachineType_FIRST; m < MachineType_NUM; ++m) { + for (int c = 0; cgetSwitch(node_number)); + routers = routers | mask; + } + node_number++; + } + } + return routers; +} + +//****************************************************************************** +// Function in charge of filtering messages with src=dst +// this kind of messages are not routed through TOPAZ network +//****************************************************************************** +void +TopazSwitchFlow::filterZeroDistanceMessages( MsgPtr& msg_ptr, int vnet, + NetDest& destinations) { + int source=m_switch_id; + int destination; + bool isOrdered= m_network_ptr->isVNetOrdered(vnet); + int m_queue=0; + for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType){ + int limit = MachineType_base_count(mType); + for (int component = 0; component < limit; component++) { + MachineID mach = {mType, component}; + if(destinations.elementAt(mach)==1) { + destination=m_network_ptr->getSwitch(m_queue+component); + if (source == destination){ + MessageBuffer* outputQueue=m_network_ptr-> + getFromSimNetQueue(component+m_queue, isOrdered, vnet); + MsgPtr unaMas=msg_ptr->clone(); + outputQueue->enqueue(unaMas); + destinations.remove(mach); // Here destinations are modified + } + } + } + m_queue += MachineType_base_count(mType); + } +} + +//****************************************************************************** +// This function returns a NetDest vector result of the following operation +// msg_destinations & Router_mask +// where Router_mask indicates which components are reachable through a certain +// switch +//****************************************************************************** +NetDest +TopazSwitchFlow::getConsumerDestinations(int switch_id, NetDest& dest) { + NetDest consumers = m_network_ptr->getMachines(switch_id); + return consumers.AND(dest); +} + +//****************************************************************************** +// Function in charge of deciding which network must be used, GEMS or TOPAZ +//****************************************************************************** +void TopazSwitchFlow::wakeup() { + m_wakeups_wo_switch++; + int highest_prio_vnet = m_virtual_networks-1; + int source=m_switch_id; + for (int vnet = highest_prio_vnet; vnet >= 0; vnet--) { + //If we are in warmup or the adaptive interface is used and then + //network is lightly loadad we may ruby network + if (m_network_ptr->useGemsNetwork(vnet)) { + wakeupVnet(vnet); + } + //Otherwise, use topaz + else{ + if(m_pending_message_count[vnet]>0) + for(int incoming=0;incomingisReady()){ + MsgPtr msg_ptr = m_in[incoming][vnet]->peekMsgPtr(); + NetworkMessage *net_msg_ptr = + dynamic_cast(msg_ptr.get()); + NetDest msg_destinations = + net_msg_ptr->getInternalDestination(); + int topaz_size=m_network_ptr-> + getMessageSizeTopaz(net_msg_ptr->getMessageSize()); + assert(topaz_size); + filterZeroDistanceMessages( msg_ptr, vnet, msg_destinations); + if ( msg_destinations.count() !=0) { + TPZMessage msg; + TPZPosition origen; + TPZPosition destino; + MessageTopaz* copia=new MessageTopaz; + copia->message=msg_ptr->clone(); + copia->vnet=vnet; + copia->destinations=msg_destinations.count(); + // TOPAZ message generation + msg.setExternalInfo(static_cast(copia)); + msg.setGenerationTime(TPZSIMULATOR()-> + getSimulation(1)->getCurrentTime()); + origen=TPZSIMULATOR()->getSimulation(1)-> + getNetwork()->CreatePosition(source); + msg.setSource(origen); + msg.setVnet(vnet+1); + msg.setMessageSize(1); + msg.setPacketSize(topaz_size); + if (m_network_ptr->isVNetOrdered(vnet)){ + msg.setOrdered(); + m_network_ptr-> + increaseNumTopazOrderedMsg(msg_destinations.count()); + } + if (msg_destinations.count()==1) { + msg.clearMulticast(); + int componente = getUnicastDestination(msg_destinations); + destino=TPZSIMULATOR()->getSimulation(1)-> + getNetwork()->CreatePosition(componente); + msg.setDestiny(destino); + } + else { + msg.setMulticast(); + //This destination is necessary because topaz + //checks the existence + //of src and destination routers + //this destination is only used for this purpose, + //no messages will arrive to it. + msg.setDestiny(origen); + unsigned long long msgMask= + getMulticastDestination(msg_destinations); + msg.setMsgmask(msgMask); + } + // Send the message to the network + DPRINTF(RubyNetwork, "Send at switch: [%d] vnet: [%d] time: [%d].\n", + m_switch_id, vnet, g_eventQueue_ptr->getTime()); + TPZSIMULATOR()->getSimulation(1)->getNetwork()->sendMessage(msg); + m_network_ptr->increaseNumTopazMsg(msg_destinations.count()); + } + m_in[incoming][vnet]->pop(); + m_pending_message_count[vnet]--; + } + } + } + } + //ijust a prewarmed simulation + if (m_network_ptr->inWarmup()) return; + if (m_network_ptr->getTriggerSwitch() == ~0) { + m_network_ptr->setTriggerSwitch(m_switch_id); + } + //Only first switch run and implement consumption. + if ( m_switch_id != m_network_ptr->getTriggerSwitch() ) return; + wakeUpTopaz(); +} + +//****************************************************************************** +// This function is in charge of running TOPAZ and collecting the messages +// to send then back to GEMS queues +//****************************************************************************** +void TopazSwitchFlow::wakeUpTopaz() { + long unsigned current_time = + static_cast(g_eventQueue_ptr->getTime()) - m_ruby_start; + int procesorNetRatio=m_network_ptr->getProcRouterRatio(); + int messagesOnNets=0; + long diff_time = current_time - TPZSIMULATOR()->getSimulation(1)->getCurrentTime()*procesorNetRatio; + if (diff_time > 0) { + TPZSIMULATOR()->getSimulation(1)->setCurrentTime((current_time/procesorNetRatio)-1); + TPZSIMULATOR()->getSimulation(1)->run(1); + for (int consumer = 0; + consumergetSimulation(1)->getNetwork()->Number_of_nodes(); + consumer++) { + TPZPosition position_f= + TPZSIMULATOR()->getSimulation(1)->getNetwork()->CreatePosition(consumer); + void* ptr =(TPZSIMULATOR()->getSimulation(1)->getExternalInfoAt(position_f)); + if (ptr!=NULL) { + MessageTopaz* topaz_message = static_cast(ptr); + assert (topaz_message->destinations>0); + MsgPtr localCopy = (topaz_message->message); + NetworkMessage* net_msg_ptr = + dynamic_cast(localCopy.get()); + int vvnet=topaz_message->vnet; + int isOrdered= m_network_ptr->isVNetOrdered(vvnet); + NetDest ConsDestinations = + getConsumerDestinations(consumer, + net_msg_ptr->getInternalDestination()); + DPRINTF(RubyNetwork, "Arrival at switch: [%d] vnet: [%d] time: [%d].\n", + consumer, vvnet, g_eventQueue_ptr->getTime()); + int m_queue=0; + for (MachineType mType = MachineType_FIRST; + mType < MachineType_NUM; ++mType) { + int limit = MachineType_base_count(mType); + for (int component = 0; component < limit; component++) { + MachineID mach = {mType, component}; + if(ConsDestinations.elementAt(mach)==1) { + MsgPtr unaMas = localCopy->clone(); + MessageBuffer* outputQueue= + m_network_ptr->getFromSimNetQueue(component+m_queue, + isOrdered, + vvnet); + outputQueue->enqueue(unaMas); + topaz_message->destinations=topaz_message->destinations-1; + m_network_ptr->decreaseNumTopazMsg(vvnet); + } + } + m_queue += MachineType_base_count(mType); + } + int pendientes=topaz_message->destinations; + if (pendientes==0) delete topaz_message; + } + } + messagesOnNets=m_network_ptr->getTopazMessages(); + } + if ( messagesOnNets!=0) + g_eventQueue_ptr->scheduleEvent(this, 1); +} +//END TOPAZ + +void TopazSwitchFlow::wakeupVnet(int vnet) { + NetworkMessage* net_msg_ptr; + MsgPtr msg_ptr; + // This is for round-robin scheduling + int incoming = m_round_robin_start; + m_round_robin_start++; + if (m_round_robin_start >= m_in.size()) { + m_round_robin_start = 0; + } + + if(m_pending_message_count[vnet] > 0) { + // for all input ports, use round robin scheduling + for (int counter = 0; counter < m_in.size(); counter++) { + // Round robin scheduling + incoming++; + if (incoming >= m_in.size()) { + incoming = 0; + } + + // temporary vectors to store the routing results + vector output_links; + vector output_link_destinations; + + // Is there a message waiting? + while (m_in[incoming][vnet]->isReady()) { + DPRINTF(RubyNetwork, "incoming: %d\n", incoming); + + // Peek at message + msg_ptr = m_in[incoming][vnet]->peekMsgPtr(); + net_msg_ptr = safe_cast(msg_ptr.get()); + DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); + //BEGIN TOPAZ + //New adaptive interface. We have to catch al messages + //moving thorugh GEMS and TOPAZ + // Keeping track of messeges through GEMS + + if( m_in[incoming][vnet]->isToNet()) { + if (m_network_ptr->isVNetOrdered(vnet)) { + m_network_ptr->increaseNumOrderedMsg(net_msg_ptr->getInternalDestination().count()); + } + m_network_ptr->increaseTotalMsg(net_msg_ptr->getInternalDestination().count()); + m_network_ptr->increaseNumMsg(net_msg_ptr->getInternalDestination().count()); + } + //END TOPAZ + + output_links.clear(); + output_link_destinations.clear(); + NetDest msg_dsts = + net_msg_ptr->getInternalDestination(); + + // Unfortunately, the token-protocol sends some + // zero-destination messages, so this assert isn't valid + // assert(msg_dsts.count() > 0); + + assert(m_link_order.size() == m_routing_table.size()); + assert(m_link_order.size() == m_out.size()); + if (m_network_ptr->getAdaptiveRouting()) { + if (m_network_ptr->isVNetOrdered(vnet)) { + + // Don't adaptively route + for (int out = 0; out < m_out.size(); out++) { + m_link_order[out].m_link = out; + m_link_order[out].m_value = 0; + } + } else { + + // Find how clogged each link is + for (int out = 0; out < m_out.size(); out++) { + int out_queue_length = 0; + for (int v = 0; v < m_virtual_networks; v++) { + out_queue_length += m_out[out][v]->getSize(); + } + int value = + (out_queue_length << 8) | (random() & 0xff); + m_link_order[out].m_link = out; + m_link_order[out].m_value = value; + } + + // Look at the most empty link first + sort(m_link_order.begin(), m_link_order.end(), predicateToSort); + } + } + for (int i = 0; i < m_routing_table.size(); i++) { + // pick the next link to look at + int link = m_link_order[i].m_link; + NetDest dst = m_routing_table[link]; + DPRINTF(RubyNetwork, "dst: %s\n", dst); + + if (!msg_dsts.intersectionIsNotEmpty(dst)) + continue; + + // Remember what link we're using + output_links.push_back(link); + + // Need to remember which destinations need this + // message in another vector. This Set is the + // intersection of the routing_table entry and the + // current destination set. The intersection must + // not be empty, since we are inside "if" + output_link_destinations.push_back(msg_dsts.AND(dst)); + + // Next, we update the msg_destination not to + // include those nodes that were already handled + // by this link + msg_dsts.removeNetDest(dst); + } + + assert(msg_dsts.count() == 0); + + // Check for resources - for all outgoing queues + bool enough = true; + for (int i = 0; i < output_links.size(); i++) { + int outgoing = output_links[i]; + if (!m_out[outgoing][vnet]->areNSlotsAvailable(1)) + enough = false; + DPRINTF(RubyNetwork, "Checking if node is blocked ..." + "outgoing: %d, vnet: %d, enough: %d\n", + outgoing, vnet, enough); + } + + // There were not enough resources + if (!enough) { + g_eventQueue_ptr->scheduleEvent(this, 1); + DPRINTF(RubyNetwork, "Can't deliver message since a node " + "is blocked\n"); + DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); + break; // go to next incoming port + } + + MsgPtr unmodified_msg_ptr; + + if (output_links.size() > 1) { + // If we are sending this message down more than + // one link (size>1), we need to make a copy of + // the message so each branch can have a different + // internal destination we need to create an + // unmodified MsgPtr because the MessageBuffer + // enqueue func will modify the message + + // This magic line creates a private copy of the + // message + unmodified_msg_ptr = msg_ptr->clone(); + } + + // Enqueue it - for all outgoing queues + for (int i=0; i 0) { + // create a private copy of the unmodified + // message + msg_ptr = unmodified_msg_ptr->clone(); + } + + // Change the internal destination set of the + // message so it knows which destinations this + // link is responsible for. + net_msg_ptr = safe_cast(msg_ptr.get()); + net_msg_ptr->getInternalDestination() = + output_link_destinations[i]; + + // Enqeue msg + DPRINTF(RubyNetwork, "Enqueuing net msg from " + "inport[%d][%d] to outport [%d][%d].\n", + incoming, vnet, outgoing, vnet); + + int spooling_delay=1; + + //BEGIN TOPAZ + if (m_out[outgoing][vnet]->isFromNet()) { + net_msg_ptr = safe_cast(msg_ptr.get()); + spooling_delay += m_network_ptr->getMessageSizeTopaz(net_msg_ptr->getMessageSize()); + m_network_ptr->decreaseNumMsg(vnet); + } + //END TOPAZ + m_out[outgoing][vnet]->enqueue(msg_ptr,spooling_delay); + } + + // Dequeue msg + m_in[incoming][vnet]->pop(); + m_pending_message_count[vnet]--; + } + } + } +} + + +void +TopazSwitchFlow::storeEventInfo(int info) +{ + m_pending_message_count[info]++; +} + + +void +TopazSwitchFlow::printStats(std::ostream& out) const +{ + out << "TopazSwitchFlow printStats" << endl; +} + +void +TopazSwitchFlow::clearStats() +{ +} + +void +TopazSwitchFlow::printConfig(std::ostream& out) const +{ +} + +void +TopazSwitchFlow::print(std::ostream& out) const +{ + out << "[TopazSwitchFlow " << m_switch_id << "]"; +} + diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/profiler/Profiler.cc --- a/src/mem/ruby/profiler/Profiler.cc Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/profiler/Profiler.cc Mon Mar 12 18:17:19 2012 +0100 @@ -57,7 +57,7 @@ #include "mem/ruby/profiler/AddressProfiler.hh" #include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/system/System.hh" - +#include "mem/ruby/network/simple/SimpleNetwork.hh" using namespace std; using m5::stl_helpers::operator<<; @@ -414,7 +414,19 @@ out << " virtual_network_" << i << "_delay_cycles: " << m_delayedCyclesVCHistograms[i] << endl; } - +#ifdef USE_TOPAZ + out << endl; + SimpleNetwork* net=static_cast(g_system_ptr->getNetwork()); + long int Topaz_messages=net->getTotalTopazMsg(); + int percent = 100*Topaz_messages/(Topaz_messages+net->getTotalMsg()+1); + out << "TOPAZ NETWORK USAGE" << endl; + out << "(RUBY point of view. May differ from TOPAZ if multiple destinations are connected on a switch)" << endl; + out << "----------------------------------------------------------------------------------------------" << endl; + out << "Usage TOPAZ network: " << percent << "%" << endl; + out << "Total TOPAZ messages: " << Topaz_messages << endl; + out << "Total Number of messages: " << Topaz_messages+net->getTotalMsg() << endl; + out << endl; +#endif printResourceUsage(out); } } diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/profiler/Profiler.cc --- a/src/mem/ruby/profiler/Profiler.cc Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/profiler/Profiler.cc Mon Mar 19 19:34:15 2012 +0100 @@ -414,19 +414,6 @@ out << " virtual_network_" << i << "_delay_cycles: " << m_delayedCyclesVCHistograms[i] << endl; } -#ifdef USE_TOPAZ - out << endl; - SimpleNetwork* net=static_cast(g_system_ptr->getNetwork()); - long int Topaz_messages=net->getTotalTopazMsg(); - int percent = 100*Topaz_messages/(Topaz_messages+net->getTotalMsg()+1); - out << "TOPAZ NETWORK USAGE" << endl; - out << "(RUBY point of view. May differ from TOPAZ if multiple destinations are connected on a switch)" << endl; - out << "----------------------------------------------------------------------------------------------" << endl; - out << "Usage TOPAZ network: " << percent << "%" << endl; - out << "Total TOPAZ messages: " << Topaz_messages << endl; - out << "Total Number of messages: " << Topaz_messages+net->getTotalMsg() << endl; - out << endl; -#endif printResourceUsage(out); } } diff -r be4990a2c764 -r 0315c934bbfc src/mem/ruby/system/MachineID.hh --- a/src/mem/ruby/system/MachineID.hh Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/system/MachineID.hh Mon Mar 12 18:17:19 2012 +0100 @@ -41,6 +41,31 @@ int num; // range: 0 ... number of this machine's components in system - 1 }; +#ifdef USE_TOPAZ +// Example for 8 L1s, 32 L2s and 8 memories. +// +// 0 -------- 7 8 -------- 39 40 -------- 47 -> node number received +// L1_0 -- L1_7 L2_0 -- L2_31 Mem_0 -- Mem_7 -> MachineID returned + +extern inline +MachineID nodeNumber_to_MachineID(SwitchID node) { + for (MachineType m = MachineType_FIRST; m < MachineType_NUM; ++m) { + int num_machines = MachineType_base_count(m); + if (node < num_machines) { + MachineID mid = {m, node}; + return mid; + } + else { + node = node - num_machines; + } + } + MachineType merror = MachineType_FIRST; + MachineID error = {merror,node}; + return error; + //cerr<< "Wrong number of node." << endl; +} +#endif + inline std::string MachineIDToString(MachineID machine) { changeset: 8813:81a9c05b8495 tag: tip user: Valentin Puente date: Mon Mar 19 19:34:15 2012 +0100 summary: Topaz interface as a peer network diff -r 0315c934bbfc -r 81a9c05b8495 src/mem/ruby/system/MachineID.hh --- a/src/mem/ruby/system/MachineID.hh Mon Mar 12 18:17:19 2012 +0100 +++ b/src/mem/ruby/system/MachineID.hh Mon Mar 19 19:34:15 2012 +0100 @@ -41,31 +41,6 @@ int num; // range: 0 ... number of this machine's components in system - 1 }; -#ifdef USE_TOPAZ -// Example for 8 L1s, 32 L2s and 8 memories. -// -// 0 -------- 7 8 -------- 39 40 -------- 47 -> node number received -// L1_0 -- L1_7 L2_0 -- L2_31 Mem_0 -- Mem_7 -> MachineID returned - -extern inline -MachineID nodeNumber_to_MachineID(SwitchID node) { - for (MachineType m = MachineType_FIRST; m < MachineType_NUM; ++m) { - int num_machines = MachineType_base_count(m); - if (node < num_machines) { - MachineID mid = {m, node}; - return mid; - } - else { - node = node - num_machines; - } - } - MachineType merror = MachineType_FIRST; - MachineID error = {merror,node}; - return error; - //cerr<< "Wrong number of node." << endl; -} -#endif - inline std::string MachineIDToString(MachineID machine) {