50 #include "debug/Branch.hh"
55 namespace branch_prediction
60 numThreads(params.numThreads),
62 BTB(params.BTBEntries,
67 iPred(params.indirectBranchPred),
69 instShiftAmt(params.instShiftAmt)
76 : statistics::
Group(parent),
78 "Number of BP lookups"),
80 "Number of conditional branches predicted"),
82 "Number of conditional branches incorrect"),
84 "Number of BTB lookups"),
86 "Number of BTB updates"),
87 ADD_STAT(BTBHits, statistics::units::
Count::get(),
"Number of BTB hits"),
88 ADD_STAT(BTBHitRatio, statistics::units::Ratio::get(),
"BTB Hit Ratio",
89 BTBHits / BTBLookups),
91 "Number of times the RAS was used to get a target."),
93 "Number of incorrect RAS predictions."),
95 "Number of indirect predictor lookups."),
97 "Number of indirect target hits."),
99 "Number of indirect misses."),
100 ADD_STAT(indirectMispredicted, statistics::units::
Count::get(),
101 "Number of mispredicted indirect branches.")
127 for ([[maybe_unused]]
const auto& ph :
predHist)
140 bool pred_taken =
false;
141 std::unique_ptr<PCStateBase> target(
pc.clone());
146 void *bp_history = NULL;
147 void *indirect_history = NULL;
150 DPRINTF(
Branch,
"[tid:%i] [sn:%llu] Unconditional control\n",
157 pred_taken =
lookup(tid,
pc.instAddr(), bp_history);
160 "Branch predictor predicted %i for PC %s\n",
161 tid, seqNum, pred_taken,
pc);
164 const bool orig_pred_taken = pred_taken;
170 "[tid:%i] [sn:%llu] Creating prediction history for PC %s\n",
174 bp_history, indirect_history, tid, inst);
196 DPRINTF(
Branch,
"[tid:%i] [sn:%llu] Instruction %s is a return, "
197 "RAS predicted target: %s, RAS index: %i\n",
198 tid, seqNum,
pc, *target, predict_record.
RASIndex);
210 "[tid:%i] [sn:%llu] Instruction %s was a call, adding "
211 "%s to the RAS index: %i\n",
212 tid, seqNum,
pc,
pc,
RAS[tid].topIdx());
226 "[tid:%i] [sn:%llu] Instruction %s predicted "
228 tid, seqNum,
pc, *target);
231 "valid entry\n", tid, seqNum);
240 "[tid:%i] [sn:%llu] btbUpdate "
257 "[tid:%i] [sn:%llu] Instruction %s predicted "
258 "indirect target is %s\n",
259 tid, seqNum,
pc, *target);
265 "[tid:%i] [sn:%llu] Instruction %s no indirect "
286 predict_record.
target = target->instAddr();
299 predHist[tid].push_front(predict_record);
302 "[tid:%i] [sn:%llu] History entry added. "
303 "predHist.size(): %i\n",
313 "sn:%llu]\n", tid, done_sn);
316 predHist[tid].back().seqNum <= done_sn) {
320 predHist[tid].back().bpHistory,
false,
341 while (!pred_hist.empty() &&
342 pred_hist.front().seqNum > squashed_sn) {
343 if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
346 " Call [sn:%llu] PC: %s Popping RAS\n", tid, squashed_sn,
347 pred_hist.front().seqNum, pred_hist.front().pc);
350 if (pred_hist.front().usedRAS) {
351 if (pred_hist.front().RASTarget !=
nullptr) {
353 " Restoring top of RAS to: %i,"
354 " target: %s\n", tid, squashed_sn,
355 pred_hist.front().RASIndex,
356 *pred_hist.front().RASTarget);
360 " Restoring top of RAS to: %i,"
361 " target: INVALID_TARGET\n", tid, squashed_sn,
362 pred_hist.front().RASIndex);
365 RAS[tid].restore(pred_hist.front().RASIndex,
366 pred_hist.front().RASTarget.get());
370 squash(tid, pred_hist.front().bpHistory);
376 "Removing history for [sn:%llu] "
377 "PC %#x\n", tid, squashed_sn, pred_hist.front().seqNum,
378 pred_hist.front().pc);
380 pred_hist.pop_front();
382 DPRINTF(
Branch,
"[tid:%i] [squash sn:%llu] predHist.size(): %i\n",
383 tid, squashed_sn,
predHist[tid].size());
408 DPRINTF(
Branch,
"[tid:%i] Squashing from sequence number %i, "
409 "setting target to %s\n", tid, squashed_sn, corr_target);
417 if (!pred_hist.empty()) {
419 auto hist_it = pred_hist.begin();
424 if (pred_hist.front().seqNum != squashed_sn) {
426 pred_hist.front().seqNum, squashed_sn);
428 assert(pred_hist.front().seqNum == squashed_sn);
432 if ((*hist_it).usedRAS) {
435 "[tid:%i] [squash sn:%llu] Incorrect RAS [sn:%llu]\n",
436 tid, squashed_sn, hist_it->seqNum);
449 pred_hist.front().predTaken = actually_taken;
450 pred_hist.front().target = corr_target.
instAddr();
452 update(tid, (*hist_it).pc, actually_taken,
453 pred_hist.front().bpHistory,
true, pred_hist.front().inst,
458 pred_hist.front().indirectHistory, actually_taken);
461 if (actually_taken) {
462 if (hist_it->wasReturn && !hist_it->usedRAS) {
464 "Incorrectly predicted "
465 "return [sn:%llu] PC: %#x\n", tid, squashed_sn,
469 hist_it->usedRAS =
true;
471 if (hist_it->wasIndirect) {
475 hist_it->seqNum, pred_hist.front().indirectHistory,
480 "BTB Update called for [sn:%llu] "
481 "PC %#x\n", tid, squashed_sn,
482 hist_it->seqNum, hist_it->pc);
485 BTB.
update(hist_it->pc, corr_target, tid);
489 if (hist_it->wasCall && hist_it->pushedRAS) {
492 "[tid:%i] [squash sn:%llu] "
493 "Incorrectly predicted "
494 "Call [sn:%llu] PC: %s Popping RAS\n",
496 hist_it->seqNum, hist_it->pc);
498 hist_it->pushedRAS =
false;
500 if (hist_it->usedRAS) {
502 "[tid:%i] [squash sn:%llu] Incorrectly predicted "
503 "return [sn:%llu] PC: %#x Restoring RAS\n", tid,
505 hist_it->seqNum, hist_it->pc);
507 "[tid:%i] [squash sn:%llu] Restoring top of RAS "
508 "to: %i, target: %s\n", tid, squashed_sn,
509 hist_it->RASIndex, *hist_it->RASTarget);
510 RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget.get());
511 hist_it->usedRAS =
false;
516 "update\n", tid, squashed_sn);
526 auto pred_hist_it = ph.begin();
528 cprintf(
"predHist[%i].size(): %i\n",
i++, ph.size());
530 while (pred_hist_it != ph.end()) {
531 cprintf(
"sn:%llu], PC:%#x, tid:%i, predTaken:%i, "
533 pred_hist_it->seqNum, pred_hist_it->pc,
534 pred_hist_it->tid, pred_hist_it->predTaken,
535 pred_hist_it->bpHistory);