traffic_gen.cc (9584:1a21964b7227) traffic_gen.cc (9666:74aca4cb081e)
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

--- 31 unchanged lines hidden (view full) ---

40 */
41
42#include <sstream>
43
44#include "base/random.hh"
45#include "cpu/testers/traffic_gen/traffic_gen.hh"
46#include "debug/Checkpoint.hh"
47#include "debug/TrafficGen.hh"
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

--- 31 unchanged lines hidden (view full) ---

40 */
41
42#include <sstream>
43
44#include "base/random.hh"
45#include "cpu/testers/traffic_gen/traffic_gen.hh"
46#include "debug/Checkpoint.hh"
47#include "debug/TrafficGen.hh"
48#include "proto/packet.pb.h"
49#include "sim/stats.hh"
50#include "sim/system.hh"
51
52using namespace std;
53
54TrafficGen::TrafficGen(const TrafficGenParams* p)
55 : MemObject(p),
56 system(p->system),

--- 282 unchanged lines hidden (view full) ---

339{
340 DPRINTF(TrafficGen, "Transition to state %d\n", newState);
341
342 currState = newState;
343 nextTransitionTick += states[currState]->duration;
344 states[currState]->enter();
345}
346
48#include "sim/stats.hh"
49#include "sim/system.hh"
50
51using namespace std;
52
53TrafficGen::TrafficGen(const TrafficGenParams* p)
54 : MemObject(p),
55 system(p->system),

--- 282 unchanged lines hidden (view full) ---

