From 8be59c268c548cc3098fed05395075b3c8a92e8c Mon Sep 17 00:00:00 2001 From: Tiago Muck Date: Mon, 28 Jan 2019 15:07:53 -0600 Subject: [PATCH] cpu: Limit TrafficGen outstanding reqs Parameter to limit the number of requests waiting for a response. Change-Id: I6cf9e8782a06ae978fb66f7c4278f4c9e9980c79 Signed-off-by: Tiago Muck Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/18417 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/cpu/testers/traffic_gen/BaseTrafficGen.py | 5 +++ src/cpu/testers/traffic_gen/base.cc | 43 +++++++++++++++---- src/cpu/testers/traffic_gen/base.hh | 33 +++++++++++++- 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/cpu/testers/traffic_gen/BaseTrafficGen.py b/src/cpu/testers/traffic_gen/BaseTrafficGen.py index 00fe08743..5980bfd46 100644 --- a/src/cpu/testers/traffic_gen/BaseTrafficGen.py +++ b/src/cpu/testers/traffic_gen/BaseTrafficGen.py @@ -72,6 +72,11 @@ class BaseTrafficGen(ClockedObject): elastic_req = Param.Bool(False, "Slow down requests in case of backpressure") + # Maximum number of requests waiting for response. Set to 0 for an + # unlimited number of outstanding requests. + max_outstanding_reqs = Param.Int(0, + "Maximum number of outstanding requests") + # Let the user know if we have waited for a retry and not made any # progress for a long period of time. The default value is # somewhat arbitrary and may well have to be tuned. diff --git a/src/cpu/testers/traffic_gen/base.cc b/src/cpu/testers/traffic_gen/base.cc index 43a1b831a..f2385a49c 100644 --- a/src/cpu/testers/traffic_gen/base.cc +++ b/src/cpu/testers/traffic_gen/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2016-2018 ARM Limited + * Copyright (c) 2012-2013, 2016-2019 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -75,9 +75,10 @@ BaseTrafficGen::BaseTrafficGen(const BaseTrafficGenParams* p) noProgressEvent([this]{ noProgress(); }, name()), nextTransitionTick(0), nextPacketTick(0), + maxOutstandingReqs(p->max_outstanding_reqs), port(name() + ".port", *this), retryPkt(NULL), - retryPktTick(0), + retryPktTick(0), blockedWaitingResp(false), updateEvent([this]{ update(); }, name()), masterID(system->getMasterId(this)), streamGenerator(StreamGen::create(p)) @@ -195,7 +196,9 @@ BaseTrafficGen::update() // device accesses that could be part of a trace if (pkt && system->isMemAddr(pkt->getAddr())) { numPackets++; - if (!port.sendTimingReq(pkt)) { + // Only attempts to send if not blocked by pending responses + blockedWaitingResp = allocateWaitingRespSlot(pkt); + if (blockedWaitingResp || !port.sendTimingReq(pkt)) { retryPkt = pkt; retryPktTick = curTick(); } @@ -213,8 +216,8 @@ BaseTrafficGen::update() } } - // if we are waiting for a retry, do not schedule any further - // events, in the case of a transition or a successful send, go + // if we are waiting for a retry or for a response, do not schedule any + // further events, in the case of a transition or a successful send, go // ahead and determine when the next update should take place if (retryPkt == NULL) { nextPacketTick = activeGenerator->nextPacketTick(elasticReq, 0); @@ -284,10 +287,18 @@ BaseTrafficGen::start() void BaseTrafficGen::recvReqRetry() { - assert(retryPkt != NULL); - DPRINTF(TrafficGen, "Received retry\n"); numRetries++; + retryReq(); +} + +void +BaseTrafficGen::retryReq() +{ + assert(retryPkt != NULL); + assert(retryPktTick != 0); + assert(!blockedWaitingResp); + // attempt to send the packet, and if we are successful start up // the machinery again if (port.sendTimingReq(retryPkt)) { @@ -449,9 +460,25 @@ BaseTrafficGen::createTrace(Tick duration, } bool -BaseTrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt) +BaseTrafficGen::recvTimingResp(PacketPtr pkt) { + auto iter = waitingResp.find(pkt->req); + + panic_if(iter == waitingResp.end(), "%s: " + "Received unexpected response [%s reqPtr=%x]\n", + pkt->print(), pkt->req); + + assert(iter->second <= curTick()); + + waitingResp.erase(iter); + delete pkt; + // Sends up the request if we were blocked + if (blockedWaitingResp) { + blockedWaitingResp = false; + retryReq(); + } + return true; } diff --git a/src/cpu/testers/traffic_gen/base.hh b/src/cpu/testers/traffic_gen/base.hh index 811770fe4..5ffe508a7 100644 --- a/src/cpu/testers/traffic_gen/base.hh +++ b/src/cpu/testers/traffic_gen/base.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2016-2018 ARM Limited + * Copyright (c) 2012-2013, 2016-2019 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -44,6 +44,7 @@ #include #include +#include #include "base/statistics.hh" #include "mem/qport.hh" @@ -93,6 +94,10 @@ class BaseTrafficGen : public ClockedObject */ void recvReqRetry(); + void retryReq(); + + bool recvTimingResp(PacketPtr pkt); + /** Transition to the next generator */ void transition(); @@ -118,6 +123,8 @@ class BaseTrafficGen : public ClockedObject /** Time of the next packet. */ Tick nextPacketTick; + const int maxOutstandingReqs; + /** Master port specialisation for the traffic generator */ class TrafficGenPort : public MasterPort @@ -132,7 +139,8 @@ class BaseTrafficGen : public ClockedObject void recvReqRetry() { trafficGen.recvReqRetry(); } - bool recvTimingResp(PacketPtr pkt); + bool recvTimingResp(PacketPtr pkt) + { return trafficGen.recvTimingResp(pkt); } void recvTimingSnoopReq(PacketPtr pkt) { } @@ -161,6 +169,24 @@ class BaseTrafficGen : public ClockedObject /** Tick when the stalled packet was meant to be sent. */ Tick retryPktTick; + /** Set when we blocked waiting for outstanding reqs */ + bool blockedWaitingResp; + + /** + * Puts this packet in the waitingResp list and returns true if + * we are above the maximum number of oustanding requests. + */ + bool allocateWaitingRespSlot(PacketPtr pkt) + { + assert(waitingResp.find(pkt->req) == waitingResp.end()); + assert(pkt->needsResponse()); + + waitingResp[pkt->req] = curTick(); + + return (maxOutstandingReqs > 0) && + (waitingResp.size() > maxOutstandingReqs); + } + /** Event for scheduling updates */ EventFunctionWrapper updateEvent; @@ -177,6 +203,9 @@ class BaseTrafficGen : public ClockedObject /** Count the time incurred from back-pressure. */ Stats::Scalar retryTicks; + /** Reqs waiting for response **/ + std::unordered_map waitingResp; + public: BaseTrafficGen(const BaseTrafficGenParams* p); -- 2.30.2