Permalink
Browse files

cpu: Add support for throttling the traffic generator

Add the parameter maxPendingRequests to the traffic generator. This
parameter controls the maximum number of outstanding memory
requests. Once this limit has been reached, the traffic generators
simply drops excess requests until a response has been received.

Traffic generators may check the return value of BaseGen::send() to
determine if a send request succeeded and retry the current address in
that case.
  • Loading branch information...
1 parent ed400ad commit 12f912fcdaf3e6acf7bfe6e81afec2789eecca6c @andysan committed Mar 15, 2013
View
3 src/cpu/testers/traffic_gen/TrafficGen.py
@@ -71,3 +71,6 @@ class TrafficGen(MemObject):
# System used to determine the mode of the memory system
system = Param.System(Parent.any, "System this generator is part of")
+
+ maxPendingRequests = Param.Unsigned(16, "Maximum number of pending " \
+ "memory accesses")
View
92 src/cpu/testers/traffic_gen/traffic_gen.cc
@@ -56,6 +56,7 @@ TrafficGen::TrafficGen(const TrafficGenParams* p)
system(p->system),
masterID(system->getMasterId(name())),
port(name() + ".port", *this),
+ pendingRequests(0), maxPendingRequests(p->maxPendingRequests),
stateGraph(*this, port, p->config_file, masterID),
updateStateGraphEvent(this)
{
@@ -152,6 +153,38 @@ TrafficGen::unserialize(Checkpoint* cp, const string& section)
stateGraph.nextTransitionTick = nextTransitionTick;
}
+bool
+TrafficGen::send(Addr addr, unsigned size, const MemCmd& cmd, uint8_t *data)
+{
+ if (pendingRequests < maxPendingRequests) {
+ // Create new request
+ Request::Flags flags;
+ Request *req = new Request(addr, size, flags, masterID);
+
+ // Embed it in a packet
+ PacketPtr pkt = new Packet(req, cmd);
+ pkt->dataDynamicArray(data);
+
+ ++pendingRequests;
+ port.schedTimingReq(pkt, curTick());
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool
+TrafficGen::recvTimingResp(PacketPtr pkt)
+{
+ assert(pendingRequests >= 1);
+ --pendingRequests;
+
+ delete pkt->req;
+ delete pkt;
+
+ return true;
+}
+
void
TrafficGen::updateStateGraph()
{
@@ -210,11 +243,11 @@ TrafficGen::StateGraph::parseConfig(const string& file_name,
is >> traceFile >> addrOffset;
- states[id] = new TraceGen(port, master_id, duration,
+ states[id] = new TraceGen(owner, 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(owner, duration);
DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
} else if (mode == "LINEAR" || mode == "RANDOM") {
uint32_t read_percent;
@@ -237,14 +270,14 @@ TrafficGen::StateGraph::parseConfig(const string& file_name,
panic("%s cannot have more than 100% reads", name());
if (mode == "LINEAR") {
- states[id] = new LinearGen(port, master_id,
+ states[id] = new LinearGen(owner,
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(owner,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
@@ -344,32 +377,25 @@ TrafficGen::StateGraph::enterState(uint32_t newState)
states[currState]->enter();
}
-TrafficGen::StateGraph::BaseGen::BaseGen(QueuedMasterPort& _port,
- MasterID master_id,
- Tick _duration)
- : port(_port), masterID(master_id), duration(_duration)
+TrafficGen::StateGraph::BaseGen::BaseGen(TrafficGen& _owner, Tick _duration)
+ : owner(_owner), duration(_duration)
{
}
-void
+bool
TrafficGen::StateGraph::BaseGen::send(Addr addr, unsigned size,
- const MemCmd& cmd)
+ const MemCmd& cmd)
{
- // Create new request
- Request::Flags flags;
- Request *req = new Request(addr, size, flags, masterID);
-
- // Embed it in a packet
- PacketPtr pkt = new Packet(req, cmd);
-
- uint8_t* pkt_data = new uint8_t[req->getSize()];
- pkt->dataDynamicArray(pkt_data);
+ uint8_t* pkt_data = new uint8_t[size];
+ if (cmd.isWrite())
+ memset(pkt_data, 0xA, size);
- if (cmd.isWrite()) {
- memset(pkt_data, 0xA, req->getSize());
+ if (!owner.send(addr, size, cmd, pkt_data)) {
+ delete[] pkt_data;
+ return false;
+ } else {
+ return true;
}
-
- port.schedTimingReq(pkt, curTick());
}
void
@@ -381,9 +407,10 @@ TrafficGen::StateGraph::LinearGen::enter()
// 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())
+ if (owner.port.deviceBlockSize() &&
+ blocksize > owner.port.deviceBlockSize())
fatal("TrafficGen %s block size (%d) is larger than port"
- " block size (%d)\n", blocksize, port.deviceBlockSize());
+ " block size (%d)\n", blocksize, owner.port.deviceBlockSize());
}
@@ -441,9 +468,11 @@ TrafficGen::StateGraph::RandomGen::enter()
// 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())
+ if (owner.port.deviceBlockSize() &&
+ blocksize > owner.port.deviceBlockSize())
fatal("TrafficGen %s block size (%d) is larger than port"
- " block size (%d)\n", name(), blocksize, port.deviceBlockSize());
+ " block size (%d)\n", name(), blocksize,
+ owner.port.deviceBlockSize());
}
void
@@ -607,12 +636,3 @@ TrafficGen::StateGraph::TraceGen::exit() {
// file
trace.reset();
}
-
-bool
-TrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
-{
- delete pkt->req;
- delete pkt;
-
- return true;
-}
View
94 src/cpu/testers/traffic_gen/traffic_gen.hh
@@ -164,22 +164,23 @@ class TrafficGen : public MemObject
{
protected:
-
- /** Port used to send requests */
- QueuedMasterPort& port;
-
- /** 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.
*
+ * @note This method may return false to indicate that a packet
+ * couldn't be delivered because the maximum number of outstanding
+ * memory requests has been reached.
+ *
* @param addr Physical address to use
* @param size Size of the request
* @param cmd Memory command to send
+ * @return True if the request was sent, false otherwise.
*/
- void send(Addr addr, unsigned size, const MemCmd& cmd);
+ bool send(Addr addr, unsigned size, const MemCmd& cmd);
+
+ /** Pointer to owner of generator */
+ TrafficGen& owner;
public:
@@ -189,12 +190,10 @@ class TrafficGen : public MemObject
/**
* Create a base generator.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @param _duration duration of this state before transitioning
*/
- BaseGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration);
+ BaseGen(TrafficGen& _owner, Tick _duration);
virtual ~BaseGen() { }
@@ -203,7 +202,7 @@ class TrafficGen : public MemObject
*
* @return the port name
*/
- std::string name() const { return port.name(); }
+ std::string name() const { return owner.name(); }
/**
* Enter this generator state.
@@ -239,9 +238,8 @@ class TrafficGen : public MemObject
public:
- IdleGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration)
- : BaseGen(_port, master_id, _duration)
+ IdleGen(TrafficGen& _owner, Tick _duration)
+ : BaseGen(_owner, _duration)
{ }
void enter() { }
@@ -268,8 +266,7 @@ class TrafficGen : public MemObject
* min_period == max_period for a fixed inter-transaction
* time.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @param _duration duration of this state before transitioning
* @param start_addr Start address
* @param end_addr End address
@@ -279,11 +276,11 @@ class TrafficGen : public MemObject
* @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,
+ LinearGen(TrafficGen& _owner, 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(_owner, _duration),
startAddr(start_addr), endAddr(end_addr),
blocksize(_blocksize), minPeriod(min_period),
maxPeriod(max_period), readPercent(read_percent),
@@ -345,8 +342,7 @@ class TrafficGen : public MemObject
* min_period == max_period for a fixed inter-transaction
* time.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @param _duration duration of this state before transitioning
* @param start_addr Start address
* @param end_addr End address
@@ -356,11 +352,11 @@ class TrafficGen : public MemObject
* @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,
+ RandomGen(TrafficGen& _owner, 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(_owner, _duration),
startAddr(start_addr), endAddr(end_addr),
blocksize(_blocksize), minPeriod(min_period),
maxPeriod(max_period), readPercent(read_percent),
@@ -492,16 +488,15 @@ class TrafficGen : public MemObject
/**
* Create a trace generator.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @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,
+ TraceGen(TrafficGen& _owner, Tick _duration,
+ const std::string& trace_file,
Addr addr_offset)
- : BaseGen(_port, master_id, _duration),
+ : BaseGen(_owner, _duration),
trace(trace_file),
addrOffset(addr_offset),
traceComplete(false)
@@ -575,21 +570,52 @@ class TrafficGen : public MemObject
public:
TrafficGenPort(const std::string& name, TrafficGen& _owner)
- : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this)
+ : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this),
+ owner(_owner)
{ }
protected:
- bool recvTimingResp(PacketPtr pkt);
+ bool recvTimingResp(PacketPtr pkt) {
+ return owner.recvTimingResp(pkt);
+ }
private:
MasterPacketQueue queue;
-
+ TrafficGen &owner;
};
+ /**
+ * Create a new request and associated packet and schedule it to
+ * be sent in the current tick.
+ *
+ * @note This method may return false to indicate that a packet
+ * couldn't be delivered because the maximum number of outstanding
+ * memory requests has been reached.
+ *
+ * @param addr Request address
+ * @param size Request size
+ * @param cmd Memory command
+ * @param data Dynamic array of data associated with the packet.
+ * @return True if the request was sent, false otherwise.
+ */
+ bool send(Addr addr, unsigned size, const MemCmd& cmd, uint8_t *data);
+
+ /**
+ * Handle a timing response from the memory system.
+ *
+ * @see MasterPort::recvTimingResp()
+ */
+ bool recvTimingResp(PacketPtr pkt);
+
TrafficGenPort port;
+ /** Number of requests still pending in the memory system */
+ unsigned pendingRequests;
+ /** Maximum number of pending requests */
+ const unsigned maxPendingRequests;
+
/** Request generator state graph */
StateGraph stateGraph;

0 comments on commit 12f912f

Please sign in to comment.