gem5 v23.0.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
tage_sc_l.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Metempsy Technology Consulting
3 * All rights reserved.
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 * Author: André Seznec, Pau Cabre, Javier Bueno
35 *
36 */
37
38/*
39 * TAGE-SC-L branch predictor base class (devised by Andre Seznec)
40 * It consits of a TAGE + a statistical corrector (SC) + a loop predictor (L)
41 */
42
43#include "cpu/pred/tage_sc_l.hh"
44
45#include "base/random.hh"
46#include "debug/TageSCL.hh"
47
48namespace gem5
49{
50
51namespace branch_prediction
52{
53
54bool
56{
59}
60
61bool
63{
64 return (random_mt.random<int>() & 7) == 0;
65}
66
67TAGE_SC_L::TAGE_SC_L(const TAGE_SC_LParams &p)
68 : LTAGE(p), statisticalCorrector(p.statistical_corrector)
69{
70}
71
74{
75 return new BranchInfo(*this);
76}
77void
79{
80 unsigned numHistLengths = nHistoryTables/2;
82 histLengths[numHistLengths] = maxHist;
83
84 // This calculates the different history lenghts
85 // there are only numHistLengths different lengths
86 // They are initially set to the lower half of histLengths
87 for (int i = 2; i <= numHistLengths; i++) {
88 histLengths[i] = (int) (((double) minHist *
89 pow ((double) (maxHist) / (double) minHist,
90 (double) (i - 1) / (double) ((numHistLengths - 1))))
91 + 0.5);
92 }
93
94 // This copies and duplicates the values from the lower half of the table
95 // Ex: 4, 6, 9, 13 would get exanded to 4, 4, 6, 6, 9, 9, 13, 13
96 for (int i = nHistoryTables; i > 1; i--)
97 {
98 histLengths[i] = histLengths[(i + 1) / 2];
99 }
100
101 for (int i = 1; i <= nHistoryTables; i++)
102 {
103 tagTableTagWidths.push_back(
105
107 }
108}
109
110void
112{
113 // Trick! We only allocate entries for tables 1 and firstLongTagTable and
114 // make the other tables point to these allocated entries
115
119 for (int i = 2; i < firstLongTagTable; ++i) {
120 gtable[i] = gtable[1];
121 }
122 for (int i = firstLongTagTable + 1; i <= nHistoryTables; ++i) {
124 }
125}
126
127void
130{
131 // computes the table addresses and the partial tags
132
133 for (int i = 1; i <= nHistoryTables; i += 2) {
134 tableIndices[i] = gindex(tid, pc, i);
135 tableTags[i] = gtag(tid, pc, i);
136 tableTags[i + 1] = tableTags[i];
137 tableIndices[i + 1] = tableIndices[i] ^
138 (tableTags[i] & ((1 << logTagTableSizes[i]) - 1));
139
140 bi->tableTags[i] = tableTags[i];
141 bi->tableTags[i+1] = tableTags[i+1];
142 }
143
144 Addr t = (pc ^ (threadHistory[tid].pathHist &
145 ((1 << histLengths[firstLongTagTable]) - 1)))
147
148 for (int i = firstLongTagTable; i <= nHistoryTables; i++) {
149 if (noSkip[i]) {
151 bi->tableIndices[i] = tableIndices[i];
152 t++;
154 }
155 }
156
157 t = (pc ^ (threadHistory[tid].pathHist & ((1 << histLengths[1]) - 1)))
159
160 for (int i = 1; i <= firstLongTagTable - 1; i++) {
161 if (noSkip[i]) {
163 bi->tableIndices[i] = tableIndices[i];
164 t++;
166 }
167 }
168}
169
170unsigned
172{
173 BranchInfo *tbi = static_cast<BranchInfo *>(bi);
174 unsigned idx;
175 idx = ((((bi->hitBank-1)/8)<<1)+tbi->altConf) % (numUseAltOnNa-1);
176 return idx;
177}
178
179int
181{
182 int index;
183 int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits :
184 histLengths[bank];
185 unsigned int shortPc = pc;
186
187 // pc is not shifted by instShiftAmt in this implementation
188 index = shortPc ^
189 (shortPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^
190 threadHistory[tid].computeIndices[bank].comp ^
191 F(threadHistory[tid].pathHist, hlen, bank);
192
193 index = gindex_ext(index, bank);
194
195 return (index & ((1ULL << (logTagTableSizes[bank])) - 1));
196}
197
198int
199TAGE_SC_L_TAGE::F(int a, int size, int bank) const
200{
201 int a1, a2;
202
203 a = a & ((1ULL << size) - 1);
204 a1 = (a & ((1ULL << logTagTableSizes[bank]) - 1));
205 a2 = (a >> logTagTableSizes[bank]);
206
207 if (bank < logTagTableSizes[bank]) {
208 a2 = ((a2 << bank) & ((1ULL << logTagTableSizes[bank]) - 1))
209 + (a2 >> (logTagTableSizes[bank] - bank));
210 }
211
212 a = a1 ^ a2;
213
214 if (bank < logTagTableSizes[bank]) {
215 a = ((a << bank) & ((1ULL << logTagTableSizes[bank]) - 1))
216 + (a >> (logTagTableSizes[bank] - bank));
217 }
218
219 return a;
220}
221
222int
224{
225 return ((pc ^ (pc >> instShiftAmt)) &
226 ((1ULL << (logTagTableSizes[0])) - 1));
227}
228
229void
231 ThreadHistory& tHist, int brtype, bool taken, Addr branch_pc, Addr target)
232{
233 // TAGE update
234 int tmp = ((branch_pc ^ (branch_pc >> instShiftAmt))) ^ taken;
235 int path = branch_pc ^ (branch_pc >> instShiftAmt)
236 ^ (branch_pc >> (instShiftAmt+2));
237 if ((brtype == 3) & taken) {
238 tmp = (tmp ^ (target >> instShiftAmt));
239 path = path ^ (target >> instShiftAmt) ^ (target >> (instShiftAmt+2));
240 }
241
242 // some branch types use 3 bits in global history, the others just 2
243 int maxt = (brtype == 2) ? 3 : 2;
244
245 for (int t = 0; t < maxt; t++) {
246 bool dir = (tmp & 1);
247 tmp >>= 1;
248 int pathbit = (path & 127);
249 path >>= 1;
250 updateGHist(tHist.gHist, dir, tHist.globalHistory, tHist.ptGhist);
251 tHist.pathHist = (tHist.pathHist << 1) ^ pathbit;
252 if (truncatePathHist) {
253 // The 8KB implementation does not do this truncation
254 tHist.pathHist = (tHist.pathHist & ((1ULL << pathHistBits) - 1));
255 }
256 for (int i = 1; i <= nHistoryTables; i++) {
257 tHist.computeIndices[i].update(tHist.gHist);
258 tHist.computeTags[0][i].update(tHist.gHist);
259 tHist.computeTags[1][i].update(tHist.gHist);
260 }
261 }
262}
263
264void
266 ThreadID tid, Addr branch_pc, bool taken, TAGEBase::BranchInfo* b,
267 bool speculative, const StaticInstPtr &inst, Addr target)
268{
269 if (speculative != speculativeHistUpdate) {
270 return;
271 }
272 // speculation is not implemented
273 assert(! speculative);
274
275 ThreadHistory& tHist = threadHistory[tid];
276
277 int brtype = inst->isDirectCtrl() ? 0 : 2;
278 if (! inst->isUncondCtrl()) {
279 ++brtype;
280 }
281 updatePathAndGlobalHistory(tHist, brtype, taken, branch_pc, target);
282
283 DPRINTF(TageSCL, "Updating global histories with branch:%lx; taken?:%d, "
284 "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist,
285 tHist.ptGhist);
286}
287
288void
290 Addr target)
291{
292 fatal("Speculation is not implemented");
293}
294
295void
296TAGE_SC_L_TAGE::adjustAlloc(bool & alloc, bool taken, bool pred_taken)
297{
298 // Do not allocate too often if the prediction is ok
299 if ((taken == pred_taken) && ((random_mt.random<int>() & 31) != 0)) {
300 alloc = false;
301 }
302}
303
304int
306{
307 int a = 1;
308 if ((random_mt.random<int>() & 127) < 32) {
309 a = 2;
310 }
311 return ((((bi->hitBank - 1 + 2 * a) & 0xffe)) ^
312 (random_mt.random<int>() & 1));
313}
314
315void
317{
318 //just the best formula for the Championship:
319 //In practice when one out of two entries are useful
320 if (tCounter < 0) {
321 tCounter = 0;
322 }
323
324 if (tCounter >= ((1ULL << logUResetPeriod))) {
325 // Update the u bits for the short tags table
326 for (int j = 0; j < (shortTagsTageFactor*(1<<logTagTableSize)); j++) {
327 resetUctr(gtable[1][j].u);
328 }
329
330 // Update the u bits for the long tags table
331 for (int j = 0; j < (longTagsTageFactor*(1<<logTagTableSize)); j++) {
333 }
334
335 tCounter = 0;
336 }
337}
338
339bool
341{
343 static_cast<TAGE_SC_L_TAGE::BranchInfo *>(tage_bi);
344
345 int bim = (btablePrediction[bi->bimodalIndex] << 1)
347
348 bi->highConf = (bim == 0) || (bim == 3);
349 bi->lowConf = ! bi->highConf;
350 bi->altConf = bi->highConf;
351 bi->medConf = false;
352 return TAGEBase::getBimodePred(pc, tage_bi);
353}
354
355void
357{
358 TAGE_SC_L_TAGE::BranchInfo *tage_scl_bi =
359 static_cast<TAGE_SC_L_TAGE::BranchInfo *>(bi);
360 int8_t ctr = gtable[bi->altBank][bi->altBankIndex].ctr;
361 tage_scl_bi->altConf = (abs(2*ctr + 1) > 1);
362}
363
364bool
365TAGE_SC_L::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b)
366{
370 b = (void*)(bi);
371
372 bool pred_taken = tage->tagePredict(tid, branch_pc, cond_branch,
373 bi->tageBranchInfo);
374 pred_taken = loopPredictor->loopPredict(tid, branch_pc, cond_branch,
375 bi->lpBranchInfo, pred_taken,
377
378 if (bi->lpBranchInfo->loopPredUsed) {
379 bi->tageBranchInfo->provider = LOOP;
380 }
381
382 TAGE_SC_L_TAGE::BranchInfo* tage_scl_bi =
383 static_cast<TAGE_SC_L_TAGE::BranchInfo *>(bi->tageBranchInfo);
384
385 // Copy the confidences computed by TAGE
386 bi->scBranchInfo->lowConf = tage_scl_bi->lowConf;
387 bi->scBranchInfo->highConf = tage_scl_bi->highConf;
388 bi->scBranchInfo->altConf = tage_scl_bi->altConf;
389 bi->scBranchInfo->medConf = tage_scl_bi->medConf;
390
391 bool use_tage_ctr = bi->tageBranchInfo->hitBank > 0;
392 int8_t tage_ctr = use_tage_ctr ?
393 tage->getCtr(tage_scl_bi->hitBank, tage_scl_bi->hitBankIndex) : 0;
394 bool bias = (bi->tageBranchInfo->longestMatchPred !=
395 bi->tageBranchInfo->altTaken);
396
397 pred_taken = statisticalCorrector->scPredict(tid, branch_pc, cond_branch,
398 bi->scBranchInfo, pred_taken, bias, use_tage_ctr, tage_ctr,
399 tage->getTageCtrBits(), bi->tageBranchInfo->hitBank,
400 bi->tageBranchInfo->altBank, tage->getPathHist(tid));
401
402 if (bi->scBranchInfo->usedScPred) {
403 bi->tageBranchInfo->provider = SC;
404 }
405
406 // record final prediction
407 bi->lpBranchInfo->predTaken = pred_taken;
408
409 return pred_taken;
410}
411
412void
413TAGE_SC_L::update(ThreadID tid, Addr branch_pc, bool taken, void *bp_history,
414 bool squashed, const StaticInstPtr & inst, Addr corrTarget)
415{
416 assert(bp_history);
417
418 TageSCLBranchInfo* bi = static_cast<TageSCLBranchInfo*>(bp_history);
420 static_cast<TAGE_SC_L_TAGE::BranchInfo *>(bi->tageBranchInfo);
421
422 if (squashed) {
424 // This restores the global history, then update it
425 // and recomputes the folded histories.
426 tage->squash(tid, taken, tage_bi, corrTarget);
427 if (bi->tageBranchInfo->condBranch) {
428 loopPredictor->squashLoop(bi->lpBranchInfo);
429 }
430 }
431 return;
432 }
433
434 int nrand = random_mt.random<int>() & 3;
435 if (tage_bi->condBranch) {
436 DPRINTF(TageSCL, "Updating tables for branch:%lx; taken?:%d\n",
437 branch_pc, taken);
438 tage->updateStats(taken, bi->tageBranchInfo);
439
440 loopPredictor->updateStats(taken, bi->lpBranchInfo);
441
442 statisticalCorrector->updateStats(taken, bi->scBranchInfo);
443
444 bool bias = (bi->tageBranchInfo->longestMatchPred !=
445 bi->tageBranchInfo->altTaken);
446 statisticalCorrector->condBranchUpdate(tid, branch_pc, taken,
447 bi->scBranchInfo, corrTarget, bias, bi->tageBranchInfo->hitBank,
448 bi->tageBranchInfo->altBank, tage->getPathHist(tid));
449
450 loopPredictor->condBranchUpdate(tid, branch_pc, taken,
451 bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt);
452
453 tage->condBranchUpdate(tid, branch_pc, taken, bi->tageBranchInfo,
454 nrand, corrTarget, bi->lpBranchInfo->predTaken);
455 }
456
458 statisticalCorrector->scHistoryUpdate(branch_pc, inst, taken,
459 bi->scBranchInfo, corrTarget);
460
461 tage->updateHistories(tid, branch_pc, taken, bi->tageBranchInfo, false,
462 inst, corrTarget);
463 }
464
465 delete bi;
466}
467
468} // namespace branch_prediction
469} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
static std::stack< std::string > path
Definition serialize.hh:315
bool isDirectCtrl() const
bool isUncondCtrl() const
const unsigned instShiftAmt
Number of bits to shift instructions by for predictor addresses.
LoopPredictor * loopPredictor
The loop predictor object.
Definition ltage.hh:81
void updateStats(bool taken, BranchInfo *bi)
Update the stats.
void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, bool tage_pred, BranchInfo *bi, unsigned instShiftAmt)
Update LTAGE for conditional branches.
virtual bool calcConf(int index) const
bool loopPredict(ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo *bi, bool prev_pred_taken, unsigned instShiftAmt)
Get the loop prediction.
virtual void scHistoryUpdate(Addr branch_pc, const StaticInstPtr &inst, bool taken, BranchInfo *tage_bi, Addr corrTarget)
virtual bool scPredict(ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo *bi, bool prev_pred_taken, bool bias_bit, bool use_conf_ctr, int8_t conf_ctr, unsigned conf_bits, int hitBank, int altBank, int64_t phist, int init_lsum=0)
virtual void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, BranchInfo *bi, Addr corrTarget, bool bias_bit, int hitBank, int altBank, int64_t phist)
virtual void updateHistories(ThreadID tid, Addr branch_pc, bool taken, BranchInfo *b, bool speculative, const StaticInstPtr &inst=nullStaticInstPtr, Addr target=MaxAddr)
(Speculatively) updates global histories (path and direction).
Definition tage_base.cc:588
virtual void resetUctr(uint8_t &u)
Algorithm for resetting a single U counter.
Definition tage_base.cc:508
virtual void updateStats(bool taken, BranchInfo *bi)
Update the stats.
Definition tage_base.cc:662
const unsigned logRatioBiModalHystEntries
Definition tage_base.hh:424
std::vector< bool > btableHysteresis
Definition tage_base.hh:437
void updateGHist(uint8_t *&h, bool dir, uint8_t *tab, int &PT)
(Speculatively) updates the global branch history.
Definition tage_base.cc:322
std::vector< bool > btablePrediction
Definition tage_base.hh:436
std::vector< ThreadHistory > threadHistory
Definition tage_base.hh:464
virtual bool getBimodePred(Addr pc, BranchInfo *bi) const
Get a branch prediction from the bimodal predictor.
Definition tage_base.cc:293
int8_t getCtr(int hitBank, int hitBankIndex) const
Definition tage_base.cc:768
std::vector< int > logTagTableSizes
Definition tage_base.hh:434
virtual void squash(ThreadID tid, bool taken, BranchInfo *bi, Addr target)
Restores speculatively updated path and direction histories.
Definition tage_base.cc:629
bool tagePredict(ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo *bi)
TAGE prediction called from TAGE::predict.
Definition tage_base.cc:360
int getPathHist(ThreadID tid) const
Definition tage_base.cc:780
std::vector< unsigned > tagTableTagWidths
Definition tage_base.hh:433
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:514
virtual bool optionalAgeInc() const override
Definition tage_sc_l.cc:62
virtual bool calcConf(int index) const override
Definition tage_sc_l.cc:55
void updatePathAndGlobalHistory(ThreadHistory &tHist, int brtype, bool taken, Addr branch_pc, Addr target)
Definition tage_sc_l.cc:230
void extraAltCalc(TAGEBase::BranchInfo *bi) override
Extra steps for calculating altTaken For this base TAGE class it does nothing.
Definition tage_sc_l.cc:356
void calculateIndicesAndTags(ThreadID tid, Addr branch_pc, TAGEBase::BranchInfo *bi) override
On a prediction, calculates the TAGE indices and tags for all the different history lengths.
Definition tage_sc_l.cc:128
int bindex(Addr pc_in) const override
Computes the index used to access the bimodal table.
Definition tage_sc_l.cc:223
int calcDep(TAGEBase::BranchInfo *bi)
Definition tage_sc_l.cc:305
bool getBimodePred(Addr branch_pc, TAGEBase::BranchInfo *tage_bi) const override
Get a branch prediction from the bimodal predictor.
Definition tage_sc_l.cc:340
virtual TAGEBase::BranchInfo * makeBranchInfo() override
Definition tage_sc_l.cc:73
int gindex(ThreadID tid, Addr pc, int bank) const override
Computes the index used to access a partially tagged table.
Definition tage_sc_l.cc:180
virtual int gindex_ext(int index, int bank) const =0
int F(int phist, int size, int bank) const override
Utility function to shuffle the path history depending on which tagged table we are accessing.
Definition tage_sc_l.cc:199
void calculateParameters() override
Calculates the history lengths and some other paramters in derived classes.
Definition tage_sc_l.cc:78
void squash(ThreadID tid, bool taken, TAGEBase::BranchInfo *bi, Addr target) override
Restores speculatively updated path and direction histories.
Definition tage_sc_l.cc:289
void adjustAlloc(bool &alloc, bool taken, bool pred_taken) override
Extra calculation to tell whether TAGE allocaitons may happen or not on an update For this base TAGE ...
Definition tage_sc_l.cc:296
void buildTageTables() override
Instantiates the TAGE table entries.
Definition tage_sc_l.cc:111
unsigned getUseAltIdx(TAGEBase::BranchInfo *bi, Addr branch_pc) override
Calculation of the index for useAltPredForNewlyAllocated On this base TAGE implementation it is alway...
Definition tage_sc_l.cc:171
virtual uint16_t gtag(ThreadID tid, Addr pc, int bank) const override=0
Computes the partial tag of a tagged table.
void updateHistories(ThreadID tid, Addr branch_pc, bool taken, TAGEBase::BranchInfo *b, bool speculative, const StaticInstPtr &inst, Addr target) override
(Speculatively) updates global histories (path and direction).
Definition tage_sc_l.cc:265
void handleUReset() override
Handles the U bits reset.
Definition tage_sc_l.cc:316
void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, bool squashed, const StaticInstPtr &inst, Addr corrTarget) override
Updates the BP with taken/not taken information.
Definition tage_sc_l.cc:413
bool predict(ThreadID tid, Addr branch_pc, bool cond_branch, void *&b) override
Get a branch prediction from LTAGE.
Definition tage_sc_l.cc:365
TAGE_SC_L(const TAGE_SC_LParams &params)
Definition tage_sc_l.cc:67
StatisticalCorrector * statisticalCorrector
Definition tage_sc_l.hh:158
Random random_mt
Definition random.cc:99
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition random.hh:90
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
Bitfield< 22 > a1
Bitfield< 5 > t
Definition misc_types.hh:71
Bitfield< 7 > b
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 20 > tbi
Bitfield< 8 > a
Definition misc_types.hh:66
Bitfield< 22 > u
Bitfield< 24 > j
Definition misc_types.hh:57
Bitfield< 4 > pc
Bitfield< 30, 0 > index
Bitfield< 0 > p
Bitfield< 20, 16 > bi
Definition types.hh:80
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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

Generated on Mon Jul 10 2023 15:32:01 for gem5 by doxygen 1.9.7