traffic_gen.hh revision 9402:f6e3c60f04e5
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__ 630