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>
This commit is contained in:
@@ -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')
|
||||
|
||||
@@ -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")
|
||||
|
||||
457
src/arch/arm/tracers/tarmac_record.cc
Normal file
457
src/arch/arm/tracers/tarmac_record.cc
Normal file
@@ -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 ®Queue = 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
|
||||
265
src/arch/arm/tracers/tarmac_record.hh
Normal file
265
src/arch/arm/tracers/tarmac_record.hh
Normal file
@@ -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__
|
||||
248
src/arch/arm/tracers/tarmac_record_v8.cc
Normal file
248
src/arch/arm/tracers/tarmac_record_v8.cc
Normal file
@@ -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
|
||||
153
src/arch/arm/tracers/tarmac_record_v8.hh
Normal file
153
src/arch/arm/tracers/tarmac_record_v8.hh
Normal file
@@ -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__
|
||||
103
src/arch/arm/tracers/tarmac_tracer.cc
Normal file
103
src/arch/arm/tracers/tarmac_tracer.cc
Normal file
@@ -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);
|
||||
}
|
||||
132
src/arch/arm/tracers/tarmac_tracer.hh
Normal file
132
src/arch/arm/tracers/tarmac_tracer.hh
Normal file
@@ -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__
|
||||
Reference in New Issue
Block a user