113626Sjairo.balart@metempsy.com/* 213626Sjairo.balart@metempsy.com * Copyright (c) 2014 The University of Wisconsin 313626Sjairo.balart@metempsy.com * 413626Sjairo.balart@metempsy.com * Copyright (c) 2006 INRIA (Institut National de Recherche en 513626Sjairo.balart@metempsy.com * Informatique et en Automatique / French National Research Institute 613626Sjairo.balart@metempsy.com * for Computer Science and Applied Mathematics) 713626Sjairo.balart@metempsy.com * 813626Sjairo.balart@metempsy.com * All rights reserved. 913626Sjairo.balart@metempsy.com * 1013626Sjairo.balart@metempsy.com * Redistribution and use in source and binary forms, with or without 1113626Sjairo.balart@metempsy.com * modification, are permitted provided that the following conditions are 1213626Sjairo.balart@metempsy.com * met: redistributions of source code must retain the above copyright 1313626Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer; 1413626Sjairo.balart@metempsy.com * redistributions in binary form must reproduce the above copyright 1513626Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer in the 1613626Sjairo.balart@metempsy.com * documentation and/or other materials provided with the distribution; 1713626Sjairo.balart@metempsy.com * neither the name of the copyright holders nor the names of its 1813626Sjairo.balart@metempsy.com * contributors may be used to endorse or promote products derived from 1913626Sjairo.balart@metempsy.com * this software without specific prior written permission. 2013626Sjairo.balart@metempsy.com * 2113626Sjairo.balart@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2213626Sjairo.balart@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2313626Sjairo.balart@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2413626Sjairo.balart@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2513626Sjairo.balart@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2613626Sjairo.balart@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2713626Sjairo.balart@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2813626Sjairo.balart@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2913626Sjairo.balart@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3013626Sjairo.balart@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3113626Sjairo.balart@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3213626Sjairo.balart@metempsy.com * 3313626Sjairo.balart@metempsy.com * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais, 3413626Sjairo.balart@metempsy.com * from André Seznec's code. 3513626Sjairo.balart@metempsy.com */ 3613626Sjairo.balart@metempsy.com 3713626Sjairo.balart@metempsy.com/* @file 3813626Sjairo.balart@metempsy.com * Implementation of a TAGE branch predictor 3913626Sjairo.balart@metempsy.com */ 4013626Sjairo.balart@metempsy.com 4113626Sjairo.balart@metempsy.com#include "cpu/pred/tage_base.hh" 4213626Sjairo.balart@metempsy.com 4313626Sjairo.balart@metempsy.com#include "base/intmath.hh" 4413626Sjairo.balart@metempsy.com#include "base/logging.hh" 4513626Sjairo.balart@metempsy.com#include "debug/Fetch.hh" 4613626Sjairo.balart@metempsy.com#include "debug/Tage.hh" 4713626Sjairo.balart@metempsy.com 4813626Sjairo.balart@metempsy.comTAGEBase::TAGEBase(const TAGEBaseParams *p) 4913626Sjairo.balart@metempsy.com : SimObject(p), 5013626Sjairo.balart@metempsy.com logRatioBiModalHystEntries(p->logRatioBiModalHystEntries), 5113626Sjairo.balart@metempsy.com nHistoryTables(p->nHistoryTables), 5213626Sjairo.balart@metempsy.com tagTableCounterBits(p->tagTableCounterBits), 5313626Sjairo.balart@metempsy.com tagTableUBits(p->tagTableUBits), 5413626Sjairo.balart@metempsy.com histBufferSize(p->histBufferSize), 5513626Sjairo.balart@metempsy.com minHist(p->minHist), 5613626Sjairo.balart@metempsy.com maxHist(p->maxHist), 5713626Sjairo.balart@metempsy.com pathHistBits(p->pathHistBits), 5813626Sjairo.balart@metempsy.com tagTableTagWidths(p->tagTableTagWidths), 5913626Sjairo.balart@metempsy.com logTagTableSizes(p->logTagTableSizes), 6013626Sjairo.balart@metempsy.com threadHistory(p->numThreads), 6113626Sjairo.balart@metempsy.com logUResetPeriod(p->logUResetPeriod), 6214081Sjavier.bueno@metempsy.com initialTCounterValue(p->initialTCounterValue), 6313626Sjairo.balart@metempsy.com numUseAltOnNa(p->numUseAltOnNa), 6413626Sjairo.balart@metempsy.com useAltOnNaBits(p->useAltOnNaBits), 6513626Sjairo.balart@metempsy.com maxNumAlloc(p->maxNumAlloc), 6613626Sjairo.balart@metempsy.com noSkip(p->noSkip), 6713626Sjairo.balart@metempsy.com speculativeHistUpdate(p->speculativeHistUpdate), 6814081Sjavier.bueno@metempsy.com instShiftAmt(p->instShiftAmt), 6914081Sjavier.bueno@metempsy.com initialized(false) 7013626Sjairo.balart@metempsy.com{ 7113626Sjairo.balart@metempsy.com if (noSkip.empty()) { 7213626Sjairo.balart@metempsy.com // Set all the table to enabled by default 7313626Sjairo.balart@metempsy.com noSkip.resize(nHistoryTables + 1, true); 7413626Sjairo.balart@metempsy.com } 7513626Sjairo.balart@metempsy.com} 7613626Sjairo.balart@metempsy.com 7713626Sjairo.balart@metempsy.comTAGEBase::BranchInfo* 7813626Sjairo.balart@metempsy.comTAGEBase::makeBranchInfo() { 7913626Sjairo.balart@metempsy.com return new BranchInfo(*this); 8013626Sjairo.balart@metempsy.com} 8113626Sjairo.balart@metempsy.com 8213626Sjairo.balart@metempsy.comvoid 8313626Sjairo.balart@metempsy.comTAGEBase::init() 8413626Sjairo.balart@metempsy.com{ 8514081Sjavier.bueno@metempsy.com if (initialized) { 8614081Sjavier.bueno@metempsy.com return; 8714081Sjavier.bueno@metempsy.com } 8813626Sjairo.balart@metempsy.com // Current method for periodically resetting the u counter bits only 8913626Sjairo.balart@metempsy.com // works for 1 or 2 bits 9013626Sjairo.balart@metempsy.com // Also make sure that it is not 0 9113626Sjairo.balart@metempsy.com assert(tagTableUBits <= 2 && (tagTableUBits > 0)); 9213626Sjairo.balart@metempsy.com 9313626Sjairo.balart@metempsy.com // we use int type for the path history, so it cannot be more than 9413626Sjairo.balart@metempsy.com // its size 9513626Sjairo.balart@metempsy.com assert(pathHistBits <= (sizeof(int)*8)); 9613626Sjairo.balart@metempsy.com 9713626Sjairo.balart@metempsy.com // initialize the counter to half of the period 9813626Sjairo.balart@metempsy.com assert(logUResetPeriod != 0); 9914081Sjavier.bueno@metempsy.com tCounter = initialTCounterValue; 10013626Sjairo.balart@metempsy.com 10113626Sjairo.balart@metempsy.com assert(histBufferSize > maxHist * 2); 10213626Sjairo.balart@metempsy.com 10313626Sjairo.balart@metempsy.com useAltPredForNewlyAllocated.resize(numUseAltOnNa, 0); 10413626Sjairo.balart@metempsy.com 10513626Sjairo.balart@metempsy.com for (auto& history : threadHistory) { 10613626Sjairo.balart@metempsy.com history.pathHist = 0; 10713626Sjairo.balart@metempsy.com history.globalHistory = new uint8_t[histBufferSize]; 10813626Sjairo.balart@metempsy.com history.gHist = history.globalHistory; 10913626Sjairo.balart@metempsy.com memset(history.gHist, 0, histBufferSize); 11013626Sjairo.balart@metempsy.com history.ptGhist = 0; 11113626Sjairo.balart@metempsy.com } 11213626Sjairo.balart@metempsy.com 11313626Sjairo.balart@metempsy.com histLengths = new int [nHistoryTables+1]; 11413626Sjairo.balart@metempsy.com 11513626Sjairo.balart@metempsy.com calculateParameters(); 11613626Sjairo.balart@metempsy.com 11713626Sjairo.balart@metempsy.com assert(tagTableTagWidths.size() == (nHistoryTables+1)); 11813626Sjairo.balart@metempsy.com assert(logTagTableSizes.size() == (nHistoryTables+1)); 11913626Sjairo.balart@metempsy.com 12013626Sjairo.balart@metempsy.com // First entry is for the Bimodal table and it is untagged in this 12113626Sjairo.balart@metempsy.com // implementation 12213626Sjairo.balart@metempsy.com assert(tagTableTagWidths[0] == 0); 12313626Sjairo.balart@metempsy.com 12413626Sjairo.balart@metempsy.com for (auto& history : threadHistory) { 12513626Sjairo.balart@metempsy.com history.computeIndices = new FoldedHistory[nHistoryTables+1]; 12613626Sjairo.balart@metempsy.com history.computeTags[0] = new FoldedHistory[nHistoryTables+1]; 12713626Sjairo.balart@metempsy.com history.computeTags[1] = new FoldedHistory[nHistoryTables+1]; 12813626Sjairo.balart@metempsy.com 12913626Sjairo.balart@metempsy.com initFoldedHistories(history); 13013626Sjairo.balart@metempsy.com } 13113626Sjairo.balart@metempsy.com 13213626Sjairo.balart@metempsy.com const uint64_t bimodalTableSize = ULL(1) << logTagTableSizes[0]; 13313626Sjairo.balart@metempsy.com btablePrediction.resize(bimodalTableSize, false); 13413626Sjairo.balart@metempsy.com btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries, 13513626Sjairo.balart@metempsy.com true); 13613626Sjairo.balart@metempsy.com 13713626Sjairo.balart@metempsy.com gtable = new TageEntry*[nHistoryTables + 1]; 13813626Sjairo.balart@metempsy.com buildTageTables(); 13913626Sjairo.balart@metempsy.com 14013626Sjairo.balart@metempsy.com tableIndices = new int [nHistoryTables+1]; 14113626Sjairo.balart@metempsy.com tableTags = new int [nHistoryTables+1]; 14214081Sjavier.bueno@metempsy.com initialized = true; 14313626Sjairo.balart@metempsy.com} 14413626Sjairo.balart@metempsy.com 14513626Sjairo.balart@metempsy.comvoid 14613626Sjairo.balart@metempsy.comTAGEBase::initFoldedHistories(ThreadHistory & history) 14713626Sjairo.balart@metempsy.com{ 14813626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 14913626Sjairo.balart@metempsy.com history.computeIndices[i].init( 15013626Sjairo.balart@metempsy.com histLengths[i], (logTagTableSizes[i])); 15113626Sjairo.balart@metempsy.com history.computeTags[0][i].init( 15213626Sjairo.balart@metempsy.com history.computeIndices[i].origLength, tagTableTagWidths[i]); 15313626Sjairo.balart@metempsy.com history.computeTags[1][i].init( 15413626Sjairo.balart@metempsy.com history.computeIndices[i].origLength, tagTableTagWidths[i]-1); 15513626Sjairo.balart@metempsy.com DPRINTF(Tage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n", 15613626Sjairo.balart@metempsy.com histLengths[i], logTagTableSizes[i], tagTableTagWidths[i]); 15713626Sjairo.balart@metempsy.com } 15813626Sjairo.balart@metempsy.com} 15913626Sjairo.balart@metempsy.com 16013626Sjairo.balart@metempsy.comvoid 16113626Sjairo.balart@metempsy.comTAGEBase::buildTageTables() 16213626Sjairo.balart@metempsy.com{ 16313626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 16413626Sjairo.balart@metempsy.com gtable[i] = new TageEntry[1<<(logTagTableSizes[i])]; 16513626Sjairo.balart@metempsy.com } 16613626Sjairo.balart@metempsy.com} 16713626Sjairo.balart@metempsy.com 16813626Sjairo.balart@metempsy.comvoid 16913626Sjairo.balart@metempsy.comTAGEBase::calculateParameters() 17013626Sjairo.balart@metempsy.com{ 17113626Sjairo.balart@metempsy.com histLengths[1] = minHist; 17213626Sjairo.balart@metempsy.com histLengths[nHistoryTables] = maxHist; 17313626Sjairo.balart@metempsy.com 17413626Sjairo.balart@metempsy.com for (int i = 2; i <= nHistoryTables; i++) { 17513626Sjairo.balart@metempsy.com histLengths[i] = (int) (((double) minHist * 17613626Sjairo.balart@metempsy.com pow ((double) (maxHist) / (double) minHist, 17713626Sjairo.balart@metempsy.com (double) (i - 1) / (double) ((nHistoryTables- 1)))) 17813626Sjairo.balart@metempsy.com + 0.5); 17913626Sjairo.balart@metempsy.com } 18013626Sjairo.balart@metempsy.com} 18113626Sjairo.balart@metempsy.com 18213626Sjairo.balart@metempsy.comvoid 18313626Sjairo.balart@metempsy.comTAGEBase::btbUpdate(ThreadID tid, Addr branch_pc, BranchInfo* &bi) 18413626Sjairo.balart@metempsy.com{ 18513626Sjairo.balart@metempsy.com if (speculativeHistUpdate) { 18613626Sjairo.balart@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 18713626Sjairo.balart@metempsy.com DPRINTF(Tage, "BTB miss resets prediction: %lx\n", branch_pc); 18813626Sjairo.balart@metempsy.com assert(tHist.gHist == &tHist.globalHistory[tHist.ptGhist]); 18913626Sjairo.balart@metempsy.com tHist.gHist[0] = 0; 19013626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 19113626Sjairo.balart@metempsy.com tHist.computeIndices[i].comp = bi->ci[i]; 19213626Sjairo.balart@metempsy.com tHist.computeTags[0][i].comp = bi->ct0[i]; 19313626Sjairo.balart@metempsy.com tHist.computeTags[1][i].comp = bi->ct1[i]; 19413626Sjairo.balart@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 19513626Sjairo.balart@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 19613626Sjairo.balart@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 19713626Sjairo.balart@metempsy.com } 19813626Sjairo.balart@metempsy.com } 19913626Sjairo.balart@metempsy.com} 20013626Sjairo.balart@metempsy.com 20113626Sjairo.balart@metempsy.comint 20213626Sjairo.balart@metempsy.comTAGEBase::bindex(Addr pc_in) const 20313626Sjairo.balart@metempsy.com{ 20413626Sjairo.balart@metempsy.com return ((pc_in >> instShiftAmt) & ((ULL(1) << (logTagTableSizes[0])) - 1)); 20513626Sjairo.balart@metempsy.com} 20613626Sjairo.balart@metempsy.com 20713626Sjairo.balart@metempsy.comint 20813626Sjairo.balart@metempsy.comTAGEBase::F(int A, int size, int bank) const 20913626Sjairo.balart@metempsy.com{ 21013626Sjairo.balart@metempsy.com int A1, A2; 21113626Sjairo.balart@metempsy.com 21213626Sjairo.balart@metempsy.com A = A & ((ULL(1) << size) - 1); 21313626Sjairo.balart@metempsy.com A1 = (A & ((ULL(1) << logTagTableSizes[bank]) - 1)); 21413626Sjairo.balart@metempsy.com A2 = (A >> logTagTableSizes[bank]); 21513626Sjairo.balart@metempsy.com A2 = ((A2 << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 21613626Sjairo.balart@metempsy.com + (A2 >> (logTagTableSizes[bank] - bank)); 21713626Sjairo.balart@metempsy.com A = A1 ^ A2; 21813626Sjairo.balart@metempsy.com A = ((A << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 21913626Sjairo.balart@metempsy.com + (A >> (logTagTableSizes[bank] - bank)); 22013626Sjairo.balart@metempsy.com return (A); 22113626Sjairo.balart@metempsy.com} 22213626Sjairo.balart@metempsy.com 22313626Sjairo.balart@metempsy.com// gindex computes a full hash of pc, ghist and pathHist 22413626Sjairo.balart@metempsy.comint 22513626Sjairo.balart@metempsy.comTAGEBase::gindex(ThreadID tid, Addr pc, int bank) const 22613626Sjairo.balart@metempsy.com{ 22713626Sjairo.balart@metempsy.com int index; 22813626Sjairo.balart@metempsy.com int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits : 22913626Sjairo.balart@metempsy.com histLengths[bank]; 23013626Sjairo.balart@metempsy.com const unsigned int shiftedPc = pc >> instShiftAmt; 23113626Sjairo.balart@metempsy.com index = 23213626Sjairo.balart@metempsy.com shiftedPc ^ 23313626Sjairo.balart@metempsy.com (shiftedPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^ 23413626Sjairo.balart@metempsy.com threadHistory[tid].computeIndices[bank].comp ^ 23513626Sjairo.balart@metempsy.com F(threadHistory[tid].pathHist, hlen, bank); 23613626Sjairo.balart@metempsy.com 23713626Sjairo.balart@metempsy.com return (index & ((ULL(1) << (logTagTableSizes[bank])) - 1)); 23813626Sjairo.balart@metempsy.com} 23913626Sjairo.balart@metempsy.com 24013626Sjairo.balart@metempsy.com 24113626Sjairo.balart@metempsy.com// Tag computation 24213626Sjairo.balart@metempsy.comuint16_t 24313626Sjairo.balart@metempsy.comTAGEBase::gtag(ThreadID tid, Addr pc, int bank) const 24413626Sjairo.balart@metempsy.com{ 24513626Sjairo.balart@metempsy.com int tag = (pc >> instShiftAmt) ^ 24613626Sjairo.balart@metempsy.com threadHistory[tid].computeTags[0][bank].comp ^ 24713626Sjairo.balart@metempsy.com (threadHistory[tid].computeTags[1][bank].comp << 1); 24813626Sjairo.balart@metempsy.com 24913626Sjairo.balart@metempsy.com return (tag & ((ULL(1) << tagTableTagWidths[bank]) - 1)); 25013626Sjairo.balart@metempsy.com} 25113626Sjairo.balart@metempsy.com 25213626Sjairo.balart@metempsy.com 25313626Sjairo.balart@metempsy.com// Up-down saturating counter 25413626Sjairo.balart@metempsy.comtemplate<typename T> 25513626Sjairo.balart@metempsy.comvoid 25613626Sjairo.balart@metempsy.comTAGEBase::ctrUpdate(T & ctr, bool taken, int nbits) 25713626Sjairo.balart@metempsy.com{ 25813626Sjairo.balart@metempsy.com assert(nbits <= sizeof(T) << 3); 25913626Sjairo.balart@metempsy.com if (taken) { 26013626Sjairo.balart@metempsy.com if (ctr < ((1 << (nbits - 1)) - 1)) 26113626Sjairo.balart@metempsy.com ctr++; 26213626Sjairo.balart@metempsy.com } else { 26313626Sjairo.balart@metempsy.com if (ctr > -(1 << (nbits - 1))) 26413626Sjairo.balart@metempsy.com ctr--; 26513626Sjairo.balart@metempsy.com } 26613626Sjairo.balart@metempsy.com} 26713626Sjairo.balart@metempsy.com 26813626Sjairo.balart@metempsy.com// int8_t and int versions of this function may be needed 26913626Sjairo.balart@metempsy.comtemplate void TAGEBase::ctrUpdate(int8_t & ctr, bool taken, int nbits); 27013626Sjairo.balart@metempsy.comtemplate void TAGEBase::ctrUpdate(int & ctr, bool taken, int nbits); 27113626Sjairo.balart@metempsy.com 27213626Sjairo.balart@metempsy.com// Up-down unsigned saturating counter 27313626Sjairo.balart@metempsy.comvoid 27413626Sjairo.balart@metempsy.comTAGEBase::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits) 27513626Sjairo.balart@metempsy.com{ 27613626Sjairo.balart@metempsy.com assert(nbits <= sizeof(uint8_t) << 3); 27713626Sjairo.balart@metempsy.com if (up) { 27813626Sjairo.balart@metempsy.com if (ctr < ((1 << nbits) - 1)) 27913626Sjairo.balart@metempsy.com ctr++; 28013626Sjairo.balart@metempsy.com } else { 28113626Sjairo.balart@metempsy.com if (ctr) 28213626Sjairo.balart@metempsy.com ctr--; 28313626Sjairo.balart@metempsy.com } 28413626Sjairo.balart@metempsy.com} 28513626Sjairo.balart@metempsy.com 28613626Sjairo.balart@metempsy.com// Bimodal prediction 28713626Sjairo.balart@metempsy.combool 28813626Sjairo.balart@metempsy.comTAGEBase::getBimodePred(Addr pc, BranchInfo* bi) const 28913626Sjairo.balart@metempsy.com{ 29013626Sjairo.balart@metempsy.com return btablePrediction[bi->bimodalIndex]; 29113626Sjairo.balart@metempsy.com} 29213626Sjairo.balart@metempsy.com 29313626Sjairo.balart@metempsy.com 29413626Sjairo.balart@metempsy.com// Update the bimodal predictor: a hysteresis bit is shared among N prediction 29513626Sjairo.balart@metempsy.com// bits (N = 2 ^ logRatioBiModalHystEntries) 29613626Sjairo.balart@metempsy.comvoid 29713626Sjairo.balart@metempsy.comTAGEBase::baseUpdate(Addr pc, bool taken, BranchInfo* bi) 29813626Sjairo.balart@metempsy.com{ 29913626Sjairo.balart@metempsy.com int inter = (btablePrediction[bi->bimodalIndex] << 1) 30013626Sjairo.balart@metempsy.com + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries]; 30113626Sjairo.balart@metempsy.com if (taken) { 30213626Sjairo.balart@metempsy.com if (inter < 3) 30313626Sjairo.balart@metempsy.com inter++; 30413626Sjairo.balart@metempsy.com } else if (inter > 0) { 30513626Sjairo.balart@metempsy.com inter--; 30613626Sjairo.balart@metempsy.com } 30713626Sjairo.balart@metempsy.com const bool pred = inter >> 1; 30813626Sjairo.balart@metempsy.com const bool hyst = inter & 1; 30913626Sjairo.balart@metempsy.com btablePrediction[bi->bimodalIndex] = pred; 31013626Sjairo.balart@metempsy.com btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst; 31113626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst); 31213626Sjairo.balart@metempsy.com} 31313626Sjairo.balart@metempsy.com 31413626Sjairo.balart@metempsy.com// shifting the global history: we manage the history in a big table in order 31513626Sjairo.balart@metempsy.com// to reduce simulation time 31613626Sjairo.balart@metempsy.comvoid 31713626Sjairo.balart@metempsy.comTAGEBase::updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &pt) 31813626Sjairo.balart@metempsy.com{ 31913626Sjairo.balart@metempsy.com if (pt == 0) { 32013626Sjairo.balart@metempsy.com DPRINTF(Tage, "Rolling over the histories\n"); 32113626Sjairo.balart@metempsy.com // Copy beginning of globalHistoryBuffer to end, such that 32213626Sjairo.balart@metempsy.com // the last maxHist outcomes are still reachable 32313626Sjairo.balart@metempsy.com // through pt[0 .. maxHist - 1]. 32413626Sjairo.balart@metempsy.com for (int i = 0; i < maxHist; i++) 32513626Sjairo.balart@metempsy.com tab[histBufferSize - maxHist + i] = tab[i]; 32613626Sjairo.balart@metempsy.com pt = histBufferSize - maxHist; 32713626Sjairo.balart@metempsy.com h = &tab[pt]; 32813626Sjairo.balart@metempsy.com } 32913626Sjairo.balart@metempsy.com pt--; 33013626Sjairo.balart@metempsy.com h--; 33113626Sjairo.balart@metempsy.com h[0] = (dir) ? 1 : 0; 33213626Sjairo.balart@metempsy.com} 33313626Sjairo.balart@metempsy.com 33413626Sjairo.balart@metempsy.comvoid 33513626Sjairo.balart@metempsy.comTAGEBase::calculateIndicesAndTags(ThreadID tid, Addr branch_pc, 33613626Sjairo.balart@metempsy.com BranchInfo* bi) 33713626Sjairo.balart@metempsy.com{ 33813626Sjairo.balart@metempsy.com // computes the table addresses and the partial tags 33913626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 34013626Sjairo.balart@metempsy.com tableIndices[i] = gindex(tid, branch_pc, i); 34113626Sjairo.balart@metempsy.com bi->tableIndices[i] = tableIndices[i]; 34213626Sjairo.balart@metempsy.com tableTags[i] = gtag(tid, branch_pc, i); 34313626Sjairo.balart@metempsy.com bi->tableTags[i] = tableTags[i]; 34413626Sjairo.balart@metempsy.com } 34513626Sjairo.balart@metempsy.com} 34613626Sjairo.balart@metempsy.com 34713626Sjairo.balart@metempsy.comunsigned 34814081Sjavier.bueno@metempsy.comTAGEBase::getUseAltIdx(BranchInfo* bi, Addr branch_pc) 34913626Sjairo.balart@metempsy.com{ 35013626Sjairo.balart@metempsy.com // There is only 1 counter on the base TAGE implementation 35113626Sjairo.balart@metempsy.com return 0; 35213626Sjairo.balart@metempsy.com} 35313626Sjairo.balart@metempsy.com 35413626Sjairo.balart@metempsy.combool 35513626Sjairo.balart@metempsy.comTAGEBase::tagePredict(ThreadID tid, Addr branch_pc, 35613626Sjairo.balart@metempsy.com bool cond_branch, BranchInfo* bi) 35713626Sjairo.balart@metempsy.com{ 35813626Sjairo.balart@metempsy.com Addr pc = branch_pc; 35913626Sjairo.balart@metempsy.com bool pred_taken = true; 36013626Sjairo.balart@metempsy.com 36113626Sjairo.balart@metempsy.com if (cond_branch) { 36213626Sjairo.balart@metempsy.com // TAGE prediction 36313626Sjairo.balart@metempsy.com 36413626Sjairo.balart@metempsy.com calculateIndicesAndTags(tid, pc, bi); 36513626Sjairo.balart@metempsy.com 36613626Sjairo.balart@metempsy.com bi->bimodalIndex = bindex(pc); 36713626Sjairo.balart@metempsy.com 36813626Sjairo.balart@metempsy.com bi->hitBank = 0; 36913626Sjairo.balart@metempsy.com bi->altBank = 0; 37013626Sjairo.balart@metempsy.com //Look for the bank with longest matching history 37113626Sjairo.balart@metempsy.com for (int i = nHistoryTables; i > 0; i--) { 37213626Sjairo.balart@metempsy.com if (noSkip[i] && 37313626Sjairo.balart@metempsy.com gtable[i][tableIndices[i]].tag == tableTags[i]) { 37413626Sjairo.balart@metempsy.com bi->hitBank = i; 37513626Sjairo.balart@metempsy.com bi->hitBankIndex = tableIndices[bi->hitBank]; 37613626Sjairo.balart@metempsy.com break; 37713626Sjairo.balart@metempsy.com } 37813626Sjairo.balart@metempsy.com } 37913626Sjairo.balart@metempsy.com //Look for the alternate bank 38013626Sjairo.balart@metempsy.com for (int i = bi->hitBank - 1; i > 0; i--) { 38113626Sjairo.balart@metempsy.com if (noSkip[i] && 38213626Sjairo.balart@metempsy.com gtable[i][tableIndices[i]].tag == tableTags[i]) { 38313626Sjairo.balart@metempsy.com bi->altBank = i; 38413626Sjairo.balart@metempsy.com bi->altBankIndex = tableIndices[bi->altBank]; 38513626Sjairo.balart@metempsy.com break; 38613626Sjairo.balart@metempsy.com } 38713626Sjairo.balart@metempsy.com } 38813626Sjairo.balart@metempsy.com //computes the prediction and the alternate prediction 38913626Sjairo.balart@metempsy.com if (bi->hitBank > 0) { 39013626Sjairo.balart@metempsy.com if (bi->altBank > 0) { 39113626Sjairo.balart@metempsy.com bi->altTaken = 39213626Sjairo.balart@metempsy.com gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0; 39313626Sjairo.balart@metempsy.com extraAltCalc(bi); 39413626Sjairo.balart@metempsy.com }else { 39513626Sjairo.balart@metempsy.com bi->altTaken = getBimodePred(pc, bi); 39613626Sjairo.balart@metempsy.com } 39713626Sjairo.balart@metempsy.com 39813626Sjairo.balart@metempsy.com bi->longestMatchPred = 39913626Sjairo.balart@metempsy.com gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0; 40013626Sjairo.balart@metempsy.com bi->pseudoNewAlloc = 40113626Sjairo.balart@metempsy.com abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1; 40213626Sjairo.balart@metempsy.com 40313626Sjairo.balart@metempsy.com //if the entry is recognized as a newly allocated entry and 40413626Sjairo.balart@metempsy.com //useAltPredForNewlyAllocated is positive use the alternate 40513626Sjairo.balart@metempsy.com //prediction 40614081Sjavier.bueno@metempsy.com if ((useAltPredForNewlyAllocated[getUseAltIdx(bi, branch_pc)] < 0) 40714081Sjavier.bueno@metempsy.com || ! bi->pseudoNewAlloc) { 40813626Sjairo.balart@metempsy.com bi->tagePred = bi->longestMatchPred; 40913626Sjairo.balart@metempsy.com bi->provider = TAGE_LONGEST_MATCH; 41013626Sjairo.balart@metempsy.com } else { 41113626Sjairo.balart@metempsy.com bi->tagePred = bi->altTaken; 41213626Sjairo.balart@metempsy.com bi->provider = bi->altBank ? TAGE_ALT_MATCH 41313626Sjairo.balart@metempsy.com : BIMODAL_ALT_MATCH; 41413626Sjairo.balart@metempsy.com } 41513626Sjairo.balart@metempsy.com } else { 41613626Sjairo.balart@metempsy.com bi->altTaken = getBimodePred(pc, bi); 41713626Sjairo.balart@metempsy.com bi->tagePred = bi->altTaken; 41813626Sjairo.balart@metempsy.com bi->longestMatchPred = bi->altTaken; 41913626Sjairo.balart@metempsy.com bi->provider = BIMODAL_ONLY; 42013626Sjairo.balart@metempsy.com } 42113626Sjairo.balart@metempsy.com //end TAGE prediction 42213626Sjairo.balart@metempsy.com 42313626Sjairo.balart@metempsy.com pred_taken = (bi->tagePred); 42413626Sjairo.balart@metempsy.com DPRINTF(Tage, "Predict for %lx: taken?:%d, tagePred:%d, altPred:%d\n", 42513626Sjairo.balart@metempsy.com branch_pc, pred_taken, bi->tagePred, bi->altTaken); 42613626Sjairo.balart@metempsy.com } 42713626Sjairo.balart@metempsy.com bi->branchPC = branch_pc; 42813626Sjairo.balart@metempsy.com bi->condBranch = cond_branch; 42913626Sjairo.balart@metempsy.com return pred_taken; 43013626Sjairo.balart@metempsy.com} 43113626Sjairo.balart@metempsy.com 43213626Sjairo.balart@metempsy.comvoid 43313685Sjavier.bueno@metempsy.comTAGEBase::adjustAlloc(bool & alloc, bool taken, bool pred_taken) 43413626Sjairo.balart@metempsy.com{ 43513626Sjairo.balart@metempsy.com // Nothing for this base class implementation 43613626Sjairo.balart@metempsy.com} 43713626Sjairo.balart@metempsy.com 43813626Sjairo.balart@metempsy.comvoid 43913626Sjairo.balart@metempsy.comTAGEBase::handleAllocAndUReset(bool alloc, bool taken, BranchInfo* bi, 44013626Sjairo.balart@metempsy.com int nrand) 44113626Sjairo.balart@metempsy.com{ 44213626Sjairo.balart@metempsy.com if (alloc) { 44313626Sjairo.balart@metempsy.com // is there some "unuseful" entry to allocate 44413626Sjairo.balart@metempsy.com uint8_t min = 1; 44513626Sjairo.balart@metempsy.com for (int i = nHistoryTables; i > bi->hitBank; i--) { 44613626Sjairo.balart@metempsy.com if (gtable[i][bi->tableIndices[i]].u < min) { 44713626Sjairo.balart@metempsy.com min = gtable[i][bi->tableIndices[i]].u; 44813626Sjairo.balart@metempsy.com } 44913626Sjairo.balart@metempsy.com } 45013626Sjairo.balart@metempsy.com 45113626Sjairo.balart@metempsy.com // we allocate an entry with a longer history 45213626Sjairo.balart@metempsy.com // to avoid ping-pong, we do not choose systematically the next 45313626Sjairo.balart@metempsy.com // entry, but among the 3 next entries 45413626Sjairo.balart@metempsy.com int Y = nrand & 45513626Sjairo.balart@metempsy.com ((ULL(1) << (nHistoryTables - bi->hitBank - 1)) - 1); 45613626Sjairo.balart@metempsy.com int X = bi->hitBank + 1; 45713626Sjairo.balart@metempsy.com if (Y & 1) { 45813626Sjairo.balart@metempsy.com X++; 45913626Sjairo.balart@metempsy.com if (Y & 2) 46013626Sjairo.balart@metempsy.com X++; 46113626Sjairo.balart@metempsy.com } 46213626Sjairo.balart@metempsy.com // No entry available, forces one to be available 46313626Sjairo.balart@metempsy.com if (min > 0) { 46413626Sjairo.balart@metempsy.com gtable[X][bi->tableIndices[X]].u = 0; 46513626Sjairo.balart@metempsy.com } 46613626Sjairo.balart@metempsy.com 46713626Sjairo.balart@metempsy.com 46813626Sjairo.balart@metempsy.com //Allocate entries 46913626Sjairo.balart@metempsy.com unsigned numAllocated = 0; 47013626Sjairo.balart@metempsy.com for (int i = X; i <= nHistoryTables; i++) { 47113626Sjairo.balart@metempsy.com if ((gtable[i][bi->tableIndices[i]].u == 0)) { 47213626Sjairo.balart@metempsy.com gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; 47313626Sjairo.balart@metempsy.com gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1; 47413626Sjairo.balart@metempsy.com ++numAllocated; 47513626Sjairo.balart@metempsy.com if (numAllocated == maxNumAlloc) { 47613626Sjairo.balart@metempsy.com break; 47713626Sjairo.balart@metempsy.com } 47813626Sjairo.balart@metempsy.com } 47913626Sjairo.balart@metempsy.com } 48013626Sjairo.balart@metempsy.com } 48113626Sjairo.balart@metempsy.com 48213626Sjairo.balart@metempsy.com tCounter++; 48313626Sjairo.balart@metempsy.com 48413626Sjairo.balart@metempsy.com handleUReset(); 48513626Sjairo.balart@metempsy.com} 48613626Sjairo.balart@metempsy.com 48713626Sjairo.balart@metempsy.comvoid 48813626Sjairo.balart@metempsy.comTAGEBase::handleUReset() 48913626Sjairo.balart@metempsy.com{ 49013626Sjairo.balart@metempsy.com //periodic reset of u: reset is not complete but bit by bit 49113626Sjairo.balart@metempsy.com if ((tCounter & ((ULL(1) << logUResetPeriod) - 1)) == 0) { 49213626Sjairo.balart@metempsy.com // reset least significant bit 49313626Sjairo.balart@metempsy.com // most significant bit becomes least significant bit 49413626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 49513626Sjairo.balart@metempsy.com for (int j = 0; j < (ULL(1) << logTagTableSizes[i]); j++) { 49613626Sjairo.balart@metempsy.com resetUctr(gtable[i][j].u); 49713626Sjairo.balart@metempsy.com } 49813626Sjairo.balart@metempsy.com } 49913626Sjairo.balart@metempsy.com } 50013626Sjairo.balart@metempsy.com} 50113626Sjairo.balart@metempsy.com 50213626Sjairo.balart@metempsy.comvoid 50313626Sjairo.balart@metempsy.comTAGEBase::resetUctr(uint8_t & u) 50413626Sjairo.balart@metempsy.com{ 50513626Sjairo.balart@metempsy.com u >>= 1; 50613626Sjairo.balart@metempsy.com} 50713626Sjairo.balart@metempsy.com 50813626Sjairo.balart@metempsy.comvoid 50913626Sjairo.balart@metempsy.comTAGEBase::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, 51014081Sjavier.bueno@metempsy.com BranchInfo* bi, int nrand, Addr corrTarget, bool pred, bool preAdjustAlloc) 51113626Sjairo.balart@metempsy.com{ 51213626Sjairo.balart@metempsy.com // TAGE UPDATE 51313626Sjairo.balart@metempsy.com // try to allocate a new entries only if prediction was wrong 51413626Sjairo.balart@metempsy.com bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables); 51514081Sjavier.bueno@metempsy.com 51614081Sjavier.bueno@metempsy.com if (preAdjustAlloc) { 51714081Sjavier.bueno@metempsy.com adjustAlloc(alloc, taken, pred); 51814081Sjavier.bueno@metempsy.com } 51914081Sjavier.bueno@metempsy.com 52013626Sjairo.balart@metempsy.com if (bi->hitBank > 0) { 52113626Sjairo.balart@metempsy.com // Manage the selection between longest matching and alternate 52213626Sjairo.balart@metempsy.com // matching for "pseudo"-newly allocated longest matching entry 52313626Sjairo.balart@metempsy.com bool PseudoNewAlloc = bi->pseudoNewAlloc; 52413626Sjairo.balart@metempsy.com // an entry is considered as newly allocated if its prediction 52513626Sjairo.balart@metempsy.com // counter is weak 52613626Sjairo.balart@metempsy.com if (PseudoNewAlloc) { 52713626Sjairo.balart@metempsy.com if (bi->longestMatchPred == taken) { 52813626Sjairo.balart@metempsy.com alloc = false; 52913626Sjairo.balart@metempsy.com } 53013626Sjairo.balart@metempsy.com // if it was delivering the correct prediction, no need to 53113626Sjairo.balart@metempsy.com // allocate new entry even if the overall prediction was false 53213626Sjairo.balart@metempsy.com if (bi->longestMatchPred != bi->altTaken) { 53314081Sjavier.bueno@metempsy.com ctrUpdate( 53414081Sjavier.bueno@metempsy.com useAltPredForNewlyAllocated[getUseAltIdx(bi, branch_pc)], 53514081Sjavier.bueno@metempsy.com bi->altTaken == taken, useAltOnNaBits); 53613626Sjairo.balart@metempsy.com } 53713626Sjairo.balart@metempsy.com } 53813626Sjairo.balart@metempsy.com } 53913626Sjairo.balart@metempsy.com 54014081Sjavier.bueno@metempsy.com if (!preAdjustAlloc) { 54114081Sjavier.bueno@metempsy.com adjustAlloc(alloc, taken, pred); 54214081Sjavier.bueno@metempsy.com } 54313626Sjairo.balart@metempsy.com 54413626Sjairo.balart@metempsy.com handleAllocAndUReset(alloc, taken, bi, nrand); 54513626Sjairo.balart@metempsy.com 54613626Sjairo.balart@metempsy.com handleTAGEUpdate(branch_pc, taken, bi); 54713626Sjairo.balart@metempsy.com} 54813626Sjairo.balart@metempsy.com 54913626Sjairo.balart@metempsy.comvoid 55013626Sjairo.balart@metempsy.comTAGEBase::handleTAGEUpdate(Addr branch_pc, bool taken, BranchInfo* bi) 55113626Sjairo.balart@metempsy.com{ 55213626Sjairo.balart@metempsy.com if (bi->hitBank > 0) { 55313626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating tag table entry (%d,%d) for branch %lx\n", 55413626Sjairo.balart@metempsy.com bi->hitBank, bi->hitBankIndex, branch_pc); 55513626Sjairo.balart@metempsy.com ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken, 55613626Sjairo.balart@metempsy.com tagTableCounterBits); 55713626Sjairo.balart@metempsy.com // if the provider entry is not certified to be useful also update 55813626Sjairo.balart@metempsy.com // the alternate prediction 55913626Sjairo.balart@metempsy.com if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) { 56013626Sjairo.balart@metempsy.com if (bi->altBank > 0) { 56113626Sjairo.balart@metempsy.com ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken, 56213626Sjairo.balart@metempsy.com tagTableCounterBits); 56313626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating tag table entry (%d,%d) for" 56413626Sjairo.balart@metempsy.com " branch %lx\n", bi->hitBank, bi->hitBankIndex, 56513626Sjairo.balart@metempsy.com branch_pc); 56613626Sjairo.balart@metempsy.com } 56713626Sjairo.balart@metempsy.com if (bi->altBank == 0) { 56813626Sjairo.balart@metempsy.com baseUpdate(branch_pc, taken, bi); 56913626Sjairo.balart@metempsy.com } 57013626Sjairo.balart@metempsy.com } 57113626Sjairo.balart@metempsy.com 57213626Sjairo.balart@metempsy.com // update the u counter 57313626Sjairo.balart@metempsy.com if (bi->tagePred != bi->altTaken) { 57413626Sjairo.balart@metempsy.com unsignedCtrUpdate(gtable[bi->hitBank][bi->hitBankIndex].u, 57513626Sjairo.balart@metempsy.com bi->tagePred == taken, tagTableUBits); 57613626Sjairo.balart@metempsy.com } 57713626Sjairo.balart@metempsy.com } else { 57813626Sjairo.balart@metempsy.com baseUpdate(branch_pc, taken, bi); 57913626Sjairo.balart@metempsy.com } 58013626Sjairo.balart@metempsy.com} 58113626Sjairo.balart@metempsy.com 58213626Sjairo.balart@metempsy.comvoid 58313626Sjairo.balart@metempsy.comTAGEBase::updateHistories(ThreadID tid, Addr branch_pc, bool taken, 58413626Sjairo.balart@metempsy.com BranchInfo* bi, bool speculative, 58513626Sjairo.balart@metempsy.com const StaticInstPtr &inst, Addr target) 58613626Sjairo.balart@metempsy.com{ 58713626Sjairo.balart@metempsy.com if (speculative != speculativeHistUpdate) { 58813626Sjairo.balart@metempsy.com return; 58913626Sjairo.balart@metempsy.com } 59013626Sjairo.balart@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 59113626Sjairo.balart@metempsy.com // UPDATE HISTORIES 59213626Sjairo.balart@metempsy.com bool pathbit = ((branch_pc >> instShiftAmt) & 1); 59313626Sjairo.balart@metempsy.com //on a squash, return pointers to this and recompute indices. 59413626Sjairo.balart@metempsy.com //update user history 59513626Sjairo.balart@metempsy.com updateGHist(tHist.gHist, taken, tHist.globalHistory, tHist.ptGhist); 59613626Sjairo.balart@metempsy.com tHist.pathHist = (tHist.pathHist << 1) + pathbit; 59713626Sjairo.balart@metempsy.com tHist.pathHist = (tHist.pathHist & ((ULL(1) << pathHistBits) - 1)); 59813626Sjairo.balart@metempsy.com 59913626Sjairo.balart@metempsy.com if (speculative) { 60013626Sjairo.balart@metempsy.com bi->ptGhist = tHist.ptGhist; 60113626Sjairo.balart@metempsy.com bi->pathHist = tHist.pathHist; 60213626Sjairo.balart@metempsy.com } 60313626Sjairo.balart@metempsy.com 60413626Sjairo.balart@metempsy.com //prepare next index and tag computations for user branchs 60513626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) 60613626Sjairo.balart@metempsy.com { 60713626Sjairo.balart@metempsy.com if (speculative) { 60813626Sjairo.balart@metempsy.com bi->ci[i] = tHist.computeIndices[i].comp; 60913626Sjairo.balart@metempsy.com bi->ct0[i] = tHist.computeTags[0][i].comp; 61013626Sjairo.balart@metempsy.com bi->ct1[i] = tHist.computeTags[1][i].comp; 61113626Sjairo.balart@metempsy.com } 61213626Sjairo.balart@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 61313626Sjairo.balart@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 61413626Sjairo.balart@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 61513626Sjairo.balart@metempsy.com } 61613626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating global histories with branch:%lx; taken?:%d, " 61713626Sjairo.balart@metempsy.com "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist, 61813626Sjairo.balart@metempsy.com tHist.ptGhist); 61913626Sjairo.balart@metempsy.com assert(threadHistory[tid].gHist == 62013626Sjairo.balart@metempsy.com &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]); 62113626Sjairo.balart@metempsy.com} 62213626Sjairo.balart@metempsy.com 62313626Sjairo.balart@metempsy.comvoid 62413626Sjairo.balart@metempsy.comTAGEBase::squash(ThreadID tid, bool taken, TAGEBase::BranchInfo *bi, 62513626Sjairo.balart@metempsy.com Addr target) 62613626Sjairo.balart@metempsy.com{ 62713626Sjairo.balart@metempsy.com if (!speculativeHistUpdate) { 62813626Sjairo.balart@metempsy.com /* If there are no speculative updates, no actions are needed */ 62913626Sjairo.balart@metempsy.com return; 63013626Sjairo.balart@metempsy.com } 63113626Sjairo.balart@metempsy.com 63213626Sjairo.balart@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 63313626Sjairo.balart@metempsy.com DPRINTF(Tage, "Restoring branch info: %lx; taken? %d; PathHistory:%x, " 63413626Sjairo.balart@metempsy.com "pointer:%d\n", bi->branchPC,taken, bi->pathHist, bi->ptGhist); 63513626Sjairo.balart@metempsy.com tHist.pathHist = bi->pathHist; 63613626Sjairo.balart@metempsy.com tHist.ptGhist = bi->ptGhist; 63713626Sjairo.balart@metempsy.com tHist.gHist = &(tHist.globalHistory[tHist.ptGhist]); 63813626Sjairo.balart@metempsy.com tHist.gHist[0] = (taken ? 1 : 0); 63913626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 64013626Sjairo.balart@metempsy.com tHist.computeIndices[i].comp = bi->ci[i]; 64113626Sjairo.balart@metempsy.com tHist.computeTags[0][i].comp = bi->ct0[i]; 64213626Sjairo.balart@metempsy.com tHist.computeTags[1][i].comp = bi->ct1[i]; 64313626Sjairo.balart@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 64413626Sjairo.balart@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 64513626Sjairo.balart@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 64613626Sjairo.balart@metempsy.com } 64713626Sjairo.balart@metempsy.com} 64813626Sjairo.balart@metempsy.com 64913626Sjairo.balart@metempsy.comvoid 65013626Sjairo.balart@metempsy.comTAGEBase::extraAltCalc(BranchInfo* bi) 65113626Sjairo.balart@metempsy.com{ 65213626Sjairo.balart@metempsy.com // do nothing. This is only used in some derived classes 65313626Sjairo.balart@metempsy.com return; 65413626Sjairo.balart@metempsy.com} 65513626Sjairo.balart@metempsy.com 65613626Sjairo.balart@metempsy.comvoid 65713626Sjairo.balart@metempsy.comTAGEBase::updateStats(bool taken, BranchInfo* bi) 65813626Sjairo.balart@metempsy.com{ 65913626Sjairo.balart@metempsy.com if (taken == bi->tagePred) { 66013626Sjairo.balart@metempsy.com // correct prediction 66113626Sjairo.balart@metempsy.com switch (bi->provider) { 66213626Sjairo.balart@metempsy.com case BIMODAL_ONLY: tageBimodalProviderCorrect++; break; 66313626Sjairo.balart@metempsy.com case TAGE_LONGEST_MATCH: tageLongestMatchProviderCorrect++; break; 66413626Sjairo.balart@metempsy.com case BIMODAL_ALT_MATCH: bimodalAltMatchProviderCorrect++; break; 66513626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: tageAltMatchProviderCorrect++; break; 66613626Sjairo.balart@metempsy.com } 66713626Sjairo.balart@metempsy.com } else { 66813626Sjairo.balart@metempsy.com // wrong prediction 66913626Sjairo.balart@metempsy.com switch (bi->provider) { 67013626Sjairo.balart@metempsy.com case BIMODAL_ONLY: tageBimodalProviderWrong++; break; 67113626Sjairo.balart@metempsy.com case TAGE_LONGEST_MATCH: 67213626Sjairo.balart@metempsy.com tageLongestMatchProviderWrong++; 67313626Sjairo.balart@metempsy.com if (bi->altTaken == taken) { 67413626Sjairo.balart@metempsy.com tageAltMatchProviderWouldHaveHit++; 67513626Sjairo.balart@metempsy.com } 67613626Sjairo.balart@metempsy.com break; 67713626Sjairo.balart@metempsy.com case BIMODAL_ALT_MATCH: 67813626Sjairo.balart@metempsy.com bimodalAltMatchProviderWrong++; 67913626Sjairo.balart@metempsy.com break; 68013626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: 68113626Sjairo.balart@metempsy.com tageAltMatchProviderWrong++; 68213626Sjairo.balart@metempsy.com break; 68313626Sjairo.balart@metempsy.com } 68413626Sjairo.balart@metempsy.com 68513626Sjairo.balart@metempsy.com switch (bi->provider) { 68613626Sjairo.balart@metempsy.com case BIMODAL_ALT_MATCH: 68713626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: 68813626Sjairo.balart@metempsy.com if (bi->longestMatchPred == taken) { 68913626Sjairo.balart@metempsy.com tageLongestMatchProviderWouldHaveHit++; 69013626Sjairo.balart@metempsy.com } 69113626Sjairo.balart@metempsy.com } 69213626Sjairo.balart@metempsy.com } 69313626Sjairo.balart@metempsy.com 69413626Sjairo.balart@metempsy.com switch (bi->provider) { 69513626Sjairo.balart@metempsy.com case TAGE_LONGEST_MATCH: 69613626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: 69713626Sjairo.balart@metempsy.com tageLongestMatchProvider[bi->hitBank]++; 69813626Sjairo.balart@metempsy.com tageAltMatchProvider[bi->altBank]++; 69913626Sjairo.balart@metempsy.com break; 70013626Sjairo.balart@metempsy.com } 70113626Sjairo.balart@metempsy.com} 70213626Sjairo.balart@metempsy.com 70313626Sjairo.balart@metempsy.comunsigned 70413626Sjairo.balart@metempsy.comTAGEBase::getGHR(ThreadID tid, BranchInfo *bi) const 70513626Sjairo.balart@metempsy.com{ 70613626Sjairo.balart@metempsy.com unsigned val = 0; 70713626Sjairo.balart@metempsy.com for (unsigned i = 0; i < 32; i++) { 70813626Sjairo.balart@metempsy.com // Make sure we don't go out of bounds 70913626Sjairo.balart@metempsy.com int gh_offset = bi->ptGhist + i; 71013626Sjairo.balart@metempsy.com assert(&(threadHistory[tid].globalHistory[gh_offset]) < 71113626Sjairo.balart@metempsy.com threadHistory[tid].globalHistory + histBufferSize); 71213626Sjairo.balart@metempsy.com val |= ((threadHistory[tid].globalHistory[gh_offset] & 0x1) << i); 71313626Sjairo.balart@metempsy.com } 71413626Sjairo.balart@metempsy.com 71513626Sjairo.balart@metempsy.com return val; 71613626Sjairo.balart@metempsy.com} 71713626Sjairo.balart@metempsy.com 71813626Sjairo.balart@metempsy.comvoid 71913626Sjairo.balart@metempsy.comTAGEBase::regStats() 72013626Sjairo.balart@metempsy.com{ 72113626Sjairo.balart@metempsy.com tageLongestMatchProviderCorrect 72213626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProviderCorrect") 72313626Sjairo.balart@metempsy.com .desc("Number of times TAGE Longest Match is the provider and " 72413626Sjairo.balart@metempsy.com "the prediction is correct"); 72513626Sjairo.balart@metempsy.com 72613626Sjairo.balart@metempsy.com tageAltMatchProviderCorrect 72713626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProviderCorrect") 72813626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the provider and " 72913626Sjairo.balart@metempsy.com "the prediction is correct"); 73013626Sjairo.balart@metempsy.com 73113626Sjairo.balart@metempsy.com bimodalAltMatchProviderCorrect 73213626Sjairo.balart@metempsy.com .name(name() + ".bimodalAltMatchProviderCorrect") 73313626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the bimodal and it is the " 73413626Sjairo.balart@metempsy.com "provider and the prediction is correct"); 73513626Sjairo.balart@metempsy.com 73613626Sjairo.balart@metempsy.com tageBimodalProviderCorrect 73713626Sjairo.balart@metempsy.com .name(name() + ".tageBimodalProviderCorrect") 73813626Sjairo.balart@metempsy.com .desc("Number of times there are no hits on the TAGE tables " 73913626Sjairo.balart@metempsy.com "and the bimodal prediction is correct"); 74013626Sjairo.balart@metempsy.com 74113626Sjairo.balart@metempsy.com tageLongestMatchProviderWrong 74213626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProviderWrong") 74313626Sjairo.balart@metempsy.com .desc("Number of times TAGE Longest Match is the provider and " 74413626Sjairo.balart@metempsy.com "the prediction is wrong"); 74513626Sjairo.balart@metempsy.com 74613626Sjairo.balart@metempsy.com tageAltMatchProviderWrong 74713626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProviderWrong") 74813626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the provider and " 74913626Sjairo.balart@metempsy.com "the prediction is wrong"); 75013626Sjairo.balart@metempsy.com 75113626Sjairo.balart@metempsy.com bimodalAltMatchProviderWrong 75213626Sjairo.balart@metempsy.com .name(name() + ".bimodalAltMatchProviderWrong") 75313626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the bimodal and it is the " 75413626Sjairo.balart@metempsy.com "provider and the prediction is wrong"); 75513626Sjairo.balart@metempsy.com 75613626Sjairo.balart@metempsy.com tageBimodalProviderWrong 75713626Sjairo.balart@metempsy.com .name(name() + ".tageBimodalProviderWrong") 75813626Sjairo.balart@metempsy.com .desc("Number of times there are no hits on the TAGE tables " 75913626Sjairo.balart@metempsy.com "and the bimodal prediction is wrong"); 76013626Sjairo.balart@metempsy.com 76113626Sjairo.balart@metempsy.com tageAltMatchProviderWouldHaveHit 76213626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProviderWouldHaveHit") 76313626Sjairo.balart@metempsy.com .desc("Number of times TAGE Longest Match is the provider, " 76413626Sjairo.balart@metempsy.com "the prediction is wrong and Alt Match prediction was correct"); 76513626Sjairo.balart@metempsy.com 76613626Sjairo.balart@metempsy.com tageLongestMatchProviderWouldHaveHit 76713626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProviderWouldHaveHit") 76813626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the provider, the " 76913626Sjairo.balart@metempsy.com "prediction is wrong and Longest Match prediction was correct"); 77013626Sjairo.balart@metempsy.com 77113626Sjairo.balart@metempsy.com tageLongestMatchProvider 77213626Sjairo.balart@metempsy.com .init(nHistoryTables + 1) 77313626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProvider") 77413626Sjairo.balart@metempsy.com .desc("TAGE provider for longest match"); 77513626Sjairo.balart@metempsy.com 77613626Sjairo.balart@metempsy.com tageAltMatchProvider 77713626Sjairo.balart@metempsy.com .init(nHistoryTables + 1) 77813626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProvider") 77913626Sjairo.balart@metempsy.com .desc("TAGE provider for alt match"); 78013626Sjairo.balart@metempsy.com} 78113626Sjairo.balart@metempsy.com 78213626Sjairo.balart@metempsy.comint8_t 78313626Sjairo.balart@metempsy.comTAGEBase::getCtr(int hitBank, int hitBankIndex) const 78413626Sjairo.balart@metempsy.com{ 78513626Sjairo.balart@metempsy.com return gtable[hitBank][hitBankIndex].ctr; 78613626Sjairo.balart@metempsy.com} 78713626Sjairo.balart@metempsy.com 78813626Sjairo.balart@metempsy.comunsigned 78913626Sjairo.balart@metempsy.comTAGEBase::getTageCtrBits() const 79013626Sjairo.balart@metempsy.com{ 79113626Sjairo.balart@metempsy.com return tagTableCounterBits; 79213626Sjairo.balart@metempsy.com} 79313626Sjairo.balart@metempsy.com 79413626Sjairo.balart@metempsy.comint 79513626Sjairo.balart@metempsy.comTAGEBase::getPathHist(ThreadID tid) const 79613626Sjairo.balart@metempsy.com{ 79713626Sjairo.balart@metempsy.com return threadHistory[tid].pathHist; 79813626Sjairo.balart@metempsy.com} 79913626Sjairo.balart@metempsy.com 80013626Sjairo.balart@metempsy.combool 80113626Sjairo.balart@metempsy.comTAGEBase::isSpeculativeUpdateEnabled() const 80213626Sjairo.balart@metempsy.com{ 80313626Sjairo.balart@metempsy.com return speculativeHistUpdate; 80413626Sjairo.balart@metempsy.com} 80513626Sjairo.balart@metempsy.com 80614081Sjavier.bueno@metempsy.comsize_t 80714081Sjavier.bueno@metempsy.comTAGEBase::getSizeInBits() const { 80814081Sjavier.bueno@metempsy.com size_t bits = 0; 80914081Sjavier.bueno@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 81014081Sjavier.bueno@metempsy.com bits += (1 << logTagTableSizes[i]) * 81114081Sjavier.bueno@metempsy.com (tagTableCounterBits + tagTableUBits + tagTableTagWidths[i]); 81214081Sjavier.bueno@metempsy.com } 81314081Sjavier.bueno@metempsy.com uint64_t bimodalTableSize = ULL(1) << logTagTableSizes[0]; 81414081Sjavier.bueno@metempsy.com bits += numUseAltOnNa * useAltOnNaBits; 81514081Sjavier.bueno@metempsy.com bits += bimodalTableSize; 81614081Sjavier.bueno@metempsy.com bits += (bimodalTableSize >> logRatioBiModalHystEntries); 81714081Sjavier.bueno@metempsy.com bits += histLengths[nHistoryTables]; 81814081Sjavier.bueno@metempsy.com bits += pathHistBits; 81914081Sjavier.bueno@metempsy.com bits += logUResetPeriod; 82014081Sjavier.bueno@metempsy.com return bits; 82114081Sjavier.bueno@metempsy.com} 82214081Sjavier.bueno@metempsy.com 82313626Sjairo.balart@metempsy.comTAGEBase* 82413626Sjairo.balart@metempsy.comTAGEBaseParams::create() 82513626Sjairo.balart@metempsy.com{ 82613626Sjairo.balart@metempsy.com return new TAGEBase(this); 82713626Sjairo.balart@metempsy.com} 828