summaryrefslogtreecommitdiff
path: root/src/cpu/testers
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/testers')
-rw-r--r--src/cpu/testers/traffic_gen/BaseTrafficGen.py5
-rw-r--r--src/cpu/testers/traffic_gen/base.cc43
-rw-r--r--src/cpu/testers/traffic_gen/base.hh33
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 <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);