diff -r 92590adf7454 -r 943e7cadb412 SConstruct --- a/SConstruct Wed Feb 22 11:56:03 2012 +0100 +++ b/SConstruct Mon Mar 12 13:55:53 2012 +0100 @@ -888,10 +888,10 @@ # gzstream build is shared across all configs in the build root. 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')) + variant_dir = joinpath(build_root, 'topaz')) ################################################### # diff -r be4990a2c764 -r 92590adf7454 SConstruct --- a/SConstruct Thu Feb 02 04:51:13 2012 -0500 +++ b/SConstruct Wed Feb 22 11:56:03 2012 +0100 @@ -888,6 +888,10 @@ # gzstream build is shared across all configs in the build root. 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')) ################################################### # diff -r 92590adf7454 -r 943e7cadb412 TPZSimul.ini --- a/TPZSimul.ini Wed Feb 22 11:56:03 2012 +0100 +++ b/TPZSimul.ini Mon Mar 12 13:55:53 2012 +0100 @@ -1,4 +1,3 @@ - diff -r be4990a2c764 -r 92590adf7454 TPZSimul.ini --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TPZSimul.ini Wed Feb 22 11:56:03 2012 +0100 @@ -0,0 +1,4 @@ + + + + diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 be4990a2c764 -r 92590adf7454 build_opts/ALPHA_Network_Topaz_test --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_opts/ALPHA_Network_Topaz_test Wed Feb 22 11:56:03 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 92590adf7454 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 Wed Feb 22 11:56:03 2012 +0100 @@ -1,3 +1,4 @@ SS_COMPATIBLE_FP = 1 CPU_MODELS = 'AtomicSimpleCPU,TimingSimpleCPU,O3CPU,InOrderCPU' PROTOCOL = 'Network_test' + diff -r be4990a2c764 -r 92590adf7454 build_opts/ALPHA_directory_topaz --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_opts/ALPHA_directory_topaz Wed Feb 22 11:56:03 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 92590adf7454 build_opts/ALPHA_token_topaz --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build_opts/ALPHA_token_topaz Wed Feb 22 11:56:03 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 92590adf7454 configs/ruby/Ruby.py --- a/configs/ruby/Ruby.py Thu Feb 02 04:51:13 2012 -0500 +++ b/configs/ruby/Ruby.py Wed Feb 22 11:56:03 2012 +0100 @@ -71,7 +71,24 @@ help="Used for seeding the random number generator") 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,14 +159,33 @@ 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. # Determine the total memory size of the ruby system and verify it is equal diff -r be4990a2c764 -r 92590adf7454 src/mem/ruby/SConscript --- a/src/mem/ruby/SConscript Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/SConscript Wed Feb 22 11:56:03 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 be4990a2c764 -r 92590adf7454 src/mem/ruby/SConsopts --- a/src/mem/ruby/SConsopts Thu Feb 02 04:51:13 2012 -0500 +++ b/src/mem/ruby/SConsopts Wed Feb 22 11:56:03 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 92590adf7454 -r 943e7cadb412 src/mem/ruby/buffers/MessageBuffer.hh --- a/src/mem/ruby/buffers/MessageBuffer.hh Wed Feb 22 11:56:03 2012 +0100 +++ b/src/mem/ruby/buffers/MessageBuffer.hh Mon Mar 12 13:55:53 2012 +0100 @@ -144,7 +144,7 @@ #ifdef USE_TOPAZ void setNetwork(SimpleNetwork* network) { m_net_ptr = network; } void setOutPort() { m_out_port = true; } - void setInPort() { m_in_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; } diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 92590adf7454 -r 943e7cadb412 src/mem/ruby/network/Network.hh --- a/src/mem/ruby/network/Network.hh Wed Feb 22 11:56:03 2012 +0100 +++ b/src/mem/ruby/network/Network.hh Mon Mar 12 13:55:53 2012 +0100 @@ -97,7 +97,7 @@ #ifdef USE_TOPAZ virtual void enableTopaz() =0; - virtual void disableTopaz()=0; + virtual void disableTopaz()=0; virtual void setTopazMapping (SwitchID node0, SwitchID node1)=0; #endif diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 92590adf7454 -r 943e7cadb412 src/mem/ruby/network/Topology.cc --- a/src/mem/ruby/network/Topology.cc Wed Feb 22 11:56:03 2012 +0100 +++ b/src/mem/ruby/network/Topology.cc Mon Mar 12 13:55:53 2012 +0100 @@ -248,7 +248,7 @@ 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) { diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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" @@ -249,6 +253,10 @@ 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 be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 92590adf7454 -r 943e7cadb412 src/mem/ruby/network/simple/PerfectSwitch.cc --- a/src/mem/ruby/network/simple/PerfectSwitch.cc Wed Feb 22 11:56:03 2012 +0100 +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc Mon Mar 12 13:55:53 2012 +0100 @@ -106,7 +106,7 @@ } #ifdef USE_TOPAZ -void +void PerfectSwitch::addOutNetPort(const vector& out, const NetDest& routing_table_entry){ assert(out.size() == m_virtual_networks); // Setup link order @@ -117,7 +117,6 @@ // 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); @@ -161,8 +160,7 @@ //****************************************************************************** // Function in charge of calculating the destination of an Unicast message //****************************************************************************** -int -PerfectSwitch::getUnicastDestination(NetDest destinations) { +int PerfectSwitch::getUnicastDestination(NetDest destinations) { int this_id; int m_queue=0; for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) { @@ -183,8 +181,7 @@ //****************************************************************************** // Function in charge of calculating the mask of a Multicast message //****************************************************************************** -unsigned long long -PerfectSwitch::getMulticastDestination(NetDest& destinations) { +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) { @@ -205,8 +202,7 @@ // 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) { +void PerfectSwitch :: filterZeroDistanceMessages( MsgPtr& msg_ptr, int vnet, NetDest& destinations) { int source=m_switch_id; int destination; bool isOrdered= m_network_ptr->isVNetOrdered(vnet); @@ -235,8 +231,7 @@ // where Router_mask indicates which components are reachable through a certain // switch //****************************************************************************** -NetDest -PerfectSwitch::getConsumerDestinations(int switch_id, NetDest& dest) { +NetDest PerfectSwitch::getConsumerDestinations(int switch_id, NetDest& dest) { NetDest consumers = m_network_ptr->getMachines(switch_id); return consumers.AND(dest); } @@ -244,8 +239,7 @@ //****************************************************************************** // Function in charge of deciding which network must be used, GEMS or TOPAZ //****************************************************************************** -void -PerfectSwitch::wakeup() { +void PerfectSwitch::wakeup() { m_wakeups_wo_switch++; int highest_prio_vnet = m_virtual_networks-1; int source=m_switch_id; @@ -263,14 +257,12 @@ 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; @@ -279,7 +271,6 @@ 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()); @@ -311,8 +302,8 @@ TPZSIMULATOR()->getSimulation(1)->getNetwork()->sendMessage(msg); m_network_ptr->increaseNumTopazMsg(msg_destinations.count()); } - m_in[incoming][vnet]->pop(); - m_pending_message_count[vnet]--; + m_in[incoming][vnet]->pop(); + m_pending_message_count[vnet]--; } } } @@ -330,12 +321,11 @@ // This function is in charge of running TOPAZ and collecting the messages // to send then back to GEMS queues //****************************************************************************** -void -PerfectSwitch::wakeUpTopaz() { +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; + 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); @@ -379,15 +369,12 @@ #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; - // invert priorities to avoid starvation seen in the component network if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) { m_wakeups_wo_switch = 0; @@ -395,7 +382,6 @@ 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); @@ -406,14 +392,12 @@ 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++) { @@ -422,21 +406,16 @@ 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()) { @@ -450,14 +429,11 @@ 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 @@ -482,7 +458,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; @@ -570,10 +545,11 @@ //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()); + +#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); @@ -595,7 +571,7 @@ } -void PerfectSwitch::printStats(ostream& out) const +void PerfectSwitch::printStats(std::ostream& out) const { out << "PerfectSwitch printStats" << endl; } @@ -604,11 +580,11 @@ { } -void PerfectSwitch::printConfig(ostream& out) const +void PerfectSwitch::printConfig(std::ostream& out) const { } -void PerfectSwitch::print(ostream& out) const +void PerfectSwitch::print(std::ostream& out) const { out << "[PerfectSwitch " << m_switch_id << "]"; } diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 2012 +0100 @@ -27,6 +27,7 @@ */ #include +#include #include "base/cast.hh" #include "debug/RubyNetwork.hh" @@ -37,6 +38,12 @@ #include "mem/ruby/slicc_interface/NetworkMessage.hh" #include "mem/ruby/system/System.hh" +#ifdef USE_TOPAZ +#include //Main simulator include +#include +#include +#endif + using namespace std; const int PRIORITY_SWITCH_LIMIT = 128; @@ -55,7 +62,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 +105,26 @@ 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,32 +157,257 @@ { } -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) { + if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) { m_wakeups_wo_switch = 0; highest_prio_vnet = 0; 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()) { @@ -175,6 +429,7 @@ // Is there a message waiting? while (m_in[incoming][vnet]->isReady()) { + DPRINTF(RubyNetwork, "incoming: %d\n", incoming); // Peek at message @@ -182,6 +437,15 @@ 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 = @@ -304,7 +568,15 @@ "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 +586,7 @@ } } } -} + void PerfectSwitch::storeEventInfo(int info) @@ -322,25 +594,22 @@ m_pending_message_count[info]++; } -void -PerfectSwitch::printStats(std::ostream& out) const -{ - out << "PerfectSwitch printStats" << endl; + +void PerfectSwitch::printStats(ostream& out) const +{ + out << "PerfectSwitch printStats" << endl; } -void -PerfectSwitch::clearStats() +void PerfectSwitch::clearStats() { } -void -PerfectSwitch::printConfig(std::ostream& out) const -{ +void PerfectSwitch::printConfig(ostream& out) const +{ } -void -PerfectSwitch::print(std::ostream& out) const +void PerfectSwitch::print(ostream& out) const { - out << "[PerfectSwitch " << m_switch_id << "]"; + out << "[PerfectSwitch " << m_switch_id << "]"; } diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 2012 +0100 @@ -37,6 +37,24 @@ #include "params/SimpleNetwork.hh" #include "sim/sim_object.hh" +#ifdef USE_TOPAZ +#include //Main simulator include +#include +#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 +78,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 +150,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 92590adf7454 -r 943e7cadb412 src/mem/ruby/network/simple/SimpleNetwork.cc --- a/src/mem/ruby/network/simple/SimpleNetwork.cc Wed Feb 22 11:56:03 2012 +0100 +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc Mon Mar 12 13:55:53 2012 +0100 @@ -94,17 +94,15 @@ m_fromNetQueues[node][j]->setOutPort(); m_fromNetQueues[node][j]->setNetwork(this); m_fromNetQueues[node][j]->setVNet(j); -#endif +#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){ @@ -128,7 +126,7 @@ } // false because this isn't a reconfiguration - m_topology_ptr->createLinks(this, false); + m_topology_ptr->createLinks(this, false); // // TOPAZ INITIALIZATION AND INSTALLERS // @@ -147,9 +145,7 @@ // m_permanentDisable=true; // return; //} - m_permanentDisable=false; - //TOPAZ initialization file is here? //(otherwise segment.fault) ifstream own(m_topazInitFile); @@ -162,9 +158,7 @@ } own.close(); TPZString initString ; - initString = TPZString("TPZSimul -q -s ") + m_simulName + TPZString (" -t EMPTY -d 100000 -v 4 -F ")+m_topazInitFile; - m_firstTrigger=~0; //Run each virtual network in a separate phisical netwokr (aka DASH) or just rely on virtual netowkrs //the network should be conveived to manage separetelly all traffic if we want to avoid end-to-end deadlock @@ -173,13 +167,13 @@ TPZSIMULATOR()->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; + m_unify=1; + break; } else { - m_unify=m_virtual_networks; + m_unify=m_virtual_networks; } - } + } if (m_flitSize == 0) { //Not specified by ruby con m_flitSize=TPZSIMULATOR()->getSimulation(1)->getFlitSize(); @@ -193,10 +187,9 @@ assert(0); } - for (unsigned i = 1; i <= m_unify; i++) - TPZSIMULATOR()->getSimulation(i)->setPacketLength(getMessageSizeTopaz(MessageSizeType_Data)); //VCT applied. Largest packet - - //Clock ratio + 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()); } @@ -210,16 +203,14 @@ } #ifdef USE_TOPAZ -int -SimpleNetwork::getMessageSizeTopaz(MessageSizeType size_type) const { +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) { +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 @@ -229,11 +220,10 @@ 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) { @@ -252,8 +242,7 @@ return false; } -void -SimpleNetwork::enableTopaz(){ +void SimpleNetwork::enableTopaz(){ if( m_permanentDisable ){ cout<<"TOPAZ PERMANETLY DISABLED"< ******* Topaz DISABLED! ******* "<"<getSimulation(currentVnet)->writeSimulationStatus(out); cerr<<"Messages in :"<"<< @@ -440,12 +424,11 @@ TPZSIMULATOR()->getSimulation(currentVnet)->getNetwork()->writeComponentStatus(out); } out<<""< #include "base/cast.hh" +#include "debug/RubyNetwork.hh" #include "base/stl_helpers.hh" #include "mem/protocol/TopologyType.hh" #include "mem/ruby/buffers/MessageBuffer.hh" @@ -65,20 +66,52 @@ 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); + m_topology_ptr->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 +554,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 be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 92590adf7454 -r 943e7cadb412 src/mem/ruby/network/simple/Switch.cc --- a/src/mem/ruby/network/simple/Switch.cc Wed Feb 22 11:56:03 2012 +0100 +++ b/src/mem/ruby/network/simple/Switch.cc Mon Mar 12 13:55:53 2012 +0100 @@ -98,22 +98,20 @@ } #ifdef USE_TOPAZ -void -Switch::addOutNetPort(const vector& out, const NetDest& routing_table_entry, int link_latency, int bw_multiplier) +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); } @@ -126,14 +124,12 @@ } #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++) { changeset: 8812:92590adf7454 user: Valentin Puente date: Wed Feb 22 11:56:03 2012 +0100 summary: MEM: GEM5-ruby / TOPAZ integration. diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 2012 +0100 @@ -97,6 +97,35 @@ 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() { diff -r be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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 be4990a2c764 -r 92590adf7454 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 Wed Feb 22 11:56:03 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: 8811:be4990a2c764 user: Andreas Hansson date: Thu Feb 02 04:51:13 2012 -0500 summary: Regression: Update the regress script after SE/FS merge diff -r 00f0d0230596 -r be4990a2c764 util/regress --- a/util/regress Wed Feb 01 09:48:28 2012 -0800 +++ b/util/regress Thu Feb 02 04:51:13 2012 -0500 @@ -40,17 +40,19 @@ add_option('-v', '--verbose', action='store_true', default=False, help='echo commands before executing') add_option('--builds', - default='ALPHA_SE,ALPHA_SE_MOESI_hammer,' \ - 'ALPHA_SE_MESI_CMP_directory,' \ - 'ALPHA_SE_MOESI_CMP_directory,' \ - 'ALPHA_SE_MOESI_CMP_token,' \ - 'ALPHA_FS,' \ - 'MIPS_SE,' \ - 'POWER_SE,' \ - 'SPARC_SE,SPARC_FS,' \ - 'X86_SE,X86_FS,' \ - 'ARM_SE,ARM_FS', + default='ALPHA,ALPHA_MOESI_hammer,' \ + 'ALPHA_MESI_CMP_directory,' \ + 'ALPHA_MOESI_CMP_directory,' \ + 'ALPHA_MOESI_CMP_token,' \ + 'MIPS,' \ + 'POWER,' \ + 'SPARC,' \ + 'X86,' \ + 'ARM', help="comma-separated build targets to test (default: '%default')") +add_option('--modes', + default='se,fs', + help="comma-separated modes to test (default: '%default')") add_option('--test-variants', default='opt', help="comma-separated build variants to test (default: '%default')"\ ", set to '' for none") @@ -82,6 +84,7 @@ # split list options on ',' to get Python lists builds = split_if_nonempty(options.builds) +modes = split_if_nonempty(options.modes) test_variants = split_if_nonempty(options.test_variants) compile_variants = split_if_nonempty(options.compile_variants) @@ -112,25 +115,21 @@ for variant in compile_variants for build in builds] -# By default run the 'quick' tests +# By default run the 'quick' tests, all expands to quick and long if not tests: tests = ['quick'] +elif 'all' in tests: + tests = ['quick,long'] -# set up test targets for scons -if 'all' in tests: - targets += ['%s/%s/tests/%s' % (options.build_dir, build, variant) - for build in builds - for variant in test_variants] -else: - # Ugly! Since we don't have any quick SPARC_FS tests remove the - # SPARC_FS target If we ever get a quick SPARC_FS test, this code - # should be removed - if 'quick' in tests and 'SPARC_FS' in builds: - builds.remove('SPARC_FS') - targets += ['%s/%s/tests/%s/%s' % (options.build_dir, build, variant, test) - for build in builds - for variant in test_variants - for test in tests] +# set up test targets for scons, since we don't have any quick SPARC +# full-system tests exclude it +targets += ['%s/%s/tests/%s/%s/%s' % (options.build_dir, build, variant, test, + mode) + for build in builds + for variant in test_variants + for test in tests + for mode in modes + if not (build == 'SPARC' and test == 'quick' and mode == 'fs')] def cpu_count(): if 'bsd' in sys.platform or sys.platform == 'darwin':