tage_base.cc revision 13626:d6a6358aa6db
16313Sgblack@eecs.umich.edu/* 212529Sgiacomo.travaglini@arm.com * Copyright (c) 2014 The University of Wisconsin 37093Sgblack@eecs.umich.edu * 47093Sgblack@eecs.umich.edu * Copyright (c) 2006 INRIA (Institut National de Recherche en 57093Sgblack@eecs.umich.edu * Informatique et en Automatique / French National Research Institute 67093Sgblack@eecs.umich.edu * for Computer Science and Applied Mathematics) 77093Sgblack@eecs.umich.edu * 87093Sgblack@eecs.umich.edu * All rights reserved. 97093Sgblack@eecs.umich.edu * 107093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 117093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 127093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 137093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 146313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 156313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 166313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 176313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 186313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 196313Sgblack@eecs.umich.edu * this software without specific prior written permission. 206313Sgblack@eecs.umich.edu * 216313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 226313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 236313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 246313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 256313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 266313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 276313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 286313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 296313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 306313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 316313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 326313Sgblack@eecs.umich.edu * 336313Sgblack@eecs.umich.edu * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais, 346313Sgblack@eecs.umich.edu * from André Seznec's code. 356313Sgblack@eecs.umich.edu */ 366313Sgblack@eecs.umich.edu 376313Sgblack@eecs.umich.edu/* @file 386313Sgblack@eecs.umich.edu * Implementation of a TAGE branch predictor 396313Sgblack@eecs.umich.edu */ 406313Sgblack@eecs.umich.edu 416313Sgblack@eecs.umich.edu#include "cpu/pred/tage_base.hh" 426313Sgblack@eecs.umich.edu 436313Sgblack@eecs.umich.edu#include "base/intmath.hh" 447404SAli.Saidi@ARM.com#include "base/logging.hh" 456313Sgblack@eecs.umich.edu#include "base/random.hh" 4610461SAndreas.Sandberg@ARM.com#include "debug/Fetch.hh" 4712479SCurtis.Dunham@arm.com#include "debug/Tage.hh" 486333Sgblack@eecs.umich.edu 4910037SARM gem5 DevelopersTAGEBase::TAGEBase(const TAGEBaseParams *p) 507404SAli.Saidi@ARM.com : SimObject(p), 516313Sgblack@eecs.umich.edu logRatioBiModalHystEntries(p->logRatioBiModalHystEntries), 5212109SRekai.GonzalezAlberquilla@arm.com nHistoryTables(p->nHistoryTables), 538232Snate@binkert.org tagTableCounterBits(p->tagTableCounterBits), 5412109SRekai.GonzalezAlberquilla@arm.com tagTableUBits(p->tagTableUBits), 559384SAndreas.Sandberg@arm.com histBufferSize(p->histBufferSize), 5611165SRekai.GonzalezAlberquilla@arm.com minHist(p->minHist), 576313Sgblack@eecs.umich.edu maxHist(p->maxHist), 589384SAndreas.Sandberg@arm.com pathHistBits(p->pathHistBits), 5910461SAndreas.Sandberg@ARM.com tagTableTagWidths(p->tagTableTagWidths), 606333Sgblack@eecs.umich.edu logTagTableSizes(p->logTagTableSizes), 616313Sgblack@eecs.umich.edu threadHistory(p->numThreads), 626313Sgblack@eecs.umich.edu logUResetPeriod(p->logUResetPeriod), 636313Sgblack@eecs.umich.edu numUseAltOnNa(p->numUseAltOnNa), 646313Sgblack@eecs.umich.edu useAltOnNaBits(p->useAltOnNaBits), 656313Sgblack@eecs.umich.edu maxNumAlloc(p->maxNumAlloc), 669384SAndreas.Sandberg@arm.com noSkip(p->noSkip), 676313Sgblack@eecs.umich.edu speculativeHistUpdate(p->speculativeHistUpdate), 686313Sgblack@eecs.umich.edu instShiftAmt(p->instShiftAmt) 6910037SARM gem5 Developers{ 7010037SARM gem5 Developers if (noSkip.empty()) { 7110037SARM gem5 Developers // Set all the table to enabled by default 7211165SRekai.GonzalezAlberquilla@arm.com noSkip.resize(nHistoryTables + 1, true); 7311165SRekai.GonzalezAlberquilla@arm.com } 7412109SRekai.GonzalezAlberquilla@arm.com} 7511165SRekai.GonzalezAlberquilla@arm.com 7610461SAndreas.Sandberg@ARM.comTAGEBase::BranchInfo* 7710461SAndreas.Sandberg@ARM.comTAGEBase::makeBranchInfo() { 7810461SAndreas.Sandberg@ARM.com return new BranchInfo(*this); 7910461SAndreas.Sandberg@ARM.com} 8010461SAndreas.Sandberg@ARM.com 8110461SAndreas.Sandberg@ARM.comvoid 8210844Sandreas.sandberg@arm.comTAGEBase::init() 8310844Sandreas.sandberg@arm.com{ 8410844Sandreas.sandberg@arm.com // Current method for periodically resetting the u counter bits only 8513531Sjairo.balart@metempsy.com // works for 1 or 2 bits 8613531Sjairo.balart@metempsy.com // Also make sure that it is not 0 8713531Sjairo.balart@metempsy.com assert(tagTableUBits <= 2 && (tagTableUBits > 0)); 8810037SARM gem5 Developers 8911771SCurtis.Dunham@arm.com // we use int type for the path history, so it cannot be more than 9010037SARM gem5 Developers // its size 9110037SARM gem5 Developers assert(pathHistBits <= (sizeof(int)*8)); 9210037SARM gem5 Developers 9313173Sgiacomo.travaglini@arm.com // initialize the counter to half of the period 9410037SARM gem5 Developers assert(logUResetPeriod != 0); 9513531Sjairo.balart@metempsy.com tCounter = ULL(1) << (logUResetPeriod - 1); 9613114Sgiacomo.travaglini@arm.com 9710037SARM gem5 Developers assert(histBufferSize > maxHist * 2); 9812714Sgiacomo.travaglini@arm.com 9912714Sgiacomo.travaglini@arm.com useAltPredForNewlyAllocated.resize(numUseAltOnNa, 0); 10012714Sgiacomo.travaglini@arm.com 10112714Sgiacomo.travaglini@arm.com for (auto& history : threadHistory) { 10212714Sgiacomo.travaglini@arm.com history.pathHist = 0; 10312714Sgiacomo.travaglini@arm.com history.globalHistory = new uint8_t[histBufferSize]; 10412478SCurtis.Dunham@arm.com history.gHist = history.globalHistory; 10510037SARM gem5 Developers memset(history.gHist, 0, histBufferSize); 10612477SCurtis.Dunham@arm.com history.ptGhist = 0; 10712477SCurtis.Dunham@arm.com } 10812478SCurtis.Dunham@arm.com 10912478SCurtis.Dunham@arm.com histLengths = new int [nHistoryTables+1]; 11012478SCurtis.Dunham@arm.com 11112478SCurtis.Dunham@arm.com calculateParameters(); 11212478SCurtis.Dunham@arm.com 11312478SCurtis.Dunham@arm.com assert(tagTableTagWidths.size() == (nHistoryTables+1)); 11412478SCurtis.Dunham@arm.com assert(logTagTableSizes.size() == (nHistoryTables+1)); 11512478SCurtis.Dunham@arm.com 11612478SCurtis.Dunham@arm.com // First entry is for the Bimodal table and it is untagged in this 11712478SCurtis.Dunham@arm.com // implementation 11812478SCurtis.Dunham@arm.com assert(tagTableTagWidths[0] == 0); 11912478SCurtis.Dunham@arm.com 12012478SCurtis.Dunham@arm.com for (auto& history : threadHistory) { 12112478SCurtis.Dunham@arm.com history.computeIndices = new FoldedHistory[nHistoryTables+1]; 12212478SCurtis.Dunham@arm.com history.computeTags[0] = new FoldedHistory[nHistoryTables+1]; 12312478SCurtis.Dunham@arm.com history.computeTags[1] = new FoldedHistory[nHistoryTables+1]; 12410037SARM gem5 Developers 12510037SARM gem5 Developers initFoldedHistories(history); 12612477SCurtis.Dunham@arm.com } 12712479SCurtis.Dunham@arm.com 12812477SCurtis.Dunham@arm.com const uint64_t bimodalTableSize = ULL(1) << logTagTableSizes[0]; 12912477SCurtis.Dunham@arm.com btablePrediction.resize(bimodalTableSize, false); 13012477SCurtis.Dunham@arm.com btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries, 13112479SCurtis.Dunham@arm.com true); 13212477SCurtis.Dunham@arm.com 13312477SCurtis.Dunham@arm.com gtable = new TageEntry*[nHistoryTables + 1]; 13412477SCurtis.Dunham@arm.com buildTageTables(); 13512477SCurtis.Dunham@arm.com 13612477SCurtis.Dunham@arm.com tableIndices = new int [nHistoryTables+1]; 13712477SCurtis.Dunham@arm.com tableTags = new int [nHistoryTables+1]; 13812477SCurtis.Dunham@arm.com} 13912478SCurtis.Dunham@arm.com 14012478SCurtis.Dunham@arm.comvoid 14112478SCurtis.Dunham@arm.comTAGEBase::initFoldedHistories(ThreadHistory & history) 14212478SCurtis.Dunham@arm.com{ 14312478SCurtis.Dunham@arm.com for (int i = 1; i <= nHistoryTables; i++) { 14412478SCurtis.Dunham@arm.com history.computeIndices[i].init( 14512478SCurtis.Dunham@arm.com histLengths[i], (logTagTableSizes[i])); 14612478SCurtis.Dunham@arm.com history.computeTags[0][i].init( 14712478SCurtis.Dunham@arm.com history.computeIndices[i].origLength, tagTableTagWidths[i]); 14812478SCurtis.Dunham@arm.com history.computeTags[1][i].init( 14912478SCurtis.Dunham@arm.com history.computeIndices[i].origLength, tagTableTagWidths[i]-1); 15012478SCurtis.Dunham@arm.com DPRINTF(Tage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n", 15112478SCurtis.Dunham@arm.com histLengths[i], logTagTableSizes[i], tagTableTagWidths[i]); 15212478SCurtis.Dunham@arm.com } 15312478SCurtis.Dunham@arm.com} 15412478SCurtis.Dunham@arm.com 15512479SCurtis.Dunham@arm.comvoid 15612479SCurtis.Dunham@arm.comTAGEBase::buildTageTables() 15712479SCurtis.Dunham@arm.com{ 15812479SCurtis.Dunham@arm.com for (int i = 1; i <= nHistoryTables; i++) { 15912479SCurtis.Dunham@arm.com gtable[i] = new TageEntry[1<<(logTagTableSizes[i])]; 16012479SCurtis.Dunham@arm.com } 16112479SCurtis.Dunham@arm.com} 16212479SCurtis.Dunham@arm.com 16312479SCurtis.Dunham@arm.comvoid 16412479SCurtis.Dunham@arm.comTAGEBase::calculateParameters() 16512479SCurtis.Dunham@arm.com{ 16612479SCurtis.Dunham@arm.com histLengths[1] = minHist; 16712479SCurtis.Dunham@arm.com histLengths[nHistoryTables] = maxHist; 16812479SCurtis.Dunham@arm.com 16912479SCurtis.Dunham@arm.com for (int i = 2; i <= nHistoryTables; i++) { 17012479SCurtis.Dunham@arm.com histLengths[i] = (int) (((double) minHist * 17112479SCurtis.Dunham@arm.com pow ((double) (maxHist) / (double) minHist, 17212479SCurtis.Dunham@arm.com (double) (i - 1) / (double) ((nHistoryTables- 1)))) 17312479SCurtis.Dunham@arm.com + 0.5); 17412479SCurtis.Dunham@arm.com } 17512479SCurtis.Dunham@arm.com} 17612479SCurtis.Dunham@arm.com 17712479SCurtis.Dunham@arm.comvoid 17812479SCurtis.Dunham@arm.comTAGEBase::btbUpdate(ThreadID tid, Addr branch_pc, BranchInfo* &bi) 17912479SCurtis.Dunham@arm.com{ 18012479SCurtis.Dunham@arm.com if (speculativeHistUpdate) { 18112479SCurtis.Dunham@arm.com ThreadHistory& tHist = threadHistory[tid]; 18212479SCurtis.Dunham@arm.com DPRINTF(Tage, "BTB miss resets prediction: %lx\n", branch_pc); 18312479SCurtis.Dunham@arm.com assert(tHist.gHist == &tHist.globalHistory[tHist.ptGhist]); 18412479SCurtis.Dunham@arm.com tHist.gHist[0] = 0; 18512479SCurtis.Dunham@arm.com for (int i = 1; i <= nHistoryTables; i++) { 18612479SCurtis.Dunham@arm.com tHist.computeIndices[i].comp = bi->ci[i]; 18712479SCurtis.Dunham@arm.com tHist.computeTags[0][i].comp = bi->ct0[i]; 18812479SCurtis.Dunham@arm.com tHist.computeTags[1][i].comp = bi->ct1[i]; 18912479SCurtis.Dunham@arm.com tHist.computeIndices[i].update(tHist.gHist); 19012479SCurtis.Dunham@arm.com tHist.computeTags[0][i].update(tHist.gHist); 19112479SCurtis.Dunham@arm.com tHist.computeTags[1][i].update(tHist.gHist); 19212479SCurtis.Dunham@arm.com } 19312479SCurtis.Dunham@arm.com } 19412479SCurtis.Dunham@arm.com} 19512479SCurtis.Dunham@arm.com 19612479SCurtis.Dunham@arm.comint 19712479SCurtis.Dunham@arm.comTAGEBase::bindex(Addr pc_in) const 19812479SCurtis.Dunham@arm.com{ 19912479SCurtis.Dunham@arm.com return ((pc_in >> instShiftAmt) & ((ULL(1) << (logTagTableSizes[0])) - 1)); 20012479SCurtis.Dunham@arm.com} 20112479SCurtis.Dunham@arm.com 20212479SCurtis.Dunham@arm.comint 20312479SCurtis.Dunham@arm.comTAGEBase::F(int A, int size, int bank) const 20412479SCurtis.Dunham@arm.com{ 20512479SCurtis.Dunham@arm.com int A1, A2; 20612479SCurtis.Dunham@arm.com 20712479SCurtis.Dunham@arm.com A = A & ((ULL(1) << size) - 1); 20812479SCurtis.Dunham@arm.com A1 = (A & ((ULL(1) << logTagTableSizes[bank]) - 1)); 20912479SCurtis.Dunham@arm.com A2 = (A >> logTagTableSizes[bank]); 21012479SCurtis.Dunham@arm.com A2 = ((A2 << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 21112479SCurtis.Dunham@arm.com + (A2 >> (logTagTableSizes[bank] - bank)); 21212479SCurtis.Dunham@arm.com A = A1 ^ A2; 21312668Sgiacomo.travaglini@arm.com A = ((A << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 21412668Sgiacomo.travaglini@arm.com + (A >> (logTagTableSizes[bank] - bank)); 21512668Sgiacomo.travaglini@arm.com return (A); 21612668Sgiacomo.travaglini@arm.com} 21712668Sgiacomo.travaglini@arm.com 21812479SCurtis.Dunham@arm.com// gindex computes a full hash of pc, ghist and pathHist 21912479SCurtis.Dunham@arm.comint 22012479SCurtis.Dunham@arm.comTAGEBase::gindex(ThreadID tid, Addr pc, int bank) const 22112479SCurtis.Dunham@arm.com{ 22212479SCurtis.Dunham@arm.com int index; 22312479SCurtis.Dunham@arm.com int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits : 22412479SCurtis.Dunham@arm.com histLengths[bank]; 22512479SCurtis.Dunham@arm.com const unsigned int shiftedPc = pc >> instShiftAmt; 22612479SCurtis.Dunham@arm.com index = 22712479SCurtis.Dunham@arm.com shiftedPc ^ 22812479SCurtis.Dunham@arm.com (shiftedPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^ 22912479SCurtis.Dunham@arm.com threadHistory[tid].computeIndices[bank].comp ^ 23012479SCurtis.Dunham@arm.com F(threadHistory[tid].pathHist, hlen, bank); 23112668Sgiacomo.travaglini@arm.com 23212668Sgiacomo.travaglini@arm.com return (index & ((ULL(1) << (logTagTableSizes[bank])) - 1)); 23312668Sgiacomo.travaglini@arm.com} 23412668Sgiacomo.travaglini@arm.com 23512668Sgiacomo.travaglini@arm.com 23613395Sgiacomo.travaglini@arm.com// Tag computation 23713395Sgiacomo.travaglini@arm.comuint16_t 23813395Sgiacomo.travaglini@arm.comTAGEBase::gtag(ThreadID tid, Addr pc, int bank) const 23913395Sgiacomo.travaglini@arm.com{ 24013395Sgiacomo.travaglini@arm.com int tag = (pc >> instShiftAmt) ^ 24112479SCurtis.Dunham@arm.com threadHistory[tid].computeTags[0][bank].comp ^ 24212479SCurtis.Dunham@arm.com (threadHistory[tid].computeTags[1][bank].comp << 1); 24312479SCurtis.Dunham@arm.com 24412479SCurtis.Dunham@arm.com return (tag & ((ULL(1) << tagTableTagWidths[bank]) - 1)); 24512479SCurtis.Dunham@arm.com} 24612479SCurtis.Dunham@arm.com 24712479SCurtis.Dunham@arm.com 24812479SCurtis.Dunham@arm.com// Up-down saturating counter 24912479SCurtis.Dunham@arm.comtemplate<typename T> 25012479SCurtis.Dunham@arm.comvoid 25112479SCurtis.Dunham@arm.comTAGEBase::ctrUpdate(T & ctr, bool taken, int nbits) 25212479SCurtis.Dunham@arm.com{ 25312479SCurtis.Dunham@arm.com assert(nbits <= sizeof(T) << 3); 25412479SCurtis.Dunham@arm.com if (taken) { 25512479SCurtis.Dunham@arm.com if (ctr < ((1 << (nbits - 1)) - 1)) 25612479SCurtis.Dunham@arm.com ctr++; 25712479SCurtis.Dunham@arm.com } else { 25812479SCurtis.Dunham@arm.com if (ctr > -(1 << (nbits - 1))) 25912479SCurtis.Dunham@arm.com ctr--; 26012479SCurtis.Dunham@arm.com } 26112479SCurtis.Dunham@arm.com} 26212479SCurtis.Dunham@arm.com 26312479SCurtis.Dunham@arm.com// int8_t and int versions of this function may be needed 26412479SCurtis.Dunham@arm.comtemplate void TAGEBase::ctrUpdate(int8_t & ctr, bool taken, int nbits); 26512479SCurtis.Dunham@arm.comtemplate void TAGEBase::ctrUpdate(int & ctr, bool taken, int nbits); 26612479SCurtis.Dunham@arm.com 26712479SCurtis.Dunham@arm.com// Up-down unsigned saturating counter 26812479SCurtis.Dunham@arm.comvoid 26912479SCurtis.Dunham@arm.comTAGEBase::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits) 27012479SCurtis.Dunham@arm.com{ 27112479SCurtis.Dunham@arm.com assert(nbits <= sizeof(uint8_t) << 3); 27212479SCurtis.Dunham@arm.com if (up) { 27312479SCurtis.Dunham@arm.com if (ctr < ((1 << nbits) - 1)) 27412479SCurtis.Dunham@arm.com ctr++; 27512479SCurtis.Dunham@arm.com } else { 27612479SCurtis.Dunham@arm.com if (ctr) 27712479SCurtis.Dunham@arm.com ctr--; 27812479SCurtis.Dunham@arm.com } 27912479SCurtis.Dunham@arm.com} 28012479SCurtis.Dunham@arm.com 28112479SCurtis.Dunham@arm.com// Bimodal prediction 28212479SCurtis.Dunham@arm.combool 28312479SCurtis.Dunham@arm.comTAGEBase::getBimodePred(Addr pc, BranchInfo* bi) const 28412479SCurtis.Dunham@arm.com{ 28512479SCurtis.Dunham@arm.com return btablePrediction[bi->bimodalIndex]; 28612479SCurtis.Dunham@arm.com} 28712479SCurtis.Dunham@arm.com 28812479SCurtis.Dunham@arm.com 28912479SCurtis.Dunham@arm.com// Update the bimodal predictor: a hysteresis bit is shared among N prediction 29012479SCurtis.Dunham@arm.com// bits (N = 2 ^ logRatioBiModalHystEntries) 29112479SCurtis.Dunham@arm.comvoid 29212479SCurtis.Dunham@arm.comTAGEBase::baseUpdate(Addr pc, bool taken, BranchInfo* bi) 29312479SCurtis.Dunham@arm.com{ 29412479SCurtis.Dunham@arm.com int inter = (btablePrediction[bi->bimodalIndex] << 1) 29512479SCurtis.Dunham@arm.com + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries]; 29612479SCurtis.Dunham@arm.com if (taken) { 29712479SCurtis.Dunham@arm.com if (inter < 3) 29812479SCurtis.Dunham@arm.com inter++; 29912479SCurtis.Dunham@arm.com } else if (inter > 0) { 30012479SCurtis.Dunham@arm.com inter--; 30112479SCurtis.Dunham@arm.com } 30212479SCurtis.Dunham@arm.com const bool pred = inter >> 1; 30312479SCurtis.Dunham@arm.com const bool hyst = inter & 1; 30412479SCurtis.Dunham@arm.com btablePrediction[bi->bimodalIndex] = pred; 30512479SCurtis.Dunham@arm.com btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst; 30612479SCurtis.Dunham@arm.com DPRINTF(Tage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst); 30712479SCurtis.Dunham@arm.com} 30812479SCurtis.Dunham@arm.com 30912479SCurtis.Dunham@arm.com// shifting the global history: we manage the history in a big table in order 31012479SCurtis.Dunham@arm.com// to reduce simulation time 31112479SCurtis.Dunham@arm.comvoid 31212479SCurtis.Dunham@arm.comTAGEBase::updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &pt) 31312479SCurtis.Dunham@arm.com{ 31412479SCurtis.Dunham@arm.com if (pt == 0) { 31512479SCurtis.Dunham@arm.com DPRINTF(Tage, "Rolling over the histories\n"); 31612479SCurtis.Dunham@arm.com // Copy beginning of globalHistoryBuffer to end, such that 31712479SCurtis.Dunham@arm.com // the last maxHist outcomes are still reachable 31812479SCurtis.Dunham@arm.com // through pt[0 .. maxHist - 1]. 31912479SCurtis.Dunham@arm.com for (int i = 0; i < maxHist; i++) 32012479SCurtis.Dunham@arm.com tab[histBufferSize - maxHist + i] = tab[i]; 32112479SCurtis.Dunham@arm.com pt = histBufferSize - maxHist; 32212479SCurtis.Dunham@arm.com h = &tab[pt]; 32312479SCurtis.Dunham@arm.com } 32412479SCurtis.Dunham@arm.com pt--; 32512479SCurtis.Dunham@arm.com h--; 32612479SCurtis.Dunham@arm.com h[0] = (dir) ? 1 : 0; 32712479SCurtis.Dunham@arm.com} 32812479SCurtis.Dunham@arm.com 32912479SCurtis.Dunham@arm.comvoid 33012479SCurtis.Dunham@arm.comTAGEBase::calculateIndicesAndTags(ThreadID tid, Addr branch_pc, 33112479SCurtis.Dunham@arm.com BranchInfo* bi) 33212479SCurtis.Dunham@arm.com{ 33312479SCurtis.Dunham@arm.com // computes the table addresses and the partial tags 33412479SCurtis.Dunham@arm.com for (int i = 1; i <= nHistoryTables; i++) { 33512479SCurtis.Dunham@arm.com tableIndices[i] = gindex(tid, branch_pc, i); 33612479SCurtis.Dunham@arm.com bi->tableIndices[i] = tableIndices[i]; 33712479SCurtis.Dunham@arm.com tableTags[i] = gtag(tid, branch_pc, i); 33812479SCurtis.Dunham@arm.com bi->tableTags[i] = tableTags[i]; 33912479SCurtis.Dunham@arm.com } 34012479SCurtis.Dunham@arm.com} 34112479SCurtis.Dunham@arm.com 34212479SCurtis.Dunham@arm.comunsigned 34312479SCurtis.Dunham@arm.comTAGEBase::getUseAltIdx(BranchInfo* bi) 34412479SCurtis.Dunham@arm.com{ 34512479SCurtis.Dunham@arm.com // There is only 1 counter on the base TAGE implementation 34612479SCurtis.Dunham@arm.com return 0; 34712479SCurtis.Dunham@arm.com} 34812479SCurtis.Dunham@arm.com 34912479SCurtis.Dunham@arm.combool 35012479SCurtis.Dunham@arm.comTAGEBase::tagePredict(ThreadID tid, Addr branch_pc, 35112479SCurtis.Dunham@arm.com bool cond_branch, BranchInfo* bi) 35212479SCurtis.Dunham@arm.com{ 35312479SCurtis.Dunham@arm.com Addr pc = branch_pc; 35412479SCurtis.Dunham@arm.com bool pred_taken = true; 35512479SCurtis.Dunham@arm.com 35610037SARM gem5 Developers if (cond_branch) { 35710037SARM gem5 Developers // TAGE prediction 35812477SCurtis.Dunham@arm.com 35912479SCurtis.Dunham@arm.com calculateIndicesAndTags(tid, pc, bi); 36012479SCurtis.Dunham@arm.com 36112477SCurtis.Dunham@arm.com bi->bimodalIndex = bindex(pc); 36210037SARM gem5 Developers 36312477SCurtis.Dunham@arm.com bi->hitBank = 0; 36410037SARM gem5 Developers bi->altBank = 0; 36513581Sgabeblack@google.com //Look for the bank with longest matching history 3666718Sgblack@eecs.umich.edu for (int i = nHistoryTables; i > 0; i--) { 3676718Sgblack@eecs.umich.edu if (noSkip[i] && 3686718Sgblack@eecs.umich.edu gtable[i][tableIndices[i]].tag == tableTags[i]) { 3696718Sgblack@eecs.umich.edu bi->hitBank = i; 3706718Sgblack@eecs.umich.edu bi->hitBankIndex = tableIndices[bi->hitBank]; 37110037SARM gem5 Developers break; 37210037SARM gem5 Developers } 37310037SARM gem5 Developers } 37410037SARM gem5 Developers //Look for the alternate bank 37510037SARM gem5 Developers for (int i = bi->hitBank - 1; i > 0; i--) { 37610037SARM gem5 Developers if (noSkip[i] && 37710037SARM gem5 Developers gtable[i][tableIndices[i]].tag == tableTags[i]) { 37810037SARM gem5 Developers bi->altBank = i; 37910037SARM gem5 Developers bi->altBankIndex = tableIndices[bi->altBank]; 38010037SARM gem5 Developers break; 38110037SARM gem5 Developers } 38210037SARM gem5 Developers } 38310037SARM gem5 Developers //computes the prediction and the alternate prediction 38410037SARM gem5 Developers if (bi->hitBank > 0) { 38510037SARM gem5 Developers if (bi->altBank > 0) { 38610037SARM gem5 Developers bi->altTaken = 38710037SARM gem5 Developers gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0; 38810037SARM gem5 Developers extraAltCalc(bi); 38910037SARM gem5 Developers }else { 39010037SARM gem5 Developers bi->altTaken = getBimodePred(pc, bi); 39110037SARM gem5 Developers } 39210037SARM gem5 Developers 39310037SARM gem5 Developers bi->longestMatchPred = 39410037SARM gem5 Developers gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0; 39510037SARM gem5 Developers bi->pseudoNewAlloc = 39610037SARM gem5 Developers abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1; 39710037SARM gem5 Developers 39810037SARM gem5 Developers //if the entry is recognized as a newly allocated entry and 39910037SARM gem5 Developers //useAltPredForNewlyAllocated is positive use the alternate 40010037SARM gem5 Developers //prediction 40110037SARM gem5 Developers if ((useAltPredForNewlyAllocated[getUseAltIdx(bi)] < 0) || 40210037SARM gem5 Developers ! bi->pseudoNewAlloc) { 4036718Sgblack@eecs.umich.edu bi->tagePred = bi->longestMatchPred; 4046718Sgblack@eecs.umich.edu bi->provider = TAGE_LONGEST_MATCH; 4056313Sgblack@eecs.umich.edu } else { 40610844Sandreas.sandberg@arm.com bi->tagePred = bi->altTaken; 40713531Sjairo.balart@metempsy.com bi->provider = bi->altBank ? TAGE_ALT_MATCH 40810037SARM gem5 Developers : BIMODAL_ALT_MATCH; 40910037SARM gem5 Developers } 41010037SARM gem5 Developers } else { 41110037SARM gem5 Developers bi->altTaken = getBimodePred(pc, bi); 41210037SARM gem5 Developers bi->tagePred = bi->altTaken; 41310037SARM gem5 Developers bi->longestMatchPred = bi->altTaken; 41410037SARM gem5 Developers bi->provider = BIMODAL_ONLY; 41510037SARM gem5 Developers } 41610037SARM gem5 Developers //end TAGE prediction 41710037SARM gem5 Developers 41810037SARM gem5 Developers pred_taken = (bi->tagePred); 41910037SARM gem5 Developers DPRINTF(Tage, "Predict for %lx: taken?:%d, tagePred:%d, altPred:%d\n", 42010037SARM gem5 Developers branch_pc, pred_taken, bi->tagePred, bi->altTaken); 4216313Sgblack@eecs.umich.edu } 4227427Sgblack@eecs.umich.edu bi->branchPC = branch_pc; 42313114Sgiacomo.travaglini@arm.com bi->condBranch = cond_branch; 42413114Sgiacomo.travaglini@arm.com return pred_taken; 42513393Sgiacomo.travaglini@arm.com} 42610037SARM gem5 Developers 42713114Sgiacomo.travaglini@arm.comvoid 42813114Sgiacomo.travaglini@arm.comTAGEBase::adjustAlloc(bool & alloc, bool taken) 4296313Sgblack@eecs.umich.edu{ 43013114Sgiacomo.travaglini@arm.com // Nothing for this base class implementation 43113581Sgabeblack@google.com} 43213581Sgabeblack@google.com 43313581Sgabeblack@google.comvoid 43413581Sgabeblack@google.comTAGEBase::handleAllocAndUReset(bool alloc, bool taken, BranchInfo* bi, 4356313Sgblack@eecs.umich.edu int nrand) 43612106SRekai.GonzalezAlberquilla@arm.com{ 43712106SRekai.GonzalezAlberquilla@arm.com if (alloc) { 43812106SRekai.GonzalezAlberquilla@arm.com // is there some "unuseful" entry to allocate 43912106SRekai.GonzalezAlberquilla@arm.com uint8_t min = 1; 44012106SRekai.GonzalezAlberquilla@arm.com for (int i = nHistoryTables; i > bi->hitBank; i--) { 44112106SRekai.GonzalezAlberquilla@arm.com if (gtable[i][bi->tableIndices[i]].u < min) { 44212106SRekai.GonzalezAlberquilla@arm.com min = gtable[i][bi->tableIndices[i]].u; 44312106SRekai.GonzalezAlberquilla@arm.com } 44412109SRekai.GonzalezAlberquilla@arm.com } 44512109SRekai.GonzalezAlberquilla@arm.com 44612109SRekai.GonzalezAlberquilla@arm.com // we allocate an entry with a longer history 44713545Sgiacomo.travaglini@arm.com // to avoid ping-pong, we do not choose systematically the next 44813545Sgiacomo.travaglini@arm.com // entry, but among the 3 next entries 44912106SRekai.GonzalezAlberquilla@arm.com int Y = nrand & 45012106SRekai.GonzalezAlberquilla@arm.com ((ULL(1) << (nHistoryTables - bi->hitBank - 1)) - 1); 45112106SRekai.GonzalezAlberquilla@arm.com int X = bi->hitBank + 1; 45212106SRekai.GonzalezAlberquilla@arm.com if (Y & 1) { 45312106SRekai.GonzalezAlberquilla@arm.com X++; 45412106SRekai.GonzalezAlberquilla@arm.com if (Y & 2) 45512106SRekai.GonzalezAlberquilla@arm.com X++; 45612106SRekai.GonzalezAlberquilla@arm.com } 4576313Sgblack@eecs.umich.edu // No entry available, forces one to be available 45810035Sandreas.hansson@arm.com if (min > 0) { 4596313Sgblack@eecs.umich.edu gtable[X][bi->tableIndices[X]].u = 0; 4606718Sgblack@eecs.umich.edu } 4616718Sgblack@eecs.umich.edu 4626718Sgblack@eecs.umich.edu 4636726Sgblack@eecs.umich.edu //Allocate entries 4646726Sgblack@eecs.umich.edu unsigned numAllocated = 0; 46510037SARM gem5 Developers for (int i = X; i <= nHistoryTables; i++) { 46610037SARM gem5 Developers if ((gtable[i][bi->tableIndices[i]].u == 0)) { 46710037SARM gem5 Developers gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; 46810037SARM gem5 Developers gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1; 46910037SARM gem5 Developers ++numAllocated; 47010037SARM gem5 Developers if (numAllocated == maxNumAlloc) { 47110037SARM gem5 Developers break; 47210037SARM gem5 Developers } 47310037SARM gem5 Developers } 47411574SCurtis.Dunham@arm.com } 47511574SCurtis.Dunham@arm.com } 47610037SARM gem5 Developers 47710037SARM gem5 Developers tCounter++; 47810037SARM gem5 Developers 47910037SARM gem5 Developers handleUReset(); 48010037SARM gem5 Developers} 48110037SARM gem5 Developers 48213020Sshunhsingou@google.comvoid 48310037SARM gem5 DevelopersTAGEBase::handleUReset() 4846718Sgblack@eecs.umich.edu{ 48510037SARM gem5 Developers //periodic reset of u: reset is not complete but bit by bit 4866718Sgblack@eecs.umich.edu if ((tCounter & ((ULL(1) << logUResetPeriod) - 1)) == 0) { 4876313Sgblack@eecs.umich.edu // reset least significant bit 4886313Sgblack@eecs.umich.edu // most significant bit becomes least significant bit 4896313Sgblack@eecs.umich.edu for (int i = 1; i <= nHistoryTables; i++) { 49010035Sandreas.hansson@arm.com for (int j = 0; j < (ULL(1) << logTagTableSizes[i]); j++) { 4916313Sgblack@eecs.umich.edu resetUctr(gtable[i][j].u); 49210338SCurtis.Dunham@arm.com } 4936313Sgblack@eecs.umich.edu } 4946313Sgblack@eecs.umich.edu } 4956313Sgblack@eecs.umich.edu} 4969920Syasuko.eckert@amd.com 49712109SRekai.GonzalezAlberquilla@arm.comvoid 49812109SRekai.GonzalezAlberquilla@arm.comTAGEBase::resetUctr(uint8_t & u) 49912109SRekai.GonzalezAlberquilla@arm.com{ 50012109SRekai.GonzalezAlberquilla@arm.com u >>= 1; 50112109SRekai.GonzalezAlberquilla@arm.com} 50212109SRekai.GonzalezAlberquilla@arm.com 50312109SRekai.GonzalezAlberquilla@arm.comvoid 50412109SRekai.GonzalezAlberquilla@arm.comTAGEBase::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, 50512109SRekai.GonzalezAlberquilla@arm.com BranchInfo* bi, int nrand, Addr corrTarget) 50612109SRekai.GonzalezAlberquilla@arm.com{ 50712109SRekai.GonzalezAlberquilla@arm.com // TAGE UPDATE 50812109SRekai.GonzalezAlberquilla@arm.com // try to allocate a new entries only if prediction was wrong 50912109SRekai.GonzalezAlberquilla@arm.com bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables); 51012109SRekai.GonzalezAlberquilla@arm.com if (bi->hitBank > 0) { 51110035Sandreas.hansson@arm.com // Manage the selection between longest matching and alternate 5129920Syasuko.eckert@amd.com // matching for "pseudo"-newly allocated longest matching entry 51310338SCurtis.Dunham@arm.com bool PseudoNewAlloc = bi->pseudoNewAlloc; 5149920Syasuko.eckert@amd.com // an entry is considered as newly allocated if its prediction 5159920Syasuko.eckert@amd.com // counter is weak 5169920Syasuko.eckert@amd.com if (PseudoNewAlloc) { 5177614Sminkyu.jeong@arm.com if (bi->longestMatchPred == taken) { 51810035Sandreas.hansson@arm.com alloc = false; 5197614Sminkyu.jeong@arm.com } 52010338SCurtis.Dunham@arm.com // if it was delivering the correct prediction, no need to 52110037SARM gem5 Developers // allocate new entry even if the overall prediction was false 52210037SARM gem5 Developers if (bi->longestMatchPred != bi->altTaken) { 5237614Sminkyu.jeong@arm.com ctrUpdate(useAltPredForNewlyAllocated[getUseAltIdx(bi)], 5247614Sminkyu.jeong@arm.com bi->altTaken == taken, useAltOnNaBits); 5257614Sminkyu.jeong@arm.com } 52610037SARM gem5 Developers } 52710037SARM gem5 Developers } 52810037SARM gem5 Developers 52910037SARM gem5 Developers adjustAlloc(alloc, taken); 53010037SARM gem5 Developers 53110037SARM gem5 Developers handleAllocAndUReset(alloc, taken, bi, nrand); 53210037SARM gem5 Developers 53310037SARM gem5 Developers handleTAGEUpdate(branch_pc, taken, bi); 53410037SARM gem5 Developers} 53510037SARM gem5 Developers 53610037SARM gem5 Developersvoid 53710037SARM gem5 DevelopersTAGEBase::handleTAGEUpdate(Addr branch_pc, bool taken, BranchInfo* bi) 53810037SARM gem5 Developers{ 53910037SARM gem5 Developers if (bi->hitBank > 0) { 54010037SARM gem5 Developers DPRINTF(Tage, "Updating tag table entry (%d,%d) for branch %lx\n", 54110037SARM gem5 Developers bi->hitBank, bi->hitBankIndex, branch_pc); 5427614Sminkyu.jeong@arm.com ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken, 5437614Sminkyu.jeong@arm.com tagTableCounterBits); 54410037SARM gem5 Developers // if the provider entry is not certified to be useful also update 5457614Sminkyu.jeong@arm.com // the alternate prediction 5467614Sminkyu.jeong@arm.com if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) { 54710037SARM gem5 Developers if (bi->altBank > 0) { 5487614Sminkyu.jeong@arm.com ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken, 5497614Sminkyu.jeong@arm.com tagTableCounterBits); 55010037SARM gem5 Developers DPRINTF(Tage, "Updating tag table entry (%d,%d) for" 5517614Sminkyu.jeong@arm.com " branch %lx\n", bi->hitBank, bi->hitBankIndex, 5527614Sminkyu.jeong@arm.com branch_pc); 55310037SARM gem5 Developers } 5547614Sminkyu.jeong@arm.com if (bi->altBank == 0) { 5557614Sminkyu.jeong@arm.com baseUpdate(branch_pc, taken, bi); 55610037SARM gem5 Developers } 5577614Sminkyu.jeong@arm.com } 5587614Sminkyu.jeong@arm.com 55910037SARM gem5 Developers // update the u counter 56010037SARM gem5 Developers if (bi->tagePred != bi->altTaken) { 56110037SARM gem5 Developers unsignedCtrUpdate(gtable[bi->hitBank][bi->hitBankIndex].u, 56210037SARM gem5 Developers bi->tagePred == taken, tagTableUBits); 5637614Sminkyu.jeong@arm.com } 5647614Sminkyu.jeong@arm.com } else { 56510037SARM gem5 Developers baseUpdate(branch_pc, taken, bi); 5667614Sminkyu.jeong@arm.com } 5677614Sminkyu.jeong@arm.com} 5687614Sminkyu.jeong@arm.com 5697614Sminkyu.jeong@arm.comvoid 57010037SARM gem5 DevelopersTAGEBase::updateHistories(ThreadID tid, Addr branch_pc, bool taken, 5717614Sminkyu.jeong@arm.com BranchInfo* bi, bool speculative, 5727614Sminkyu.jeong@arm.com const StaticInstPtr &inst, Addr target) 57310037SARM gem5 Developers{ 57410037SARM gem5 Developers if (speculative != speculativeHistUpdate) { 57510037SARM gem5 Developers return; 57610037SARM gem5 Developers } 57710037SARM gem5 Developers ThreadHistory& tHist = threadHistory[tid]; 57810037SARM gem5 Developers // UPDATE HISTORIES 57910037SARM gem5 Developers bool pathbit = ((branch_pc >> instShiftAmt) & 1); 58010037SARM gem5 Developers //on a squash, return pointers to this and recompute indices. 58110037SARM gem5 Developers //update user history 58210037SARM gem5 Developers updateGHist(tHist.gHist, taken, tHist.globalHistory, tHist.ptGhist); 58310037SARM gem5 Developers tHist.pathHist = (tHist.pathHist << 1) + pathbit; 58410037SARM gem5 Developers tHist.pathHist = (tHist.pathHist & ((ULL(1) << pathHistBits) - 1)); 58510037SARM gem5 Developers 58610037SARM gem5 Developers if (speculative) { 58710037SARM gem5 Developers bi->ptGhist = tHist.ptGhist; 58810037SARM gem5 Developers bi->pathHist = tHist.pathHist; 58910037SARM gem5 Developers } 59010037SARM gem5 Developers 59110037SARM gem5 Developers //prepare next index and tag computations for user branchs 59210037SARM gem5 Developers for (int i = 1; i <= nHistoryTables; i++) 59310037SARM gem5 Developers { 59410037SARM gem5 Developers if (speculative) { 59510037SARM gem5 Developers bi->ci[i] = tHist.computeIndices[i].comp; 59610037SARM gem5 Developers bi->ct0[i] = tHist.computeTags[0][i].comp; 59710037SARM gem5 Developers bi->ct1[i] = tHist.computeTags[1][i].comp; 59810037SARM gem5 Developers } 59910037SARM gem5 Developers tHist.computeIndices[i].update(tHist.gHist); 60010037SARM gem5 Developers tHist.computeTags[0][i].update(tHist.gHist); 60110037SARM gem5 Developers tHist.computeTags[1][i].update(tHist.gHist); 60210037SARM gem5 Developers } 60310037SARM gem5 Developers DPRINTF(Tage, "Updating global histories with branch:%lx; taken?:%d, " 60410037SARM gem5 Developers "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist, 60510037SARM gem5 Developers tHist.ptGhist); 60610037SARM gem5 Developers assert(threadHistory[tid].gHist == 60710037SARM gem5 Developers &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]); 60810037SARM gem5 Developers} 60910037SARM gem5 Developers 61010037SARM gem5 Developersvoid 61110037SARM gem5 DevelopersTAGEBase::squash(ThreadID tid, bool taken, TAGEBase::BranchInfo *bi, 61210037SARM gem5 Developers Addr target) 61310037SARM gem5 Developers{ 61410037SARM gem5 Developers if (!speculativeHistUpdate) { 61510037SARM gem5 Developers /* If there are no speculative updates, no actions are needed */ 61610037SARM gem5 Developers return; 61710037SARM gem5 Developers } 61810037SARM gem5 Developers 61910037SARM gem5 Developers ThreadHistory& tHist = threadHistory[tid]; 62010037SARM gem5 Developers DPRINTF(Tage, "Restoring branch info: %lx; taken? %d; PathHistory:%x, " 62110037SARM gem5 Developers "pointer:%d\n", bi->branchPC,taken, bi->pathHist, bi->ptGhist); 62210037SARM gem5 Developers tHist.pathHist = bi->pathHist; 62311771SCurtis.Dunham@arm.com tHist.ptGhist = bi->ptGhist; 62410037SARM gem5 Developers tHist.gHist = &(tHist.globalHistory[tHist.ptGhist]); 62510037SARM gem5 Developers tHist.gHist[0] = (taken ? 1 : 0); 62610037SARM gem5 Developers for (int i = 1; i <= nHistoryTables; i++) { 62710037SARM gem5 Developers tHist.computeIndices[i].comp = bi->ci[i]; 6287614Sminkyu.jeong@arm.com tHist.computeTags[0][i].comp = bi->ct0[i]; 62910037SARM gem5 Developers tHist.computeTags[1][i].comp = bi->ct1[i]; 6307614Sminkyu.jeong@arm.com tHist.computeIndices[i].update(tHist.gHist); 6317614Sminkyu.jeong@arm.com tHist.computeTags[0][i].update(tHist.gHist); 63211771SCurtis.Dunham@arm.com tHist.computeTags[1][i].update(tHist.gHist); 63311771SCurtis.Dunham@arm.com } 63411771SCurtis.Dunham@arm.com} 63511771SCurtis.Dunham@arm.com 63611771SCurtis.Dunham@arm.comvoid 63711771SCurtis.Dunham@arm.comTAGEBase::extraAltCalc(BranchInfo* bi) 63811771SCurtis.Dunham@arm.com{ 63911771SCurtis.Dunham@arm.com // do nothing. This is only used in some derived classes 64011771SCurtis.Dunham@arm.com return; 64111771SCurtis.Dunham@arm.com} 64211771SCurtis.Dunham@arm.com 64311771SCurtis.Dunham@arm.comint 64411771SCurtis.Dunham@arm.comTAGEBase::getRandom() 64511771SCurtis.Dunham@arm.com{ 64611771SCurtis.Dunham@arm.com return random_mt.random<int>(); 64711771SCurtis.Dunham@arm.com} 64811771SCurtis.Dunham@arm.com 64911771SCurtis.Dunham@arm.comvoid 65011771SCurtis.Dunham@arm.comTAGEBase::updateStats(bool taken, BranchInfo* bi) 65111771SCurtis.Dunham@arm.com{ 65211771SCurtis.Dunham@arm.com if (taken == bi->tagePred) { 65310905Sandreas.sandberg@arm.com // correct prediction 6547733SAli.Saidi@ARM.com switch (bi->provider) { 6557733SAli.Saidi@ARM.com case BIMODAL_ONLY: tageBimodalProviderCorrect++; break; 65612529Sgiacomo.travaglini@arm.com case TAGE_LONGEST_MATCH: tageLongestMatchProviderCorrect++; break; 65710037SARM gem5 Developers case BIMODAL_ALT_MATCH: bimodalAltMatchProviderCorrect++; break; 65811771SCurtis.Dunham@arm.com case TAGE_ALT_MATCH: tageAltMatchProviderCorrect++; break; 65910037SARM gem5 Developers } 66010037SARM gem5 Developers } else { 66110037SARM gem5 Developers // wrong prediction 66210037SARM gem5 Developers switch (bi->provider) { 66313114Sgiacomo.travaglini@arm.com case BIMODAL_ONLY: tageBimodalProviderWrong++; break; 6647733SAli.Saidi@ARM.com case TAGE_LONGEST_MATCH: 66510905Sandreas.sandberg@arm.com tageLongestMatchProviderWrong++; 6667733SAli.Saidi@ARM.com if (bi->altTaken == taken) { 6677733SAli.Saidi@ARM.com tageAltMatchProviderWouldHaveHit++; 66812529Sgiacomo.travaglini@arm.com } 6697733SAli.Saidi@ARM.com break; 6707733SAli.Saidi@ARM.com case BIMODAL_ALT_MATCH: 67110037SARM gem5 Developers bimodalAltMatchProviderWrong++; 67211771SCurtis.Dunham@arm.com break; 67310037SARM gem5 Developers case TAGE_ALT_MATCH: 67410037SARM gem5 Developers tageAltMatchProviderWrong++; 67510037SARM gem5 Developers break; 67610037SARM gem5 Developers } 67713114Sgiacomo.travaglini@arm.com 6787733SAli.Saidi@ARM.com switch (bi->provider) { 6796313Sgblack@eecs.umich.edu case BIMODAL_ALT_MATCH: 68012972Sandreas.sandberg@arm.com case TAGE_ALT_MATCH: 6819461Snilay@cs.wisc.edu if (bi->longestMatchPred == taken) { 68211165SRekai.GonzalezAlberquilla@arm.com tageLongestMatchProviderWouldHaveHit++; 68311165SRekai.GonzalezAlberquilla@arm.com } 68412109SRekai.GonzalezAlberquilla@arm.com } 68512109SRekai.GonzalezAlberquilla@arm.com } 68612109SRekai.GonzalezAlberquilla@arm.com 68712109SRekai.GonzalezAlberquilla@arm.com switch (bi->provider) { 68812109SRekai.GonzalezAlberquilla@arm.com case TAGE_LONGEST_MATCH: 68912109SRekai.GonzalezAlberquilla@arm.com case TAGE_ALT_MATCH: 6909553Sandreas.hansson@arm.com tageLongestMatchProvider[bi->hitBank]++; 6919553Sandreas.hansson@arm.com tageAltMatchProvider[bi->altBank]++; 6929553Sandreas.hansson@arm.com break; 6939384SAndreas.Sandberg@arm.com } 6947400SAli.Saidi@ARM.com} 6959384SAndreas.Sandberg@arm.com 6969384SAndreas.Sandberg@arm.comunsigned 6979384SAndreas.Sandberg@arm.comTAGEBase::getGHR(ThreadID tid, BranchInfo *bi) const 6986313Sgblack@eecs.umich.edu{ 6996313Sgblack@eecs.umich.edu unsigned val = 0; 7006313Sgblack@eecs.umich.edu for (unsigned i = 0; i < 32; i++) { 70112109SRekai.GonzalezAlberquilla@arm.com // Make sure we don't go out of bounds 70212109SRekai.GonzalezAlberquilla@arm.com int gh_offset = bi->ptGhist + i; 70312109SRekai.GonzalezAlberquilla@arm.com assert(&(threadHistory[tid].globalHistory[gh_offset]) < 70412109SRekai.GonzalezAlberquilla@arm.com threadHistory[tid].globalHistory + histBufferSize); 70512109SRekai.GonzalezAlberquilla@arm.com val |= ((threadHistory[tid].globalHistory[gh_offset] & 0x1) << i); 70612109SRekai.GonzalezAlberquilla@arm.com } 70712109SRekai.GonzalezAlberquilla@arm.com 70812109SRekai.GonzalezAlberquilla@arm.com return val; 70912109SRekai.GonzalezAlberquilla@arm.com} 71012109SRekai.GonzalezAlberquilla@arm.com 71112109SRekai.GonzalezAlberquilla@arm.comvoid 71212109SRekai.GonzalezAlberquilla@arm.comTAGEBase::regStats() 71312109SRekai.GonzalezAlberquilla@arm.com{ 7146313Sgblack@eecs.umich.edu tageLongestMatchProviderCorrect 715 .name(name() + ".tageLongestMatchProviderCorrect") 716 .desc("Number of times TAGE Longest Match is the provider and " 717 "the prediction is correct"); 718 719 tageAltMatchProviderCorrect 720 .name(name() + ".tageAltMatchProviderCorrect") 721 .desc("Number of times TAGE Alt Match is the provider and " 722 "the prediction is correct"); 723 724 bimodalAltMatchProviderCorrect 725 .name(name() + ".bimodalAltMatchProviderCorrect") 726 .desc("Number of times TAGE Alt Match is the bimodal and it is the " 727 "provider and the prediction is correct"); 728 729 tageBimodalProviderCorrect 730 .name(name() + ".tageBimodalProviderCorrect") 731 .desc("Number of times there are no hits on the TAGE tables " 732 "and the bimodal prediction is correct"); 733 734 tageLongestMatchProviderWrong 735 .name(name() + ".tageLongestMatchProviderWrong") 736 .desc("Number of times TAGE Longest Match is the provider and " 737 "the prediction is wrong"); 738 739 tageAltMatchProviderWrong 740 .name(name() + ".tageAltMatchProviderWrong") 741 .desc("Number of times TAGE Alt Match is the provider and " 742 "the prediction is wrong"); 743 744 bimodalAltMatchProviderWrong 745 .name(name() + ".bimodalAltMatchProviderWrong") 746 .desc("Number of times TAGE Alt Match is the bimodal and it is the " 747 "provider and the prediction is wrong"); 748 749 tageBimodalProviderWrong 750 .name(name() + ".tageBimodalProviderWrong") 751 .desc("Number of times there are no hits on the TAGE tables " 752 "and the bimodal prediction is wrong"); 753 754 tageAltMatchProviderWouldHaveHit 755 .name(name() + ".tageAltMatchProviderWouldHaveHit") 756 .desc("Number of times TAGE Longest Match is the provider, " 757 "the prediction is wrong and Alt Match prediction was correct"); 758 759 tageLongestMatchProviderWouldHaveHit 760 .name(name() + ".tageLongestMatchProviderWouldHaveHit") 761 .desc("Number of times TAGE Alt Match is the provider, the " 762 "prediction is wrong and Longest Match prediction was correct"); 763 764 tageLongestMatchProvider 765 .init(nHistoryTables + 1) 766 .name(name() + ".tageLongestMatchProvider") 767 .desc("TAGE provider for longest match"); 768 769 tageAltMatchProvider 770 .init(nHistoryTables + 1) 771 .name(name() + ".tageAltMatchProvider") 772 .desc("TAGE provider for alt match"); 773} 774 775int8_t 776TAGEBase::getCtr(int hitBank, int hitBankIndex) const 777{ 778 return gtable[hitBank][hitBankIndex].ctr; 779} 780 781unsigned 782TAGEBase::getTageCtrBits() const 783{ 784 return tagTableCounterBits; 785} 786 787int 788TAGEBase::getPathHist(ThreadID tid) const 789{ 790 return threadHistory[tid].pathHist; 791} 792 793bool 794TAGEBase::isSpeculativeUpdateEnabled() const 795{ 796 return speculativeHistUpdate; 797} 798 799TAGEBase* 800TAGEBaseParams::create() 801{ 802 return new TAGEBase(this); 803} 804