Deleted Added
sdiff udiff text old ( 9402:f6e3c60f04e5 ) new ( 9403:af9066bc088c )
full compact
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
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.
13 *
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.
24 *
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.
36 *
37 * Authors: Thomas Grass
38 * Andreas Hansson
39 * Sascha Bischoff
40 */
41#ifndef __MEM_TRAFFIC_GEN_HH__
42#define __MEM_TRAFFIC_GEN_HH__
43
44#include "base/hashmap.hh"
45#include "mem/mem_object.hh"
46#include "mem/qport.hh"
47#include "params/TrafficGen.hh"
48#include "proto/protoio.hh"
49
50/**
51 * The traffic generator is a master module that generates stimuli for
52 * the memory system, based on a collection of simple behaviours that
53 * are either probabilistic or based on traces. It can be used stand
54 * alone for creating test cases for interconnect and memory
55 * controllers, or function as a black box replacement for system
56 * components that are not yet modelled in detail, e.g. a video engine
57 * or baseband subsystem.
58 */
59class TrafficGen : public MemObject
60{
61
62 private:
63
64 /**
65 * The system used to determine which mode we are currently operating
66 * in.
67 */
68 System* system;
69
70 /**
71 * MasterID used in generated requests.
72 */
73 MasterID masterID;
74
75 protected:
76
77 /**
78 * The state graph is responsible for instantiating and keeping
79 * track of the various generator states and also perform the
80 * transitions and call the appropriate functions when entering,
81 * executing and exiting a state.
82 */
83 class StateGraph
84 {
85
86 public:
87
88 /**
89 * Create a state graph from an input file.
90 *
91 * @param _owner used solely for the name
92 * @param _port port used to send requests
93 * @param file_name configuration description to read in
94 * @param master_id the unique id used for all requests
95 */
96 StateGraph(TrafficGen& _owner, QueuedMasterPort& _port,
97 const std::string& file_name, MasterID master_id)
98 : nextTransitionTick(0), owner(_owner), port(_port)
99 {
100 parseConfig(file_name, master_id);
101 }
102
103 /**
104 * Get the name, used for DPRINTFs.
105 *
106 * @return the owner's name
107 */
108 std::string name() const { return owner.name(); }
109
110 /**
111 * Either perform a state transition or execute the current
112 * state, depending on the current time.
113 */
114 void update();
115
116 /**
117 * Determine next state and perform the transition.
118 */
119 void transition();
120
121 /**
122 * Enter a new state.
123 *
124 * @param newState identifier of state to enter
125 */
126 void enterState(uint32_t newState);
127
128 /**
129 * Get the tick of the next event, either an execution or a
130 * transition.
131 *
132 * @return tick of the next state graph event
133 */
134 Tick nextEventTick()
135 {
136 return std::min(states[currState]->nextExecuteTick(),
137 nextTransitionTick);
138
139 }
140
141 /** Time of next transition */
142 Tick nextTransitionTick;
143
144 private:
145
146 /**
147 * Parse the config file and build the state map and
148 * transition matrix.
149 *
150 * @param file_name Config file name to parse
151 * @param master_id MasterID to use for generated requests
152 */
153 void parseConfig(const std::string& file_name, MasterID master_id);
154
155 /** Struct to represent a probabilistic transition during parsing. */
156 struct Transition {
157 uint32_t from;
158 uint32_t to;
159 double p;
160 };
161
162 /** Base class for all generator states */
163 class BaseGen
164 {
165
166 protected:
167
168 /** Port used to send requests */
169 QueuedMasterPort& port;
170
171 /** The MasterID used for generating requests */
172 const MasterID masterID;
173
174 public:
175
176 /** Time to spend in this state */
177 const Tick duration;
178
179 /**
180 * Create a base generator.
181 *
182 * @param _port port used to send requests
183 * @param master_id MasterID set on each request
184 * @param _duration duration of this state before transitioning
185 */
186 BaseGen(QueuedMasterPort& _port, MasterID master_id,
187 Tick _duration);
188
189 virtual ~BaseGen() { }
190
191 /**
192 * Get the name, useful for DPRINTFs.
193 *
194 * @return the port name
195 */
196 std::string name() const { return port.name(); }
197
198 /**
199 * Enter this generator state.
200 */
201 virtual void enter() = 0;
202
203 /**
204 * Execute this generator state.
205 */
206 virtual void execute() = 0;
207
208 /**
209 * Exit this generator state. By default do nothing.
210 */
211 virtual void exit() { };
212
213 /**
214 * Determine the next execute tick. MaxTick means that
215 * there will not be any further event in the current
216 * activation cycle of the state.
217 *
218 * @return next tick when the state should be executed
219 */
220 virtual Tick nextExecuteTick() = 0;
221
222 };
223
224 /**
225 * The idle generator does nothing.
226 */
227 class IdleGen : public BaseGen
228 {
229
230 public:
231
232 IdleGen(QueuedMasterPort& _port, MasterID master_id,
233 Tick _duration)
234 : BaseGen(_port, master_id, _duration)
235 { }
236
237 void enter() { }
238
239 void execute() { }
240
241 Tick nextExecuteTick() { return MaxTick; }
242 };
243
244 /**
245 * The linear generator generates sequential requests from a
246 * start to an end address, with a fixed block size. A
247 * fraction of the requests are reads, as determined by the
248 * read percent. There is an optional data limit for when to
249 * stop generating new requests.
250 */
251 class LinearGen : public BaseGen
252 {
253
254 public:
255
256 /**
257 * Create a linear address sequence generator. Set
258 * min_period == max_period for a fixed inter-transaction
259 * time.
260 *
261 * @param _port port used to send requests
262 * @param master_id MasterID set on each request
263 * @param _duration duration of this state before transitioning
264 * @param start_addr Start address
265 * @param end_addr End address
266 * @param _blocksize Size used for transactions injected
267 * @param min_period Lower limit of random inter-transaction time
268 * @param max_period Upper limit of random inter-transaction time
269 * @param read_percent Percent of transactions that are reads
270 * @param data_limit Upper limit on how much data to read/write
271 */
272 LinearGen(QueuedMasterPort& _port, MasterID master_id,
273 Tick _duration, Addr start_addr, Addr end_addr,
274 Addr _blocksize, Tick min_period, Tick max_period,
275 uint8_t read_percent, Addr data_limit)
276 : BaseGen(_port, master_id, _duration),
277 startAddr(start_addr), endAddr(end_addr),
278 blocksize(_blocksize), minPeriod(min_period),
279 maxPeriod(max_period), readPercent(read_percent),
280 dataLimit(data_limit)
281 { }
282
283 void enter();
284
285 void execute();
286
287 Tick nextExecuteTick();
288
289 private:
290
291 /** Start of address range */
292 const Addr startAddr;
293
294 /** End of address range */
295 const Addr endAddr;
296
297 /** Blocksize and address increment */
298 const Addr blocksize;
299
300 /** Request generation period */
301 const Tick minPeriod;
302 const Tick maxPeriod;
303
304 /**
305 * Percent of generated transactions that should be reads
306 */
307 const uint8_t readPercent;
308
309 /** Maximum amount of data to manipulate */
310 const Addr dataLimit;
311
312 /** Address of next request */
313 Addr nextAddr;
314
315 /**
316 * Counter to determine the amount of data
317 * manipulated. Used to determine if we should continue
318 * generating requests.
319 */
320 Addr dataManipulated;
321 };
322
323 /**
324 * The random generator is similar to the linear one, but does
325 * not generate sequential addresses. Instead it randomly
326 * picks an address in the range, aligned to the block size.
327 */
328 class RandomGen : public BaseGen
329 {
330
331 public:
332
333 /**
334 * Create a random address sequence generator. Set
335 * min_period == max_period for a fixed inter-transaction
336 * time.
337 *
338 * @param _port port used to send requests
339 * @param master_id MasterID set on each request
340 * @param _duration duration of this state before transitioning
341 * @param start_addr Start address
342 * @param end_addr End address
343 * @param _blocksize Size used for transactions injected
344 * @param min_period Lower limit of random inter-transaction time
345 * @param max_period Upper limit of random inter-transaction time
346 * @param read_percent Percent of transactions that are reads
347 * @param data_limit Upper limit on how much data to read/write
348 */
349 RandomGen(QueuedMasterPort& _port, MasterID master_id,
350 Tick _duration, Addr start_addr, Addr end_addr,
351 Addr _blocksize, Tick min_period, Tick max_period,
352 uint8_t read_percent, Addr data_limit)
353 : BaseGen(_port, master_id, _duration),
354 startAddr(start_addr), endAddr(end_addr),
355 blocksize(_blocksize), minPeriod(min_period),
356 maxPeriod(max_period), readPercent(read_percent),
357 dataLimit(data_limit)
358 { }
359
360 void enter();
361
362 void execute();
363
364 Tick nextExecuteTick();
365
366 private:
367
368 /** Start of address range */
369 const Addr startAddr;
370
371 /** End of address range */
372 const Addr endAddr;
373
374 /** Block size */
375 const Addr blocksize;
376
377 /** Request generation period */
378 const Tick minPeriod;
379 const Tick maxPeriod;
380
381 /**
382 * Percent of generated transactions that should be reads
383 */
384 const uint8_t readPercent;
385
386 /** Maximum amount of data to manipulate */
387 const Addr dataLimit;
388
389 /**
390 * Counter to determine the amount of data
391 * manipulated. Used to determine if we should continue
392 * generating requests.
393 */
394 Addr dataManipulated;
395 };
396
397 /**
398 * The trace replay generator reads a trace file and plays
399 * back the transactions. The trace is offset with respect to
400 * the time when the state was entered.
401 */
402 class TraceGen : public BaseGen
403 {
404
405 private:
406
407 /**
408 * This struct stores a line in the trace file.
409 */
410 struct TraceElement {
411
412 /** Specifies if the request is to be a read or a write */
413 MemCmd cmd;
414
415 /** The address for the request */
416 Addr addr;
417
418 /** The size of the access for the request */
419 Addr blocksize;
420
421 /** The time at which the request should be sent */
422 Tick tick;
423
424 /**
425 * Check validity of this element.
426 *
427 * @return if this element is valid
428 */
429 bool isValid() const {
430 return cmd != MemCmd::InvalidCmd;
431 }
432
433 /**
434 * Make this element invalid.
435 */
436 void clear() {
437 cmd = MemCmd::InvalidCmd;
438 }
439 };
440
441 /**
442 * The InputStream encapsulates a trace file and the
443 * internal buffers and populates TraceElements based on
444 * the input.
445 */
446 class InputStream
447 {
448
449 private:
450
451 /// Input file stream for the protobuf trace
452 ProtoInputStream trace;
453
454 public:
455
456 /**
457 * Create a trace input stream for a given file name.
458 *
459 * @param filename Path to the file to read from
460 */
461 InputStream(const std::string& filename);
462
463 /**
464 * Reset the stream such that it can be played once
465 * again.
466 */
467 void reset();
468
469 /**
470 * Attempt to read a trace element from the stream,
471 * and also notify the caller if the end of the file
472 * was reached.
473 *
474 * @param element Trace element to populate
475 * @return True if an element could be read successfully
476 */
477 bool read(TraceElement& element);
478 };
479
480 public:
481
482 /**
483 * Create a trace generator.
484 *
485 * @param _port port used to send requests
486 * @param master_id MasterID set on each request
487 * @param _duration duration of this state before transitioning
488 * @param trace_file File to read the transactions from
489 * @param addr_offset Positive offset to add to trace address
490 */
491 TraceGen(QueuedMasterPort& _port, MasterID master_id,
492 Tick _duration, const std::string& trace_file,
493 Addr addr_offset)
494 : BaseGen(_port, master_id, _duration),
495 trace(trace_file),
496 addrOffset(addr_offset),
497 traceComplete(false)
498 {
499 }
500
501 void enter();
502
503 void execute();
504
505 void exit();
506
507 /**
508 * Read a line of the trace file. Returns the raw tick
509 * when the next request should be generated. If the end
510 * of the file has been reached, it returns MaxTick to
511 * indicate that there will be no more requests.
512 */
513 Tick nextExecuteTick();
514
515 private:
516
517 /** Input stream used for reading the input trace file */
518 InputStream trace;
519
520 /** Store the current and next element in the trace */
521 TraceElement currElement;
522 TraceElement nextElement;
523
524 /**
525 * Stores the time when the state was entered. This is to add an
526 * offset to the times stored in the trace file.
527 */
528 Tick tickOffset;
529
530 /**
531 * Offset for memory requests. Used to shift the trace
532 * away from the CPU address space.
533 */
534 Addr addrOffset;
535
536 /**
537 * Set to true when the trace replay for one instance of
538 * state is complete.
539 */
540 bool traceComplete;
541
542 /**
543 * Used to store the Tick when the next generate should
544 * occur. It is to remove a transaction as soon as we
545 * enter the state.
546 */
547 Tick oldEmitTime;
548 };
549
550 /** Pointer to owner of request handler */
551 TrafficGen& owner;
552
553 /** Pointer to request handler */
554 QueuedMasterPort& port;
555
556 /** State transition matrix */
557 std::vector<std::vector<double> > transitionMatrix;
558
559 public:
560
561 /** Index of the current state */
562 uint32_t currState;
563
564 /** Map of states */
565 m5::hash_map<uint32_t, BaseGen*> states;
566 };
567
568
569 /** Queued handler */
570 class TrafficGenPort : public QueuedMasterPort
571 {
572 public:
573
574 TrafficGenPort(const std::string& name, TrafficGen& _owner)
575 : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this),
576 owner(_owner)
577 { }
578
579 protected:
580
581 bool recvTimingResp(PacketPtr pkt);
582
583 private:
584
585 MasterPacketQueue queue;
586
587 // Owner of the port
588 TrafficGen& owner;
589
590 };
591
592 TrafficGenPort port;
593
594 /** Request generator state graph */
595 StateGraph stateGraph;
596
597 /**
598 * Schedules event for next update and executes an update on the
599 * state graph.
600 */
601 void updateStateGraph();
602
603 /** Event for updating the state graph */
604 EventWrapper<TrafficGen,
605 &TrafficGen::updateStateGraph> updateStateGraphEvent;
606
607
608 public:
609
610 TrafficGen(const TrafficGenParams* p);
611
612 ~TrafficGen() {}
613
614 virtual BaseMasterPort& getMasterPort(const std::string &if_name,
615 PortID idx = InvalidPortID);
616
617 void init();
618
619 void initState();
620
621 unsigned int drain(DrainManager *dm);
622
623 void serialize(std::ostream &os);
624
625 void unserialize(Checkpoint* cp, const std::string& section);
626
627};
628
629#endif //__MEM_TRAFFIC_GEN_HH__