gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
bpred_unit.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011-2012, 2014 ARM Limited
3 * Copyright (c) 2010,2022-2023 The University of Edinburgh
4 * Copyright (c) 2012 Mark D. Hill and David A. Wood
5 * All rights reserved
6 *
7 * The license below extends only to copyright in the software and shall
8 * not be construed as granting a license to any other intellectual
9 * property including but not limited to intellectual property relating
10 * to a hardware implementation of the functionality of the software
11 * licensed hereunder. You may use the software subject to the license
12 * terms below provided that you ensure that this notice is replicated
13 * unmodified and in its entirety in all distributions of the software,
14 * modified or unmodified, in source code or in binary form.
15 *
16 * Copyright (c) 2004-2005 The Regents of The University of Michigan
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met: redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer;
23 * redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution;
26 * neither the name of the copyright holders nor the names of its
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
44
45#include <algorithm>
46
48#include "base/compiler.hh"
49#include "base/trace.hh"
50#include "debug/Branch.hh"
51
52namespace gem5
53{
54
55namespace branch_prediction
56{
57
67
68
71{
73 ptr.reset(new probing::PMU(getProbeManager(), name));
74
75 return ptr;
76}
77
78void
80{
81 ppBranches = pmuProbePoint("Branches");
82 ppMisses = pmuProbePoint("Misses");
83}
84
85void
87{
88 // We shouldn't have any outstanding requests when we resume from
89 // a drained system.
90 for ([[maybe_unused]] const auto& ph : predHist)
91 assert(ph.empty());
92}
93
94
95bool
96BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
98{
100 PredictorHistory* bpu_history = nullptr;
101 bool taken = predict(inst, seqNum, pc, tid, bpu_history);
102
103 assert(bpu_history!=nullptr);
104
106 predHist[tid].push_front(bpu_history);
107
108 DPRINTF(Branch, "[tid:%i] [sn:%llu] History entry added. "
109 "predHist.size(): %i\n", tid, seqNum, predHist[tid].size());
110
111 return taken;
112}
113
114void
116{
117 predHist[tid].push_front(bpu_history);
118}
119
120bool
121BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
123{
124 assert(hist == nullptr);
125
126
127 // See if branch predictor predicts taken.
128 // If so, get its target addr either from the BTB or the RAS.
129 // Save off branch stuff into `hist` so we can correct the predictor
130 // if prediction was wrong.
131
132 BranchType brType = getBranchType(inst);
133 hist = new PredictorHistory(tid, seqNum, pc.instAddr(), inst);
134
135 stats.lookups[tid][brType]++;
136 ppBranches->notify(1);
137
138
139 /* -----------------------------------------------
140 * Get branch direction
141 * -----------------------------------------------
142 * Lookup the direction predictor for every
143 * conditional branch. For unconditional branches
144 * the direction is always taken
145 */
146
147 if (hist->uncond) {
148 // Unconditional branches -----
149 hist->condPred = true;
150 } else {
151 // Conditional branches -------
152 ++stats.condPredicted;
153 hist->condPred = cPred->lookup(tid, pc.instAddr(), hist->bpHistory);
154
155 if (hist->condPred) {
156 ++stats.condPredictedTaken;
157 }
158 }
159 hist->predTaken = hist->condPred;
160
162 "[tid:%i, sn:%llu] Branch predictor predicted %i for PC:%#x %s\n",
163 tid, seqNum, hist->condPred, hist->pc, toString(brType));
164
165
166 // The direction is done now get the target address
167 // from BTB, RAS or indirect predictor.
168 hist->targetProvider = TargetProvider::NoTarget;
169
170 /* -----------------------------------------------
171 * Branch Target Buffer (BTB)
172 * -----------------------------------------------
173 * First check for a BTB hit. This will be done
174 * regardless of whether the RAS or the indirect
175 * predictor provide the final target. That is
176 * necessary as modern front-end does not have a
177 * chance to detect a branch without a BTB hit.
178 */
179 stats.BTBLookups++;
180 const PCStateBase * btb_target = btb->lookup(tid, pc.instAddr(), brType);
181 if (btb_target) {
182 stats.BTBHits++;
183 hist->btbHit = true;
184
185 if (hist->predTaken) {
186 hist->targetProvider = TargetProvider::BTB;
187 set(hist->target, btb_target);
188 }
189 }
190
191 DPRINTF(Branch, "[tid:%i, sn:%llu] PC:%#x BTB:%s\n",
192 tid, seqNum, hist->pc, (hist->btbHit) ? "hit" : "miss");
193
194
195 // In a high performance CPU there is no other way than a BTB hit
196 // to know about a branch instruction. In that case consolidate
197 // indirect and RAS predictor only if there was a BTB it.
198 // For low end CPUs predecoding might be used to identify branches.
199 const bool branch_detected = (hist->btbHit || !requiresBTBHit);
200
201
202 /* -----------------------------------------------
203 * Return Address Stack (RAS)
204 * -----------------------------------------------
205 * Perform RAS operations for calls and returns.
206 * Calls: push their RETURN address onto
207 * the RAS.
208 * Return: pop the the return address from the
209 * top of the RAS.
210 */
211 if (ras && branch_detected) {
212 if (inst->isCall()) {
213 // In case of a call build the return address and
214 // push it to the RAS.
215 auto return_addr = inst->buildRetPC(pc, pc);
216 ras->push(tid, *return_addr, hist->rasHistory);
217
218 DPRINTF(Branch, "[tid:%i] [sn:%llu] Instr. %s was "
219 "a call, push return address %s onto the RAS\n",
220 tid, seqNum, pc, *return_addr);
221
222 }
223 else if (inst->isReturn()) {
224
225 // If it's a return from a function call, then look up the
226 // RETURN address in the RAS.
227 const PCStateBase *return_addr = ras->pop(tid, hist->rasHistory);
228 if (return_addr) {
229
230 // Set the target to the return address
231 set(hist->target, *return_addr);
232 hist->targetProvider = TargetProvider::RAS;
233
234 DPRINTF(Branch, "[tid:%i] [sn:%llu] Instr. %s is a "
235 "return, RAS poped return addr: %s\n",
236 tid, seqNum, pc, *hist->target);
237 }
238 }
239 }
240
241
242 /* -----------------------------------------------
243 * Indirect Predictor
244 * -----------------------------------------------
245 * For indirect branches/calls check the indirect
246 * predictor if one is available. Not for returns.
247 * Note that depending on the implementation a
248 * indirect predictor might only return a target
249 * for an indirect branch with a changing target.
250 * As most indirect branches have a static target
251 * using the target from the BTB is the optimal
252 * to save space in the indirect predictor itself.
253 */
254 if (iPred && hist->predTaken && branch_detected &&
255 inst->isIndirectCtrl() && !inst->isReturn()) {
256
257 ++stats.indirectLookups;
258
259 std::unique_ptr<const PCStateBase> itarget(
260 iPred->lookup(tid, seqNum, pc.instAddr(),
261 hist->indirectHistory));
262
263 if (itarget) {
264 // Indirect predictor hit
265 ++stats.indirectHits;
266 hist->targetProvider = TargetProvider::Indirect;
267 set(hist->target, *itarget);
268
270 "[tid:%i, sn:%llu] Instruction %s predicted "
271 "indirect target is %s\n",
272 tid, seqNum, pc, *hist->target);
273 } else {
274 ++stats.indirectMisses;
276 "[tid:%i, sn:%llu] PC:%#x no indirect target\n",
277 tid, seqNum, pc.instAddr());
278 }
279 }
280
281
289 if (hist->targetProvider == TargetProvider::NoTarget) {
290 set(hist->target, pc);
291 inst->advancePC(*hist->target);
292 hist->predTaken = false;
293 }
294 stats.targetProvider[tid][hist->targetProvider]++;
295
296 // The actual prediction is done.
297 // For now the BPU assume its correct. The update
298 // functions will correct the branch if needed.
299 // If prediction and actual direction are the same
300 // at commit the prediction was correct.
301 hist->actuallyTaken = hist->predTaken;
302 set(pc, *hist->target);
303
304 DPRINTF(Branch, "%s(tid:%i, sn:%i, PC:%#x, %s) -> taken:%i, target:%s "
305 "provider:%s\n", __func__, tid, seqNum, hist->pc,
306 toString(brType), hist->predTaken, *hist->target,
307 enums::TargetProviderStrings[hist->targetProvider]);
308
309
320 cPred->updateHistories(tid, hist->pc, hist->uncond, hist->predTaken,
321 hist->target->instAddr(), hist->inst,
322 hist->bpHistory);
323
324
325 if (iPred) {
326 // Update the indirect predictor with the direction prediction
327 iPred->update(tid, seqNum, hist->pc, false, hist->predTaken,
328 *hist->target, brType, hist->indirectHistory);
329 }
330
331 return hist->predTaken;
332}
333
334
335void
337{
338 DPRINTF(Branch, "[tid:%i] Committing branches until "
339 "[sn:%llu]\n", tid, done_sn);
340
341 while (!predHist[tid].empty() &&
342 predHist[tid].back()->seqNum <= done_sn) {
343
344 // Iterate from the back to front. Least recent
345 // sequence number until the most recent done number
346 commitBranch(tid, *predHist[tid].rbegin());
347
348 delete predHist[tid].back();
349 predHist[tid].pop_back();
350 DPRINTF(Branch, "[tid:%i] [commit sn:%llu] pred_hist.size(): %i\n",
351 tid, done_sn, predHist[tid].size());
352 }
353}
354
355void
357{
358
359 stats.committed[tid][hist->type]++;
360 if (hist->mispredict) {
361 stats.mispredicted[tid][hist->type]++;
362 // stats for identifying miss-prediction due to BTB or predictor
363 if (hist->actuallyTaken && !hist->btbHit) {
364 stats.mispredictDueToBTBMiss[tid][hist->type]++;
365 } else {
366 stats.mispredictDueToPredictor[tid][hist->type]++;
367 }
368 ++stats.condIncorrect;
369 ppMisses->notify(1);
370 }
371
372
373 DPRINTF(Branch, "Commit branch: sn:%llu, PC:%#x %s, "
374 "pred:%i, taken:%i, target:%#x\n",
375 hist->seqNum, hist->pc, toString(hist->type),
376 hist->predTaken, hist->actuallyTaken,
377 hist->target->instAddr());
378
379 // Update the branch predictor with the correct results.
380 cPred->update(tid, hist->pc, hist->actuallyTaken, hist->bpHistory, false,
381 hist->inst, hist->target->instAddr());
382
383 // Commit also Indirect predictor and RAS
384 if (iPred) {
385 iPred->commit(tid, hist->seqNum,
386 hist->indirectHistory);
387 }
388
389 if (ras) {
390 ras->commit(tid, hist->mispredict,
391 hist->type,
392 hist->rasHistory);
393 }
394
395 // Correct BTB (at commit) -------------------------------------
396 // Update the BTB for all committed taken branches.
397 if (hist->actuallyTaken && !updateBTBAtSquash) { updateBTB(tid, hist); }
398}
399
400
401
402void
403BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
404{
405
406 while (!predHist[tid].empty() &&
407 predHist[tid].front()->seqNum > squashed_sn) {
408
409 auto hist = predHist[tid].front();
410
412 "[tid:%i, squash sn:%llu] Removing history for "
413 "sn:%llu, PC:%#x\n",
414 tid, squashed_sn, hist->seqNum, hist->pc);
415
416 squashHistory(tid, hist);
417
418 predHist[tid].pop_front();
419
420 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] pred_hist.size(): %i\n",
421 tid, squashed_sn, predHist[tid].size());
422 }
423}
424
425
426
427void
429{
430
431 stats.squashes[tid][history->type]++;
432 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect: %s\n",
433 tid, history->seqNum,
434 toString(history->type));
435
436
437 if (history->rasHistory) {
438 assert(ras);
439
440 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect call/return "
441 "PC %#x. Fix RAS.\n", tid, history->seqNum,
442 history->pc);
443
444 ras->squash(tid, history->rasHistory);
445 }
446
447 if (iPred) {
448 iPred->squash(tid, history->seqNum,
449 history->indirectHistory);
450 }
451
452 // This call will delete the bpHistory.
453 cPred->squash(tid, history->bpHistory);
454
455 delete history;
456 history = nullptr;
457}
458
459
460void
461BPredUnit::squash(const InstSeqNum &squashed_sn,
462 const PCStateBase &corr_target,
463 bool actually_taken, ThreadID tid, bool from_commit)
464{
465 // Now that we know that a branch was mispredicted, we need to undo
466 // all the branches that have been seen up until this branch and
467 // fix up everything.
468 // NOTE: This should be call conceivably in 2 scenarios:
469 // (1) After an branch is executed, it updates its status in the ROB
470 // The commit stage then checks the ROB update and sends a signal to
471 // the fetch stage to squash history after the mispredict
472 // (2) In the decode stage, you can find out early if a unconditional
473 // PC-relative, branch was predicted incorrectly. If so, a signal
474 // to the fetch stage is sent to squash history after the mispredict
475
476 DPRINTF(Branch, "[tid:%i] Squash from %s start from sequence number %i, "
477 "setting target to %s\n", tid, from_commit ? "commit" : "decode",
478 squashed_sn, corr_target);
479
480 // dump();
481
482 // Squash All Branches AFTER this mispredicted branch
483 // First the Prefetch history then the main history.
484 squash(squashed_sn, tid);
485
486 // If there's a squash due to a syscall, there may not be an entry
487 // corresponding to the squash. In that case, don't bother trying to
488 // fix up the entry.
489 if (!predHist[tid].empty()) {
490
491 PredictorHistory *hist = predHist[tid].front();
492
493 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Mispredicted: %s, PC:%#x\n",
494 tid, squashed_sn, toString(hist->type), hist->pc);
495
496 // Update stats
497 stats.corrected[tid][hist->type]++;
498 if (hist->target &&
499 (hist->target->instAddr() != corr_target.instAddr())) {
500 stats.targetWrong[tid][hist->targetProvider]++;
501 }
502
503 // If the squash is comming from decode it can be
504 // redirected earlier. Note that this branch might never get
505 // committed as a preceeding branch was mispredicted
506 if (!from_commit) {
507 stats.earlyResteers[tid][hist->type]++;
508 }
509
510
511 // There are separate functions for in-order and out-of-order
512 // branch prediction, but not for update. Therefore, this
513 // call should take into account that the mispredicted branch may
514 // be on the wrong path (i.e., OoO execution), and that the counter
515 // counter table(s) should not be updated. Thus, this call should
516 // restore the state of the underlying predictor, for instance the
517 // local/global histories. The counter tables will be updated when
518 // the branch actually commits.
519
520 // Remember the correct direction and target for the update at commit.
521 hist->mispredict = true;
522 hist->actuallyTaken = actually_taken;
523 set(hist->target, corr_target);
524
525 // Correct Direction predictor ------------------
526 cPred->update(tid, hist->pc, actually_taken, hist->bpHistory,
527 true, hist->inst, corr_target.instAddr());
528
529
530 // Correct Indirect predictor -------------------
531 if (iPred) {
532 iPred->update(tid, squashed_sn, hist->pc,
533 true, actually_taken, corr_target,
534 hist->type, hist->indirectHistory);
535 }
536
537 // Correct RAS ---------------------------------
538 if (ras) {
539 // The branch was taken and the RAS was not updated.
540 // In case of call or return that needs to be fixed.
541 if (actually_taken && (hist->rasHistory == nullptr)) {
542
543 // A return has not poped the RAS.
544 if (hist->type == BranchType::Return) {
545 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] "
546 "Incorrectly predicted return [sn:%llu] PC: %#x\n",
547 tid, squashed_sn, hist->seqNum, hist->pc);
548
549 ras->pop(tid, hist->rasHistory);
550 }
551
552 // A call has not pushed a return address to the RAS.
553 if (hist->call) {
554 // In case of a call build the return address and
555 // push it to the RAS.
556 auto return_addr = hist->inst->buildRetPC(
557 corr_target, corr_target);
558
559 if (hist->inst->size()) {
560 return_addr->set(hist->pc + hist->inst->size());
561 }
562
563 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] "
564 "Incorrectly predicted call: [sn:%llu,PC:%#x] "
565 " Push return address %s onto RAS\n", tid,
566 squashed_sn, hist->seqNum, hist->pc,
567 *return_addr);
568 ras->push(tid, *return_addr, hist->rasHistory);
569 }
570
571 // The branch was not taken but the RAS modified.
572 } else if (!actually_taken && (hist->rasHistory != nullptr)) {
573 // The branch was not taken but the RAS was modified.
574 // Needs to be fixed.
575 ras->squash(tid, hist->rasHistory);
576 }
577 }
578
579 // Correct BTB (at squash) -------------------------------------
580 // Update the BTB for all mispredicted taken branches.
581 if (actually_taken && updateBTBAtSquash) { updateBTB(tid, hist); }
582
583 } else {
585 "[tid:%i] [sn:%llu] predHist empty, can't "
586 "update\n",
587 tid, squashed_sn);
588 }
589}
590
591void
593{
594 // If a BTB hit is not required to identify branches
595 // (requiresBTBHit=False) we will not install `returns`
596 // and `indirect` branchee into the BTB.
597 if (!requiresBTBHit) {
598 if (hist->inst->isReturn()) return;
599 // For indirect branches we do install them if there is no
600 // indirector available
601 if (iPred && hist->inst->isIndirectCtrl()) return;
602 }
603
604 DPRINTF(Branch, "[tid:%i] BTB Update for [sn:%llu] PC %#x -> T:%#x\n", tid,
605 hist->seqNum, hist->pc, hist->target->instAddr());
606
607 if (!hist->btbHit) {
608 ++stats.BTBMispredicted;
609 if (hist->condPred) ++stats.predTakenBTBMiss;
610 }
611
612 stats.BTBUpdates++;
613 btb->update(tid, hist->pc, *hist->target, hist->type, hist->inst);
614 btb->incorrectTarget(hist->pc, hist->type);
615}
616
617void
619 bool uncond, void * &bp_history)
620{
621 // Delegate to conditional predictor
622 cPred->branchPlaceholder(tid, pc, uncond, bp_history);
623}
624
625void
627{
628 int i = 0;
629 for (const auto& ph : predHist) {
630 if (!ph.empty()) {
631 auto hist = ph.begin();
632
633 cprintf("predHist[%i].size(): %i\n", i++, ph.size());
634
635 while (hist != ph.end()) {
636 cprintf("sn:%llu], PC:%#x, tid:%i, predTaken:%i, "
637 "bpHistory:%#x, rasHistory:%#x\n",
638 (*hist)->seqNum, (*hist)->pc,
639 (*hist)->tid, (*hist)->predTaken,
640 (*hist)->bpHistory, (*hist)->rasHistory);
641 hist++;
642 }
643
644 cprintf("\n");
645 }
646 }
647}
648
649
651 : statistics::Group(bp),
652 ADD_STAT(lookups, statistics::units::Count::get(),
653 "Number of BP lookups"),
654 ADD_STAT(squashes, statistics::units::Count::get(),
655 "Number of branches that got squashed (completely removed) as "
656 "an earlier branch was mispredicted."),
657 ADD_STAT(corrected, statistics::units::Count::get(),
658 "Number of branches that got corrected but not yet commited. "
659 "Branches get corrected by decode or after execute. Also a "
660 "branch misprediction can be detected out-of-order. Therefore, "
661 "a corrected branch might not end up beeing committed in case "
662 "an even earlier branch was mispredicted"),
663 ADD_STAT(earlyResteers, statistics::units::Count::get(),
664 "Number of branches that got redirected after decode."),
665 ADD_STAT(committed, statistics::units::Count::get(),
666 "Number of branches finally committed "),
667 ADD_STAT(mispredicted, statistics::units::Count::get(),
668 "Number of committed branches that were mispredicted."),
670 "Number of committed branches that were mispredicted by the "
671 "predictor."),
673 "Number of committed branches that were mispredicted because of "
674 "a BTB miss."),
675 ADD_STAT(targetProvider, statistics::units::Count::get(),
676 "The component providing the target for taken branches"),
677 ADD_STAT(targetWrong, statistics::units::Count::get(),
678 "Number of branches where the target was incorrect or not "
679 "available at prediction time."),
680 ADD_STAT(condPredicted, statistics::units::Count::get(),
681 "Number of conditional branches predicted"),
683 "Number of conditional branches predicted as taken"),
684 ADD_STAT(condIncorrect, statistics::units::Count::get(),
685 "Number of conditional branches incorrect"),
687 "Number of branches predicted taken but missed in BTB"),
688 ADD_STAT(BTBLookups, statistics::units::Count::get(),
689 "Number of BTB lookups"),
690 ADD_STAT(BTBUpdates, statistics::units::Count::get(),
691 "Number of BTB updates"),
692 ADD_STAT(BTBHits, statistics::units::Count::get(),
693 "Number of BTB hits"),
694 ADD_STAT(BTBHitRatio, statistics::units::Ratio::get(), "BTB Hit Ratio",
697 "Number BTB mispredictions. No target found or target wrong"),
699 "Number of indirect predictor lookups."),
700 ADD_STAT(indirectHits, statistics::units::Count::get(),
701 "Number of indirect target hits."),
702 ADD_STAT(indirectMisses, statistics::units::Count::get(),
703 "Number of indirect misses."),
705 "Number of mispredicted indirect branches.")
706
707{
708 using namespace statistics;
709 BTBHitRatio.precision(6);
710
711 lookups
712 .init(bp->numThreads, enums::Num_BranchType)
713 .flags(total | pdf);
714 lookups.ysubnames(enums::BranchTypeStrings);
715
717 .init(bp->numThreads, enums::Num_BranchType)
718 .flags(total | pdf);
719 squashes.ysubnames(enums::BranchTypeStrings);
720
722 .init(bp->numThreads, enums::Num_BranchType)
723 .flags(total | pdf);
724 corrected.ysubnames(enums::BranchTypeStrings);
725
727 .init(bp->numThreads, enums::Num_BranchType)
728 .flags(total | pdf);
729 earlyResteers.ysubnames(enums::BranchTypeStrings);
730
732 .init(bp->numThreads, enums::Num_BranchType)
733 .flags(total | pdf);
734 committed.ysubnames(enums::BranchTypeStrings);
735
737 .init(bp->numThreads, enums::Num_BranchType)
738 .flags(total | pdf);
739 mispredicted.ysubnames(enums::BranchTypeStrings);
740
742 .init(bp->numThreads, enums::Num_BranchType)
743 .flags(total | pdf);
744 mispredictDueToPredictor.ysubnames(enums::BranchTypeStrings);
745
747 .init(bp->numThreads, enums::Num_BranchType)
748 .flags(total | pdf);
749 mispredictDueToBTBMiss.ysubnames(enums::BranchTypeStrings);
750
752 .init(bp->numThreads, enums::Num_TargetProvider)
753 .flags(total | pdf);
754 targetProvider.ysubnames(enums::TargetProviderStrings);
755
757 .init(bp->numThreads, enums::Num_BranchType)
758 .flags(total | pdf);
759 targetWrong.ysubnames(enums::BranchTypeStrings);
760
761}
762
763} // namespace branch_prediction
764} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
virtual std::string name() const
Definition named.hh:60
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition pcstate.hh:108
Base class for branch operations.
Definition branch.hh:49
virtual std::unique_ptr< PCStateBase > buildRetPC(const PCStateBase &cur_pc, const PCStateBase &call_pc) const
virtual void advancePC(PCStateBase &pc_state) const =0
size_t size() const
bool isReturn() const
bool isIndirectCtrl() const
bool isCall() const
std::vector< std::deque< PredictorHistory * > > predHist
The per-thread predictor history.
probing::PMUUPtr pmuProbePoint(const char *name)
Helper method to instantiate probe points belonging to this object.
Definition bpred_unit.cc:70
void update(const InstSeqNum &done_sn, ThreadID tid)
Tells the branch predictor to commit any updates until the given sequence number.
BPredUnit(const Params &p)
Branch Predictor Unit (BPU) interface functions.
Definition bpred_unit.cc:58
bool predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, PCStateBase &pc, ThreadID tid)
Predicts whether or not the instruction is a taken branch, and the target of the branch if it is take...
Definition bpred_unit.cc:96
ConditionalPredictor * cPred
The conditional branch predictor.
void branchPlaceholder(ThreadID tid, Addr pc, bool uncond, void *&bp_history)
Special function for the decoupled front-end.
probing::PMUUPtr ppMisses
Miss-predicted branches.
const bool requiresBTBHit
Requires the BTB to hit for returns and indirect branches.
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition bpred_unit.cc:86
IndirectPredictor * iPred
The indirect target predictor.
void commitBranch(ThreadID tid, PredictorHistory *&bpu_history)
Commit a particular branch.
probing::PMUUPtr ppBranches
Branches seen by the branch predictor.
void regProbePoints() override
Register probe points for this object.
Definition bpred_unit.cc:79
void insertPredictorHistory(ThreadID tid, PredictorHistory *&bpu_history)
Pushes a PredictorHistory object into the branch predictor history queue.
const unsigned numThreads
Number of the threads for which the branch history is maintained.
const unsigned instShiftAmt
Number of bits to shift instructions by for predictor addresses.
BranchPredictorParams Params
Definition bpred_unit.hh:73
void squashHistory(ThreadID tid, PredictorHistory *&bpu_history)
Squashes a particular branch instance.
const bool updateBTBAtSquash
Update the BTB at squash time instead of commit.
ReturnAddrStack * ras
The return address stack.
void squash(const InstSeqNum &squashed_sn, ThreadID tid)
Squashes all outstanding updates until a given sequence number.
gem5::branch_prediction::BPredUnit::BPredUnitStats stats
BranchTargetBuffer * btb
The BTB.
void updateBTB(ThreadID tid, PredictorHistory *&bpu_history)
Update the BTB with the correct target of a branch.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
const Params & params() const
SimObject(const Params &p)
Definition sim_object.cc:58
ProbeManager * getProbeManager()
Get the probe manager for this object.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
Bitfield< 4 > pc
std::string toString(BranchType type)
BranchType getBranchType(StaticInstPtr inst)
enums::BranchType BranchType
std::unique_ptr< PMU > PMUUPtr
Definition pmu.hh:60
ProbePointArg< uint64_t > PMU
PMU probe point.
Definition pmu.hh:59
Units for Stats.
Definition units.hh:113
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition info.hh:61
const FlagsType total
Print the total.
Definition info.hh:59
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
void cprintf(const char *format, const Args &...args)
Definition cprintf.hh:155
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
RefCountingPtr< StaticInst > StaticInstPtr
uint64_t InstSeqNum
Definition inst_seq.hh:40
statistics::Scalar indirectLookups
Indirect stats.
statistics::Vector2d lookups
Stats per branch type.
statistics::Vector2d targetProvider
Target prediction per branch type.
statistics::Scalar condPredicted
Additional scalar stats for conditional branches.
Branch Predictor Unit (BPU) history object PredictorHistory This class holds all information needed t...
InstSeqNum seqNum
The sequence number for the predictor history entry.
bool predTaken
Whether or not it was predicted taken.
bool condPred
The prediction of the conditional predictor.
void * bpHistory
Pointer to the history objects passed back from the branch predictor subcomponents.
const Addr pc
The PC associated with the sequence number.
const bool call
Whether or not the instruction was a call.
const StaticInstPtr inst
The branch instrction.
bool actuallyTaken
To record the actual outcome of the branch.
bool mispredict
The branch was corrected hence was mispredicted.
const bool uncond
Was unconditional control.
const BranchType type
The type of the branch.
bool btbHit
Was BTB hit at prediction time.
std::unique_ptr< PCStateBase > target
The predicted target.
TargetProvider targetProvider
Which component provided the target.

Generated on Mon Oct 27 2025 04:13:00 for gem5 by doxygen 1.14.0