*/
#include "base/random.hh"
+#include "base/trace.hh"
#include "cpu/testers/traffic_gen/generators.hh"
#include "debug/TrafficGen.hh"
#include "proto/packet.pb.h"
-BaseGen::BaseGen(QueuedMasterPort& _port, MasterID master_id, Tick _duration)
- : port(_port), masterID(master_id), duration(_duration)
+BaseGen::BaseGen(const std::string& _name, MasterID master_id, Tick _duration)
+ : _name(_name), masterID(master_id), duration(_duration)
{
}
-void
-BaseGen::send(Addr addr, unsigned size, const MemCmd& cmd,
- Request::FlagsType flags)
+PacketPtr
+BaseGen::getPacket(Addr addr, unsigned size, const MemCmd& cmd,
+ Request::FlagsType flags)
{
// Create new request
Request *req = new Request(addr, size, flags, masterID);
memset(pkt_data, 0xA, req->getSize());
}
- port.schedTimingReq(pkt, curTick());
+ return pkt;
}
void
// reset the address and the data counter
nextAddr = startAddr;
dataManipulated = 0;
-
- // this test only needs to happen once, but cannot be performed
- // before init() is called and the ports are connected
- if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
- fatal("TrafficGen %s block size (%d) is larger than port"
- " block size (%d)\n", blocksize, port.deviceBlockSize());
}
-void
-LinearGen::execute()
+PacketPtr
+LinearGen::getNextPacket()
{
// choose if we generate a read or a write here
bool isRead = readPercent != 0 &&
assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) ||
readPercent != 100);
- DPRINTF(TrafficGen, "LinearGen::execute: %c to addr %x, size %d\n",
+ DPRINTF(TrafficGen, "LinearGen::getNextPacket: %c to addr %x, size %d\n",
isRead ? 'r' : 'w', nextAddr, blocksize);
- send(nextAddr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
+ // Add the amount of data manipulated to the total
+ dataManipulated += blocksize;
+
+ PacketPtr pkt = getPacket(nextAddr, blocksize,
+ isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
// increment the address
nextAddr += blocksize;
- // Add the amount of data manipulated to the total
- dataManipulated += blocksize;
+ return pkt;
}
Tick
-LinearGen::nextExecuteTick()
+LinearGen::nextPacketTick()
{
// If we have reached the end of the address space, reset the
// address to the start of the range
{
// reset the counter to zero
dataManipulated = 0;
-
- // this test only needs to happen once, but cannot be performed
- // before init() is called and the ports are connected
- if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
- fatal("TrafficGen %s block size (%d) is larger than port"
- " block size (%d)\n", blocksize, port.deviceBlockSize());
}
-void
-RandomGen::execute()
+PacketPtr
+RandomGen::getNextPacket()
{
// choose if we generate a read or a write here
bool isRead = readPercent != 0 &&
// round down to start address of block
addr -= addr % blocksize;
- DPRINTF(TrafficGen, "RandomGen::execute: %c to addr %x, size %d\n",
+ DPRINTF(TrafficGen, "RandomGen::getNextPacket: %c to addr %x, size %d\n",
isRead ? 'r' : 'w', addr, blocksize);
- // send a new request packet
- send(addr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
-
- // Add the amount of data manipulated to the total
+ // add the amount of data manipulated to the total
dataManipulated += blocksize;
+
+ // create a new request packet
+ return getPacket(addr, blocksize,
+ isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
}
Tick
-RandomGen::nextExecuteTick()
+RandomGen::nextPacketTick()
{
// 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
}
Tick
-TraceGen::nextExecuteTick() {
+TraceGen::nextPacketTick() {
if (traceComplete)
// We are at the end of the file, thus we have no more data in
// the trace Return MaxTick to signal that there will be no
traceComplete = false;
}
-void
-TraceGen::execute()
+PacketPtr
+TraceGen::getNextPacket()
{
- // it is the responsibility of nextExecuteTick to prevent the
+ // it is the responsibility of nextPacketTick to prevent the
// state graph from executing the state if it should not
assert(currElement.isValid());
- DPRINTF(TrafficGen, "TraceGen::execute: %c %d %d %d 0x%x\n",
+ DPRINTF(TrafficGen, "TraceGen::getNextPacket: %c %d %d %d 0x%x\n",
currElement.cmd.isRead() ? 'r' : 'w',
currElement.addr,
currElement.blocksize,
currElement.tick,
currElement.flags);
- send(currElement.addr + addrOffset, currElement.blocksize,
- currElement.cmd, currElement.flags);
+ return getPacket(currElement.addr + addrOffset, currElement.blocksize,
+ currElement.cmd, currElement.flags);
}
void
#ifndef __CPU_TRAFFIC_GEN_GENERATORS_HH__
#define __CPU_TRAFFIC_GEN_GENERATORS_HH__
-#include "mem/qport.hh"
+#include "mem/packet.hh"
#include "proto/protoio.hh"
/**
protected:
- /** Port used to send requests */
- QueuedMasterPort& port;
+ /** Name to use for status and debug printing */
+ const std::string _name;
/** The MasterID used for generating requests */
const MasterID masterID;
/**
- * Create a new request and associated packet and schedule
- * it to be sent in the current tick.
+ * Generate a new request and associated packet
*
* @param addr Physical address to use
* @param size Size of the request
* @param cmd Memory command to send
* @param flags Optional request flags
*/
- void send(Addr addr, unsigned size, const MemCmd& cmd,
- Request::FlagsType flags = 0);
+ PacketPtr getPacket(Addr addr, unsigned size, const MemCmd& cmd,
+ Request::FlagsType flags = 0);
public:
/**
* Create a base generator.
*
- * @param _port port used to send requests
+ * @param _name Name to use for status and debug
* @param master_id MasterID set on each request
* @param _duration duration of this state before transitioning
*/
- BaseGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration);
+ BaseGen(const std::string& _name, MasterID master_id, Tick _duration);
virtual ~BaseGen() { }
/**
* Get the name, useful for DPRINTFs.
*
- * @return the port name
+ * @return the given name
*/
- std::string name() const { return port.name(); }
+ std::string name() const { return _name; }
/**
* Enter this generator state.
virtual void enter() = 0;
/**
- * Execute this generator state.
+ * Get the next generated packet.
+ *
+ * @return A packet to be sent at the current tick
*/
- virtual void execute() = 0;
+ virtual PacketPtr getNextPacket() = 0;
/**
* Exit this generator state. By default do nothing.
virtual void exit() { };
/**
- * Determine the next execute tick. MaxTick means that
- * there will not be any further event in the current
- * activation cycle of the state.
+ * Determine the tick when the next packet is available. MaxTick
+ * means that there will not be any further packets in the current
+ * activation cycle of the generator.
*
- * @return next tick when the state should be executed
+ * @return next tick when a packet is available
*/
- virtual Tick nextExecuteTick() = 0;
+ virtual Tick nextPacketTick() = 0;
};
public:
- IdleGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration)
- : BaseGen(_port, master_id, _duration)
+ IdleGen(const std::string& _name, MasterID master_id, Tick _duration)
+ : BaseGen(_name, master_id, _duration)
{ }
void enter() { }
- void execute() { }
+ PacketPtr getNextPacket() { return NULL; }
- Tick nextExecuteTick() { return MaxTick; }
+ Tick nextPacketTick() { return MaxTick; }
};
/**
* min_period == max_period for a fixed inter-transaction
* time.
*
- * @param _port port used to send requests
+ * @param _name Name to use for status and debug
* @param master_id MasterID set on each request
* @param _duration duration of this state before transitioning
* @param start_addr Start address
* @param read_percent Percent of transactions that are reads
* @param data_limit Upper limit on how much data to read/write
*/
- LinearGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration, Addr start_addr, Addr end_addr,
- Addr _blocksize, Tick min_period, Tick max_period,
+ LinearGen(const std::string& _name, MasterID master_id, Tick _duration,
+ Addr start_addr, Addr end_addr, Addr _blocksize,
+ Tick min_period, Tick max_period,
uint8_t read_percent, Addr data_limit)
- : BaseGen(_port, master_id, _duration),
+ : BaseGen(_name, master_id, _duration),
startAddr(start_addr), endAddr(end_addr),
blocksize(_blocksize), minPeriod(min_period),
maxPeriod(max_period), readPercent(read_percent),
void enter();
- void execute();
+ PacketPtr getNextPacket();
- Tick nextExecuteTick();
+ Tick nextPacketTick();
private:
* min_period == max_period for a fixed inter-transaction
* time.
*
- * @param _port port used to send requests
+ * @param _name Name to use for status and debug
* @param master_id MasterID set on each request
* @param _duration duration of this state before transitioning
* @param start_addr Start address
* @param read_percent Percent of transactions that are reads
* @param data_limit Upper limit on how much data to read/write
*/
- RandomGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration, Addr start_addr, Addr end_addr,
- Addr _blocksize, Tick min_period, Tick max_period,
+ RandomGen(const std::string& _name, MasterID master_id, Tick _duration,
+ Addr start_addr, Addr end_addr, Addr _blocksize,
+ Tick min_period, Tick max_period,
uint8_t read_percent, Addr data_limit)
- : BaseGen(_port, master_id, _duration),
+ : BaseGen(_name, master_id, _duration),
startAddr(start_addr), endAddr(end_addr),
blocksize(_blocksize), minPeriod(min_period),
maxPeriod(max_period), readPercent(read_percent),
void enter();
- void execute();
+ PacketPtr getNextPacket();
- Tick nextExecuteTick();
+ Tick nextPacketTick();
private:
/**
* Create a trace generator.
*
- * @param _port port used to send requests
+ * @param _name Name to use for status and debug
* @param master_id MasterID set on each request
* @param _duration duration of this state before transitioning
* @param trace_file File to read the transactions from
* @param addr_offset Positive offset to add to trace address
*/
- TraceGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration, const std::string& trace_file,
- Addr addr_offset)
- : BaseGen(_port, master_id, _duration),
+ TraceGen(const std::string& _name, MasterID master_id, Tick _duration,
+ const std::string& trace_file, Addr addr_offset)
+ : BaseGen(_name, master_id, _duration),
trace(trace_file),
addrOffset(addr_offset),
traceComplete(false)
void enter();
- void execute();
+ PacketPtr getNextPacket();
void exit();
* of the file has been reached, it returns MaxTick to
* indicate that there will be no more requests.
*/
- Tick nextExecuteTick();
+ Tick nextPacketTick();
private:
: MemObject(p),
system(p->system),
masterID(system->getMasterId(name())),
+ configFile(p->config_file),
nextTransitionTick(0),
port(name() + ".port", *this),
updateEvent(this)
{
- parseConfig(p->config_file, masterID);
}
TrafficGen*
if (system->isTimingMode()) {
DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
+ parseConfig();
+
// enter initial state
enterState(currState);
} else {
transition();
} else {
// we are still in the current state and should execute it
- states[currState]->execute();
+ PacketPtr pkt = states[currState]->getNextPacket();
+ port.schedTimingReq(pkt, curTick());
}
}
void
-TrafficGen::parseConfig(const string& file_name, MasterID master_id)
+TrafficGen::parseConfig()
{
// keep track of the transitions parsed to create the matrix when
// done
// open input file
ifstream infile;
- infile.open(file_name.c_str(), ifstream::in);
+ infile.open(configFile.c_str(), ifstream::in);
if (!infile.is_open()) {
fatal("Traffic generator %s config file not found at %s\n",
- name(), file_name);
+ name(), configFile);
}
// read line by line and determine the action based on the first
is >> traceFile >> addrOffset;
- states[id] = new TraceGen(port, master_id, duration,
+ states[id] = new TraceGen(name(), masterID, duration,
traceFile, addrOffset);
DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
} else if (mode == "IDLE") {
- states[id] = new IdleGen(port, master_id, duration);
+ states[id] = new IdleGen(name(), masterID, duration);
DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
} else if (mode == "LINEAR" || mode == "RANDOM") {
uint32_t read_percent;
mode, start_addr, end_addr, blocksize, min_period,
max_period, read_percent);
+
+ if (port.deviceBlockSize() &&
+ blocksize > port.deviceBlockSize())
+ fatal("TrafficGen %s block size (%d) is larger than "
+ "port block size (%d)\n", name(),
+ blocksize, port.deviceBlockSize());
+
if (read_percent > 100)
- panic("%s cannot have more than 100% reads", name());
+ fatal("%s cannot have more than 100% reads", name());
if (mode == "LINEAR") {
- states[id] = new LinearGen(port, master_id,
+ states[id] = new LinearGen(name(), masterID,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
read_percent, data_limit);
DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
} else if (mode == "RANDOM") {
- states[id] = new RandomGen(port, master_id,
+ states[id] = new RandomGen(name(), masterID,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
void enterState(uint32_t newState);
/**
- * Get the tick of the next event, either an execution or a
+ * Get the tick of the next event, either a new packet or a
* transition.
*
* @return tick of the next update event
*/
Tick nextEventTick()
{
- return std::min(states[currState]->nextExecuteTick(),
+ return std::min(states[currState]->nextPacketTick(),
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);
+ void parseConfig();
/**
* Schedules event for next update and executes an update on the
*/
MasterID masterID;
+ /**
+ * The config file to parse.
+ */
+ const std::string configFile;
+
/** Time of next transition */
Tick nextTransitionTick;