summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKorey Sewell <ksewell@umich.edu>2010-06-25 17:42:35 -0400
committerKorey Sewell <ksewell@umich.edu>2010-06-25 17:42:35 -0400
commit868181f24df3d48170a4676e9df96928a0608e40 (patch)
tree66bca2a3c6fc7366db7c470a1af563ea1e27c9e2
parent6bfd766f2c6c93cca3f79482bfddf7e6cdeb455e (diff)
downloadgem5-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.
-rw-r--r--src/cpu/inorder/resources/bpred_unit.cc25
-rw-r--r--src/cpu/inorder/resources/bpred_unit.hh5
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 {