ruby: perfect switch: refactor code
authorNilay Vaish <nilay@cs.wisc.edu>
Sat, 12 Sep 2015 21:16:17 +0000 (16:16 -0500)
committerNilay Vaish <nilay@cs.wisc.edu>
Sat, 12 Sep 2015 21:16:17 +0000 (16:16 -0500)
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.

src/mem/ruby/network/simple/PerfectSwitch.cc
src/mem/ruby/network/simple/PerfectSwitch.hh

index 84ead6e26c5b9730ad48e8a1ac9c2191191f3286..697357ccb86c7ee2730885b82316f253b37c02b8 100644 (file)
@@ -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);
         }
     }
 }
index dddbdc9ba802d5ab9b05919380585d2f73c9d03c..1cc9869642d3220908efbe1b535eae50814eca38 100644 (file)
@@ -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;