summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2018-03-14 17:26:06 +0000
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2018-04-06 10:10:10 +0000
commit4a66b5f7f8f9fbaec814d956ac53362a574a8620 (patch)
tree90c7ca9cbad3fd06ed52ab8db59e4c79ae190a8c
parent2d1add2d5d6b49a0eac1ef9180786fe28d207098 (diff)
downloadgem5-4a66b5f7f8f9fbaec814d956ac53362a574a8620.tar.xz
arch-arm: Add support for Tarmac trace generation
This patch introduces the TarmacTracer: an instruction tracer which allows to dump a gem5 execution trace in Tarmac format [1]. The new tracer is supporting either Tarmac and TarmacV8 format specifications. Not every traceable information has been implemented: Implemented Trace Type: Instruction Trace Register Trace Processor Memory Access Trace Unimplemented Trace Type: Program Flow Trace Event Trace Memory Bus Trace [1]: https://developer.arm.com/docs/dui0845/f/tarmac-trace-file-format Change-Id: I8799d8e5852e868673f728971db3fe8c63961f5e Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/9382 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
-rw-r--r--src/arch/arm/tracers/SConscript3
-rw-r--r--src/arch/arm/tracers/TarmacTrace.py11
-rw-r--r--src/arch/arm/tracers/tarmac_record.cc457
-rw-r--r--src/arch/arm/tracers/tarmac_record.hh265
-rw-r--r--src/arch/arm/tracers/tarmac_record_v8.cc248
-rw-r--r--src/arch/arm/tracers/tarmac_record_v8.hh153
-rw-r--r--src/arch/arm/tracers/tarmac_tracer.cc103
-rw-r--r--src/arch/arm/tracers/tarmac_tracer.hh132
8 files changed, 1372 insertions, 0 deletions
diff --git a/src/arch/arm/tracers/SConscript b/src/arch/arm/tracers/SConscript
index 1491e1a62..ad11b0a67 100644
--- a/src/arch/arm/tracers/SConscript
+++ b/src/arch/arm/tracers/SConscript
@@ -42,3 +42,6 @@ if env['TARGET_ISA'] == 'arm':
SimObject('TarmacTrace.py')
Source('tarmac_base.cc')
Source('tarmac_parser.cc')
+ Source('tarmac_tracer.cc')
+ Source('tarmac_record.cc')
+ Source('tarmac_record_v8.cc')
diff --git a/src/arch/arm/tracers/TarmacTrace.py b/src/arch/arm/tracers/TarmacTrace.py
index c2bcbb3c2..8955fadd6 100644
--- a/src/arch/arm/tracers/TarmacTrace.py
+++ b/src/arch/arm/tracers/TarmacTrace.py
@@ -64,3 +64,14 @@ class TarmacParser(InstTracer):
ignore_mem_addr = Param.AddrRange(AddrRange(0, size=0),
"Range of unverifiable memory addresses")
+
+class TarmacTracer(InstTracer):
+ type = 'TarmacTracer'
+ cxx_class = 'Trace::TarmacTracer'
+ cxx_header = "arch/arm/tracers/tarmac_tracer.hh"
+
+ start_tick = Param.Tick(0,
+ "tracing starts when the tick time gets this value")
+
+ end_tick = Param.Tick(MaxTick,
+ "tracing ends when the tick time gets this value")
diff --git a/src/arch/arm/tracers/tarmac_record.cc b/src/arch/arm/tracers/tarmac_record.cc
new file mode 100644
index 000000000..7034d2586
--- /dev/null
+++ b/src/arch/arm/tracers/tarmac_record.cc
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2017-2018 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 hereunder. 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: Giacomo Travaglini
+ */
+
+#include "arch/arm/tracers/tarmac_record.hh"
+
+#include "arch/arm/insts/static_inst.hh"
+#include "tarmac_tracer.hh"
+
+namespace Trace {
+
+// TARMAC Instruction Record static variables
+uint64_t TarmacTracerRecord::TraceInstEntry::instCount = 0;
+
+std::string
+iSetStateToStr(TarmacBaseRecord::ISetState isetstate)
+{
+ switch (isetstate) {
+ case TarmacBaseRecord::ISET_ARM:
+ return "A";
+ case TarmacBaseRecord::ISET_THUMB:
+ return "T";
+ case TarmacBaseRecord::ISET_A64:
+ return "O";
+ default:
+ return "Unsupported";
+ }
+}
+
+std::string
+opModeToStr(OperatingMode opMode)
+{
+ switch (opMode) {
+ case MODE_EL0T:
+ return "EL0t";
+ case MODE_EL1T:
+ return "EL1t";
+ case MODE_EL1H:
+ return "EL1h";
+ case MODE_EL2T:
+ return "EL2t";
+ case MODE_EL2H:
+ return "EL2h";
+ case MODE_EL3T:
+ return "EL3t";
+ case MODE_EL3H:
+ return "EL3h";
+ case MODE_USER:
+ return "usr";
+ case MODE_FIQ:
+ return "fiq";
+ case MODE_IRQ:
+ return "irq";
+ case MODE_SVC:
+ return "svc";
+ case MODE_MON:
+ return "mon";
+ case MODE_ABORT:
+ return "abt";
+ case MODE_HYP:
+ return "hyp";
+ case MODE_UNDEFINED:
+ return "und";
+ case MODE_SYSTEM:
+ return "sys";
+ default:
+ return "Unsupported";
+ }
+}
+
+// TarmacTracerRecord ctor
+TarmacTracerRecord::TarmacTracerRecord(Tick _when, ThreadContext *_thread,
+ const StaticInstPtr _staticInst,
+ PCState _pc,
+ TarmacTracer& _tracer,
+ const StaticInstPtr _macroStaticInst)
+ : TarmacBaseRecord(_when, _thread, _staticInst,
+ _pc, _macroStaticInst),
+ tracer(_tracer)
+{
+}
+
+TarmacTracerRecord::TraceInstEntry::TraceInstEntry(
+ const TarmacContext& tarmCtx,
+ bool predicate)
+ : InstEntry(tarmCtx.thread, tarmCtx.pc, tarmCtx.staticInst, predicate)
+{
+ secureMode = inSecureState(tarmCtx.thread);
+
+ auto arm_inst = static_cast<const ArmStaticInst*>(
+ tarmCtx.staticInst.get()
+ );
+
+ // Get the instruction size as a number of bits:
+ // (multiply byte size by 8)
+ instSize = (arm_inst->instSize() << 3);
+
+ // Mask the opcode using the instruction size: the
+ // opcode field will otherwise be 32 bit wide even
+ // for 16bit (Thumb) instruction.
+ opcode = arm_inst->encoding();
+
+ // Update the instruction count: number of executed
+ // instructions.
+ instCount++;
+}
+
+TarmacTracerRecord::TraceMemEntry::TraceMemEntry(
+ const TarmacContext& tarmCtx,
+ uint8_t _size, Addr _addr, uint64_t _data)
+ : MemEntry(_size, _addr, _data),
+ loadAccess(tarmCtx.staticInst->isLoad())
+{
+}
+
+TarmacTracerRecord::TraceRegEntry::TraceRegEntry(
+ const TarmacContext& tarmCtx,
+ const RegId& reg)
+ : RegEntry(tarmCtx.pc),
+ regValid(false),
+ regClass(reg.classValue()),
+ regRel(reg.index())
+{
+}
+
+void
+TarmacTracerRecord::TraceRegEntry::update(
+ const TarmacContext& tarmCtx
+)
+{
+ // Fill the register entry data, according to register
+ // class.
+ switch (regClass) {
+ case CCRegClass:
+ updateCC(tarmCtx, regRel);
+ break;
+ case FloatRegClass:
+ updateFloat(tarmCtx, regRel);
+ break;
+ case IntRegClass:
+ updateInt(tarmCtx, regRel);
+ break;
+ case MiscRegClass:
+ updateMisc(tarmCtx, regRel);
+ break;
+ default:
+ // If unsupported format, do nothing: non updating
+ // the register will prevent it to be printed.
+ break;
+ }
+}
+
+void
+TarmacTracerRecord::TraceRegEntry::updateMisc(
+ const TarmacContext& tarmCtx,
+ RegIndex regRelIdx
+)
+{
+ auto thread = tarmCtx.thread;
+
+ regValid = true;
+ regName = miscRegName[regRelIdx];
+ valueLo = thread->readMiscRegNoEffect(regRelIdx);
+
+ // If it is the CPSR:
+ // update the value of the CPSR register and add
+ // the CC flags on top of the value
+ if (regRelIdx == MISCREG_CPSR) {
+ CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR);
+ cpsr.nz = thread->readCCReg(CCREG_NZ);
+ cpsr.c = thread->readCCReg(CCREG_C);
+ cpsr.v = thread->readCCReg(CCREG_V);
+ cpsr.ge = thread->readCCReg(CCREG_GE);
+
+ // update the entry value
+ valueLo = cpsr;
+ }
+}
+
+void
+TarmacTracerRecord::TraceRegEntry::updateCC(
+ const TarmacContext& tarmCtx,
+ RegIndex regRelIdx
+)
+{
+ auto thread = tarmCtx.thread;
+
+ regValid = true;
+ regName = ccRegName[regRelIdx];
+ valueLo = thread->readCCReg(regRelIdx);
+}
+
+void
+TarmacTracerRecord::TraceRegEntry::updateFloat(
+ const TarmacContext& tarmCtx,
+ RegIndex regRelIdx
+)
+{
+ auto thread = tarmCtx.thread;
+
+ regValid = true;
+ regName = "f" + std::to_string(regRelIdx);
+ valueLo = thread->readFloatReg(regRelIdx);
+}
+
+void
+TarmacTracerRecord::TraceRegEntry::updateInt(
+ const TarmacContext& tarmCtx,
+ RegIndex regRelIdx
+)
+{
+ auto thread = tarmCtx.thread;
+
+ // Reading operating mode from CPSR.
+ // This is needed when printing the register name in case
+ // of banked register (e.g. lr_svc)
+ CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR);
+ OperatingMode mode = (OperatingMode)(uint8_t)cpsr.mode;
+
+ std::string reg_suffix;
+ if (mode != MODE_USER) {
+ reg_suffix = "_" + opModeToStr(mode);
+ }
+
+ regValid = true;
+ switch (regRelIdx) {
+ case PCReg:
+ regName = "pc";
+ break;
+ case StackPointerReg:
+ regName = "sp" + reg_suffix ;
+ break;
+ case FramePointerReg:
+ regName = "fp" + reg_suffix;
+ break;
+ case ReturnAddressReg:
+ regName = "lr" + reg_suffix;
+ break;
+ default:
+ regName = "r" + std::to_string(regRelIdx);
+ break;
+ }
+ valueLo = thread->readIntReg(regRelIdx);
+}
+
+void
+TarmacTracerRecord::addInstEntry(std::vector<InstPtr>& queue,
+ const TarmacContext& tarmCtx)
+{
+ // Generate an instruction entry in the record and
+ // add it to the Instruction Queue
+ queue.push_back(
+ m5::make_unique<TraceInstEntry>(tarmCtx, predicate)
+ );
+}
+
+void
+TarmacTracerRecord::addMemEntry(std::vector<MemPtr>& queue,
+ const TarmacContext& tarmCtx)
+{
+ // Generate a memory entry in the record if the record
+ // implies a valid memory access, and add it to the
+ // Memory Queue
+ if (getMemValid()) {
+ queue.push_back(
+ m5::make_unique<TraceMemEntry>(tarmCtx,
+ static_cast<uint8_t>(getSize()),
+ getAddr(), getIntData())
+ );
+ }
+}
+
+void
+TarmacTracerRecord::addRegEntry(std::vector<RegPtr>& queue,
+ const TarmacContext& tarmCtx)
+{
+ // Generate an entry for every ARM register being
+ // written by the current instruction
+ for (auto reg = 0; reg < staticInst->numDestRegs(); ++reg) {
+
+ RegId reg_id = staticInst->destRegIdx(reg);
+
+ // Creating a single register change entry
+ auto single_reg = genRegister<TraceRegEntry>(tarmCtx, reg_id);
+
+ // Copying the entry and adding it to the "list"
+ // of entries to be dumped to trace.
+ queue.push_back(
+ m5::make_unique<TraceRegEntry>(single_reg)
+ );
+ }
+
+ // Gem5 is treating CPSR flags as separate registers (CC registers),
+ // in contrast with Tarmac specification: we need to merge the gem5 CC
+ // entries altogether with the CPSR register and produce a single entry.
+ mergeCCEntry<TraceRegEntry>(queue, tarmCtx);
+}
+
+void
+TarmacTracerRecord::dump()
+{
+ // Generate and print all the record's entries.
+ auto &instQueue = tracer.instQueue;
+ auto &memQueue = tracer.memQueue;
+ auto &regQueue = tracer.regQueue;
+
+ const TarmacContext tarmCtx(
+ thread,
+ staticInst->isMicroop()? macroStaticInst : staticInst,
+ pc
+ );
+
+ if (!staticInst->isMicroop()) {
+ // Current instruction is NOT a micro-instruction:
+ // Generate Tarmac entries and dump them immediately
+
+ // Generate Tarmac entries and add them to the respective
+ // queues.
+ addInstEntry(instQueue, tarmCtx);
+ addMemEntry(memQueue, tarmCtx);
+ addRegEntry(regQueue, tarmCtx);
+
+ // Flush (print) any queued entry.
+ flushQueues(instQueue, memQueue, regQueue);
+
+ } else {
+ // Current instruction is a micro-instruction:
+ // save micro entries into dedicated queues and flush them
+ // into the tracefile only when the MACRO-instruction
+ // has completed.
+
+ if (staticInst->isFirstMicroop()) {
+ addInstEntry(instQueue, tarmCtx);
+ }
+
+ addRegEntry(regQueue, tarmCtx);
+ addMemEntry(memQueue, tarmCtx);
+
+ if (staticInst->isLastMicroop()) {
+ // Flush (print) any queued entry.
+ flushQueues(instQueue, memQueue, regQueue);
+ }
+ }
+}
+
+template<typename Queue>
+void
+TarmacTracerRecord::flushQueues(Queue& queue)
+{
+ std::ostream &outs = Trace::output();
+
+ for (const auto &single_entry : queue) {
+ single_entry->print(outs);
+ }
+
+ queue.clear();
+}
+
+template<typename Queue, typename... Args>
+void
+TarmacTracerRecord::flushQueues(Queue& queue, Args & ... args)
+{
+ flushQueues(queue);
+ flushQueues(args...);
+}
+
+void
+TarmacTracerRecord::TraceInstEntry::print(
+ std::ostream& outs,
+ int verbosity,
+ const std::string &prefix) const
+{
+ // Pad the opcode
+ std::string opcode_str = csprintf("%0*x", instSize >> 2, opcode);
+
+ // Print the instruction record formatted according
+ // to the Tarmac specification
+ ccprintf(outs, "%s clk %s (%u) %08x %s %s %s_%s : %s\n",
+ curTick(), /* Tick time */
+ taken? "IT" : "IS", /* Instruction taken/skipped */
+ instCount, /* Instruction count */
+ addr, /* Instruction address */
+ opcode_str, /* Instruction opcode */
+ iSetStateToStr(isetstate), /* Instruction Set */
+ opModeToStr(mode), /* Exception level */
+ secureMode? "s" : "ns", /* Security */
+ disassemble); /* Instruction disass */
+}
+
+void
+TarmacTracerRecord::TraceMemEntry::print(
+ std::ostream& outs,
+ int verbosity,
+ const std::string &prefix) const
+{
+ // Print the memory record formatted according
+ // to the Tarmac specification
+ ccprintf(outs, "%s clk M%s%d %08x %0*x\n",
+ curTick(), /* Tick time */
+ loadAccess? "R" : "W", /* Access type */
+ size, /* Access size */
+ addr, /* Memory address */
+ size*2, /* Padding with access size */
+ data); /* Memory data */
+}
+
+void
+TarmacTracerRecord::TraceRegEntry::print(
+ std::ostream& outs,
+ int verbosity,
+ const std::string &prefix) const
+{
+ // Print the register record formatted according
+ // to the Tarmac specification
+ if (regValid)
+ ccprintf(outs, "%s clk R %s %08x\n",
+ curTick(), /* Tick time */
+ regName, /* Register name */
+ valueLo); /* Register value */
+}
+
+} // namespace Trace
diff --git a/src/arch/arm/tracers/tarmac_record.hh b/src/arch/arm/tracers/tarmac_record.hh
new file mode 100644
index 000000000..f54abf56a
--- /dev/null
+++ b/src/arch/arm/tracers/tarmac_record.hh
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017-2018 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 hereunder. 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: Giacomo Travaglini
+ */
+
+/**
+ * @file: The file contains the informations used to generate records
+ * for the pre-ARMv8 cores.
+ */
+
+#ifndef __ARCH_ARM_TRACERS_TARMAC_RECORD_HH__
+#define __ARCH_ARM_TRACERS_TARMAC_RECORD_HH__
+
+#include "arch/arm/tracers/tarmac_base.hh"
+#include "base/printable.hh"
+#include "config/the_isa.hh"
+#include "cpu/reg_class.hh"
+#include "cpu/static_inst.hh"
+
+namespace Trace {
+
+class TarmacContext;
+
+class TarmacTracer;
+
+/**
+ * Returns the string representation of the instruction set being
+ * currently run according to the Tarmac format.
+ *
+ * @param isetstate: enum variable (ISetState) specifying an ARM
+ * instruction set.
+ * @return instruction set in string format.
+ */
+std::string
+iSetStateToStr(TarmacBaseRecord::ISetState isetstate);
+
+/**
+ * Returns the string representation of the ARM Operating Mode
+ * (CPSR.M[3:0] field) according to the Tarmac format.
+ *
+ * @param opMode: ARM operating mode.
+ * @return operating mode in string format.
+ */
+std::string
+opModeToStr(ArmISA::OperatingMode opMode);
+
+/**
+ * TarmacTracer Record:
+ * Record generated by the TarmacTracer for every executed instruction.
+ * The record is composed by a set of entries, matching the tracing
+ * capabilities provided by the Tarmac specifications:
+ *
+ * - Instruction Entry
+ * - Register Entry
+ * - Memory Entry
+ */
+class TarmacTracerRecord : public TarmacBaseRecord
+{
+ public:
+ /** Instruction Entry */
+ struct TraceInstEntry: public InstEntry, Printable
+ {
+ TraceInstEntry(const TarmacContext& tarmCtx, bool predicate);
+
+ virtual void print(std::ostream& outs,
+ int verbosity = 0,
+ const std::string &prefix = "") const override;
+
+ protected:
+ /** Number of instructions being traced */
+ static uint64_t instCount;
+
+ /** True if instruction is executed in secure mode */
+ bool secureMode;
+ /**
+ * Instruction size:
+ * 16 for 16-bit Thumb Instruction
+ * 32 otherwise (ARM and BigThumb)
+ */
+ uint8_t instSize;
+ };
+
+ /** Register Entry */
+ struct TraceRegEntry: public RegEntry, Printable
+ {
+ public:
+ TraceRegEntry(const TarmacContext& tarmCtx, const RegId& reg);
+
+ /**
+ * This updates the register entry using the update table. It is
+ * a required step after the register entry generation.
+ * If unupdated, the entry will be marked as invalid.
+ * The entry update cannot be done automatically at TraceRegEntry
+ * construction: the entries are extended by consequent Tarmac
+ * Tracer versions (like V8), and virtual functions should
+ * be avoided during construction.
+ */
+ void update(const TarmacContext& tarmCtx);
+
+ virtual void print(std::ostream& outs,
+ int verbosity = 0,
+ const std::string &prefix = "") const override;
+
+ protected:
+ /** Register update functions. */
+ virtual void
+ updateMisc(const TarmacContext& tarmCtx, RegIndex regRelIdx);
+
+ virtual void
+ updateCC(const TarmacContext& tarmCtx, RegIndex regRelIdx);
+
+ virtual void
+ updateFloat(const TarmacContext& tarmCtx, RegIndex regRelIdx);
+
+ virtual void
+ updateInt(const TarmacContext& tarmCtx, RegIndex regRelIdx);
+
+ public:
+ /** True if register entry is valid */
+ bool regValid;
+ /** Register class */
+ RegClass regClass;
+ /** Register arch number */
+ RegIndex regRel;
+ /** Register name to be printed */
+ std::string regName;
+ };
+
+ /** Memory Entry */
+ struct TraceMemEntry: public MemEntry, Printable
+ {
+ public:
+ TraceMemEntry(const TarmacContext& tarmCtx,
+ uint8_t _size, Addr _addr, uint64_t _data);
+
+ virtual void print(std::ostream& outs,
+ int verbosity = 0,
+ const std::string &prefix = "") const override;
+
+ protected:
+ /** True if memory access is a load */
+ bool loadAccess;
+ };
+
+ public:
+ TarmacTracerRecord(Tick _when, ThreadContext *_thread,
+ const StaticInstPtr _staticInst, TheISA::PCState _pc,
+ TarmacTracer& _tracer,
+ const StaticInstPtr _macroStaticInst = NULL);
+
+ virtual void dump() override;
+
+ using InstPtr = std::unique_ptr<TraceInstEntry>;
+ using MemPtr = std::unique_ptr<TraceMemEntry>;
+ using RegPtr = std::unique_ptr<TraceRegEntry>;
+
+ protected:
+ /** Generates an Entry for the executed instruction. */
+ virtual void addInstEntry(std::vector<InstPtr>& queue,
+ const TarmacContext& ptr);
+
+ /** Generates an Entry for every triggered memory access */
+ virtual void addMemEntry(std::vector<MemPtr>& queue,
+ const TarmacContext& ptr);
+
+ /** Generate an Entry for every register being written. */
+ virtual void addRegEntry(std::vector<RegPtr>& queue,
+ const TarmacContext& ptr);
+
+ protected:
+ /** Generate and update a register entry. */
+ template<typename RegEntry>
+ RegEntry
+ genRegister(const TarmacContext& tarmCtx, const RegId& reg)
+ {
+ RegEntry single_reg(tarmCtx, reg);
+ single_reg.update(tarmCtx);
+
+ return single_reg;
+ }
+
+ template<typename RegEntry>
+ void
+ mergeCCEntry(std::vector<RegPtr>& queue, const TarmacContext& tarmCtx)
+ {
+ // Find all CC Entries and move them at the end of the queue
+ auto it = std::remove_if(
+ queue.begin(), queue.end(),
+ [] (RegPtr& reg) ->bool { return (reg->regClass == CCRegClass); }
+ );
+
+ if (it != queue.end()) {
+ // Remove all CC Entries.
+ queue.erase(it, queue.end());
+
+ auto is_cpsr = [] (RegPtr& reg) ->bool
+ {
+ return (reg->regClass == MiscRegClass) &&
+ (reg->regRel == ArmISA::MISCREG_CPSR);
+ };
+
+ // Looking for the presence of a CPSR register entry.
+ auto cpsr_it = std::find_if(
+ queue.begin(), queue.end(), is_cpsr
+ );
+
+ // If CPSR entry not present, generate one
+ if (cpsr_it == queue.end()) {
+ RegId reg(MiscRegClass, ArmISA::MISCREG_CPSR);
+ queue.push_back(
+ m5::make_unique<RegEntry>(
+ genRegister<RegEntry>(tarmCtx, reg))
+ );
+ }
+ }
+ }
+
+ /** Flush queues to the trace output */
+ template<typename Queue>
+ void flushQueues(Queue& queue);
+ template<typename Queue, typename... Args>
+ void flushQueues(Queue& queue, Args & ... args);
+
+ protected:
+ /** Reference to tracer */
+ TarmacTracer& tracer;
+};
+
+} // namespace Trace
+
+#endif // __ARCH_ARM_TRACERS_TARMAC_RECORD_HH__
diff --git a/src/arch/arm/tracers/tarmac_record_v8.cc b/src/arch/arm/tracers/tarmac_record_v8.cc
new file mode 100644
index 000000000..dea040992
--- /dev/null
+++ b/src/arch/arm/tracers/tarmac_record_v8.cc
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2017-2018 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 hereunder. 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: Giacomo Travaglini
+ */
+
+#include "arch/arm/tracers/tarmac_record_v8.hh"
+
+#include "arch/arm/insts/static_inst.hh"
+#include "arch/arm/tlb.hh"
+#include "arch/arm/tracers/tarmac_tracer.hh"
+
+namespace Trace {
+
+TarmacTracerRecordV8::TraceInstEntryV8::TraceInstEntryV8(
+ const TarmacContext& tarmCtx,
+ bool predicate)
+ : TraceInstEntry(tarmCtx, predicate),
+ TraceEntryV8(tarmCtx.tarmacCpuName()),
+ paddr(0),
+ paddrValid(false)
+{
+ const auto thread = tarmCtx.thread;
+
+ // Evaluate physical address
+ TheISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
+ paddrValid = dtb->translateFunctional(thread, addr, paddr);
+}
+
+TarmacTracerRecordV8::TraceMemEntryV8::TraceMemEntryV8(
+ const TarmacContext& tarmCtx,
+ uint8_t _size, Addr _addr, uint64_t _data)
+ : TraceMemEntry(tarmCtx, _size, _addr, _data),
+ TraceEntryV8(tarmCtx.tarmacCpuName()),
+ paddr(_addr)
+{
+ const auto thread = tarmCtx.thread;
+
+ // Evaluate physical address
+ TheISA::TLB* dtb = static_cast<TLB*>(thread->getDTBPtr());
+ dtb->translateFunctional(thread, addr, paddr);
+}
+
+TarmacTracerRecordV8::TraceRegEntryV8::TraceRegEntryV8(
+ const TarmacContext& tarmCtx,
+ const RegId& reg)
+ : TraceRegEntry(tarmCtx, reg),
+ TraceEntryV8(tarmCtx.tarmacCpuName()),
+ regWidth(64)
+{
+}
+
+void
+TarmacTracerRecordV8::TraceRegEntryV8::updateInt(
+ const TarmacContext& tarmCtx,
+ RegIndex regRelIdx
+)
+{
+ // Do not trace pseudo register accesses: invalid
+ // register entry.
+ if (regRelIdx > NUM_ARCH_INTREGS) {
+ regValid = false;
+ return;
+ }
+
+ TraceRegEntry::updateInt(tarmCtx, regRelIdx);
+
+ if ((regRelIdx != PCReg) || (regRelIdx != StackPointerReg) ||
+ (regRelIdx != FramePointerReg) || (regRelIdx != ReturnAddressReg)) {
+
+ const auto* arm_inst = static_cast<const ArmStaticInst*>(
+ tarmCtx.staticInst.get()
+ );
+
+ regWidth = (arm_inst->getIntWidth());
+ if (regWidth == 32) {
+ regName = "W" + std::to_string(regRelIdx);
+ } else {
+ regName = "X" + std::to_string(regRelIdx);
+ }
+ }
+}
+
+void
+TarmacTracerRecordV8::TraceRegEntryV8::updateMisc(
+ const TarmacContext& tarmCtx,
+ RegIndex regRelIdx
+)
+{
+ TraceRegEntry::updateMisc(tarmCtx, regRelIdx);
+ // System registers are 32bit wide
+ regWidth = 32;
+}
+
+void
+TarmacTracerRecordV8::addInstEntry(std::vector<InstPtr>& queue,
+ const TarmacContext& tarmCtx)
+{
+ // Generate an instruction entry in the record and
+ // add it to the Instruction Queue
+ queue.push_back(
+ m5::make_unique<TraceInstEntryV8>(tarmCtx, predicate)
+ );
+}
+
+void
+TarmacTracerRecordV8::addMemEntry(std::vector<MemPtr>& queue,
+ const TarmacContext& tarmCtx)
+{
+ // Generate a memory entry in the record if the record
+ // implies a valid memory access, and add it to the
+ // Memory Queue
+ if (getMemValid()) {
+ queue.push_back(
+ m5::make_unique<TraceMemEntryV8>(tarmCtx,
+ static_cast<uint8_t>(getSize()),
+ getAddr(), getIntData())
+ );
+ }
+}
+
+void
+TarmacTracerRecordV8::addRegEntry(std::vector<RegPtr>& queue,
+ const TarmacContext& tarmCtx)
+{
+ // Generate an entry for every ARM register being
+ // written by the current instruction
+ for (auto reg = 0; reg < staticInst->numDestRegs(); ++reg) {
+
+ RegId reg_id = staticInst->destRegIdx(reg);
+
+ // Creating a single register change entry
+ auto single_reg = genRegister<TraceRegEntryV8>(tarmCtx, reg_id);
+
+ // Copying the entry and adding it to the "list"
+ // of entries to be dumped to trace.
+ queue.push_back(
+ m5::make_unique<TraceRegEntryV8>(single_reg)
+ );
+ }
+
+ // Gem5 is treating CPSR flags as separate registers (CC registers),
+ // in contrast with Tarmac specification: we need to merge the gem5 CC
+ // entries altogether with the CPSR register and produce a single entry.
+ mergeCCEntry<TraceRegEntryV8>(queue, tarmCtx);
+}
+
+void
+TarmacTracerRecordV8::TraceInstEntryV8::print(
+ std::ostream& outs,
+ int verbosity,
+ const std::string &prefix) const
+{
+ // If there is a valid vaddr->paddr translation, print the
+ // physical address, otherwise print the virtual address only.
+ std::string paddr_str = paddrValid? csprintf(":%012x",paddr) :
+ std::string();
+
+ // Pad the opcode.
+ std::string opcode_str = csprintf("%0*x", instSize >> 2, opcode);
+
+ // Print the instruction record formatted according
+ // to the Tarmac specification
+ ccprintf(outs, "%s clk %s %s (%u) %08x%s %s %s %s_%s : %s\n",
+ curTick(), /* Tick time */
+ cpuName, /* Cpu name */
+ taken? "IT" : "IS", /* Instruction taken/skipped */
+ instCount, /* Instruction count */
+ addr, /* Instruction virt address */
+ paddr_str, /* Instruction phys address */
+ opcode_str, /* Instruction opcode */
+ iSetStateToStr(isetstate), /* Instruction Set */
+ opModeToStr(mode), /* Exception level */
+ secureMode? "s" : "ns", /* Security */
+ disassemble); /* Instruction disass */
+}
+
+void
+TarmacTracerRecordV8::TraceMemEntryV8::print(
+ std::ostream& outs,
+ int verbosity,
+ const std::string &prefix) const
+{
+ // Print the memory record formatted according
+ // to the Tarmac specification
+ ccprintf(outs, "%s clk %s M%s%d %08x:%012x %0*x\n",
+ curTick(), /* Tick time */
+ cpuName, /* Cpu name */
+ loadAccess? "R" : "W", /* Access type */
+ size, /* Access size */
+ addr, /* Virt Memory address */
+ paddr, /* Phys Memory address */
+ size*2, /* Padding with access size */
+ data); /* Memory data */
+}
+
+void
+TarmacTracerRecordV8::TraceRegEntryV8::print(
+ std::ostream& outs,
+ int verbosity,
+ const std::string &prefix) const
+{
+ // Print the register record formatted according
+ // to the Tarmac specification
+ if (regValid) {
+ ccprintf(outs, "%s clk %s R %s %0*x\n",
+ curTick(), /* Tick time */
+ cpuName, /* Cpu name */
+ regName, /* Register name */
+ regWidth >> 2, /* Register value padding */
+ valueLo); /* Register value */
+ }
+}
+
+} // namespace Trace
diff --git a/src/arch/arm/tracers/tarmac_record_v8.hh b/src/arch/arm/tracers/tarmac_record_v8.hh
new file mode 100644
index 000000000..adf638f99
--- /dev/null
+++ b/src/arch/arm/tracers/tarmac_record_v8.hh
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2017-2018 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 hereunder. 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: Giacomo Travaglini
+ */
+
+/**
+ * @file: The file contains the informations used to generate records
+ * for ARMv8 cores.
+ */
+
+#ifndef __ARCH_ARM_TRACERS_TARMAC_RECORD_V8_HH__
+#define __ARCH_ARM_TRACERS_TARMAC_RECORD_V8_HH__
+
+#include "tarmac_record.hh"
+
+namespace Trace {
+
+/**
+ * TarmacTracer record for ARMv8 CPUs:
+ * The record is adding some data to the base TarmacTracer
+ * record.
+ */
+class TarmacTracerRecordV8 : public TarmacTracerRecord
+{
+ public:
+
+ /**
+ * General data shared by all v8 entries
+ */
+ struct TraceEntryV8
+ {
+ public:
+ TraceEntryV8(std::string _cpuName)
+ : cpuName(_cpuName)
+ {}
+
+ protected:
+ std::string cpuName;
+ };
+
+ /**
+ * Instruction entry for v8 records
+ */
+ struct TraceInstEntryV8: public TraceInstEntry, TraceEntryV8
+ {
+ public:
+ TraceInstEntryV8(const TarmacContext& tarmCtx, bool predicate);
+
+ virtual void print(std::ostream& outs,
+ int verbosity = 0,
+ const std::string &prefix = "") const override;
+
+ protected:
+ Addr paddr;
+ bool paddrValid;
+ };
+
+ /**
+ * Register entry for v8 records
+ */
+ struct TraceRegEntryV8: public TraceRegEntry, TraceEntryV8
+ {
+ public:
+ TraceRegEntryV8(const TarmacContext& tarmCtx, const RegId& reg);
+
+ virtual void print(std::ostream& outs,
+ int verbosity = 0,
+ const std::string &prefix = "") const override;
+
+ protected:
+ void updateInt(const TarmacContext& tarmCtx,
+ RegIndex regRelIdx) override;
+
+ void updateMisc(const TarmacContext& tarmCtx,
+ RegIndex regRelIdx) override;
+
+ uint8_t regWidth;
+ };
+
+ /**
+ * Memory Entry for V8
+ */
+ struct TraceMemEntryV8: public TraceMemEntry, TraceEntryV8
+ {
+ public:
+ TraceMemEntryV8(const TarmacContext& tarmCtx,
+ uint8_t _size, Addr _addr, uint64_t _data);
+
+ virtual void print(std::ostream& outs,
+ int verbosity = 0,
+ const std::string &prefix = "") const override;
+
+ protected:
+ Addr paddr;
+ };
+
+ public:
+ TarmacTracerRecordV8(Tick _when, ThreadContext *_thread,
+ const StaticInstPtr _staticInst, TheISA::PCState _pc,
+ TarmacTracer& _parent,
+ const StaticInstPtr _macroStaticInst = NULL)
+ : TarmacTracerRecord(_when, _thread, _staticInst, _pc,
+ _parent, _macroStaticInst)
+ {}
+
+ protected:
+ /** Generates an Entry for the executed instruction. */
+ void addInstEntry(std::vector<InstPtr>& queue, const TarmacContext& ptr);
+
+ /** Generates an Entry for every memory access triggered */
+ void addMemEntry(std::vector<MemPtr>& queue, const TarmacContext& ptr);
+
+ /** Generate a Record for every register being written */
+ void addRegEntry(std::vector<RegPtr>& queue, const TarmacContext& ptr);
+};
+
+} // namespace Trace
+
+#endif // __ARCH_ARM_TRACERS_TARMAC_RECORD_V8_HH__
diff --git a/src/arch/arm/tracers/tarmac_tracer.cc b/src/arch/arm/tracers/tarmac_tracer.cc
new file mode 100644
index 000000000..b6f876de5
--- /dev/null
+++ b/src/arch/arm/tracers/tarmac_tracer.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017-2018 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 hereunder. 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: Giacomo Travaglini
+ */
+
+#include "tarmac_tracer.hh"
+
+#include <string>
+
+#include "arch/arm/system.hh"
+#include "cpu/base.hh"
+
+namespace Trace {
+
+std::string
+TarmacContext::tarmacCpuName() const
+{
+ auto id = thread->getCpuPtr()->cpuId();
+ return "cpu" + std::to_string(id);
+}
+
+TarmacTracer::TarmacTracer(const Params *p)
+ : InstTracer(p),
+ startTick(p->start_tick),
+ endTick(p->end_tick)
+{
+ // Wrong parameter setting: The trace end happens before the
+ // trace start.
+ panic_if(startTick > endTick,
+ "Tarmac start point: %lu is bigger than "
+ "Tarmac end point: %lu\n", startTick, endTick);
+
+ // By default cpu tracers in gem5 are not tracing faults
+ // (exceptions).
+ // This is not in compliance with the Tarmac specification:
+ // instructions like SVC, SMC, HVC have to be traced.
+ // Tarmac Tracer is then automatically enabling this behaviour.
+ setDebugFlag("ExecFaulting");
+}
+
+InstRecord *
+TarmacTracer::getInstRecord(Tick when, ThreadContext *tc,
+ const StaticInstPtr staticInst,
+ TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst)
+{
+ // Check if we need to start tracing since we have passed the
+ // tick start point.
+ if (when < startTick || when > endTick)
+ return nullptr;
+
+ if (ArmSystem::highestELIs64(tc)) {
+ // TarmacTracerV8
+ return new TarmacTracerRecordV8(when, tc, staticInst, pc, *this,
+ macroStaticInst);
+ } else {
+ // TarmacTracer
+ return new TarmacTracerRecord(when, tc, staticInst, pc, *this,
+ macroStaticInst);
+ }
+}
+
+} // namespace Trace
+
+Trace::TarmacTracer *
+TarmacTracerParams::create()
+{
+ return new Trace::TarmacTracer(this);
+}
diff --git a/src/arch/arm/tracers/tarmac_tracer.hh b/src/arch/arm/tracers/tarmac_tracer.hh
new file mode 100644
index 000000000..78739999d
--- /dev/null
+++ b/src/arch/arm/tracers/tarmac_tracer.hh
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017-2018 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 hereunder. 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: Giacomo Travaglini
+ */
+
+/**
+ * @file: This file declares the interface of the Tarmac Tracer:
+ * the tracer based on the Tarmac specification.
+ */
+
+#ifndef __ARCH_ARM_TRACERS_TARMAC_TRACER_HH__
+#define __ARCH_ARM_TRACERS_TARMAC_TRACER_HH__
+
+#include "arch/arm/tracers/tarmac_record.hh"
+#include "arch/arm/tracers/tarmac_record_v8.hh"
+#include "params/TarmacTracer.hh"
+#include "sim/insttracer.hh"
+
+class ThreadContext;
+
+namespace Trace {
+
+/**
+ * This object type is encapsulating the informations needed by
+ * a Tarmac record to generate it's own entries.
+ */
+class TarmacContext
+{
+ public:
+ TarmacContext(ThreadContext* _thread,
+ const StaticInstPtr _staticInst,
+ TheISA::PCState _pc)
+ : thread(_thread), staticInst(_staticInst), pc(_pc)
+ {}
+
+ std::string tarmacCpuName() const;
+
+ public:
+ ThreadContext* thread;
+ const StaticInstPtr staticInst;
+ TheISA::PCState pc;
+};
+
+/**
+ * Tarmac Tracer: this tracer generates a new Tarmac Record for
+ * every instruction being executed in gem5.
+ * The record is made by a collection of entries which are stored
+ * in the tracer queues.
+ */
+class TarmacTracer : public InstTracer
+{
+ friend class TarmacTracerRecord;
+ friend class TarmacTracerRecordV8;
+
+ public:
+ typedef TarmacTracerParams Params;
+
+ TarmacTracer(const Params *p);
+
+ /**
+ * Generates a TarmacTracerRecord, depending on the Tarmac version.
+ * At the moment supported formats are:
+ * - Tarmac
+ * - TarmacV8
+ */
+ InstRecord* getInstRecord(Tick when, ThreadContext *tc,
+ const StaticInstPtr staticInst,
+ TheISA::PCState pc,
+ const StaticInstPtr macroStaticInst = NULL);
+
+ protected:
+ typedef std::unique_ptr<Printable> PEntryPtr;
+ typedef TarmacTracerRecord::InstPtr InstPtr;
+ typedef TarmacTracerRecord::MemPtr MemPtr;
+ typedef TarmacTracerRecord::RegPtr RegPtr;
+
+ /**
+ * startTick and endTick allow to trace a specific window of ticks
+ * rather than the entire CPU execution.
+ */
+ Tick startTick;
+ Tick endTick;
+
+ /**
+ * Collection of heterogeneous printable entries: could be
+ * representing either instructions, register or memory entries.
+ * When dealing with MacroInstructions the following separate queues
+ * will be used. micro-instruction entries will be buffered and
+ * dumped to the tracefile only at the end of the Macro.
+ */
+ std::vector<InstPtr> instQueue;
+ std::vector<MemPtr> memQueue;
+ std::vector<RegPtr> regQueue;
+};
+
+} // namespace Trace
+
+#endif // __ARCH_ARM_TRACERS_TARMAC_TRACER_HH__