mem: Enforce insertion order on the cache response path
authorAli Jafri <ali.jafri@arm.com>
Fri, 6 Nov 2015 08:26:37 +0000 (03:26 -0500)
committerAli Jafri <ali.jafri@arm.com>
Fri, 6 Nov 2015 08:26:37 +0000 (03:26 -0500)
This patch enforces insertion order transmission of packets on the
response path in the cache. Note that the logic to enforce order is
already present in the packet queue, this patch simply turns it on for
queues in the response path.

Without this patch, there are corner cases where a request-response is
faster than a response-response forwarded through the cache. This
violation of queuing order causes problems in the snoop filter leaving
it with inaccurate information. This causes assert failures in the
snoop filter later on.

A follow on patch relaxes the order enforcement in the packet queue to
limit the performance impact.

src/mem/cache/cache.cc
src/mem/dram_ctrl.cc
src/mem/qport.hh

index aa95d56041458e1982e6bcd374ce817c5ae0082a..a03790abc7a83a5132c5c81bfd72a6d12b388b1b 100644 (file)
@@ -666,7 +666,7 @@ Cache::recvTimingReq(PacketPtr pkt)
             // lat, neglecting responseLatency, modelling hit latency
             // just as lookupLatency or or the value of lat overriden
             // by access(), that calls accessBlock() function.
-            cpuSidePort->schedTimingResp(pkt, request_time);
+            cpuSidePort->schedTimingResp(pkt, request_time, true);
         } else {
             // queue the packet for deletion, as the sending cache is
             // still relying on it; if the block is found in access(),
@@ -723,7 +723,7 @@ Cache::recvTimingReq(PacketPtr pkt)
             std::memset(pkt->getPtr<uint8_t>(), 0xFF, pkt->getSize());
             // request_time is used here, taking into account lat and the delay
             // charged if the packet comes from the xbar.
-            cpuSidePort->schedTimingResp(pkt, request_time);
+            cpuSidePort->schedTimingResp(pkt, request_time, true);
 
             // If an outstanding request is in progress (we found an
             // MSHR) this is set to null
@@ -1330,7 +1330,7 @@ Cache::recvTimingResp(PacketPtr pkt)
             }
             // Reset the bus additional time as it is now accounted for
             tgt_pkt->headerDelay = tgt_pkt->payloadDelay = 0;
-            cpuSidePort->schedTimingResp(tgt_pkt, completion_time);
+            cpuSidePort->schedTimingResp(tgt_pkt, completion_time, true);
             break;
 
           case MSHR::Target::FromPrefetcher:
index abf570910dac100570f95eda4d6db66164716c8e..2364834e361fd8399fa23ec565789e602bae0658 100644 (file)
@@ -860,7 +860,7 @@ DRAMCtrl::accessAndRespond(PacketPtr pkt, Tick static_latency)
 
         // queue the packet in the response queue to be sent out after
         // the static latency has passed
-        port.schedTimingResp(pkt, response_time);
+        port.schedTimingResp(pkt, response_time, true);
     } else {
         // @todo the packet is going to be deleted, and the DRAMPacket
         // is still having a pointer to it
index 94bcc53fd35bb15c33dc75d7d9dea58b620a6310..b15bdfec2c678391f5136e18c6b5a2d0f636e1a1 100644 (file)
@@ -88,8 +88,8 @@ class QueuedSlavePort : public SlavePort
      * @param pkt Packet to send
      * @param when Absolute time (in ticks) to send packet
      */
-    void schedTimingResp(PacketPtr pkt, Tick when)
-    { respQueue.schedSendTiming(pkt, when); }
+    void schedTimingResp(PacketPtr pkt, Tick when, bool force_order = false)
+    { respQueue.schedSendTiming(pkt, when, force_order); }
 
     /** Check the list of buffered packets against the supplied
      * functional request. */