[gem5-dev] [M] Change in gem5/gem5[develop]: mem-ruby: AbstractController can send retry req to mem controller
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
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