mem: Remove infinite queue between Ruby and memory
authorMatthew Poremba <matthew.poremba@amd.com>
Fri, 8 May 2020 22:16:28 +0000 (17:16 -0500)
committerBradford Beckmann <brad.beckmann@amd.com>
Tue, 12 May 2020 21:12:21 +0000 (21:12 +0000)
AbstractController sends requests using a QueuedMasterPort which has an
implicit buffer which is unbounded. Remove this by changing the port to
a MasterPort and implement a retry mechanism for AbstractController.
Although the request remains in the MessageBuffer if a retry is needed,
the additional retry logic optimizes serviceMemoryQueue slightly and
prevents the DRAMCtrl retry stats from being incorrect due to multiple
calls to sendTimingReq.

Change-Id: I8c592af92a1a499a418f34cfee16dd69d84803ad
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/28387
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Bradford Beckmann <brad.beckmann@amd.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/mem/ruby/slicc_interface/AbstractController.cc
src/mem/ruby/slicc_interface/AbstractController.hh

index 59611ae10a5b291f32c0a91588dc7e1b885a2256..b729d26dd3ffa6c754c1cb5af3dfb1f09f16e68d 100644 (file)
@@ -56,7 +56,7 @@ AbstractController::AbstractController(const Params *p)
       m_transitions_per_cycle(p->transitions_per_cycle),
       m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency),
       m_mandatory_queue_latency(p->mandatory_queue_latency),
-      memoryPort(csprintf("%s.memory", name()), this, ""),
+      memoryPort(csprintf("%s.memory", name()), this),
       addrRanges(p->addr_ranges.begin(), p->addr_ranges.end())
 {
     if (m_version == 0) {
@@ -250,12 +250,15 @@ AbstractController::serviceMemoryQueue()
         // to make more progress. Make sure it wakes up
         scheduleEvent(Cycles(1));
         recvTimingResp(pkt);
-    } else {
+    } else if (memoryPort.sendTimingReq(pkt)) {
         mem_queue->dequeue(clockEdge());
-        memoryPort.schedTimingReq(pkt, clockEdge());
         // Since the queue was popped the controller may be able
         // to make more progress. Make sure it wakes up
         scheduleEvent(Cycles(1));
+    } else {
+        scheduleEvent(Cycles(1));
+        delete pkt;
+        delete s;
     }
 
     return true;
@@ -306,11 +309,6 @@ AbstractController::functionalMemoryWrite(PacketPtr pkt)
 {
     int num_functional_writes = 0;
 
-    // Check the buffer from the controller to the memory.
-    if (memoryPort.trySatisfyFunctional(pkt)) {
-        num_functional_writes++;
-    }
-
     // Update memory itself.
     memoryPort.sendFunctional(pkt);
     return num_functional_writes + 1;
@@ -369,12 +367,15 @@ AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt)
     return true;
 }
 
+void
+AbstractController::MemoryPort::recvReqRetry()
+{
+    controller->serviceMemoryQueue();
+}
+
 AbstractController::MemoryPort::MemoryPort(const std::string &_name,
                                            AbstractController *_controller,
-                                           const std::string &_label)
-    : QueuedMasterPort(_name, _controller, reqQueue, snoopRespQueue),
-      reqQueue(*_controller, *this, _label),
-      snoopRespQueue(*_controller, *this, false, _label),
-      controller(_controller)
+                                           PortID id)
+    : MasterPort(_name, _controller, id), controller(_controller)
 {
 }
index 15aff12b1d6a0e82b5ee4a8d4fa0011dbf1ecfca..1577cfa6fa37fcd4c2346b2c8b86ca029d073289 100644 (file)
@@ -228,26 +228,25 @@ class AbstractController : public ClockedObject, public Consumer
 
     /**
      * Port that forwards requests and receives responses from the
-     * memory controller.  It has a queue of packets not yet sent.
+     * memory controller.
      */
-    class MemoryPort : public QueuedMasterPort
+    class MemoryPort : public MasterPort
     {
       private:
-        // Packet queues used to store outgoing requests and snoop responses.
-        ReqPacketQueue reqQueue;
-        SnoopRespPacketQueue snoopRespQueue;
-
         // Controller that operates this port.
         AbstractController *controller;
 
       public:
         MemoryPort(const std::string &_name, AbstractController *_controller,
-                   const std::string &_label);
+                   PortID id = InvalidPortID);
 
+      protected:
         // Function for receiving a timing response from the peer port.
         // Currently the pkt is handed to the coherence controller
         // associated with this port.
         bool recvTimingResp(PacketPtr pkt);
+
+        void recvReqRetry();
     };
 
     /* Master port to the memory controller. */