diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index fc108484d3..b2da358d31 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -94,7 +94,7 @@ struct IEWStruct DynInstPtr mispredictInst[MaxThreads]; Addr mispredPC[MaxThreads]; InstSeqNum squashedSeqNum[MaxThreads]; - TheISA::PCState pc[MaxThreads]; + std::unique_ptr pc[MaxThreads]; bool squash[MaxThreads]; bool branchMispredict[MaxThreads]; @@ -114,7 +114,7 @@ struct TimeStruct { struct DecodeComm { - TheISA::PCState nextPC; + std::unique_ptr nextPC; DynInstPtr mispredictInst; DynInstPtr squashInst; InstSeqNum doneSeqNum; @@ -169,7 +169,7 @@ struct TimeStruct /// The pc of the next instruction to execute. This is the next /// instruction for a branch mispredict, but the same instruction for /// order violation and the like - TheISA::PCState pc; // *F + std::unique_ptr pc; // *F /// Provide fetch the instruction that mispredicted, if this /// pointer is not-null a misprediction occured diff --git a/src/cpu/o3/commit.cc b/src/cpu/o3/commit.cc index 421f1e53a7..01ec0c8270 100644 --- a/src/cpu/o3/commit.cc +++ b/src/cpu/o3/commit.cc @@ -120,7 +120,7 @@ Commit::Commit(CPU *_cpu, const O3CPUParams ¶ms) trapSquash[tid] = false; tcSquash[tid] = false; squashAfterInst[tid] = nullptr; - pc[tid].set(0); + pc[tid].reset(params.isa[0]->newPCState()); youngestSeqNum[tid] = 0; lastCommitedSeqNum[tid] = 0; trapInFlight[tid] = false; @@ -340,7 +340,7 @@ Commit::clearStates(ThreadID tid) committedStores[tid] = false; trapSquash[tid] = false; tcSquash[tid] = false; - pc[tid].set(0); + pc[tid].reset(cpu->tcBase(tid)->getIsaPtr()->newPCState()); lastCommitedSeqNum[tid] = 0; squashAfterInst[tid] = NULL; } @@ -382,7 +382,7 @@ Commit::isDrained() const * address mappings. This can happen on for example x86. */ for (ThreadID tid = 0; tid < numThreads; tid++) { - if (pc[tid].microPC() != 0) + if (pc[tid]->microPC() != 0) return false; } @@ -561,7 +561,7 @@ Commit::squashAll(ThreadID tid) toIEW->commitInfo[tid].mispredictInst = NULL; toIEW->commitInfo[tid].squashInst = NULL; - toIEW->commitInfo[tid].pc = pc[tid]; + set(toIEW->commitInfo[tid].pc, pc[tid]); } void @@ -569,7 +569,7 @@ Commit::squashFromTrap(ThreadID tid) { squashAll(tid); - DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]); + DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", *pc[tid]); thread[tid]->trapPending = false; thread[tid]->noSquashFromTC = false; @@ -586,7 +586,7 @@ Commit::squashFromTC(ThreadID tid) { squashAll(tid); - DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]); + DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", *pc[tid]); thread[tid]->noSquashFromTC = false; assert(!thread[tid]->trapPending); @@ -601,7 +601,7 @@ void Commit::squashFromSquashAfter(ThreadID tid) { DPRINTF(Commit, "Squashing after squash after request, " - "restarting at PC %s\n", pc[tid]); + "restarting at PC %s\n", *pc[tid]); squashAll(tid); // Make sure to inform the fetch stage of which instruction caused @@ -843,8 +843,7 @@ Commit::commit() } DPRINTF(Commit, "[tid:%i] Redirecting to PC %#x\n", - tid, - fromIEW->pc[tid].nextInstAddr()); + tid, *fromIEW->pc[tid]); commitStatus[tid] = ROBSquashing; @@ -884,7 +883,7 @@ Commit::commit() ++stats.branchMispredicts; } - toIEW->commitInfo[tid].pc = fromIEW->pc[tid]; + set(toIEW->commitInfo[tid].pc, fromIEW->pc[tid]); } if (commitStatus[tid] == ROBSquashing) { @@ -1014,7 +1013,7 @@ Commit::commitInsts() // Record that the number of ROB entries has changed. changedROBNumEntries[tid] = true; } else { - pc[tid] = head_inst->pcState(); + set(pc[tid], head_inst->pcState()); // Try to commit the head instruction. bool commit_success = commitHead(head_inst, num_committed); @@ -1064,9 +1063,9 @@ Commit::commitInsts() cpu->checker->verify(head_inst); } - cpu->traceFunctions(pc[tid].instAddr()); + cpu->traceFunctions(pc[tid]->instAddr()); - head_inst->staticInst->advancePC(pc[tid]); + head_inst->staticInst->advancePC(*pc[tid]); // Keep track of the last sequence number commited lastCommitedSeqNum[tid] = head_inst->seqNum; @@ -1077,12 +1076,12 @@ Commit::commitInsts() squashAfter(tid, head_inst); if (drainPending) { - if (pc[tid].microPC() == 0 && interrupt == NoFault && + if (pc[tid]->microPC() == 0 && interrupt == NoFault && !thread[tid]->trapPending) { // Last architectually committed instruction. // Squash the pipeline, stall fetch, and use // drainImminent to disable interrupts - DPRINTF(Drain, "Draining: %i:%s\n", tid, pc[tid]); + DPRINTF(Drain, "Draining: %i:%s\n", tid, *pc[tid]); squashAfter(tid, head_inst); cpu->commitDrained(tid); drainImminent = true; @@ -1101,11 +1100,11 @@ Commit::commitInsts() assert(!thread[tid]->noSquashFromTC && !thread[tid]->trapPending); do { - oldpc = pc[tid].instAddr(); + oldpc = pc[tid]->instAddr(); thread[tid]->pcEventQueue.service( oldpc, thread[tid]->getTC()); count++; - } while (oldpc != pc[tid].instAddr()); + } while (oldpc != pc[tid]->instAddr()); if (count > 1) { DPRINTF(Commit, "PC skip function event, stopping commit\n"); diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index bcb7c237a2..8a005e23af 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -306,20 +306,23 @@ class Commit public: /** Reads the PC of a specific thread. */ - TheISA::PCState pcState(ThreadID tid) { return pc[tid]; } + const PCStateBase &pcState(ThreadID tid) { return *pc[tid]; } /** Sets the PC of a specific thread. */ - void pcState(const TheISA::PCState &val, ThreadID tid) - { pc[tid] = val; } + void pcState(const PCStateBase &val, ThreadID tid) { set(pc[tid], val); } /** Returns the PC of a specific thread. */ - Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); } + Addr instAddr(ThreadID tid) { return pc[tid]->instAddr(); } /** Returns the next PC of a specific thread. */ - Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); } + Addr + nextInstAddr(ThreadID tid) + { + return pc[tid]->as().nextInstAddr(); + } /** Reads the micro PC of a specific thread. */ - Addr microPC(ThreadID tid) { return pc[tid].microPC(); } + Addr microPC(ThreadID tid) { return pc[tid]->microPC(); } private: /** Time buffer interface. */ @@ -431,7 +434,7 @@ class Commit /** The commit PC state of each thread. Refers to the instruction that * is currently being processed/committed. */ - TheISA::PCState pc[MaxThreads]; + std::unique_ptr pc[MaxThreads]; /** The sequence number of the youngest valid instruction in the ROB. */ InstSeqNum youngestSeqNum[MaxThreads]; diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index a155d789c5..05d3a51966 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -1310,7 +1310,7 @@ CPU::setArchCCReg(int reg_idx, RegVal val, ThreadID tid) TheISA::PCState CPU::pcState(ThreadID tid) { - return commit.pcState(tid); + return commit.pcState(tid).as(); } void diff --git a/src/cpu/o3/decode.cc b/src/cpu/o3/decode.cc index 5a275738c9..d10e19a2a3 100644 --- a/src/cpu/o3/decode.cc +++ b/src/cpu/o3/decode.cc @@ -715,13 +715,13 @@ Decode::decodeInsts(ThreadID tid) { ++stats.branchResolved; - if (*inst->branchTarget() != inst->readPredTarg()) { + std::unique_ptr target = inst->branchTarget(); + if (*target != inst->readPredTarg()) { ++stats.branchMispred; // Might want to set some sort of boolean and just do // a check at the end squash(inst, inst->threadNumber); - std::unique_ptr target = inst->branchTarget(); DPRINTF(Decode, "[tid:%i] [sn:%llu] " @@ -729,7 +729,7 @@ Decode::decodeInsts(ThreadID tid) PredPC: %s\n", tid, inst->seqNum, inst->readPredTarg(), *target); //The micro pc after an instruction level branch should be 0 - inst->setPredTarg(target->as()); + inst->setPredTarg(*target); break; } } diff --git a/src/cpu/o3/dyn_inst.cc b/src/cpu/o3/dyn_inst.cc index 37db1ed06f..8284c9a113 100644 --- a/src/cpu/o3/dyn_inst.cc +++ b/src/cpu/o3/dyn_inst.cc @@ -53,11 +53,10 @@ namespace o3 { DynInst::DynInst(const StaticInstPtr &static_inst, - const StaticInstPtr &_macroop, TheISA::PCState _pc, - TheISA::PCState pred_pc, InstSeqNum seq_num, CPU *_cpu) - : seqNum(seq_num), staticInst(static_inst), cpu(_cpu), pc(_pc), + const StaticInstPtr &_macroop, InstSeqNum seq_num, CPU *_cpu) + : seqNum(seq_num), staticInst(static_inst), cpu(_cpu), regs(staticInst->numSrcRegs(), staticInst->numDestRegs()), - predPC(pred_pc), macroop(_macroop) + macroop(_macroop) { regs.init(); @@ -90,9 +89,18 @@ DynInst::DynInst(const StaticInstPtr &static_inst, } +DynInst::DynInst(const StaticInstPtr &static_inst, + const StaticInstPtr &_macroop, const PCStateBase &_pc, + const PCStateBase &pred_pc, InstSeqNum seq_num, CPU *_cpu) + : DynInst(static_inst, _macroop, seq_num, _cpu) +{ + set(pc, _pc); + set(predPC, pred_pc); +} + DynInst::DynInst(const StaticInstPtr &_staticInst, const StaticInstPtr &_macroop) - : DynInst(_staticInst, _macroop, {}, {}, 0, nullptr) + : DynInst(_staticInst, _macroop, 0, nullptr) {} DynInst::~DynInst() @@ -166,8 +174,8 @@ DynInst::dumpSNList() void DynInst::dump() { - cprintf("T%d : %#08d `", threadNumber, pc.instAddr()); - std::cout << staticInst->disassemble(pc.instAddr()); + cprintf("T%d : %#08d `", threadNumber, pc->instAddr()); + std::cout << staticInst->disassemble(pc->instAddr()); cprintf("'\n"); } @@ -175,8 +183,8 @@ void DynInst::dump(std::string &outstring) { std::ostringstream s; - s << "T" << threadNumber << " : 0x" << pc.instAddr() << " " - << staticInst->disassemble(pc.instAddr()); + s << "T" << threadNumber << " : 0x" << pc->instAddr() << " " + << staticInst->disassemble(pc->instAddr()); outstring = s.str(); } diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 38815b1d42..c7e99a4f12 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -75,13 +75,17 @@ namespace o3 class DynInst : public ExecContext, public RefCounted { + private: + DynInst(const StaticInstPtr &staticInst, const StaticInstPtr ¯oop, + InstSeqNum seq_num, CPU *cpu); + public: // The list of instructions iterator type. typedef typename std::list::iterator ListIt; /** BaseDynInst constructor given a binary instruction. */ DynInst(const StaticInstPtr &staticInst, const StaticInstPtr - ¯oop, TheISA::PCState pc, TheISA::PCState predPC, + ¯oop, const PCStateBase &pc, const PCStateBase &pred_pc, InstSeqNum seq_num, CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ @@ -182,7 +186,7 @@ class DynInst : public ExecContext, public RefCounted std::queue instResult; /** PC state for this instruction. */ - TheISA::PCState pc; + std::unique_ptr pc; /** Values to be written to the destination misc. registers. */ std::vector _destMiscRegVal; @@ -361,7 +365,7 @@ class DynInst : public ExecContext, public RefCounted ////////////////////// Branch Data /////////////// /** Predicted PC state after this instruction. */ - TheISA::PCState predPC; + std::unique_ptr predPC; /** The Macroop if one exists */ const StaticInstPtr macroop; @@ -551,18 +555,22 @@ class DynInst : public ExecContext, public RefCounted bool doneTargCalc() { return false; } /** Set the predicted target of this current instruction. */ - void setPredTarg(const TheISA::PCState &_predPC) { predPC = _predPC; } + void setPredTarg(const PCStateBase &pred_pc) { set(predPC, pred_pc); } - const TheISA::PCState &readPredTarg() { return predPC; } + const PCStateBase &readPredTarg() { return *predPC; } /** Returns the predicted PC immediately after the branch. */ - Addr predInstAddr() { return predPC.instAddr(); } + Addr predInstAddr() { return predPC->instAddr(); } /** Returns the predicted PC two instructions after the branch */ - Addr predNextInstAddr() { return predPC.nextInstAddr(); } + Addr + predNextInstAddr() + { + return predPC->as().nextInstAddr(); + } /** Returns the predicted micro PC after the branch */ - Addr predMicroPC() { return predPC.microPC(); } + Addr predMicroPC() { return predPC->microPC(); } /** Returns whether the instruction was predicted taken or not. */ bool readPredTaken() { return instFlags[PredTaken]; } @@ -577,9 +585,9 @@ class DynInst : public ExecContext, public RefCounted bool mispredicted() { - TheISA::PCState tempPC = pc; - staticInst->advancePC(tempPC); - return !(tempPC == predPC); + std::unique_ptr next_pc(pc->clone()); + staticInst->advancePC(*next_pc); + return *next_pc != *predPC; } // @@ -720,7 +728,7 @@ class DynInst : public ExecContext, public RefCounted std::unique_ptr branchTarget() const { - return staticInst->branchTarget(pc); + return staticInst->branchTarget(*pc); } /** Returns the number of source registers. */ @@ -941,19 +949,27 @@ class DynInst : public ExecContext, public RefCounted } /** Read the PC state of this instruction. */ - TheISA::PCState pcState() const override { return pc; } + TheISA::PCState + pcState() const override + { + return pc->as(); + } /** Set the PC state of this instruction. */ - void pcState(const TheISA::PCState &val) override { pc = val; } + void pcState(const TheISA::PCState &val) override { set(pc, val); } /** Read the PC of this instruction. */ - Addr instAddr() const { return pc.instAddr(); } + Addr instAddr() const { return pc->instAddr(); } /** Read the PC of the next instruction. */ - Addr nextInstAddr() const { return pc.nextInstAddr(); } + Addr + nextInstAddr() const + { + return pc->as().nextInstAddr(); + } /**Read the micro PC of this instruction. */ - Addr microPC() const { return pc.microPC(); } + Addr microPC() const { return pc->microPC(); } bool readPredicate() const override { return instFlags[Predicate]; } diff --git a/src/cpu/o3/fetch.cc b/src/cpu/o3/fetch.cc index cfc3a83e55..b87af346b4 100644 --- a/src/cpu/o3/fetch.cc +++ b/src/cpu/o3/fetch.cc @@ -120,7 +120,7 @@ Fetch::Fetch(CPU *_cpu, const O3CPUParams ¶ms) for (int i = 0; i < MaxThreads; i++) { fetchStatus[i] = Idle; decoder[i] = nullptr; - pc[i].set(0); + pc[i].reset(params.isa[0]->newPCState()); fetchOffset[i] = 0; macroop[i] = nullptr; delayedCommit[i] = false; @@ -299,7 +299,7 @@ void Fetch::clearStates(ThreadID tid) { fetchStatus[tid] = Running; - pc[tid] = cpu->pcState(tid); + set(pc[tid], cpu->pcState(tid)); fetchOffset[tid] = 0; macroop[tid] = NULL; delayedCommit[tid] = false; @@ -326,7 +326,7 @@ Fetch::resetStage() // Setup PC and nextPC with initial state. for (ThreadID tid = 0; tid < numThreads; ++tid) { fetchStatus[tid] = Running; - pc[tid] = cpu->pcState(tid); + set(pc[tid], cpu->pcState(tid)); fetchOffset[tid] = 0; macroop[tid] = NULL; @@ -508,7 +508,7 @@ Fetch::deactivateThread(ThreadID tid) } bool -Fetch::lookupAndUpdateNextPC(const DynInstPtr &inst, TheISA::PCState &nextPC) +Fetch::lookupAndUpdateNextPC(const DynInstPtr &inst, PCStateBase &next_pc) { // Do branch prediction check here. // A bit of a misnomer...next_PC is actually the current PC until @@ -516,20 +516,20 @@ Fetch::lookupAndUpdateNextPC(const DynInstPtr &inst, TheISA::PCState &nextPC) bool predict_taken; if (!inst->isControl()) { - inst->staticInst->advancePC(nextPC); - inst->setPredTarg(nextPC); + inst->staticInst->advancePC(next_pc); + inst->setPredTarg(next_pc); inst->setPredTaken(false); return false; } ThreadID tid = inst->threadNumber; predict_taken = branchPred->predict(inst->staticInst, inst->seqNum, - nextPC, tid); + next_pc.as(), tid); if (predict_taken) { DPRINTF(Fetch, "[tid:%i] [sn:%llu] Branch at PC %#x " "predicted to be taken to %s\n", - tid, inst->seqNum, inst->pcState().instAddr(), nextPC); + tid, inst->seqNum, inst->pcState().instAddr(), next_pc); } else { DPRINTF(Fetch, "[tid:%i] [sn:%llu] Branch at PC %#x " "predicted to be not taken\n", @@ -538,8 +538,8 @@ Fetch::lookupAndUpdateNextPC(const DynInstPtr &inst, TheISA::PCState &nextPC) DPRINTF(Fetch, "[tid:%i] [sn:%llu] Branch at PC %#x " "predicted to go to %s\n", - tid, inst->seqNum, inst->pcState().instAddr(), nextPC); - inst->setPredTarg(nextPC); + tid, inst->seqNum, inst->pcState().instAddr(), next_pc); + inst->setPredTarg(next_pc); inst->setPredTaken(predict_taken); ++fetchStats.branches; @@ -683,15 +683,15 @@ Fetch::finishTranslation(const Fault &fault, const RequestPtr &mem_req) // Send the fault to commit. This thread will not do anything // until commit handles the fault. The only other way it can // wake up is if a squash comes along and changes the PC. - TheISA::PCState fetchPC = pc[tid]; + const PCStateBase &fetch_pc = *pc[tid]; DPRINTF(Fetch, "[tid:%i] Translation faulted, building noop.\n", tid); // We will use a nop in ordier to carry the fault. DynInstPtr instruction = buildInst(tid, nopStaticInstPtr, nullptr, - fetchPC, fetchPC, false); + fetch_pc, fetch_pc, false); instruction->setNotAnInst(); - instruction->setPredTarg(fetchPC); + instruction->setPredTarg(fetch_pc); instruction->fault = fault; wroteToTimeBuffer = true; @@ -702,21 +702,21 @@ Fetch::finishTranslation(const Fault &fault, const RequestPtr &mem_req) DPRINTF(Fetch, "[tid:%i] Blocked, need to handle the trap.\n", tid); DPRINTF(Fetch, "[tid:%i] fault (%s) detected @ PC %s.\n", - tid, fault->name(), pc[tid]); + tid, fault->name(), *pc[tid]); } _status = updateFetchStatus(); } void -Fetch::doSquash(const TheISA::PCState &newPC, const DynInstPtr squashInst, +Fetch::doSquash(const PCStateBase &new_pc, const DynInstPtr squashInst, ThreadID tid) { DPRINTF(Fetch, "[tid:%i] Squashing, setting PC to: %s.\n", - tid, newPC); + tid, new_pc); - pc[tid] = newPC; + set(pc[tid], new_pc); fetchOffset[tid] = 0; - if (squashInst && squashInst->pcState().instAddr() == newPC.instAddr()) + if (squashInst && squashInst->pcState().instAddr() == new_pc.instAddr()) macroop[tid] = squashInst->macroop; else macroop[tid] = NULL; @@ -759,12 +759,12 @@ Fetch::doSquash(const TheISA::PCState &newPC, const DynInstPtr squashInst, } void -Fetch::squashFromDecode(const TheISA::PCState &newPC, - const DynInstPtr squashInst, const InstSeqNum seq_num, ThreadID tid) +Fetch::squashFromDecode(const PCStateBase &new_pc, const DynInstPtr squashInst, + const InstSeqNum seq_num, ThreadID tid) { DPRINTF(Fetch, "[tid:%i] Squashing from decode.\n", tid); - doSquash(newPC, squashInst, tid); + doSquash(new_pc, squashInst, tid); // Tell the CPU to remove any instructions that are in flight between // fetch and decode. @@ -825,12 +825,12 @@ Fetch::updateFetchStatus() } void -Fetch::squash(const TheISA::PCState &newPC, const InstSeqNum seq_num, +Fetch::squash(const PCStateBase &new_pc, const InstSeqNum seq_num, DynInstPtr squashInst, ThreadID tid) { DPRINTF(Fetch, "[tid:%i] Squash from commit.\n", tid); - doSquash(newPC, squashInst, tid); + doSquash(new_pc, squashInst, tid); // Tell the CPU to remove any instructions that are not in the ROB. cpu->removeInstsNotInROB(tid); @@ -958,7 +958,7 @@ Fetch::checkSignalsAndUpdate(ThreadID tid) DPRINTF(Fetch, "[tid:%i] Squashing instructions due to squash " "from commit.\n",tid); // In any case, squash. - squash(fromCommit->commitInfo[tid].pc, + squash(*fromCommit->commitInfo[tid].pc, fromCommit->commitInfo[tid].doneSeqNum, fromCommit->commitInfo[tid].squashInst, tid); @@ -968,9 +968,8 @@ Fetch::checkSignalsAndUpdate(ThreadID tid) if (fromCommit->commitInfo[tid].mispredictInst && fromCommit->commitInfo[tid].mispredictInst->isControl()) { branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum, - fromCommit->commitInfo[tid].pc, - fromCommit->commitInfo[tid].branchTaken, - tid); + fromCommit->commitInfo[tid].pc->as(), + fromCommit->commitInfo[tid].branchTaken, tid); } else { branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum, tid); @@ -991,9 +990,8 @@ Fetch::checkSignalsAndUpdate(ThreadID tid) // Update the branch predictor. if (fromDecode->decodeInfo[tid].branchMispredict) { branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum, - fromDecode->decodeInfo[tid].nextPC, - fromDecode->decodeInfo[tid].branchTaken, - tid); + fromDecode->decodeInfo[tid].nextPC->as(), + fromDecode->decodeInfo[tid].branchTaken, tid); } else { branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum, tid); @@ -1002,9 +1000,9 @@ Fetch::checkSignalsAndUpdate(ThreadID tid) if (fetchStatus[tid] != Squashing) { DPRINTF(Fetch, "Squashing from decode with PC = %s\n", - fromDecode->decodeInfo[tid].nextPC); + *fromDecode->decodeInfo[tid].nextPC); // Squash unless we're already squashing - squashFromDecode(fromDecode->decodeInfo[tid].nextPC, + squashFromDecode(*fromDecode->decodeInfo[tid].nextPC, fromDecode->decodeInfo[tid].squashInst, fromDecode->decodeInfo[tid].doneSeqNum, tid); @@ -1044,32 +1042,30 @@ Fetch::checkSignalsAndUpdate(ThreadID tid) DynInstPtr Fetch::buildInst(ThreadID tid, StaticInstPtr staticInst, - StaticInstPtr curMacroop, TheISA::PCState thisPC, - TheISA::PCState nextPC, bool trace) + StaticInstPtr curMacroop, const PCStateBase &this_pc, + const PCStateBase &next_pc, bool trace) { // Get a sequence number. InstSeqNum seq = cpu->getAndIncrementInstSeq(); // Create a new DynInst from the instruction fetched. DynInstPtr instruction = - new DynInst(staticInst, curMacroop, thisPC, nextPC, seq, cpu); + new DynInst(staticInst, curMacroop, this_pc, next_pc, seq, cpu); instruction->setTid(tid); instruction->setThreadState(cpu->thread[tid]); - DPRINTF(Fetch, "[tid:%i] Instruction PC %#x (%d) created " - "[sn:%lli].\n", tid, thisPC.instAddr(), - thisPC.microPC(), seq); + DPRINTF(Fetch, "[tid:%i] Instruction PC %s created [sn:%lli].\n", + tid, this_pc, seq); DPRINTF(Fetch, "[tid:%i] Instruction is: %s\n", tid, - instruction->staticInst-> - disassemble(thisPC.instAddr())); + instruction->staticInst->disassemble(this_pc.instAddr())); #if TRACING_ON if (trace) { instruction->traceData = cpu->getTracer()->getInstRecord(curTick(), cpu->tcBase(tid), - instruction->staticInst, thisPC, curMacroop); + instruction->staticInst, this_pc, curMacroop); } #else instruction->traceData = NULL; @@ -1117,12 +1113,12 @@ Fetch::fetch(bool &status_change) DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid); // The current PC. - TheISA::PCState thisPC = pc[tid]; + PCStateBase &this_pc = *pc[tid]; Addr pcOffset = fetchOffset[tid]; - Addr fetchAddr = (thisPC.instAddr() + pcOffset) & decoder[tid]->pcMask(); + Addr fetchAddr = (this_pc.instAddr() + pcOffset) & decoder[tid]->pcMask(); - bool inRom = isRomMicroPC(thisPC.microPC()); + bool inRom = isRomMicroPC(this_pc.microPC()); // If returning from the delay of a cache miss, then update the status // to running, otherwise do the cache access. Possibly move this up @@ -1143,9 +1139,9 @@ Fetch::fetch(bool &status_change) fetchBufferBlockPC == fetchBufferPC[tid]) && !inRom && !macroop[tid]) { DPRINTF(Fetch, "[tid:%i] Attempting to translate and read " - "instruction, starting at PC %s.\n", tid, thisPC); + "instruction, starting at PC %s.\n", tid, this_pc); - fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); + fetchCacheLine(fetchAddr, tid, this_pc.instAddr()); if (fetchStatus[tid] == IcacheWaitResponse) ++fetchStats.icacheStallCycles; @@ -1154,7 +1150,8 @@ Fetch::fetch(bool &status_change) else ++fetchStats.miscStallCycles; return; - } else if (checkInterrupt(thisPC.instAddr()) && !delayedCommit[tid]) { + } else if (checkInterrupt(this_pc.instAddr()) && + !delayedCommit[tid]) { // Stall CPU if an interrupt is posted and we're not issuing // an delayed commit micro-op currently (delayed commit // instructions are not interruptable by interrupts, only faults) @@ -1174,7 +1171,7 @@ Fetch::fetch(bool &status_change) ++fetchStats.cycles; - TheISA::PCState nextPC = thisPC; + std::unique_ptr next_pc(this_pc.clone()); StaticInstPtr staticInst = NULL; StaticInstPtr curMacroop = macroop[tid]; @@ -1208,7 +1205,7 @@ Fetch::fetch(bool &status_change) // StaticInst from the rom, the current macroop, or what's already // in the decoder. bool needMem = !inRom && !curMacroop && !dec_ptr->instReady(); - fetchAddr = (thisPC.instAddr() + pcOffset) & pc_mask; + fetchAddr = (this_pc.instAddr() + pcOffset) & pc_mask; Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); if (needMem) { @@ -1226,7 +1223,7 @@ Fetch::fetch(bool &status_change) memcpy(dec_ptr->moreBytesPtr(), fetchBuffer[tid] + blkOffset * instSize, instSize); - decoder[tid]->moreBytes(thisPC, fetchAddr); + decoder[tid]->moreBytes(this_pc.as(), fetchAddr); if (dec_ptr->needMoreBytes()) { blkOffset++; @@ -1240,7 +1237,8 @@ Fetch::fetch(bool &status_change) do { if (!(curMacroop || inRom)) { if (dec_ptr->instReady()) { - staticInst = dec_ptr->decode(thisPC); + staticInst = dec_ptr->decode( + this_pc.as()); // Increment stat of fetched instructions. ++fetchStats.insts; @@ -1263,15 +1261,15 @@ Fetch::fetch(bool &status_change) if (curMacroop || inRom) { if (inRom) { staticInst = dec_ptr->fetchRomMicroop( - thisPC.microPC(), curMacroop); + this_pc.microPC(), curMacroop); } else { - staticInst = curMacroop->fetchMicroop(thisPC.microPC()); + staticInst = curMacroop->fetchMicroop(this_pc.microPC()); } newMacro |= staticInst->isLastMicroop(); } - DynInstPtr instruction = - buildInst(tid, staticInst, curMacroop, thisPC, nextPC, true); + DynInstPtr instruction = buildInst( + tid, staticInst, curMacroop, this_pc, *next_pc, true); ppFetch->notify(instruction); numInst++; @@ -1282,25 +1280,24 @@ Fetch::fetch(bool &status_change) } #endif - nextPC = thisPC; + set(next_pc, this_pc); // If we're branching after this instruction, quit fetching // from the same block. - predictedBranch |= thisPC.branching(); - predictedBranch |= - lookupAndUpdateNextPC(instruction, nextPC); + predictedBranch |= this_pc.as().branching(); + predictedBranch |= lookupAndUpdateNextPC(instruction, *next_pc); if (predictedBranch) { - DPRINTF(Fetch, "Branch detected with PC = %s\n", thisPC); + DPRINTF(Fetch, "Branch detected with PC = %s\n", this_pc); } - newMacro |= thisPC.instAddr() != nextPC.instAddr(); + newMacro |= this_pc.instAddr() != next_pc->instAddr(); // Move to the next instruction, unless we have a branch. - thisPC = nextPC; - inRom = isRomMicroPC(thisPC.microPC()); + set(this_pc, *next_pc); + inRom = isRomMicroPC(this_pc.microPC()); if (newMacro) { - fetchAddr = thisPC.instAddr() & pc_mask; + fetchAddr = this_pc.instAddr() & pc_mask; blkOffset = (fetchAddr - fetchBufferPC[tid]) / instSize; pcOffset = 0; curMacroop = NULL; @@ -1320,7 +1317,7 @@ Fetch::fetch(bool &status_change) // Re-evaluate whether the next instruction to fetch is in micro-op ROM // or not. - inRom = isRomMicroPC(thisPC.microPC()); + inRom = isRomMicroPC(this_pc.microPC()); } if (predictedBranch) { @@ -1341,11 +1338,9 @@ Fetch::fetch(bool &status_change) wroteToTimeBuffer = true; } - pc[tid] = thisPC; - // pipeline a fetch if we're crossing a fetch buffer boundary and not in // a state that would preclude fetching - fetchAddr = (thisPC.instAddr() + pcOffset) & pc_mask; + fetchAddr = (this_pc.instAddr() + pcOffset) & pc_mask; Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); issuePipelinedIfetch[tid] = fetchBufferBlockPC != fetchBufferPC[tid] && fetchStatus[tid] != IcacheWaitResponse && @@ -1535,14 +1530,14 @@ Fetch::pipelineIcacheAccesses(ThreadID tid) } // The next PC to access. - TheISA::PCState thisPC = pc[tid]; + const PCStateBase &this_pc = *pc[tid]; - if (isRomMicroPC(thisPC.microPC())) { + if (isRomMicroPC(this_pc.microPC())) { return; } Addr pcOffset = fetchOffset[tid]; - Addr fetchAddr = (thisPC.instAddr() + pcOffset) & decoder[tid]->pcMask(); + Addr fetchAddr = (this_pc.instAddr() + pcOffset) & decoder[tid]->pcMask(); // Align the fetch PC so its at the start of a fetch buffer segment. Addr fetchBufferBlockPC = fetchBufferAlignPC(fetchAddr); @@ -1550,9 +1545,9 @@ Fetch::pipelineIcacheAccesses(ThreadID tid) // Unless buffer already got the block, fetch it from icache. if (!(fetchBufferValid[tid] && fetchBufferBlockPC == fetchBufferPC[tid])) { DPRINTF(Fetch, "[tid:%i] Issuing a pipelined I-cache access, " - "starting at PC %s.\n", tid, thisPC); + "starting at PC %s.\n", tid, this_pc); - fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); + fetchCacheLine(fetchAddr, tid, this_pc.instAddr()); } } diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 5bfb01a277..2d903b2c30 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -284,7 +284,7 @@ class Fetch * @param next_NPC Used for ISAs which use delay slots. * @return Whether or not a branch was predicted as taken. */ - bool lookupAndUpdateNextPC(const DynInstPtr &inst, TheISA::PCState &pc); + bool lookupAndUpdateNextPC(const DynInstPtr &inst, PCStateBase &pc); /** * Fetches the cache line that contains the fetch PC. Returns any @@ -306,14 +306,14 @@ class Fetch bool checkInterrupt(Addr pc) { return interruptPending; } /** Squashes a specific thread and resets the PC. */ - void doSquash(const TheISA::PCState &newPC, - const DynInstPtr squashInst, ThreadID tid); + void doSquash(const PCStateBase &new_pc, const DynInstPtr squashInst, + ThreadID tid); /** Squashes a specific thread and resets the PC. Also tells the CPU to * remove any instructions between fetch and decode * that should be sqaushed. */ - void squashFromDecode(const TheISA::PCState &newPC, + void squashFromDecode(const PCStateBase &new_pc, const DynInstPtr squashInst, const InstSeqNum seq_num, ThreadID tid); @@ -329,7 +329,7 @@ class Fetch * remove any instructions that are not in the ROB. The source of this * squash should be the commit stage. */ - void squash(const TheISA::PCState &newPC, const InstSeqNum seq_num, + void squash(const PCStateBase &new_pc, const InstSeqNum seq_num, DynInstPtr squashInst, ThreadID tid); /** Ticks the fetch stage, processing all inputs signals and fetching @@ -362,8 +362,8 @@ class Fetch private: DynInstPtr buildInst(ThreadID tid, StaticInstPtr staticInst, - StaticInstPtr curMacroop, TheISA::PCState thisPC, - TheISA::PCState nextPC, bool trace); + StaticInstPtr curMacroop, const PCStateBase &this_pc, + const PCStateBase &next_pc, bool trace); /** Returns the appropriate thread to fetch, given the fetch policy. */ ThreadID getFetchingThread(); @@ -413,7 +413,7 @@ class Fetch /** BPredUnit. */ branch_prediction::BPredUnit *branchPred; - TheISA::PCState pc[MaxThreads]; + std::unique_ptr pc[MaxThreads]; Addr fetchOffset[MaxThreads]; diff --git a/src/cpu/o3/iew.cc b/src/cpu/o3/iew.cc index d899e8b128..79e0783f65 100644 --- a/src/cpu/o3/iew.cc +++ b/src/cpu/o3/iew.cc @@ -463,10 +463,9 @@ IEW::squashDueToBranch(const DynInstPtr& inst, ThreadID tid) toCommit->squashedSeqNum[tid] = inst->seqNum; toCommit->branchTaken[tid] = inst->pcState().branching(); - TheISA::PCState pc = inst->pcState(); - inst->staticInst->advancePC(pc); + set(toCommit->pc[tid], inst->pcState()); + inst->staticInst->advancePC(*toCommit->pc[tid]); - toCommit->pc[tid] = pc; toCommit->mispredictInst[tid] = inst; toCommit->includeSquashInst[tid] = false; @@ -491,7 +490,7 @@ IEW::squashDueToMemOrder(const DynInstPtr& inst, ThreadID tid) toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->pc[tid] = inst->pcState(); + set(toCommit->pc[tid], inst->pcState()); toCommit->mispredictInst[tid] = NULL; // Must include the memory violator in the squash. @@ -1301,13 +1300,13 @@ IEW::executeInsts() DPRINTF(IEW, "[tid:%i] [sn:%llu] Execute: " "Branch mispredict detected.\n", - tid,inst->seqNum); + tid, inst->seqNum); DPRINTF(IEW, "[tid:%i] [sn:%llu] " "Predicted target was PC: %s\n", - tid,inst->seqNum,inst->readPredTarg()); + tid, inst->seqNum, inst->readPredTarg()); DPRINTF(IEW, "[tid:%i] [sn:%llu] Execute: " "Redirecting fetch to PC: %s\n", - tid,inst->seqNum,inst->pcState()); + tid, inst->seqNum, inst->pcState()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid);