diff options
Diffstat (limited to 'src/cpu/testers/traffic_gen/trace_gen.cc')
-rw-r--r-- | src/cpu/testers/traffic_gen/trace_gen.cc | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/cpu/testers/traffic_gen/trace_gen.cc b/src/cpu/testers/traffic_gen/trace_gen.cc new file mode 100644 index 000000000..c2555eadf --- /dev/null +++ b/src/cpu/testers/traffic_gen/trace_gen.cc @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012-2013, 2016-2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed here under. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Thomas Grass + * Andreas Hansson + * Sascha Bischoff + * Neha Agarwal + */ + +#include "cpu/testers/traffic_gen/trace_gen.hh" + +#include <algorithm> + +#include "base/random.hh" +#include "base/trace.hh" +#include "debug/TrafficGen.hh" +#include "proto/packet.pb.h" + +TraceGen::InputStream::InputStream(const std::string& filename) + : trace(filename) +{ + init(); +} + +void +TraceGen::InputStream::init() +{ + // Create a protobuf message for the header and read it from the stream + ProtoMessage::PacketHeader header_msg; + if (!trace.read(header_msg)) { + panic("Failed to read packet header from trace\n"); + } else if (header_msg.tick_freq() != SimClock::Frequency) { + panic("Trace was recorded with a different tick frequency %d\n", + header_msg.tick_freq()); + } +} + +void +TraceGen::InputStream::reset() +{ + trace.reset(); + init(); +} + +bool +TraceGen::InputStream::read(TraceElement& element) +{ + ProtoMessage::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(); + element.flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0; + return true; + } + + // We have reached the end of the file + return false; +} + +Tick +TraceGen::nextPacketTick(bool elastic, Tick delay) const +{ + if (traceComplete) { + DPRINTF(TrafficGen, "No next tick as trace is finished\n"); + // 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; + } + + assert(nextElement.isValid()); + + DPRINTF(TrafficGen, "Next packet tick is %d\n", tickOffset + + nextElement.tick); + + // if the playback is supposed to be elastic, add the delay + if (elastic) + tickOffset += delay; + + return std::max(tickOffset + nextElement.tick, curTick()); +} + +void +TraceGen::enter() +{ + // update the trace offset to the time where the state was entered. + tickOffset = curTick(); + + // clear everything + currElement.clear(); + + // read the first element in the file and set the complete flag + traceComplete = !trace.read(nextElement); +} + +PacketPtr +TraceGen::getNextPacket() +{ + // shift things one step forward + currElement = nextElement; + nextElement.clear(); + + // read the next element and set the complete flag + traceComplete = !trace.read(nextElement); + + // it is the responsibility of the traceComplete flag to ensure we + // always have a valid element here + assert(currElement.isValid()); + + DPRINTF(TrafficGen, "TraceGen::getNextPacket: %c %d %d %d 0x%x\n", + currElement.cmd.isRead() ? 'r' : 'w', + currElement.addr, + currElement.blocksize, + currElement.tick, + currElement.flags); + + PacketPtr pkt = getPacket(currElement.addr + addrOffset, + currElement.blocksize, + currElement.cmd, currElement.flags); + + if (!traceComplete) + 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 pkt; +} + +void +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(); +} |