gem5 [DEVELOP-FOR-25.0]
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
70
71
74{
76 ptr.reset(new probing::PMU(getProbeManager(), name));
77
78 return ptr;
79}
80
81void
83{
84 ppBranches = pmuProbePoint("Branches");
85 ppMisses = pmuProbePoint("Misses");
86}
87
88void
90{
91 // We shouldn't have any outstanding requests when we resume from
92 // a drained system.
93 for ([[maybe_unused]] const auto& ph : predHist)
94 assert(ph.empty());
95}
96
97void
99 bool uncond, void * &bp_history)
100{
101 panic("BPredUnit::branchPlaceholder() not implemented for this BP.\n");
102}
103
104bool
105BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
106 PCStateBase &pc, ThreadID tid)
107{
109 PredictorHistory* bpu_history = nullptr;
110 bool taken = predict(inst, seqNum, pc, tid, bpu_history);
111
112 assert(bpu_history!=nullptr);
113
115 predHist[tid].push_front(bpu_history);
116
117 DPRINTF(Branch, "[tid:%i] [sn:%llu] History entry added. "
118 "predHist.size(): %i\n", tid, seqNum, predHist[tid].size());
119
120 return taken;
121}
122
123
124
125
126bool
127BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
129{
130 assert(hist == nullptr);
131
132
133 // See if branch predictor predicts taken.
134 // If so, get its target addr either from the BTB or the RAS.
135 // Save off branch stuff into `hist` so we can correct the predictor
136 // if prediction was wrong.
137
138 BranchType brType = getBranchType(inst);
139 hist = new PredictorHistory(tid, seqNum, pc.instAddr(), inst);
140
141 stats.lookups[tid][brType]++;
142 ppBranches->notify(1);
143
144
145 /* -----------------------------------------------
146 * Get branch direction
147 * -----------------------------------------------
148 * Lookup the direction predictor for every
149 * conditional branch. For unconditional branches
150 * the direction is always taken
151 */
152
153 if (inst->isUncondCtrl()) {
154 // Unconditional branches -----
155 hist->condPred = true;
156 } else {
157 // Conditional branches -------
158 ++stats.condPredicted;
159 hist->condPred = lookup(tid, pc.instAddr(), hist->bpHistory);
160
161 if (hist->condPred) {
162 ++stats.condPredictedTaken;
163 }
164 }
165 hist->predTaken = hist->condPred;
166
168 "[tid:%i, sn:%llu] Branch predictor predicted %i for PC:%#x %s\n",
169 tid, seqNum, hist->condPred, hist->pc, toString(brType));
170
171
172 // The direction is done now get the target address
173 // from BTB, RAS or indirect predictor.
174 hist->targetProvider = TargetProvider::NoTarget;
175
176 /* -----------------------------------------------
177 * Branch Target Buffer (BTB)
178 * -----------------------------------------------
179 * First check for a BTB hit. This will be done
180 * regardless of whether the RAS or the indirect
181 * predictor provide the final target. That is
182 * necessary as modern front-end does not have a
183 * chance to detect a branch without a BTB hit.
184 */
185 stats.BTBLookups++;
186 const PCStateBase * btb_target = btb->lookup(tid, pc.instAddr(), brType);
187 if (btb_target) {
188 stats.BTBHits++;
189 hist->btbHit = true;
190
191 if (hist->predTaken) {
192 hist->targetProvider = TargetProvider::BTB;
193 set(hist->target, btb_target);
194 }
195 }
196
197 DPRINTF(Branch, "[tid:%i, sn:%llu] PC:%#x BTB:%s\n",
198 tid, seqNum, hist->pc, (hist->btbHit) ? "hit" : "miss");
199
200
201 // In a high performance CPU there is no other way than a BTB hit
202 // to know about a branch instruction. In that case consolidate
203 // indirect and RAS predictor only if there was a BTB it.
204 // For low end CPUs predecoding might be used to identify branches.
205 const bool branch_detected = (hist->btbHit || !requiresBTBHit);
206
207
208 /* -----------------------------------------------
209 * Return Address Stack (RAS)
210 * -----------------------------------------------
211 * Perform RAS operations for calls and returns.
212 * Calls: push their RETURN address onto
213 * the RAS.
214 * Return: pop the the return address from the
215 * top of the RAS.
216 */
217 if (ras && branch_detected) {
218 if (inst->isCall()) {
219 // In case of a call build the return address and
220 // push it to the RAS.
221 auto return_addr = inst->buildRetPC(pc, pc);
222 ras->push(tid, *return_addr, hist->rasHistory);
223
224 DPRINTF(Branch, "[tid:%i] [sn:%llu] Instr. %s was "
225 "a call, push return address %s onto the RAS\n",
226 tid, seqNum, pc, *return_addr);
227
228 }
229 else if (inst->isReturn()) {
230
231 // If it's a return from a function call, then look up the
232 // RETURN address in the RAS.
233 const PCStateBase *return_addr = ras->pop(tid, hist->rasHistory);
234 if (return_addr) {
235
236 // Set the target to the return address
237 set(hist->target, *return_addr);
238 hist->targetProvider = TargetProvider::RAS;
239
240 DPRINTF(Branch, "[tid:%i] [sn:%llu] Instr. %s is a "
241 "return, RAS poped return addr: %s\n",
242 tid, seqNum, pc, *hist->target);
243 }
244 }
245 }
246
247
248 /* -----------------------------------------------
249 * Indirect Predictor
250 * -----------------------------------------------
251 * For indirect branches/calls check the indirect
252 * predictor if one is available. Not for returns.
253 * Note that depending on the implementation a
254 * indirect predictor might only return a target
255 * for an indirect branch with a changing target.
256 * As most indirect branches have a static target
257 * using the target from the BTB is the optimal
258 * to save space in the indirect predictor itself.
259 */
260 if (iPred && hist->predTaken && branch_detected &&
261 inst->isIndirectCtrl() && !inst->isReturn()) {
262
263 ++stats.indirectLookups;
264
265 std::unique_ptr<const PCStateBase> itarget(
266 iPred->lookup(tid, seqNum, pc.instAddr(),
267 hist->indirectHistory));
268
269 if (itarget) {
270 // Indirect predictor hit
271 ++stats.indirectHits;
272 hist->targetProvider = TargetProvider::Indirect;
273 set(hist->target, *itarget);
274
276 "[tid:%i, sn:%llu] Instruction %s predicted "
277 "indirect target is %s\n",
278 tid, seqNum, pc, *hist->target);
279 } else {
280 ++stats.indirectMisses;
282 "[tid:%i, sn:%llu] PC:%#x no indirect target\n",
283 tid, seqNum, pc.instAddr());
284 }
285 }
286
287
295 if (hist->targetProvider == TargetProvider::NoTarget) {
296 set(hist->target, pc);
297 inst->advancePC(*hist->target);
298 hist->predTaken = false;
299 }
300 stats.targetProvider[tid][hist->targetProvider]++;
301
302 // The actual prediction is done.
303 // For now the BPU assume its correct. The update
304 // functions will correct the branch if needed.
305 // If prediction and actual direction are the same
306 // at commit the prediction was correct.
307 hist->actuallyTaken = hist->predTaken;
308 set(pc, *hist->target);
309
310 DPRINTF(Branch, "%s(tid:%i, sn:%i, PC:%#x, %s) -> taken:%i, target:%s "
311 "provider:%s\n", __func__, tid, seqNum, hist->pc,
312 toString(brType), hist->predTaken, *hist->target,
313 enums::TargetProviderStrings[hist->targetProvider]);
314
315
326 updateHistories(tid, hist->pc, hist->uncond, hist->predTaken,
327 hist->target->instAddr(), hist->inst, hist->bpHistory);
328
329
330 if (iPred) {
331 // Update the indirect predictor with the direction prediction
332 iPred->update(tid, seqNum, hist->pc, false, hist->predTaken,
333 *hist->target, brType, hist->indirectHistory);
334 }
335
336 return hist->predTaken;
337}
338
339
340void
342{
343 DPRINTF(Branch, "[tid:%i] Committing branches until "
344 "[sn:%llu]\n", tid, done_sn);
345
346 while (!predHist[tid].empty() &&
347 predHist[tid].back()->seqNum <= done_sn) {
348
349 // Iterate from the back to front. Least recent
350 // sequence number until the most recent done number
351 commitBranch(tid, *predHist[tid].rbegin());
352
353 delete predHist[tid].back();
354 predHist[tid].pop_back();
355 DPRINTF(Branch, "[tid:%i] [commit sn:%llu] pred_hist.size(): %i\n",
356 tid, done_sn, predHist[tid].size());
357 }
358}
359
360void
362{
363
364 stats.committed[tid][hist->type]++;
365 if (hist->mispredict) {
366 stats.mispredicted[tid][hist->type]++;
367 // stats for identifying miss-prediction due to BTB or predictor
368 if (hist->actuallyTaken && !hist->btbHit) {
369 stats.mispredictDueToBTBMiss[tid][hist->type]++;
370 } else {
371 stats.mispredictDueToPredictor[tid][hist->type]++;
372 }
373 }
374
375
376 DPRINTF(Branch, "Commit branch: sn:%llu, PC:%#x %s, "
377 "pred:%i, taken:%i, target:%#x\n",
378 hist->seqNum, hist->pc, toString(hist->type),
379 hist->predTaken, hist->actuallyTaken,
380 hist->target->instAddr());
381
382 // Update the branch predictor with the correct results.
383 update(tid, hist->pc,
384 hist->actuallyTaken,
385 hist->bpHistory, false,
386 hist->inst,
387 hist->target->instAddr());
388
389 // Commit also Indirect predictor and RAS
390 if (iPred) {
391 iPred->commit(tid, hist->seqNum,
392 hist->indirectHistory);
393 }
394
395 if (ras) {
396 ras->commit(tid, hist->mispredict,
397 hist->type,
398 hist->rasHistory);
399 }
400}
401
402
403
404void
405BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
406{
407
408 while (!predHist[tid].empty() &&
409 predHist[tid].front()->seqNum > squashed_sn) {
410
411 auto hist = predHist[tid].front();
412
413 squashHistory(tid, hist);
414
415 predHist[tid].pop_front();
416
417 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] pred_hist.size(): %i\n",
418 tid, squashed_sn, predHist[tid].size());
419 }
420}
421
422
423
424void
426{
427
428 stats.squashes[tid][history->type]++;
429 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect: %s\n",
430 tid, history->seqNum,
431 toString(history->type));
432
433
434 if (history->rasHistory) {
435 assert(ras);
436
437 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect call/return "
438 "PC %#x. Fix RAS.\n", tid, history->seqNum,
439 history->pc);
440
441 ras->squash(tid, history->rasHistory);
442 }
443
444 if (iPred) {
445 iPred->squash(tid, history->seqNum,
446 history->indirectHistory);
447 }
448
449 // This call should delete the bpHistory.
450 squash(tid, history->bpHistory);
451
452 delete history;
453 history = nullptr;
454}
455
456
457void
458BPredUnit::squash(const InstSeqNum &squashed_sn,
459 const PCStateBase &corr_target,
460 bool actually_taken, ThreadID tid, bool from_commit)
461{
462 // Now that we know that a branch was mispredicted, we need to undo
463 // all the branches that have been seen up until this branch and
464 // fix up everything.
465 // NOTE: This should be call conceivably in 2 scenarios:
466 // (1) After an branch is executed, it updates its status in the ROB
467 // The commit stage then checks the ROB update and sends a signal to
468 // the fetch stage to squash history after the mispredict
469 // (2) In the decode stage, you can find out early if a unconditional
470 // PC-relative, branch was predicted incorrectly. If so, a signal
471 // to the fetch stage is sent to squash history after the mispredict
472
473 History &pred_hist = predHist[tid];
474
475 ++stats.condIncorrect;
476 ppMisses->notify(1);
477
478
479 DPRINTF(Branch, "[tid:%i] Squash from %s start from sequence number %i, "
480 "setting target to %s\n", tid, from_commit ? "commit" : "decode",
481 squashed_sn, corr_target);
482
483 // dump();
484
485 // Squash All Branches AFTER this mispredicted branch
486 // First the Prefetch history then the main history.
487 squash(squashed_sn, tid);
488
489 // If there's a squash due to a syscall, there may not be an entry
490 // corresponding to the squash. In that case, don't bother trying to
491 // fix up the entry.
492 if (!pred_hist.empty()) {
493
494 PredictorHistory* const hist = pred_hist.front();
495
496 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Mispredicted: %s, PC:%#x\n",
497 tid, squashed_sn, toString(hist->type), hist->pc);
498
499 // Update stats
500 stats.corrected[tid][hist->type]++;
501 if (hist->target &&
502 (hist->target->instAddr() != corr_target.instAddr())) {
503 stats.targetWrong[tid][hist->targetProvider]++;
504 }
505
506 // If the squash is comming from decode it can be
507 // redirected earlier. Note that this branch might never get
508 // committed as a preceeding branch was mispredicted
509 if (!from_commit) {
510 stats.earlyResteers[tid][hist->type]++;
511 }
512
513
514 // There are separate functions for in-order and out-of-order
515 // branch prediction, but not for update. Therefore, this
516 // call should take into account that the mispredicted branch may
517 // be on the wrong path (i.e., OoO execution), and that the counter
518 // counter table(s) should not be updated. Thus, this call should
519 // restore the state of the underlying predictor, for instance the
520 // local/global histories. The counter tables will be updated when
521 // the branch actually commits.
522
523 // Remember the correct direction and target for the update at commit.
524 hist->mispredict = true;
525 hist->actuallyTaken = actually_taken;
526 set(hist->target, corr_target);
527
528 // Correct Direction predictor ------------------
529 update(tid, hist->pc, actually_taken, hist->bpHistory,
530 true, hist->inst, corr_target.instAddr());
531
532
533 // Correct Indirect predictor -------------------
534 if (iPred) {
535 iPred->update(tid, squashed_sn, hist->pc,
536 true, actually_taken, corr_target,
537 hist->type, hist->indirectHistory);
538 }
539
540 // Correct RAS ---------------------------------
541 if (ras) {
542 // The branch was taken and the RAS was not updated.
543 // In case of call or return that needs to be fixed.
544 if (actually_taken && (hist->rasHistory == nullptr)) {
545
546 // A return has not poped the RAS.
547 if (hist->type == BranchType::Return) {
548 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] "
549 "Incorrectly predicted return [sn:%llu] PC: %#x\n",
550 tid, squashed_sn, hist->seqNum, hist->pc);
551
552 ras->pop(tid, hist->rasHistory);
553 }
554
555 // A call has not pushed a return address to the RAS.
556 if (hist->call) {
557 // In case of a call build the return address and
558 // push it to the RAS.
559 auto return_addr = hist->inst->buildRetPC(
560 corr_target, corr_target);
561
562 if (hist->inst->size()) {
563 return_addr->set(hist->pc + hist->inst->size());
564 }
565
566 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] "
567 "Incorrectly predicted call: [sn:%llu,PC:%#x] "
568 " Push return address %s onto RAS\n", tid,
569 squashed_sn, hist->seqNum, hist->pc,
570 *return_addr);
571 ras->push(tid, *return_addr, hist->rasHistory);
572 }
573
574 // The branch was not taken but the RAS modified.
575 } else if (!actually_taken && (hist->rasHistory != nullptr)) {
576 // The branch was not taken but the RAS was modified.
577 // Needs to be fixed.
578 ras->squash(tid, hist->rasHistory);
579 }
580 }
581
582 // Correct BTB ---------------------------------------------------
583 // Update the BTB for all mispredicted taken branches.
584 // Always if `requiresBTBHit` is true otherwise only if the
585 // branch was direct or no indirect predictor is available.
586 if (actually_taken &&
587 (requiresBTBHit || hist->inst->isDirectCtrl() ||
588 (!iPred && !hist->inst->isReturn()))) {
589
590 if (!hist->btbHit) {
591 ++stats.BTBMispredicted;
592 if (hist->condPred)
593 ++stats.predTakenBTBMiss;
594 }
595
596 DPRINTF(Branch,"[tid:%i] BTB Update called for [sn:%llu] "
597 "PC %#x -> T: %#x\n", tid,
598 hist->seqNum, hist->pc, hist->target->instAddr());
599
600 stats.BTBUpdates++;
601 btb->update(tid, hist->pc,
602 *hist->target,
603 hist->type,
604 hist->inst);
605 btb->incorrectTarget(hist->pc, hist->type);
606 }
607
608 } else {
609 DPRINTF(Branch, "[tid:%i] [sn:%llu] pred_hist empty, can't "
610 "update\n", tid, squashed_sn);
611 }
612}
613
614
615void
617{
618 int i = 0;
619 for (const auto& ph : predHist) {
620 if (!ph.empty()) {
621 auto hist = ph.begin();
622
623 cprintf("predHist[%i].size(): %i\n", i++, ph.size());
624
625 while (hist != ph.end()) {
626 cprintf("sn:%llu], PC:%#x, tid:%i, predTaken:%i, "
627 "bpHistory:%#x, rasHistory:%#x\n",
628 (*hist)->seqNum, (*hist)->pc,
629 (*hist)->tid, (*hist)->predTaken,
630 (*hist)->bpHistory, (*hist)->rasHistory);
631 hist++;
632 }
633
634 cprintf("\n");
635 }
636 }
637}
638
639
641 : statistics::Group(bp),
642 ADD_STAT(lookups, statistics::units::Count::get(),
643 "Number of BP lookups"),
644 ADD_STAT(squashes, statistics::units::Count::get(),
645 "Number of branches that got squashed (completely removed) as "
646 "an earlier branch was mispredicted."),
647 ADD_STAT(corrected, statistics::units::Count::get(),
648 "Number of branches that got corrected but not yet commited. "
649 "Branches get corrected by decode or after execute. Also a "
650 "branch misprediction can be detected out-of-order. Therefore, "
651 "a corrected branch might not end up beeing committed in case "
652 "an even earlier branch was mispredicted"),
653 ADD_STAT(earlyResteers, statistics::units::Count::get(),
654 "Number of branches that got redirected after decode."),
655 ADD_STAT(committed, statistics::units::Count::get(),
656 "Number of branches finally committed "),
657 ADD_STAT(mispredicted, statistics::units::Count::get(),
658 "Number of committed branches that were mispredicted."),
660 "Number of committed branches that were mispredicted by the "
661 "predictor."),
663 "Number of committed branches that were mispredicted because of "
664 "a BTB miss."),
665 ADD_STAT(targetProvider, statistics::units::Count::get(),
666 "The component providing the target for taken branches"),
667 ADD_STAT(targetWrong, statistics::units::Count::get(),
668 "Number of branches where the target was incorrect or not "
669 "available at prediction time."),
670 ADD_STAT(condPredicted, statistics::units::Count::get(),
671 "Number of conditional branches predicted"),
673 "Number of conditional branches predicted as taken"),
674 ADD_STAT(condIncorrect, statistics::units::Count::get(),
675 "Number of conditional branches incorrect"),
677 "Number of branches predicted taken but missed in BTB"),
678 ADD_STAT(BTBLookups, statistics::units::Count::get(),
679 "Number of BTB lookups"),
680 ADD_STAT(BTBUpdates, statistics::units::Count::get(),
681 "Number of BTB updates"),
682 ADD_STAT(BTBHits, statistics::units::Count::get(),
683 "Number of BTB hits"),
684 ADD_STAT(BTBHitRatio, statistics::units::Ratio::get(), "BTB Hit Ratio",
687 "Number BTB mispredictions. No target found or target wrong"),
689 "Number of indirect predictor lookups."),
690 ADD_STAT(indirectHits, statistics::units::Count::get(),
691 "Number of indirect target hits."),
692 ADD_STAT(indirectMisses, statistics::units::Count::get(),
693 "Number of indirect misses."),
695 "Number of mispredicted indirect branches.")
696
697{
698 using namespace statistics;
699 BTBHitRatio.precision(6);
700
701 lookups
702 .init(bp->numThreads, enums::Num_BranchType)
703 .flags(total | pdf);
704 lookups.ysubnames(enums::BranchTypeStrings);
705
707 .init(bp->numThreads, enums::Num_BranchType)
708 .flags(total | pdf);
709 squashes.ysubnames(enums::BranchTypeStrings);
710
712 .init(bp->numThreads, enums::Num_BranchType)
713 .flags(total | pdf);
714 corrected.ysubnames(enums::BranchTypeStrings);
715
717 .init(bp->numThreads, enums::Num_BranchType)
718 .flags(total | pdf);
719 earlyResteers.ysubnames(enums::BranchTypeStrings);
720
722 .init(bp->numThreads, enums::Num_BranchType)
723 .flags(total | pdf);
724 committed.ysubnames(enums::BranchTypeStrings);
725
727 .init(bp->numThreads, enums::Num_BranchType)
728 .flags(total | pdf);
729 mispredicted.ysubnames(enums::BranchTypeStrings);
730
732 .init(bp->numThreads, enums::Num_BranchType)
733 .flags(total | pdf);
734 mispredictDueToPredictor.ysubnames(enums::BranchTypeStrings);
735
737 .init(bp->numThreads, enums::Num_BranchType)
738 .flags(total | pdf);
739 mispredictDueToBTBMiss.ysubnames(enums::BranchTypeStrings);
740
742 .init(bp->numThreads, enums::Num_TargetProvider)
743 .flags(total | pdf);
744 targetProvider.ysubnames(enums::TargetProviderStrings);
745
747 .init(bp->numThreads, enums::Num_BranchType)
748 .flags(total | pdf);
749 targetWrong.ysubnames(enums::BranchTypeStrings);
750
751}
752
753} // namespace branch_prediction
754} // 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
bool isDirectCtrl() const
bool isUncondCtrl() const
virtual void advancePC(PCStateBase &pc_state) const =0
size_t size() const
bool isReturn() const
bool isIndirectCtrl() const
bool isCall() const
std::vector< History > 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:73
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...
virtual void branchPlaceholder(ThreadID tid, Addr pc, bool uncond, void *&bp_history)
Special function for the decoupled front-end.
Definition bpred_unit.cc:98
virtual void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, Addr target, const StaticInstPtr &inst, void *&bp_history)=0
Ones done with the prediction this function updates the path and global history.
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:89
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:82
const unsigned numThreads
Number of the threads for which the branch history is maintained.
virtual bool lookup(ThreadID tid, Addr pc, void *&bp_history)=0
Looks up a given conditional branch PC of in the BP to see if it is taken or not taken.
const unsigned instShiftAmt
Number of bits to shift instructions by for predictor addresses.
BranchPredictorParams Params
Definition bpred_unit.hh:72
void squashHistory(ThreadID tid, PredictorHistory *&bpu_history)
Squashes a particular branch instance.
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.
std::deque< PredictorHistory * > History
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
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...
bool predTaken
Whether or not it was predicted taken.
const InstSeqNum seqNum
The sequence number for the predictor history entry.
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 May 26 2025 09:19:08 for gem5 by doxygen 1.13.2