diff options
author | Mitch Hayenga <mitch.hayenga@arm.com> | 2014-09-03 07:42:36 -0400 |
---|---|---|
committer | Mitch Hayenga <mitch.hayenga@arm.com> | 2014-09-03 07:42:36 -0400 |
commit | daedc5a49127eb91036291af1619bbc98016aff0 (patch) | |
tree | 6bf2ac8d871cd9b4c49c3aa0dc48096f76dfe427 /src/cpu/pred/bpred_unit_impl.hh | |
parent | ecd53009712da59a98ad3c13ed20aaa8e8cd7e29 (diff) | |
download | gem5-daedc5a49127eb91036291af1619bbc98016aff0.tar.xz |
cpu: Fix incorrect speculative branch predictor behavior
When a branch mispredicted gem5 would squash all history after and including
the mispredicted branch. However, the mispredicted branch is still speculative
and its history is required to rollback state if another, older, branch
mispredicts. This leads to things like RAS corruption.
Diffstat (limited to 'src/cpu/pred/bpred_unit_impl.hh')
-rw-r--r-- | src/cpu/pred/bpred_unit_impl.hh | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/src/cpu/pred/bpred_unit_impl.hh b/src/cpu/pred/bpred_unit_impl.hh index 18e221775..eaffb7ea1 100644 --- a/src/cpu/pred/bpred_unit_impl.hh +++ b/src/cpu/pred/bpred_unit_impl.hh @@ -372,8 +372,12 @@ 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. - update(predHist[tid].back().pc, predHist[tid].back().predTaken, - predHist[tid].back().bpHistory, false); + if (!predHist[tid].back().wasSquashed) { + update(predHist[tid].back().pc, predHist[tid].back().predTaken, + predHist[tid].back().bpHistory, false); + } else { + retireSquashed(predHist[tid].back().bpHistory); + } predHist[tid].pop_back(); } @@ -465,12 +469,15 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, update((*hist_it).pc, actually_taken, pred_hist.front().bpHistory, true); + hist_it->wasSquashed = true; + if (actually_taken) { if (hist_it->wasReturn && !hist_it->usedRAS) { DPRINTF(Branch, "[tid: %i] Incorrectly predicted" " return [sn:%i] PC: %s\n", tid, hist_it->seqNum, hist_it->pc); RAS[tid].pop(); + hist_it->usedRAS = true; } DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]" @@ -488,23 +495,16 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, " to: %i, target: %s.\n", tid, hist_it->RASIndex, hist_it->RASTarget); RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget); - + hist_it->usedRAS = false; } else if (hist_it->wasCall && hist_it->pushedRAS) { //Was a Call but predicated false. Pop RAS here DPRINTF(Branch, "[tid: %i] Incorrectly predicted" " Call [sn:%i] PC: %s Popping RAS\n", tid, hist_it->seqNum, hist_it->pc); RAS[tid].pop(); + hist_it->pushedRAS = false; } } - DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i]" - " PC %s Actually Taken: %i\n", tid, hist_it->seqNum, - hist_it->pc, actually_taken); - - pred_hist.erase(hist_it); - - DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n", tid, - predHist[tid].size()); } else { DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't " "update.\n", tid, squashed_sn); |