338{
339 DPRINTF(TrafficGen, "Transition to state %d\n", newState);
340
341 currState = newState;
342 nextTransitionTick += states[currState]->duration;
343 states[currState]->enter();
344}
345
347TrafficGen::StateGraph::BaseGen::BaseGen(QueuedMasterPort& _port,
348 MasterID master_id,
349 Tick _duration)
350 : port(_port), masterID(master_id), duration(_duration)
351{
352}
353
354void
355TrafficGen::StateGraph::BaseGen::send(Addr addr, unsigned size,
356 const MemCmd& cmd)
357{
358 // Create new request
359 Request::Flags flags;
360 Request *req = new Request(addr, size, flags, masterID);
361
362 // Embed it in a packet
363 PacketPtr pkt = new Packet(req, cmd);
364
365 uint8_t* pkt_data = new uint8_t[req->getSize()];
366 pkt->dataDynamicArray(pkt_data);
367
368 if (cmd.isWrite()) {
369 memset(pkt_data, 0xA, req->getSize());
370 }
371
372 port.schedTimingReq(pkt, curTick());
373}
374
375void
376TrafficGen::StateGraph::LinearGen::enter()
377{
378 // reset the address and the data counter
379 nextAddr = startAddr;
380 dataManipulated = 0;
381
382 // this test only needs to happen once, but cannot be performed
383 // before init() is called and the ports are connected
384 if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
385 fatal("TrafficGen %s block size (%d) is larger than port"
386 " block size (%d)\n", blocksize, port.deviceBlockSize());
387
388}
389
390void
391TrafficGen::StateGraph::LinearGen::execute()
392{
393 // choose if we generate a read or a write here
394 bool isRead = readPercent != 0 &&
395 (readPercent == 100 || random_mt.random<uint8_t>(0, 100) < readPercent);
396
397 assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) ||
398 readPercent != 100);
399
400 DPRINTF(TrafficGen, "LinearGen::execute: %c to addr %x, size %d\n",
401 isRead ? 'r' : 'w', nextAddr, blocksize);
402
403 send(nextAddr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
404
405 // increment the address
406 nextAddr += blocksize;
407
408 // Add the amount of data manipulated to the total
409 dataManipulated += blocksize;
410}
411
412Tick
413TrafficGen::StateGraph::LinearGen::nextExecuteTick()
414{
415 // If we have reached the end of the address space, reset the
416 // address to the start of the range
417 if (nextAddr + blocksize > endAddr) {
418 DPRINTF(TrafficGen, "Wrapping address to the start of "
419 "the range\n");
420 nextAddr = startAddr;
421 }
422
423 // Check to see if we have reached the data limit. If dataLimit is
424 // zero we do not have a data limit and therefore we will keep
425 // generating requests for the entire residency in this state.
426 if (dataLimit && dataManipulated >= dataLimit) {
427 DPRINTF(TrafficGen, "Data limit for LinearGen reached.\n");
428 // there are no more requests, therefore return MaxTick
429 return MaxTick;
430 } else {
431 // return the time when the next request should take place
432 return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
433 }
434}
435
436void
437TrafficGen::StateGraph::RandomGen::enter()
438{
439 // reset the counter to zero
440 dataManipulated = 0;
441
442 // this test only needs to happen once, but cannot be performed
443 // before init() is called and the ports are connected
444 if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
445 fatal("TrafficGen %s block size (%d) is larger than port"
446 " block size (%d)\n", name(), blocksize, port.deviceBlockSize());
447}
448
449void
450TrafficGen::StateGraph::RandomGen::execute()
451{
452 // choose if we generate a read or a write here
453 bool isRead = readPercent != 0 &&
454 (readPercent == 100 || random_mt.random<uint8_t>(0, 100) < readPercent);
455
456 assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) ||
457 readPercent != 100);
458
459 // address of the request
460 Addr addr = random_mt.random<Addr>(startAddr, endAddr - 1);
461
462 // round down to start address of block
463 addr -= addr % blocksize;
464
465 DPRINTF(TrafficGen, "RandomGen::execute: %c to addr %x, size %d\n",
466 isRead ? 'r' : 'w', addr, blocksize);
467
468 // send a new request packet
469 send(addr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
470
471 // Add the amount of data manipulated to the total
472 dataManipulated += blocksize;
473}
474
475Tick
476TrafficGen::StateGraph::RandomGen::nextExecuteTick()
477{
478 // Check to see if we have reached the data limit. If dataLimit is
479 // zero we do not have a data limit and therefore we will keep
480 // generating requests for the entire residency in this state.
481 if (dataLimit && dataManipulated >= dataLimit)
482 {
483 DPRINTF(TrafficGen, "Data limit for RandomGen reached.\n");
484 // No more requests. Return MaxTick.
485 return MaxTick;
486 } else {
487 // Return the time when the next request should take place.
488 return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
489 }
490}
491
492TrafficGen::StateGraph::TraceGen::InputStream::InputStream(const string&
493 filename)
494 : trace(filename)
495{
496 // Create a protobuf message for the header and read it from the stream
497 Message::PacketHeader header_msg;
498 if (!trace.read(header_msg)) {
499 panic("Failed to read packet header from %s\n", filename);
500
501 if (header_msg.tick_freq() != SimClock::Frequency) {
502 panic("Trace %s was recorded with a different tick frequency %d\n",
503 header_msg.tick_freq());
504 }
505 }
506}
507
508void
509TrafficGen::StateGraph::TraceGen::InputStream::reset()
510{
511 trace.reset();
512}
513
514bool
346bool
515TrafficGen::StateGraph::TraceGen::InputStream::read(TraceElement& element)
516{
517 Message::Packet pkt_msg;
518 if (trace.read(pkt_msg)) {
519 element.cmd = pkt_msg.cmd();
520 element.addr = pkt_msg.addr();
521 element.blocksize = pkt_msg.size();
522 element.tick = pkt_msg.tick();
523 return true;
524 }
525
526 // We have reached the end of the file
527 return false;
528}
529
530Tick
531TrafficGen::StateGraph::TraceGen::nextExecuteTick() {
532 if (traceComplete)
533 // We are at the end of the file, thus we have no more data in
534 // the trace Return MaxTick to signal that there will be no
535 // more transactions in this active period for the state.
536 return MaxTick;
537
538
539 //Reset the nextElement to the default values
540 currElement = nextElement;
541 nextElement.clear();
542
543 // We need to look at the next line to calculate the next time an
544 // event occurs, or potentially return MaxTick to signal that
545 // nothing has to be done.
546 if (!trace.read(nextElement)) {
547 traceComplete = true;
548 return MaxTick;
549 }
550
551 DPRINTF(TrafficGen, "currElement: %c addr %d size %d tick %d (%d)\n",
552 currElement.cmd.isRead() ? 'r' : 'w',
553 currElement.addr,
554 currElement.blocksize,
555 currElement.tick + tickOffset,
556 currElement.tick);
557
558 DPRINTF(TrafficGen, "nextElement: %c addr %d size %d tick %d (%d)\n",
559 nextElement.cmd.isRead() ? 'r' : 'w',
560 nextElement.addr,
561 nextElement.blocksize,
562 nextElement.tick + tickOffset,
563 nextElement.tick);
564
565 return tickOffset + nextElement.tick;
566}
567
568void
569TrafficGen::StateGraph::TraceGen::enter() {
570 // update the trace offset to the time where the state was entered.
571 tickOffset = curTick();
572
573 // clear everything
574 nextElement.clear();
575 currElement.clear();
576
577 traceComplete = false;
578}
579
580void
581TrafficGen::StateGraph::TraceGen::execute() {
582 // it is the responsibility of nextExecuteTick to prevent the
583 // state graph from executing the state if it should not
584 assert(currElement.isValid());
585
586 DPRINTF(TrafficGen, "TraceGen::execute: %c %d %d %d\n",
587 currElement.cmd.isRead() ? 'r' : 'w',
588 currElement.addr,
589 currElement.blocksize,
590 currElement.tick);
591
592 send(currElement.addr + addrOffset, currElement.blocksize,
593 currElement.cmd);
594}
595
596void
597TrafficGen::StateGraph::TraceGen::exit() {
598 // Check if we reached the end of the trace file. If we did not
599 // then we want to generate a warning stating that not the entire
600 // trace was played.
601 if (!traceComplete) {
602 warn("Trace player %s was unable to replay the entire trace!\n",
603 name());
604 }
605
606 // Clear any flags and start over again from the beginning of the
607 // file
608 trace.reset();
609}
610
611bool
612TrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
613{
614 delete pkt->req;
615 delete pkt;
616
617 return true;
618}
347TrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
348{
349 delete pkt->req;
350 delete pkt;
351
352 return true;
353}