少しいろいろと、gem5の命令トレースの方法を解析していた。
gem5はcommit.cc
において、dump()
により命令トレースの出力を行う。
src/cpu/o3/commit.cc
bool Commit::commitHead(const DynInstPtr &head_inst, unsigned inst_num) { assert(head_inst); ThreadID tid = head_inst->threadNumber; /* ... 途中省略 ... */ DPRINTF(Commit, "[tid:%i] [sn:%llu] Committing instruction with fault\n", tid, head_inst->seqNum); if (head_inst->traceData) { // We ignore ReExecution "faults" here as they are not real // (architectural) faults but signal flush/replays. if (debug::ExecFaulting && dynamic_cast<ReExec*>(inst_fault.get()) == nullptr) { head_inst->traceData->setFaulting(true); head_inst->traceData->setFetchSeq(head_inst->seqNum); head_inst->traceData->setCPSeq(thread[tid]->numOp); head_inst->traceData->dump(); } delete head_inst->traceData; head_inst->traceData = NULL; }
traceData
に何らかの情報が入っていれば、dump()
により出力を行う。
src/cpu/o3/dyn_inst.hh
/** InstRecord that tracks this instructions. */ trace::InstRecord *traceData = nullptr;
このtraceData
がどのように設定されるか、という話なのだが、これをいろいろ追いかけて行ってもよくわからないところが多い。
build/RISCV/arch/riscv/generated/exec-ns.cc.inc
Fault Addi::execute( ExecContext *xc, trace::InstRecord *traceData) const { int64_t Rd = 0; int64_t Rs1 = 0; ; Rs1 = xc->getRegOperand(this, 0); ; Rd = rvSext(Rs1 + imm); ; { RegVal final_val = Rd; xc->setRegOperand(this, 0, final_val); if (traceData) { traceData->setData(intRegClass, final_val); } }; return NoFault; }
命令をフェッチしたときに、ここでtraceData
が挿入されるのかな?
src/cpu/o3/fetch.cc
DynInstPtr Fetch::buildInst(ThreadID tid, StaticInstPtr staticInst, StaticInstPtr curMacroop, const PCStateBase &this_pc, const PCStateBase &next_pc, bool trace) { // Get a sequence number. InstSeqNum seq = cpu->getAndIncrementInstSeq(); /* ... 途中省略 ... */ #if TRACING_ON if (trace) { instruction->traceData = cpu->getTracer()->getInstRecord(curTick(), cpu->tcBase(tid), instruction->staticInst, this_pc, curMacroop); } #else instruction->traceData = NULL; #endif
src/sim/insttracer.hh
void setData(uint64_t d) { data.asInt = d; dataStatus = DataInt64; } void setData(uint32_t d) { data.asInt = d; dataStatus = DataInt32; } void setData(uint16_t d) { data.asInt = d; dataStatus = DataInt16; } void setData(uint8_t d) { data.asInt = d; dataStatus = DataInt8; }