cpu: Limit TrafficGen outstanding reqs

Parameter to limit the number of requests waiting for a response.

Change-Id: I6cf9e8782a06ae978fb66f7c4278f4c9e9980c79
Signed-off-by: Tiago Muck <tiago.muck@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/18417
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Tiago Muck
2019-01-28 15:07:53 -06:00
committed by Tiago Mück
parent 5247008379
commit 8be59c268c
3 changed files with 71 additions and 10 deletions

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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 <memory>
#include <tuple>
#include <unordered_map>
#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<RequestPtr,Tick> waitingResp;
public:
BaseTrafficGen(const BaseTrafficGenParams* p);