Gabriel B. has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/67658?usp=email )

Change subject: mem-ruby: AbstractController can send retry req to mem controller
......................................................................

mem-ruby: AbstractController can send retry req to mem controller

Prior to this patch, when a memory controller was failing at sending a
response to AbstractController, it would not wakeup until the next
request. This patch gives the opportunity to Ruby models to notify
memory response buffer dequeue so that AbstractController can send a
retry request if necessary.

A dequeueMemRspQueue function has been added AbstractController to
automate the dequeue+notify operation.

Note that models that don't notify AbstractController will continue
working as before.

Change-Id: I261bb4593c126208c98825e54f538638d818d16b
---
M src/mem/ruby/slicc_interface/AbstractController.cc
M src/mem/ruby/slicc_interface/AbstractController.hh
2 files changed, 74 insertions(+), 7 deletions(-)



diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index 2d10422..f7b01cf 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -62,8 +62,10 @@
       m_buffer_size(p.buffer_size), m_recycle_latency(p.recycle_latency),
       m_mandatory_queue_latency(p.mandatory_queue_latency),
       m_waiting_mem_retry(false),
+      m_mem_ctrl_waiting_retry(false),
       memoryPort(csprintf("%s.memory", name()), this),
       addrRanges(p.addr_ranges.begin(), p.addr_ranges.end()),
+      mRetryRespEvent{*this, false},
       stats(this)
 {
     if (m_version == 0) {
@@ -367,11 +369,17 @@
     return num_functional_writes + 1;
 }

-void
+bool
 AbstractController::recvTimingResp(PacketPtr pkt)
 {
-    assert(getMemRespQueue());
-    assert(pkt->isResponse());
+    auto* memRspQueue = getMemRespQueue();
+    gem5_assert(memRspQueue);
+    gem5_assert(pkt->isResponse());
+
+    if (!memRspQueue->areNSlotsAvailable(1, curTick())) {
+        m_mem_ctrl_waiting_retry = true;
+        return false;
+    }

std::shared_ptr<MemoryMsg> msg = std::make_shared<MemoryMsg>(clockEdge());
     (*msg).m_addr = pkt->getAddr();
@@ -395,8 +403,9 @@
         panic("Incorrect packet type received from memory controller!");
     }

-    getMemRespQueue()->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1)));
+    memRspQueue->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1)));
     delete pkt;
+    return true;
 }

 Tick
@@ -438,11 +447,33 @@
 }


+void
+AbstractController::memRespQueueDequeued() {
+    if (m_mem_ctrl_waiting_retry && !mRetryRespEvent.scheduled()) {
+        schedule(mRetryRespEvent, clockEdge(Cycles{1}));
+    }
+}
+
+void
+AbstractController::dequeueMemRespQueue() {
+    auto* q = getMemRespQueue();
+    gem5_assert(q);
+    q->dequeue(clockEdge());
+    memRespQueueDequeued();
+}
+
+void
+AbstractController::sendRetryRespToMem() {
+    if (m_mem_ctrl_waiting_retry) {
+        m_mem_ctrl_waiting_retry = false;
+        memoryPort.sendRetryResp();
+    }
+}
+
 bool
 AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt)
 {
-    controller->recvTimingResp(pkt);
-    return true;
+    return controller->recvTimingResp(pkt);
 }

 void
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index a5ab5c2..f483412 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -61,6 +61,7 @@
 #include "mem/ruby/system/CacheRecorder.hh"
 #include "params/RubyController.hh"
 #include "sim/clocked_object.hh"
+#include "sim/eventq.hh"

 namespace gem5
 {
@@ -100,6 +101,16 @@
     virtual MessageBuffer* getMandatoryQueue() const = 0;
     virtual MessageBuffer* getMemReqQueue() const = 0;
     virtual MessageBuffer* getMemRespQueue() const = 0;
+    virtual void memReqQueueDequeued() {};
+    virtual void memRespQueueEnqueued() {};
+
+ // That function must be called by controller when dequeuing mem resp queue
+    // for memory controller to receive the retry request in time
+    void memRespQueueDequeued();
+ // Or that function can be called to perform both dequeue and notification
+    // at once.
+    void dequeueMemRespQueue();
+
     virtual AccessPermission getAccessPermission(const Addr &addr) = 0;

     virtual void print(std::ostream & out) const = 0;
@@ -165,7 +176,7 @@
     Port &getPort(const std::string &if_name,
                   PortID idx=InvalidPortID);

-    void recvTimingResp(PacketPtr pkt);
+    bool recvTimingResp(PacketPtr pkt);
     Tick recvAtomic(PacketPtr pkt);

     const AddrRangeList &getAddrRanges() const { return addrRanges; }
@@ -364,6 +375,7 @@
     Cycles m_recycle_latency;
     const Cycles m_mandatory_queue_latency;
     bool m_waiting_mem_retry;
+    bool m_mem_ctrl_waiting_retry;

     /**
      * Port that forwards requests and receives responses from the
@@ -411,6 +423,9 @@
     NetDest downstreamDestinations;
     NetDest upstreamDestinations;

+    void sendRetryRespToMem();
+ MemberEventWrapper<&AbstractController::sendRetryRespToMem> mRetryRespEvent;
+
   public:
     struct ControllerStats : public statistics::Group
     {

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/67658?usp=email To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I261bb4593c126208c98825e54f538638d818d16b
Gerrit-Change-Number: 67658
Gerrit-PatchSet: 1
Gerrit-Owner: Gabriel B. <gabriel.bus...@arteris.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org

Reply via email to