cpu-minor: Use PCStateBase in the minor CPU DynInst class.
Change-Id: I43d538568d473e27cdbfe6ea77c317b18cfdf18f Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52047 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: ZHENGRONG WANG <seanyukigeek@gmail.com> Maintainer: ZHENGRONG WANG <seanyukigeek@gmail.com>
This commit is contained in:
@@ -115,7 +115,7 @@ dynInstAddTracing(MinorDynInstPtr inst, StaticInstPtr static_inst,
|
||||
{
|
||||
inst->traceData = cpu.getTracer()->getInstRecord(curTick(),
|
||||
cpu.getContext(inst->id.threadId),
|
||||
inst->staticInst, inst->pc, static_inst);
|
||||
inst->staticInst, *inst->pc, static_inst);
|
||||
|
||||
/* Use the execSeqNum as the fetch sequence number as this most closely
|
||||
* matches the other processor models' idea of fetch sequence */
|
||||
@@ -176,7 +176,7 @@ Decode::evaluate()
|
||||
|
||||
/* Set up PC for the next micro-op emitted */
|
||||
if (!decode_info.inMacroop) {
|
||||
decode_info.microopPC = inst->pc;
|
||||
set(decode_info.microopPC, *inst->pc);
|
||||
decode_info.inMacroop = true;
|
||||
}
|
||||
|
||||
@@ -188,14 +188,15 @@ Decode::evaluate()
|
||||
|
||||
output_inst =
|
||||
new MinorDynInst(static_micro_inst, inst->id);
|
||||
output_inst->pc = decode_info.microopPC;
|
||||
set(output_inst->pc, decode_info.microopPC);
|
||||
output_inst->fault = NoFault;
|
||||
|
||||
/* Allow a predicted next address only on the last
|
||||
* microop */
|
||||
if (static_micro_inst->isLastMicroop()) {
|
||||
output_inst->predictedTaken = inst->predictedTaken;
|
||||
output_inst->predictedTarget = inst->predictedTarget;
|
||||
set(output_inst->predictedTarget,
|
||||
inst->predictedTarget);
|
||||
}
|
||||
|
||||
DPRINTF(Decode, "Microop decomposition inputIndex:"
|
||||
|
||||
@@ -120,7 +120,7 @@ std::ostream &
|
||||
operator <<(std::ostream &os, const MinorDynInst &inst)
|
||||
{
|
||||
os << inst.id << " pc: 0x"
|
||||
<< std::hex << inst.pc.instAddr() << std::dec << " (";
|
||||
<< std::hex << inst.pc->instAddr() << std::dec << " (";
|
||||
|
||||
if (inst.isFault())
|
||||
os << "fault: \"" << inst.fault->name() << '"';
|
||||
@@ -180,7 +180,7 @@ MinorDynInst::minorTraceInst(const Named &named_object,
|
||||
{
|
||||
if (isFault()) {
|
||||
minorInst(named_object, "id=F;%s addr=0x%x fault=\"%s\"\n",
|
||||
id, pc.instAddr(), fault->name());
|
||||
id, pc->instAddr(), fault->name());
|
||||
} else {
|
||||
unsigned int num_src_regs = staticInst->numSrcRegs();
|
||||
unsigned int num_dest_regs = staticInst->numDestRegs();
|
||||
@@ -222,7 +222,7 @@ MinorDynInst::minorTraceInst(const Named &named_object,
|
||||
|
||||
minorInst(named_object, "id=%s addr=0x%x inst=\"%s\" class=%s"
|
||||
" flags=\"%s\"%s%s\n",
|
||||
id, pc.instAddr(),
|
||||
id, pc->instAddr(),
|
||||
(staticInst->opClass() == No_OpClass ?
|
||||
"(invalid)" : staticInst->disassemble(0,NULL)),
|
||||
enums::OpClassStrings[staticInst->opClass()],
|
||||
|
||||
@@ -173,64 +173,64 @@ class MinorDynInst : public RefCounted
|
||||
InstId id;
|
||||
|
||||
/** Trace information for this instruction's execution */
|
||||
Trace::InstRecord *traceData;
|
||||
Trace::InstRecord *traceData = nullptr;
|
||||
|
||||
/** The fetch address of this instruction */
|
||||
TheISA::PCState pc;
|
||||
std::unique_ptr<PCStateBase> pc;
|
||||
|
||||
/** This is actually a fault masquerading as an instruction */
|
||||
Fault fault;
|
||||
|
||||
/** Tried to predict the destination of this inst (if a control
|
||||
* instruction or a sys call) */
|
||||
bool triedToPredict;
|
||||
bool triedToPredict = false;
|
||||
|
||||
/** This instruction was predicted to change control flow and
|
||||
* the following instructions will have a newer predictionSeqNum */
|
||||
bool predictedTaken;
|
||||
bool predictedTaken = false;
|
||||
|
||||
/** Predicted branch target */
|
||||
TheISA::PCState predictedTarget;
|
||||
std::unique_ptr<PCStateBase> predictedTarget;
|
||||
|
||||
/** Fields only set during execution */
|
||||
|
||||
/** FU this instruction is issued to */
|
||||
unsigned int fuIndex;
|
||||
unsigned int fuIndex = 0;
|
||||
|
||||
/** This instruction is in the LSQ, not a functional unit */
|
||||
bool inLSQ;
|
||||
bool inLSQ = false;
|
||||
|
||||
/** Translation fault in case of a mem ref */
|
||||
Fault translationFault;
|
||||
|
||||
/** The instruction has been sent to the store buffer */
|
||||
bool inStoreBuffer;
|
||||
bool inStoreBuffer = false;
|
||||
|
||||
/** Can this instruction be executed out of order. In this model,
|
||||
* this only happens with mem refs that need to be issued early
|
||||
* to allow other instructions to fill the fetch delay */
|
||||
bool canEarlyIssue;
|
||||
bool canEarlyIssue = false;
|
||||
|
||||
/** Flag controlling conditional execution of the instruction */
|
||||
bool predicate;
|
||||
bool predicate = true;
|
||||
|
||||
/** Flag controlling conditional execution of the memory access associated
|
||||
* with the instruction (only meaningful for loads/stores) */
|
||||
bool memAccPredicate;
|
||||
bool memAccPredicate = true;
|
||||
|
||||
/** execSeqNum of the latest inst on which this inst depends.
|
||||
* This can be used as a sanity check for dependency ordering
|
||||
* where slightly out of order execution is required (notably
|
||||
* initiateAcc for memory ops) */
|
||||
InstSeqNum instToWaitFor;
|
||||
InstSeqNum instToWaitFor = 0;
|
||||
|
||||
/** Extra delay at the end of the pipeline */
|
||||
Cycles extraCommitDelay;
|
||||
TimingExpr *extraCommitDelayExpr;
|
||||
Cycles extraCommitDelay{0};
|
||||
TimingExpr *extraCommitDelayExpr = nullptr;
|
||||
|
||||
/** Once issued, extraCommitDelay becomes minimumCommitCycle
|
||||
* to account for delay in absolute time */
|
||||
Cycles minimumCommitCycle;
|
||||
Cycles minimumCommitCycle{0};
|
||||
|
||||
/** Flat register indices so that, when clearing the scoreboard, we
|
||||
* have the same register indices as when the instruction was marked
|
||||
@@ -239,13 +239,7 @@ class MinorDynInst : public RefCounted
|
||||
|
||||
public:
|
||||
MinorDynInst(StaticInstPtr si, InstId id_=InstId(), Fault fault_=NoFault) :
|
||||
staticInst(si), id(id_), traceData(NULL),
|
||||
pc(TheISA::PCState(0)), fault(fault_),
|
||||
triedToPredict(false), predictedTaken(false),
|
||||
fuIndex(0), inLSQ(false), translationFault(NoFault),
|
||||
inStoreBuffer(false), canEarlyIssue(false), predicate(true),
|
||||
memAccPredicate(true), instToWaitFor(0), extraCommitDelay(Cycles(0)),
|
||||
extraCommitDelayExpr(NULL), minimumCommitCycle(Cycles(0)),
|
||||
staticInst(si), id(id_), fault(fault_), translationFault(NoFault),
|
||||
flatDestRegIdx(si ? si->numDestRegs() : 0)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -93,8 +93,8 @@ class ExecContext : public gem5::ExecContext
|
||||
execute(execute_),
|
||||
inst(inst_)
|
||||
{
|
||||
DPRINTF(MinorExecute, "ExecContext setting PC: %s\n", inst->pc);
|
||||
pcState(inst->pc);
|
||||
DPRINTF(MinorExecute, "ExecContext setting PC: %s\n", *inst->pc);
|
||||
pcState(inst->pc->as<TheISA::PCState>());
|
||||
setPredicate(inst->readPredicate());
|
||||
setMemAccPredicate(inst->readMemAccPredicate());
|
||||
thread.setIntReg(zeroReg, 0);
|
||||
|
||||
@@ -224,7 +224,7 @@ void
|
||||
Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
|
||||
{
|
||||
ThreadContext *thread = cpu.getContext(inst->id.threadId);
|
||||
const TheISA::PCState &pc_before = inst->pc;
|
||||
const std::unique_ptr<PCStateBase> pc_before(inst->pc->clone());
|
||||
TheISA::PCState target = thread->pcState();
|
||||
|
||||
/* Force a branch for SerializeAfter/SquashAfter instructions
|
||||
@@ -236,10 +236,10 @@ Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
|
||||
inst->staticInst->isSquashAfter());
|
||||
|
||||
DPRINTF(Branch, "tryToBranch before: %s after: %s%s\n",
|
||||
pc_before, target, (force_branch ? " (forcing)" : ""));
|
||||
*pc_before, target, (force_branch ? " (forcing)" : ""));
|
||||
|
||||
/* Will we change the PC to something other than the next instruction? */
|
||||
bool must_branch = pc_before != target ||
|
||||
bool must_branch = *pc_before != target ||
|
||||
fault != NoFault ||
|
||||
force_branch;
|
||||
|
||||
@@ -251,7 +251,7 @@ Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
|
||||
thread->pcState(target);
|
||||
|
||||
DPRINTF(Branch, "Advancing current PC from: %s to: %s\n",
|
||||
pc_before, target);
|
||||
*pc_before, target);
|
||||
}
|
||||
|
||||
if (inst->predictedTaken && !force_branch) {
|
||||
@@ -261,24 +261,26 @@ Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
|
||||
* intended PC value */
|
||||
DPRINTF(Branch, "Predicted a branch from 0x%x to 0x%x but"
|
||||
" none happened inst: %s\n",
|
||||
inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
|
||||
inst->pc->instAddr(), inst->predictedTarget->instAddr(),
|
||||
*inst);
|
||||
|
||||
reason = BranchData::BadlyPredictedBranch;
|
||||
} else if (inst->predictedTarget == target) {
|
||||
} else if (*inst->predictedTarget == target) {
|
||||
/* Branch prediction got the right target, kill the branch and
|
||||
* carry on.
|
||||
* Note that this information to the branch predictor might get
|
||||
* overwritten by a "real" branch during this cycle */
|
||||
DPRINTF(Branch, "Predicted a branch from 0x%x to 0x%x correctly"
|
||||
" inst: %s\n",
|
||||
inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
|
||||
inst->pc->instAddr(), inst->predictedTarget->instAddr(),
|
||||
*inst);
|
||||
|
||||
reason = BranchData::CorrectlyPredictedBranch;
|
||||
} else {
|
||||
/* Branch prediction got the wrong target */
|
||||
DPRINTF(Branch, "Predicted a branch from 0x%x to 0x%x"
|
||||
" but got the wrong target (actual: 0x%x) inst: %s\n",
|
||||
inst->pc.instAddr(), inst->predictedTarget.instAddr(),
|
||||
inst->pc->instAddr(), inst->predictedTarget->instAddr(),
|
||||
target.instAddr(), *inst);
|
||||
|
||||
reason = BranchData::BadlyPredictedBranchTarget;
|
||||
@@ -286,7 +288,7 @@ Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
|
||||
} else if (must_branch) {
|
||||
/* Unpredicted branch */
|
||||
DPRINTF(Branch, "Unpredicted branch from 0x%x to 0x%x inst: %s\n",
|
||||
inst->pc.instAddr(), target.instAddr(), *inst);
|
||||
inst->pc->instAddr(), target.instAddr(), *inst);
|
||||
|
||||
reason = BranchData::UnpredictedBranch;
|
||||
} else {
|
||||
@@ -890,7 +892,7 @@ Execute::doInstCommitAccounting(MinorDynInstPtr inst)
|
||||
if (inst->traceData)
|
||||
inst->traceData->setCPSeq(thread->numOp);
|
||||
|
||||
cpu.probeInstCommit(inst->staticInst, inst->pc.instAddr());
|
||||
cpu.probeInstCommit(inst->staticInst, inst->pc->instAddr());
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -192,26 +192,24 @@ void
|
||||
Fetch2::predictBranch(MinorDynInstPtr inst, BranchData &branch)
|
||||
{
|
||||
Fetch2ThreadInfo &thread = fetchInfo[inst->id.threadId];
|
||||
TheISA::PCState inst_pc = inst->pc;
|
||||
|
||||
assert(!inst->predictedTaken);
|
||||
|
||||
/* Skip non-control/sys call instructions */
|
||||
if (inst->staticInst->isControl() ||
|
||||
inst->staticInst->isSyscall())
|
||||
{
|
||||
if (inst->staticInst->isControl() || inst->staticInst->isSyscall()){
|
||||
std::unique_ptr<PCStateBase> inst_pc(inst->pc->clone());
|
||||
|
||||
/* Tried to predict */
|
||||
inst->triedToPredict = true;
|
||||
|
||||
DPRINTF(Branch, "Trying to predict for inst: %s\n", *inst);
|
||||
|
||||
if (branchPredictor.predict(inst->staticInst,
|
||||
inst->id.fetchSeqNum, inst_pc,
|
||||
inst->id.threadId))
|
||||
{
|
||||
inst->id.fetchSeqNum, inst_pc->as<TheISA::PCState>(),
|
||||
inst->id.threadId)) {
|
||||
set(branch.target, *inst_pc);
|
||||
inst->predictedTaken = true;
|
||||
inst->predictedTarget = inst_pc;
|
||||
branch.target = inst_pc;
|
||||
set(inst->predictedTarget, inst_pc);
|
||||
}
|
||||
} else {
|
||||
DPRINTF(Branch, "Not attempting prediction for inst: %s\n", *inst);
|
||||
@@ -226,7 +224,7 @@ Fetch2::predictBranch(MinorDynInstPtr inst, BranchData &branch)
|
||||
BranchData new_branch = BranchData(BranchData::BranchPrediction,
|
||||
inst->id.threadId,
|
||||
inst->id.streamSeqNum, thread.predictionSeqNum + 1,
|
||||
inst->predictedTarget, inst);
|
||||
inst->predictedTarget->as<TheISA::PCState>(), inst);
|
||||
|
||||
/* Mark with a new prediction number by the stream number of the
|
||||
* instruction causing the prediction */
|
||||
@@ -235,7 +233,7 @@ Fetch2::predictBranch(MinorDynInstPtr inst, BranchData &branch)
|
||||
|
||||
DPRINTF(Branch, "Branch predicted taken inst: %s target: %s"
|
||||
" new predictionSeqNum: %d\n",
|
||||
*inst, inst->predictedTarget, thread.predictionSeqNum);
|
||||
*inst, *inst->predictedTarget, thread.predictionSeqNum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +367,7 @@ Fetch2::evaluate()
|
||||
* not been set */
|
||||
assert(dyn_inst->id.execSeqNum == 0);
|
||||
|
||||
dyn_inst->pc = fetch_info.pc;
|
||||
set(dyn_inst->pc, fetch_info.pc);
|
||||
|
||||
/* Pack a faulting instruction but allow other
|
||||
* instructions to be generated. (Fetch2 makes no
|
||||
@@ -412,7 +410,7 @@ Fetch2::evaluate()
|
||||
* has not been set */
|
||||
assert(dyn_inst->id.execSeqNum == 0);
|
||||
|
||||
dyn_inst->pc = fetch_info.pc;
|
||||
set(dyn_inst->pc, fetch_info.pc);
|
||||
DPRINTF(Fetch, "decoder inst %s\n", *dyn_inst);
|
||||
|
||||
// Collect some basic inst class stats
|
||||
|
||||
@@ -1648,7 +1648,7 @@ LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
|
||||
request->request->setVirt(
|
||||
addr, size, flags, cpu.dataRequestorId(),
|
||||
/* I've no idea why we need the PC, but give it */
|
||||
inst->pc.instAddr(), std::move(amo_op));
|
||||
inst->pc->instAddr(), std::move(amo_op));
|
||||
request->request->setByteEnable(byte_enable);
|
||||
|
||||
requests.push(request);
|
||||
|
||||
Reference in New Issue
Block a user