cpu: Fold together the StateGraph and the TrafficGen

This patch simplifies the object hierarchy of the traffic generator by
getting rid of the StateGraph class and folding this functionality
into the traffic generator itself.

The main goal of this patch is to facilitate upcoming changes by
reducing the number of affected layers.
This commit is contained in:
Andreas Hansson 2013-05-30 12:54:03 -04:00
parent 7e13c4d046
commit ba11a02cf2
2 changed files with 98 additions and 163 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 ARM Limited
* Copyright (c) 2012-2013 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -54,10 +54,11 @@ TrafficGen::TrafficGen(const TrafficGenParams* p)
: MemObject(p),
system(p->system),
masterID(system->getMasterId(name())),
nextTransitionTick(0),
port(name() + ".port", *this),
stateGraph(*this, port, p->config_file, masterID),
updateStateGraphEvent(this)
updateEvent(this)
{
parseConfig(p->config_file, masterID);
}
TrafficGen*
@ -87,7 +88,7 @@ TrafficGen::init()
DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
// enter initial state
stateGraph.enterState(stateGraph.currState);
enterState(currState);
} else {
DPRINTF(TrafficGen,
"Traffic generator is only active in timing mode\n");
@ -99,8 +100,7 @@ TrafficGen::initState()
{
// when not restoring from a checkpoint, make sure we kick things off
if (system->isTimingMode()) {
Tick nextStateGraphEvent = stateGraph.nextEventTick();
schedule(updateStateGraphEvent, nextStateGraphEvent);
schedule(updateEvent, nextEventTick());
} else {
DPRINTF(TrafficGen,
"Traffic generator is only active in timing mode\n");
@ -121,15 +121,14 @@ TrafficGen::serialize(ostream &os)
DPRINTF(Checkpoint, "Serializing TrafficGen\n");
// save ticks of the graph event if it is scheduled
Tick nextStateGraphEvent = updateStateGraphEvent.scheduled() ?
updateStateGraphEvent.when() : 0;
Tick nextEvent = updateEvent.scheduled() ?
updateEvent.when() : 0;
DPRINTF(TrafficGen, "Saving nextStateGraphEvent=%llu\n",
nextStateGraphEvent);
DPRINTF(TrafficGen, "Saving nextEvent=%llu\n",
nextEvent);
SERIALIZE_SCALAR(nextStateGraphEvent);
SERIALIZE_SCALAR(nextEvent);
Tick nextTransitionTick = stateGraph.nextTransitionTick;
SERIALIZE_SCALAR(nextTransitionTick);
// @todo: also serialise the current state, figure out the best
@ -140,34 +139,39 @@ void
TrafficGen::unserialize(Checkpoint* cp, const string& section)
{
// restore scheduled events
Tick nextStateGraphEvent;
UNSERIALIZE_SCALAR(nextStateGraphEvent);
if (nextStateGraphEvent != 0) {
schedule(updateStateGraphEvent, nextStateGraphEvent);
Tick nextEvent;
UNSERIALIZE_SCALAR(nextEvent);
if (nextEvent != 0) {
schedule(updateEvent, nextEvent);
}
Tick nextTransitionTick;
UNSERIALIZE_SCALAR(nextTransitionTick);
stateGraph.nextTransitionTick = nextTransitionTick;
}
void
TrafficGen::updateStateGraph()
TrafficGen::update()
{
// schedule next update event based on either the next execute
// tick or the next transition, which ever comes first
Tick nextStateGraphEvent = stateGraph.nextEventTick();
Tick nextEvent = nextEventTick();
DPRINTF(TrafficGen, "Updating state graph, next event at %lld\n",
nextStateGraphEvent);
schedule(updateStateGraphEvent, nextStateGraphEvent);
nextEvent);
schedule(updateEvent, nextEvent);
// perform the update associated with the current update event
stateGraph.update();
// if we have reached the time for the next state transition, then
// perform the transition
if (curTick() >= nextTransitionTick) {
transition();
} else {
// we are still in the current state and should execute it
states[currState]->execute();
}
}
void
TrafficGen::StateGraph::parseConfig(const string& file_name,
MasterID master_id)
TrafficGen::parseConfig(const string& file_name, MasterID master_id)
{
// keep track of the transitions parsed to create the matrix when
// done
@ -178,7 +182,7 @@ TrafficGen::StateGraph::parseConfig(const string& file_name,
infile.open(file_name.c_str(), ifstream::in);
if (!infile.is_open()) {
fatal("Traffic generator %s config file not found at %s\n",
owner.name(), file_name);
name(), file_name);
}
// read line by line and determine the action based on the first
@ -302,20 +306,7 @@ TrafficGen::StateGraph::parseConfig(const string& file_name,
}
void
TrafficGen::StateGraph::update()
{
// if we have reached the time for the next state transition, then
// perform the transition
if (curTick() >= nextTransitionTick) {
transition();
} else {
// we are still in the current state and should execute it
states[currState]->execute();
}
}
void
TrafficGen::StateGraph::transition()
TrafficGen::transition()
{
// exit the current state
states[currState]->exit();
@ -334,7 +325,7 @@ TrafficGen::StateGraph::transition()
}
void
TrafficGen::StateGraph::enterState(uint32_t newState)
TrafficGen::enterState(uint32_t newState)
{
DPRINTF(TrafficGen, "Transition to state %d\n", newState);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 ARM Limited
* Copyright (c) 2012-2013 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@ -49,18 +49,65 @@
/**
* The traffic generator is a master module that generates stimuli for
* the memory system, based on a collection of simple behaviours that
* are either probabilistic or based on traces. It can be used stand
* alone for creating test cases for interconnect and memory
* controllers, or function as a black box replacement for system
* components that are not yet modelled in detail, e.g. a video engine
* or baseband subsystem.
* the memory system, based on a collection of simple generator
* behaviours that are either probabilistic or based on traces. It can
* be used stand alone for creating test cases for interconnect and
* memory controllers, or function as a black box replacement for
* system components that are not yet modelled in detail, e.g. a video
* engine or baseband subsystem.
*/
class TrafficGen : public MemObject
{
private:
/**
* Determine next state and perform the transition.
*/
void transition();
/**
* Enter a new state.
*
* @param newState identifier of state to enter
*/
void enterState(uint32_t newState);
/**
* Get the tick of the next event, either an execution or a
* transition.
*
* @return tick of the next update event
*/
Tick nextEventTick()
{
return std::min(states[currState]->nextExecuteTick(),
nextTransitionTick);
}
/**
* Parse the config file and build the state map and
* transition matrix.
*
* @param file_name Config file name to parse
* @param master_id MasterID to use for generated requests
*/
void parseConfig(const std::string& file_name, MasterID master_id);
/**
* Schedules event for next update and executes an update on the
* state graph, either performing a state transition or executing
* the current state, depending on the current time.
*/
void update();
/** Struct to represent a probabilistic transition during parsing. */
struct Transition {
uint32_t from;
uint32_t to;
double p;
};
/**
* The system used to determine which mode we are currently operating
* in.
@ -72,113 +119,19 @@ class TrafficGen : public MemObject
*/
MasterID masterID;
protected:
/** Time of next transition */
Tick nextTransitionTick;
/**
* The state graph is responsible for instantiating and keeping
* track of the various generator states and also perform the
* transitions and call the appropriate functions when entering,
* executing and exiting a state.
*/
class StateGraph
{
/** State transition matrix */
std::vector<std::vector<double> > transitionMatrix;
public:
/** Index of the current state */
uint32_t currState;
/**
* Create a state graph from an input file.
*
* @param _owner used solely for the name
* @param _port port used to send requests
* @param file_name configuration description to read in
* @param master_id the unique id used for all requests
*/
StateGraph(TrafficGen& _owner, QueuedMasterPort& _port,
const std::string& file_name, MasterID master_id)
: nextTransitionTick(0), owner(_owner), port(_port)
{
parseConfig(file_name, master_id);
}
/** Map of generator states */
m5::hash_map<uint32_t, BaseGen*> states;
/**
* Get the name, used for DPRINTFs.
*
* @return the owner's name
*/
std::string name() const { return owner.name(); }
/**
* Either perform a state transition or execute the current
* state, depending on the current time.
*/
void update();
/**
* Determine next state and perform the transition.
*/
void transition();
/**
* Enter a new state.
*
* @param newState identifier of state to enter
*/
void enterState(uint32_t newState);
/**
* Get the tick of the next event, either an execution or a
* transition.
*
* @return tick of the next state graph event
*/
Tick nextEventTick()
{
return std::min(states[currState]->nextExecuteTick(),
nextTransitionTick);
}
/** Time of next transition */
Tick nextTransitionTick;
private:
/**
* Parse the config file and build the state map and
* transition matrix.
*
* @param file_name Config file name to parse
* @param master_id MasterID to use for generated requests
*/
void parseConfig(const std::string& file_name, MasterID master_id);
/** Struct to represent a probabilistic transition during parsing. */
struct Transition {
uint32_t from;
uint32_t to;
double p;
};
/** Pointer to owner of request handler */
TrafficGen& owner;
/** Pointer to request handler */
QueuedMasterPort& port;
/** State transition matrix */
std::vector<std::vector<double> > transitionMatrix;
public:
/** Index of the current state */
uint32_t currState;
/** Map of states */
m5::hash_map<uint32_t, BaseGen*> states;
};
/** Queued handler */
/** Queued master port */
class TrafficGenPort : public QueuedMasterPort
{
public:
@ -197,20 +150,11 @@ class TrafficGen : public MemObject
};
/** The instance of master port used by the traffic generator. */
TrafficGenPort port;
/** Request generator state graph */
StateGraph stateGraph;
/**
* Schedules event for next update and executes an update on the
* state graph.
*/
void updateStateGraph();
/** Event for updating the state graph */
EventWrapper<TrafficGen,
&TrafficGen::updateStateGraph> updateStateGraphEvent;
/** Event for scheduling updates */
EventWrapper<TrafficGen, &TrafficGen::update> updateEvent;
public: