gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
tage_base.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 The University of Wisconsin
3 * Copyright (c) 2024 Technical University of Munich
4 *
5 * Copyright (c) 2006 INRIA (Institut National de Recherche en
6 * Informatique et en Automatique / French National Research Institute
7 * for Computer Science and Applied Mathematics)
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are
13 * met: redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer;
15 * redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution;
18 * neither the name of the copyright holders nor the names of its
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/* @file
36 * Implementation of a TAGE branch predictor
37 */
38
39#include "cpu/pred/tage_base.hh"
40
41#include "base/intmath.hh"
42#include "base/logging.hh"
43#include "debug/Fetch.hh"
44#include "debug/Tage.hh"
45
46namespace gem5
47{
48
49namespace branch_prediction
50{
81
83TAGEBase::makeBranchInfo(Addr pc, bool conditional) {
84 return new BranchInfo(*this, pc, conditional);
85}
86
87void
89{
90 if (initialized) {
91 return;
92 }
93
94 // Current method for periodically resetting the u counter bits only
95 // works for 1 or 2 bits
96 // Also make sure that it is not 0
97 assert(tagTableUBits <= 2 && (tagTableUBits > 0));
98
99 // we use int type for the path history, so it cannot be more than
100 // its size
101 assert(pathHistBits <= (sizeof(int)*8));
102
103 // initialize the counter to half of the period
104 assert(logUResetPeriod != 0);
106
107 assert(histBufferSize > maxHist * 3);
108
110
111 for (auto& history : threadHistory) {
112 history.pathHist = 0;
113 history.nonSpecPathHist = 0;
114 history.globalHist.resize(histBufferSize, 0);
115 history.ptGhist = 0;
116 }
117
118 histLengths = new int [nHistoryTables+1];
119
121
122 assert(tagTableTagWidths.size() == (nHistoryTables+1));
123 assert(logTagTableSizes.size() == (nHistoryTables+1));
124
125 // First entry is for the Bimodal table and it is untagged in this
126 // implementation
127 assert(tagTableTagWidths[0] == 0);
128
129 for (auto& history : threadHistory) {
130 history.computeIndices = new FoldedHistory[nHistoryTables+1];
131 history.computeTags[0] = new FoldedHistory[nHistoryTables+1];
132 history.computeTags[1] = new FoldedHistory[nHistoryTables+1];
133
134 initFoldedHistories(history);
135 }
136
137 const uint64_t bimodalTableSize = 1ULL << logTagTableSizes[0];
138 btablePrediction.resize(bimodalTableSize, false);
139 btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries,
140 true);
141
142 gtable = new TageEntry*[nHistoryTables + 1];
144
145 tableIndices = new int [nHistoryTables+1];
146 tableTags = new int [nHistoryTables+1];
147 initialized = true;
148}
149
150void
152{
153 for (int i = 1; i <= nHistoryTables; i++) {
154 history.computeIndices[i].init(
156 history.computeTags[0][i].init(
158 history.computeTags[1][i].init(
160 DPRINTF(Tage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n",
162 }
163}
164
165void
167{
168 for (int i = 1; i <= nHistoryTables; i++) {
169 gtable[i] = new TageEntry[1<<(logTagTableSizes[i])];
170 }
171}
172
173void
175{
176 histLengths[1] = minHist;
178
179 for (int i = 2; i <= nHistoryTables; i++) {
180 histLengths[i] = (int) (((double) minHist *
181 pow ((double) (maxHist) / (double) minHist,
182 (double) (i - 1) / (double) ((nHistoryTables- 1))))
183 + 0.5);
184 }
185}
186
187int
189{
190 return ((pc_in >> instShiftAmt) & ((1ULL << (logTagTableSizes[0])) - 1));
191}
192
193int
194TAGEBase::F(int A, int size, int bank) const
195{
196 int A1, A2;
197
198 A = A & ((1ULL << size) - 1);
199 A1 = (A & ((1ULL << logTagTableSizes[bank]) - 1));
200 A2 = (A >> logTagTableSizes[bank]);
201 A2 = ((A2 << bank) & ((1ULL << logTagTableSizes[bank]) - 1))
202 + (A2 >> (logTagTableSizes[bank] - bank));
203 A = A1 ^ A2;
204 A = ((A << bank) & ((1ULL << logTagTableSizes[bank]) - 1))
205 + (A >> (logTagTableSizes[bank] - bank));
206 return (A);
207}
208
209// gindex computes a full hash of pc, ghist and pathHist
210int
211TAGEBase::gindex(ThreadID tid, Addr pc, int bank) const
212{
213 int index;
214 int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits :
215 histLengths[bank];
216 const unsigned int shiftedPc = pc >> instShiftAmt;
217 index =
218 shiftedPc ^
219 (shiftedPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^
220 threadHistory[tid].computeIndices[bank].comp ^
221 F(threadHistory[tid].pathHist, hlen, bank);
222
223 return (index & ((1ULL << (logTagTableSizes[bank])) - 1));
224}
225
226
227// Tag computation
228uint16_t
229TAGEBase::gtag(ThreadID tid, Addr pc, int bank) const
230{
231 int tag = (pc >> instShiftAmt) ^
232 threadHistory[tid].computeTags[0][bank].comp ^
233 (threadHistory[tid].computeTags[1][bank].comp << 1);
234
235 return (tag & ((1ULL << tagTableTagWidths[bank]) - 1));
236}
237
238
239// Up-down saturating counter
240template<typename T>
241void
242TAGEBase::ctrUpdate(T & ctr, bool taken, int nbits)
243{
244 assert(nbits <= sizeof(T) << 3);
245 if (taken) {
246 if (ctr < ((1 << (nbits - 1)) - 1))
247 ctr++;
248 } else {
249 if (ctr > -(1 << (nbits - 1)))
250 ctr--;
251 }
252}
253
254// int8_t and int versions of this function may be needed
255template void TAGEBase::ctrUpdate(int8_t & ctr, bool taken, int nbits);
256template void TAGEBase::ctrUpdate(int & ctr, bool taken, int nbits);
257
258// Up-down unsigned saturating counter
259void
260TAGEBase::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits)
261{
262 assert(nbits <= sizeof(uint8_t) << 3);
263 if (up) {
264 if (ctr < ((1 << nbits) - 1))
265 ctr++;
266 } else {
267 if (ctr)
268 ctr--;
269 }
270}
271
272// Bimodal prediction
273bool
275{
276 return btablePrediction[bi->bimodalIndex];
277}
278
279
280// Update the bimodal predictor: a hysteresis bit is shared among N prediction
281// bits (N = 2 ^ logRatioBiModalHystEntries)
282void
284{
285 int inter = (btablePrediction[bi->bimodalIndex] << 1)
287 if (taken) {
288 if (inter < 3)
289 inter++;
290 } else if (inter > 0) {
291 inter--;
292 }
293 const bool pred = inter >> 1;
294 const bool hyst = inter & 1;
295 btablePrediction[bi->bimodalIndex] = pred;
296 btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst;
297 DPRINTF(Tage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst);
298}
299
300// shifting the global history: we manage the history in a big table in order
301// to reduce simulation time
302void
303TAGEBase::updateGHist(ThreadID tid, uint64_t bv, uint8_t n)
304{
305 if (n == 0) return;
306
307 // Handle rollovers first.
308 ThreadHistory& tHist = threadHistory[tid];
309 if (tHist.ptGhist < n) {
310 DPRINTF(Tage, "Rolling over the histories\n");
311 // Copy beginning of globalHistoryBuffer to end, such that the last
312 // maxHist outcomes are still reachable through
313 // globalHist[0 .. maxHist - 1].
314 // The rollover may happen when the predictor is in a speculative state
315 // where multiple predictions are already in flight. In case of a
316 // misprediction we must be able to recover the history but if we just
317 // copy the maxHist length at rollover we will run out-of-bounce.
318 // To avoid this we copy an addition rollback window of 1k additional
319 // bit. This should allow more than 500 predictions (TAGE-SC-L) in
320 // flight.
321 const int rollbackBuffer = 1000;
322 for (int i = 0; i < (maxHist + rollbackBuffer); i++) {
323 tHist.globalHist[histBufferSize - maxHist - rollbackBuffer + i] =
324 tHist.globalHist[tHist.ptGhist + i];
325 }
326
327 tHist.ptGhist = histBufferSize - maxHist - rollbackBuffer;
328 }
329
330 // Update the global history
331 for (int i = 0; i < n; i++) {
332 // Shift the next bit of the bit vector into the history
333 // Use `at` to check for out-of-bounds access.
334 tHist.ptGhist--;
335 tHist.globalHist.at(tHist.ptGhist) = (bv & 1) ? 1 : 0;
336 bv >>= 1;
337
338 // Update the folded histories with the new bit.
339 uint8_t *gh_ptr = &(tHist.globalHist[tHist.ptGhist]);
340
341 for (int i = 1; i <= nHistoryTables; i++) {
342 tHist.computeIndices[i].update(gh_ptr);
343 tHist.computeTags[0][i].update(gh_ptr);
344 tHist.computeTags[1][i].update(gh_ptr);
345 }
346 }
347}
348
349void
351 BranchInfo* bi)
352{
353 // computes the table addresses and the partial tags
354 for (int i = 1; i <= nHistoryTables; i++) {
355 tableIndices[i] = gindex(tid, branch_pc, i);
356 bi->tableIndices[i] = tableIndices[i];
357 tableTags[i] = gtag(tid, branch_pc, i);
358 bi->tableTags[i] = tableTags[i];
359 }
360 bi->valid = true;
361}
362
363unsigned
365{
366 // There is only 1 counter on the base TAGE implementation
367 return 0;
368}
369
370bool
372 bool cond_branch, BranchInfo* bi)
373{
374 if (!cond_branch) {
375 // Unconditional branch, predict taken
376 assert(bi->branchPC == branch_pc);
377 return true;
378 }
379
380 // TAGE prediction
381
382 calculateIndicesAndTags(tid, branch_pc, bi);
383 bi->bimodalIndex = bindex(branch_pc);
384
385 bi->hitBank = 0;
386 bi->altBank = 0;
387 //Look for the bank with longest matching history
388 for (int i = nHistoryTables; i > 0; i--) {
389 if (noSkip[i] &&
390 gtable[i][tableIndices[i]].tag == tableTags[i]) {
391 bi->hitBank = i;
392 bi->hitBankIndex = tableIndices[bi->hitBank];
393 break;
394 }
395 }
396 //Look for the alternate bank
397 for (int i = bi->hitBank - 1; i > 0; i--) {
398 if (noSkip[i] &&
399 gtable[i][tableIndices[i]].tag == tableTags[i]) {
400 bi->altBank = i;
401 bi->altBankIndex = tableIndices[bi->altBank];
402 break;
403 }
404 }
405 //computes the prediction and the alternate prediction
406 if (bi->hitBank > 0) {
407 if (bi->altBank > 0) {
408 bi->altTaken =
409 gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0;
411 } else {
412 bi->altTaken = getBimodePred(branch_pc, bi);
413 }
414
415 bi->longestMatchPred =
416 gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0;
417 bi->pseudoNewAlloc =
418 abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1;
419
420 //if the entry is recognized as a newly allocated entry and
421 //useAltPredForNewlyAllocated is positive use the alternate
422 //prediction
423 if ((useAltPredForNewlyAllocated[getUseAltIdx(bi, branch_pc)] < 0)
424 || ! bi->pseudoNewAlloc) {
425 bi->tagePred = bi->longestMatchPred;
426 bi->provider = TAGE_LONGEST_MATCH;
427 } else {
428 bi->tagePred = bi->altTaken;
429 bi->provider = bi->altBank ? TAGE_ALT_MATCH
431 }
432 } else {
433 bi->altTaken = getBimodePred(branch_pc, bi);
434 bi->tagePred = bi->altTaken;
435 bi->longestMatchPred = bi->altTaken;
436 bi->provider = BIMODAL_ONLY;
437 }
438
439 DPRINTF(Tage, "Predict for %lx: tagePred:%d, altPred:%d\n",
440 branch_pc, bi->tagePred, bi->altTaken);
441
442 return bi->tagePred;
443}
444
445void
446TAGEBase::adjustAlloc(bool & alloc, bool taken, bool pred_taken)
447{
448 // Nothing for this base class implementation
449}
450
451void
453 int nrand)
454{
455 if (alloc) {
456 // is there some "unuseful" entry to allocate
457 uint8_t min = 1;
458 for (int i = nHistoryTables; i > bi->hitBank; i--) {
459 if (gtable[i][bi->tableIndices[i]].u < min) {
460 min = gtable[i][bi->tableIndices[i]].u;
461 }
462 }
463
464 // we allocate an entry with a longer history
465 // to avoid ping-pong, we do not choose systematically the next
466 // entry, but among the 3 next entries
467 int Y = nrand &
468 ((1ULL << (nHistoryTables - bi->hitBank - 1)) - 1);
469 int X = bi->hitBank + 1;
470 if (Y & 1) {
471 X++;
472 if (Y & 2)
473 X++;
474 }
475 // No entry available, forces one to be available
476 if (min > 0) {
477 gtable[X][bi->tableIndices[X]].u = 0;
478 }
479
480
481 //Allocate entries
482 unsigned numAllocated = 0;
483 for (int i = X; i <= nHistoryTables; i++) {
484 if (gtable[i][bi->tableIndices[i]].u == 0) {
485 gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i];
486 gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1;
487 ++numAllocated;
488 if (numAllocated == maxNumAlloc) {
489 break;
490 }
491 }
492 }
493 }
494
495 tCounter++;
496
497 handleUReset();
498}
499
500void
502{
503 //periodic reset of u: reset is not complete but bit by bit
504 if ((tCounter & ((1ULL << logUResetPeriod) - 1)) == 0) {
505 // reset least significant bit
506 // most significant bit becomes least significant bit
507 for (int i = 1; i <= nHistoryTables; i++) {
508 for (int j = 0; j < (1ULL << logTagTableSizes[i]); j++) {
509 resetUctr(gtable[i][j].u);
510 }
511 }
512 }
513}
514
515void
517{
518 u >>= 1;
519}
520
521void
522TAGEBase::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken,
523 BranchInfo* bi, int nrand, Addr corrTarget, bool pred, bool preAdjustAlloc)
524{
525 // TAGE UPDATE
526 // try to allocate a new entries only if prediction was wrong
527 bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables);
528
529 if (preAdjustAlloc) {
530 adjustAlloc(alloc, taken, pred);
531 }
532
533 if (bi->hitBank > 0) {
534 // Manage the selection between longest matching and alternate
535 // matching for "pseudo"-newly allocated longest matching entry
536 bool PseudoNewAlloc = bi->pseudoNewAlloc;
537 // an entry is considered as newly allocated if its prediction
538 // counter is weak
539 if (PseudoNewAlloc) {
540 if (bi->longestMatchPred == taken) {
541 alloc = false;
542 }
543 // if it was delivering the correct prediction, no need to
544 // allocate new entry even if the overall prediction was false
545 if (bi->longestMatchPred != bi->altTaken) {
546 ctrUpdate(
548 bi->altTaken == taken, useAltOnNaBits);
549 }
550 }
551 }
552
553 if (!preAdjustAlloc) {
554 adjustAlloc(alloc, taken, pred);
555 }
556
557 handleAllocAndUReset(alloc, taken, bi, nrand);
558
559 handleTAGEUpdate(branch_pc, taken, bi);
560}
561
562void
564{
565 if (bi->hitBank > 0) {
566 DPRINTF(Tage, "Updating tag table entry (%d,%d) for branch %lx\n",
567 bi->hitBank, bi->hitBankIndex, branch_pc);
568 ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken,
570 // if the provider entry is not certified to be useful also update
571 // the alternate prediction
572 if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) {
573 if (bi->altBank > 0) {
574 ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken,
576 DPRINTF(Tage, "Updating tag table entry (%d,%d) for"
577 " branch %lx\n", bi->hitBank, bi->hitBankIndex,
578 branch_pc);
579 }
580 if (bi->altBank == 0) {
581 baseUpdate(branch_pc, taken, bi);
582 }
583 }
584
585 // update the u counter
586 if (bi->tagePred != bi->altTaken) {
587 unsignedCtrUpdate(gtable[bi->hitBank][bi->hitBankIndex].u,
588 bi->tagePred == taken, tagTableUBits);
589 }
590 } else {
591 baseUpdate(branch_pc, taken, bi);
592 }
593}
594
595void
597 Addr branch_pc, Addr target, BranchInfo* bi)
598{
599 ThreadHistory& tHist = threadHistory[tid];
600
601 // Update path history
602 tHist.pathHist =
603 calcNewPathHist(tid, branch_pc, tHist.pathHist, taken, brtype, target);
604
605 if (takenOnlyHistory) {
606 // Taken-only history is implemented after the paper:
607 // https://ieeexplore.ieee.org/document/9246215
608 //
609 // For taken-only history two bits of a hash of pc and its target
610 // is shifted into the global history in case the branch was taken.
611 // For not-taken branches no history update will happen.
612 if (taken) {
613 bi->ghist = (((branch_pc >> instShiftAmt) >> 2) ^
614 ((target >> instShiftAmt) >> 3));
615 bi->nGhist = 2;
616 }
617
618 } else {
619 // For normal direction history update the history by
620 // whether the branch was taken or not.
621 bi->ghist = taken ? 1 : 0;
622 bi->nGhist = 1;
623 }
624
625 // Update the global history
626 updateGHist(tid, bi->ghist, bi->nGhist);
627}
628
629
630void
631TAGEBase::updateHistories(ThreadID tid, Addr branch_pc, bool speculative,
632 bool taken, Addr target,
633 const StaticInstPtr & inst, BranchInfo* bi)
634{
635 if (speculative != speculativeHistUpdate) {
636 if (!speculative) {
637 // Save the speculative path history as non-speculative
638 threadHistory[tid].nonSpecPathHist =
639 calcNewPathHist(tid, branch_pc, bi->pathHist, taken,
640 branchTypeExtra(inst), target);
641 }
642 return;
643 }
644
645 // If this is the first time we see this branch record the current
646 // state of the history to be able to recover.
647 if (speculativeHistUpdate && (!bi->modified)) {
648 recordHistState(tid, bi);
649 }
650
651 // In case the branch already updated the history
652 // we need to revert the previous update first.
653 if (bi->modified) {
654 restoreHistState(tid, bi);
655 }
656
657 // Recalculate the tags and indices if needed. This can be the case
658 // as in the decoupled frontend branches can be inserted out of order
659 // (surprise branches). We can not compute the tags and indices
660 // at that point since the BPU might already speculated on other branches
661 // which updated the history. We can recalculate the tags and indices
662 // now since either the branch was correctly not taken and the history
663 // will not be updated or the branch was incorrect in which case the
664 // branches afterwards where squashed and the history was restored.
665 if (!bi->valid && bi->condBranch) {
666 calculateIndicesAndTags(tid, branch_pc, bi);
667 }
668
669 // We should have not already modified the history
670 // for this branch
671 assert(bi->nGhist == 0);
672
673 // Do the actual history update. Might be different for different
674 // TAGE implementations.
676 branch_pc, target, bi);
677 bi->modified = true;
678
679 DPRINTF(Tage,
680 "Updating global histories with branch:%lx; taken?:%d, "
681 "path Hist: %x; pointer:%d\n",
682 branch_pc, taken, threadHistory[tid].pathHist,
683 threadHistory[tid].ptGhist);
684}
685
686void
688{
689 ThreadHistory &tHist = threadHistory[tid];
690 bi->pathHist = tHist.pathHist;
691
692 for (int i = 1; i <= nHistoryTables; i++) {
693 bi->ci[i] = tHist.computeIndices[i].comp;
694 bi->ct0[i] = tHist.computeTags[0][i].comp;
695 bi->ct1[i] = tHist.computeTags[1][i].comp;
696 }
697}
698
699void
701{
703 return;
704 }
705 if (!bi->modified) {
706 return;
707 }
708
709 ThreadHistory& tHist = threadHistory[tid];
710 tHist.pathHist = bi->pathHist;
711
712 if (bi->nGhist == 0)
713 return;
714
715 // RESTORE HISTORIES
716 // Shift out the inserted bits from the folded history
717 // and the global history vector
718 for (int n = 0; n < bi->nGhist; n++) {
719 uint8_t *gh_ptr = &(tHist.globalHist[tHist.ptGhist]);
720
721 // First revert the folded history
722 for (int i = 1; i <= nHistoryTables; i++) {
723 tHist.computeIndices[i].restore(gh_ptr);
724 tHist.computeTags[0][i].restore(gh_ptr);
725 tHist.computeTags[1][i].restore(gh_ptr);
726 }
727 tHist.ptGhist++;
728 // Make sure we do not go out of bounds.
729 // If we do its likely that there where too many branches in flight
730 // during a rollover. Consider increasing the `rollbackBuffer`
731 assert((tHist.ptGhist + maxHist) < tHist.globalHist.size());
732 }
733 bi->nGhist = 0;
734 bi->modified = false;
735}
736
737int
738TAGEBase::calcNewPathHist(ThreadID tid, Addr pc, int cur_phist, bool taken,
739 int brtype, Addr target) const
740{
741 if (takenOnlyHistory && !taken) {
742 // For taken-only history we update only if the branch was taken
743 return cur_phist;
744 }
745 int pathbit = ((pc >> instShiftAmt) & 1);
746 cur_phist = (cur_phist << 1) + pathbit;
747 cur_phist = (cur_phist & ((1ULL << pathHistBits) - 1));
748 return cur_phist;
749}
750
751void
752TAGEBase::squash(ThreadID tid, bool taken, Addr target,
754{
755 updateHistories(tid, bi->branchPC, true, taken, target, inst, bi);
756}
757
758void
760{
761 // do nothing. This is only used in some derived classes
762 return;
763}
764
765void
767{
768 if (taken == bi->tagePred) {
769 // correct prediction
770 switch (bi->provider) {
771 case BIMODAL_ONLY: stats.bimodalProviderCorrect++; break;
772 case TAGE_LONGEST_MATCH: stats.longestMatchProviderCorrect++; break;
774 stats.bimodalAltMatchProviderCorrect++;
775 break;
776 case TAGE_ALT_MATCH: stats.altMatchProviderCorrect++; break;
777 }
778 } else {
779 // wrong prediction
780 switch (bi->provider) {
781 case BIMODAL_ONLY: stats.bimodalProviderWrong++; break;
783 stats.longestMatchProviderWrong++;
784 if (bi->altTaken == taken) {
785 stats.altMatchProviderWouldHaveHit++;
786 }
787 break;
789 stats.bimodalAltMatchProviderWrong++;
790 break;
791 case TAGE_ALT_MATCH:
792 stats.altMatchProviderWrong++;
793 break;
794 }
795
796 switch (bi->provider) {
798 case TAGE_ALT_MATCH:
799 if (bi->longestMatchPred == taken) {
800 stats.longestMatchProviderWouldHaveHit++;
801 }
802 }
803 }
804
805 switch (bi->provider) {
807 case TAGE_ALT_MATCH:
808 stats.longestMatchProvider[bi->hitBank]++;
809 stats.altMatchProvider[bi->altBank]++;
810 break;
811 }
812}
813
814unsigned
816{
817 unsigned val = 0;
818 int gh_ptr = threadHistory[tid].ptGhist;
819 for (unsigned i = 0; i < 16; i++) {
820 // Make sure we don't go out of bounds with `at`.
821 val |= ((threadHistory[tid].globalHist.at(gh_ptr + i) & 0x1) << i);
822 }
823 return val;
824}
825
826
828 statistics::Group *parent, unsigned nHistoryTables)
829 : statistics::Group(parent),
831 "Number of times TAGE Longest Match is the provider and the "
832 "prediction is correct"),
834 "Number of times TAGE Alt Match is the provider and the "
835 "prediction is correct"),
837 "Number of times TAGE Alt Match is the bimodal and it is the "
838 "provider and the prediction is correct"),
840 "Number of times there are no hits on the TAGE tables and the "
841 "bimodal prediction is correct"),
843 "Number of times TAGE Longest Match is the provider and the "
844 "prediction is wrong"),
846 "Number of times TAGE Alt Match is the provider and the "
847 "prediction is wrong"),
849 "Number of times TAGE Alt Match is the bimodal and it is the "
850 "provider and the prediction is wrong"),
852 "Number of times there are no hits on the TAGE tables and the "
853 "bimodal prediction is wrong"),
855 "Number of times TAGE Longest Match is the provider, the "
856 "prediction is wrong and Alt Match prediction was correct"),
858 "Number of times TAGE Alt Match is the provider, the "
859 "prediction is wrong and Longest Match prediction was correct"),
861 "TAGE provider for longest match"),
863 "TAGE provider for alt match")
864{
867}
868
869int8_t
870TAGEBase::getCtr(int hitBank, int hitBankIndex) const
871{
872 return gtable[hitBank][hitBankIndex].ctr;
873}
874
875unsigned
877{
878 return tagTableCounterBits;
879}
880
881int
882TAGEBase::getPathHist(ThreadID tid, bool speculative) const
883{
884 return speculative ? threadHistory[tid].pathHist
885 : threadHistory[tid].nonSpecPathHist;
886}
887
888bool
893
894size_t
896 size_t bits = 0;
897 for (int i = 1; i <= nHistoryTables; i++) {
898 bits += (1 << logTagTableSizes[i]) *
900 }
901 uint64_t bimodalTableSize = 1ULL << logTagTableSizes[0];
903 bits += bimodalTableSize;
904 bits += (bimodalTableSize >> logRatioBiModalHystEntries);
908 return bits;
909}
910
911} // namespace branch_prediction
912} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
int getPathHist(ThreadID tid, bool speculative=true) const
Definition tage_base.cc:882
TAGEBase(const TAGEBaseParams &p)
Definition tage_base.cc:51
virtual int branchTypeExtra(const StaticInstPtr &inst)
This function acts as a hook for other TAGE implementations to adjust the branch type.
Definition tage_base.hh:356
virtual BranchInfo * makeBranchInfo(Addr pc, bool conditional)
Definition tage_base.cc:83
virtual void handleAllocAndUReset(bool alloc, bool taken, BranchInfo *bi, int nrand)
Handles Allocation and U bits reset on an update.
Definition tage_base.cc:452
virtual void initFoldedHistories(ThreadHistory &history)
Initialization of the folded histories.
Definition tage_base.cc:151
static void ctrUpdate(T &ctr, bool taken, int nbits)
Updates a direction counter based on the actual branch outcome.
Definition tage_base.cc:242
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition tage_base.cc:88
virtual unsigned getUseAltIdx(BranchInfo *bi, Addr branch_pc)
Calculation of the index for useAltPredForNewlyAllocated On this base TAGE implementation it is alway...
Definition tage_base.cc:364
virtual void resetUctr(uint8_t &u)
Algorithm for resetting a single U counter.
Definition tage_base.cc:516
virtual void extraAltCalc(BranchInfo *bi)
Extra steps for calculating altTaken For this base TAGE class it does nothing.
Definition tage_base.cc:759
static void unsignedCtrUpdate(uint8_t &ctr, bool up, unsigned nbits)
Updates an unsigned counter based on up/down parameter.
Definition tage_base.cc:260
virtual void handleUReset()
Handles the U bits reset.
Definition tage_base.cc:501
virtual void updateStats(bool taken, BranchInfo *bi)
Update the stats.
Definition tage_base.cc:766
virtual void calculateParameters()
Calculates the history lengths and some other paramters in derived classes.
Definition tage_base.cc:174
const unsigned logRatioBiModalHystEntries
Definition tage_base.hh:484
std::vector< bool > btableHysteresis
Definition tage_base.hh:497
std::vector< bool > btablePrediction
Definition tage_base.hh:496
virtual void adjustAlloc(bool &alloc, bool taken, bool pred_taken)
Extra calculation to tell whether TAGE allocaitons may happen or not on an update For this base TAGE ...
Definition tage_base.cc:446
void recordHistState(ThreadID tid, BranchInfo *bi)
Records the current state of the histories to be able to restore it in case of a mispredicted specula...
Definition tage_base.cc:687
std::vector< ThreadHistory > threadHistory
Definition tage_base.hh:522
virtual void calculateIndicesAndTags(ThreadID tid, Addr branch_pc, BranchInfo *bi)
On a prediction, calculates the TAGE indices and tags for all the different history lengths.
Definition tage_base.cc:350
virtual bool getBimodePred(Addr pc, BranchInfo *bi) const
Get a branch prediction from the bimodal predictor.
Definition tage_base.cc:274
virtual int calcNewPathHist(ThreadID tid, Addr pc, int cur_phist, bool taken, int brtype, Addr target) const
Definition tage_base.cc:738
int8_t getCtr(int hitBank, int hitBankIndex) const
Definition tage_base.cc:870
virtual void squash(ThreadID tid, bool taken, Addr target, const StaticInstPtr &inst, BranchInfo *bi)
Restores speculatively updated path and direction histories.
Definition tage_base.cc:752
virtual uint16_t gtag(ThreadID tid, Addr pc, int bank) const
Computes the partial tag of a tagged table.
Definition tage_base.cc:229
std::vector< int > logTagTableSizes
Definition tage_base.hh:494
void baseUpdate(Addr pc, bool taken, BranchInfo *bi)
Updates the bimodal predictor.
Definition tage_base.cc:283
virtual int F(int phist, int size, int bank) const
Utility function to shuffle the path history depending on which tagged table we are accessing.
Definition tage_base.cc:194
bool tagePredict(ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo *bi)
TAGE prediction called from TAGE::predict.
Definition tage_base.cc:371
std::vector< int8_t > useAltPredForNewlyAllocated
Definition tage_base.hh:533
unsigned getGHR(ThreadID tid) const
Definition tage_base.cc:815
virtual void updatePathAndGlobalHistory(ThreadID tid, int brtype, bool taken, Addr branch_pc, Addr target, BranchInfo *bi)
Does the actual update of path and global history.
Definition tage_base.cc:596
const bool takenOnlyHistory
Use taken only history.
Definition tage_base.hh:541
virtual void updateHistories(ThreadID tid, Addr branch_pc, bool speculative, bool taken, Addr target, const StaticInstPtr &inst, BranchInfo *bi)
(Speculatively) updates global histories (path and direction).
Definition tage_base.cc:631
std::vector< unsigned > tagTableTagWidths
Definition tage_base.hh:493
gem5::branch_prediction::TAGEBase::TAGEBaseStats stats
virtual void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, BranchInfo *bi, int nrand, Addr corrTarget, bool pred, bool preAdjustAlloc=false)
Update TAGE for conditional branches.
Definition tage_base.cc:522
virtual void buildTageTables()
Instantiates the TAGE table entries.
Definition tage_base.cc:166
void updateGHist(ThreadID tid, uint64_t bv, uint8_t n)
Internal history update function.
Definition tage_base.cc:303
virtual int gindex(ThreadID tid, Addr pc, int bank) const
Computes the index used to access a partially tagged table.
Definition tage_base.cc:211
virtual void handleTAGEUpdate(Addr branch_pc, bool taken, BranchInfo *bi)
Handles the update of the TAGE entries.
Definition tage_base.cc:563
virtual int bindex(Addr pc_in) const
Computes the index used to access the bimodal table.
Definition tage_base.cc:188
void restoreHistState(ThreadID tid, BranchInfo *bi)
Restore the state of the histories in case of detecting a mispredicted speculative update.
Definition tage_base.cc:700
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
SimObject(const Params &p)
Definition sim_object.cc:58
Bitfield< 31 > n
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23 > up
Definition types.hh:124
Bitfield< 22 > u
Bitfield< 4 > pc
Bitfield< 30, 0 > index
Bitfield< 0 > p
Bitfield< 20, 16 > bi
Definition types.hh:80
Bitfield< 27, 24 > pred
Definition types.hh:91
Bitfield< 15, 0 > X
Definition int.hh:58
Bitfield< 63 > val
Definition misc.hh:804
Units for Stats.
Definition units.hh:113
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
RefCountingPtr< StaticInst > StaticInstPtr
void init(int original_length, int compressed_length)
Definition tage_base.hh:100
TAGEBaseStats(statistics::Group *parent, unsigned nHistoryTables)
Definition tage_base.cc:827

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