gem5 v24.0.0.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
59 : SimObject(params),
60 numThreads(params.numThreads),
61 requiresBTBHit(params.requiresBTBHit),
62 instShiftAmt(params.instShiftAmt),
63 predHist(numThreads),
64 btb(params.btb),
65 ras(params.ras),
66 iPred(params.indirectBranchPred),
67 stats(this)
68{
69}
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
97
98bool
99BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
100 PCStateBase &pc, ThreadID tid)
101{
103 PredictorHistory* bpu_history = nullptr;
104 bool taken = predict(inst, seqNum, pc, tid, bpu_history);
105
106 assert(bpu_history!=nullptr);
107
109 predHist[tid].push_front(bpu_history);
110
111 DPRINTF(Branch, "[tid:%i] [sn:%llu] History entry added. "
112 "predHist.size(): %i\n", tid, seqNum, predHist[tid].size());
113
114 return taken;
115}
116
117
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 (inst->isUncondCtrl()) {
148 // Unconditional branches -----
149 hist->condPred = true;
150 } else {
151 // Conditional branches -------
153 hist->condPred = lookup(tid, pc.instAddr(), hist->bpHistory);
154
155 if (hist->condPred) {
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 */
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
258
259 const PCStateBase *itarget = iPred->lookup(tid, seqNum,
260 pc.instAddr(),
261 hist->indirectHistory);
262
263 if (itarget) {
264 // Indirect predictor hit
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 {
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 updateHistories(tid, hist->pc, hist->uncond, hist->predTaken,
321 hist->target->instAddr(), hist->bpHistory);
322
323
324 if (iPred) {
325 // Update the indirect predictor with the direction prediction
326 iPred->update(tid, seqNum, hist->pc, false, hist->predTaken,
327 *hist->target, brType, hist->indirectHistory);
328 }
329
330 return hist->predTaken;
331}
332
333
334void
336{
337 DPRINTF(Branch, "[tid:%i] Committing branches until "
338 "[sn:%llu]\n", tid, done_sn);
339
340 while (!predHist[tid].empty() &&
341 predHist[tid].back()->seqNum <= done_sn) {
342
343 // Iterate from the back to front. Least recent
344 // sequence number until the most recent done number
345 commitBranch(tid, *predHist[tid].rbegin());
346
347 delete predHist[tid].back();
348 predHist[tid].pop_back();
349 DPRINTF(Branch, "[tid:%i] [commit sn:%llu] pred_hist.size(): %i\n",
350 tid, done_sn, predHist[tid].size());
351 }
352}
353
354void
356{
357
358 stats.committed[tid][hist->type]++;
359 if (hist->mispredict) {
360 stats.mispredicted[tid][hist->type]++;
361 }
362
363
364 DPRINTF(Branch, "Commit branch: sn:%llu, PC:%#x %s, "
365 "pred:%i, taken:%i, target:%#x\n",
366 hist->seqNum, hist->pc, toString(hist->type),
367 hist->predTaken, hist->actuallyTaken,
368 hist->target->instAddr());
369
370 // Update the branch predictor with the correct results.
371 update(tid, hist->pc,
372 hist->actuallyTaken,
373 hist->bpHistory, false,
374 hist->inst,
375 hist->target->instAddr());
376
377 // Commit also Indirect predictor and RAS
378 if (iPred) {
379 iPred->commit(tid, hist->seqNum,
380 hist->indirectHistory);
381 }
382
383 if (ras) {
384 ras->commit(tid, hist->mispredict,
385 hist->type,
386 hist->rasHistory);
387 }
388}
389
390
391
392void
393BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
394{
395
396 while (!predHist[tid].empty() &&
397 predHist[tid].front()->seqNum > squashed_sn) {
398
399 auto hist = predHist[tid].front();
400
401 squashHistory(tid, hist);
402
403 DPRINTF(Branch, "[tid:%i, squash sn:%llu] Removing history for "
404 "sn:%llu, PC:%#x\n", tid, squashed_sn, hist->seqNum,
405 hist->pc);
406
407
408 delete predHist[tid].front();
409 predHist[tid].pop_front();
410
411 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] pred_hist.size(): %i\n",
412 tid, squashed_sn, predHist[tid].size());
413 }
414}
415
416
417
418void
420{
421
422 stats.squashes[tid][history->type]++;
423 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect: %s\n",
424 tid, history->seqNum,
425 toString(history->type));
426
427
428 if (history->rasHistory) {
429 assert(ras);
430
431 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Incorrect call/return "
432 "PC %#x. Fix RAS.\n", tid, history->seqNum,
433 history->pc);
434
435 ras->squash(tid, history->rasHistory);
436 }
437
438 if (iPred) {
439 iPred->squash(tid, history->seqNum,
440 history->indirectHistory);
441 }
442
443 // This call should delete the bpHistory.
444 squash(tid, history->bpHistory);
445}
446
447
448void
449BPredUnit::squash(const InstSeqNum &squashed_sn,
450 const PCStateBase &corr_target,
451 bool actually_taken, ThreadID tid, bool from_commit)
452{
453 // Now that we know that a branch was mispredicted, we need to undo
454 // all the branches that have been seen up until this branch and
455 // fix up everything.
456 // NOTE: This should be call conceivably in 2 scenarios:
457 // (1) After an branch is executed, it updates its status in the ROB
458 // The commit stage then checks the ROB update and sends a signal to
459 // the fetch stage to squash history after the mispredict
460 // (2) In the decode stage, you can find out early if a unconditional
461 // PC-relative, branch was predicted incorrectly. If so, a signal
462 // to the fetch stage is sent to squash history after the mispredict
463
464 History &pred_hist = predHist[tid];
465
467 ppMisses->notify(1);
468
469
470 DPRINTF(Branch, "[tid:%i] Squash from %s start from sequence number %i, "
471 "setting target to %s\n", tid, from_commit ? "commit" : "decode",
472 squashed_sn, corr_target);
473
474 // dump();
475
476 // Squash All Branches AFTER this mispredicted branch
477 // First the Prefetch history then the main history.
478 squash(squashed_sn, tid);
479
480 // If there's a squash due to a syscall, there may not be an entry
481 // corresponding to the squash. In that case, don't bother trying to
482 // fix up the entry.
483 if (!pred_hist.empty()) {
484
485 PredictorHistory* const hist = pred_hist.front();
486
487 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Mispredicted: %s, PC:%#x\n",
488 tid, squashed_sn, toString(hist->type), hist->pc);
489
490 // Update stats
491 stats.corrected[tid][hist->type]++;
492 if (hist->target &&
493 (hist->target->instAddr() != corr_target.instAddr())) {
494 stats.targetWrong[tid][hist->targetProvider]++;
495 }
496
497 // If the squash is comming from decode it can be
498 // redirected earlier. Note that this branch might never get
499 // committed as a preceeding branch was mispredicted
500 if (!from_commit) {
501 stats.earlyResteers[tid][hist->type]++;
502 }
503
504 if (actually_taken) {
506 } else {
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 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 DPRINTF(Branch, "[tid:%i] [squash sn:%llu] "
560 "Incorrectly predicted call: [sn:%llu,PC:%#x] "
561 " Push return address %s onto RAS\n", tid,
562 squashed_sn, hist->seqNum, hist->pc,
563 *return_addr);
564 ras->push(tid, *return_addr, hist->rasHistory);
565 }
566
567 // The branch was not taken but the RAS modified.
568 } else if (!actually_taken && (hist->rasHistory != nullptr)) {
569 // The branch was not taken but the RAS was modified.
570 // Needs to be fixed.
571 ras->squash(tid, hist->rasHistory);
572 }
573 }
574
575 // Correct BTB ---------------------------------------------------
576 // Update the BTB for all mispredicted taken branches.
577 // Always if `requiresBTBHit` is true otherwise only if the
578 // branch was direct or no indirect predictor is available.
579 if (actually_taken &&
580 (requiresBTBHit || hist->inst->isDirectCtrl() ||
581 (!iPred && !hist->inst->isReturn()))) {
582
583 if (!hist->btbHit) {
585 if (hist->condPred)
587 }
588
589 DPRINTF(Branch,"[tid:%i] BTB Update called for [sn:%llu] "
590 "PC %#x -> T: %#x\n", tid,
591 hist->seqNum, hist->pc, hist->target->instAddr());
592
594 btb->update(tid, hist->pc,
595 *hist->target,
596 hist->type,
597 hist->inst);
598 btb->incorrectTarget(hist->pc, hist->type);
599 }
600
601 } else {
602 DPRINTF(Branch, "[tid:%i] [sn:%llu] pred_hist empty, can't "
603 "update\n", tid, squashed_sn);
604 }
605}
606
607
608void
610{
611 int i = 0;
612 for (const auto& ph : predHist) {
613 if (!ph.empty()) {
614 auto hist = ph.begin();
615
616 cprintf("predHist[%i].size(): %i\n", i++, ph.size());
617
618 while (hist != ph.end()) {
619 cprintf("sn:%llu], PC:%#x, tid:%i, predTaken:%i, "
620 "bpHistory:%#x, rasHistory:%#x\n",
621 (*hist)->seqNum, (*hist)->pc,
622 (*hist)->tid, (*hist)->predTaken,
623 (*hist)->bpHistory, (*hist)->rasHistory);
624 hist++;
625 }
626
627 cprintf("\n");
628 }
629 }
630}
631
632
634 : statistics::Group(bp),
635 ADD_STAT(lookups, statistics::units::Count::get(),
636 "Number of BP lookups"),
637 ADD_STAT(squashes, statistics::units::Count::get(),
638 "Number of branches that got squashed (completely removed) as "
639 "an earlier branch was mispredicted."),
640 ADD_STAT(corrected, statistics::units::Count::get(),
641 "Number of branches that got corrected but not yet commited. "
642 "Branches get corrected by decode or after execute. Also a "
643 "branch misprediction can be detected out-of-order. Therefore, "
644 "a corrected branch might not end up beeing committed in case "
645 "an even earlier branch was mispredicted"),
646 ADD_STAT(earlyResteers, statistics::units::Count::get(),
647 "Number of branches that got redirected after decode."),
648 ADD_STAT(committed, statistics::units::Count::get(),
649 "Number of branches finally committed "),
650 ADD_STAT(mispredicted, statistics::units::Count::get(),
651 "Number of committed branches that were mispredicted."),
652 ADD_STAT(targetProvider, statistics::units::Count::get(),
653 "The component providing the target for taken branches"),
654 ADD_STAT(targetWrong, statistics::units::Count::get(),
655 "Number of branches where the target was incorrect or not "
656 "available at prediction time."),
657 ADD_STAT(condPredicted, statistics::units::Count::get(),
658 "Number of conditional branches predicted"),
659 ADD_STAT(condPredictedTaken, statistics::units::Count::get(),
660 "Number of conditional branches predicted as taken"),
661 ADD_STAT(condIncorrect, statistics::units::Count::get(),
662 "Number of conditional branches incorrect"),
663 ADD_STAT(predTakenBTBMiss, statistics::units::Count::get(),
664 "Number of branches predicted taken but missed in BTB"),
665 ADD_STAT(NotTakenMispredicted, statistics::units::Count::get(),
666 "Number branches predicted 'not taken' but turned out "
667 "to be taken"),
668 ADD_STAT(TakenMispredicted, statistics::units::Count::get(),
669 "Number branches predicted taken but are actually not taken"),
670 ADD_STAT(BTBLookups, statistics::units::Count::get(),
671 "Number of BTB lookups"),
672 ADD_STAT(BTBUpdates, statistics::units::Count::get(),
673 "Number of BTB updates"),
674 ADD_STAT(BTBHits, statistics::units::Count::get(),
675 "Number of BTB hits"),
676 ADD_STAT(BTBHitRatio, statistics::units::Ratio::get(), "BTB Hit Ratio",
677 BTBHits / BTBLookups),
678 ADD_STAT(BTBMispredicted, statistics::units::Count::get(),
679 "Number BTB mispredictions. No target found or target wrong"),
680 ADD_STAT(indirectLookups, statistics::units::Count::get(),
681 "Number of indirect predictor lookups."),
682 ADD_STAT(indirectHits, statistics::units::Count::get(),
683 "Number of indirect target hits."),
684 ADD_STAT(indirectMisses, statistics::units::Count::get(),
685 "Number of indirect misses."),
686 ADD_STAT(indirectMispredicted, statistics::units::Count::get(),
687 "Number of mispredicted indirect branches.")
688
689{
690 using namespace statistics;
692
693 lookups
694 .init(bp->numThreads, enums::Num_BranchType)
695 .flags(total | pdf);
696 lookups.ysubnames(enums::BranchTypeStrings);
697
699 .init(bp->numThreads, enums::Num_BranchType)
700 .flags(total | pdf);
701 squashes.ysubnames(enums::BranchTypeStrings);
702
704 .init(bp->numThreads, enums::Num_BranchType)
705 .flags(total | pdf);
706 corrected.ysubnames(enums::BranchTypeStrings);
707
709 .init(bp->numThreads, enums::Num_BranchType)
710 .flags(total | pdf);
711 earlyResteers.ysubnames(enums::BranchTypeStrings);
712
714 .init(bp->numThreads, enums::Num_BranchType)
715 .flags(total | pdf);
716 committed.ysubnames(enums::BranchTypeStrings);
717
719 .init(bp->numThreads, enums::Num_BranchType)
720 .flags(total | pdf);
721 mispredicted.ysubnames(enums::BranchTypeStrings);
722
724 .init(bp->numThreads, enums::Num_TargetProvider)
725 .flags(total | pdf);
726 targetProvider.ysubnames(enums::TargetProviderStrings);
727
729 .init(bp->numThreads, enums::Num_BranchType)
730 .flags(total | pdf);
731 targetWrong.ysubnames(enums::BranchTypeStrings);
732
733}
734
735} // namespace branch_prediction
736} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
virtual std::string name() const
Definition named.hh:47
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition pcstate.hh:108
ProbePointArg generates a point for the class of Arg.
Definition probe.hh:264
Abstract superclass for simulation objects.
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
bool isReturn() const
bool isIndirectCtrl() const
bool isCall() const
Basically a wrapper class to hold both the branch predictor and the BTB.
Definition bpred_unit.hh:71
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...
Definition bpred_unit.cc:99
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.
virtual void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, Addr target, void *&bp_history)=0
Ones done with the prediction this function updates the path and global history.
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.
virtual const PCStateBase * lookup(ThreadID tid, Addr instPC, BranchType type=BranchType::NoBranch)=0
Looks up an address in the BTB to get the target of the branch.
virtual void incorrectTarget(Addr inst_pc, BranchType type=BranchType::NoBranch)
Update BTB statistics.
Definition btb.hh:103
virtual void update(ThreadID tid, Addr inst_pc, const PCStateBase &target_pc, BranchType type=BranchType::NoBranch, StaticInstPtr inst=nullptr)=0
Updates the BTB with the target of a branch.
virtual void commit(ThreadID tid, InstSeqNum sn, void *&i_history)=0
A branch gets finally commited.
virtual void update(ThreadID tid, InstSeqNum sn, Addr pc, bool squash, bool taken, const PCStateBase &target, BranchType br_type, void *&i_history)=0
Updates the indirect predictor with history information of a branch.
virtual const PCStateBase * lookup(ThreadID tid, InstSeqNum sn, Addr pc, void *&i_history)=0
Predicts the indirect target of an indirect branch.
virtual void squash(ThreadID tid, InstSeqNum sn, void *&i_history)=0
Squashes a branch.
const PCStateBase * pop(ThreadID tid, void *&ras_history)
Pops the top address from the RAS.
Definition ras.cc:188
void squash(ThreadID tid, void *&ras_history)
The branch (call/return) got squashed.
Definition ras.cc:216
void commit(ThreadID tid, bool misp, const BranchType brType, void *&ras_history)
A branch got finally got finally commited.
Definition ras.cc:251
void push(ThreadID tid, const PCStateBase &pc, void *&ras_history)
Pushes an address onto the RAS.
Definition ras.cc:166
Derived & ysubnames(const char **names)
Derived & precision(int _precision)
Set the precision and marks this stat to print at the end of simulation.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Statistics container.
Definition group.hh:93
Derived & init(size_type _x, size_type _y)
STL deque class.
Definition stl.hh:44
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
ProbeManager * getProbeManager()
Get the probe manager for this object.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
Bitfield< 31, 28 > ras
Bitfield< 4 > pc
std::string toString(BranchType type)
BranchType getBranchType(StaticInstPtr inst)
enums::BranchType BranchType
std::unique_ptr< PMU > PMUUPtr
Definition pmu.hh:60
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 - Pranith Kumar Copyright (c) 2020 Inria 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 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.
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.
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0