2 * Copyright (c) 2012 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 * Authors: Thomas Grass
41 #ifndef __MEM_TRAFFIC_GEN_HH__
42 #define __MEM_TRAFFIC_GEN_HH__
46 #include "base/hashmap.hh"
47 #include "mem/mem_object.hh"
48 #include "mem/qport.hh"
49 #include "params/TrafficGen.hh"
52 * The traffic generator is a master module that generates stimuli for
53 * the memory system, based on a collection of simple behaviours that
54 * are either probabilistic or based on traces. It can be used stand
55 * alone for creating test cases for interconnect and memory
56 * controllers, or function as a black box replacement for system
57 * components that are not yet modelled in detail, e.g. a video engine
58 * or baseband subsystem.
60 class TrafficGen : public MemObject
66 * The system used to determine which mode we are currently operating
72 * MasterID used in generated requests.
79 * The state graph is responsible for instantiating and keeping
80 * track of the various generator states and also perform the
81 * transitions and call the appropriate functions when entering,
82 * executing and exiting a state.
90 * Create a state graph from an input file.
92 * @param _owner used solely for the name
93 * @param _port port used to send requests
94 * @param file_name configuration description to read in
95 * @param master_id the unique id used for all requests
97 StateGraph(TrafficGen& _owner, QueuedMasterPort& _port,
98 const std::string& file_name, MasterID master_id)
99 : nextTransitionTick(0), owner(_owner), port(_port)
101 parseConfig(file_name, master_id);
105 * Get the name, used for DPRINTFs.
107 * @return the owner's name
109 std::string name() const { return owner.name(); }
112 * Either perform a state transition or execute the current
113 * state, depending on the current time.
118 * Determine next state and perform the transition.
125 * @param newState identifier of state to enter
127 void enterState(uint32_t newState);
130 * Get the tick of the next event, either an execution or a
133 * @return tick of the next state graph event
137 return std::min(states[currState]->nextExecuteTick(),
142 /** Time of next transition */
143 Tick nextTransitionTick;
148 * Parse the config file and build the state map and
151 * @param file_name Config file name to parse
152 * @param master_id MasterID to use for generated requests
154 void parseConfig(const std::string& file_name, MasterID master_id);
156 /** Struct to represent a probabilistic transition during parsing. */
163 /** Base class for all generator states */
169 /** Port used to send requests */
170 QueuedMasterPort& port;
172 /** The MasterID used for generating requests */
173 const MasterID masterID;
177 /** Time to spend in this state */
181 * Create a base generator.
183 * @param _port port used to send requests
184 * @param master_id MasterID set on each request
185 * @param _duration duration of this state before transitioning
187 BaseGen(QueuedMasterPort& _port, MasterID master_id,
190 virtual ~BaseGen() { }
193 * Get the name, useful for DPRINTFs.
195 * @return the port name
197 std::string name() const { return port.name(); }
200 * Enter this generator state.
202 virtual void enter() = 0;
205 * Execute this generator state.
207 virtual void execute() = 0;
210 * Exit this generator state. By default do nothing.
212 virtual void exit() { };
215 * Determine the next execute tick. MaxTick means that
216 * there will not be any further event in the current
217 * activation cycle of the state.
219 * @return next tick when the state should be executed
221 virtual Tick nextExecuteTick() = 0;
226 * The idle generator does nothing.
228 class IdleGen : public BaseGen
233 IdleGen(QueuedMasterPort& _port, MasterID master_id,
235 : BaseGen(_port, master_id, _duration)
242 Tick nextExecuteTick() { return MaxTick; }
246 * The linear generator generates sequential requests from a
247 * start to an end address, with a fixed block size. A
248 * fraction of the requests are reads, as determined by the
249 * read percent. There is an optional data limit for when to
250 * stop generating new requests.
252 class LinearGen : public BaseGen
258 * Create a linear address sequence generator. Set
259 * min_period == max_period for a fixed inter-transaction
262 * @param _port port used to send requests
263 * @param master_id MasterID set on each request
264 * @param _duration duration of this state before transitioning
265 * @param start_addr Start address
266 * @param end_addr End address
267 * @param _blocksize Size used for transactions injected
268 * @param min_period Lower limit of random inter-transaction time
269 * @param max_period Upper limit of random inter-transaction time
270 * @param read_percent Percent of transactions that are reads
271 * @param data_limit Upper limit on how much data to read/write
273 LinearGen(QueuedMasterPort& _port, MasterID master_id,
274 Tick _duration, Addr start_addr, Addr end_addr,
275 Addr _blocksize, Tick min_period, Tick max_period,
276 uint8_t read_percent, Addr data_limit)
277 : BaseGen(_port, master_id, _duration),
278 startAddr(start_addr), endAddr(end_addr),
279 blocksize(_blocksize), minPeriod(min_period),
280 maxPeriod(max_period), readPercent(read_percent),
281 dataLimit(data_limit)
288 Tick nextExecuteTick();
292 /** Start of address range */
293 const Addr startAddr;
295 /** End of address range */
298 /** Blocksize and address increment */
299 const Addr blocksize;
301 /** Request generation period */
302 const Tick minPeriod;
303 const Tick maxPeriod;
306 * Percent of generated transactions that should be reads
308 const uint8_t readPercent;
310 /** Maximum amount of data to manipulate */
311 const Addr dataLimit;
313 /** Address of next request */
317 * Counter to determine the amount of data
318 * manipulated. Used to determine if we should continue
319 * generating requests.
321 Addr dataManipulated;
325 * The random generator is similar to the linear one, but does
326 * not generate sequential addresses. Instead it randomly
327 * picks an address in the range, aligned to the block size.
329 class RandomGen : public BaseGen
335 * Create a random address sequence generator. Set
336 * min_period == max_period for a fixed inter-transaction
339 * @param _port port used to send requests
340 * @param master_id MasterID set on each request
341 * @param _duration duration of this state before transitioning
342 * @param start_addr Start address
343 * @param end_addr End address
344 * @param _blocksize Size used for transactions injected
345 * @param min_period Lower limit of random inter-transaction time
346 * @param max_period Upper limit of random inter-transaction time
347 * @param read_percent Percent of transactions that are reads
348 * @param data_limit Upper limit on how much data to read/write
350 RandomGen(QueuedMasterPort& _port, MasterID master_id,
351 Tick _duration, Addr start_addr, Addr end_addr,
352 Addr _blocksize, Tick min_period, Tick max_period,
353 uint8_t read_percent, Addr data_limit)
354 : BaseGen(_port, master_id, _duration),
355 startAddr(start_addr), endAddr(end_addr),
356 blocksize(_blocksize), minPeriod(min_period),
357 maxPeriod(max_period), readPercent(read_percent),
358 dataLimit(data_limit)
365 Tick nextExecuteTick();
369 /** Start of address range */
370 const Addr startAddr;
372 /** End of address range */
376 const Addr blocksize;
378 /** Request generation period */
379 const Tick minPeriod;
380 const Tick maxPeriod;
383 * Percent of generated transactions that should be reads
385 const uint8_t readPercent;
387 /** Maximum amount of data to manipulate */
388 const Addr dataLimit;
391 * Counter to determine the amount of data
392 * manipulated. Used to determine if we should continue
393 * generating requests.
395 Addr dataManipulated;
399 * The trace replay generator reads a trace file and plays
400 * back the transactions. The trace is offset with respect to
401 * the time when the state was entered.
403 class TraceGen : public BaseGen
409 * This struct stores a line in the trace file.
411 struct TraceElement {
413 /** Specifies if the request is to be a read or a write */
416 /** The address for the request */
419 /** The size of the access for the request */
422 /** The time at which the request should be sent */
426 * Check validity of this element.
428 * @return if this element is valid
430 bool isValid() const {
431 return cmd != MemCmd::InvalidCmd;
435 * Make this element invalid.
438 cmd = MemCmd::InvalidCmd;
445 * Create a trace generator.
447 * @param _port port used to send requests
448 * @param master_id MasterID set on each request
449 * @param _duration duration of this state before transitioning
450 * @param trace_file File to read the transactions from
451 * @param addr_offset Positive offset to add to trace address
453 TraceGen(QueuedMasterPort& _port, MasterID master_id,
454 Tick _duration, const std::string& trace_file,
456 : BaseGen(_port, master_id, _duration),
457 traceFile(trace_file),
458 addrOffset(addr_offset),
462 * Create a 4MB read buffer for the input trace
463 * file. This is to reduce the number of disk accesses
464 * and thereby speed up the execution of the code.
466 readBuffer = new char[4 * 1024 * 1024];
467 trace.rdbuf()->pubsetbuf(readBuffer, 4 * 1024 * 1024);
468 trace.open(traceFile.c_str(), std::ifstream::in);
470 if (!trace.is_open()) {
471 fatal("Traffic generator %s trace file could not be"
472 " opened: %s\n", name(), traceFile);
477 // free the memory used by the readBuffer
488 * Read a line of the trace file. Returns the raw tick
489 * when the next request should be generated. If the end
490 * of the file has been reached, it returns MaxTick to
491 * indicate that there will be no more requests.
493 Tick nextExecuteTick();
497 /** Path to the trace file */
498 std::string traceFile;
500 /** Input stream used for reading the input trace file */
503 /** Larger buffer used for reading from the stream */
506 /** Store the current and next element in the trace */
507 TraceElement currElement;
508 TraceElement nextElement;
511 * Stores the time when the state was entered. This is to add an
512 * offset to the times stored in the trace file.
517 * Offset for memory requests. Used to shift the trace
518 * away from the CPU address space.
523 * Set to true when the trace replay for one instance of
529 * Used to store the Tick when the next generate should
530 * occur. It is to remove a transaction as soon as we
536 /** Pointer to owner of request handler */
539 /** Pointer to request handler */
540 QueuedMasterPort& port;
542 /** State transition matrix */
543 std::vector<std::vector<double> > transitionMatrix;
547 /** Index of the current state */
551 m5::hash_map<uint32_t, BaseGen*> states;
555 /** Queued handler */
556 class TrafficGenPort : public QueuedMasterPort
560 TrafficGenPort(const std::string& name, TrafficGen& _owner)
561 : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this),
567 bool recvTimingResp(PacketPtr pkt);
571 MasterPacketQueue queue;
580 /** Request generator state graph */
581 StateGraph stateGraph;
584 * Schedules event for next update and executes an update on the
587 void updateStateGraph();
589 /** Event for updating the state graph */
590 EventWrapper<TrafficGen,
591 &TrafficGen::updateStateGraph> updateStateGraphEvent;
596 TrafficGen(const TrafficGenParams* p);
600 virtual BaseMasterPort& getMasterPort(const std::string &if_name,
601 PortID idx = InvalidPortID);
607 unsigned int drain(DrainManager *dm);
609 void serialize(std::ostream &os);
611 void unserialize(Checkpoint* cp, const std::string& section);
615 #endif //__MEM_TRAFFIC_GEN_HH__