summaryrefslogtreecommitdiff
path: root/src/cpu/testers/traffic_gen/traffic_gen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/testers/traffic_gen/traffic_gen.cc')
-rw-r--r--src/cpu/testers/traffic_gen/traffic_gen.cc275
1 files changed, 43 insertions, 232 deletions
diff --git a/src/cpu/testers/traffic_gen/traffic_gen.cc b/src/cpu/testers/traffic_gen/traffic_gen.cc
index d262fd9f7..b3f73e2e5 100644
--- a/src/cpu/testers/traffic_gen/traffic_gen.cc
+++ b/src/cpu/testers/traffic_gen/traffic_gen.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, 2016-2017 ARM Limited
+ * Copyright (c) 2012-2013, 2016-2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -47,29 +47,24 @@
#include "base/intmath.hh"
#include "base/random.hh"
-#include "debug/Checkpoint.hh"
+#include "cpu/testers/traffic_gen/dram_gen.hh"
+#include "cpu/testers/traffic_gen/dram_rot_gen.hh"
+#include "cpu/testers/traffic_gen/exit_gen.hh"
+#include "cpu/testers/traffic_gen/idle_gen.hh"
+#include "cpu/testers/traffic_gen/linear_gen.hh"
+#include "cpu/testers/traffic_gen/random_gen.hh"
+#include "cpu/testers/traffic_gen/trace_gen.hh"
#include "debug/TrafficGen.hh"
+#include "params/TrafficGen.hh"
#include "sim/stats.hh"
#include "sim/system.hh"
using namespace std;
TrafficGen::TrafficGen(const TrafficGenParams* p)
- : MemObject(p),
- system(p->system),
- masterID(system->getMasterId(this)),
+ : BaseTrafficGen(p),
configFile(p->config_file),
- elasticReq(p->elastic_req),
- progressCheck(p->progress_check),
- noProgressEvent([this]{ noProgress(); }, name()),
- nextTransitionTick(0),
- nextPacketTick(0),
- currState(0),
- port(name() + ".port", *this),
- retryPkt(NULL),
- retryPktTick(0),
- updateEvent([this]{ update(); }, name()),
- numSuppressed(0)
+ currState(0)
{
}
@@ -79,156 +74,46 @@ TrafficGenParams::create()
return new TrafficGen(this);
}
-BaseMasterPort&
-TrafficGen::getMasterPort(const string& if_name, PortID idx)
-{
- if (if_name == "port") {
- return port;
- } else {
- return MemObject::getMasterPort(if_name, idx);
- }
-}
-
void
TrafficGen::init()
{
- if (!port.isConnected())
- fatal("The port of %s is not connected!\n", name());
-
- // if the system is in timing mode active the request generator
- if (system->isTimingMode()) {
- DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
-
- parseConfig();
+ BaseTrafficGen::init();
- // enter initial state
- enterState(currState);
- } else {
- DPRINTF(TrafficGen,
- "Traffic generator is only active in timing mode\n");
- }
+ parseConfig();
}
void
TrafficGen::initState()
{
+ BaseTrafficGen::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(elasticReq, 0);
- schedule(updateEvent, std::min(nextPacketTick, nextTransitionTick));
+ DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
+ start();
} else {
DPRINTF(TrafficGen,
"Traffic generator is only active in timing mode\n");
}
}
-DrainState
-TrafficGen::drain()
-{
- if (!updateEvent.scheduled()) {
- // no event has been scheduled yet (e.g. switched from atomic mode)
- return DrainState::Drained;
- }
-
- if (retryPkt == NULL) {
- // shut things down
- nextPacketTick = MaxTick;
- nextTransitionTick = MaxTick;
- deschedule(updateEvent);
- return DrainState::Drained;
- } else {
- return DrainState::Draining;
- }
-}
-
void
TrafficGen::serialize(CheckpointOut &cp) const
{
- DPRINTF(Checkpoint, "Serializing TrafficGen\n");
-
- // save ticks of the graph event if it is scheduled
- Tick nextEvent = updateEvent.scheduled() ? updateEvent.when() : 0;
-
- DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", nextEvent);
-
- SERIALIZE_SCALAR(nextEvent);
-
- SERIALIZE_SCALAR(nextTransitionTick);
-
- SERIALIZE_SCALAR(nextPacketTick);
-
SERIALIZE_SCALAR(currState);
+
+ BaseTrafficGen::serialize(cp);
}
void
TrafficGen::unserialize(CheckpointIn &cp)
{
- // restore scheduled events
- Tick nextEvent;
- UNSERIALIZE_SCALAR(nextEvent);
- if (nextEvent != 0) {
- schedule(updateEvent, nextEvent);
- }
-
- UNSERIALIZE_SCALAR(nextTransitionTick);
-
- UNSERIALIZE_SCALAR(nextPacketTick);
-
// @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 and the tick offset
UNSERIALIZE_SCALAR(currState);
-}
-void
-TrafficGen::update()
-{
- // shift our progress-tracking event forward
- reschedule(noProgressEvent, curTick() + progressCheck, true);
-
- // if we have reached the time for the next state transition, then
- // perform the transition
- if (curTick() >= nextTransitionTick) {
- transition();
- } else {
- assert(curTick() >= nextPacketTick);
- // get the next packet and try to send it
- PacketPtr pkt = states[currState]->getNextPacket();
-
- // suppress packets that are not destined for a memory, such as
- // device accesses that could be part of a trace
- if (system->isMemAddr(pkt->getAddr())) {
- numPackets++;
- if (!port.sendTimingReq(pkt)) {
- retryPkt = pkt;
- retryPktTick = curTick();
- }
- } else {
- DPRINTF(TrafficGen, "Suppressed packet %s 0x%x\n",
- pkt->cmdString(), pkt->getAddr());
-
- ++numSuppressed;
- if (numSuppressed % 10000)
- warn("%s suppressed %d packets with non-memory addresses\n",
- name(), numSuppressed);
-
- delete pkt;
- pkt = nullptr;
- }
- }
-
- // if we are waiting for a retry, 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) {
- // schedule next update event based on either the next execute
- // tick or the next transition, which ever comes first
- nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
- Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
- DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick);
- schedule(updateEvent, nextEventTick);
- }
+ BaseTrafficGen::unserialize(cp);
}
std::string
@@ -298,14 +183,14 @@ TrafficGen::parseConfig()
is >> traceFile >> addrOffset;
traceFile = resolveFile(traceFile);
- states[id] = new TraceGen(name(), masterID, duration,
- traceFile, addrOffset);
+ states[id].reset(new TraceGen(name(), masterID, duration,
+ traceFile, addrOffset));
DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
} else if (mode == "IDLE") {
- states[id] = new IdleGen(name(), masterID, duration);
+ states[id].reset(new IdleGen(name(), masterID, duration));
DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
} else if (mode == "EXIT") {
- states[id] = new ExitGen(name(), masterID, duration);
+ states[id].reset(new ExitGen(name(), masterID, duration));
DPRINTF(TrafficGen, "State: %d ExitGen\n", id);
} else if (mode == "LINEAR" || mode == "RANDOM" ||
mode == "DRAM" || mode == "DRAM_ROTATE") {
@@ -338,18 +223,18 @@ TrafficGen::parseConfig()
fatal("%s cannot have min_period > max_period", name());
if (mode == "LINEAR") {
- states[id] = new LinearGen(name(), masterID,
+ states[id].reset(new LinearGen(name(), masterID,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
- read_percent, data_limit);
+ read_percent, data_limit));
DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
} else if (mode == "RANDOM") {
- states[id] = new RandomGen(name(), masterID,
+ states[id].reset(new RandomGen(name(), masterID,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
- read_percent, data_limit);
+ read_percent, data_limit));
DPRINTF(TrafficGen, "State: %d RandomGen\n", id);
} else if (mode == "DRAM" || mode == "DRAM_ROTATE") {
// stride size (bytes) of the request for achieving
@@ -387,7 +272,7 @@ TrafficGen::parseConfig()
}
if (mode == "DRAM") {
- states[id] = new DramGen(name(), masterID,
+ states[id].reset(new DramGen(name(), masterID,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
@@ -396,7 +281,7 @@ TrafficGen::parseConfig()
nbr_of_banks_DRAM,
nbr_of_banks_util,
addr_mapping,
- nbr_of_ranks);
+ nbr_of_ranks));
DPRINTF(TrafficGen, "State: %d DramGen\n", id);
} else {
// Will rotate to the next rank after rotating
@@ -407,7 +292,7 @@ TrafficGen::parseConfig()
(read_percent == 50) ? nbr_of_banks_util * 2
: nbr_of_banks_util;
- states[id] = new DramRotGen(name(), masterID,
+ states[id].reset(new DramRotGen(name(), masterID,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
@@ -417,7 +302,7 @@ TrafficGen::parseConfig()
nbr_of_banks_util,
addr_mapping,
nbr_of_ranks,
- max_seq_count_per_rank);
+ max_seq_count_per_rank));
DPRINTF(TrafficGen, "State: %d DramRotGen\n", id);
}
}
@@ -478,13 +363,9 @@ TrafficGen::parseConfig()
infile.close();
}
-void
-TrafficGen::transition()
+size_t
+TrafficGen::nextState()
{
- // exit the current state
- states[currState]->exit();
-
- // determine next state
double p = random_mt.random<double>();
assert(currState < transitionMatrix.size());
double cumulative = 0.0;
@@ -494,87 +375,17 @@ TrafficGen::transition()
++i;
} while (cumulative < p && i < transitionMatrix[currState].size());
- enterState(i - 1);
-}
-
-void
-TrafficGen::enterState(uint32_t newState)
-{
- DPRINTF(TrafficGen, "Transition to state %d\n", newState);
-
- currState = newState;
- // we could have been delayed and not transitioned on the exact
- // tick when we were supposed to (due to back pressure when
- // sending a packet)
- nextTransitionTick = curTick() + states[currState]->duration;
- states[currState]->enter();
-}
-
-void
-TrafficGen::recvReqRetry()
-{
- assert(retryPkt != NULL);
-
- DPRINTF(TrafficGen, "Received retry\n");
- numRetries++;
- // attempt to send the packet, and if we are successful start up
- // the machinery again
- if (port.sendTimingReq(retryPkt)) {
- retryPkt = NULL;
- // remember how much delay was incurred due to back-pressure
- // 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 (drainState() != DrainState::Draining) {
- // packet is sent, so find out when the next one is due
- nextPacketTick = states[currState]->nextPacketTick(elasticReq,
- delay);
- Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
- schedule(updateEvent, std::max(curTick(), nextEventTick));
- } else {
- // shut things down
- nextPacketTick = MaxTick;
- nextTransitionTick = MaxTick;
- signalDrainDone();
- }
- }
-}
-
-void
-TrafficGen::noProgress()
-{
- fatal("TrafficGen %s spent %llu ticks without making progress",
- name(), progressCheck);
-}
-
-void
-TrafficGen::regStats()
-{
- ClockedObject::regStats();
-
- // Initialise all the stats
- using namespace Stats;
-
- numPackets
- .name(name() + ".numPackets")
- .desc("Number of packets generated");
-
- numRetries
- .name(name() + ".numRetries")
- .desc("Number of retries");
-
- retryTicks
- .name(name() + ".retryTicks")
- .desc("Time spent waiting due to back-pressure (ticks)");
+ return i - 1;
}
-bool
-TrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
+std::shared_ptr<BaseGen>
+TrafficGen::nextGenerator()
{
- delete pkt;
+ // Return the initial state if there isn't an active generator,
+ // otherwise perform a state transition.
+ if (activeGenerator)
+ currState = nextState();
- return true;
+ DPRINTF(TrafficGen, "Transition to state %d\n", currState);
+ return states[currState];
}