tage_base.cc revision 13685
1/* 2 * Copyright (c) 2014 The University of Wisconsin 3 * 4 * Copyright (c) 2006 INRIA (Institut National de Recherche en 5 * Informatique et en Automatique / French National Research Institute 6 * for Computer Science and Applied Mathematics) 7 * 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are 12 * met: redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer; 14 * redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution; 17 * neither the name of the copyright holders nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais, 34 * from André Seznec's code. 35 */ 36 37/* @file 38 * Implementation of a TAGE branch predictor 39 */ 40 41#include "cpu/pred/tage_base.hh" 42 43#include "base/intmath.hh" 44#include "base/logging.hh" 45#include "debug/Fetch.hh" 46#include "debug/Tage.hh" 47 48TAGEBase::TAGEBase(const TAGEBaseParams *p) 49 : SimObject(p), 50 logRatioBiModalHystEntries(p->logRatioBiModalHystEntries), 51 nHistoryTables(p->nHistoryTables), 52 tagTableCounterBits(p->tagTableCounterBits), 53 tagTableUBits(p->tagTableUBits), 54 histBufferSize(p->histBufferSize), 55 minHist(p->minHist), 56 maxHist(p->maxHist), 57 pathHistBits(p->pathHistBits), 58 tagTableTagWidths(p->tagTableTagWidths), 59 logTagTableSizes(p->logTagTableSizes), 60 threadHistory(p->numThreads), 61 logUResetPeriod(p->logUResetPeriod), 62 numUseAltOnNa(p->numUseAltOnNa), 63 useAltOnNaBits(p->useAltOnNaBits), 64 maxNumAlloc(p->maxNumAlloc), 65 noSkip(p->noSkip), 66 speculativeHistUpdate(p->speculativeHistUpdate), 67 instShiftAmt(p->instShiftAmt) 68{ 69 if (noSkip.empty()) { 70 // Set all the table to enabled by default 71 noSkip.resize(nHistoryTables + 1, true); 72 } 73} 74 75TAGEBase::BranchInfo* 76TAGEBase::makeBranchInfo() { 77 return new BranchInfo(*this); 78} 79 80void 81TAGEBase::init() 82{ 83 // Current method for periodically resetting the u counter bits only 84 // works for 1 or 2 bits 85 // Also make sure that it is not 0 86 assert(tagTableUBits <= 2 && (tagTableUBits > 0)); 87 88 // we use int type for the path history, so it cannot be more than 89 // its size 90 assert(pathHistBits <= (sizeof(int)*8)); 91 92 // initialize the counter to half of the period 93 assert(logUResetPeriod != 0); 94 tCounter = ULL(1) << (logUResetPeriod - 1); 95 96 assert(histBufferSize > maxHist * 2); 97 98 useAltPredForNewlyAllocated.resize(numUseAltOnNa, 0); 99 100 for (auto& history : threadHistory) { 101 history.pathHist = 0; 102 history.globalHistory = new uint8_t[histBufferSize]; 103 history.gHist = history.globalHistory; 104 memset(history.gHist, 0, histBufferSize); 105 history.ptGhist = 0; 106 } 107 108 histLengths = new int [nHistoryTables+1]; 109 110 calculateParameters(); 111 112 assert(tagTableTagWidths.size() == (nHistoryTables+1)); 113 assert(logTagTableSizes.size() == (nHistoryTables+1)); 114 115 // First entry is for the Bimodal table and it is untagged in this 116 // implementation 117 assert(tagTableTagWidths[0] == 0); 118 119 for (auto& history : threadHistory) { 120 history.computeIndices = new FoldedHistory[nHistoryTables+1]; 121 history.computeTags[0] = new FoldedHistory[nHistoryTables+1]; 122 history.computeTags[1] = new FoldedHistory[nHistoryTables+1]; 123 124 initFoldedHistories(history); 125 } 126 127 const uint64_t bimodalTableSize = ULL(1) << logTagTableSizes[0]; 128 btablePrediction.resize(bimodalTableSize, false); 129 btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries, 130 true); 131 132 gtable = new TageEntry*[nHistoryTables + 1]; 133 buildTageTables(); 134 135 tableIndices = new int [nHistoryTables+1]; 136 tableTags = new int [nHistoryTables+1]; 137} 138 139void 140TAGEBase::initFoldedHistories(ThreadHistory & history) 141{ 142 for (int i = 1; i <= nHistoryTables; i++) { 143 history.computeIndices[i].init( 144 histLengths[i], (logTagTableSizes[i])); 145 history.computeTags[0][i].init( 146 history.computeIndices[i].origLength, tagTableTagWidths[i]); 147 history.computeTags[1][i].init( 148 history.computeIndices[i].origLength, tagTableTagWidths[i]-1); 149 DPRINTF(Tage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n", 150 histLengths[i], logTagTableSizes[i], tagTableTagWidths[i]); 151 } 152} 153 154void 155TAGEBase::buildTageTables() 156{ 157 for (int i = 1; i <= nHistoryTables; i++) { 158 gtable[i] = new TageEntry[1<<(logTagTableSizes[i])]; 159 } 160} 161 162void 163TAGEBase::calculateParameters() 164{ 165 histLengths[1] = minHist; 166 histLengths[nHistoryTables] = maxHist; 167 168 for (int i = 2; i <= nHistoryTables; i++) { 169 histLengths[i] = (int) (((double) minHist * 170 pow ((double) (maxHist) / (double) minHist, 171 (double) (i - 1) / (double) ((nHistoryTables- 1)))) 172 + 0.5); 173 } 174} 175 176void 177TAGEBase::btbUpdate(ThreadID tid, Addr branch_pc, BranchInfo* &bi) 178{ 179 if (speculativeHistUpdate) { 180 ThreadHistory& tHist = threadHistory[tid]; 181 DPRINTF(Tage, "BTB miss resets prediction: %lx\n", branch_pc); 182 assert(tHist.gHist == &tHist.globalHistory[tHist.ptGhist]); 183 tHist.gHist[0] = 0; 184 for (int i = 1; i <= nHistoryTables; i++) { 185 tHist.computeIndices[i].comp = bi->ci[i]; 186 tHist.computeTags[0][i].comp = bi->ct0[i]; 187 tHist.computeTags[1][i].comp = bi->ct1[i]; 188 tHist.computeIndices[i].update(tHist.gHist); 189 tHist.computeTags[0][i].update(tHist.gHist); 190 tHist.computeTags[1][i].update(tHist.gHist); 191 } 192 } 193} 194 195int 196TAGEBase::bindex(Addr pc_in) const 197{ 198 return ((pc_in >> instShiftAmt) & ((ULL(1) << (logTagTableSizes[0])) - 1)); 199} 200 201int 202TAGEBase::F(int A, int size, int bank) const 203{ 204 int A1, A2; 205 206 A = A & ((ULL(1) << size) - 1); 207 A1 = (A & ((ULL(1) << logTagTableSizes[bank]) - 1)); 208 A2 = (A >> logTagTableSizes[bank]); 209 A2 = ((A2 << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 210 + (A2 >> (logTagTableSizes[bank] - bank)); 211 A = A1 ^ A2; 212 A = ((A << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 213 + (A >> (logTagTableSizes[bank] - bank)); 214 return (A); 215} 216 217// gindex computes a full hash of pc, ghist and pathHist 218int 219TAGEBase::gindex(ThreadID tid, Addr pc, int bank) const 220{ 221 int index; 222 int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits : 223 histLengths[bank]; 224 const unsigned int shiftedPc = pc >> instShiftAmt; 225 index = 226 shiftedPc ^ 227 (shiftedPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^ 228 threadHistory[tid].computeIndices[bank].comp ^ 229 F(threadHistory[tid].pathHist, hlen, bank); 230 231 return (index & ((ULL(1) << (logTagTableSizes[bank])) - 1)); 232} 233 234 235// Tag computation 236uint16_t 237TAGEBase::gtag(ThreadID tid, Addr pc, int bank) const 238{ 239 int tag = (pc >> instShiftAmt) ^ 240 threadHistory[tid].computeTags[0][bank].comp ^ 241 (threadHistory[tid].computeTags[1][bank].comp << 1); 242 243 return (tag & ((ULL(1) << tagTableTagWidths[bank]) - 1)); 244} 245 246 247// Up-down saturating counter 248template<typename T> 249void 250TAGEBase::ctrUpdate(T & ctr, bool taken, int nbits) 251{ 252 assert(nbits <= sizeof(T) << 3); 253 if (taken) { 254 if (ctr < ((1 << (nbits - 1)) - 1)) 255 ctr++; 256 } else { 257 if (ctr > -(1 << (nbits - 1))) 258 ctr--; 259 } 260} 261 262// int8_t and int versions of this function may be needed 263template void TAGEBase::ctrUpdate(int8_t & ctr, bool taken, int nbits); 264template void TAGEBase::ctrUpdate(int & ctr, bool taken, int nbits); 265 266// Up-down unsigned saturating counter 267void 268TAGEBase::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits) 269{ 270 assert(nbits <= sizeof(uint8_t) << 3); 271 if (up) { 272 if (ctr < ((1 << nbits) - 1)) 273 ctr++; 274 } else { 275 if (ctr) 276 ctr--; 277 } 278} 279 280// Bimodal prediction 281bool 282TAGEBase::getBimodePred(Addr pc, BranchInfo* bi) const 283{ 284 return btablePrediction[bi->bimodalIndex]; 285} 286 287 288// Update the bimodal predictor: a hysteresis bit is shared among N prediction 289// bits (N = 2 ^ logRatioBiModalHystEntries) 290void 291TAGEBase::baseUpdate(Addr pc, bool taken, BranchInfo* bi) 292{ 293 int inter = (btablePrediction[bi->bimodalIndex] << 1) 294 + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries]; 295 if (taken) { 296 if (inter < 3) 297 inter++; 298 } else if (inter > 0) { 299 inter--; 300 } 301 const bool pred = inter >> 1; 302 const bool hyst = inter & 1; 303 btablePrediction[bi->bimodalIndex] = pred; 304 btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst; 305 DPRINTF(Tage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst); 306} 307 308// shifting the global history: we manage the history in a big table in order 309// to reduce simulation time 310void 311TAGEBase::updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &pt) 312{ 313 if (pt == 0) { 314 DPRINTF(Tage, "Rolling over the histories\n"); 315 // Copy beginning of globalHistoryBuffer to end, such that 316 // the last maxHist outcomes are still reachable 317 // through pt[0 .. maxHist - 1]. 318 for (int i = 0; i < maxHist; i++) 319 tab[histBufferSize - maxHist + i] = tab[i]; 320 pt = histBufferSize - maxHist; 321 h = &tab[pt]; 322 } 323 pt--; 324 h--; 325 h[0] = (dir) ? 1 : 0; 326} 327 328void 329TAGEBase::calculateIndicesAndTags(ThreadID tid, Addr branch_pc, 330 BranchInfo* bi) 331{ 332 // computes the table addresses and the partial tags 333 for (int i = 1; i <= nHistoryTables; i++) { 334 tableIndices[i] = gindex(tid, branch_pc, i); 335 bi->tableIndices[i] = tableIndices[i]; 336 tableTags[i] = gtag(tid, branch_pc, i); 337 bi->tableTags[i] = tableTags[i]; 338 } 339} 340 341unsigned 342TAGEBase::getUseAltIdx(BranchInfo* bi) 343{ 344 // There is only 1 counter on the base TAGE implementation 345 return 0; 346} 347 348bool 349TAGEBase::tagePredict(ThreadID tid, Addr branch_pc, 350 bool cond_branch, BranchInfo* bi) 351{ 352 Addr pc = branch_pc; 353 bool pred_taken = true; 354 355 if (cond_branch) { 356 // TAGE prediction 357 358 calculateIndicesAndTags(tid, pc, bi); 359 360 bi->bimodalIndex = bindex(pc); 361 362 bi->hitBank = 0; 363 bi->altBank = 0; 364 //Look for the bank with longest matching history 365 for (int i = nHistoryTables; i > 0; i--) { 366 if (noSkip[i] && 367 gtable[i][tableIndices[i]].tag == tableTags[i]) { 368 bi->hitBank = i; 369 bi->hitBankIndex = tableIndices[bi->hitBank]; 370 break; 371 } 372 } 373 //Look for the alternate bank 374 for (int i = bi->hitBank - 1; i > 0; i--) { 375 if (noSkip[i] && 376 gtable[i][tableIndices[i]].tag == tableTags[i]) { 377 bi->altBank = i; 378 bi->altBankIndex = tableIndices[bi->altBank]; 379 break; 380 } 381 } 382 //computes the prediction and the alternate prediction 383 if (bi->hitBank > 0) { 384 if (bi->altBank > 0) { 385 bi->altTaken = 386 gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0; 387 extraAltCalc(bi); 388 }else { 389 bi->altTaken = getBimodePred(pc, bi); 390 } 391 392 bi->longestMatchPred = 393 gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0; 394 bi->pseudoNewAlloc = 395 abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1; 396 397 //if the entry is recognized as a newly allocated entry and 398 //useAltPredForNewlyAllocated is positive use the alternate 399 //prediction 400 if ((useAltPredForNewlyAllocated[getUseAltIdx(bi)] < 0) || 401 ! bi->pseudoNewAlloc) { 402 bi->tagePred = bi->longestMatchPred; 403 bi->provider = TAGE_LONGEST_MATCH; 404 } else { 405 bi->tagePred = bi->altTaken; 406 bi->provider = bi->altBank ? TAGE_ALT_MATCH 407 : BIMODAL_ALT_MATCH; 408 } 409 } else { 410 bi->altTaken = getBimodePred(pc, bi); 411 bi->tagePred = bi->altTaken; 412 bi->longestMatchPred = bi->altTaken; 413 bi->provider = BIMODAL_ONLY; 414 } 415 //end TAGE prediction 416 417 pred_taken = (bi->tagePred); 418 DPRINTF(Tage, "Predict for %lx: taken?:%d, tagePred:%d, altPred:%d\n", 419 branch_pc, pred_taken, bi->tagePred, bi->altTaken); 420 } 421 bi->branchPC = branch_pc; 422 bi->condBranch = cond_branch; 423 return pred_taken; 424} 425 426void 427TAGEBase::adjustAlloc(bool & alloc, bool taken, bool pred_taken) 428{ 429 // Nothing for this base class implementation 430} 431 432void 433TAGEBase::handleAllocAndUReset(bool alloc, bool taken, BranchInfo* bi, 434 int nrand) 435{ 436 if (alloc) { 437 // is there some "unuseful" entry to allocate 438 uint8_t min = 1; 439 for (int i = nHistoryTables; i > bi->hitBank; i--) { 440 if (gtable[i][bi->tableIndices[i]].u < min) { 441 min = gtable[i][bi->tableIndices[i]].u; 442 } 443 } 444 445 // we allocate an entry with a longer history 446 // to avoid ping-pong, we do not choose systematically the next 447 // entry, but among the 3 next entries 448 int Y = nrand & 449 ((ULL(1) << (nHistoryTables - bi->hitBank - 1)) - 1); 450 int X = bi->hitBank + 1; 451 if (Y & 1) { 452 X++; 453 if (Y & 2) 454 X++; 455 } 456 // No entry available, forces one to be available 457 if (min > 0) { 458 gtable[X][bi->tableIndices[X]].u = 0; 459 } 460 461 462 //Allocate entries 463 unsigned numAllocated = 0; 464 for (int i = X; i <= nHistoryTables; i++) { 465 if ((gtable[i][bi->tableIndices[i]].u == 0)) { 466 gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; 467 gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1; 468 ++numAllocated; 469 if (numAllocated == maxNumAlloc) { 470 break; 471 } 472 } 473 } 474 } 475 476 tCounter++; 477 478 handleUReset(); 479} 480 481void 482TAGEBase::handleUReset() 483{ 484 //periodic reset of u: reset is not complete but bit by bit 485 if ((tCounter & ((ULL(1) << logUResetPeriod) - 1)) == 0) { 486 // reset least significant bit 487 // most significant bit becomes least significant bit 488 for (int i = 1; i <= nHistoryTables; i++) { 489 for (int j = 0; j < (ULL(1) << logTagTableSizes[i]); j++) { 490 resetUctr(gtable[i][j].u); 491 } 492 } 493 } 494} 495 496void 497TAGEBase::resetUctr(uint8_t & u) 498{ 499 u >>= 1; 500} 501 502void 503TAGEBase::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, 504 BranchInfo* bi, int nrand, Addr corrTarget, bool pred) 505{ 506 // TAGE UPDATE 507 // try to allocate a new entries only if prediction was wrong 508 bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables); 509 if (bi->hitBank > 0) { 510 // Manage the selection between longest matching and alternate 511 // matching for "pseudo"-newly allocated longest matching entry 512 bool PseudoNewAlloc = bi->pseudoNewAlloc; 513 // an entry is considered as newly allocated if its prediction 514 // counter is weak 515 if (PseudoNewAlloc) { 516 if (bi->longestMatchPred == taken) { 517 alloc = false; 518 } 519 // if it was delivering the correct prediction, no need to 520 // allocate new entry even if the overall prediction was false 521 if (bi->longestMatchPred != bi->altTaken) { 522 ctrUpdate(useAltPredForNewlyAllocated[getUseAltIdx(bi)], 523 bi->altTaken == taken, useAltOnNaBits); 524 } 525 } 526 } 527 528 adjustAlloc(alloc, taken, pred); 529 530 handleAllocAndUReset(alloc, taken, bi, nrand); 531 532 handleTAGEUpdate(branch_pc, taken, bi); 533} 534 535void 536TAGEBase::handleTAGEUpdate(Addr branch_pc, bool taken, BranchInfo* bi) 537{ 538 if (bi->hitBank > 0) { 539 DPRINTF(Tage, "Updating tag table entry (%d,%d) for branch %lx\n", 540 bi->hitBank, bi->hitBankIndex, branch_pc); 541 ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken, 542 tagTableCounterBits); 543 // if the provider entry is not certified to be useful also update 544 // the alternate prediction 545 if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) { 546 if (bi->altBank > 0) { 547 ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken, 548 tagTableCounterBits); 549 DPRINTF(Tage, "Updating tag table entry (%d,%d) for" 550 " branch %lx\n", bi->hitBank, bi->hitBankIndex, 551 branch_pc); 552 } 553 if (bi->altBank == 0) { 554 baseUpdate(branch_pc, taken, bi); 555 } 556 } 557 558 // update the u counter 559 if (bi->tagePred != bi->altTaken) { 560 unsignedCtrUpdate(gtable[bi->hitBank][bi->hitBankIndex].u, 561 bi->tagePred == taken, tagTableUBits); 562 } 563 } else { 564 baseUpdate(branch_pc, taken, bi); 565 } 566} 567 568void 569TAGEBase::updateHistories(ThreadID tid, Addr branch_pc, bool taken, 570 BranchInfo* bi, bool speculative, 571 const StaticInstPtr &inst, Addr target) 572{ 573 if (speculative != speculativeHistUpdate) { 574 return; 575 } 576 ThreadHistory& tHist = threadHistory[tid]; 577 // UPDATE HISTORIES 578 bool pathbit = ((branch_pc >> instShiftAmt) & 1); 579 //on a squash, return pointers to this and recompute indices. 580 //update user history 581 updateGHist(tHist.gHist, taken, tHist.globalHistory, tHist.ptGhist); 582 tHist.pathHist = (tHist.pathHist << 1) + pathbit; 583 tHist.pathHist = (tHist.pathHist & ((ULL(1) << pathHistBits) - 1)); 584 585 if (speculative) { 586 bi->ptGhist = tHist.ptGhist; 587 bi->pathHist = tHist.pathHist; 588 } 589 590 //prepare next index and tag computations for user branchs 591 for (int i = 1; i <= nHistoryTables; i++) 592 { 593 if (speculative) { 594 bi->ci[i] = tHist.computeIndices[i].comp; 595 bi->ct0[i] = tHist.computeTags[0][i].comp; 596 bi->ct1[i] = tHist.computeTags[1][i].comp; 597 } 598 tHist.computeIndices[i].update(tHist.gHist); 599 tHist.computeTags[0][i].update(tHist.gHist); 600 tHist.computeTags[1][i].update(tHist.gHist); 601 } 602 DPRINTF(Tage, "Updating global histories with branch:%lx; taken?:%d, " 603 "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist, 604 tHist.ptGhist); 605 assert(threadHistory[tid].gHist == 606 &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]); 607} 608 609void 610TAGEBase::squash(ThreadID tid, bool taken, TAGEBase::BranchInfo *bi, 611 Addr target) 612{ 613 if (!speculativeHistUpdate) { 614 /* If there are no speculative updates, no actions are needed */ 615 return; 616 } 617 618 ThreadHistory& tHist = threadHistory[tid]; 619 DPRINTF(Tage, "Restoring branch info: %lx; taken? %d; PathHistory:%x, " 620 "pointer:%d\n", bi->branchPC,taken, bi->pathHist, bi->ptGhist); 621 tHist.pathHist = bi->pathHist; 622 tHist.ptGhist = bi->ptGhist; 623 tHist.gHist = &(tHist.globalHistory[tHist.ptGhist]); 624 tHist.gHist[0] = (taken ? 1 : 0); 625 for (int i = 1; i <= nHistoryTables; i++) { 626 tHist.computeIndices[i].comp = bi->ci[i]; 627 tHist.computeTags[0][i].comp = bi->ct0[i]; 628 tHist.computeTags[1][i].comp = bi->ct1[i]; 629 tHist.computeIndices[i].update(tHist.gHist); 630 tHist.computeTags[0][i].update(tHist.gHist); 631 tHist.computeTags[1][i].update(tHist.gHist); 632 } 633} 634 635void 636TAGEBase::extraAltCalc(BranchInfo* bi) 637{ 638 // do nothing. This is only used in some derived classes 639 return; 640} 641 642void 643TAGEBase::updateStats(bool taken, BranchInfo* bi) 644{ 645 if (taken == bi->tagePred) { 646 // correct prediction 647 switch (bi->provider) { 648 case BIMODAL_ONLY: tageBimodalProviderCorrect++; break; 649 case TAGE_LONGEST_MATCH: tageLongestMatchProviderCorrect++; break; 650 case BIMODAL_ALT_MATCH: bimodalAltMatchProviderCorrect++; break; 651 case TAGE_ALT_MATCH: tageAltMatchProviderCorrect++; break; 652 } 653 } else { 654 // wrong prediction 655 switch (bi->provider) { 656 case BIMODAL_ONLY: tageBimodalProviderWrong++; break; 657 case TAGE_LONGEST_MATCH: 658 tageLongestMatchProviderWrong++; 659 if (bi->altTaken == taken) { 660 tageAltMatchProviderWouldHaveHit++; 661 } 662 break; 663 case BIMODAL_ALT_MATCH: 664 bimodalAltMatchProviderWrong++; 665 break; 666 case TAGE_ALT_MATCH: 667 tageAltMatchProviderWrong++; 668 break; 669 } 670 671 switch (bi->provider) { 672 case BIMODAL_ALT_MATCH: 673 case TAGE_ALT_MATCH: 674 if (bi->longestMatchPred == taken) { 675 tageLongestMatchProviderWouldHaveHit++; 676 } 677 } 678 } 679 680 switch (bi->provider) { 681 case TAGE_LONGEST_MATCH: 682 case TAGE_ALT_MATCH: 683 tageLongestMatchProvider[bi->hitBank]++; 684 tageAltMatchProvider[bi->altBank]++; 685 break; 686 } 687} 688 689unsigned 690TAGEBase::getGHR(ThreadID tid, BranchInfo *bi) const 691{ 692 unsigned val = 0; 693 for (unsigned i = 0; i < 32; i++) { 694 // Make sure we don't go out of bounds 695 int gh_offset = bi->ptGhist + i; 696 assert(&(threadHistory[tid].globalHistory[gh_offset]) < 697 threadHistory[tid].globalHistory + histBufferSize); 698 val |= ((threadHistory[tid].globalHistory[gh_offset] & 0x1) << i); 699 } 700 701 return val; 702} 703 704void 705TAGEBase::regStats() 706{ 707 tageLongestMatchProviderCorrect 708 .name(name() + ".tageLongestMatchProviderCorrect") 709 .desc("Number of times TAGE Longest Match is the provider and " 710 "the prediction is correct"); 711 712 tageAltMatchProviderCorrect 713 .name(name() + ".tageAltMatchProviderCorrect") 714 .desc("Number of times TAGE Alt Match is the provider and " 715 "the prediction is correct"); 716 717 bimodalAltMatchProviderCorrect 718 .name(name() + ".bimodalAltMatchProviderCorrect") 719 .desc("Number of times TAGE Alt Match is the bimodal and it is the " 720 "provider and the prediction is correct"); 721 722 tageBimodalProviderCorrect 723 .name(name() + ".tageBimodalProviderCorrect") 724 .desc("Number of times there are no hits on the TAGE tables " 725 "and the bimodal prediction is correct"); 726 727 tageLongestMatchProviderWrong 728 .name(name() + ".tageLongestMatchProviderWrong") 729 .desc("Number of times TAGE Longest Match is the provider and " 730 "the prediction is wrong"); 731 732 tageAltMatchProviderWrong 733 .name(name() + ".tageAltMatchProviderWrong") 734 .desc("Number of times TAGE Alt Match is the provider and " 735 "the prediction is wrong"); 736 737 bimodalAltMatchProviderWrong 738 .name(name() + ".bimodalAltMatchProviderWrong") 739 .desc("Number of times TAGE Alt Match is the bimodal and it is the " 740 "provider and the prediction is wrong"); 741 742 tageBimodalProviderWrong 743 .name(name() + ".tageBimodalProviderWrong") 744 .desc("Number of times there are no hits on the TAGE tables " 745 "and the bimodal prediction is wrong"); 746 747 tageAltMatchProviderWouldHaveHit 748 .name(name() + ".tageAltMatchProviderWouldHaveHit") 749 .desc("Number of times TAGE Longest Match is the provider, " 750 "the prediction is wrong and Alt Match prediction was correct"); 751 752 tageLongestMatchProviderWouldHaveHit 753 .name(name() + ".tageLongestMatchProviderWouldHaveHit") 754 .desc("Number of times TAGE Alt Match is the provider, the " 755 "prediction is wrong and Longest Match prediction was correct"); 756 757 tageLongestMatchProvider 758 .init(nHistoryTables + 1) 759 .name(name() + ".tageLongestMatchProvider") 760 .desc("TAGE provider for longest match"); 761 762 tageAltMatchProvider 763 .init(nHistoryTables + 1) 764 .name(name() + ".tageAltMatchProvider") 765 .desc("TAGE provider for alt match"); 766} 767 768int8_t 769TAGEBase::getCtr(int hitBank, int hitBankIndex) const 770{ 771 return gtable[hitBank][hitBankIndex].ctr; 772} 773 774unsigned 775TAGEBase::getTageCtrBits() const 776{ 777 return tagTableCounterBits; 778} 779 780int 781TAGEBase::getPathHist(ThreadID tid) const 782{ 783 return threadHistory[tid].pathHist; 784} 785 786bool 787TAGEBase::isSpeculativeUpdateEnabled() const 788{ 789 return speculativeHistUpdate; 790} 791 792TAGEBase* 793TAGEBaseParams::create() 794{ 795 return new TAGEBase(this); 796} 797