1d0
<
30,39c29,31
< /*
< * PerfectSwitch.cc
< *
< * Description: See PerfectSwitch.hh
< *
< * $Id$
< *
< */
<
<
---
> #include "mem/gems_common/util.hh"
> #include "mem/protocol/Protocol.hh"
> #include "mem/ruby/buffers/MessageBuffer.hh"
41c33
< #include "mem/ruby/slicc_interface/NetworkMessage.hh"
---
> #include "mem/ruby/network/simple/SimpleNetwork.hh"
42a35
> #include "mem/ruby/slicc_interface/NetworkMessage.hh"
44,47d36
< #include "mem/ruby/network/simple/SimpleNetwork.hh"
< #include "mem/gems_common/util.hh"
< #include "mem/ruby/buffers/MessageBuffer.hh"
< #include "mem/protocol/Protocol.hh"
52,53c41,44
< bool operator<(const LinkOrder& l1, const LinkOrder& l2) {
< return (l1.m_value < l2.m_value);
---
> bool
> operator<(const LinkOrder& l1, const LinkOrder& l2)
> {
> return (l1.m_value < l2.m_value);
58,62c49,53
< 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;
---
> 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;
65c56,57
< void PerfectSwitch::addInPort(const Vector<MessageBuffer*>& in)
---
> void
> PerfectSwitch::addInPort(const Vector<MessageBuffer*>& in)
67,74c59,68
< assert(in.size() == m_virtual_networks);
< NodeID port = m_in.size();
< m_in.insertAtBottom(in);
< for (int j = 0; j < m_virtual_networks; j++) {
< m_in[port][j]->setConsumer(this);
< string desc = "[Queue from port " + NodeIDToString(m_switch_id) + " " + NodeIDToString(port) + " " + NodeIDToString(j) + " to PerfectSwitch]";
< m_in[port][j]->setDescription(desc);
< }
---
> assert(in.size() == m_virtual_networks);
> NodeID port = m_in.size();
> m_in.insertAtBottom(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 PerfectSwitch]",
> NodeIDToString(m_switch_id), NodeIDToString(port),
> NodeIDToString(j));
> m_in[port][j]->setDescription(desc);
> }
77c71,73
< void PerfectSwitch::addOutPort(const Vector<MessageBuffer*>& out, const NetDest& routing_table_entry)
---
> void
> PerfectSwitch::addOutPort(const Vector<MessageBuffer*>& out,
> const NetDest& routing_table_entry)
79c75
< assert(out.size() == m_virtual_networks);
---
> assert(out.size() == m_virtual_networks);
81,85c77,81
< // Setup link order
< LinkOrder l;
< l.m_value = 0;
< l.m_link = m_out.size();
< m_link_order.insertAtBottom(l);
---
> // Setup link order
> LinkOrder l;
> l.m_value = 0;
> l.m_link = m_out.size();
> m_link_order.insertAtBottom(l);
87,90c83,85
< // Add to routing table
< m_out.insertAtBottom(out);
< m_routing_table.insertAtBottom(routing_table_entry);
<
---
> // Add to routing table
> m_out.insertAtBottom(out);
> m_routing_table.insertAtBottom(routing_table_entry);
93c88,89
< void PerfectSwitch::clearRoutingTables()
---
> void
> PerfectSwitch::clearRoutingTables()
95c91
< m_routing_table.clear();
---
> m_routing_table.clear();
98c94,95
< void PerfectSwitch::clearBuffers()
---
> void
> PerfectSwitch::clearBuffers()
100,102c97,100
< 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_in.size(); i++){
> for(int vnet = 0; vnet < m_virtual_networks; vnet++) {
> m_in[i][vnet]->clear();
> }
104d101
< }
106,108c103,106
< for(int i=0; i<m_out.size(); i++){
< for(int vnet=0; vnet < m_virtual_networks; vnet++) {
< m_out[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();
> }
110d107
< }
113c110,111
< void PerfectSwitch::reconfigureOutPort(const NetDest& routing_table_entry)
---
> void
> PerfectSwitch::reconfigureOutPort(const NetDest& routing_table_entry)
115c113
< m_routing_table.insertAtBottom(routing_table_entry);
---
> m_routing_table.insertAtBottom(routing_table_entry);
122c120,121
< void PerfectSwitch::wakeup()
---
> void
> PerfectSwitch::wakeup()
123a123
> DEBUG_EXPR(NETWORK_COMP, MedPrio, m_switch_id);
125c125
< DEBUG_EXPR(NETWORK_COMP, MedPrio, m_switch_id);
---
> MsgPtr msg_ptr;
127c127,132
< MsgPtr msg_ptr;
---
> // 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;
129,134c134,140
< // 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;
> highest_prio_vnet = 0;
> lowest_prio_vnet = m_virtual_networks-1;
> decrementer = -1;
> }
136,145d141
< // invert priorities to avoid starvation seen in the component network
< 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) {
<
147,151c143,145
< int incoming = m_round_robin_start; // This is for round-robin scheduling
< m_round_robin_start++;
< if (m_round_robin_start >= m_in.size()) {
< m_round_robin_start = 0;
< }
---
> for (int vnet = highest_prio_vnet;
> (vnet * decrementer) >= (decrementer * lowest_prio_vnet);
> vnet -= decrementer) {
153,154c147,152
< // for all input ports, use round robin scheduling
< for (int counter = 0; counter < m_in.size(); counter++) {
---
> // 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;
> }
156,160c154,160
< // Round robin scheduling
< incoming++;
< if (incoming >= m_in.size()) {
< incoming = 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;
> }
162,164c162,164
< // temporary vectors to store the routing results
< Vector<LinkID> output_links;
< Vector<NetDest> output_link_destinations;
---
> // temporary vectors to store the routing results
> Vector<LinkID> output_links;
> Vector<NetDest> output_link_destinations;
166,167c166,168
< // Is there a message waiting?
< while (m_in[incoming][vnet]->isReady()) {
---
> // Is there a message waiting?
> while (m_in[incoming][vnet]->isReady()) {
> DEBUG_EXPR(NETWORK_COMP, MedPrio, incoming);
169c170,173
< DEBUG_EXPR(NETWORK_COMP, MedPrio, incoming);
---
> // Peek at message
> msg_ptr = m_in[incoming][vnet]->peekMsgPtr();
> net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
> DEBUG_EXPR(NETWORK_COMP, MedPrio, *net_msg_ptr);
171,174c175,178
< // Peek at message
< msg_ptr = m_in[incoming][vnet]->peekMsgPtr();
< net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
< DEBUG_EXPR(NETWORK_COMP, MedPrio, *net_msg_ptr);
---
> output_links.clear();
> output_link_destinations.clear();
> NetDest msg_dsts =
> net_msg_ptr->getInternalDestination();
176,178c180,182
< output_links.clear();
< output_link_destinations.clear();
< NetDest msg_destinations = net_msg_ptr->getInternalDestination();
---
> // Unfortunately, the token-protocol sends some
> // zero-destination messages, so this assert isn't valid
> // assert(msg_dsts.count() > 0);
180,182c184,185
< // Unfortunately, the token-protocol sends some
< // zero-destination messages, so this assert isn't valid
< // assert(msg_destinations.count() > 0);
---
> assert(m_link_order.size() == m_routing_table.size());
> assert(m_link_order.size() == m_out.size());
184,185c187,205
< 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;
> }
187,208c207,210
< if (m_network_ptr->getAdaptiveRouting()) {
< if (m_network_ptr->isVNetOrdered(vnet)) {
< // Don't adaptively route
< for (int outlink=0; outlink<m_out.size(); outlink++) {
< m_link_order[outlink].m_link = outlink;
< m_link_order[outlink].m_value = 0;
< }
< } else {
< // Find how clogged each link is
< for (int outlink=0; outlink<m_out.size(); outlink++) {
< int out_queue_length = 0;
< for (int v=0; v<m_virtual_networks; v++) {
< out_queue_length += m_out[outlink][v]->getSize();
< }
< m_link_order[outlink].m_link = outlink;
< m_link_order[outlink].m_value = 0;
< m_link_order[outlink].m_value |= (out_queue_length << 8);
< m_link_order[outlink].m_value |= (random() & 0xff);
< }
< m_link_order.sortVector(); // Look at the most empty link first
< }
< }
---
> // Look at the most empty link first
> m_link_order.sortVector();
> }
> }
210,212c212,216
< 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;
---
> 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];
> DEBUG_EXPR(NETWORK_COMP, MedPrio, dst);
214c218,219
< DEBUG_EXPR(NETWORK_COMP, MedPrio, m_routing_table[link]);
---
> if (!msg_dsts.intersectionIsNotEmpty(dst))
> continue;
216c221,222
< if (msg_destinations.intersectionIsNotEmpty(m_routing_table[link])) {
---
> // Remember what link we're using
> output_links.insertAtBottom(link);
218,219c224,229
< // Remember what link we're using
< output_links.insertAtBottom(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.insertAtBottom(msg_dsts.AND(dst));
221,225c231,235
< // 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.insertAtBottom(msg_destinations.AND(m_routing_table[link]));
---
> // Next, we update the msg_destination not to
> // include those nodes that were already handled
> // by this link
> msg_dsts.removeNetDest(dst);
> }
227,231c237,238
< // Next, we update the msg_destination not to include
< // those nodes that were already handled by this link
< msg_destinations.removeNetDest(m_routing_table[link]);
< }
< }
---
> assert(msg_dsts.count() == 0);
> //assert(output_links.size() > 0);
233,234c240,251
< assert(msg_destinations.count() == 0);
< //assert(output_links.size() > 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;
> DEBUG_MSG(NETWORK_COMP, HighPrio,
> "checking if node is blocked");
> DEBUG_EXPR(NETWORK_COMP, HighPrio, outgoing);
> DEBUG_EXPR(NETWORK_COMP, HighPrio, vnet);
> DEBUG_EXPR(NETWORK_COMP, HighPrio, enough);
> }
236,245c253,260
< // Check for resources - for all outgoing queues
< bool enough = true;
< for (int i=0; i<output_links.size(); i++) {
< int outgoing = output_links[i];
< enough = enough && m_out[outgoing][vnet]->areNSlotsAvailable(1);
< DEBUG_MSG(NETWORK_COMP, HighPrio, "checking if node is blocked");
< DEBUG_EXPR(NETWORK_COMP, HighPrio, outgoing);
< DEBUG_EXPR(NETWORK_COMP, HighPrio, vnet);
< DEBUG_EXPR(NETWORK_COMP, HighPrio, enough);
< }
---
> // There were not enough resources
> if (!enough) {
> g_eventQueue_ptr->scheduleEvent(this, 1);
> DEBUG_MSG(NETWORK_COMP, HighPrio,
> "Can't deliver message since a node is blocked");
> DEBUG_EXPR(NETWORK_COMP, HighPrio, *net_msg_ptr);
> break; // go to next incoming port
> }
247,253c262
< // There were not enough resources
< if(!enough) {
< g_eventQueue_ptr->scheduleEvent(this, 1);
< DEBUG_MSG(NETWORK_COMP, HighPrio, "Can't deliver message to anyone since a node is blocked");
< DEBUG_EXPR(NETWORK_COMP, HighPrio, *net_msg_ptr);
< break; // go to next incoming port
< }
---
> MsgPtr unmodified_msg_ptr;
255c264,270
< 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
257,264c272,275
< 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
< unmodified_msg_ptr = *(msg_ptr.ref()); // This magic line creates a private copy of the message
< }
---
> // This magic line creates a private copy of the
> // message
> unmodified_msg_ptr = *(msg_ptr.ref());
> }
266,268c277,279
< // Enqueue it - for all outgoing queues
< for (int i=0; i<output_links.size(); i++) {
< int outgoing = output_links[i];
---
> // Enqueue it - for all outgoing queues
> for (int i=0; i<output_links.size(); i++) {
> int outgoing = output_links[i];
270,272c281,285
< if (i > 0) {
< msg_ptr = *(unmodified_msg_ptr.ref()); // create a private copy of the unmodified message
< }
---
> if (i > 0) {
> // create a private copy of the unmodified
> // message
> msg_ptr = *(unmodified_msg_ptr.ref());
> }
274,277c287,292
< // Change the internal destination set of the message so it
< // knows which destinations this link is responsible for.
< net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
< net_msg_ptr->getInternalDestination() = output_link_destinations[i];
---
> // Change the internal destination set of the
> // message so it knows which destinations this
> // link is responsible for.
> net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.ref());
> net_msg_ptr->getInternalDestination() =
> output_link_destinations[i];
279,286c294,301
< // Enqeue msg
< DEBUG_NEWLINE(NETWORK_COMP,HighPrio);
< DEBUG_MSG(NETWORK_COMP,HighPrio,"switch: " + int_to_string(m_switch_id)
< + " enqueuing net msg from inport[" + int_to_string(incoming) + "]["
< + int_to_string(vnet) +"] to outport [" + int_to_string(outgoing)
< + "][" + int_to_string(vnet) +"]"
< + " time: " + int_to_string(g_eventQueue_ptr->getTime()) + ".");
< DEBUG_NEWLINE(NETWORK_COMP,HighPrio);
---
> // Enqeue msg
> DEBUG_NEWLINE(NETWORK_COMP,HighPrio);
> DEBUG_MSG(NETWORK_COMP, HighPrio,
> csprintf("switch: %d enqueuing net msg from "
> "inport[%d][%d] to outport [%d][%d] time: %d.",
> m_switch_id, incoming, vnet, outgoing, vnet,
> g_eventQueue_ptr->getTime()));
> DEBUG_NEWLINE(NETWORK_COMP,HighPrio);
288,289c303,304
< m_out[outgoing][vnet]->enqueue(msg_ptr);
< }
---
> m_out[outgoing][vnet]->enqueue(msg_ptr);
> }
291,293c306,309
< // Dequeue msg
< m_in[incoming][vnet]->pop();
< }
---
> // Dequeue msg
> m_in[incoming][vnet]->pop();
> }
> }
295d310
< }
298c313,314
< void PerfectSwitch::printStats(std::ostream& out) const
---
> void
> PerfectSwitch::printStats(std::ostream& out) const
300c316
< out << "PerfectSwitch printStats" << endl;
---
> out << "PerfectSwitch printStats" << endl;
303c319,320
< void PerfectSwitch::clearStats()
---
> void
> PerfectSwitch::clearStats()
307c324,325
< void PerfectSwitch::printConfig(std::ostream& out) const
---
> void
> PerfectSwitch::printConfig(std::ostream& out) const
311c329,330
< void PerfectSwitch::print(std::ostream& out) const
---
> void
> PerfectSwitch::print(std::ostream& out) const
313c332
< out << "[PerfectSwitch " << m_switch_id << "]";
---
> out << "[PerfectSwitch " << m_switch_id << "]";