diff options
author | Korey Sewell <ksewell@umich.edu> | 2010-06-25 17:42:35 -0400 |
---|---|---|
committer | Korey Sewell <ksewell@umich.edu> | 2010-06-25 17:42:35 -0400 |
commit | 868181f24df3d48170a4676e9df96928a0608e40 (patch) | |
tree | 66bca2a3c6fc7366db7c470a1af563ea1e27c9e2 /src | |
parent | 6bfd766f2c6c93cca3f79482bfddf7e6cdeb455e (diff) | |
download | gem5-868181f24df3d48170a4676e9df96928a0608e40.tar.xz |
inorder: Return Address Stack bug
the nextPC was getting sent to the branch predictor not the current PC, so
the RAS was returning the wrong PC and mispredicting everything.
Diffstat (limited to 'src')
-rw-r--r-- | src/cpu/inorder/resources/bpred_unit.cc | 25 | ||||
-rw-r--r-- | src/cpu/inorder/resources/bpred_unit.hh | 5 |
2 files changed, 16 insertions, 14 deletions
diff --git a/src/cpu/inorder/resources/bpred_unit.cc b/src/cpu/inorder/resources/bpred_unit.cc index 0a78e518e..b08a393f7 100644 --- a/src/cpu/inorder/resources/bpred_unit.cc +++ b/src/cpu/inorder/resources/bpred_unit.cc @@ -66,7 +66,9 @@ BPredUnit::BPredUnit(Resource *_res, ThePipeline::Params *params) } for (int i=0; i < ThePipeline::MaxThreads; i++) - RAS[i].init(params->RASSize); + RAS[i].init(params->RASSize); + + instSize = sizeof(TheISA::MachInst); } std::string @@ -147,7 +149,7 @@ BPredUnit::takeOverFrom() bool -BPredUnit::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) +BPredUnit::predict(DynInstPtr &inst, Addr &pred_PC, ThreadID tid) { // See if branch predictor predicts taken. // If so, get its target addr either from the BTB or the RAS. @@ -183,14 +185,14 @@ BPredUnit::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) } else { ++condPredicted; - pred_taken = BPLookup(PC, bp_history); + pred_taken = BPLookup(pred_PC, bp_history); DPRINTF(InOrderBPred, "[tid:%i]: Branch predictor predicted %i " "for PC %#x\n", tid, pred_taken, inst->readPC()); } - PredictorHistory predict_record(inst->seqNum, PC, pred_taken, + PredictorHistory predict_record(inst->seqNum, pred_PC, pred_taken, bp_history, tid); // Now lookup in the BTB or RAS. @@ -218,10 +220,11 @@ BPredUnit::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) ++BTBLookups; if (inst->isCall()) { + #if ISA_HAS_DELAY_SLOT - Addr ras_pc = PC + (2 * sizeof(MachInst)); // Next Next PC + Addr ras_pc = pred_PC + instSize; // Next Next PC #else - Addr ras_pc = PC + sizeof(MachInst); // Next PC + Addr ras_pc = pred_PC; // Next PC #endif RAS[tid].push(ras_pc); @@ -243,11 +246,11 @@ BPredUnit::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) DPRINTF(InOrderBPred, "[tid:%i]: Setting %#x predicted" " target to %#x.\n", tid, inst->readPC(), target); - } else if (BTB.valid(PC, asid)) { + } else if (BTB.valid(pred_PC, asid)) { ++BTBHits; // If it's not a return, use the BTB to get the target addr. - target = BTB.lookup(PC, asid); + target = BTB.lookup(pred_PC, asid); DPRINTF(InOrderBPred, "[tid:%i]: [asid:%i] Instruction %#x " "predicted target is %#x.\n", @@ -262,16 +265,14 @@ BPredUnit::predict(DynInstPtr &inst, Addr &PC, ThreadID tid) if (pred_taken) { // Set the PC and the instruction's predicted target. - PC = target; - inst->setPredTarg(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. - PC = PC + sizeof(MachInst); + pred_PC = pred_PC + instSize; #endif - inst->setPredTarg(PC); } predHist[tid].push_front(predict_record); diff --git a/src/cpu/inorder/resources/bpred_unit.hh b/src/cpu/inorder/resources/bpred_unit.hh index 8f4ef593d..881bfcc95 100644 --- a/src/cpu/inorder/resources/bpred_unit.hh +++ b/src/cpu/inorder/resources/bpred_unit.hh @@ -83,11 +83,11 @@ 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 PC The predicted PC is passed back through this parameter. + * @param pred_PC 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 &PC, ThreadID tid); + bool predict(ThePipeline::DynInstPtr &inst, Addr &pred_PC, ThreadID tid); // @todo: Rename this function. void BPUncond(void * &bp_history); @@ -173,6 +173,7 @@ class BPredUnit void dump(); private: + int instSize; Resource *res; struct PredictorHistory { |