[gem5-dev] [M] Change in gem5/gem5[develop]: mem-ruby: AbstractController can send retry req to mem controller

2023-07-07 Thread Gabriel B. (Gerrit) via gem5-dev
Gabriel B. has submitted this change. (  
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
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67658
Tested-by: kokoro 
Reviewed-by: Bobby Bruce 
Maintainer: Bobby Bruce 
---
M src/mem/ruby/slicc_interface/AbstractController.cc
M src/mem/ruby/slicc_interface/AbstractController.hh
2 files changed, 51 insertions(+), 7 deletions(-)

Approvals:
  kokoro: Regressions pass
  Bobby Bruce: Looks good to me, approved; Looks good to me, approved




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 msg =  
std::make_shared(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..7fdb88b 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,14 @@
 virtual MessageBuffer* getMandatoryQueue() const = 0;
 virtual MessageBuffer* getMemReqQueue() const = 0;
 virtual MessageBuffer* getMemRespQueue() const = 0;
+
+// 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 ) = 0;

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

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

 const AddrRangeList () const { return addrRanges; }
@@ -364,6 +373,7 @@
 Cycles 

[gem5-dev] [M] Change in gem5/gem5[develop]: mem-ruby: AbstractController can send retry req to mem controller

2023-02-06 Thread Gabriel B. (Gerrit) via gem5-dev
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 msg =  
std::make_shared(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 ) = 0;

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

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

 const AddrRangeList () 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