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/TrafficGen.py6
-rw-r--r--src/cpu/testers/traffic_gen/generators.cc42
-rw-r--r--src/cpu/testers/traffic_gen/generators.hh18
-rw-r--r--src/cpu/testers/traffic_gen/traffic_gen.cc13
-rw-r--r--src/cpu/testers/traffic_gen/traffic_gen.hh6
5 files changed, 66 insertions, 19 deletions
diff --git a/src/cpu/testers/traffic_gen/TrafficGen.py b/src/cpu/testers/traffic_gen/TrafficGen.py
index 916279f91..f29cedb3a 100644
--- a/src/cpu/testers/traffic_gen/TrafficGen.py
+++ b/src/cpu/testers/traffic_gen/TrafficGen.py
@@ -71,3 +71,9 @@ class TrafficGen(MemObject):
# System used to determine the mode of the memory system
system = Param.System(Parent.any, "System this generator is part of")
+
+ # Should requests respond to back-pressure or not, if true, the
+ # rate of the traffic generator will be slowed down if requests
+ # are not immediately accepted
+ elastic_req = Param.Bool(False,
+ "Slow down requests in case of backpressure")
diff --git a/src/cpu/testers/traffic_gen/generators.cc b/src/cpu/testers/traffic_gen/generators.cc
index f9556b2b3..8a03e21d0 100644
--- a/src/cpu/testers/traffic_gen/generators.cc
+++ b/src/cpu/testers/traffic_gen/generators.cc
@@ -112,7 +112,7 @@ LinearGen::getNextPacket()
}
Tick
-LinearGen::nextPacketTick() const
+LinearGen::nextPacketTick(bool elastic, Tick delay) const
{
// Check to see if we have reached the data limit. If dataLimit is
// zero we do not have a data limit and therefore we will keep
@@ -123,7 +123,19 @@ LinearGen::nextPacketTick() const
return MaxTick;
} else {
// return the time when the next request should take place
- return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
+ Tick wait = random_mt.random<Tick>(minPeriod, maxPeriod);
+
+ // compensate for the delay experienced to not be elastic, by
+ // default the value we generate is from the time we are
+ // asked, so the elasticity happens automatically
+ if (!elastic) {
+ if (wait < delay)
+ wait = 0;
+ else
+ wait -= delay;
+ }
+
+ return curTick() + wait;
}
}
@@ -162,7 +174,7 @@ RandomGen::getNextPacket()
}
Tick
-RandomGen::nextPacketTick() const
+RandomGen::nextPacketTick(bool elastic, Tick delay) const
{
// Check to see if we have reached the data limit. If dataLimit is
// zero we do not have a data limit and therefore we will keep
@@ -173,8 +185,20 @@ RandomGen::nextPacketTick() const
// No more requests. Return MaxTick.
return MaxTick;
} else {
- // Return the time when the next request should take place.
- return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
+ // return the time when the next request should take place
+ Tick wait = random_mt.random<Tick>(minPeriod, maxPeriod);
+
+ // compensate for the delay experienced to not be elastic, by
+ // default the value we generate is from the time we are
+ // asked, so the elasticity happens automatically
+ if (!elastic) {
+ if (wait < delay)
+ wait = 0;
+ else
+ wait -= delay;
+ }
+
+ return curTick() + wait;
}
}
@@ -217,7 +241,7 @@ TraceGen::InputStream::read(TraceElement& element)
}
Tick
-TraceGen::nextPacketTick() const
+TraceGen::nextPacketTick(bool elastic, Tick delay) const
{
if (traceComplete) {
DPRINTF(TrafficGen, "No next tick as trace is finished\n");
@@ -232,7 +256,11 @@ TraceGen::nextPacketTick() const
DPRINTF(TrafficGen, "Next packet tick is %d\n", tickOffset +
nextElement.tick);
- return tickOffset + nextElement.tick;
+ // if the playback is supposed to be elastic, add the delay
+ if (elastic)
+ tickOffset += delay;
+
+ return std::max(tickOffset + nextElement.tick, curTick());
}
void
diff --git a/src/cpu/testers/traffic_gen/generators.hh b/src/cpu/testers/traffic_gen/generators.hh
index 2b86afa22..dd3706a8f 100644
--- a/src/cpu/testers/traffic_gen/generators.hh
+++ b/src/cpu/testers/traffic_gen/generators.hh
@@ -124,9 +124,11 @@ class BaseGen
* means that there will not be any further packets in the current
* activation cycle of the generator.
*
+ * @param elastic should the injection respond to flow control or not
+ * @param delay time the previous packet spent waiting
* @return next tick when a packet is available
*/
- virtual Tick nextPacketTick() const = 0;
+ virtual Tick nextPacketTick(bool elastic, Tick delay) const = 0;
};
@@ -146,7 +148,7 @@ class IdleGen : public BaseGen
PacketPtr getNextPacket() { return NULL; }
- Tick nextPacketTick() const { return MaxTick; }
+ Tick nextPacketTick(bool elastic, Tick delay) const { return MaxTick; }
};
/**
@@ -192,7 +194,7 @@ class LinearGen : public BaseGen
PacketPtr getNextPacket();
- Tick nextPacketTick() const;
+ Tick nextPacketTick(bool elastic, Tick delay) const;
private:
@@ -269,7 +271,7 @@ class RandomGen : public BaseGen
PacketPtr getNextPacket();
- Tick nextPacketTick() const;
+ Tick nextPacketTick(bool elastic, Tick delay) const;
private:
@@ -403,6 +405,7 @@ class TraceGen : public BaseGen
const std::string& trace_file, Addr addr_offset)
: BaseGen(_name, master_id, _duration),
trace(trace_file),
+ tickOffset(0),
addrOffset(addr_offset),
traceComplete(false)
{
@@ -419,7 +422,7 @@ class TraceGen : public BaseGen
* the end of the file has been reached, it returns MaxTick to
* indicate that there will be no more requests.
*/
- Tick nextPacketTick() const;
+ Tick nextPacketTick(bool elastic, Tick delay) const;
private:
@@ -432,9 +435,10 @@ class TraceGen : public BaseGen
/**
* Stores the time when the state was entered. This is to add an
- * offset to the times stored in the trace file.
+ * offset to the times stored in the trace file. This is mutable
+ * to allow us to change it as part of nextPacketTick.
*/
- Tick tickOffset;
+ mutable Tick tickOffset;
/**
* Offset for memory requests. Used to shift the trace
diff --git a/src/cpu/testers/traffic_gen/traffic_gen.cc b/src/cpu/testers/traffic_gen/traffic_gen.cc
index 8916dcb8d..f5835f8f4 100644
--- a/src/cpu/testers/traffic_gen/traffic_gen.cc
+++ b/src/cpu/testers/traffic_gen/traffic_gen.cc
@@ -55,6 +55,7 @@ TrafficGen::TrafficGen(const TrafficGenParams* p)
system(p->system),
masterID(system->getMasterId(name())),
configFile(p->config_file),
+ elasticReq(p->elastic_req),
nextTransitionTick(0),
nextPacketTick(0),
port(name() + ".port", *this),
@@ -107,7 +108,7 @@ TrafficGen::initState()
// when not restoring from a checkpoint, make sure we kick things off
if (system->isTimingMode()) {
// call nextPacketTick on the state to advance it
- nextPacketTick = states[currState]->nextPacketTick();
+ nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
schedule(updateEvent, std::min(nextPacketTick, nextTransitionTick));
} else {
DPRINTF(TrafficGen,
@@ -165,7 +166,7 @@ TrafficGen::unserialize(Checkpoint* cp, const string& section)
// @todo In the case of a stateful generator state such as the
// trace player we would also have to restore the position in the
- // trace playback
+ // trace playback and the tick offset
UNSERIALIZE_SCALAR(currState);
}
@@ -193,7 +194,7 @@ TrafficGen::update()
if (retryPkt == NULL) {
// schedule next update event based on either the next execute
// tick or the next transition, which ever comes first
- nextPacketTick = states[currState]->nextPacketTick();
+ nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick);
schedule(updateEvent, nextEventTick);
@@ -386,14 +387,16 @@ TrafficGen::recvRetry()
if (port.sendTimingReq(retryPkt)) {
retryPkt = NULL;
// remember how much delay was incurred due to back-pressure
- // when sending the request
+ // when sending the request, we also use this to derive
+ // the tick for the next packet
Tick delay = curTick() - retryPktTick;
retryPktTick = 0;
retryTicks += delay;
if (drainManager == NULL) {
// packet is sent, so find out when the next one is due
- nextPacketTick = states[currState]->nextPacketTick();
+ nextPacketTick = states[currState]->nextPacketTick(elasticReq,
+ delay);
Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
schedule(updateEvent, std::max(curTick(), nextEventTick));
} else {
diff --git a/src/cpu/testers/traffic_gen/traffic_gen.hh b/src/cpu/testers/traffic_gen/traffic_gen.hh
index 0adcf781e..91460053a 100644
--- a/src/cpu/testers/traffic_gen/traffic_gen.hh
+++ b/src/cpu/testers/traffic_gen/traffic_gen.hh
@@ -116,6 +116,12 @@ class TrafficGen : public MemObject
*/
const std::string configFile;
+ /**
+ * Determine whether to add elasticity in the request injection,
+ * thus responding to backpressure by slowing things down.
+ */
+ const bool elasticReq;
+
/** Time of next transition */
Tick nextTransitionTick;