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:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user