diff options
Diffstat (limited to 'src/cpu')
68 files changed, 937 insertions, 1622 deletions
diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index e9b7daa4a..bc6f59407 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -38,6 +38,7 @@ #include <string> #include "arch/faults.hh" +#include "arch/utility.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" #include "config/full_system.hh" @@ -241,36 +242,15 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Records changes to result? */ bool recordResult; - /** PC of this instruction. */ - Addr PC; - - /** Micro PC of this instruction. */ - Addr microPC; - /** Did this instruction execute, or is it predicated false */ bool predicate; protected: - /** Next non-speculative PC. It is not filled in at fetch, but rather - * once the target of the branch is truly known (either decode or - * execute). - */ - Addr nextPC; - - /** Next non-speculative NPC. Target PC for Mips or Sparc. */ - Addr nextNPC; + /** PC state for this instruction. */ + TheISA::PCState pc; - /** Next non-speculative micro PC. */ - Addr nextMicroPC; - - /** Predicted next PC. */ - Addr predPC; - - /** Predicted next NPC. */ - Addr predNPC; - - /** Predicted next microPC */ - Addr predMicroPC; + /** Predicted PC state after this instruction. */ + TheISA::PCState predPC; /** If this is a branch that was predicted taken */ bool predTaken; @@ -386,27 +366,23 @@ class BaseDynInst : public FastAlloc, public RefCounted } /** BaseDynInst constructor given a binary instruction. * @param staticInst A StaticInstPtr to the underlying instruction. - * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. - * @param pred_NPC The predicted next NPC. + * @param pc The PC state for the instruction. + * @param predPC The predicted next PC state for the instruction. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, - Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC, - InstSeqNum seq_num, ImplCPU *cpu); + BaseDynInst(StaticInstPtr staticInst, TheISA::PCState pc, + TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a binary instruction. * @param inst The binary instruction. - * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. - * @param pred_NPC The predicted next NPC. + * @param _pc The PC state for the instruction. + * @param _predPC The predicted next PC state for the instruction. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, - Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC, - InstSeqNum seq_num, ImplCPU *cpu); + BaseDynInst(TheISA::ExtMachInst inst, TheISA::PCState pc, + TheISA::PCState predPC, InstSeqNum seq_num, ImplCPU *cpu); /** BaseDynInst constructor given a StaticInst pointer. * @param _staticInst The StaticInst for this BaseDynInst. @@ -443,45 +419,22 @@ class BaseDynInst : public FastAlloc, public RefCounted */ bool doneTargCalc() { return false; } - /** Returns the next PC. This could be the speculative next PC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextPC() { return nextPC; } - - /** Returns the next NPC. This could be the speculative next NPC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextNPC() - { -#if ISA_HAS_DELAY_SLOT - return nextNPC; -#else - return nextPC + sizeof(TheISA::MachInst); -#endif - } - - Addr readNextMicroPC() - { - return nextMicroPC; - } - /** Set the predicted target of this current instruction. */ - void setPredTarg(Addr predicted_PC, Addr predicted_NPC, - Addr predicted_MicroPC) + void setPredTarg(const TheISA::PCState &_predPC) { - predPC = predicted_PC; - predNPC = predicted_NPC; - predMicroPC = predicted_MicroPC; + predPC = _predPC; } + const TheISA::PCState &readPredTarg() { return predPC; } + /** Returns the predicted PC immediately after the branch. */ - Addr readPredPC() { return predPC; } + Addr predInstAddr() { return predPC.instAddr(); } /** Returns the predicted PC two instructions after the branch */ - Addr readPredNPC() { return predNPC; } + Addr predNextInstAddr() { return predPC.nextInstAddr(); } /** Returns the predicted micro PC after the branch */ - Addr readPredMicroPC() { return predMicroPC; } + Addr predMicroPC() { return predPC.microPC(); } /** Returns whether the instruction was predicted taken or not. */ bool readPredTaken() @@ -497,9 +450,9 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns whether the instruction mispredicted. */ bool mispredicted() { - return readPredPC() != readNextPC() || - readPredNPC() != readNextNPC() || - readPredMicroPC() != readNextMicroPC(); + TheISA::PCState tempPC = pc; + TheISA::advancePC(tempPC, staticInst); + return !(tempPC == predPC); } // @@ -576,7 +529,8 @@ class BaseDynInst : public FastAlloc, public RefCounted OpClass opClass() const { return staticInst->opClass(); } /** Returns the branch target address. */ - Addr branchTarget() const { return staticInst->branchTarget(PC); } + TheISA::PCState branchTarget() const + { return staticInst->branchTarget(pc); } /** Returns the number of source registers. */ int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } @@ -773,30 +727,20 @@ class BaseDynInst : public FastAlloc, public RefCounted /** Returns whether or not this instruction is squashed in the ROB. */ bool isSquashedInROB() const { return status[SquashedInROB]; } - /** Read the PC of this instruction. */ - const Addr readPC() const { return PC; } + /** Read the PC state of this instruction. */ + const TheISA::PCState pcState() const { return pc; } - /**Read the micro PC of this instruction. */ - const Addr readMicroPC() const { return microPC; } + /** Set the PC state of this instruction. */ + const void pcState(const TheISA::PCState &val) { pc = val; } - /** Set the next PC of this instruction (its actual target). */ - void setNextPC(Addr val) - { - nextPC = val; - } + /** Read the PC of this instruction. */ + const Addr instAddr() const { return pc.instAddr(); } - /** Set the next NPC of this instruction (the target in Mips or Sparc).*/ - void setNextNPC(Addr val) - { -#if ISA_HAS_DELAY_SLOT - nextNPC = val; -#endif - } + /** Read the PC of the next instruction. */ + const Addr nextInstAddr() const { return pc.nextInstAddr(); } - void setNextMicroPC(Addr val) - { - nextMicroPC = val; - } + /**Read the micro PC of this instruction. */ + const Addr microPC() const { return pc.microPC(); } bool readPredicate() { @@ -895,7 +839,7 @@ BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags) { reqMade = true; - Request *req = new Request(asid, addr, size, flags, this->PC, + Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(), thread->contextId(), threadNumber); Request *sreqLow = NULL; @@ -956,7 +900,7 @@ BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size, } reqMade = true; - Request *req = new Request(asid, addr, size, flags, this->PC, + Request *req = new Request(asid, addr, size, flags, this->pc.instAddr(), thread->contextId(), threadNumber); Request *sreqLow = NULL; diff --git a/src/cpu/base_dyn_inst_impl.hh b/src/cpu/base_dyn_inst_impl.hh index 4fb8490c1..923b204ce 100644 --- a/src/cpu/base_dyn_inst_impl.hh +++ b/src/cpu/base_dyn_inst_impl.hh @@ -62,32 +62,14 @@ my_hash_t thishash; template <class Impl> BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst, - Addr inst_PC, Addr inst_NPC, - Addr inst_MicroPC, - Addr pred_PC, Addr pred_NPC, - Addr pred_MicroPC, + TheISA::PCState _pc, TheISA::PCState _predPC, InstSeqNum seq_num, ImplCPU *cpu) : staticInst(_staticInst), traceData(NULL), cpu(cpu) { seqNum = seq_num; - bool nextIsMicro = - staticInst->isMicroop() && !staticInst->isLastMicroop(); - - PC = inst_PC; - microPC = inst_MicroPC; - if (nextIsMicro) { - nextPC = inst_PC; - nextNPC = inst_NPC; - nextMicroPC = microPC + 1; - } else { - nextPC = inst_NPC; - nextNPC = nextPC + sizeof(TheISA::MachInst); - nextMicroPC = 0; - } - predPC = pred_PC; - predNPC = pred_NPC; - predMicroPC = pred_MicroPC; + pc = _pc; + predPC = _predPC; predTaken = false; initVars(); @@ -95,32 +77,14 @@ BaseDynInst<Impl>::BaseDynInst(StaticInstPtr _staticInst, template <class Impl> BaseDynInst<Impl>::BaseDynInst(TheISA::ExtMachInst inst, - Addr inst_PC, Addr inst_NPC, - Addr inst_MicroPC, - Addr pred_PC, Addr pred_NPC, - Addr pred_MicroPC, + TheISA::PCState _pc, TheISA::PCState _predPC, InstSeqNum seq_num, ImplCPU *cpu) - : staticInst(inst, inst_PC), traceData(NULL), cpu(cpu) + : staticInst(inst, _pc.instAddr()), traceData(NULL), cpu(cpu) { seqNum = seq_num; - bool nextIsMicro = - staticInst->isMicroop() && !staticInst->isLastMicroop(); - - PC = inst_PC; - microPC = inst_MicroPC; - if (nextIsMicro) { - nextPC = inst_PC; - nextNPC = inst_NPC; - nextMicroPC = microPC + 1; - } else { - nextPC = inst_NPC; - nextNPC = nextPC + sizeof(TheISA::MachInst); - nextMicroPC = 0; - } - predPC = pred_PC; - predNPC = pred_NPC; - predMicroPC = pred_MicroPC; + pc = _pc; + predPC = _predPC; predTaken = false; initVars(); @@ -301,8 +265,8 @@ template <class Impl> void BaseDynInst<Impl>::dump() { - cprintf("T%d : %#08d `", threadNumber, PC); - std::cout << staticInst->disassemble(PC); + cprintf("T%d : %#08d `", threadNumber, pc.instAddr()); + std::cout << staticInst->disassemble(pc.instAddr()); cprintf("'\n"); } @@ -311,8 +275,8 @@ void BaseDynInst<Impl>::dump(std::string &outstring) { std::ostringstream s; - s << "T" << threadNumber << " : 0x" << PC << " " - << staticInst->disassemble(PC); + s << "T" << threadNumber << " : 0x" << pc.instAddr() << " " + << staticInst->disassemble(pc.instAddr()); outstring = s.str(); } diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index a2f44106d..df5d8209b 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -241,13 +241,9 @@ class CheckerCPU : public BaseCPU result.integer = val; } - uint64_t readPC() { return thread->readPC(); } + uint64_t instAddr() { return thread->instAddr(); } - uint64_t readNextPC() { return thread->readNextPC(); } - - void setNextPC(uint64_t val) { - thread->setNextPC(val); - } + uint64_t nextInstAddr() { return thread->nextInstAddr(); } MiscReg readMiscRegNoEffect(int misc_reg) { diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 4bab778ba..f8b25ef73 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -72,10 +72,7 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran) std::string sym_str; Addr sym_addr; - Addr cur_pc = PC; -#if THE_ISA == ARM_ISA - cur_pc &= ~PcModeMask; -#endif + Addr cur_pc = pc.instAddr(); if (debugSymbolTable && IsOn(ExecSymbol) #if FULL_SYSTEM @@ -85,13 +82,12 @@ Trace::ExeTracerRecord::traceInst(StaticInstPtr inst, bool ran) if (cur_pc != sym_addr) sym_str += csprintf("+%d",cur_pc - sym_addr); outs << "@" << sym_str; - } - else { + } else { outs << "0x" << hex << cur_pc; } if (inst->isMicroop()) { - outs << "." << setw(2) << dec << upc; + outs << "." << setw(2) << dec << pc.microPC(); } else { outs << " "; } diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 1982595eb..65950728b 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -47,10 +47,10 @@ class ExeTracerRecord : public InstRecord { public: ExeTracerRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : InstRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc) + _macroStaticInst) { } @@ -69,8 +69,8 @@ class ExeTracer : public InstTracer InstRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (!IsOn(ExecEnable)) return NULL; @@ -82,7 +82,7 @@ class ExeTracer : public InstTracer return NULL; return new ExeTracerRecord(when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } }; diff --git a/src/cpu/inorder/comm.hh b/src/cpu/inorder/comm.hh index f1b3cacac..386046d1c 100644 --- a/src/cpu/inorder/comm.hh +++ b/src/cpu/inorder/comm.hh @@ -75,8 +75,8 @@ struct TimeStruct { // struct as it is used pretty frequently. bool branchMispredict; bool branchTaken; - uint64_t mispredPC; - uint64_t nextPC; + Addr mispredPC; + TheISA::PCState nextPC; unsigned branchCount; diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 5d42ba559..6cd938dc6 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -988,47 +988,6 @@ InOrderCPU::getPipeStage(int stage_num) } uint64_t -InOrderCPU::readPC(ThreadID tid) -{ - return PC[tid]; -} - - -void -InOrderCPU::setPC(Addr new_PC, ThreadID tid) -{ - PC[tid] = new_PC; -} - - -uint64_t -InOrderCPU::readNextPC(ThreadID tid) -{ - return nextPC[tid]; -} - - -void -InOrderCPU::setNextPC(uint64_t new_NPC, ThreadID tid) -{ - nextPC[tid] = new_NPC; -} - - -uint64_t -InOrderCPU::readNextNPC(ThreadID tid) -{ - return nextNPC[tid]; -} - - -void -InOrderCPU::setNextNPC(uint64_t new_NNPC, ThreadID tid) -{ - nextNPC[tid] = new_NNPC; -} - -uint64_t InOrderCPU::readIntReg(int reg_idx, ThreadID tid) { return intRegs[tid][reg_idx]; @@ -1156,15 +1115,12 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid) // Set the CPU's PCs - This contributes to the precise state of the CPU // which can be used when restoring a thread to the CPU after after any // type of context switching activity (fork, exception, etc.) - setPC(inst->readPC(), tid); - setNextPC(inst->readNextPC(), tid); - setNextNPC(inst->readNextNPC(), tid); + pcState(inst->pcState(), tid); if (inst->isControl()) { thread[tid]->lastGradIsBranch = true; - thread[tid]->lastBranchPC = inst->readPC(); - thread[tid]->lastBranchNextPC = inst->readNextPC(); - thread[tid]->lastBranchNextNPC = inst->readNextNPC(); + thread[tid]->lastBranchPC = inst->pcState(); + TheISA::advancePC(thread[tid]->lastBranchPC, inst->staticInst); } else { thread[tid]->lastGradIsBranch = false; } @@ -1236,15 +1192,15 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst) { removeInstsThisCycle = true; if (!inst->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " "[sn:%lli] to remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); inst->setRemoveList(); removeList.push(inst->getInstListIt()); } else { - DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " "[sn:%lli], already remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); } } @@ -1252,23 +1208,23 @@ InOrderCPU::addToRemoveList(DynInstPtr &inst) void InOrderCPU::removeInst(DynInstPtr &inst) { - DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %s " "[sn:%lli]\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); removeInstsThisCycle = true; // Remove the instruction. if (!inst->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " "[sn:%lli] to remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); inst->setRemoveList(); removeList.push(inst->getInstListIt()); } else { - DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " "[sn:%lli], already on remove list\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); } } @@ -1307,24 +1263,24 @@ InOrderCPU::squashInstIt(const ListIt &instIt, ThreadID tid) { if ((*instIt)->threadNumber == tid) { DPRINTF(InOrderCPU, "Squashing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*instIt)->threadNumber, (*instIt)->seqNum, - (*instIt)->readPC()); + (*instIt)->pcState()); (*instIt)->setSquashed(); if (!(*instIt)->isRemoveList()) { - DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %#x " + DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " "[sn:%lli] to remove list\n", - (*instIt)->threadNumber, (*instIt)->readPC(), + (*instIt)->threadNumber, (*instIt)->pcState(), (*instIt)->seqNum); (*instIt)->setRemoveList(); removeList.push(instIt); } else { DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i]" - " PC %#x [sn:%lli], already on remove list\n", - (*instIt)->threadNumber, (*instIt)->readPC(), + " PC %s [sn:%lli], already on remove list\n", + (*instIt)->threadNumber, (*instIt)->pcState(), (*instIt)->seqNum); } @@ -1338,10 +1294,10 @@ InOrderCPU::cleanUpRemovedInsts() { while (!removeList.empty()) { DPRINTF(InOrderCPU, "Removing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*removeList.front())->threadNumber, (*removeList.front())->seqNum, - (*removeList.front())->readPC()); + (*removeList.front())->pcState()); DynInstPtr inst = *removeList.front(); ThreadID tid = inst->threadNumber; @@ -1417,9 +1373,10 @@ InOrderCPU::dumpInsts() cprintf("Dumping Instruction List\n"); while (inst_list_it != instList[0].end()) { - cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" + cprintf("Instruction:%i\nPC:%s\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" "Squashed:%i\n\n", - num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, + num, (*inst_list_it)->pcState(), + (*inst_list_it)->threadNumber, (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed()); inst_list_it++; diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index abe24d6ed..df6617d56 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -273,9 +273,7 @@ class InOrderCPU : public BaseCPU PipelineStage *pipelineStage[ThePipeline::NumStages]; /** Program Counters */ - TheISA::IntReg PC[ThePipeline::MaxThreads]; - TheISA::IntReg nextPC[ThePipeline::MaxThreads]; - TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; + TheISA::PCState pc[ThePipeline::MaxThreads]; /** The Register File for the CPU */ union { @@ -471,22 +469,22 @@ class InOrderCPU : public BaseCPU ThreadID tid); /** Reads the commit PC of a specific thread. */ - uint64_t readPC(ThreadID tid); + TheISA::PCState + pcState(ThreadID tid) + { + return pc[tid]; + } /** Sets the commit PC of a specific thread. */ - void setPC(Addr new_PC, ThreadID tid); - - /** Reads the next PC of a specific thread. */ - uint64_t readNextPC(ThreadID tid); - - /** Sets the next PC of a specific thread. */ - void setNextPC(uint64_t val, ThreadID tid); - - /** Reads the next NPC of a specific thread. */ - uint64_t readNextNPC(ThreadID tid); + void + pcState(const TheISA::PCState &newPC, ThreadID tid) + { + pc[tid] = newPC; + } - /** Sets the next NPC of a specific thread. */ - void setNextNPC(uint64_t val, ThreadID tid); + Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); } + Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); } + MicroPC microPC(ThreadID tid) { return pc[tid].microPC(); } /** Function to add instruction onto the head of the list of the * instructions. Used when new instructions are fetched. diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc index 658ce37d3..ae458c604 100644 --- a/src/cpu/inorder/first_stage.cc +++ b/src/cpu/inorder/first_stage.cc @@ -84,8 +84,8 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid) break; } DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] " - "PC %08p.\n", tid, insts[tid].front()->seqNum, - insts[tid].front()->PC); + "PC %s.\n", tid, insts[tid].front()->seqNum, + insts[tid].front()->pc); insts[tid].pop(); } diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index 2465744e5..f672082f3 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -47,17 +47,16 @@ using namespace std; using namespace TheISA; using namespace ThePipeline; -InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, Addr inst_PC, - Addr pred_PC, InstSeqNum seq_num, - InOrderCPU *cpu) - : staticInst(machInst, inst_PC), traceData(NULL), cpu(cpu) +InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, + const TheISA::PCState &instPC, + const TheISA::PCState &_predPC, + InstSeqNum seq_num, InOrderCPU *cpu) + : staticInst(machInst, instPC.instAddr()), traceData(NULL), cpu(cpu) { seqNum = seq_num; - PC = inst_PC; - nextPC = PC + sizeof(MachInst); - nextNPC = nextPC + sizeof(MachInst); - predPC = pred_PC; + pc = instPC; + predPC = _predPC; initVars(); } @@ -94,7 +93,7 @@ int InOrderDynInst::instcount = 0; void InOrderDynInst::setMachInst(ExtMachInst machInst) { - staticInst = StaticInst::decode(machInst, PC); + staticInst = StaticInst::decode(machInst, pc.instAddr()); for (int i = 0; i < this->staticInst->numDestRegs(); i++) { _destRegIdx[i] = this->staticInst->destRegIdx(i); @@ -747,8 +746,8 @@ InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) void InOrderDynInst::dump() { - cprintf("T%d : %#08d `", threadNumber, PC); - cout << staticInst->disassemble(PC); + cprintf("T%d : %#08d `", threadNumber, pc.instAddr()); + cout << staticInst->disassemble(pc.instAddr()); cprintf("'\n"); } @@ -756,8 +755,8 @@ void InOrderDynInst::dump(std::string &outstring) { std::ostringstream s; - s << "T" << threadNumber << " : 0x" << PC << " " - << staticInst->disassemble(PC); + s << "T" << threadNumber << " : " << pc << " " + << staticInst->disassemble(pc.instAddr()); outstring = s.str(); } diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index 0d42f4696..105e37657 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -41,6 +41,7 @@ #include "arch/isa_traits.hh" #include "arch/mt.hh" #include "arch/types.hh" +#include "arch/utility.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" #include "base/types.hh" @@ -108,12 +109,13 @@ class InOrderDynInst : public FastAlloc, public RefCounted /** BaseDynInst constructor given a binary instruction. * @param inst The binary instruction. * @param PC The PC of the instruction. - * @param pred_PC The predicted next PC. + * @param predPC The predicted next PC. * @param seq_num The sequence number of the instruction. * @param cpu Pointer to the instruction's CPU. */ - InOrderDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num, - InOrderCPU *cpu); + InOrderDynInst(ExtMachInst inst, const TheISA::PCState &PC, + const TheISA::PCState &predPC, InstSeqNum seq_num, + InOrderCPU *cpu); /** BaseDynInst constructor given a binary instruction. * @param seq_num The sequence number of the instruction. @@ -269,28 +271,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted InstResult instResult[MaxInstDestRegs]; /** PC of this instruction. */ - Addr PC; - - /** Next non-speculative PC. It is not filled in at fetch, but rather - * once the target of the branch is truly known (either decode or - * execute). - */ - Addr nextPC; - - /** Next next non-speculative PC. It is not filled in at fetch, but rather - * once the target of the branch is truly known (either decode or - * execute). - */ - Addr nextNPC; + TheISA::PCState pc; /** Predicted next PC. */ - Addr predPC; - - /** Predicted next NPC. */ - Addr predNPC; - - /** Predicted next microPC */ - Addr predMicroPC; + TheISA::PCState predPC; /** Address to fetch from */ Addr fetchAddr; @@ -540,33 +524,14 @@ class InOrderDynInst : public FastAlloc, public RefCounted // //////////////////////////////////////////////////////////// /** Read the PC of this instruction. */ - const Addr readPC() const { return PC; } + const TheISA::PCState &pcState() const { return pc; } /** Sets the PC of this instruction. */ - void setPC(Addr pc) { PC = pc; } - - /** Returns the next PC. This could be the speculative next PC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextPC() { return nextPC; } + void pcState(const TheISA::PCState &_pc) { pc = _pc; } - /** Set the next PC of this instruction (its actual target). */ - void setNextPC(uint64_t val) { nextPC = val; } - - /** Returns the next NPC. This could be the speculative next NPC if it is - * called prior to the actual branch target being calculated. - */ - Addr readNextNPC() - { -#if ISA_HAS_DELAY_SLOT - return nextNPC; -#else - return nextPC + sizeof(TheISA::MachInst); -#endif - } - - /** Set the next PC of this instruction (its actual target). */ - void setNextNPC(uint64_t val) { nextNPC = val; } + const Addr instAddr() { return pc.instAddr(); } + const Addr nextInstAddr() { return pc.nextInstAddr(); } + const MicroPC microPC() { return pc.microPC(); } //////////////////////////////////////////////////////////// // @@ -574,38 +539,36 @@ class InOrderDynInst : public FastAlloc, public RefCounted // //////////////////////////////////////////////////////////// /** Set the predicted target of this current instruction. */ - void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; } + void setPredTarg(const TheISA::PCState &predictedPC) + { predPC = predictedPC; } /** Returns the predicted target of the branch. */ - Addr readPredTarg() { return predPC; } + TheISA::PCState readPredTarg() { return predPC; } /** Returns the predicted PC immediately after the branch. */ - Addr readPredPC() { return predPC; } + Addr predInstAddr() { return predPC.instAddr(); } /** Returns the predicted PC two instructions after the branch */ - Addr readPredNPC() { return predNPC; } + Addr predNextInstAddr() { return predPC.nextInstAddr(); } /** Returns the predicted micro PC after the branch */ - Addr readPredMicroPC() { return predMicroPC; } + Addr readPredMicroPC() { return predPC.microPC(); } /** Returns whether the instruction was predicted taken or not. */ bool predTaken() { return predictTaken; } /** Returns whether the instruction mispredicted. */ - bool mispredicted() + bool + mispredicted() { -#if ISA_HAS_DELAY_SLOT - return predPC != nextNPC; -#else - return predPC != nextPC; -#endif + TheISA::PCState nextPC = pc; + TheISA::advancePC(nextPC, staticInst); + return !(nextPC == predPC); } - /** Returns whether the instruction mispredicted. */ - bool mistargeted() { return predPC != nextNPC; } - /** Returns the branch target address. */ - Addr branchTarget() const { return staticInst->branchTarget(PC); } + TheISA::PCState branchTarget() const + { return staticInst->branchTarget(pc); } /** Checks whether or not this instruction has had its branch target * calculated yet. For now it is not utilized and is hacked to be diff --git a/src/cpu/inorder/inorder_trace.cc b/src/cpu/inorder/inorder_trace.cc index 90c94a4f5..70a947671 100644 --- a/src/cpu/inorder/inorder_trace.cc +++ b/src/cpu/inorder/inorder_trace.cc @@ -70,15 +70,15 @@ InOrderTrace::getInstRecord(unsigned num_stages, bool stage_tracing, if (!Trace::enabled) return NULL; - return new InOrderTraceRecord(num_stages, stage_tracing, tc); + return new InOrderTraceRecord(num_stages, stage_tracing, tc, 0); } InOrderTraceRecord * InOrderTrace::getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst, MicroPC upc) + const StaticInstPtr staticInst, TheISA::PCState _pc, + const StaticInstPtr macroStaticInst) { - return new InOrderTraceRecord(ThePipeline::NumStages, true, tc); + return new InOrderTraceRecord(ThePipeline::NumStages, true, tc, _pc); } /* namespace Trace */ } diff --git a/src/cpu/inorder/inorder_trace.hh b/src/cpu/inorder/inorder_trace.hh index ccc868f15..fd1427500 100644 --- a/src/cpu/inorder/inorder_trace.hh +++ b/src/cpu/inorder/inorder_trace.hh @@ -47,8 +47,8 @@ class InOrderTraceRecord : public ExeTracerRecord { public: InOrderTraceRecord(unsigned num_stages, bool _stage_tracing, - ThreadContext *_thread, bool spec = false) - : ExeTracerRecord(0, _thread, NULL, 0, spec) + ThreadContext *_thread, TheISA::PCState _pc, bool spec = false) + : ExeTracerRecord(0, _thread, NULL, _pc, spec) { stageTrace = _stage_tracing; stageCycle.resize(num_stages); @@ -75,7 +75,8 @@ class InOrderTraceRecord : public ExeTracerRecord { staticInst = _staticInst; } - void setPC(Addr _pc) { PC = _pc; } + + void setPC(TheISA::PCState _pc) { pc = _pc; } }; class InOrderTrace : public InstTracer @@ -87,9 +88,9 @@ class InOrderTrace : public InstTracer InOrderTraceRecord * getInstRecord(unsigned num_stages, bool stage_tracing, ThreadContext *tc); - virtual InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0); + InOrderTraceRecord *getInstRecord(Tick when, ThreadContext *tc, + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL); }; /* namespace Trace */ } diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index f0b48d6f6..dc36965b0 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -350,27 +350,21 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid) toPrevStages->stageInfo[stageNum][tid].squash = true; toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg(); + toPrevStages->stageInfo[stageNum][tid].branchTaken = + inst->pcState().branching(); #if ISA_HAS_DELAY_SLOT - toPrevStages->stageInfo[stageNum][tid].branchTaken = - inst->readNextNPC() != - (inst->readNextPC() + sizeof(TheISA::MachInst)); - - toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = + toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->bdelaySeqNum; InstSeqNum squash_seq_num = inst->bdelaySeqNum; #else - toPrevStages->stageInfo[stageNum][tid].branchTaken = - inst->readNextPC() != - (inst->readPC() + sizeof(TheISA::MachInst)); - toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum; InstSeqNum squash_seq_num = inst->seqNum; #endif DPRINTF(InOrderStage, "Target being re-set to %08p\n", - inst->readPredTarg()); + inst->predInstAddr()); DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], " "due to [sn:%i] branch.\n", tid, squash_seq_num, inst->seqNum); @@ -398,10 +392,10 @@ PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid) prevStage->insts[i]->seqNum > squash_seq_num) { // Change Comment to Annulling previous instruction DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, " - "[sn:%i] PC %08p.\n", + "[sn:%i] PC %s.\n", tid, prevStage->insts[i]->seqNum, - prevStage->insts[i]->readPC()); + prevStage->insts[i]->pcState()); prevStage->insts[i]->setSquashed(); prevStage->insts[i] = cpu->dummyBufferInst; @@ -429,8 +423,8 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid) break; } DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] " - " PC %08p.\n", tid, skidBuffer[tid].front()->seqNum, - skidBuffer[tid].front()->PC); + " PC %s.\n", tid, skidBuffer[tid].front()->seqNum, + skidBuffer[tid].front()->pc); skidBuffer[tid].pop(); } @@ -488,8 +482,8 @@ PipelineStage::skidInsert(ThreadID tid) assert(tid == inst->threadNumber); - DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%#x into stage " - "skidBuffer %i\n", tid, inst->seqNum, inst->readPC(), + DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%s into stage " + "skidBuffer %i\n", tid, inst->seqNum, inst->pcState(), inst->threadNumber); skidBuffer[tid].push(inst); @@ -571,9 +565,9 @@ PipelineStage::activateThread(ThreadID tid) } else { DynInstPtr inst = switchedOutBuffer[tid]; - DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into" + DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%s into" " stage skidBuffer %i\n", tid, inst->seqNum, - inst->readPC(), inst->threadNumber); + inst->pcState(), inst->threadNumber); // Make instruction available for pipeline processing skidBuffer[tid].push(inst); @@ -895,13 +889,12 @@ PipelineStage::processInsts(ThreadID tid) inst = insts_to_stage.front(); DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] " - "with PC %#x\n", - tid, inst->seqNum, inst->readPC()); + "with PC %s\n", tid, inst->seqNum, inst->pcState()); if (inst->isSquashed()) { - DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %#x is " + DPRINTF(InOrderStage, "[tid:%u]: Instruction %i with PC %s is " "squashed, skipping.\n", - tid, inst->seqNum, inst->readPC()); + tid, inst->seqNum, inst->pcState()); insts_to_stage.pop(); @@ -1001,8 +994,8 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed) switchedOutValid[tid] = true; // Remove Thread From Pipeline & Resource Pool - inst->squashingStage = stageNum; - inst->bdelaySeqNum = inst->seqNum; + inst->squashingStage = stageNum; + inst->bdelaySeqNum = inst->seqNum; cpu->squashFromMemStall(inst, tid); // Switch On Cache Miss @@ -1038,9 +1031,9 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed) res_stage_num = inst->nextResStage(); } } else { - DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %#x " + DPRINTF(InOrderStage, "[tid:%u]: Instruction [sn:%i] with PC %s " " needed no resources in stage %i.\n", - tid, inst->seqNum, inst->readPC(), stageNum); + tid, inst->seqNum, inst->pcState(), stageNum); } return last_req_completed; @@ -1134,8 +1127,8 @@ PipelineStage::dumpInsts() while (!copy_buff.empty()) { DynInstPtr inst = copy_buff.front(); - cprintf("Inst. PC:%#x\n[tid:%i]\n[sn:%i]\n\n", - inst->readPC(), inst->threadNumber, inst->seqNum); + cprintf("Inst. PC:%s\n[tid:%i]\n[sn:%i]\n\n", + inst->pcState(), inst->threadNumber, inst->seqNum); copy_buff.pop(); } diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index c971e400e..6df104e6c 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -293,15 +293,15 @@ class PipelineStage /** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */ Addr bdelayDoneSeqNum[ThePipeline::MaxThreads]; - /** Instruction used for squashing branch (used for MIPS) */ - DynInstPtr squashInst[ThePipeline::MaxThreads]; - /** Tells when their is a pending delay slot inst. to send * to rename. If there is, then wait squash after the next * instruction (used for MIPS). */ bool squashAfterDelaySlot[ThePipeline::MaxThreads]; + /** Instruction used for squashing branch (used for MIPS) */ + DynInstPtr squashInst[ThePipeline::MaxThreads]; + /** Maximum size of the inter-stage buffer connecting the previous stage to * this stage (which we call a skid buffer) */ unsigned stageBufferMax; diff --git a/src/cpu/inorder/resources/bpred_unit.cc b/src/cpu/inorder/resources/bpred_unit.cc index b08a393f7..310053409 100644 --- a/src/cpu/inorder/resources/bpred_unit.cc +++ b/src/cpu/inorder/resources/bpred_unit.cc @@ -31,6 +31,7 @@ #include <list> #include <vector> +#include "arch/utility.hh" #include "base/trace.hh" #include "base/traceflags.hh" #include "config/the_isa.hh" @@ -149,7 +150,7 @@ BPredUnit::takeOverFrom() bool -BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) +BPredUnit::predict(DynInstPtr &inst, TheISA::PCState &predPC, ThreadID tid) { // See if branch predictor predicts taken. // If so, get its target addr either from the BTB or the RAS. @@ -160,12 +161,13 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) int asid = inst->asid; bool pred_taken = false; - Addr target; + TheISA::PCState target; ++lookups; - DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC%#x doing branch " + DPRINTF(InOrderBPred, "[tid:%i] [sn:%i] %s ... PC %s doing branch " "prediction\n", tid, inst->seqNum, - inst->staticInst->disassemble(inst->PC), inst->readPC()); + inst->staticInst->disassemble(inst->instAddr()), + inst->pcState()); void *bp_history = NULL; @@ -185,14 +187,14 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) } else { ++condPredicted; - pred_taken = BPLookup(pred_PC, bp_history); + pred_taken = BPLookup(predPC.instAddr(), bp_history); DPRINTF(InOrderBPred, "[tid:%i]: Branch predictor predicted %i " - "for PC %#x\n", - tid, pred_taken, inst->readPC()); + "for PC %s\n", + tid, pred_taken, inst->pcState()); } - PredictorHistory predict_record(inst->seqNum, pred_PC, pred_taken, + PredictorHistory predict_record(inst->seqNum, predPC, pred_taken, bp_history, tid); // Now lookup in the BTB or RAS. @@ -202,40 +204,37 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) // If it's a function return call, then look up the address // in the RAS. - target = RAS[tid].top(); + TheISA::PCState rasTop = RAS[tid].top(); + target = TheISA::buildRetPC(inst->pcState(), rasTop); // Record the top entry of the RAS, and its index. predict_record.usedRAS = true; predict_record.RASIndex = RAS[tid].topIdx(); - predict_record.RASTarget = target; + predict_record.rasTarget = rasTop; assert(predict_record.RASIndex < 16); RAS[tid].pop(); - DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x is a return, " - "RAS predicted target: %#x, RAS index: %i.\n", - tid, inst->readPC(), target, predict_record.RASIndex); + DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s is a return, " + "RAS predicted target: %s, RAS index: %i.\n", + tid, inst->pcState(), target, + predict_record.RASIndex); } else { ++BTBLookups; if (inst->isCall()) { -#if ISA_HAS_DELAY_SLOT - Addr ras_pc = pred_PC + instSize; // Next Next PC -#else - Addr ras_pc = pred_PC; // Next PC -#endif - - RAS[tid].push(ras_pc); + RAS[tid].push(inst->pcState()); // Record that it was a call so that the top RAS entry can // be popped off if the speculation is incorrect. predict_record.wasCall = true; - DPRINTF(InOrderBPred, "[tid:%i]: Instruction %#x was a call" - ", adding %#x to the RAS index: %i.\n", - tid, inst->readPC(), ras_pc, RAS[tid].topIdx()); + DPRINTF(InOrderBPred, "[tid:%i]: Instruction %s was a call" + ", adding %s to the RAS index: %i.\n", + tid, inst->pcState(), predPC, + RAS[tid].topIdx()); } if (inst->isCall() && @@ -243,18 +242,18 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) inst->isDirectCtrl()) { target = inst->branchTarget(); - DPRINTF(InOrderBPred, "[tid:%i]: Setting %#x predicted" - " target to %#x.\n", - tid, inst->readPC(), target); - } else if (BTB.valid(pred_PC, asid)) { + DPRINTF(InOrderBPred, "[tid:%i]: Setting %s predicted" + " target to %s.\n", + tid, inst->pcState(), target); + } else if (BTB.valid(predPC.instAddr(), asid)) { ++BTBHits; // If it's not a return, use the BTB to get the target addr. - target = BTB.lookup(pred_PC, asid); + target = BTB.lookup(predPC.instAddr(), asid); - DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %#x " - "predicted target is %#x.\n", - tid, asid, inst->readPC(), target); + DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %s " + "predicted target is %s.\n", + tid, asid, inst->pcState(), target); } else { DPRINTF(InOrderBPred, "[tid:%i]: BTB doesn't have a " "valid entry.\n",tid); @@ -265,14 +264,7 @@ BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) if (pred_taken) { // Set the PC and the instruction's predicted target. - pred_PC = target; - } else { -#if ISA_HAS_DELAY_SLOT - // This value will be inst->PC + 4 (nextPC) - // Delay Slot archs need this to be inst->PC + 8 (nextNPC) - // so we increment one more time here. - pred_PC = pred_PC + instSize; -#endif + predPC = target; } predHist[tid].push_front(predict_record); @@ -296,7 +288,7 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) while (!predHist[tid].empty() && predHist[tid].back().seqNum <= done_sn) { // Update the branch predictor with the correct results. - BPUpdate(predHist[tid].back().PC, + BPUpdate(predHist[tid].back().pc.instAddr(), predHist[tid].back().predTaken, predHist[tid].back().bpHistory); @@ -314,13 +306,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid) pred_hist.front().seqNum > squashed_sn) { if (pred_hist.front().usedRAS) { DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Restoring top of RAS " - "to: %i, target: %#x.\n", + "to: %i, target: %s.\n", tid, pred_hist.front().RASIndex, - pred_hist.front().RASTarget); + pred_hist.front().rasTarget); RAS[tid].restore(pred_hist.front().RASIndex, - pred_hist.front().RASTarget); + pred_hist.front().rasTarget); } else if (pred_hist.front().wasCall) { DPRINTF(InOrderBPred, "BranchPred: [tid:%i]: Removing speculative " @@ -340,7 +332,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid, ThreadID asid) void BPredUnit::squash(const InstSeqNum &squashed_sn, - const Addr &corr_target, + const TheISA::PCState &corrTarget, bool actually_taken, ThreadID tid, ThreadID asid) @@ -354,8 +346,8 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ++condIncorrect; DPRINTF(InOrderBPred, "[tid:%i]: Squashing from sequence number %i, " - "setting target to %#x.\n", - tid, squashed_sn, corr_target); + "setting target to %s.\n", + tid, squashed_sn, corrTarget); squash(squashed_sn, tid); @@ -380,13 +372,13 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ++RASIncorrect; } - BPUpdate((*hist_it).PC, actually_taken, + BPUpdate((*hist_it).pc.instAddr(), actually_taken, pred_hist.front().bpHistory); - BTB.update((*hist_it).PC, corr_target, asid); + BTB.update((*hist_it).pc.instAddr(), corrTarget, asid); DPRINTF(InOrderBPred, "[tid:%i]: Removing history for [sn:%i] " - "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC); + "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc); pred_hist.erase(hist_it); @@ -424,7 +416,7 @@ BPredUnit::BPSquash(void *bp_history) bool -BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history) +BPredUnit::BPLookup(Addr inst_PC, void * &bp_history) { if (predictor == Local) { return localBP->lookup(inst_PC, bp_history); @@ -437,7 +429,7 @@ BPredUnit::BPLookup(Addr &inst_PC, void * &bp_history) void -BPredUnit::BPUpdate(Addr &inst_PC, bool taken, void *bp_history) +BPredUnit::BPUpdate(Addr inst_PC, bool taken, void *bp_history) { if (predictor == Local) { localBP->update(inst_PC, taken, bp_history); diff --git a/src/cpu/inorder/resources/bpred_unit.hh b/src/cpu/inorder/resources/bpred_unit.hh index 881bfcc95..3b1c0f4ef 100644 --- a/src/cpu/inorder/resources/bpred_unit.hh +++ b/src/cpu/inorder/resources/bpred_unit.hh @@ -83,11 +83,12 @@ class BPredUnit * Predicts whether or not the instruction is a taken branch, and the * target of the branch if it is taken. * @param inst The branch instruction. - * @param pred_PC The predicted PC is passed back through this parameter. + * @param predPC The predicted PC is passed back through this parameter. * @param tid The thread id. * @return Returns if the branch is taken or not. */ - bool predict(ThePipeline::DynInstPtr &inst, Addr &pred_PC, ThreadID tid); + bool predict(ThePipeline::DynInstPtr &inst, + TheISA::PCState &predPC, ThreadID tid); // @todo: Rename this function. void BPUncond(void * &bp_history); @@ -114,12 +115,13 @@ class BPredUnit * corrects that sn's update with the proper address and taken/not taken. * @param squashed_sn The sequence number to squash any younger updates up * until. - * @param corr_target The correct branch target. + * @param corrTarget The correct branch target. * @param actually_taken The correct branch direction. * @param tid The thread id. */ - void squash(const InstSeqNum &squashed_sn, const Addr &corr_target, - bool actually_taken, ThreadID tid, ThreadID asid = 0); + void squash(const InstSeqNum &squashed_sn, + const TheISA::PCState &corrTarget, bool actually_taken, + ThreadID tid, ThreadID asid = 0); /** * @param bp_history Pointer to the history object. The predictor @@ -134,7 +136,7 @@ class BPredUnit * has the branch predictor state associated with the lookup. * @return Whether the branch is taken or not taken. */ - bool BPLookup(Addr &inst_PC, void * &bp_history); + bool BPLookup(Addr instPC, void * &bp_history); /** * Looks up a given PC in the BTB to see if a matching entry exists. @@ -149,26 +151,26 @@ class BPredUnit * @param inst_PC The PC to look up. * @return The address of the target of the branch. */ - Addr BTBLookup(Addr &inst_PC) - { return BTB.lookup(inst_PC, 0); } + TheISA::PCState BTBLookup(Addr instPC) + { return BTB.lookup(instPC, 0); } /** * Updates the BP with taken/not taken information. - * @param inst_PC The branch's PC that will be updated. + * @param instPC The branch's PC that will be updated. * @param taken Whether the branch was taken or not taken. * @param bp_history Pointer to the branch predictor state that is * associated with the branch lookup that is being updated. * @todo Make this update flexible enough to handle a global predictor. */ - void BPUpdate(Addr &inst_PC, bool taken, void *bp_history); + void BPUpdate(Addr instPC, bool taken, void *bp_history); /** * Updates the BTB with the target of a branch. * @param inst_PC The branch's PC that will be updated. * @param target_PC The branch's target that will be added to the BTB. */ - void BTBUpdate(Addr &inst_PC, Addr &target_PC) - { BTB.update(inst_PC, target_PC,0); } + void BTBUpdate(Addr instPC, const TheISA::PCState &targetPC) + { BTB.update(instPC, targetPC, 0); } void dump(); @@ -181,22 +183,22 @@ class BPredUnit * Makes a predictor history struct that contains any * information needed to update the predictor, BTB, and RAS. */ - PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC, - bool pred_taken, void *bp_history, - ThreadID _tid) - : seqNum(seq_num), PC(inst_PC), RASTarget(0), - RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0), - wasCall(0), bpHistory(bp_history) - { } + PredictorHistory(const InstSeqNum &seq_num, + const TheISA::PCState &instPC, bool pred_taken, + void *bp_history, ThreadID _tid) + : seqNum(seq_num), pc(instPC), rasTarget(0), RASIndex(0), + tid(_tid), predTaken(pred_taken), usedRAS(0), wasCall(0), + bpHistory(bp_history) + {} /** The sequence number for the predictor history entry. */ InstSeqNum seqNum; /** The PC associated with the sequence number. */ - Addr PC; + TheISA::PCState pc; /** The RAS target (only valid if a return). */ - Addr RASTarget; + TheISA::PCState rasTarget; /** The RAS index of the instruction (only valid if a call). */ unsigned RASIndex; diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc index b971d959a..33b67ce4a 100644 --- a/src/cpu/inorder/resources/branch_predictor.cc +++ b/src/cpu/inorder/resources/branch_predictor.cc @@ -84,41 +84,34 @@ BranchPredictor::execute(int slot_num) DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, " "skipping prediction \n", tid, inst->seqNum); } else { - Addr pred_PC = inst->readNextPC(); + TheISA::PCState predPC = inst->pcState(); + TheISA::advancePC(predPC, inst->staticInst); if (inst->isControl()) { // If not, the pred_PC be updated to pc+8 // If predicted, the pred_PC will be updated to new target // value - bool predict_taken = branchPred.predict(inst, pred_PC, tid); + bool predict_taken = branchPred.predict(inst, predPC, tid); if (predict_taken) { DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch " "predicted true.\n", tid, seq_num); - - inst->setPredTarg(pred_PC); - predictedTaken++; } else { DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Branch " "predicted false.\n", tid, seq_num); - - if (inst->isCondDelaySlot()) - { - inst->setPredTarg(inst->readPC() + (2 * instSize)); - } else { - inst->setPredTarg(pred_PC); - } - predictedNotTaken++; } + inst->setPredTarg(predPC); + inst->setBranchPred(predict_taken); DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: Predicted PC is " - "%08p.\n", tid, seq_num, pred_PC); + "%s.\n", tid, seq_num, predPC); } else { + inst->setPredTarg(predPC); //DPRINTF(InOrderBPred, "[tid:%i]: Ignoring [sn:%i] " // "because this isn't " // "a control instruction.\n", tid, seq_num); @@ -166,10 +159,9 @@ BranchPredictor::squash(DynInstPtr inst, int squash_stage, squash_seq_num = squash_seq_num - 1; #endif - if(squash_stage>=ThePipeline::BackEndStartStage) { - Addr corr_targ=inst->readPredPC(); - bool taken=inst->predTaken(); - branchPred.squash(squash_seq_num,corr_targ,taken,tid); + if (squash_stage >= ThePipeline::BackEndStartStage) { + bool taken = inst->predTaken(); + branchPred.squash(squash_seq_num, inst->readPredTarg(), taken, tid); } else { branchPred.squash(squash_seq_num, tid); } diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 73deacb12..e7f689ffa 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -392,15 +392,16 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, unsigned slot_idx = cache_req->getSlot(); if (tlb_mode == TheISA::TLB::Execute) { - inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, - acc_size, flags, inst->readPC(), - cpu->readCpuId(), inst->readTid()); - cache_req->memReq = inst->fetchMemReq; + inst->fetchMemReq = + new Request(inst->readTid(), aligned_addr, acc_size, flags, + inst->instAddr(), cpu->readCpuId(), inst->readTid()); + cache_req->memReq = inst->fetchMemReq; } else { if (!cache_req->is2ndSplit()) { - inst->dataMemReq = new Request(cpu->asid[tid], aligned_addr, - acc_size, flags, inst->readPC(), - cpu->readCpuId(), inst->readTid()); + inst->dataMemReq = + new Request(cpu->asid[tid], aligned_addr, acc_size, flags, + inst->instAddr(), cpu->readCpuId(), + inst->readTid()); cache_req->memReq = inst->dataMemReq; } else { assert(inst->splitInst); @@ -409,7 +410,7 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, inst->split2ndAddr, acc_size, flags, - inst->readPC(), + inst->instAddr(), cpu->readCpuId(), tid); cache_req->memReq = inst->splitMemReq; @@ -754,7 +755,8 @@ CacheUnit::execute(int slot_num) DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n", - tid, seq_num, inst->staticInst->disassemble(inst->PC)); + tid, seq_num, + inst->staticInst->disassemble(inst->instAddr())); removeAddrDependency(inst); @@ -771,7 +773,7 @@ CacheUnit::execute(int slot_num) tid, inst->seqNum); DPRINTF(InOrderStall, "STALL: [tid:%i]: Fetch miss from %08p\n", - tid, cache_req->inst->readPC()); + tid, cache_req->inst->instAddr()); cache_req->setCompleted(false); //cache_req->setMemStall(true); } @@ -1046,21 +1048,22 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) // @todo: update thsi ExtMachInst ext_inst; StaticInstPtr staticInst = NULL; - Addr inst_pc = inst->readPC(); + TheISA::PCState instPC = inst->pcState(); MachInst mach_inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *> (cache_pkt->getPtr<uint8_t>())); predecoder.setTC(cpu->thread[tid]->getTC()); - predecoder.moreBytes(inst_pc, inst_pc, mach_inst); - ext_inst = predecoder.getExtMachInst(); + predecoder.moreBytes(instPC, inst->instAddr(), mach_inst); + ext_inst = predecoder.getExtMachInst(instPC); + inst->pcState(instPC); inst->setMachInst(ext_inst); // Set Up More TraceData info if (inst->traceData) { inst->traceData->setStaticInst(inst->staticInst); - inst->traceData->setPC(inst->readPC()); + inst->traceData->setPC(instPC); } } else if (inst->staticInst && inst->isMemRef()) { @@ -1149,7 +1152,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) } else { DPRINTF(InOrderCachePort, "[tid:%u] Miss on block @ %08p completed, but squashed\n", - tid, cache_req->inst->readPC()); + tid, cache_req->inst->instAddr()); cache_req->setMemAccCompleted(); } } diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc index 91e788fbc..4342042e9 100644 --- a/src/cpu/inorder/resources/execution_unit.cc +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -91,8 +91,8 @@ ExecutionUnit::execute(int slot_num) exec_req->fault = NoFault; - DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%#x] %s.\n", - tid, seq_num, inst->readPC(), inst->instName()); + DPRINTF(InOrderExecute, "[tid:%i] Executing [sn:%i] [PC:%s] %s.\n", + tid, seq_num, inst->pcState(), inst->instName()); switch (exec_req->cmd) { @@ -124,58 +124,61 @@ ExecutionUnit::execute(int slot_num) if (inst->isDirectCtrl()) { assert(!inst->isIndirectCtrl()); + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + inst->setPredTarg(pc); + if (inst->predTaken() && inst->isCondDelaySlot()) { inst->bdelaySeqNum = seq_num; - inst->setPredTarg(inst->nextPC); DPRINTF(InOrderExecute, "[tid:%i]: Conditional" - " branch inst [sn:%i] PC %#x mis" + " branch inst [sn:%i] PC %s mis" "predicted as taken.\n", tid, - seq_num, inst->PC); + seq_num, inst->pcState()); } else if (!inst->predTaken() && inst->isCondDelaySlot()) { inst->bdelaySeqNum = seq_num; - inst->setPredTarg(inst->nextPC); inst->procDelaySlotOnMispred = true; DPRINTF(InOrderExecute, "[tid:%i]: Conditional" - " branch inst [sn:%i] PC %#x mis" + " branch inst [sn:%i] PC %s mis" "predicted as not taken.\n", tid, - seq_num, inst->PC); + seq_num, inst->pcState()); } else { #if ISA_HAS_DELAY_SLOT inst->bdelaySeqNum = seq_num + 1; - inst->setPredTarg(inst->nextNPC); #else inst->bdelaySeqNum = seq_num; - inst->setPredTarg(inst->nextPC); #endif DPRINTF(InOrderExecute, "[tid:%i]: " "Misprediction detected at " - "[sn:%i] PC %#x,\n\t squashing after " + "[sn:%i] PC %s,\n\t squashing after " "delay slot instruction [sn:%i].\n", - tid, seq_num, inst->PC, + tid, seq_num, inst->pcState(), inst->bdelaySeqNum); DPRINTF(InOrderStall, "STALL: [tid:%i]: Branch" - " misprediction at %#x\n", - tid, inst->PC); + " misprediction at %s\n", + tid, inst->pcState()); } DPRINTF(InOrderExecute, "[tid:%i] Redirecting " - "fetch to %#x.\n", tid, + "fetch to %s.\n", tid, inst->readPredTarg()); - } else if(inst->isIndirectCtrl()){ + } else if (inst->isIndirectCtrl()){ + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + inst->seqNum = seq_num; + inst->setPredTarg(pc); + #if ISA_HAS_DELAY_SLOT - inst->setPredTarg(inst->nextNPC); inst->bdelaySeqNum = seq_num + 1; #else - inst->setPredTarg(inst->nextPC); inst->bdelaySeqNum = seq_num; #endif DPRINTF(InOrderExecute, "[tid:%i] Redirecting" - " fetch to %#x.\n", tid, + " fetch to %s.\n", tid, inst->readPredTarg()); } else { panic("Non-control instruction (%s) mispredict" @@ -197,14 +200,20 @@ ExecutionUnit::execute(int slot_num) if (inst->predTaken()) { predictedTakenIncorrect++; - DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Taken)\n", - tid, inst->seqNum, inst->staticInst->disassemble(inst->PC), - inst->readPC()); + DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..." + "PC %s ... Mispredicts! (Taken)\n", + tid, inst->seqNum, + inst->staticInst->disassemble( + inst->instAddr()), + inst->pcState()); } else { predictedNotTakenIncorrect++; - DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ... PC%#x ... Mispredicts! (Not Taken)\n", - tid, inst->seqNum, inst->staticInst->disassemble(inst->PC), - inst->readPC()); + DPRINTF(InOrderExecute, "[tid:%i] [sn:%i] %s ..." + "PC %s ... Mispredicts! (Not Taken)\n", + tid, inst->seqNum, + inst->staticInst->disassemble( + inst->instAddr()), + inst->pcState()); } predictedIncorrect++; } else { diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc index 8a1ec3ce5..3bfe912e7 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -44,9 +44,6 @@ FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width, instSize(sizeof(MachInst)) { for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetReady = false; - pcValid[tid] = false; pcBlockStage[tid] = 0; @@ -86,53 +83,17 @@ FetchSeqUnit::execute(int slot_num) case AssignNextPC: { if (pcValid[tid]) { + inst->pcState(pc[tid]); + inst->setMemAddr(pc[tid].instAddr()); - if (delaySlotInfo[tid].targetReady && - delaySlotInfo[tid].numInsts == 0) { - // Set PC to target - PC[tid] = delaySlotInfo[tid].targetAddr; //next_PC - nextPC[tid] = PC[tid] + instSize; //next_NPC - nextNPC[tid] = PC[tid] + (2 * instSize); - - delaySlotInfo[tid].targetReady = false; - - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to delay " - "slot target\n",tid); - } + pc[tid].advance(); //XXX HACK! + inst->setPredTarg(pc[tid]); - inst->setPC(PC[tid]); - inst->setNextPC(PC[tid] + instSize); - inst->setNextNPC(PC[tid] + (instSize * 2)); - -#if ISA_HAS_DELAY_SLOT - inst->setPredTarg(inst->readNextNPC()); -#else - inst->setPredTarg(inst->readNextPC()); -#endif - inst->setMemAddr(PC[tid]); inst->setSeqNum(cpu->getAndIncrementInstSeq(tid)); DPRINTF(InOrderFetchSeq, "[tid:%i]: Assigning [sn:%i] to " - "PC %08p, NPC %08p, NNPC %08p\n", tid, - inst->seqNum, inst->readPC(), inst->readNextPC(), - inst->readNextNPC()); - - if (delaySlotInfo[tid].numInsts > 0) { - --delaySlotInfo[tid].numInsts; - - // It's OK to set PC to target of branch - if (delaySlotInfo[tid].numInsts == 0) { - delaySlotInfo[tid].targetReady = true; - } - - DPRINTF(InOrderFetchSeq, "[tid:%i]: %i delay slot inst(s) " - "left to process.\n", tid, - delaySlotInfo[tid].numInsts); - } - - PC[tid] = nextPC[tid]; - nextPC[tid] = nextNPC[tid]; - nextNPC[tid] += instSize; + "PC %s\n", tid, inst->seqNum, + inst->pcState()); fs_req->done(); } else { @@ -147,18 +108,21 @@ FetchSeqUnit::execute(int slot_num) if (inst->isControl()) { // If it's a return, then we must wait for resolved address. if (inst->isReturn() && !inst->predTaken()) { - cpu->pipelineStage[stage_num]->toPrevStages->stageBlock[stage_num][tid] = true; + cpu->pipelineStage[stage_num]-> + toPrevStages->stageBlock[stage_num][tid] = true; pcValid[tid] = false; pcBlockStage[tid] = stage_num; } else if (inst->isCondDelaySlot() && !inst->predTaken()) { // Not-Taken AND Conditional Control - DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%08p] " - "Predicted Not-Taken Cond. " - "Delay inst. Skipping delay slot and Updating PC to %08p\n", - tid, inst->seqNum, inst->readPC(), inst->readPredTarg()); + DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: [PC:%s] " + "Predicted Not-Taken Cond. Delay inst. Skipping " + "delay slot and Updating PC to %s\n", + tid, inst->seqNum, inst->pcState(), + inst->readPredTarg()); - DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to start from stage %i, after [sn:%i].\n", - tid, stage_num, seq_num); + DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to " + "start from stage %i, after [sn:%i].\n", tid, + stage_num, seq_num); inst->bdelaySeqNum = seq_num; inst->squashingStage = stage_num; @@ -168,33 +132,26 @@ FetchSeqUnit::execute(int slot_num) // Not-Taken Control DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Predicted " "Not-Taken Control " - "inst. updating PC to %08p\n", tid, inst->seqNum, - inst->readNextPC()); + "inst. updating PC to %s\n", tid, inst->seqNum, + inst->readPredTarg()); #if ISA_HAS_DELAY_SLOT - ++delaySlotInfo[tid].numInsts; - delaySlotInfo[tid].targetReady = false; - delaySlotInfo[tid].targetAddr = inst->readNextNPC(); -#else - assert(delaySlotInfo[tid].numInsts == 0); + pc[tid] = inst->pcState(); + advancePC(pc[tid], inst->staticInst); #endif } else if (inst->predTaken()) { // Taken Control #if ISA_HAS_DELAY_SLOT - ++delaySlotInfo[tid].numInsts; - delaySlotInfo[tid].targetReady = false; - delaySlotInfo[tid].targetAddr = inst->readPredTarg(); + pc[tid] = inst->readPredTarg(); DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i] Updating delay" - " slot target to PC %08p\n", tid, inst->seqNum, + " slot target to PC %s\n", tid, inst->seqNum, inst->readPredTarg()); inst->bdelaySeqNum = seq_num + 1; #else inst->bdelaySeqNum = seq_num; - assert(delaySlotInfo[tid].numInsts == 0); #endif inst->squashingStage = stage_num; - DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to " "start from stage %i, after [sn:%i].\n", tid, stage_num, inst->bdelaySeqNum); @@ -225,11 +182,12 @@ FetchSeqUnit::squashAfterInst(DynInstPtr inst, int stage_num, ThreadID tid) // Squash inside current resource, so if there needs to be fetching on // same cycle the fetch information will be correct. - // squash(inst, stage_num, inst->bdelaySeqNum, tid); // Schedule Squash Through-out Resource Pool - cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0); + cpu->resPool->scheduleEvent( + (InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0); } + void FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, InstSeqNum squash_seq_num, ThreadID tid) @@ -241,8 +199,15 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, // Handles the case where we are squashing because of something that is // not a branch...like a memory stall - Addr new_PC = (inst->isControl()) ? - inst->readPredTarg() : inst->readPC() + instSize; + TheISA::PCState newPC; + if (inst->isControl()) { + newPC = inst->readPredTarg(); + } else { + TheISA::PCState thisPC = inst->pcState(); + assert(inst->staticInst); + advancePC(thisPC, inst->staticInst); + newPC = thisPC; + } if (squashSeqNum[tid] <= done_seq_num && lastSquashCycle[tid] == curTick) { @@ -258,31 +223,25 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, // the last done_seq_num then this is the delay slot inst. if (cpu->nextInstSeqNum(tid) != done_seq_num && !inst->procDelaySlotOnMispred) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetReady = false; // Reset PC - PC[tid] = new_PC; - nextPC[tid] = new_PC + instSize; - nextNPC[tid] = new_PC + (2 * instSize); + pc[tid] = newPC; +#if ISA_HAS_DELAY_SLOT + TheISA::advancePC(pc[tid], inst->staticInst); +#endif - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %08p.\n", - tid, PC[tid]); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n", + tid, newPC); } else { -#if !ISA_HAS_DELAY_SLOT - assert(0); -#endif + assert(ISA_HAS_DELAY_SLOT); - delaySlotInfo[tid].numInsts = 1; - delaySlotInfo[tid].targetReady = false; - delaySlotInfo[tid].targetAddr = (inst->procDelaySlotOnMispred) ? - inst->branchTarget() : new_PC; + pc[tid] = (inst->procDelaySlotOnMispred) ? + inst->branchTarget() : newPC; // Reset PC to Delay Slot Instruction if (inst->procDelaySlotOnMispred) { - PC[tid] = new_PC; - nextPC[tid] = new_PC + instSize; - nextNPC[tid] = new_PC + (2 * instSize); + // Reset PC + pc[tid] = newPC; } } @@ -309,18 +268,13 @@ FetchSeqUnit::FetchSeqEvent::process() FetchSeqUnit* fs_res = dynamic_cast<FetchSeqUnit*>(resource); assert(fs_res); - for (int i=0; i < MaxThreads; i++) { - fs_res->PC[i] = fs_res->cpu->readPC(i); - fs_res->nextPC[i] = fs_res->cpu->readNextPC(i); - fs_res->nextNPC[i] = fs_res->cpu->readNextNPC(i); - DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC:%08p NPC:%08p " - "NNPC:%08p.\n", fs_res->PC[i], fs_res->nextPC[i], - fs_res->nextNPC[i]); + for (int i = 0; i < MaxThreads; i++) { + fs_res->pc[i] = fs_res->cpu->pcState(i); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC: %s.\n", + fs_res->pc[i]); fs_res->pcValid[i] = true; } - - //cpu->fetchPriorityList.push_back(tid); } @@ -329,22 +283,17 @@ FetchSeqUnit::activateThread(ThreadID tid) { pcValid[tid] = true; - PC[tid] = cpu->readPC(tid); - nextPC[tid] = cpu->readNextPC(tid); - nextNPC[tid] = cpu->readNextNPC(tid); + pc[tid] = cpu->pcState(tid); cpu->fetchPriorityList.push_back(tid); - DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC:%08p NPC:%08p " - "NNPC:%08p.\n", tid, PC[tid], nextPC[tid], nextNPC[tid]); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Reading PC: %s.\n", + tid, pc[tid]); } void FetchSeqUnit::deactivateThread(ThreadID tid) { - delaySlotInfo[tid].numInsts = 0; - delaySlotInfo[tid].targetReady = false; - pcValid[tid] = false; pcBlockStage[tid] = 0; @@ -375,18 +324,14 @@ FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) * switch was right after the branch. Thus, if it's not, then * we are updating incorrectly here */ - assert(cpu->thread[tid]->lastBranchNextPC == inst->readPC()); - - PC[tid] = cpu->thread[tid]->lastBranchNextNPC; - nextPC[tid] = PC[tid] + instSize; - nextNPC[tid] = nextPC[tid] + instSize; + assert(cpu->nextInstAddr(tid) == inst->instAddr()); + pc[tid] = cpu->thread[tid]->lastBranchPC; } else { - PC[tid] = inst->readNextPC(); - nextPC[tid] = inst->readNextNPC(); - nextNPC[tid] = inst->readNextNPC() + instSize; + pc[tid] = inst->pcState(); } + assert(inst->staticInst); + advancePC(pc[tid], inst->staticInst); DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch." - "Assigning PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid], - nextPC[tid], nextNPC[tid]); + "Assigning PC: %s.\n", tid, pc[tid]); } diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh index aab462224..a258dc0e5 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.hh +++ b/src/cpu/inorder/resources/fetch_seq_unit.hh @@ -80,22 +80,7 @@ class FetchSeqUnit : public Resource { bool pcValid[ThePipeline::MaxThreads]; int pcBlockStage[ThePipeline::MaxThreads]; - TheISA::IntReg PC[ThePipeline::MaxThreads]; - TheISA::IntReg nextPC[ThePipeline::MaxThreads]; - TheISA::IntReg nextNPC[ThePipeline::MaxThreads]; - - /** Tracks delay slot information for threads in ISAs which use - * delay slots; - */ - struct DelaySlotInfo { - InstSeqNum delaySlotSeqNum; - InstSeqNum branchSeqNum; - int numInsts; - Addr targetAddr; - bool targetReady; - }; - - DelaySlotInfo delaySlotInfo[ThePipeline::MaxThreads]; + TheISA::PCState pc[ThePipeline::MaxThreads]; /** Squash Seq. Nums*/ InstSeqNum squashSeqNum[ThePipeline::MaxThreads]; diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh index 5c62c7751..eb1bf55f0 100644 --- a/src/cpu/inorder/resources/tlb_unit.hh +++ b/src/cpu/inorder/resources/tlb_unit.hh @@ -111,8 +111,10 @@ class TLBUnitRequest : public ResourceRequest { aligned_addr = inst->getMemAddr(); req_size = sizeof(TheISA::MachInst); flags = 0; - inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, req_size, - flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid()); + inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, + req_size, flags, inst->instAddr(), + res->cpu->readCpuId(), + inst->readTid()); memReq = inst->fetchMemReq; } else { aligned_addr = inst->getMemAddr();; @@ -123,8 +125,10 @@ class TLBUnitRequest : public ResourceRequest { req_size = 8; } - inst->dataMemReq = new Request(inst->readTid(), aligned_addr, req_size, - flags, inst->readPC(), res->cpu->readCpuId(), inst->readTid()); + inst->dataMemReq = new Request(inst->readTid(), aligned_addr, + req_size, flags, inst->instAddr(), + res->cpu->readCpuId(), + inst->readTid()); memReq = inst->dataMemReq; } } diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index e6d0af2cc..bbccf626a 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -234,30 +234,6 @@ InOrderThreadContext::setRegOtherThread(int misc_reg, const MiscReg &val, } void -InOrderThreadContext::setPC(uint64_t val) -{ - DPRINTF(InOrderCPU, "[tid:%i] Setting PC to %08p\n", - thread->readTid(), val); - cpu->setPC(val, thread->readTid()); -} - -void -InOrderThreadContext::setNextPC(uint64_t val) -{ - DPRINTF(InOrderCPU, "[tid:%i] Setting NPC to %08p\n", - thread->readTid(), val); - cpu->setNextPC(val, thread->readTid()); -} - -void -InOrderThreadContext::setNextNPC(uint64_t val) -{ - DPRINTF(InOrderCPU, "[tid:%i] Setting NNPC to %08p\n", - thread->readTid(), val); - cpu->setNextNPC(val, thread->readTid()); -} - -void InOrderThreadContext::setMiscRegNoEffect(int misc_reg, const MiscReg &val) { cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 0c0f563c0..21f1e5835 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -204,23 +204,21 @@ class InOrderThreadContext : public ThreadContext ThreadID tid); /** Reads this thread's PC. */ - uint64_t readPC() - { return cpu->readPC(thread->readTid()); } + TheISA::PCState pcState() + { return cpu->pcState(thread->readTid()); } /** Sets this thread's PC. */ - void setPC(uint64_t val); + void pcState(const TheISA::PCState &val) + { cpu->pcState(val, thread->readTid()); } - /** Reads this thread's next PC. */ - uint64_t readNextPC() - { return cpu->readNextPC(thread->readTid()); } + Addr instAddr() + { return cpu->instAddr(thread->readTid()); } - /** Sets this thread's next PC. */ - void setNextPC(uint64_t val); + Addr nextInstAddr() + { return cpu->nextInstAddr(thread->readTid()); } - uint64_t readNextNPC() - { return cpu->readNextNPC(thread->readTid()); } - - void setNextNPC(uint64_t val); + MicroPC microPC() + { return cpu->microPC(thread->readTid()); } /** Reads a miscellaneous register. */ MiscReg readMiscRegNoEffect(int misc_reg) diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh index 0a171a99f..20ace6659 100644 --- a/src/cpu/inorder/thread_state.hh +++ b/src/cpu/inorder/thread_state.hh @@ -111,9 +111,7 @@ class InOrderThreadState : public ThreadState { /** Is last instruction graduated a branch? */ bool lastGradIsBranch; - Addr lastBranchPC; - Addr lastBranchNextPC; - Addr lastBranchNextNPC; + TheISA::PCState lastBranchPC; }; #endif // __CPU_INORDER_THREAD_STATE_HH__ diff --git a/src/cpu/inteltrace.cc b/src/cpu/inteltrace.cc index ec51b80e7..ee148c50f 100644 --- a/src/cpu/inteltrace.cc +++ b/src/cpu/inteltrace.cc @@ -48,7 +48,7 @@ Trace::IntelTraceRecord::dump() { ostream &outs = Trace::output(); ccprintf(outs, "%7d ) ", when); - outs << "0x" << hex << PC << ":\t"; + outs << "0x" << hex << pc.instAddr() << ":\t"; if (staticInst->isLoad()) { ccprintf(outs, "<RD %#x>", addr); } else if (staticInst->isStore()) { diff --git a/src/cpu/inteltrace.hh b/src/cpu/inteltrace.hh index c4ace4f4b..234b173e9 100644 --- a/src/cpu/inteltrace.hh +++ b/src/cpu/inteltrace.hh @@ -46,10 +46,10 @@ class IntelTraceRecord : public InstRecord { public: IntelTraceRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : InstRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc) + _macroStaticInst) { } @@ -65,8 +65,8 @@ class IntelTrace : public InstTracer IntelTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (!IsOn(ExecEnable)) return NULL; @@ -78,7 +78,7 @@ class IntelTrace : public InstTracer return NULL; return new IntelTraceRecord(when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } }; diff --git a/src/cpu/legiontrace.cc b/src/cpu/legiontrace.cc index 1390d0807..8750e56e5 100644 --- a/src/cpu/legiontrace.cc +++ b/src/cpu/legiontrace.cc @@ -211,7 +211,7 @@ Trace::LegionTraceRecord::dump() if(!staticInst->isMicroop() || staticInst->isLastMicroop()) { while (!compared) { if (shared_data->flags == OWN_M5) { - m5Pc = PC & SparcISA::PAddrImplMask; + m5Pc = pc.instAddr() & SparcISA::PAddrImplMask; if (bits(shared_data->pstate,3,3)) { m5Pc &= mask(32); } @@ -432,13 +432,14 @@ Trace::LegionTraceRecord::dump() << endl; predecoder.setTC(thread); - predecoder.moreBytes(m5Pc, m5Pc, - shared_data->instruction); + predecoder.moreBytes(m5Pc, m5Pc, shared_data->instruction); assert(predecoder.extMachInstReady()); + PCState tempPC = pc; StaticInstPtr legionInst = - StaticInst::decode(predecoder.getExtMachInst(), lgnPc); + StaticInst::decode(predecoder.getExtMachInst(tempPC), + lgnPc); outs << setfill(' ') << setw(15) << " Legion Inst: " << "0x" << setw(8) << setfill('0') << hex diff --git a/src/cpu/legiontrace.hh b/src/cpu/legiontrace.hh index 829941d4b..a60b9ad10 100644 --- a/src/cpu/legiontrace.hh +++ b/src/cpu/legiontrace.hh @@ -46,10 +46,10 @@ class LegionTraceRecord : public InstRecord { public: LegionTraceRecord(Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : InstRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc) + _macroStaticInst) { } @@ -65,14 +65,14 @@ class LegionTrace : public InstTracer LegionTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (tc->misspeculating()) return NULL; return new LegionTraceRecord(when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } }; diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh index 6ad6b0242..5c5b9a66d 100644 --- a/src/cpu/nativetrace.hh +++ b/src/cpu/nativetrace.hh @@ -54,10 +54,10 @@ class NativeTraceRecord : public ExeTracerRecord public: NativeTraceRecord(NativeTrace * _parent, Tick _when, ThreadContext *_thread, - const StaticInstPtr _staticInst, Addr _pc, bool spec, - const StaticInstPtr _macroStaticInst = NULL, MicroPC _upc = 0) + const StaticInstPtr _staticInst, TheISA::PCState _pc, + bool spec, const StaticInstPtr _macroStaticInst = NULL) : ExeTracerRecord(_when, _thread, _staticInst, _pc, spec, - _macroStaticInst, _upc), + _macroStaticInst), parent(_parent) { } @@ -79,14 +79,14 @@ class NativeTrace : public ExeTracer NativeTraceRecord * getInstRecord(Tick when, ThreadContext *tc, - const StaticInstPtr staticInst, Addr pc, - const StaticInstPtr macroStaticInst = NULL, MicroPC upc = 0) + const StaticInstPtr staticInst, TheISA::PCState pc, + const StaticInstPtr macroStaticInst = NULL) { if (tc->misspeculating()) return NULL; return new NativeTraceRecord(this, when, tc, - staticInst, pc, tc->misspeculating(), macroStaticInst, upc); + staticInst, pc, tc->misspeculating(), macroStaticInst); } template<class T> diff --git a/src/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh index f199bdd75..58b1147c9 100644 --- a/src/cpu/o3/bpred_unit.hh +++ b/src/cpu/o3/bpred_unit.hh @@ -88,7 +88,7 @@ class BPredUnit * @param tid The thread id. * @return Returns if the branch is taken or not. */ - bool predict(DynInstPtr &inst, Addr &PC, ThreadID tid); + bool predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid); // @todo: Rename this function. void BPUncond(void * &bp_history); @@ -118,7 +118,8 @@ class BPredUnit * @param actually_taken The correct branch direction. * @param tid The thread id. */ - void squash(const InstSeqNum &squashed_sn, const Addr &corr_target, + void squash(const InstSeqNum &squashed_sn, + const TheISA::PCState &corr_target, bool actually_taken, ThreadID tid); /** @@ -134,23 +135,23 @@ class BPredUnit * has the branch predictor state associated with the lookup. * @return Whether the branch is taken or not taken. */ - bool BPLookup(Addr &inst_PC, void * &bp_history); + bool BPLookup(Addr instPC, void * &bp_history); /** * Looks up a given PC in the BTB to see if a matching entry exists. * @param inst_PC The PC to look up. * @return Whether the BTB contains the given PC. */ - bool BTBValid(Addr &inst_PC) - { return BTB.valid(inst_PC, 0); } + bool BTBValid(Addr instPC) + { return BTB.valid(instPC, 0); } /** * Looks up a given PC in the BTB to get the predicted target. * @param inst_PC The PC to look up. * @return The address of the target of the branch. */ - Addr BTBLookup(Addr &inst_PC) - { return BTB.lookup(inst_PC, 0); } + TheISA::PCState BTBLookup(Addr instPC) + { return BTB.lookup(instPC, 0); } /** * Updates the BP with taken/not taken information. @@ -160,15 +161,15 @@ class BPredUnit * associated with the branch lookup that is being updated. * @todo Make this update flexible enough to handle a global predictor. */ - void BPUpdate(Addr &inst_PC, bool taken, void *bp_history); + void BPUpdate(Addr instPC, bool taken, void *bp_history); /** * Updates the BTB with the target of a branch. * @param inst_PC The branch's PC that will be updated. * @param target_PC The branch's target that will be added to the BTB. */ - void BTBUpdate(Addr &inst_PC, Addr &target_PC) - { BTB.update(inst_PC, target_PC,0); } + void BTBUpdate(Addr instPC, const TheISA::PCState &target) + { BTB.update(instPC, target, 0); } void dump(); @@ -178,13 +179,13 @@ class BPredUnit * Makes a predictor history struct that contains any * information needed to update the predictor, BTB, and RAS. */ - PredictorHistory(const InstSeqNum &seq_num, const Addr &inst_PC, + PredictorHistory(const InstSeqNum &seq_num, Addr instPC, bool pred_taken, void *bp_history, ThreadID _tid) - : seqNum(seq_num), PC(inst_PC), RASTarget(0), - RASIndex(0), tid(_tid), predTaken(pred_taken), usedRAS(0), + : seqNum(seq_num), pc(instPC), RASTarget(0), RASIndex(0), + tid(_tid), predTaken(pred_taken), usedRAS(0), wasCall(0), bpHistory(bp_history) - { } + {} bool operator==(const PredictorHistory &entry) const { return this->seqNum == entry.seqNum; @@ -194,10 +195,10 @@ class BPredUnit InstSeqNum seqNum; /** The PC associated with the sequence number. */ - Addr PC; + Addr pc; /** The RAS target (only valid if a return). */ - Addr RASTarget; + TheISA::PCState RASTarget; /** The RAS index of the instruction (only valid if a call). */ unsigned RASIndex; diff --git a/src/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh index ed3471761..14d47df9f 100644 --- a/src/cpu/o3/bpred_unit_impl.hh +++ b/src/cpu/o3/bpred_unit_impl.hh @@ -31,6 +31,7 @@ #include <algorithm> #include "arch/types.hh" +#include "arch/utility.hh" #include "arch/isa_traits.hh" #include "base/trace.hh" #include "base/traceflags.hh" @@ -144,17 +145,15 @@ BPredUnit<Impl>::takeOverFrom() template <class Impl> bool -BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) +BPredUnit<Impl>::predict(DynInstPtr &inst, TheISA::PCState &pc, ThreadID tid) { // See if branch predictor predicts taken. // If so, get its target addr either from the BTB or the RAS. // Save off record of branch stuff so the RAS can be fixed // up once it's done. - using TheISA::MachInst; - bool pred_taken = false; - Addr target = PC; + TheISA::PCState target = pc; ++lookups; @@ -168,19 +167,19 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) } else { ++condPredicted; - pred_taken = BPLookup(PC, bp_history); + pred_taken = BPLookup(pc.instAddr(), bp_history); DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i " - "for PC %#x\n", - tid, pred_taken, inst->readPC()); + "for PC %s\n", + tid, pred_taken, inst->pcState()); } DPRINTF(Fetch, "BranchPred: [tid:%i]: [sn:%i] Creating prediction history " - "for PC %#x\n", - tid, inst->seqNum, inst->readPC()); + "for PC %s\n", + tid, inst->seqNum, inst->pcState()); - PredictorHistory predict_record(inst->seqNum, PC, pred_taken, - bp_history, tid); + PredictorHistory predict_record(inst->seqNum, pc.instAddr(), + pred_taken, bp_history, tid); // Now lookup in the BTB or RAS. if (pred_taken) { @@ -189,60 +188,58 @@ BPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) // If it's a function return call, then look up the address // in the RAS. - target = RAS[tid].top(); + TheISA::PCState rasTop = RAS[tid].top(); + target = TheISA::buildRetPC(pc, rasTop); // Record the top entry of the RAS, and its index. predict_record.usedRAS = true; predict_record.RASIndex = RAS[tid].topIdx(); - predict_record.RASTarget = target; + predict_record.RASTarget = rasTop; assert(predict_record.RASIndex < 16); RAS[tid].pop(); - DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x is a return, " - "RAS predicted target: %#x, RAS index: %i.\n", - tid, inst->readPC(), target, predict_record.RASIndex); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s is a return, " + "RAS predicted target: %s, RAS index: %i.\n", + tid, inst->pcState(), target, predict_record.RASIndex); } else { ++BTBLookups; if (inst->isCall()) { -#if ISA_HAS_DELAY_SLOT - Addr ras_pc = PC + (2 * sizeof(MachInst)); // Next Next PC -#else - Addr ras_pc = PC + sizeof(MachInst); // Next PC -#endif - RAS[tid].push(ras_pc); + RAS[tid].push(pc); // Record that it was a call so that the top RAS entry can // be popped off if the speculation is incorrect. predict_record.wasCall = true; - DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x was a call" - ", adding %#x to the RAS index: %i.\n", - tid, inst->readPC(), ras_pc, RAS[tid].topIdx()); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s was a " + "call, adding %s to the RAS index: %i.\n", + tid, inst->pcState(), pc, RAS[tid].topIdx()); } - if (BTB.valid(PC, tid)) { + if (BTB.valid(pc.instAddr(), tid)) { ++BTBHits; // If it's not a return, use the BTB to get the target addr. - target = BTB.lookup(PC, tid); + target = BTB.lookup(pc.instAddr(), tid); - DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x predicted" - " target is %#x.\n", - tid, inst->readPC(), target); + DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %s predicted" + " target is %s.\n", tid, inst->pcState(), target); } else { DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a " "valid entry.\n",tid); pred_taken = false; + TheISA::advancePC(target, inst->staticInst); } } + } else { + TheISA::advancePC(target, inst->staticInst); } - PC = target; + pc = target; predHist[tid].push_front(predict_record); @@ -262,7 +259,7 @@ BPredUnit<Impl>::update(const InstSeqNum &done_sn, ThreadID tid) while (!predHist[tid].empty() && predHist[tid].back().seqNum <= done_sn) { // Update the branch predictor with the correct results. - BPUpdate(predHist[tid].back().PC, + BPUpdate(predHist[tid].back().pc, predHist[tid].back().predTaken, predHist[tid].back().bpHistory); @@ -280,10 +277,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid) pred_hist.front().seqNum > squashed_sn) { if (pred_hist.front().usedRAS) { DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i," - " target: %#x.\n", - tid, - pred_hist.front().RASIndex, - pred_hist.front().RASTarget); + " target: %s.\n", tid, + pred_hist.front().RASIndex, pred_hist.front().RASTarget); RAS[tid].restore(pred_hist.front().RASIndex, pred_hist.front().RASTarget); @@ -298,11 +293,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid) BPSquash(pred_hist.front().bpHistory); DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] " - "PC %#x.\n", tid, pred_hist.front().seqNum, pred_hist.front().PC); + "PC %s.\n", tid, pred_hist.front().seqNum, + pred_hist.front().pc); pred_hist.pop_front(); - DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", tid, predHist[tid].size()); + DPRINTF(Fetch, "[tid:%i]: predHist.size(): %i\n", + tid, predHist[tid].size()); } } @@ -310,7 +307,7 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ThreadID tid) template <class Impl> void BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, - const Addr &corr_target, + const TheISA::PCState &corrTarget, bool actually_taken, ThreadID tid) { @@ -330,8 +327,8 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ++condIncorrect; DPRINTF(Fetch, "BranchPred: [tid:%i]: Squashing from sequence number %i, " - "setting target to %#x.\n", - tid, squashed_sn, corr_target); + "setting target to %s.\n", + tid, squashed_sn, corrTarget); // Squash All Branches AFTER this mispredicted branch squash(squashed_sn, tid); @@ -358,13 +355,13 @@ BPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, ++RASIncorrect; } - BPUpdate((*hist_it).PC, actually_taken, + BPUpdate((*hist_it).pc, actually_taken, pred_hist.front().bpHistory); - BTB.update((*hist_it).PC, corr_target, tid); + BTB.update((*hist_it).pc, corrTarget, tid); DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing history for [sn:%i] " - "PC %#x.\n", tid, (*hist_it).seqNum, (*hist_it).PC); + "PC %s.\n", tid, (*hist_it).seqNum, (*hist_it).pc); pred_hist.erase(hist_it); @@ -397,12 +394,12 @@ BPredUnit<Impl>::BPSquash(void *bp_history) template <class Impl> bool -BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history) +BPredUnit<Impl>::BPLookup(Addr instPC, void * &bp_history) { if (predictor == Local) { - return localBP->lookup(inst_PC, bp_history); + return localBP->lookup(instPC, bp_history); } else if (predictor == Tournament) { - return tournamentBP->lookup(inst_PC, bp_history); + return tournamentBP->lookup(instPC, bp_history); } else { panic("Predictor type is unexpected value!"); } @@ -410,12 +407,12 @@ BPredUnit<Impl>::BPLookup(Addr &inst_PC, void * &bp_history) template <class Impl> void -BPredUnit<Impl>::BPUpdate(Addr &inst_PC, bool taken, void *bp_history) +BPredUnit<Impl>::BPUpdate(Addr instPC, bool taken, void *bp_history) { if (predictor == Local) { - localBP->update(inst_PC, taken, bp_history); + localBP->update(instPC, taken, bp_history); } else if (predictor == Tournament) { - tournamentBP->update(inst_PC, taken, bp_history); + tournamentBP->update(instPC, taken, bp_history); } else { panic("Predictor type is unexpected value!"); } @@ -436,9 +433,9 @@ BPredUnit<Impl>::dump() while (pred_hist_it != predHist[i].end()) { cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, " "bpHistory:%#x\n", - (*pred_hist_it).seqNum, (*pred_hist_it).PC, - (*pred_hist_it).tid, (*pred_hist_it).predTaken, - (*pred_hist_it).bpHistory); + pred_hist_it->seqNum, pred_hist_it->pc, + pred_hist_it->tid, pred_hist_it->predTaken, + pred_hist_it->bpHistory); pred_hist_it++; } diff --git a/src/cpu/o3/comm.hh b/src/cpu/o3/comm.hh index 23b836f73..c9fb3319b 100644 --- a/src/cpu/o3/comm.hh +++ b/src/cpu/o3/comm.hh @@ -33,6 +33,7 @@ #include <vector> +#include "arch/types.hh" #include "base/types.hh" #include "cpu/inst_seq.hh" #include "sim/faults.hh" @@ -88,9 +89,7 @@ struct DefaultIEWDefaultCommit { bool branchMispredict[Impl::MaxThreads]; bool branchTaken[Impl::MaxThreads]; Addr mispredPC[Impl::MaxThreads]; - Addr nextPC[Impl::MaxThreads]; - Addr nextNPC[Impl::MaxThreads]; - Addr nextMicroPC[Impl::MaxThreads]; + TheISA::PCState pc[Impl::MaxThreads]; InstSeqNum squashedSeqNum[Impl::MaxThreads]; bool includeSquashInst[Impl::MaxThreads]; @@ -120,9 +119,7 @@ struct TimeBufStruct { bool branchMispredict; bool branchTaken; Addr mispredPC; - Addr nextPC; - Addr nextNPC; - Addr nextMicroPC; + TheISA::PCState nextPC; unsigned branchCount; }; @@ -161,9 +158,7 @@ struct TimeBufStruct { bool branchMispredict; bool branchTaken; Addr mispredPC; - Addr nextPC; - Addr nextNPC; - Addr nextMicroPC; + TheISA::PCState pc; // Represents the instruction that has either been retired or // squashed. Similar to having a single bus that broadcasts the diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index d93b85984..326f3a1d3 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -277,40 +277,21 @@ class DefaultCommit ThreadID oldestReady(); public: - /** Returns the PC of the head instruction of the ROB. - * @todo: Probably remove this function as it returns only thread 0. - */ - Addr readPC() { return PC[0]; } - - /** Returns the PC of a specific thread. */ - Addr readPC(ThreadID tid) { return PC[tid]; } + /** Reads the PC of a specific thread. */ + TheISA::PCState pcState(ThreadID tid) { return pc[tid]; } /** Sets the PC of a specific thread. */ - void setPC(Addr val, ThreadID tid) { PC[tid] = val; } - - /** Reads the micro PC of a specific thread. */ - Addr readMicroPC(ThreadID tid) { return microPC[tid]; } - - /** Sets the micro PC of a specific thread */ - void setMicroPC(Addr val, ThreadID tid) { microPC[tid] = val; } - - /** Reads the next PC of a specific thread. */ - Addr readNextPC(ThreadID tid) { return nextPC[tid]; } - - /** Sets the next PC of a specific thread. */ - void setNextPC(Addr val, ThreadID tid) { nextPC[tid] = val; } + void pcState(const TheISA::PCState &val, ThreadID tid) + { pc[tid] = val; } - /** Reads the next NPC of a specific thread. */ - Addr readNextNPC(ThreadID tid) { return nextNPC[tid]; } + /** Returns the PC of a specific thread. */ + Addr instAddr(ThreadID tid) { return pc[tid].instAddr(); } - /** Sets the next NPC of a specific thread. */ - void setNextNPC(Addr val, ThreadID tid) { nextNPC[tid] = val; } + /** Returns the next PC of a specific thread. */ + Addr nextInstAddr(ThreadID tid) { return pc[tid].nextInstAddr(); } /** Reads the micro PC of a specific thread. */ - Addr readNextMicroPC(ThreadID tid) { return nextMicroPC[tid]; } - - /** Sets the micro PC of a specific thread */ - void setNextMicroPC(Addr val, ThreadID tid) { nextMicroPC[tid] = val; } + Addr microPC(ThreadID tid) { return pc[tid].microPC(); } private: /** Time buffer interface. */ @@ -410,24 +391,10 @@ class DefaultCommit /** The interrupt fault. */ Fault interrupt; - /** The commit PC of each thread. Refers to the instruction that - * is currently being processed/committed. - */ - Addr PC[Impl::MaxThreads]; - - /** The commit micro PC of each thread. Refers to the instruction that + /** The commit PC state of each thread. Refers to the instruction that * is currently being processed/committed. */ - Addr microPC[Impl::MaxThreads]; - - /** The next PC of each thread. */ - Addr nextPC[Impl::MaxThreads]; - - /** The next NPC of each thread. */ - Addr nextNPC[Impl::MaxThreads]; - - /** The next micro PC of each thread. */ - Addr nextMicroPC[Impl::MaxThreads]; + TheISA::PCState pc[Impl::MaxThreads]; /** The sequence number of the youngest valid instruction in the ROB. */ InstSeqNum youngestSeqNum[Impl::MaxThreads]; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 98c7b49c8..8d3edfb19 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -128,11 +128,7 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params) committedStores[tid] = false; trapSquash[tid] = false; tcSquash[tid] = false; - microPC[tid] = 0; - nextMicroPC[tid] = 0; - PC[tid] = 0; - nextPC[tid] = 0; - nextNPC[tid] = 0; + pc[tid].set(0); } #if FULL_SYSTEM interrupt = NoFault; @@ -513,9 +509,7 @@ DefaultCommit<Impl>::squashAll(ThreadID tid) toIEW->commitInfo[tid].branchMispredict = false; - toIEW->commitInfo[tid].nextPC = PC[tid]; - toIEW->commitInfo[tid].nextNPC = nextPC[tid]; - toIEW->commitInfo[tid].nextMicroPC = nextMicroPC[tid]; + toIEW->commitInfo[tid].pc = pc[tid]; } template <class Impl> @@ -524,7 +518,7 @@ DefaultCommit<Impl>::squashFromTrap(ThreadID tid) { squashAll(tid); - DPRINTF(Commit, "Squashing from trap, restarting at PC %#x\n", PC[tid]); + DPRINTF(Commit, "Squashing from trap, restarting at PC %s\n", pc[tid]); thread[tid]->trapPending = false; thread[tid]->inSyscall = false; @@ -542,7 +536,7 @@ DefaultCommit<Impl>::squashFromTC(ThreadID tid) { squashAll(tid); - DPRINTF(Commit, "Squashing from TC, restarting at PC %#x\n", PC[tid]); + DPRINTF(Commit, "Squashing from TC, restarting at PC %s\n", pc[tid]); thread[tid]->inSyscall = false; assert(!thread[tid]->trapPending); @@ -611,16 +605,16 @@ DefaultCommit<Impl>::tick() DynInstPtr inst = rob->readHeadInst(tid); - DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %#x is head of" + DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of" " ROB and ready to commit\n", - tid, inst->seqNum, inst->readPC()); + tid, inst->seqNum, inst->pcState()); } else if (!rob->isEmpty(tid)) { DynInstPtr inst = rob->readHeadInst(tid); DPRINTF(Commit,"[tid:%i]: Can't commit, Instruction [sn:%lli] PC " - "%#x is head of ROB and not ready\n", - tid, inst->seqNum, inst->readPC()); + "%s is head of ROB and not ready\n", + tid, inst->seqNum, inst->pcState()); } DPRINTF(Commit, "[tid:%i]: ROB has %d insts & %d free entries.\n", @@ -738,7 +732,7 @@ DefaultCommit<Impl>::commit() DPRINTF(Commit, "[tid:%i]: Redirecting to PC %#x\n", tid, - fromIEW->nextPC[tid]); + fromIEW->pc[tid].nextInstAddr()); commitStatus[tid] = ROBSquashing; @@ -771,9 +765,7 @@ DefaultCommit<Impl>::commit() toIEW->commitInfo[tid].branchTaken = fromIEW->branchTaken[tid]; - toIEW->commitInfo[tid].nextPC = fromIEW->nextPC[tid]; - toIEW->commitInfo[tid].nextNPC = fromIEW->nextNPC[tid]; - toIEW->commitInfo[tid].nextMicroPC = fromIEW->nextMicroPC[tid]; + toIEW->commitInfo[tid].pc = fromIEW->pc[tid]; toIEW->commitInfo[tid].mispredPC = fromIEW->mispredPC[tid]; @@ -880,10 +872,7 @@ DefaultCommit<Impl>::commitInsts() // Record that the number of ROB entries has changed. changedROBNumEntries[tid] = true; } else { - PC[tid] = head_inst->readPC(); - nextPC[tid] = head_inst->readNextPC(); - nextNPC[tid] = head_inst->readNextNPC(); - nextMicroPC[tid] = head_inst->readNextMicroPC(); + pc[tid] = head_inst->pcState(); // Increment the total number of non-speculative instructions // executed. @@ -911,11 +900,7 @@ DefaultCommit<Impl>::commitInsts() cpu->instDone(tid); } - PC[tid] = nextPC[tid]; - nextPC[tid] = nextNPC[tid]; - nextNPC[tid] = nextNPC[tid] + sizeof(TheISA::MachInst); - microPC[tid] = nextMicroPC[tid]; - nextMicroPC[tid] = microPC[tid] + 1; + TheISA::advancePC(pc[tid], head_inst->staticInst); int count = 0; Addr oldpc; @@ -923,19 +908,19 @@ DefaultCommit<Impl>::commitInsts() // currently updating state while handling PC events. assert(!thread[tid]->inSyscall && !thread[tid]->trapPending); do { - oldpc = PC[tid]; + oldpc = pc[tid].instAddr(); cpu->system->pcEventQueue.service(thread[tid]->getTC()); count++; - } while (oldpc != PC[tid]); + } while (oldpc != pc[tid].instAddr()); if (count > 1) { DPRINTF(Commit, "PC skip function event, stopping commit\n"); break; } } else { - DPRINTF(Commit, "Unable to commit head instruction PC:%#x " + DPRINTF(Commit, "Unable to commit head instruction PC:%s " "[tid:%i] [sn:%i].\n", - head_inst->readPC(), tid ,head_inst->seqNum); + head_inst->pcState(), tid ,head_inst->seqNum); break; } } @@ -970,8 +955,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) head_inst->isWriteBarrier()) { DPRINTF(Commit, "Encountered a barrier or non-speculative " - "instruction [sn:%lli] at the head of the ROB, PC %#x.\n", - head_inst->seqNum, head_inst->readPC()); + "instruction [sn:%lli] at the head of the ROB, PC %s.\n", + head_inst->seqNum, head_inst->pcState()); if (inst_num > 0 || iewStage->hasStoresToWB(tid)) { DPRINTF(Commit, "Waiting for all stores to writeback.\n"); @@ -994,8 +979,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) } assert(head_inst->uncacheable()); - DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n", - head_inst->seqNum, head_inst->readPC()); + DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %s.\n", + head_inst->seqNum, head_inst->pcState()); // Send back the non-speculative instruction's sequence // number. Tell the lsq to re-execute the load. @@ -1034,8 +1019,8 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) #endif if (inst_fault != NoFault) { - DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n", - head_inst->seqNum, head_inst->readPC()); + DPRINTF(Commit, "Inst [sn:%lli] PC %s has a fault\n", + head_inst->seqNum, head_inst->pcState()); if (iewStage->hasStoresToWB(tid) || inst_num > 0) { DPRINTF(Commit, "Stores outstanding, fault must wait.\n"); @@ -1081,7 +1066,6 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) // Generate trap squash event. generateTrapEvent(tid); -// warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC()); return false; } @@ -1089,9 +1073,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) #if FULL_SYSTEM if (thread[tid]->profile) { -// bool usermode = TheISA::inUserMode(thread[tid]->getTC()); -// thread[tid]->profilePC = usermode ? 1 : head_inst->readPC(); - thread[tid]->profilePC = head_inst->readPC(); + thread[tid]->profilePC = head_inst->instAddr(); ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(), head_inst->staticInst); @@ -1101,7 +1083,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num) if (CPA::available()) { if (head_inst->isControl()) { ThreadContext *tc = thread[tid]->getTC(); - CPA::cpa()->swAutoBegin(tc, head_inst->readNextPC()); + CPA::cpa()->swAutoBegin(tc, head_inst->nextInstAddr()); } } #endif @@ -1154,8 +1136,8 @@ DefaultCommit<Impl>::getInsts() commitStatus[tid] != TrapPending) { changedROBNumEntries[tid] = true; - DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n", - inst->readPC(), inst->seqNum, tid); + DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ROB.\n", + inst->pcState(), inst->seqNum, tid); rob->insertInst(inst); @@ -1163,9 +1145,9 @@ DefaultCommit<Impl>::getInsts() youngestSeqNum[tid] = inst->seqNum; } else { - DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " + DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " "squashed, skipping.\n", - inst->readPC(), inst->seqNum, tid); + inst->pcState(), inst->seqNum, tid); } } } @@ -1181,14 +1163,14 @@ DefaultCommit<Impl>::skidInsert() DynInstPtr inst = fromRename->insts[inst_num]; if (!inst->isSquashed()) { - DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ", - "skidBuffer.\n", inst->readPC(), inst->seqNum, + DPRINTF(Commit, "Inserting PC %s [sn:%i] [tid:%i] into ", + "skidBuffer.\n", inst->pcState(), inst->seqNum, inst->threadNumber); skidBuffer.push(inst); } else { - DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was " + DPRINTF(Commit, "Instruction PC %s [sn:%i] [tid:%i] was " "squashed, skipping.\n", - inst->readPC(), inst->seqNum, inst->threadNumber); + inst->pcState(), inst->seqNum, inst->threadNumber); } } } @@ -1204,10 +1186,10 @@ DefaultCommit<Impl>::markCompletedInsts() ++inst_num) { if (!fromIEW->insts[inst_num]->isSquashed()) { - DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready " + DPRINTF(Commit, "[tid:%i]: Marking PC %s, [sn:%lli] ready " "within ROB.\n", fromIEW->insts[inst_num]->threadNumber, - fromIEW->insts[inst_num]->readPC(), + fromIEW->insts[inst_num]->pcState(), fromIEW->insts[inst_num]->seqNum); // Mark the instruction as ready to commit. diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 8e9f3ef5d..21c5cc706 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -732,9 +732,7 @@ FullO3CPU<Impl>::insertThread(ThreadID tid) //this->copyFromTC(tid); //Set PC/NPC/NNPC - setPC(src_tc->readPC(), tid); - setNextPC(src_tc->readNextPC(), tid); - setNextNPC(src_tc->readNextNPC(), tid); + pcState(src_tc->pcState(), tid); src_tc->setStatus(ThreadContext::Active); @@ -778,7 +776,7 @@ FullO3CPU<Impl>::removeThread(ThreadID tid) // Squash Throughout Pipeline InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum; - fetch.squash(0, sizeof(TheISA::MachInst), 0, squash_seq_num, tid); + fetch.squash(0, squash_seq_num, tid); decode.squash(tid); rename.squash(squash_seq_num, tid); iew.squash(tid); @@ -1306,73 +1304,38 @@ FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid) } template <class Impl> -uint64_t -FullO3CPU<Impl>::readPC(ThreadID tid) +TheISA::PCState +FullO3CPU<Impl>::pcState(ThreadID tid) { - return commit.readPC(tid); + return commit.pcState(tid); } template <class Impl> void -FullO3CPU<Impl>::setPC(Addr new_PC, ThreadID tid) -{ - commit.setPC(new_PC, tid); -} - -template <class Impl> -uint64_t -FullO3CPU<Impl>::readMicroPC(ThreadID tid) +FullO3CPU<Impl>::pcState(const TheISA::PCState &val, ThreadID tid) { - return commit.readMicroPC(tid); + commit.pcState(val, tid); } template <class Impl> -void -FullO3CPU<Impl>::setMicroPC(Addr new_PC, ThreadID tid) +Addr +FullO3CPU<Impl>::instAddr(ThreadID tid) { - commit.setMicroPC(new_PC, tid); + return commit.instAddr(tid); } template <class Impl> -uint64_t -FullO3CPU<Impl>::readNextPC(ThreadID tid) +Addr +FullO3CPU<Impl>::nextInstAddr(ThreadID tid) { - return commit.readNextPC(tid); + return commit.nextInstAddr(tid); } template <class Impl> -void -FullO3CPU<Impl>::setNextPC(uint64_t val, ThreadID tid) -{ - commit.setNextPC(val, tid); -} - -template <class Impl> -uint64_t -FullO3CPU<Impl>::readNextNPC(ThreadID tid) -{ - return commit.readNextNPC(tid); -} - -template <class Impl> -void -FullO3CPU<Impl>::setNextNPC(uint64_t val, ThreadID tid) -{ - commit.setNextNPC(val, tid); -} - -template <class Impl> -uint64_t -FullO3CPU<Impl>::readNextMicroPC(ThreadID tid) -{ - return commit.readNextMicroPC(tid); -} - -template <class Impl> -void -FullO3CPU<Impl>::setNextMicroPC(Addr new_PC, ThreadID tid) +MicroPC +FullO3CPU<Impl>::microPC(ThreadID tid) { - commit.setNextMicroPC(new_PC, tid); + return commit.microPC(tid); } template <class Impl> @@ -1419,9 +1382,9 @@ template <class Impl> void FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst) { - DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x " + DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s " "[sn:%lli]\n", - inst->threadNumber, inst->readPC(), inst->seqNum); + inst->threadNumber, inst->pcState(), inst->seqNum); removeInstsThisCycle = true; @@ -1509,10 +1472,10 @@ FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, ThreadID tid) { if ((*instIt)->threadNumber == tid) { DPRINTF(O3CPU, "Squashing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*instIt)->threadNumber, (*instIt)->seqNum, - (*instIt)->readPC()); + (*instIt)->pcState()); // Mark it as squashed. (*instIt)->setSquashed(); @@ -1530,10 +1493,10 @@ FullO3CPU<Impl>::cleanUpRemovedInsts() { while (!removeList.empty()) { DPRINTF(O3CPU, "Removing instruction, " - "[tid:%i] [sn:%lli] PC %#x\n", + "[tid:%i] [sn:%lli] PC %s\n", (*removeList.front())->threadNumber, (*removeList.front())->seqNum, - (*removeList.front())->readPC()); + (*removeList.front())->pcState()); instList.erase(removeList.front()); @@ -1563,7 +1526,7 @@ FullO3CPU<Impl>::dumpInsts() while (inst_list_it != instList.end()) { cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" "Squashed:%i\n\n", - num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber, + num, (*inst_list_it)->instAddr(), (*inst_list_it)->threadNumber, (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed()); inst_list_it++; diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 57c07a9ec..2669016ff 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -444,35 +444,20 @@ class FullO3CPU : public BaseO3CPU void setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid); - /** Reads the commit PC of a specific thread. */ - Addr readPC(ThreadID tid); + /** Sets the commit PC state of a specific thread. */ + void pcState(const TheISA::PCState &newPCState, ThreadID tid); - /** Sets the commit PC of a specific thread. */ - void setPC(Addr new_PC, ThreadID tid); + /** Reads the commit PC state of a specific thread. */ + TheISA::PCState pcState(ThreadID tid); - /** Reads the commit micro PC of a specific thread. */ - Addr readMicroPC(ThreadID tid); + /** Reads the commit PC of a specific thread. */ + Addr instAddr(ThreadID tid); - /** Sets the commmit micro PC of a specific thread. */ - void setMicroPC(Addr new_microPC, ThreadID tid); + /** Reads the commit micro PC of a specific thread. */ + MicroPC microPC(ThreadID tid); /** Reads the next PC of a specific thread. */ - Addr readNextPC(ThreadID tid); - - /** Sets the next PC of a specific thread. */ - void setNextPC(Addr val, ThreadID tid); - - /** Reads the next NPC of a specific thread. */ - Addr readNextNPC(ThreadID tid); - - /** Sets the next NPC of a specific thread. */ - void setNextNPC(Addr val, ThreadID tid); - - /** Reads the commit next micro PC of a specific thread. */ - Addr readNextMicroPC(ThreadID tid); - - /** Sets the commit next micro PC of a specific thread. */ - void setNextMicroPC(Addr val, ThreadID tid); + Addr nextInstAddr(ThreadID tid); /** Initiates a squash of all in-flight instructions for a given * thread. The source of the squash is an external update of diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 1b76de132..5063e0f07 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -264,29 +264,16 @@ template<class Impl> void DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid) { - DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch prediction " - "detected at decode.\n", tid, inst->seqNum); + DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch " + "prediction detected at decode.\n", tid, inst->seqNum); // Send back mispredict information. toFetch->decodeInfo[tid].branchMispredict = true; toFetch->decodeInfo[tid].predIncorrect = true; toFetch->decodeInfo[tid].squash = true; toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; - toFetch->decodeInfo[tid].nextMicroPC = inst->readMicroPC(); - -#if ISA_HAS_DELAY_SLOT - toFetch->decodeInfo[tid].nextPC = inst->readPC() + sizeof(TheISA::MachInst); - toFetch->decodeInfo[tid].nextNPC = inst->branchTarget(); - toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() != - (inst->readNextPC() + sizeof(TheISA::MachInst)); -#else toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); - toFetch->decodeInfo[tid].nextNPC = - inst->branchTarget() + sizeof(TheISA::MachInst); - toFetch->decodeInfo[tid].branchTaken = - inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); -#endif - + toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching(); InstSeqNum squash_seq_num = inst->seqNum; @@ -382,8 +369,8 @@ DefaultDecode<Impl>::skidInsert(ThreadID tid) assert(tid == inst->threadNumber); - DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n", - inst->seqNum, inst->readPC(), inst->threadNumber); + DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n", + inst->seqNum, inst->pcState(), inst->threadNumber); skidBuffer[tid].push(inst); } @@ -681,13 +668,12 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid) insts_to_decode.pop(); DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " - "PC %#x\n", - tid, inst->seqNum, inst->readPC()); + "PC %s\n", tid, inst->seqNum, inst->pcState()); if (inst->isSquashed()) { - DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is " + DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is " "squashed, skipping.\n", - tid, inst->seqNum, inst->readPC()); + tid, inst->seqNum, inst->pcState()); ++decodeSquashedInsts; @@ -717,9 +703,6 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid) // Ensure that if it was predicted as a branch, it really is a // branch. if (inst->readPredTaken() && !inst->isControl()) { - DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n", - inst->readPredPC(), inst->readNextPC() + 4); - panic("Instruction predicted as a branch!"); ++decodeControlMispred; @@ -735,26 +718,18 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid) if (inst->isDirectCtrl() && inst->isUncondCtrl()) { ++decodeBranchResolved; - if (inst->branchTarget() != inst->readPredPC()) { + if (!(inst->branchTarget() == inst->readPredTarg())) { ++decodeBranchMispred; // Might want to set some sort of boolean and just do // a check at the end squash(inst, inst->threadNumber); - Addr target = inst->branchTarget(); + TheISA::PCState target = inst->branchTarget(); -#if ISA_HAS_DELAY_SLOT - DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x PredNextPC: %#x\n", - inst->seqNum, inst->readPC() + sizeof(TheISA::MachInst), target); - - //The micro pc after an instruction level branch should be 0 - inst->setPredTarg(inst->readPC() + sizeof(TheISA::MachInst), target, 0); -#else - DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %#x PredNextPC: %#x\n", - inst->seqNum, target, target + sizeof(TheISA::MachInst)); + DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n", + inst->seqNum, target); //The micro pc after an instruction level branch should be 0 - inst->setPredTarg(target, target + sizeof(TheISA::MachInst), 0); -#endif + inst->setPredTarg(target); break; } } diff --git a/src/cpu/o3/dep_graph.hh b/src/cpu/o3/dep_graph.hh index c19fd0abf..804b3f9cd 100644 --- a/src/cpu/o3/dep_graph.hh +++ b/src/cpu/o3/dep_graph.hh @@ -251,8 +251,8 @@ DependencyGraph<DynInstPtr>::dump() curr = &dependGraph[i]; if (curr->inst) { - cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ", - i, curr->inst->readPC(), curr->inst->seqNum); + cprintf("dependGraph[%i]: producer: %s [sn:%lli] consumer: ", + i, curr->inst->pcState(), curr->inst->seqNum); } else { cprintf("dependGraph[%i]: No producer. consumer: ", i); } @@ -260,8 +260,8 @@ DependencyGraph<DynInstPtr>::dump() while (curr->next != NULL) { curr = curr->next; - cprintf("%#x [sn:%lli] ", - curr->inst->readPC(), curr->inst->seqNum); + cprintf("%s [sn:%lli] ", + curr->inst->pcState(), curr->inst->seqNum); } cprintf("\n"); diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index e1279f82b..6bd1f9fad 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -74,14 +74,14 @@ class BaseO3DynInst : public BaseDynInst<Impl> public: /** BaseDynInst constructor given a binary instruction. */ - BaseO3DynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); + BaseO3DynInst(StaticInstPtr staticInst, + TheISA::PCState pc, TheISA::PCState predPC, + InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a binary instruction. */ - BaseO3DynInst(ExtMachInst inst, Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, Addr Pred_MicroPC, - InstSeqNum seq_num, O3CPU *cpu); + BaseO3DynInst(ExtMachInst inst, + TheISA::PCState pc, TheISA::PCState predPC, + InstSeqNum seq_num, O3CPU *cpu); /** BaseDynInst constructor given a static inst pointer. */ BaseO3DynInst(StaticInstPtr &_staticInst); diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index 3e015d962..6f7c23b2f 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -33,24 +33,18 @@ template <class Impl> BaseO3DynInst<Impl>::BaseO3DynInst(StaticInstPtr staticInst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, - Addr Pred_MicroPC, + TheISA::PCState pc, TheISA::PCState predPC, InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst<Impl>(staticInst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) + : BaseDynInst<Impl>(staticInst, pc, predPC, seq_num, cpu) { initVars(); } template <class Impl> BaseO3DynInst<Impl>::BaseO3DynInst(ExtMachInst inst, - Addr PC, Addr NPC, Addr microPC, - Addr Pred_PC, Addr Pred_NPC, - Addr Pred_MicroPC, + TheISA::PCState pc, TheISA::PCState predPC, InstSeqNum seq_num, O3CPU *cpu) - : BaseDynInst<Impl>(inst, PC, NPC, microPC, - Pred_PC, Pred_NPC, Pred_MicroPC, seq_num, cpu) + : BaseDynInst<Impl>(inst, pc, predPC, seq_num, cpu) { initVars(); } @@ -131,15 +125,17 @@ BaseO3DynInst<Impl>::hwrei() { #if THE_ISA == ALPHA_ISA // Can only do a hwrei when in pal mode. - if (!(this->readPC() & 0x3)) + if (!(this->instAddr() & 0x3)) return new AlphaISA::UnimplementedOpcodeFault; // Set the next PC based on the value of the EXC_ADDR IPR. - this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, - this->threadNumber)); + AlphaISA::PCState pc = this->pcState(); + pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, + this->threadNumber)); + this->pcState(pc); if (CPA::available()) { ThreadContext *tc = this->cpu->tcBase(this->threadNumber); - CPA::cpa()->swAutoBegin(tc, this->readNextPC()); + CPA::cpa()->swAutoBegin(tc, this->nextInstAddr()); } // Tell CPU to clear any state it needs to if a hwrei is taken. @@ -175,11 +171,11 @@ BaseO3DynInst<Impl>::syscall(int64_t callnum) // HACK: check CPU's nextPC before and after syscall. If it // changes, update this instruction's nextPC because the syscall // must have changed the nextPC. - Addr cpu_next_pc = this->cpu->readNextPC(this->threadNumber); + TheISA::PCState curPC = this->cpu->pcState(this->threadNumber); this->cpu->syscall(callnum, this->threadNumber); - Addr new_next_pc = this->cpu->readNextPC(this->threadNumber); - if (cpu_next_pc != new_next_pc) { - this->setNextPC(new_next_pc); + TheISA::PCState newPC = this->cpu->pcState(this->threadNumber); + if (!(curPC == newPC)) { + this->pcState(newPC); } } #endif diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index d881c291f..22e9e51b4 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -229,7 +229,7 @@ class DefaultFetch * @param next_NPC Used for ISAs which use delay slots. * @return Whether or not a branch was predicted as taken. */ - bool lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, Addr &next_NPC, Addr &next_MicroPC); + bool lookupAndUpdateNextPC(DynInstPtr &inst, TheISA::PCState &pc); /** * Fetches the cache line that contains fetch_PC. Returns any @@ -244,14 +244,12 @@ class DefaultFetch bool fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid); /** Squashes a specific thread and resets the PC. */ - inline void doSquash(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, ThreadID tid); + inline void doSquash(const TheISA::PCState &newPC, 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 Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, + void squashFromDecode(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid); /** Checks if a thread is stalled. */ @@ -266,8 +264,7 @@ class DefaultFetch * remove any instructions that are not in the ROB. The source of this * squash should be the commit stage. */ - void squash(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, + void squash(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid); /** Ticks the fetch stage, processing all inputs signals and fetching @@ -348,14 +345,7 @@ class DefaultFetch /** Predecoder. */ TheISA::Predecoder predecoder; - /** Per-thread fetch PC. */ - Addr PC[Impl::MaxThreads]; - - /** Per-thread fetch micro PC. */ - Addr microPC[Impl::MaxThreads]; - - /** Per-thread next PC. */ - Addr nextPC[Impl::MaxThreads]; + TheISA::PCState pc[Impl::MaxThreads]; /** Memory request used to access cache. */ RequestPtr memReq[Impl::MaxThreads]; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 3f8f84cab..bbd9ce4a2 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -316,9 +316,7 @@ DefaultFetch<Impl>::initStage() { // Setup PC and nextPC with initial state. for (ThreadID tid = 0; tid < numThreads; tid++) { - PC[tid] = cpu->readPC(tid); - nextPC[tid] = cpu->readNextPC(tid); - microPC[tid] = cpu->readMicroPC(tid); + pc[tid] = cpu->pcState(tid); } for (ThreadID tid = 0; tid < numThreads; tid++) { @@ -445,9 +443,7 @@ DefaultFetch<Impl>::takeOverFrom() stalls[i].rename = 0; stalls[i].iew = 0; stalls[i].commit = 0; - PC[i] = cpu->readPC(i); - nextPC[i] = cpu->readNextPC(i); - microPC[i] = cpu->readMicroPC(i); + pc[i] = cpu->pcState(i); fetchStatus[i] = Running; } numInst = 0; @@ -496,8 +492,8 @@ DefaultFetch<Impl>::switchToInactive() template <class Impl> bool -DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, - Addr &next_NPC, Addr &next_MicroPC) +DefaultFetch<Impl>::lookupAndUpdateNextPC( + DynInstPtr &inst, TheISA::PCState &nextPC) { // Do branch prediction check here. // A bit of a misnomer...next_PC is actually the current PC until @@ -505,51 +501,26 @@ DefaultFetch<Impl>::lookupAndUpdateNextPC(DynInstPtr &inst, Addr &next_PC, bool predict_taken; if (!inst->isControl()) { - if (inst->isMicroop() && !inst->isLastMicroop()) { - next_MicroPC++; - } else { - next_PC = next_NPC; - next_NPC = next_NPC + instSize; - next_MicroPC = 0; - } - inst->setPredTarg(next_PC, next_NPC, next_MicroPC); + TheISA::advancePC(nextPC, inst->staticInst); + inst->setPredTarg(nextPC); inst->setPredTaken(false); return false; } - //Assume for now that all control flow is to a different macroop which - //would reset the micro pc to 0. - next_MicroPC = 0; - ThreadID tid = inst->threadNumber; - Addr pred_PC = next_PC; - predict_taken = branchPred.predict(inst, pred_PC, tid); + predict_taken = branchPred.predict(inst, nextPC, tid); if (predict_taken) { - DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %#x.\n", - tid, inst->seqNum, pred_PC); + DPRINTF(Fetch, "[tid:%i]: [sn:%i]: Branch predicted to be taken to %s.\n", + tid, inst->seqNum, nextPC); } else { DPRINTF(Fetch, "[tid:%i]: [sn:%i]:Branch predicted to be not taken.\n", tid, inst->seqNum); } -#if ISA_HAS_DELAY_SLOT - next_PC = next_NPC; - if (predict_taken) - next_NPC = pred_PC; - else - next_NPC += instSize; -#else - if (predict_taken) - next_PC = pred_PC; - else - next_PC += instSize; - next_NPC = next_PC + instSize; -#endif - - DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %#x and then %#x.\n", - tid, inst->seqNum, next_PC, next_NPC); - inst->setPredTarg(next_PC, next_NPC, next_MicroPC); + DPRINTF(Fetch, "[tid:%i]: [sn:%i] Branch predicted to go to %s.\n", + tid, inst->seqNum, nextPC); + inst->setPredTarg(nextPC); inst->setPredTaken(predict_taken); ++fetchedBranches; @@ -668,15 +639,12 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, ThreadID tid template <class Impl> inline void -DefaultFetch<Impl>::doSquash(const Addr &new_PC, - const Addr &new_NPC, const Addr &new_microPC, ThreadID tid) +DefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, ThreadID tid) { - DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %#x, NPC to: %#x.\n", - tid, new_PC, new_NPC); + DPRINTF(Fetch, "[tid:%i]: Squashing, setting PC to: %s.\n", + tid, newPC); - PC[tid] = new_PC; - nextPC[tid] = new_NPC; - microPC[tid] = new_microPC; + pc[tid] = newPC; // Clear the icache miss if it's outstanding. if (fetchStatus[tid] == IcacheWaitResponse) { @@ -703,13 +671,12 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, template<class Impl> void -DefaultFetch<Impl>::squashFromDecode(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, +DefaultFetch<Impl>::squashFromDecode(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid) { - DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n",tid); + DPRINTF(Fetch, "[tid:%i]: Squashing from decode.\n", tid); - doSquash(new_PC, new_NPC, new_MicroPC, tid); + doSquash(newPC, tid); // Tell the CPU to remove any instructions that are in flight between // fetch and decode. @@ -784,13 +751,12 @@ DefaultFetch<Impl>::updateFetchStatus() template <class Impl> void -DefaultFetch<Impl>::squash(const Addr &new_PC, const Addr &new_NPC, - const Addr &new_MicroPC, +DefaultFetch<Impl>::squash(const TheISA::PCState &newPC, const InstSeqNum &seq_num, ThreadID tid) { - DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n",tid); + DPRINTF(Fetch, "[tid:%u]: Squash from commit.\n", tid); - doSquash(new_PC, new_NPC, new_MicroPC, tid); + doSquash(newPC, tid); // Tell the CPU to remove any instructions that are not in the ROB. cpu->removeInstsNotInROB(tid); @@ -903,16 +869,14 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) DPRINTF(Fetch, "[tid:%u]: Squashing instructions due to squash " "from commit.\n",tid); // In any case, squash. - squash(fromCommit->commitInfo[tid].nextPC, - fromCommit->commitInfo[tid].nextNPC, - fromCommit->commitInfo[tid].nextMicroPC, + squash(fromCommit->commitInfo[tid].pc, fromCommit->commitInfo[tid].doneSeqNum, tid); // Also check if there's a mispredict that happened. if (fromCommit->commitInfo[tid].branchMispredict) { branchPred.squash(fromCommit->commitInfo[tid].doneSeqNum, - fromCommit->commitInfo[tid].nextPC, + fromCommit->commitInfo[tid].pc, fromCommit->commitInfo[tid].branchTaken, tid); } else { @@ -955,13 +919,10 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(ThreadID tid) if (fetchStatus[tid] != Squashing) { - DPRINTF(Fetch, "Squashing from decode with PC = %#x, NPC = %#x\n", - fromDecode->decodeInfo[tid].nextPC, - fromDecode->decodeInfo[tid].nextNPC); + TheISA::PCState nextPC = fromDecode->decodeInfo[tid].nextPC; + DPRINTF(Fetch, "Squashing from decode with PC = %s\n", nextPC); // Squash unless we're already squashing squashFromDecode(fromDecode->decodeInfo[tid].nextPC, - fromDecode->decodeInfo[tid].nextNPC, - fromDecode->decodeInfo[tid].nextMicroPC, fromDecode->decodeInfo[tid].doneSeqNum, tid); @@ -1016,9 +977,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) DPRINTF(Fetch, "Attempting to fetch from [tid:%i]\n", tid); // The current PC. - Addr fetch_PC = PC[tid]; - Addr fetch_NPC = nextPC[tid]; - Addr fetch_MicroPC = microPC[tid]; + TheISA::PCState fetchPC = pc[tid]; // Fault code for memory access. Fault fault = NoFault; @@ -1034,10 +993,9 @@ DefaultFetch<Impl>::fetch(bool &status_change) status_change = true; } else if (fetchStatus[tid] == Running) { DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read " - "instruction, starting at PC %08p.\n", - tid, fetch_PC); + "instruction, starting at PC %s.\n", tid, fetchPC); - bool fetch_success = fetchCacheLine(fetch_PC, fault, tid); + bool fetch_success = fetchCacheLine(fetchPC.instAddr(), fault, tid); if (!fetch_success) { if (cacheBlocked) { ++icacheStallCycles; @@ -1075,20 +1033,21 @@ DefaultFetch<Impl>::fetch(bool &status_change) return; } - Addr next_PC = fetch_PC; - Addr next_NPC = fetch_NPC; - Addr next_MicroPC = fetch_MicroPC; + TheISA::PCState nextPC = fetchPC; InstSeqNum inst_seq; MachInst inst; ExtMachInst ext_inst; - // @todo: Fix this hack. - unsigned offset = (fetch_PC & cacheBlkMask) & ~3; StaticInstPtr staticInst = NULL; StaticInstPtr macroop = NULL; if (fault == NoFault) { + //XXX Masking out pal mode bit. This will break x86. Alpha needs + //to pull the pal mode bit ouf ot the instruction address. + unsigned offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid]; + assert(offset < cacheBlkSize); + // If the read of the first instruction was successful, then grab the // instructions from the rest of the cache line and put them into the // queue heading to decode. @@ -1104,15 +1063,6 @@ DefaultFetch<Impl>::fetch(bool &status_change) numInst < fetchWidth && !predicted_branch) { - // If we're branching after this instruction, quite fetching - // from the same block then. - predicted_branch = - (fetch_PC + sizeof(TheISA::MachInst) != fetch_NPC); - if (predicted_branch) { - DPRINTF(Fetch, "Branch detected with PC = %#x, NPC = %#x\n", - fetch_PC, fetch_NPC); - } - // Make sure this is a valid index. assert(offset <= cacheBlkSize - instSize); @@ -1122,16 +1072,16 @@ DefaultFetch<Impl>::fetch(bool &status_change) (&cacheData[tid][offset])); predecoder.setTC(cpu->thread[tid]->getTC()); - predecoder.moreBytes(fetch_PC, fetch_PC, inst); + predecoder.moreBytes(fetchPC, fetchPC.instAddr(), inst); - ext_inst = predecoder.getExtMachInst(); - staticInst = StaticInstPtr(ext_inst, fetch_PC); + ext_inst = predecoder.getExtMachInst(fetchPC); + staticInst = StaticInstPtr(ext_inst, fetchPC.instAddr()); if (staticInst->isMacroop()) macroop = staticInst; } do { if (macroop) { - staticInst = macroop->fetchMicroop(fetch_MicroPC); + staticInst = macroop->fetchMicroop(fetchPC.microPC()); if (staticInst->isLastMicroop()) macroop = NULL; } @@ -1141,8 +1091,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Create a new DynInst from the instruction fetched. DynInstPtr instruction = new DynInst(staticInst, - fetch_PC, fetch_NPC, fetch_MicroPC, - next_PC, next_NPC, next_MicroPC, + fetchPC, nextPC, inst_seq, cpu); instruction->setTid(tid); @@ -1150,27 +1099,32 @@ DefaultFetch<Impl>::fetch(bool &status_change) instruction->setThreadState(cpu->thread[tid]); - DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x (%d) created " - "[sn:%lli]\n", tid, instruction->readPC(), - instruction->readMicroPC(), inst_seq); + DPRINTF(Fetch, "[tid:%i]: Instruction PC %s (%d) created " + "[sn:%lli]\n", tid, instruction->pcState(), + instruction->microPC(), inst_seq); //DPRINTF(Fetch, "[tid:%i]: MachInst is %#x\n", tid, ext_inst); - DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", - tid, instruction->staticInst->disassemble(fetch_PC)); + DPRINTF(Fetch, "[tid:%i]: Instruction is: %s\n", tid, + instruction->staticInst-> + disassemble(fetchPC.instAddr())); #if TRACING_ON instruction->traceData = cpu->getTracer()->getInstRecord(curTick, cpu->tcBase(tid), - instruction->staticInst, instruction->readPC(), - macroop, instruction->readMicroPC()); + instruction->staticInst, fetchPC, macroop); #else instruction->traceData = NULL; #endif - ///FIXME This needs to be more robust in dealing with delay slots + // If we're branching after this instruction, quite fetching + // from the same block then. + predicted_branch = fetchPC.branching(); predicted_branch |= - lookupAndUpdateNextPC(instruction, next_PC, next_NPC, next_MicroPC); + lookupAndUpdateNextPC(instruction, nextPC); + if (predicted_branch) { + DPRINTF(Fetch, "Branch detected with PC = %s\n", fetchPC); + } // Add instruction to the CPU's list of instructions. instruction->setInstListIt(cpu->addInst(instruction)); @@ -1185,9 +1139,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) ++fetchedInsts; // Move to the next instruction, unless we have a branch. - fetch_PC = next_PC; - fetch_NPC = next_NPC; - fetch_MicroPC = next_MicroPC; + fetchPC = nextPC; if (instruction->isQuiesce()) { DPRINTF(Fetch, "Quiesce instruction encountered, halting fetch!", @@ -1202,7 +1154,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) } while (staticInst->isMicroop() && !staticInst->isLastMicroop() && numInst < fetchWidth); - offset += instSize; + //XXX Masking out pal mode bit. + offset = (fetchPC.instAddr() & ~1) - cacheDataPC[tid]; } if (predicted_branch) { @@ -1224,10 +1177,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Now that fetching is completed, update the PC to signify what the next // cycle will be. if (fault == NoFault) { - PC[tid] = next_PC; - nextPC[tid] = next_NPC; - microPC[tid] = next_MicroPC; - DPRINTF(Fetch, "[tid:%i]: Setting PC to %08p.\n", tid, next_PC); + pc[tid] = nextPC; + DPRINTF(Fetch, "[tid:%i]: Setting PC to %s.\n", tid, nextPC); } else { // We shouldn't be in an icache miss and also have a fault (an ITB // miss) @@ -1245,11 +1196,10 @@ DefaultFetch<Impl>::fetch(bool &status_change) ext_inst = TheISA::NoopMachInst; // Create a new DynInst from the dummy nop. - DynInstPtr instruction = new DynInst(ext_inst, - fetch_PC, fetch_NPC, fetch_MicroPC, - next_PC, next_NPC, next_MicroPC, + DynInstPtr instruction = new DynInst(ext_inst, fetchPC, nextPC, inst_seq, cpu); - instruction->setPredTarg(next_NPC, next_NPC + instSize, 0); + TheISA::advancePC(nextPC, instruction->staticInst); + instruction->setPredTarg(nextPC); instruction->setTid(tid); instruction->setASID(tid); @@ -1272,8 +1222,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) fetchStatus[tid] = TrapPending; status_change = true; - DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %08p", - tid, fault->name(), PC[tid]); + DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s", + tid, fault->name(), pc[tid]); } } diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 2089913ef..608e70cde 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -449,27 +449,18 @@ template<class Impl> void DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) { - DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x " - "[sn:%i].\n", tid, inst->readPC(), inst->seqNum); + DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s " + "[sn:%i].\n", tid, inst->pcState(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->mispredPC[tid] = inst->readPC(); + toCommit->mispredPC[tid] = inst->instAddr(); toCommit->branchMispredict[tid] = true; -#if ISA_HAS_DELAY_SLOT - int instSize = sizeof(TheISA::MachInst); - toCommit->branchTaken[tid] = - !(inst->readNextPC() + instSize == inst->readNextNPC() && - (inst->readNextPC() == inst->readPC() + instSize || - inst->readNextPC() == inst->readPC() + 2 * instSize)); -#else - toCommit->branchTaken[tid] = inst->readNextPC() != - (inst->readPC() + sizeof(TheISA::MachInst)); -#endif - toCommit->nextPC[tid] = inst->readNextPC(); - toCommit->nextNPC[tid] = inst->readNextNPC(); - toCommit->nextMicroPC[tid] = inst->readNextMicroPC(); + toCommit->branchTaken[tid] = inst->pcState().branching(); + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + toCommit->pc[tid] = pc; toCommit->includeSquashInst[tid] = false; @@ -481,12 +472,13 @@ void DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) { DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, " - "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); + "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->nextPC[tid] = inst->readNextPC(); - toCommit->nextNPC[tid] = inst->readNextNPC(); + TheISA::PCState pc = inst->pcState(); + TheISA::advancePC(pc, inst->staticInst); + toCommit->pc[tid] = pc; toCommit->branchMispredict[tid] = false; toCommit->includeSquashInst[tid] = false; @@ -499,12 +491,11 @@ void DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid) { DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " - "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum); + "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); toCommit->squash[tid] = true; toCommit->squashedSeqNum[tid] = inst->seqNum; - toCommit->nextPC[tid] = inst->readPC(); - toCommit->nextNPC[tid] = inst->readNextPC(); + toCommit->pc[tid] = inst->pcState(); toCommit->branchMispredict[tid] = false; // Must include the broadcasted SN in the squash. @@ -628,9 +619,9 @@ DefaultIEW<Impl>::skidInsert(ThreadID tid) insts[tid].pop(); - DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into " + DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%s into " "dispatch skidBuffer %i\n",tid, inst->seqNum, - inst->readPC(),tid); + inst->pcState(),tid); skidBuffer[tid].push(inst); } @@ -986,9 +977,9 @@ DefaultIEW<Impl>::dispatchInsts(ThreadID tid) // Make sure there's a valid instruction there. assert(inst); - DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to " + DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to " "IQ.\n", - tid, inst->readPC(), inst->seqNum, inst->threadNumber); + tid, inst->pcState(), inst->seqNum, inst->threadNumber); // Be sure to mark these instructions as ready so that the // commit stage can go ahead and execute them, and mark @@ -1165,7 +1156,7 @@ DefaultIEW<Impl>::printAvailableInsts() if (inst%3==0) std::cout << "\n\t"; - std::cout << "PC: " << fromIssue->insts[inst]->readPC() + std::cout << "PC: " << fromIssue->insts[inst]->pcState() << " TN: " << fromIssue->insts[inst]->threadNumber << " SN: " << fromIssue->insts[inst]->seqNum << " | "; @@ -1205,8 +1196,8 @@ DefaultIEW<Impl>::executeInsts() DynInstPtr inst = instQueue.getInstToExecute(); - DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n", - inst->readPC(), inst->threadNumber,inst->seqNum); + DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n", + inst->pcState(), inst->threadNumber,inst->seqNum); // Check if the instruction is squashed; if so then skip it if (inst->isSquashed()) { @@ -1298,10 +1289,9 @@ DefaultIEW<Impl>::executeInsts() DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", - inst->readPredPC(), inst->readPredNPC()); - DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," - " NPC: %#x.\n", inst->readNextPC(), - inst->readNextNPC()); + inst->predInstAddr(), inst->predNextInstAddr()); + DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", + inst->pcState(), inst->nextInstAddr()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); @@ -1318,16 +1308,11 @@ DefaultIEW<Impl>::executeInsts() DynInstPtr violator; violator = ldstQueue.getMemDepViolator(tid); - DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %#x " - "[sn:%lli], inst PC: %#x [sn:%lli]. Addr is: %#x.\n", - violator->readPC(), violator->seqNum, - inst->readPC(), inst->seqNum, inst->physEffAddr); - // Ensure the violating instruction is older than - // current squash -/* if (fetchRedirect[tid] && - violator->seqNum >= toCommit->squashedSeqNum[tid] + 1) - continue; -*/ + DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s " + "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n", + violator->pcState(), violator->seqNum, + inst->pcState(), inst->seqNum, inst->physEffAddr); + fetchRedirect[tid] = true; // Tell the instruction queue that a violation has occured. @@ -1342,8 +1327,8 @@ DefaultIEW<Impl>::executeInsts() fetchRedirect[tid] = true; DPRINTF(IEW, "Load operation couldn't execute because the " - "memory system is blocked. PC: %#x [sn:%lli]\n", - inst->readPC(), inst->seqNum); + "memory system is blocked. PC: %s [sn:%lli]\n", + inst->pcState(), inst->seqNum); squashDueToMemBlocked(inst, tid); } @@ -1356,8 +1341,9 @@ DefaultIEW<Impl>::executeInsts() DynInstPtr violator = ldstQueue.getMemDepViolator(tid); DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " - "%#x, inst PC: %#x. Addr is: %#x.\n", - violator->readPC(), inst->readPC(), inst->physEffAddr); + "%s, inst PC: %s. Addr is: %#x.\n", + violator->pcState(), inst->pcState(), + inst->physEffAddr); DPRINTF(IEW, "Violation will not be handled because " "already squashing\n"); @@ -1366,8 +1352,8 @@ DefaultIEW<Impl>::executeInsts() if (ldstQueue.loadBlocked(tid) && !ldstQueue.isLoadBlockedHandled(tid)) { DPRINTF(IEW, "Load operation couldn't execute because the " - "memory system is blocked. PC: %#x [sn:%lli]\n", - inst->readPC(), inst->seqNum); + "memory system is blocked. PC: %s [sn:%lli]\n", + inst->pcState(), inst->seqNum); DPRINTF(IEW, "Blocked load will not be handled because " "already squashing\n"); @@ -1408,8 +1394,8 @@ DefaultIEW<Impl>::writebackInsts() DynInstPtr inst = toCommit->insts[inst_num]; ThreadID tid = inst->threadNumber; - DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %#x.\n", - inst->seqNum, inst->readPC()); + DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n", + inst->seqNum, inst->pcState()); iewInstsToCommit[tid]++; @@ -1613,10 +1599,10 @@ DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst) DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", - inst->readPredPC(), inst->readPredNPC()); + inst->predInstAddr(), inst->predNextInstAddr()); DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," - " NPC: %#x.\n", inst->readNextPC(), - inst->readNextNPC()); + " NPC: %#x.\n", inst->nextInstAddr(), + inst->nextInstAddr()); // If incorrect, then signal the ROB that it must be squashed. squashDueToBranch(inst, tid); diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 3d5eadf84..b944979f2 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -504,8 +504,8 @@ InstructionQueue<Impl>::insert(DynInstPtr &new_inst) // Make sure the instruction is valid assert(new_inst); - DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n", - new_inst->seqNum, new_inst->readPC()); + DPRINTF(IQ, "Adding instruction [sn:%lli] PC %s to the IQ.\n", + new_inst->seqNum, new_inst->pcState()); assert(freeEntries != 0); @@ -547,9 +547,9 @@ InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst) nonSpecInsts[new_inst->seqNum] = new_inst; - DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x " + DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %s " "to the IQ.\n", - new_inst->seqNum, new_inst->readPC()); + new_inst->seqNum, new_inst->pcState()); assert(freeEntries != 0); @@ -767,9 +767,9 @@ InstructionQueue<Impl>::scheduleReadyInsts() } } - DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x " + DPRINTF(IQ, "Thread %i: Issuing instruction PC %s " "[sn:%lli]\n", - tid, issuing_inst->readPC(), + tid, issuing_inst->pcState(), issuing_inst->seqNum); readyInsts[op_class].pop(); @@ -910,7 +910,7 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst) while (dep_inst) { DPRINTF(IQ, "Waking up a dependent instruction, [sn:%lli] " - "PC%#x.\n", dep_inst->seqNum, dep_inst->readPC()); + "PC %s.\n", dep_inst->seqNum, dep_inst->pcState()); // Might want to give more information to the instruction // so that it knows which of its source registers is @@ -955,8 +955,8 @@ InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst) } DPRINTF(IQ, "Instruction is ready to issue, putting it onto " - "the ready list, PC %#x opclass:%i [sn:%lli].\n", - ready_inst->readPC(), op_class, ready_inst->seqNum); + "the ready list, PC %s opclass:%i [sn:%lli].\n", + ready_inst->pcState(), op_class, ready_inst->seqNum); } template <class Impl> @@ -981,8 +981,8 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst) { ThreadID tid = completed_inst->threadNumber; - DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n", - completed_inst->readPC(), completed_inst->seqNum); + DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%lli]\n", + completed_inst->pcState(), completed_inst->seqNum); ++freeEntries; @@ -1050,9 +1050,8 @@ InstructionQueue<Impl>::doSquash(ThreadID tid) (squashed_inst->isMemRef() && !squashed_inst->memOpDone)) { - DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x " - "squashed.\n", - tid, squashed_inst->seqNum, squashed_inst->readPC()); + DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %s squashed.\n", + tid, squashed_inst->seqNum, squashed_inst->pcState()); // Remove the instruction from the dependency list. if (!squashed_inst->isNonSpeculative() && @@ -1147,9 +1146,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst) if (src_reg >= numPhysRegs) { continue; } else if (regScoreboard[src_reg] == false) { - DPRINTF(IQ, "Instruction PC %#x has src reg %i that " + DPRINTF(IQ, "Instruction PC %s has src reg %i that " "is being added to the dependency chain.\n", - new_inst->readPC(), src_reg); + new_inst->pcState(), src_reg); dependGraph.insert(src_reg, new_inst); @@ -1157,9 +1156,9 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst) // was added to the dependency graph. return_val = true; } else { - DPRINTF(IQ, "Instruction PC %#x has src reg %i that " + DPRINTF(IQ, "Instruction PC %s has src reg %i that " "became ready before it reached the IQ.\n", - new_inst->readPC(), src_reg); + new_inst->pcState(), src_reg); // Mark a register ready within the instruction. new_inst->markSrcRegReady(src_reg_idx); } @@ -1228,8 +1227,8 @@ InstructionQueue<Impl>::addIfReady(DynInstPtr &inst) OpClass op_class = inst->opClass(); DPRINTF(IQ, "Instruction is ready to issue, putting it onto " - "the ready list, PC %#x opclass:%i [sn:%lli].\n", - inst->readPC(), op_class, inst->seqNum); + "the ready list, PC %s opclass:%i [sn:%lli].\n", + inst->pcState(), op_class, inst->seqNum); readyInsts[op_class].push(inst); @@ -1299,7 +1298,7 @@ InstructionQueue<Impl>::dumpLists() cprintf("Non speculative list: "); while (non_spec_it != non_spec_end_it) { - cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(), + cprintf("%s [sn:%lli]", (*non_spec_it).second->pcState(), (*non_spec_it).second->seqNum); ++non_spec_it; } @@ -1348,9 +1347,9 @@ InstructionQueue<Impl>::dumpInsts() } } - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" + cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n" "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), + (*inst_list_it)->pcState(), (*inst_list_it)->seqNum, (*inst_list_it)->threadNumber, (*inst_list_it)->isIssued(), @@ -1390,9 +1389,9 @@ InstructionQueue<Impl>::dumpInsts() } } - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" + cprintf("PC: %s\n[sn:%lli]\n[tid:%i]\n" "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), + (*inst_list_it)->pcState(), (*inst_list_it)->seqNum, (*inst_list_it)->threadNumber, (*inst_list_it)->isIssued(), diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index a9047558d..372e76b71 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -530,8 +530,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh, (load_idx != loadHead || !load_inst->isAtCommit())) { iewStage->rescheduleMemInst(load_inst); ++lsqRescheduledLoads; - DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %#x\n", - load_inst->seqNum, load_inst->readPC()); + DPRINTF(LSQUnit, "Uncachable load [sn:%lli] PC %s\n", + load_inst->seqNum, load_inst->pcState()); // Must delete request now that it wasn't handed off to // memory. This is quite ugly. @todo: Figure out the proper @@ -687,8 +687,8 @@ LSQUnit<Impl>::read(Request *req, Request *sreqLow, Request *sreqHigh, } // If there's no forwarding case, then go access memory - DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", - load_inst->seqNum, load_inst->readPC()); + DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n", + load_inst->seqNum, load_inst->pcState()); assert(!load_inst->memData); load_inst->memData = new uint8_t[64]; diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 8aa7fe397..345d3ea69 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -352,8 +352,8 @@ LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) assert((loadTail + 1) % LQEntries != loadHead); assert(loads < LQEntries); - DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", - load_inst->readPC(), loadTail, load_inst->seqNum); + DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n", + load_inst->pcState(), loadTail, load_inst->seqNum); load_inst->lqIdx = loadTail; @@ -378,8 +378,8 @@ LSQUnit<Impl>::insertStore(DynInstPtr &store_inst) assert((storeTail + 1) % SQEntries != storeHead); assert(stores < SQEntries); - DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", - store_inst->readPC(), storeTail, store_inst->seqNum); + DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n", + store_inst->pcState(), storeTail, store_inst->seqNum); store_inst->sqIdx = storeTail; store_inst->lqIdx = loadTail; @@ -444,8 +444,8 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst) // Execute a specific load. Fault load_fault = NoFault; - DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", - inst->readPC(),inst->seqNum); + DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n", + inst->pcState(),inst->seqNum); assert(!inst->isSquashed()); @@ -519,8 +519,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) int store_idx = store_inst->sqIdx; - DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", - store_inst->readPC(), store_inst->seqNum); + DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n", + store_inst->pcState(), store_inst->seqNum); assert(!store_inst->isSquashed()); @@ -531,8 +531,8 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) Fault store_fault = store_inst->initiateAcc(); if (storeQueue[store_idx].size == 0) { - DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", - store_inst->readPC(),store_inst->seqNum); + DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli],Size = 0\n", + store_inst->pcState(), store_inst->seqNum); return store_fault; } @@ -593,8 +593,8 @@ LSQUnit<Impl>::commitLoad() { assert(loadQueue[loadHead]); - DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", - loadQueue[loadHead]->readPC()); + DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n", + loadQueue[loadHead]->pcState()); loadQueue[loadHead] = NULL; @@ -631,8 +631,8 @@ LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) break; } DPRINTF(LSQUnit, "Marking store as able to write back, PC " - "%#x [sn:%lli]\n", - storeQueue[store_idx].inst->readPC(), + "%s [sn:%lli]\n", + storeQueue[store_idx].inst->pcState(), storeQueue[store_idx].inst->seqNum); storeQueue[store_idx].canWB = true; @@ -757,9 +757,9 @@ LSQUnit<Impl>::writebackStores() req = sreqLow; } - DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " + DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s " "to Addr:%#x, data:%#x [sn:%lli]\n", - storeWBIdx, inst->readPC(), + storeWBIdx, inst->pcState(), req->getPaddr(), (int)*(inst->memData), inst->seqNum); @@ -861,9 +861,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) decrLdIdx(load_idx); while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { - DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " + DPRINTF(LSQUnit,"Load Instruction PC %s squashed, " "[sn:%lli]\n", - loadQueue[load_idx]->readPC(), + loadQueue[load_idx]->pcState(), loadQueue[load_idx]->seqNum); if (isStalled() && load_idx == stallingLoadIdx) { @@ -906,9 +906,9 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) break; } - DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " + DPRINTF(LSQUnit,"Store Instruction PC %s squashed, " "idx:%i [sn:%lli]\n", - storeQueue[store_idx].inst->readPC(), + storeQueue[store_idx].inst->pcState(), store_idx, storeQueue[store_idx].inst->seqNum); // I don't think this can happen. It should have been cleared @@ -1156,7 +1156,7 @@ LSQUnit<Impl>::dumpInsts() int load_idx = loadHead; while (load_idx != loadTail && loadQueue[load_idx]) { - cprintf("%#x ", loadQueue[load_idx]->readPC()); + cprintf("%s ", loadQueue[load_idx]->pcState()); incrLdIdx(load_idx); } @@ -1167,7 +1167,7 @@ LSQUnit<Impl>::dumpInsts() int store_idx = storeHead; while (store_idx != storeTail && storeQueue[store_idx].inst) { - cprintf("%#x ", storeQueue[store_idx].inst->readPC()); + cprintf("%s ", storeQueue[store_idx].inst->pcState()); incrStIdx(store_idx); } diff --git a/src/cpu/o3/mem_dep_unit_impl.hh b/src/cpu/o3/mem_dep_unit_impl.hh index 5f5e71624..fdea84ed5 100644 --- a/src/cpu/o3/mem_dep_unit_impl.hh +++ b/src/cpu/o3/mem_dep_unit_impl.hh @@ -171,7 +171,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) storeBarrierSN); producing_store = storeBarrierSN; } else { - producing_store = depPred.checkInst(inst->readPC()); + producing_store = depPred.checkInst(inst->instAddr()); } MemDepEntryPtr store_entry = NULL; @@ -191,7 +191,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) // are ready. if (!store_entry) { DPRINTF(MemDepUnit, "No dependency for inst PC " - "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum); + "%s [sn:%lli].\n", inst->pcState(), inst->seqNum); inst_entry->memDepReady = true; @@ -203,8 +203,8 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) } else { // Otherwise make the instruction dependent on the store/barrier. DPRINTF(MemDepUnit, "Adding to dependency list; " - "inst PC %#x is dependent on [sn:%lli].\n", - inst->readPC(), producing_store); + "inst PC %s is dependent on [sn:%lli].\n", + inst->pcState(), producing_store); if (inst->readyToIssue()) { inst_entry->regsReady = true; @@ -224,10 +224,10 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst) } if (inst->isStore()) { - DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); - depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber); + depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber); ++insertedStores; } else if (inst->isLoad()) { @@ -260,10 +260,10 @@ MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst) // Might want to turn this part into an inline function or something. // It's shared between both insert functions. if (inst->isStore()) { - DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + DPRINTF(MemDepUnit, "Inserting store PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); - depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber); + depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber); ++insertedStores; } else if (inst->isLoad()) { @@ -313,8 +313,8 @@ void MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst) { DPRINTF(MemDepUnit, "Marking registers as ready for " - "instruction PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + "instruction PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); MemDepEntryPtr inst_entry = findInHash(inst); @@ -336,8 +336,8 @@ void MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst) { DPRINTF(MemDepUnit, "Marking non speculative " - "instruction PC %#x as ready [sn:%lli].\n", - inst->readPC(), inst->seqNum); + "instruction PC %s as ready [sn:%lli].\n", + inst->pcState(), inst->seqNum); MemDepEntryPtr inst_entry = findInHash(inst); @@ -363,9 +363,8 @@ MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst) MemDepEntryPtr inst_entry = findInHash(temp_inst); - DPRINTF(MemDepUnit, "Replaying mem instruction PC %#x " - "[sn:%lli].\n", - temp_inst->readPC(), temp_inst->seqNum); + DPRINTF(MemDepUnit, "Replaying mem instruction PC %s [sn:%lli].\n", + temp_inst->pcState(), temp_inst->seqNum); moveToReady(inst_entry); @@ -377,9 +376,8 @@ template <class MemDepPred, class Impl> void MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst) { - DPRINTF(MemDepUnit, "Completed mem instruction PC %#x " - "[sn:%lli].\n", - inst->readPC(), inst->seqNum); + DPRINTF(MemDepUnit, "Completed mem instruction PC %s [sn:%lli].\n", + inst->pcState(), inst->seqNum); ThreadID tid = inst->threadNumber; @@ -507,10 +505,10 @@ MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst, DynInstPtr &violating_load) { DPRINTF(MemDepUnit, "Passing violating PCs to store sets," - " load: %#x, store: %#x\n", violating_load->readPC(), - store_inst->readPC()); + " load: %#x, store: %#x\n", violating_load->instAddr(), + store_inst->instAddr()); // Tell the memory dependence unit of the violation. - depPred.violation(violating_load->readPC(), store_inst->readPC()); + depPred.violation(violating_load->instAddr(), store_inst->instAddr()); } template <class MemDepPred, class Impl> @@ -518,9 +516,9 @@ void MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst) { DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n", - inst->readPC(), inst->seqNum); + inst->instAddr(), inst->seqNum); - depPred.issued(inst->readPC(), inst->seqNum, inst->isStore()); + depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore()); } template <class MemDepPred, class Impl> @@ -559,9 +557,9 @@ MemDepUnit<MemDepPred, Impl>::dumpLists() int num = 0; while (inst_list_it != instList[tid].end()) { - cprintf("Instruction:%i\nPC:%#x\n[sn:%i]\n[tid:%i]\nIssued:%i\n" + cprintf("Instruction:%i\nPC: %s\n[sn:%i]\n[tid:%i]\nIssued:%i\n" "Squashed:%i\n\n", - num, (*inst_list_it)->readPC(), + num, (*inst_list_it)->pcState(), (*inst_list_it)->seqNum, (*inst_list_it)->threadNumber, (*inst_list_it)->isIssued(), diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index 7f796c4c8..4b321d099 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -591,15 +591,14 @@ DefaultRename<Impl>::renameInsts(ThreadID tid) insts_to_rename.pop_front(); if (renameStatus[tid] == Unblocking) { - DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename " - "skidBuffer\n", - tid, inst->seqNum, inst->readPC()); + DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%s from rename " + "skidBuffer\n", tid, inst->seqNum, inst->pcState()); } if (inst->isSquashed()) { - DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is " - "squashed, skipping.\n", - tid, inst->seqNum, inst->readPC()); + DPRINTF(Rename, "[tid:%u]: instruction %i with PC %s is " + "squashed, skipping.\n", tid, inst->seqNum, + inst->pcState()); ++renameSquashedInsts; @@ -610,8 +609,7 @@ DefaultRename<Impl>::renameInsts(ThreadID tid) } DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with " - "PC %#x.\n", - tid, inst->seqNum, inst->readPC()); + "PC %s.\n", tid, inst->seqNum, inst->pcState()); // Handle serializeAfter/serializeBefore instructions. // serializeAfter marks the next instruction as serializeBefore. @@ -716,8 +714,8 @@ DefaultRename<Impl>::skidInsert(ThreadID tid) assert(tid == inst->threadNumber); - DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename " - "skidBuffer\n", tid, inst->seqNum, inst->readPC()); + DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC: %s into Rename " + "skidBuffer\n", tid, inst->seqNum, inst->pcState()); ++renameSkidInsts; @@ -731,7 +729,7 @@ DefaultRename<Impl>::skidInsert(ThreadID tid) for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++) { warn("[tid:%u]: %s [sn:%i].\n", tid, - (*it)->staticInst->disassemble(inst->readPC()), + (*it)->staticInst->disassemble(inst->instAddr()), (*it)->seqNum); } panic("Skidbuffer Exceeded Max Size"); @@ -1287,8 +1285,7 @@ DefaultRename<Impl>::checkSignalsAndUpdate(ThreadID tid) unblock(tid); DPRINTF(Rename, "[tid:%u]: Processing instruction [%lli] with " - "PC %#x.\n", - tid, serial_inst->seqNum, serial_inst->readPC()); + "PC %s.\n", tid, serial_inst->seqNum, serial_inst->pcState()); // Put instruction into queue here. serial_inst->clearSerializeBefore(); diff --git a/src/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh index cf0080b48..37f1c5504 100644 --- a/src/cpu/o3/rob_impl.hh +++ b/src/cpu/o3/rob_impl.hh @@ -204,7 +204,7 @@ ROB<Impl>::insertInst(DynInstPtr &inst) { assert(inst); - DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC()); + DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState()); assert(numInstsInROB != numEntries); @@ -247,7 +247,7 @@ ROB<Impl>::retireHead(ThreadID tid) assert(head_inst->readyToCommit()); DPRINTF(ROB, "[tid:%u]: Retiring head instruction, " - "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(), + "instruction PC %s, [sn:%lli]\n", tid, head_inst->pcState(), head_inst->seqNum); --numInstsInROB; @@ -338,9 +338,9 @@ ROB<Impl>::doSquash(ThreadID tid) (*squashIt[tid])->seqNum > squashedSeqNum[tid]; ++numSquashed) { - DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n", + DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %s, seq num %i.\n", (*squashIt[tid])->threadNumber, - (*squashIt[tid])->readPC(), + (*squashIt[tid])->pcState(), (*squashIt[tid])->seqNum); // Mark the instruction as squashed, and ready to commit so that diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index b7790cfda..4e559000b 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -172,29 +172,24 @@ class O3ThreadContext : public ThreadContext virtual void setFloatRegBits(int reg_idx, FloatRegBits val); - /** Reads this thread's PC. */ - virtual uint64_t readPC() - { return cpu->readPC(thread->threadId()); } - - /** Sets this thread's PC. */ - virtual void setPC(uint64_t val); - - /** Reads this thread's next PC. */ - virtual uint64_t readNextPC() - { return cpu->readNextPC(thread->threadId()); } + /** Reads this thread's PC state. */ + virtual TheISA::PCState pcState() + { return cpu->pcState(thread->threadId()); } - /** Sets this thread's next PC. */ - virtual void setNextPC(uint64_t val); + /** Sets this thread's PC state. */ + virtual void pcState(const TheISA::PCState &val); - virtual uint64_t readMicroPC() - { return cpu->readMicroPC(thread->threadId()); } - - virtual void setMicroPC(uint64_t val); + /** Reads this thread's PC. */ + virtual Addr instAddr() + { return cpu->instAddr(thread->threadId()); } - virtual uint64_t readNextMicroPC() - { return cpu->readNextMicroPC(thread->threadId()); } + /** Reads this thread's next PC. */ + virtual Addr nextInstAddr() + { return cpu->nextInstAddr(thread->threadId()); } - virtual void setNextMicroPC(uint64_t val); + /** Reads this thread's next PC. */ + virtual MicroPC microPC() + { return cpu->microPC(thread->threadId()); } /** Reads a miscellaneous register. */ virtual MiscReg readMiscRegNoEffect(int misc_reg) @@ -247,15 +242,6 @@ class O3ThreadContext : public ThreadContext } #endif - virtual uint64_t readNextNPC() - { - return this->cpu->readNextNPC(this->thread->threadId()); - } - - virtual void setNextNPC(uint64_t val) - { - this->cpu->setNextNPC(val, this->thread->threadId()); - } }; #endif diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 0b7a2b172..367442830 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -248,11 +248,7 @@ O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) // Then finally set the PC, the next PC, the nextNPC, the micropc, and the // next micropc. - cpu->setPC(tc->readPC(), tid); - cpu->setNextPC(tc->readNextPC(), tid); - cpu->setNextNPC(tc->readNextNPC(), tid); - cpu->setMicroPC(tc->readMicroPC(), tid); - cpu->setNextMicroPC(tc->readNextMicroPC(), tid); + cpu->pcState(tc->pcState(), tid); #if !FULL_SYSTEM this->thread->funcExeInst = tc->readFuncExeInst(); #endif @@ -327,45 +323,9 @@ O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) template <class Impl> void -O3ThreadContext<Impl>::setPC(uint64_t val) +O3ThreadContext<Impl>::pcState(const TheISA::PCState &val) { - cpu->setPC(val, thread->threadId()); - - // Squash if we're not already in a state update mode. - if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->threadId()); - } -} - -template <class Impl> -void -O3ThreadContext<Impl>::setNextPC(uint64_t val) -{ - cpu->setNextPC(val, thread->threadId()); - - // Squash if we're not already in a state update mode. - if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->threadId()); - } -} - -template <class Impl> -void -O3ThreadContext<Impl>::setMicroPC(uint64_t val) -{ - cpu->setMicroPC(val, thread->threadId()); - - // Squash if we're not already in a state update mode. - if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->threadId()); - } -} - -template <class Impl> -void -O3ThreadContext<Impl>::setNextMicroPC(uint64_t val) -{ - cpu->setNextMicroPC(val, thread->threadId()); + cpu->pcState(val, thread->threadId()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { diff --git a/src/cpu/pc_event.cc b/src/cpu/pc_event.cc index 79f5277d5..533d61498 100644 --- a/src/cpu/pc_event.cc +++ b/src/cpu/pc_event.cc @@ -83,7 +83,7 @@ PCEventQueue::schedule(PCEvent *event) bool PCEventQueue::doService(ThreadContext *tc) { - Addr pc = tc->readPC() & ~0x3; + Addr pc = tc->instAddr() & ~0x3; int serviced = 0; range_t range = equal_range(pc); for (iterator i = range.first; i != range.second; ++i) { @@ -91,7 +91,7 @@ PCEventQueue::doService(ThreadContext *tc) // another event. This for example, prevents two invocations // of the SkipFuncEvent. Maybe we should have separate PC // event queues for each processor? - if (pc != (tc->readPC() & ~0x3)) + if (pc != (tc->instAddr() & ~0x3)) continue; DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n", diff --git a/src/cpu/pred/btb.cc b/src/cpu/pred/btb.cc index c6a5e23f9..e87cc6dc2 100644 --- a/src/cpu/pred/btb.cc +++ b/src/cpu/pred/btb.cc @@ -68,25 +68,25 @@ DefaultBTB::reset() inline unsigned -DefaultBTB::getIndex(const Addr &inst_PC) +DefaultBTB::getIndex(Addr instPC) { // Need to shift PC over by the word offset. - return (inst_PC >> instShiftAmt) & idxMask; + return (instPC >> instShiftAmt) & idxMask; } inline Addr -DefaultBTB::getTag(const Addr &inst_PC) +DefaultBTB::getTag(Addr instPC) { - return (inst_PC >> tagShiftAmt) & tagMask; + return (instPC >> tagShiftAmt) & tagMask; } bool -DefaultBTB::valid(const Addr &inst_PC, ThreadID tid) +DefaultBTB::valid(Addr instPC, ThreadID tid) { - unsigned btb_idx = getIndex(inst_PC); + unsigned btb_idx = getIndex(instPC); - Addr inst_tag = getTag(inst_PC); + Addr inst_tag = getTag(instPC); assert(btb_idx < numEntries); @@ -102,12 +102,12 @@ DefaultBTB::valid(const Addr &inst_PC, ThreadID tid) // @todo Create some sort of return struct that has both whether or not the // address is valid, and also the address. For now will just use addr = 0 to // represent invalid entry. -Addr -DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid) +TheISA::PCState +DefaultBTB::lookup(Addr instPC, ThreadID tid) { - unsigned btb_idx = getIndex(inst_PC); + unsigned btb_idx = getIndex(instPC); - Addr inst_tag = getTag(inst_PC); + Addr inst_tag = getTag(instPC); assert(btb_idx < numEntries); @@ -121,14 +121,14 @@ DefaultBTB::lookup(const Addr &inst_PC, ThreadID tid) } void -DefaultBTB::update(const Addr &inst_PC, const Addr &target, ThreadID tid) +DefaultBTB::update(Addr instPC, const TheISA::PCState &target, ThreadID tid) { - unsigned btb_idx = getIndex(inst_PC); + unsigned btb_idx = getIndex(instPC); assert(btb_idx < numEntries); btb[btb_idx].tid = tid; btb[btb_idx].valid = true; btb[btb_idx].target = target; - btb[btb_idx].tag = getTag(inst_PC); + btb[btb_idx].tag = getTag(instPC); } diff --git a/src/cpu/pred/btb.hh b/src/cpu/pred/btb.hh index 6557522e0..814b23872 100644 --- a/src/cpu/pred/btb.hh +++ b/src/cpu/pred/btb.hh @@ -31,8 +31,10 @@ #ifndef __CPU_O3_BTB_HH__ #define __CPU_O3_BTB_HH__ +#include "arch/types.hh" #include "base/misc.hh" #include "base/types.hh" +#include "config/the_isa.hh" class DefaultBTB { @@ -41,14 +43,13 @@ class DefaultBTB { BTBEntry() : tag(0), target(0), valid(false) - { - } + {} /** The entry's tag. */ Addr tag; /** The entry's target. */ - Addr target; + TheISA::PCState target; /** The entry's thread id. */ ThreadID tid; @@ -74,21 +75,21 @@ class DefaultBTB * @param tid The thread id. * @return Returns the target of the branch. */ - Addr lookup(const Addr &inst_PC, ThreadID tid); + TheISA::PCState lookup(Addr instPC, ThreadID tid); /** Checks if a branch is in the BTB. * @param inst_PC The address of the branch to look up. * @param tid The thread id. * @return Whether or not the branch exists in the BTB. */ - bool valid(const Addr &inst_PC, ThreadID tid); + bool valid(Addr instPC, ThreadID tid); /** Updates the BTB with the target of a branch. * @param inst_PC The address of the branch being updated. * @param target_PC The target address of the branch. * @param tid The thread id. */ - void update(const Addr &inst_PC, const Addr &target_PC, + void update(Addr instPC, const TheISA::PCState &targetPC, ThreadID tid); private: @@ -96,13 +97,13 @@ class DefaultBTB * @param inst_PC The branch to look up. * @return Returns the index into the BTB. */ - inline unsigned getIndex(const Addr &inst_PC); + inline unsigned getIndex(Addr instPC); /** Returns the tag bits of a given address. * @param inst_PC The branch's address. * @return Returns the tag bits. */ - inline Addr getTag(const Addr &inst_PC); + inline Addr getTag(Addr instPC); /** The actual BTB. */ std::vector<BTBEntry> btb; diff --git a/src/cpu/pred/ras.cc b/src/cpu/pred/ras.cc index 6373e5de3..0ba09bfae 100644 --- a/src/cpu/pred/ras.cc +++ b/src/cpu/pred/ras.cc @@ -34,13 +34,8 @@ void ReturnAddrStack::init(unsigned _numEntries) { numEntries = _numEntries; - usedEntries = 0; - tos = 0; - addrStack.resize(numEntries); - - for (unsigned i = 0; i < numEntries; ++i) - addrStack[i] = 0; + reset(); } void @@ -49,11 +44,11 @@ ReturnAddrStack::reset() usedEntries = 0; tos = 0; for (unsigned i = 0; i < numEntries; ++i) - addrStack[i] = 0; + addrStack[i].set(0); } void -ReturnAddrStack::push(const Addr &return_addr) +ReturnAddrStack::push(const TheISA::PCState &return_addr) { incrTos(); @@ -76,9 +71,9 @@ ReturnAddrStack::pop() void ReturnAddrStack::restore(unsigned top_entry_idx, - const Addr &restored_target) + const TheISA::PCState &restored) { tos = top_entry_idx; - addrStack[tos] = restored_target; + addrStack[tos] = restored; } diff --git a/src/cpu/pred/ras.hh b/src/cpu/pred/ras.hh index a36faf79a..ab92b34c2 100644 --- a/src/cpu/pred/ras.hh +++ b/src/cpu/pred/ras.hh @@ -33,7 +33,9 @@ #include <vector> +#include "arch/types.hh" #include "base/types.hh" +#include "config/the_isa.hh" /** Return address stack class, implements a simple RAS. */ class ReturnAddrStack @@ -52,7 +54,7 @@ class ReturnAddrStack void reset(); /** Returns the top address on the RAS. */ - Addr top() + TheISA::PCState top() { return addrStack[tos]; } /** Returns the index of the top of the RAS. */ @@ -60,7 +62,7 @@ class ReturnAddrStack { return tos; } /** Pushes an address onto the RAS. */ - void push(const Addr &return_addr); + void push(const TheISA::PCState &return_addr); /** Pops the top address from the RAS. */ void pop(); @@ -68,9 +70,9 @@ class ReturnAddrStack /** Changes index to the top of the RAS, and replaces the top address with * a new target. * @param top_entry_idx The index of the RAS that will now be the top. - * @param restored_target The new target address of the new top of the RAS. + * @param restored The new target address of the new top of the RAS. */ - void restore(unsigned top_entry_idx, const Addr &restored_target); + void restore(unsigned top_entry_idx, const TheISA::PCState &restored); bool empty() { return usedEntries == 0; } @@ -85,7 +87,7 @@ class ReturnAddrStack { tos = (tos == 0 ? numEntries - 1 : tos - 1); } /** The RAS itself. */ - std::vector<Addr> addrStack; + std::vector<TheISA::PCState> addrStack; /** The number of entries in the RAS. */ unsigned numEntries; diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index d97e7aeec..de26ca2f8 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -321,7 +321,7 @@ AtomicSimpleCPU::readBytes(Addr addr, uint8_t * data, dcache_latency = 0; while (1) { - req->setVirt(0, addr, size, flags, thread->readPC()); + req->setVirt(0, addr, size, flags, thread->pcState().instAddr()); // translate to physical address Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Read); @@ -475,7 +475,7 @@ AtomicSimpleCPU::writeBytes(uint8_t *data, unsigned size, dcache_latency = 0; while(1) { - req->setVirt(0, addr, size, flags, thread->readPC()); + req->setVirt(0, addr, size, flags, thread->pcState().instAddr()); // translate to physical address Fault fault = thread->dtb->translateAtomic(req, tc, BaseTLB::Write); @@ -643,8 +643,11 @@ AtomicSimpleCPU::tick() Fault fault = NoFault; - bool fromRom = isRomMicroPC(thread->readMicroPC()); - if (!fromRom && !curMacroStaticInst) { + TheISA::PCState pcState = thread->pcState(); + + bool needToFetch = !isRomMicroPC(pcState.microPC()) && + !curMacroStaticInst; + if (needToFetch) { setupFetchRequest(&ifetch_req); fault = thread->itb->translateAtomic(&ifetch_req, tc, BaseTLB::Execute); @@ -655,7 +658,7 @@ AtomicSimpleCPU::tick() bool icache_access = false; dcache_access = false; // assume no dcache access - if (!fromRom && !curMacroStaticInst) { + if (needToFetch) { // This is commented out because the predecoder would act like // a tiny cache otherwise. It wouldn't be flushed when needed // like the I cache. It should be flushed, and when that works diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 088d5ff16..196b72cc0 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -368,19 +368,13 @@ BaseSimpleCPU::checkForInterrupts() void BaseSimpleCPU::setupFetchRequest(Request *req) { - Addr threadPC = thread->readPC(); + Addr instAddr = thread->instAddr(); // set up memory request for instruction fetch -#if ISA_HAS_DELAY_SLOT - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",threadPC, - thread->readNextPC(),thread->readNextNPC()); -#else - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p\n",threadPC, - thread->readNextPC()); -#endif + DPRINTF(Fetch, "Fetch: PC:%08p\n", instAddr); - Addr fetchPC = (threadPC & PCMask) + fetchOffset; - req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, threadPC); + Addr fetchPC = (instAddr & PCMask) + fetchOffset; + req->setVirt(0, fetchPC, sizeof(MachInst), Request::INST_FETCH, instAddr); } @@ -399,11 +393,12 @@ BaseSimpleCPU::preExecute() // decode the instruction inst = gtoh(inst); - MicroPC upc = thread->readMicroPC(); + TheISA::PCState pcState = thread->pcState(); - if (isRomMicroPC(upc)) { + if (isRomMicroPC(pcState.microPC())) { stayAtPC = false; - curStaticInst = microcodeRom.fetchMicroop(upc, curMacroStaticInst); + curStaticInst = microcodeRom.fetchMicroop(pcState.microPC(), + curMacroStaticInst); } else if (!curMacroStaticInst) { //We're not in the middle of a macro instruction StaticInstPtr instPtr = NULL; @@ -412,21 +407,19 @@ BaseSimpleCPU::preExecute() //This should go away once the constructor can be set up properly predecoder.setTC(thread->getTC()); //If more fetch data is needed, pass it in. - Addr fetchPC = (thread->readPC() & PCMask) + fetchOffset; + Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset; //if(predecoder.needMoreBytes()) - predecoder.moreBytes(thread->readPC(), fetchPC, inst); + predecoder.moreBytes(pcState, fetchPC, inst); //else // predecoder.process(); //If an instruction is ready, decode it. Otherwise, we'll have to //fetch beyond the MachInst at the current pc. if (predecoder.extMachInstReady()) { -#if THE_ISA == X86_ISA || THE_ISA == ARM_ISA - thread->setNextPC(thread->readPC() + predecoder.getInstSize()); -#endif // X86_ISA stayAtPC = false; - instPtr = StaticInst::decode(predecoder.getExtMachInst(), - thread->readPC()); + ExtMachInst machInst = predecoder.getExtMachInst(pcState); + thread->pcState(pcState); + instPtr = StaticInst::decode(machInst, pcState.instAddr()); } else { stayAtPC = true; fetchOffset += sizeof(MachInst); @@ -436,13 +429,13 @@ BaseSimpleCPU::preExecute() //out micro ops if (instPtr && instPtr->isMacroop()) { curMacroStaticInst = instPtr; - curStaticInst = curMacroStaticInst->fetchMicroop(upc); + curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC()); } else { curStaticInst = instPtr; } } else { //Read the next micro op from the macro op - curStaticInst = curMacroStaticInst->fetchMicroop(upc); + curStaticInst = curMacroStaticInst->fetchMicroop(pcState.microPC()); } //If we decoded an instruction this "tick", record information about it. @@ -450,8 +443,7 @@ BaseSimpleCPU::preExecute() { #if TRACING_ON traceData = tracer->getInstRecord(curTick, tc, - curStaticInst, thread->readPC(), - curMacroStaticInst, thread->readMicroPC()); + curStaticInst, thread->pcState(), curMacroStaticInst); DPRINTF(Decode,"Decode: Decoded %s instruction: 0x%x\n", curStaticInst->getName(), curStaticInst->machInst); @@ -462,10 +454,14 @@ BaseSimpleCPU::preExecute() void BaseSimpleCPU::postExecute() { + assert(curStaticInst); + + TheISA::PCState pc = tc->pcState(); + Addr instAddr = pc.instAddr(); #if FULL_SYSTEM - if (thread->profile && curStaticInst) { + if (thread->profile) { bool usermode = TheISA::inUserMode(tc); - thread->profilePC = usermode ? 1 : thread->readPC(); + thread->profilePC = usermode ? 1 : instAddr; ProfileNode *node = thread->profile->consume(tc, curStaticInst); if (node) thread->profileNode = node; @@ -482,10 +478,10 @@ BaseSimpleCPU::postExecute() } if (CPA::available()) { - CPA::cpa()->swAutoBegin(tc, thread->readNextPC()); + CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr()); } - traceFunctions(thread->readPC()); + traceFunctions(instAddr); if (traceData) { traceData->dump(); @@ -505,30 +501,12 @@ BaseSimpleCPU::advancePC(Fault fault) fault->invoke(tc, curStaticInst); predecoder.reset(); } else { - //If we're at the last micro op for this instruction - if (curStaticInst && curStaticInst->isLastMicroop()) { - //We should be working with a macro op or be in the ROM - assert(curMacroStaticInst || - isRomMicroPC(thread->readMicroPC())); - //Close out this macro op, and clean up the - //microcode state - curMacroStaticInst = StaticInst::nullStaticInstPtr; - thread->setMicroPC(normalMicroPC(0)); - thread->setNextMicroPC(normalMicroPC(1)); - } - //If we're still in a macro op - if (curMacroStaticInst || isRomMicroPC(thread->readMicroPC())) { - //Advance the micro pc - thread->setMicroPC(thread->readNextMicroPC()); - //Advance the "next" micro pc. Note that there are no delay - //slots, and micro ops are "word" addressed. - thread->setNextMicroPC(thread->readNextMicroPC() + 1); - } else { - // go to the next instruction - thread->setPC(thread->readNextPC()); - thread->setNextPC(thread->readNextNPC()); - thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); - assert(thread->readNextPC() != thread->readNextNPC()); + if (curStaticInst) { + if (curStaticInst->isLastMicroop()) + curMacroStaticInst = StaticInst::nullStaticInstPtr; + TheISA::PCState pcState = thread->pcState(); + TheISA::advancePC(pcState, curStaticInst); + thread->pcState(pcState); } } } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 0aa0a295c..a713533fc 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -88,11 +88,12 @@ class BaseSimpleCPU : public BaseCPU Trace::InstRecord *traceData; inline void checkPcEventQueue() { - Addr oldpc; + Addr oldpc, pc = thread->instAddr(); do { - oldpc = thread->readPC(); + oldpc = pc; system->pcEventQueue.service(tc); - } while (oldpc != thread->readPC()); + pc = thread->instAddr(); + } while (oldpc != pc); } public: @@ -282,18 +283,7 @@ class BaseSimpleCPU : public BaseCPU thread->setFloatRegBits(reg_idx, val); } - uint64_t readPC() { return thread->readPC(); } - uint64_t readMicroPC() { return thread->readMicroPC(); } - uint64_t readNextPC() { return thread->readNextPC(); } - uint64_t readNextMicroPC() { return thread->readNextMicroPC(); } - uint64_t readNextNPC() { return thread->readNextNPC(); } bool readPredicate() { return thread->readPredicate(); } - - void setPC(uint64_t val) { thread->setPC(val); } - void setMicroPC(uint64_t val) { thread->setMicroPC(val); } - void setNextPC(uint64_t val) { thread->setNextPC(val); } - void setNextMicroPC(uint64_t val) { thread->setNextMicroPC(val); } - void setNextNPC(uint64_t val) { thread->setNextNPC(val); } void setPredicate(bool val) { thread->setPredicate(val); @@ -301,6 +291,11 @@ class BaseSimpleCPU : public BaseCPU traceData->setPredicate(val); } } + TheISA::PCState pcState() { return thread->pcState(); } + void pcState(const TheISA::PCState &val) { thread->pcState(val); } + Addr instAddr() { return thread->instAddr(); } + Addr nextInstAddr() { return thread->nextInstAddr(); } + MicroPC microPC() { return thread->microPC(); } MiscReg readMiscRegNoEffect(int misc_reg) { diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 2eb5b432b..863c28be2 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -422,7 +422,7 @@ TimingSimpleCPU::readBytes(Addr addr, uint8_t *data, Fault fault; const int asid = 0; const ThreadID tid = 0; - const Addr pc = thread->readPC(); + const Addr pc = thread->instAddr(); unsigned block_size = dcachePort.peerBlockSize(); BaseTLB::Mode mode = BaseTLB::Read; @@ -545,7 +545,7 @@ TimingSimpleCPU::writeTheseBytes(uint8_t *data, unsigned size, { const int asid = 0; const ThreadID tid = 0; - const Addr pc = thread->readPC(); + const Addr pc = thread->instAddr(); unsigned block_size = dcachePort.peerBlockSize(); BaseTLB::Mode mode = BaseTLB::Write; @@ -701,9 +701,10 @@ TimingSimpleCPU::fetch() checkPcEventQueue(); - bool fromRom = isRomMicroPC(thread->readMicroPC()); + TheISA::PCState pcState = thread->pcState(); + bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst; - if (!fromRom && !curMacroStaticInst) { + if (needToFetch) { Request *ifetch_req = new Request(); ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); setupFetchRequest(ifetch_req); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index bd796428a..15fac8677 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -193,11 +193,7 @@ SimpleThread::serialize(ostream &os) ThreadState::serialize(os); SERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs); SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs); - SERIALIZE_SCALAR(microPC); - SERIALIZE_SCALAR(nextMicroPC); - SERIALIZE_SCALAR(PC); - SERIALIZE_SCALAR(nextPC); - SERIALIZE_SCALAR(nextNPC); + _pcState.serialize(os); // thread_num and cpu_id are deterministic from the config // @@ -213,11 +209,7 @@ SimpleThread::unserialize(Checkpoint *cp, const std::string §ion) ThreadState::unserialize(cp, section); UNSERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs); UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs); - UNSERIALIZE_SCALAR(microPC); - UNSERIALIZE_SCALAR(nextMicroPC); - UNSERIALIZE_SCALAR(PC); - UNSERIALIZE_SCALAR(nextPC); - UNSERIALIZE_SCALAR(nextNPC); + _pcState.unserialize(cp, section); // thread_num and cpu_id are deterministic from the config // diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index e4a7b7a77..48077a9b9 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -106,27 +106,7 @@ class SimpleThread : public ThreadState TheISA::IntReg intRegs[TheISA::NumIntRegs]; TheISA::ISA isa; // one "instance" of the current ISA. - /** The current microcode pc for the currently executing macro - * operation. - */ - MicroPC microPC; - - /** The next microcode pc for the currently executing macro - * operation. - */ - MicroPC nextMicroPC; - - /** The current pc. - */ - Addr PC; - - /** The next pc. - */ - Addr nextPC; - - /** The next next pc. - */ - Addr nextNPC; + TheISA::PCState _pcState; /** Did this instruction execute or is it predicated false */ bool predicate; @@ -245,9 +225,7 @@ class SimpleThread : public ThreadState void clearArchRegs() { - microPC = 0; - nextMicroPC = 1; - PC = nextPC = nextNPC = 0; + _pcState = 0; memset(intRegs, 0, sizeof(intRegs)); memset(floatRegs.i, 0, sizeof(floatRegs.i)); isa.clear(); @@ -313,60 +291,34 @@ class SimpleThread : public ThreadState reg_idx, flatIndex, val, floatRegs.f[flatIndex]); } - uint64_t readPC() - { - return PC; - } - - void setPC(uint64_t val) - { - PC = val; - } - - uint64_t readMicroPC() - { - return microPC; - } - - void setMicroPC(uint64_t val) - { - microPC = val; - } - - uint64_t readNextPC() + TheISA::PCState + pcState() { - return nextPC; + return _pcState; } - void setNextPC(uint64_t val) + void + pcState(const TheISA::PCState &val) { - nextPC = val; + _pcState = val; } - uint64_t readNextMicroPC() + Addr + instAddr() { - return nextMicroPC; + return _pcState.instAddr(); } - void setNextMicroPC(uint64_t val) + Addr + nextInstAddr() { - nextMicroPC = val; + return _pcState.nextInstAddr(); } - uint64_t readNextNPC() + MicroPC + microPC() { -#if ISA_HAS_DELAY_SLOT - return nextNPC; -#else - return nextPC + sizeof(TheISA::MachInst); -#endif - } - - void setNextNPC(uint64_t val) - { -#if ISA_HAS_DELAY_SLOT - nextNPC = val; -#endif + return _pcState.microPC(); } bool readPredicate() diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index 2c4fc8ab9..f2a72c96a 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -68,7 +68,8 @@ StaticInst::dumpDecodeCacheStats() } bool -StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const +StaticInst::hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc, + TheISA::PCState &tgt) const { if (isDirectCtrl()) { tgt = branchTarget(pc); @@ -84,21 +85,21 @@ StaticInst::hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const } StaticInstPtr -StaticInst::fetchMicroop(MicroPC micropc) +StaticInst::fetchMicroop(MicroPC upc) const { panic("StaticInst::fetchMicroop() called on instruction " "that is not microcoded."); } -Addr -StaticInst::branchTarget(Addr branchPC) const +TheISA::PCState +StaticInst::branchTarget(const TheISA::PCState &pc) const { panic("StaticInst::branchTarget() called on instruction " "that is not a PC-relative branch."); M5_DUMMY_RETURN; } -Addr +TheISA::PCState StaticInst::branchTarget(ThreadContext *tc) const { panic("StaticInst::branchTarget() called on instruction " diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 6474bbf9c..b219fafd6 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -35,6 +35,7 @@ #include <string> #include "arch/isa_traits.hh" +#include "arch/types.hh" #include "arch/registers.hh" #include "config/the_isa.hh" #include "base/hashmap.hh" @@ -70,28 +71,6 @@ namespace Trace { class InstRecord; } -typedef uint16_t MicroPC; - -static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1); - -static inline MicroPC -romMicroPC(MicroPC upc) -{ - return upc | MicroPCRomBit; -} - -static inline MicroPC -normalMicroPC(MicroPC upc) -{ - return upc & ~MicroPCRomBit; -} - -static inline bool -isRomMicroPC(MicroPC upc) -{ - return MicroPCRomBit & upc; -} - /** * Base, ISA-independent static instruction class. * @@ -392,18 +371,20 @@ class StaticInst : public StaticInstBase */ #include "cpu/static_inst_exec_sigs.hh" + virtual void advancePC(TheISA::PCState &pcState) const = 0; + /** * Return the microop that goes with a particular micropc. This should * only be defined/used in macroops which will contain microops */ - virtual StaticInstPtr fetchMicroop(MicroPC micropc); + virtual StaticInstPtr fetchMicroop(MicroPC upc) const; /** * Return the target address for a PC-relative branch. * Invalid if not a PC-relative branch (i.e. isDirectCtrl() * should be true). */ - virtual Addr branchTarget(Addr branchPC) const; + virtual TheISA::PCState branchTarget(const TheISA::PCState &pc) const; /** * Return the target address for an indirect branch (jump). The @@ -412,13 +393,14 @@ class StaticInst : public StaticInstBase * execute the branch in question. Invalid if not an indirect * branch (i.e. isIndirectCtrl() should be true). */ - virtual Addr branchTarget(ThreadContext *tc) const; + virtual TheISA::PCState branchTarget(ThreadContext *tc) const; /** * Return true if the instruction is a control transfer, and if so, * return the target address as well. */ - bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const; + bool hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc, + TheISA::PCState &tgt) const; /** * Return string representation of disassembled instruction. diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc index f2083ef08..c4960ea30 100644 --- a/src/cpu/thread_context.cc +++ b/src/cpu/thread_context.cc @@ -65,16 +65,8 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two) } #endif - Addr pc1 = one->readPC(); - Addr pc2 = two->readPC(); - if (pc1 != pc2) - panic("PCs doesn't match, one: %#x, two: %#x", pc1, pc2); - - Addr npc1 = one->readNextPC(); - Addr npc2 = two->readNextPC(); - if (npc1 != npc2) - panic("NPCs doesn't match, one: %#x, two: %#x", npc1, npc2); - + if (!(one->pcState() == two->pcState())) + panic("PC state doesn't match."); int id1 = one->cpuId(); int id2 = two->cpuId(); if (id1 != id2) diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 753fa2146..1c70ef59a 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -192,25 +192,15 @@ class ThreadContext virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0; - virtual uint64_t readPC() = 0; + virtual TheISA::PCState pcState() = 0; - virtual void setPC(uint64_t val) = 0; + virtual void pcState(const TheISA::PCState &val) = 0; - virtual uint64_t readNextPC() = 0; + virtual Addr instAddr() = 0; - virtual void setNextPC(uint64_t val) = 0; + virtual Addr nextInstAddr() = 0; - virtual uint64_t readNextNPC() = 0; - - virtual void setNextNPC(uint64_t val) = 0; - - virtual uint64_t readMicroPC() = 0; - - virtual void setMicroPC(uint64_t val) = 0; - - virtual uint64_t readNextMicroPC() = 0; - - virtual void setNextMicroPC(uint64_t val) = 0; + virtual MicroPC microPC() = 0; virtual MiscReg readMiscRegNoEffect(int misc_reg) = 0; @@ -377,25 +367,13 @@ class ProxyThreadContext : public ThreadContext void setFloatRegBits(int reg_idx, FloatRegBits val) { actualTC->setFloatRegBits(reg_idx, val); } - uint64_t readPC() { return actualTC->readPC(); } - - void setPC(uint64_t val) { actualTC->setPC(val); } - - uint64_t readNextPC() { return actualTC->readNextPC(); } - - void setNextPC(uint64_t val) { actualTC->setNextPC(val); } - - uint64_t readNextNPC() { return actualTC->readNextNPC(); } - - void setNextNPC(uint64_t val) { actualTC->setNextNPC(val); } - - uint64_t readMicroPC() { return actualTC->readMicroPC(); } - - void setMicroPC(uint64_t val) { actualTC->setMicroPC(val); } + TheISA::PCState pcState() { return actualTC->pcState(); } - uint64_t readNextMicroPC() { return actualTC->readMicroPC(); } + void pcState(const TheISA::PCState &val) { actualTC->pcState(val); } - void setNextMicroPC(uint64_t val) { actualTC->setNextMicroPC(val); } + Addr instAddr() { return actualTC->instAddr(); } + Addr nextInstAddr() { return actualTC->nextInstAddr(); } + MicroPC microPC() { return actualTC->microPC(); } bool readPredicate() { return actualTC->readPredicate(); } |