ruby: Fix for stallAndWait bug
authorDavid Hashe <david.hashe@amd.com>
Mon, 20 Jul 2015 14:15:18 +0000 (09:15 -0500)
committerDavid Hashe <david.hashe@amd.com>
Mon, 20 Jul 2015 14:15:18 +0000 (09:15 -0500)
It was previously possible for a stalled message to be reordered after an
incomming message. This patch ensures that any stalled message stays in its
original request order.

src/mem/ruby/network/MessageBuffer.cc
src/mem/ruby/slicc_interface/AbstractController.cc
src/mem/ruby/slicc_interface/AbstractController.hh

index 0555f9b595886176f9ca8a8c087e925774ebe0a0..d823c0a1f7d30596f9003cf775357e63ed5fd9ba 100644 (file)
@@ -86,7 +86,7 @@ MessageBuffer::areNSlotsAvailable(unsigned int n)
 
     // determine the correct size for the current cycle
     // pop operations shouldn't effect the network's visible size
-    // until next cycle, but enqueue operations effect the visible
+    // until schd cycle, but enqueue operations effect the visible
     // size immediately
     unsigned int current_size = 0;
 
@@ -234,7 +234,7 @@ MessageBuffer::dequeue()
         m_receiver->ticksToCycles(message->getDelayedTicks());
 
     // record previous size and time so the current buffer size isn't
-    // adjusted until next cycle
+    // adjusted until schd cycle
     if (m_time_last_time_pop < m_receiver->clockEdge()) {
         m_size_at_cycle_start = m_prio_heap.size();
         m_time_last_time_pop = m_receiver->clockEdge();
@@ -275,19 +275,19 @@ MessageBuffer::recycle()
 }
 
 void
-MessageBuffer::reanalyzeList(list<MsgPtr> &lt, Tick nextTick)
+MessageBuffer::reanalyzeList(list<MsgPtr> &lt, Tick schdTick)
 {
     while(!lt.empty()) {
         m_msg_counter++;
         MsgPtr m = lt.front();
-        m->setLastEnqueueTime(nextTick);
+        m->setLastEnqueueTime(schdTick);
         m->setMsgCounter(m_msg_counter);
 
         m_prio_heap.push_back(m);
         push_heap(m_prio_heap.begin(), m_prio_heap.end(),
                   greater<MsgPtr>());
 
-        m_consumer->scheduleEventAbsolute(nextTick);
+        m_consumer->scheduleEventAbsolute(schdTick);
         lt.pop_front();
     }
 }
@@ -297,13 +297,15 @@ MessageBuffer::reanalyzeMessages(const Address& addr)
 {
     DPRINTF(RubyQueue, "ReanalyzeMessages\n");
     assert(m_stall_msg_map.count(addr) > 0);
-    Tick nextTick = m_receiver->clockEdge(Cycles(1));
+    Tick curTick = m_receiver->clockEdge();
 
     //
     // Put all stalled messages associated with this address back on the
-    // prio heap
+    // prio heap.  The reanalyzeList call will make sure the consumer is
+    // scheduled for the current cycle so that the previously stalled messages
+    // will be observed before any younger messages that may arrive this cycle
     //
-    reanalyzeList(m_stall_msg_map[addr], nextTick);
+    reanalyzeList(m_stall_msg_map[addr], curTick);
     m_stall_msg_map.erase(addr);
 }
 
@@ -311,15 +313,17 @@ void
 MessageBuffer::reanalyzeAllMessages()
 {
     DPRINTF(RubyQueue, "ReanalyzeAllMessages\n");
-    Tick nextTick = m_receiver->clockEdge(Cycles(1));
+    Tick curTick = m_receiver->clockEdge();
 
     //
     // Put all stalled messages associated with this address back on the
-    // prio heap
+    // prio heap.  The reanalyzeList call will make sure the consumer is
+    // scheduled for the current cycle so that the previously stalled messages
+    // will be observed before any younger messages that may arrive this cycle.
     //
     for (StallMsgMapType::iterator map_iter = m_stall_msg_map.begin();
          map_iter != m_stall_msg_map.end(); ++map_iter) {
-        reanalyzeList(map_iter->second, nextTick);
+        reanalyzeList(map_iter->second, curTick);
     }
     m_stall_msg_map.clear();
 }
index a6d05fd3a0560ecd63bd0dc5f55edecf04933bc3..1ac99c882321ee15844c16f0aab28e46e66003e8 100644 (file)
@@ -154,6 +154,7 @@ AbstractController::wakeUpAllBuffers()
     //
 
     std::vector<MsgVecType*> wokeUpMsgVecs;
+    MsgBufType wokeUpMsgBufs;
 
     if(m_waiting_buffers.size() > 0) {
         for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin();
@@ -162,8 +163,13 @@ AbstractController::wakeUpAllBuffers()
              for (MsgVecType::iterator vec_iter = buf_iter->second->begin();
                   vec_iter != buf_iter->second->end();
                   ++vec_iter) {
-                  if (*vec_iter != NULL) {
+                  //
+                  // Make sure the MessageBuffer has not already be reanalyzed
+                  //
+                  if (*vec_iter != NULL &&
+                      (wokeUpMsgBufs.count(*vec_iter) == 0)) {
                       (*vec_iter)->reanalyzeAllMessages();
+                      wokeUpMsgBufs.insert(*vec_iter);
                   }
              }
              wokeUpMsgVecs.push_back(buf_iter->second);
index e01a2a8245d23982e40ec153646ffaa4d275951e..aadf03bd8510353f326d876f0978ea8de2327477 100644 (file)
@@ -150,6 +150,7 @@ class AbstractController : public MemObject, public Consumer
     std::map<Address, MessageBuffer*> m_block_map;
 
     typedef std::vector<MessageBuffer*> MsgVecType;
+    typedef std::set<MessageBuffer*> MsgBufType;
     typedef std::map< Address, MsgVecType* > WaitingBufType;
     WaitingBufType m_waiting_buffers;