summaryrefslogtreecommitdiff
path: root/src/mem/ruby/network
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2015-09-12 16:16:17 -0500
committerNilay Vaish <nilay@cs.wisc.edu>2015-09-12 16:16:17 -0500
commit8b199b775e209c20cd7f7a8c085455931f8cb70e (patch)
treec983bf99213fc171bf26d2d41d3820acc699e337 /src/mem/ruby/network
parent25cd13dbf1d6f7d306b40c7e2e3d7231b0c5eb04 (diff)
downloadgem5-8b199b775e209c20cd7f7a8c085455931f8cb70e.tar.xz
ruby: perfect switch: refactor code
Refactored the code in operateVnet(), moved partly to a new function operateMessageBuffer(). This is required since a later patch moves to having a wakeup event per MessageBuffer instead of one event for the entire Switch.
Diffstat (limited to 'src/mem/ruby/network')
-rw-r--r--src/mem/ruby/network/simple/PerfectSwitch.cc242
-rw-r--r--src/mem/ruby/network/simple/PerfectSwitch.hh1
2 files changed, 125 insertions, 118 deletions
diff --git a/src/mem/ruby/network/simple/PerfectSwitch.cc b/src/mem/ruby/network/simple/PerfectSwitch.cc
index 84ead6e26..697357ccb 100644
--- a/src/mem/ruby/network/simple/PerfectSwitch.cc
+++ b/src/mem/ruby/network/simple/PerfectSwitch.cc
@@ -103,9 +103,6 @@ PerfectSwitch::~PerfectSwitch()
void
PerfectSwitch::operateVnet(int vnet)
{
- MsgPtr msg_ptr;
- Message *net_msg_ptr = NULL;
-
// This is for round-robin scheduling
int incoming = m_round_robin_start;
m_round_robin_start++;
@@ -122,10 +119,6 @@ PerfectSwitch::operateVnet(int vnet)
incoming = 0;
}
- // temporary vectors to store the routing results
- vector<LinkID> output_links;
- vector<NetDest> output_link_destinations;
-
// Is there a message waiting?
if (m_in[incoming].size() <= vnet) {
continue;
@@ -136,138 +129,151 @@ PerfectSwitch::operateVnet(int vnet)
continue;
}
- while (buffer->isReady()) {
- DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
-
- // Peek at message
- msg_ptr = buffer->peekMsgPtr();
- net_msg_ptr = msg_ptr.get();
- DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
-
- output_links.clear();
- output_link_destinations.clear();
- NetDest msg_dsts = net_msg_ptr->getDestination();
-
- // 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_mt.random(0, 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());
- }
- }
+ operateMessageBuffer(buffer, incoming, vnet);
+ }
+ }
+}
- 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);
+void
+PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming,
+ int vnet)
+{
+ MsgPtr msg_ptr;
+ Message *net_msg_ptr = NULL;
+
+ // temporary vectors to store the routing results
+ vector<LinkID> output_links;
+ vector<NetDest> output_link_destinations;
- if (!msg_dsts.intersectionIsNotEmpty(dst))
- continue;
+ while (buffer->isReady()) {
+ DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
- // Remember what link we're using
- output_links.push_back(link);
+ // Peek at message
+ msg_ptr = buffer->peekMsgPtr();
+ net_msg_ptr = msg_ptr.get();
+ DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
- // 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));
+ output_links.clear();
+ output_link_destinations.clear();
+ NetDest msg_dsts = net_msg_ptr->getDestination();
- // Next, we update the msg_destination not to include
- // those nodes that were already handled by this link
- msg_dsts.removeNetDest(dst);
+ // 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_mt.random(0, 0xff);
+ m_link_order[out].m_link = out;
+ m_link_order[out].m_value = value;
}
- assert(msg_dsts.count() == 0);
+ // Look at the most empty link first
+ sort(m_link_order.begin(), m_link_order.end());
+ }
+ }
- // Check for resources - for all outgoing queues
- bool enough = true;
- for (int i = 0; i < output_links.size(); i++) {
- int outgoing = output_links[i];
+ 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 (!m_out[outgoing][vnet]->areNSlotsAvailable(1))
- enough = false;
+ if (!msg_dsts.intersectionIsNotEmpty(dst))
+ continue;
- DPRINTF(RubyNetwork, "Checking if node is blocked ..."
- "outgoing: %d, vnet: %d, enough: %d\n",
- outgoing, vnet, enough);
- }
+ // Remember what link we're using
+ output_links.push_back(link);
- // There were not enough resources
- if (!enough) {
- scheduleEvent(Cycles(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
- }
+ // 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));
- MsgPtr unmodified_msg_ptr;
+ // Next, we update the msg_destination not to include
+ // those nodes that were already handled by this link
+ msg_dsts.removeNetDest(dst);
+ }
- 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
+ assert(msg_dsts.count() == 0);
- // This magic line creates a private copy of the message
- unmodified_msg_ptr = msg_ptr->clone();
- }
+ // Check for resources - for all outgoing queues
+ bool enough = true;
+ for (int i = 0; i < output_links.size(); i++) {
+ int outgoing = output_links[i];
- // Dequeue msg
- buffer->dequeue();
- m_pending_message_count[vnet]--;
+ if (!m_out[outgoing][vnet]->areNSlotsAvailable(1))
+ enough = false;
- // Enqueue it - for all outgoing queues
- for (int i=0; i<output_links.size(); i++) {
- int outgoing = output_links[i];
+ DPRINTF(RubyNetwork, "Checking if node is blocked ..."
+ "outgoing: %d, vnet: %d, enough: %d\n",
+ outgoing, vnet, enough);
+ }
- if (i > 0) {
- // create a private copy of the unmodified message
- msg_ptr = unmodified_msg_ptr->clone();
- }
+ // There were not enough resources
+ if (!enough) {
+ scheduleEvent(Cycles(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
+ }
- // Change the internal destination set of the message so it
- // knows which destinations this link is responsible for.
- net_msg_ptr = msg_ptr.get();
- net_msg_ptr->getDestination() =
- output_link_destinations[i];
+ MsgPtr unmodified_msg_ptr;
- // Enqeue msg
- DPRINTF(RubyNetwork, "Enqueuing net msg from "
- "inport[%d][%d] to outport [%d][%d].\n",
- incoming, vnet, outgoing, vnet);
+ 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
- m_out[outgoing][vnet]->enqueue(msg_ptr);
- }
+ // This magic line creates a private copy of the message
+ unmodified_msg_ptr = msg_ptr->clone();
+ }
+
+ // Dequeue msg
+ buffer->dequeue();
+ m_pending_message_count[vnet]--;
+
+ // Enqueue it - for all outgoing queues
+ for (int i=0; i<output_links.size(); i++) {
+ int outgoing = output_links[i];
+
+ if (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 = msg_ptr.get();
+ net_msg_ptr->getDestination() = output_link_destinations[i];
+
+ // Enqeue msg
+ DPRINTF(RubyNetwork, "Enqueuing net msg from "
+ "inport[%d][%d] to outport [%d][%d].\n",
+ incoming, vnet, outgoing, vnet);
+
+ m_out[outgoing][vnet]->enqueue(msg_ptr);
}
}
}
diff --git a/src/mem/ruby/network/simple/PerfectSwitch.hh b/src/mem/ruby/network/simple/PerfectSwitch.hh
index dddbdc9ba..1cc986964 100644
--- a/src/mem/ruby/network/simple/PerfectSwitch.hh
+++ b/src/mem/ruby/network/simple/PerfectSwitch.hh
@@ -85,6 +85,7 @@ class PerfectSwitch : public Consumer
PerfectSwitch& operator=(const PerfectSwitch& obj);
void operateVnet(int vnet);
+ void operateMessageBuffer(MessageBuffer *b, int incoming, int vnet);
const SwitchID m_switch_id;
Switch * const m_switch;