diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc index 2d10422487..f7b01cf939 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.cc +++ b/src/mem/ruby/slicc_interface/AbstractController.cc @@ -62,8 +62,10 @@ AbstractController::AbstractController(const Params &p) 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 @@ AbstractController::functionalMemoryWrite(PacketPtr pkt) 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 @@ AbstractController::recvTimingResp(PacketPtr pkt) 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 @@ const } +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 a5ab5c2c44..7fdb88b07d 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 @@ class AbstractController : public ClockedObject, public Consumer 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 &addr) = 0; virtual void print(std::ostream & out) const = 0; @@ -165,7 +174,7 @@ class AbstractController : public ClockedObject, public Consumer 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 +373,7 @@ class AbstractController : public ClockedObject, public Consumer 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 +421,9 @@ class AbstractController : public ClockedObject, public Consumer NetDest downstreamDestinations; NetDest upstreamDestinations; + void sendRetryRespToMem(); + MemberEventWrapper<&AbstractController::sendRetryRespToMem> mRetryRespEvent; + public: struct ControllerStats : public statistics::Group {