48d47
< #include "proto/packet.pb.h"
347,513d345
< TrafficGen::StateGraph::BaseGen::BaseGen(QueuedMasterPort& _port,
< MasterID master_id,
< Tick _duration)
< : port(_port), masterID(master_id), duration(_duration)
< {
< }
<
< void
< TrafficGen::StateGraph::BaseGen::send(Addr addr, unsigned size,
< 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);
<
< if (cmd.isWrite()) {
< memset(pkt_data, 0xA, req->getSize());
< }
<
< port.schedTimingReq(pkt, curTick());
< }
<
< void
< TrafficGen::StateGraph::LinearGen::enter()
< {
< // reset the address and the data counter
< nextAddr = startAddr;
< dataManipulated = 0;
<
< // 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())
< fatal("TrafficGen %s block size (%d) is larger than port"
< " block size (%d)\n", blocksize, port.deviceBlockSize());
<
< }
<
< void
< TrafficGen::StateGraph::LinearGen::execute()
< {
< // choose if we generate a read or a write here
< bool isRead = readPercent != 0 &&
< (readPercent == 100 || random_mt.random<uint8_t>(0, 100) < readPercent);
<
< assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) ||
< readPercent != 100);
<
< DPRINTF(TrafficGen, "LinearGen::execute: %c to addr %x, size %d\n",
< isRead ? 'r' : 'w', nextAddr, blocksize);
<
< send(nextAddr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
<
< // increment the address
< nextAddr += blocksize;
<
< // Add the amount of data manipulated to the total
< dataManipulated += blocksize;
< }
<
< Tick
< TrafficGen::StateGraph::LinearGen::nextExecuteTick()
< {
< // If we have reached the end of the address space, reset the
< // address to the start of the range
< if (nextAddr + blocksize > endAddr) {
< DPRINTF(TrafficGen, "Wrapping address to the start of "
< "the range\n");
< nextAddr = startAddr;
< }
<
< // Check to see if we have reached the data limit. If dataLimit is
< // zero we do not have a data limit and therefore we will keep
< // generating requests for the entire residency in this state.
< if (dataLimit && dataManipulated >= dataLimit) {
< DPRINTF(TrafficGen, "Data limit for LinearGen reached.\n");
< // there are no more requests, therefore return MaxTick
< return MaxTick;
< } else {
< // return the time when the next request should take place
< return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
< }
< }
<
< void
< TrafficGen::StateGraph::RandomGen::enter()
< {
< // reset the counter to zero
< dataManipulated = 0;
<
< // 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())
< fatal("TrafficGen %s block size (%d) is larger than port"
< " block size (%d)\n", name(), blocksize, port.deviceBlockSize());
< }
<
< void
< TrafficGen::StateGraph::RandomGen::execute()
< {
< // choose if we generate a read or a write here
< bool isRead = readPercent != 0 &&
< (readPercent == 100 || random_mt.random<uint8_t>(0, 100) < readPercent);
<
< assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) ||
< readPercent != 100);
<
< // address of the request
< Addr addr = random_mt.random<Addr>(startAddr, endAddr - 1);
<
< // round down to start address of block
< addr -= addr % blocksize;
<
< DPRINTF(TrafficGen, "RandomGen::execute: %c to addr %x, size %d\n",
< isRead ? 'r' : 'w', addr, blocksize);
<
< // send a new request packet
< send(addr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
<
< // Add the amount of data manipulated to the total
< dataManipulated += blocksize;
< }
<
< Tick
< TrafficGen::StateGraph::RandomGen::nextExecuteTick()
< {
< // Check to see if we have reached the data limit. If dataLimit is
< // zero we do not have a data limit and therefore we will keep
< // generating requests for the entire residency in this state.
< if (dataLimit && dataManipulated >= dataLimit)
< {
< DPRINTF(TrafficGen, "Data limit for RandomGen reached.\n");
< // No more requests. Return MaxTick.
< return MaxTick;
< } else {
< // Return the time when the next request should take place.
< return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
< }
< }
<
< TrafficGen::StateGraph::TraceGen::InputStream::InputStream(const string&
< filename)
< : trace(filename)
< {
< // Create a protobuf message for the header and read it from the stream
< Message::PacketHeader header_msg;
< if (!trace.read(header_msg)) {
< panic("Failed to read packet header from %s\n", filename);
<
< if (header_msg.tick_freq() != SimClock::Frequency) {
< panic("Trace %s was recorded with a different tick frequency %d\n",
< header_msg.tick_freq());
< }
< }
< }
<
< void
< TrafficGen::StateGraph::TraceGen::InputStream::reset()
< {
< trace.reset();
< }
<
515,611d346
< TrafficGen::StateGraph::TraceGen::InputStream::read(TraceElement& element)
< {
< Message::Packet pkt_msg;
< if (trace.read(pkt_msg)) {
< element.cmd = pkt_msg.cmd();
< element.addr = pkt_msg.addr();
< element.blocksize = pkt_msg.size();
< element.tick = pkt_msg.tick();
< return true;
< }
<
< // We have reached the end of the file
< return false;
< }
<
< Tick
< TrafficGen::StateGraph::TraceGen::nextExecuteTick() {
< if (traceComplete)
< // We are at the end of the file, thus we have no more data in
< // the trace Return MaxTick to signal that there will be no
< // more transactions in this active period for the state.
< return MaxTick;
<
<
< //Reset the nextElement to the default values
< currElement = nextElement;
< nextElement.clear();
<
< // We need to look at the next line to calculate the next time an
< // event occurs, or potentially return MaxTick to signal that
< // nothing has to be done.
< if (!trace.read(nextElement)) {
< traceComplete = true;
< return MaxTick;
< }
<
< DPRINTF(TrafficGen, "currElement: %c addr %d size %d tick %d (%d)\n",
< currElement.cmd.isRead() ? 'r' : 'w',
< currElement.addr,
< currElement.blocksize,
< currElement.tick + tickOffset,
< currElement.tick);
<
< DPRINTF(TrafficGen, "nextElement: %c addr %d size %d tick %d (%d)\n",
< nextElement.cmd.isRead() ? 'r' : 'w',
< nextElement.addr,
< nextElement.blocksize,
< nextElement.tick + tickOffset,
< nextElement.tick);
<
< return tickOffset + nextElement.tick;
< }
<
< void
< TrafficGen::StateGraph::TraceGen::enter() {
< // update the trace offset to the time where the state was entered.
< tickOffset = curTick();
<
< // clear everything
< nextElement.clear();
< currElement.clear();
<
< traceComplete = false;
< }
<
< void
< TrafficGen::StateGraph::TraceGen::execute() {
< // it is the responsibility of nextExecuteTick to prevent the
< // state graph from executing the state if it should not
< assert(currElement.isValid());
<
< DPRINTF(TrafficGen, "TraceGen::execute: %c %d %d %d\n",
< currElement.cmd.isRead() ? 'r' : 'w',
< currElement.addr,
< currElement.blocksize,
< currElement.tick);
<
< send(currElement.addr + addrOffset, currElement.blocksize,
< currElement.cmd);
< }
<
< void
< TrafficGen::StateGraph::TraceGen::exit() {
< // Check if we reached the end of the trace file. If we did not
< // then we want to generate a warning stating that not the entire
< // trace was played.
< if (!traceComplete) {
< warn("Trace player %s was unable to replay the entire trace!\n",
< name());
< }
<
< // Clear any flags and start over again from the beginning of the
< // file
< trace.reset();
< }
<
< bool