summaryrefslogtreecommitdiff
path: root/src/cpu/testers/traffic_gen/trace_gen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/testers/traffic_gen/trace_gen.cc')
-rw-r--r--src/cpu/testers/traffic_gen/trace_gen.cc181
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();
+}