tage_base.cc revision 13685
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), 6213626Sjairo.balart@metempsy.com numUseAltOnNa(p->numUseAltOnNa), 6313626Sjairo.balart@metempsy.com useAltOnNaBits(p->useAltOnNaBits), 6413626Sjairo.balart@metempsy.com maxNumAlloc(p->maxNumAlloc), 6513626Sjairo.balart@metempsy.com noSkip(p->noSkip), 6613626Sjairo.balart@metempsy.com speculativeHistUpdate(p->speculativeHistUpdate), 6713626Sjairo.balart@metempsy.com instShiftAmt(p->instShiftAmt) 6813626Sjairo.balart@metempsy.com{ 6913626Sjairo.balart@metempsy.com if (noSkip.empty()) { 7013626Sjairo.balart@metempsy.com // Set all the table to enabled by default 7113626Sjairo.balart@metempsy.com noSkip.resize(nHistoryTables + 1, true); 7213626Sjairo.balart@metempsy.com } 7313626Sjairo.balart@metempsy.com} 7413626Sjairo.balart@metempsy.com 7513626Sjairo.balart@metempsy.comTAGEBase::BranchInfo* 7613626Sjairo.balart@metempsy.comTAGEBase::makeBranchInfo() { 7713626Sjairo.balart@metempsy.com return new BranchInfo(*this); 7813626Sjairo.balart@metempsy.com} 7913626Sjairo.balart@metempsy.com 8013626Sjairo.balart@metempsy.comvoid 8113626Sjairo.balart@metempsy.comTAGEBase::init() 8213626Sjairo.balart@metempsy.com{ 8313626Sjairo.balart@metempsy.com // Current method for periodically resetting the u counter bits only 8413626Sjairo.balart@metempsy.com // works for 1 or 2 bits 8513626Sjairo.balart@metempsy.com // Also make sure that it is not 0 8613626Sjairo.balart@metempsy.com assert(tagTableUBits <= 2 && (tagTableUBits > 0)); 8713626Sjairo.balart@metempsy.com 8813626Sjairo.balart@metempsy.com // we use int type for the path history, so it cannot be more than 8913626Sjairo.balart@metempsy.com // its size 9013626Sjairo.balart@metempsy.com assert(pathHistBits <= (sizeof(int)*8)); 9113626Sjairo.balart@metempsy.com 9213626Sjairo.balart@metempsy.com // initialize the counter to half of the period 9313626Sjairo.balart@metempsy.com assert(logUResetPeriod != 0); 9413626Sjairo.balart@metempsy.com tCounter = ULL(1) << (logUResetPeriod - 1); 9513626Sjairo.balart@metempsy.com 9613626Sjairo.balart@metempsy.com assert(histBufferSize > maxHist * 2); 9713626Sjairo.balart@metempsy.com 9813626Sjairo.balart@metempsy.com useAltPredForNewlyAllocated.resize(numUseAltOnNa, 0); 9913626Sjairo.balart@metempsy.com 10013626Sjairo.balart@metempsy.com for (auto& history : threadHistory) { 10113626Sjairo.balart@metempsy.com history.pathHist = 0; 10213626Sjairo.balart@metempsy.com history.globalHistory = new uint8_t[histBufferSize]; 10313626Sjairo.balart@metempsy.com history.gHist = history.globalHistory; 10413626Sjairo.balart@metempsy.com memset(history.gHist, 0, histBufferSize); 10513626Sjairo.balart@metempsy.com history.ptGhist = 0; 10613626Sjairo.balart@metempsy.com } 10713626Sjairo.balart@metempsy.com 10813626Sjairo.balart@metempsy.com histLengths = new int [nHistoryTables+1]; 10913626Sjairo.balart@metempsy.com 11013626Sjairo.balart@metempsy.com calculateParameters(); 11113626Sjairo.balart@metempsy.com 11213626Sjairo.balart@metempsy.com assert(tagTableTagWidths.size() == (nHistoryTables+1)); 11313626Sjairo.balart@metempsy.com assert(logTagTableSizes.size() == (nHistoryTables+1)); 11413626Sjairo.balart@metempsy.com 11513626Sjairo.balart@metempsy.com // First entry is for the Bimodal table and it is untagged in this 11613626Sjairo.balart@metempsy.com // implementation 11713626Sjairo.balart@metempsy.com assert(tagTableTagWidths[0] == 0); 11813626Sjairo.balart@metempsy.com 11913626Sjairo.balart@metempsy.com for (auto& history : threadHistory) { 12013626Sjairo.balart@metempsy.com history.computeIndices = new FoldedHistory[nHistoryTables+1]; 12113626Sjairo.balart@metempsy.com history.computeTags[0] = new FoldedHistory[nHistoryTables+1]; 12213626Sjairo.balart@metempsy.com history.computeTags[1] = new FoldedHistory[nHistoryTables+1]; 12313626Sjairo.balart@metempsy.com 12413626Sjairo.balart@metempsy.com initFoldedHistories(history); 12513626Sjairo.balart@metempsy.com } 12613626Sjairo.balart@metempsy.com 12713626Sjairo.balart@metempsy.com const uint64_t bimodalTableSize = ULL(1) << logTagTableSizes[0]; 12813626Sjairo.balart@metempsy.com btablePrediction.resize(bimodalTableSize, false); 12913626Sjairo.balart@metempsy.com btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries, 13013626Sjairo.balart@metempsy.com true); 13113626Sjairo.balart@metempsy.com 13213626Sjairo.balart@metempsy.com gtable = new TageEntry*[nHistoryTables + 1]; 13313626Sjairo.balart@metempsy.com buildTageTables(); 13413626Sjairo.balart@metempsy.com 13513626Sjairo.balart@metempsy.com tableIndices = new int [nHistoryTables+1]; 13613626Sjairo.balart@metempsy.com tableTags = new int [nHistoryTables+1]; 13713626Sjairo.balart@metempsy.com} 13813626Sjairo.balart@metempsy.com 13913626Sjairo.balart@metempsy.comvoid 14013626Sjairo.balart@metempsy.comTAGEBase::initFoldedHistories(ThreadHistory & history) 14113626Sjairo.balart@metempsy.com{ 14213626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 14313626Sjairo.balart@metempsy.com history.computeIndices[i].init( 14413626Sjairo.balart@metempsy.com histLengths[i], (logTagTableSizes[i])); 14513626Sjairo.balart@metempsy.com history.computeTags[0][i].init( 14613626Sjairo.balart@metempsy.com history.computeIndices[i].origLength, tagTableTagWidths[i]); 14713626Sjairo.balart@metempsy.com history.computeTags[1][i].init( 14813626Sjairo.balart@metempsy.com history.computeIndices[i].origLength, tagTableTagWidths[i]-1); 14913626Sjairo.balart@metempsy.com DPRINTF(Tage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n", 15013626Sjairo.balart@metempsy.com histLengths[i], logTagTableSizes[i], tagTableTagWidths[i]); 15113626Sjairo.balart@metempsy.com } 15213626Sjairo.balart@metempsy.com} 15313626Sjairo.balart@metempsy.com 15413626Sjairo.balart@metempsy.comvoid 15513626Sjairo.balart@metempsy.comTAGEBase::buildTageTables() 15613626Sjairo.balart@metempsy.com{ 15713626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 15813626Sjairo.balart@metempsy.com gtable[i] = new TageEntry[1<<(logTagTableSizes[i])]; 15913626Sjairo.balart@metempsy.com } 16013626Sjairo.balart@metempsy.com} 16113626Sjairo.balart@metempsy.com 16213626Sjairo.balart@metempsy.comvoid 16313626Sjairo.balart@metempsy.comTAGEBase::calculateParameters() 16413626Sjairo.balart@metempsy.com{ 16513626Sjairo.balart@metempsy.com histLengths[1] = minHist; 16613626Sjairo.balart@metempsy.com histLengths[nHistoryTables] = maxHist; 16713626Sjairo.balart@metempsy.com 16813626Sjairo.balart@metempsy.com for (int i = 2; i <= nHistoryTables; i++) { 16913626Sjairo.balart@metempsy.com histLengths[i] = (int) (((double) minHist * 17013626Sjairo.balart@metempsy.com pow ((double) (maxHist) / (double) minHist, 17113626Sjairo.balart@metempsy.com (double) (i - 1) / (double) ((nHistoryTables- 1)))) 17213626Sjairo.balart@metempsy.com + 0.5); 17313626Sjairo.balart@metempsy.com } 17413626Sjairo.balart@metempsy.com} 17513626Sjairo.balart@metempsy.com 17613626Sjairo.balart@metempsy.comvoid 17713626Sjairo.balart@metempsy.comTAGEBase::btbUpdate(ThreadID tid, Addr branch_pc, BranchInfo* &bi) 17813626Sjairo.balart@metempsy.com{ 17913626Sjairo.balart@metempsy.com if (speculativeHistUpdate) { 18013626Sjairo.balart@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 18113626Sjairo.balart@metempsy.com DPRINTF(Tage, "BTB miss resets prediction: %lx\n", branch_pc); 18213626Sjairo.balart@metempsy.com assert(tHist.gHist == &tHist.globalHistory[tHist.ptGhist]); 18313626Sjairo.balart@metempsy.com tHist.gHist[0] = 0; 18413626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 18513626Sjairo.balart@metempsy.com tHist.computeIndices[i].comp = bi->ci[i]; 18613626Sjairo.balart@metempsy.com tHist.computeTags[0][i].comp = bi->ct0[i]; 18713626Sjairo.balart@metempsy.com tHist.computeTags[1][i].comp = bi->ct1[i]; 18813626Sjairo.balart@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 18913626Sjairo.balart@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 19013626Sjairo.balart@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 19113626Sjairo.balart@metempsy.com } 19213626Sjairo.balart@metempsy.com } 19313626Sjairo.balart@metempsy.com} 19413626Sjairo.balart@metempsy.com 19513626Sjairo.balart@metempsy.comint 19613626Sjairo.balart@metempsy.comTAGEBase::bindex(Addr pc_in) const 19713626Sjairo.balart@metempsy.com{ 19813626Sjairo.balart@metempsy.com return ((pc_in >> instShiftAmt) & ((ULL(1) << (logTagTableSizes[0])) - 1)); 19913626Sjairo.balart@metempsy.com} 20013626Sjairo.balart@metempsy.com 20113626Sjairo.balart@metempsy.comint 20213626Sjairo.balart@metempsy.comTAGEBase::F(int A, int size, int bank) const 20313626Sjairo.balart@metempsy.com{ 20413626Sjairo.balart@metempsy.com int A1, A2; 20513626Sjairo.balart@metempsy.com 20613626Sjairo.balart@metempsy.com A = A & ((ULL(1) << size) - 1); 20713626Sjairo.balart@metempsy.com A1 = (A & ((ULL(1) << logTagTableSizes[bank]) - 1)); 20813626Sjairo.balart@metempsy.com A2 = (A >> logTagTableSizes[bank]); 20913626Sjairo.balart@metempsy.com A2 = ((A2 << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 21013626Sjairo.balart@metempsy.com + (A2 >> (logTagTableSizes[bank] - bank)); 21113626Sjairo.balart@metempsy.com A = A1 ^ A2; 21213626Sjairo.balart@metempsy.com A = ((A << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 21313626Sjairo.balart@metempsy.com + (A >> (logTagTableSizes[bank] - bank)); 21413626Sjairo.balart@metempsy.com return (A); 21513626Sjairo.balart@metempsy.com} 21613626Sjairo.balart@metempsy.com 21713626Sjairo.balart@metempsy.com// gindex computes a full hash of pc, ghist and pathHist 21813626Sjairo.balart@metempsy.comint 21913626Sjairo.balart@metempsy.comTAGEBase::gindex(ThreadID tid, Addr pc, int bank) const 22013626Sjairo.balart@metempsy.com{ 22113626Sjairo.balart@metempsy.com int index; 22213626Sjairo.balart@metempsy.com int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits : 22313626Sjairo.balart@metempsy.com histLengths[bank]; 22413626Sjairo.balart@metempsy.com const unsigned int shiftedPc = pc >> instShiftAmt; 22513626Sjairo.balart@metempsy.com index = 22613626Sjairo.balart@metempsy.com shiftedPc ^ 22713626Sjairo.balart@metempsy.com (shiftedPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^ 22813626Sjairo.balart@metempsy.com threadHistory[tid].computeIndices[bank].comp ^ 22913626Sjairo.balart@metempsy.com F(threadHistory[tid].pathHist, hlen, bank); 23013626Sjairo.balart@metempsy.com 23113626Sjairo.balart@metempsy.com return (index & ((ULL(1) << (logTagTableSizes[bank])) - 1)); 23213626Sjairo.balart@metempsy.com} 23313626Sjairo.balart@metempsy.com 23413626Sjairo.balart@metempsy.com 23513626Sjairo.balart@metempsy.com// Tag computation 23613626Sjairo.balart@metempsy.comuint16_t 23713626Sjairo.balart@metempsy.comTAGEBase::gtag(ThreadID tid, Addr pc, int bank) const 23813626Sjairo.balart@metempsy.com{ 23913626Sjairo.balart@metempsy.com int tag = (pc >> instShiftAmt) ^ 24013626Sjairo.balart@metempsy.com threadHistory[tid].computeTags[0][bank].comp ^ 24113626Sjairo.balart@metempsy.com (threadHistory[tid].computeTags[1][bank].comp << 1); 24213626Sjairo.balart@metempsy.com 24313626Sjairo.balart@metempsy.com return (tag & ((ULL(1) << tagTableTagWidths[bank]) - 1)); 24413626Sjairo.balart@metempsy.com} 24513626Sjairo.balart@metempsy.com 24613626Sjairo.balart@metempsy.com 24713626Sjairo.balart@metempsy.com// Up-down saturating counter 24813626Sjairo.balart@metempsy.comtemplate<typename T> 24913626Sjairo.balart@metempsy.comvoid 25013626Sjairo.balart@metempsy.comTAGEBase::ctrUpdate(T & ctr, bool taken, int nbits) 25113626Sjairo.balart@metempsy.com{ 25213626Sjairo.balart@metempsy.com assert(nbits <= sizeof(T) << 3); 25313626Sjairo.balart@metempsy.com if (taken) { 25413626Sjairo.balart@metempsy.com if (ctr < ((1 << (nbits - 1)) - 1)) 25513626Sjairo.balart@metempsy.com ctr++; 25613626Sjairo.balart@metempsy.com } else { 25713626Sjairo.balart@metempsy.com if (ctr > -(1 << (nbits - 1))) 25813626Sjairo.balart@metempsy.com ctr--; 25913626Sjairo.balart@metempsy.com } 26013626Sjairo.balart@metempsy.com} 26113626Sjairo.balart@metempsy.com 26213626Sjairo.balart@metempsy.com// int8_t and int versions of this function may be needed 26313626Sjairo.balart@metempsy.comtemplate void TAGEBase::ctrUpdate(int8_t & ctr, bool taken, int nbits); 26413626Sjairo.balart@metempsy.comtemplate void TAGEBase::ctrUpdate(int & ctr, bool taken, int nbits); 26513626Sjairo.balart@metempsy.com 26613626Sjairo.balart@metempsy.com// Up-down unsigned saturating counter 26713626Sjairo.balart@metempsy.comvoid 26813626Sjairo.balart@metempsy.comTAGEBase::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits) 26913626Sjairo.balart@metempsy.com{ 27013626Sjairo.balart@metempsy.com assert(nbits <= sizeof(uint8_t) << 3); 27113626Sjairo.balart@metempsy.com if (up) { 27213626Sjairo.balart@metempsy.com if (ctr < ((1 << nbits) - 1)) 27313626Sjairo.balart@metempsy.com ctr++; 27413626Sjairo.balart@metempsy.com } else { 27513626Sjairo.balart@metempsy.com if (ctr) 27613626Sjairo.balart@metempsy.com ctr--; 27713626Sjairo.balart@metempsy.com } 27813626Sjairo.balart@metempsy.com} 27913626Sjairo.balart@metempsy.com 28013626Sjairo.balart@metempsy.com// Bimodal prediction 28113626Sjairo.balart@metempsy.combool 28213626Sjairo.balart@metempsy.comTAGEBase::getBimodePred(Addr pc, BranchInfo* bi) const 28313626Sjairo.balart@metempsy.com{ 28413626Sjairo.balart@metempsy.com return btablePrediction[bi->bimodalIndex]; 28513626Sjairo.balart@metempsy.com} 28613626Sjairo.balart@metempsy.com 28713626Sjairo.balart@metempsy.com 28813626Sjairo.balart@metempsy.com// Update the bimodal predictor: a hysteresis bit is shared among N prediction 28913626Sjairo.balart@metempsy.com// bits (N = 2 ^ logRatioBiModalHystEntries) 29013626Sjairo.balart@metempsy.comvoid 29113626Sjairo.balart@metempsy.comTAGEBase::baseUpdate(Addr pc, bool taken, BranchInfo* bi) 29213626Sjairo.balart@metempsy.com{ 29313626Sjairo.balart@metempsy.com int inter = (btablePrediction[bi->bimodalIndex] << 1) 29413626Sjairo.balart@metempsy.com + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries]; 29513626Sjairo.balart@metempsy.com if (taken) { 29613626Sjairo.balart@metempsy.com if (inter < 3) 29713626Sjairo.balart@metempsy.com inter++; 29813626Sjairo.balart@metempsy.com } else if (inter > 0) { 29913626Sjairo.balart@metempsy.com inter--; 30013626Sjairo.balart@metempsy.com } 30113626Sjairo.balart@metempsy.com const bool pred = inter >> 1; 30213626Sjairo.balart@metempsy.com const bool hyst = inter & 1; 30313626Sjairo.balart@metempsy.com btablePrediction[bi->bimodalIndex] = pred; 30413626Sjairo.balart@metempsy.com btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst; 30513626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst); 30613626Sjairo.balart@metempsy.com} 30713626Sjairo.balart@metempsy.com 30813626Sjairo.balart@metempsy.com// shifting the global history: we manage the history in a big table in order 30913626Sjairo.balart@metempsy.com// to reduce simulation time 31013626Sjairo.balart@metempsy.comvoid 31113626Sjairo.balart@metempsy.comTAGEBase::updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &pt) 31213626Sjairo.balart@metempsy.com{ 31313626Sjairo.balart@metempsy.com if (pt == 0) { 31413626Sjairo.balart@metempsy.com DPRINTF(Tage, "Rolling over the histories\n"); 31513626Sjairo.balart@metempsy.com // Copy beginning of globalHistoryBuffer to end, such that 31613626Sjairo.balart@metempsy.com // the last maxHist outcomes are still reachable 31713626Sjairo.balart@metempsy.com // through pt[0 .. maxHist - 1]. 31813626Sjairo.balart@metempsy.com for (int i = 0; i < maxHist; i++) 31913626Sjairo.balart@metempsy.com tab[histBufferSize - maxHist + i] = tab[i]; 32013626Sjairo.balart@metempsy.com pt = histBufferSize - maxHist; 32113626Sjairo.balart@metempsy.com h = &tab[pt]; 32213626Sjairo.balart@metempsy.com } 32313626Sjairo.balart@metempsy.com pt--; 32413626Sjairo.balart@metempsy.com h--; 32513626Sjairo.balart@metempsy.com h[0] = (dir) ? 1 : 0; 32613626Sjairo.balart@metempsy.com} 32713626Sjairo.balart@metempsy.com 32813626Sjairo.balart@metempsy.comvoid 32913626Sjairo.balart@metempsy.comTAGEBase::calculateIndicesAndTags(ThreadID tid, Addr branch_pc, 33013626Sjairo.balart@metempsy.com BranchInfo* bi) 33113626Sjairo.balart@metempsy.com{ 33213626Sjairo.balart@metempsy.com // computes the table addresses and the partial tags 33313626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 33413626Sjairo.balart@metempsy.com tableIndices[i] = gindex(tid, branch_pc, i); 33513626Sjairo.balart@metempsy.com bi->tableIndices[i] = tableIndices[i]; 33613626Sjairo.balart@metempsy.com tableTags[i] = gtag(tid, branch_pc, i); 33713626Sjairo.balart@metempsy.com bi->tableTags[i] = tableTags[i]; 33813626Sjairo.balart@metempsy.com } 33913626Sjairo.balart@metempsy.com} 34013626Sjairo.balart@metempsy.com 34113626Sjairo.balart@metempsy.comunsigned 34213626Sjairo.balart@metempsy.comTAGEBase::getUseAltIdx(BranchInfo* bi) 34313626Sjairo.balart@metempsy.com{ 34413626Sjairo.balart@metempsy.com // There is only 1 counter on the base TAGE implementation 34513626Sjairo.balart@metempsy.com return 0; 34613626Sjairo.balart@metempsy.com} 34713626Sjairo.balart@metempsy.com 34813626Sjairo.balart@metempsy.combool 34913626Sjairo.balart@metempsy.comTAGEBase::tagePredict(ThreadID tid, Addr branch_pc, 35013626Sjairo.balart@metempsy.com bool cond_branch, BranchInfo* bi) 35113626Sjairo.balart@metempsy.com{ 35213626Sjairo.balart@metempsy.com Addr pc = branch_pc; 35313626Sjairo.balart@metempsy.com bool pred_taken = true; 35413626Sjairo.balart@metempsy.com 35513626Sjairo.balart@metempsy.com if (cond_branch) { 35613626Sjairo.balart@metempsy.com // TAGE prediction 35713626Sjairo.balart@metempsy.com 35813626Sjairo.balart@metempsy.com calculateIndicesAndTags(tid, pc, bi); 35913626Sjairo.balart@metempsy.com 36013626Sjairo.balart@metempsy.com bi->bimodalIndex = bindex(pc); 36113626Sjairo.balart@metempsy.com 36213626Sjairo.balart@metempsy.com bi->hitBank = 0; 36313626Sjairo.balart@metempsy.com bi->altBank = 0; 36413626Sjairo.balart@metempsy.com //Look for the bank with longest matching history 36513626Sjairo.balart@metempsy.com for (int i = nHistoryTables; i > 0; i--) { 36613626Sjairo.balart@metempsy.com if (noSkip[i] && 36713626Sjairo.balart@metempsy.com gtable[i][tableIndices[i]].tag == tableTags[i]) { 36813626Sjairo.balart@metempsy.com bi->hitBank = i; 36913626Sjairo.balart@metempsy.com bi->hitBankIndex = tableIndices[bi->hitBank]; 37013626Sjairo.balart@metempsy.com break; 37113626Sjairo.balart@metempsy.com } 37213626Sjairo.balart@metempsy.com } 37313626Sjairo.balart@metempsy.com //Look for the alternate bank 37413626Sjairo.balart@metempsy.com for (int i = bi->hitBank - 1; i > 0; i--) { 37513626Sjairo.balart@metempsy.com if (noSkip[i] && 37613626Sjairo.balart@metempsy.com gtable[i][tableIndices[i]].tag == tableTags[i]) { 37713626Sjairo.balart@metempsy.com bi->altBank = i; 37813626Sjairo.balart@metempsy.com bi->altBankIndex = tableIndices[bi->altBank]; 37913626Sjairo.balart@metempsy.com break; 38013626Sjairo.balart@metempsy.com } 38113626Sjairo.balart@metempsy.com } 38213626Sjairo.balart@metempsy.com //computes the prediction and the alternate prediction 38313626Sjairo.balart@metempsy.com if (bi->hitBank > 0) { 38413626Sjairo.balart@metempsy.com if (bi->altBank > 0) { 38513626Sjairo.balart@metempsy.com bi->altTaken = 38613626Sjairo.balart@metempsy.com gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0; 38713626Sjairo.balart@metempsy.com extraAltCalc(bi); 38813626Sjairo.balart@metempsy.com }else { 38913626Sjairo.balart@metempsy.com bi->altTaken = getBimodePred(pc, bi); 39013626Sjairo.balart@metempsy.com } 39113626Sjairo.balart@metempsy.com 39213626Sjairo.balart@metempsy.com bi->longestMatchPred = 39313626Sjairo.balart@metempsy.com gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0; 39413626Sjairo.balart@metempsy.com bi->pseudoNewAlloc = 39513626Sjairo.balart@metempsy.com abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1; 39613626Sjairo.balart@metempsy.com 39713626Sjairo.balart@metempsy.com //if the entry is recognized as a newly allocated entry and 39813626Sjairo.balart@metempsy.com //useAltPredForNewlyAllocated is positive use the alternate 39913626Sjairo.balart@metempsy.com //prediction 40013626Sjairo.balart@metempsy.com if ((useAltPredForNewlyAllocated[getUseAltIdx(bi)] < 0) || 40113626Sjairo.balart@metempsy.com ! bi->pseudoNewAlloc) { 40213626Sjairo.balart@metempsy.com bi->tagePred = bi->longestMatchPred; 40313626Sjairo.balart@metempsy.com bi->provider = TAGE_LONGEST_MATCH; 40413626Sjairo.balart@metempsy.com } else { 40513626Sjairo.balart@metempsy.com bi->tagePred = bi->altTaken; 40613626Sjairo.balart@metempsy.com bi->provider = bi->altBank ? TAGE_ALT_MATCH 40713626Sjairo.balart@metempsy.com : BIMODAL_ALT_MATCH; 40813626Sjairo.balart@metempsy.com } 40913626Sjairo.balart@metempsy.com } else { 41013626Sjairo.balart@metempsy.com bi->altTaken = getBimodePred(pc, bi); 41113626Sjairo.balart@metempsy.com bi->tagePred = bi->altTaken; 41213626Sjairo.balart@metempsy.com bi->longestMatchPred = bi->altTaken; 41313626Sjairo.balart@metempsy.com bi->provider = BIMODAL_ONLY; 41413626Sjairo.balart@metempsy.com } 41513626Sjairo.balart@metempsy.com //end TAGE prediction 41613626Sjairo.balart@metempsy.com 41713626Sjairo.balart@metempsy.com pred_taken = (bi->tagePred); 41813626Sjairo.balart@metempsy.com DPRINTF(Tage, "Predict for %lx: taken?:%d, tagePred:%d, altPred:%d\n", 41913626Sjairo.balart@metempsy.com branch_pc, pred_taken, bi->tagePred, bi->altTaken); 42013626Sjairo.balart@metempsy.com } 42113626Sjairo.balart@metempsy.com bi->branchPC = branch_pc; 42213626Sjairo.balart@metempsy.com bi->condBranch = cond_branch; 42313626Sjairo.balart@metempsy.com return pred_taken; 42413626Sjairo.balart@metempsy.com} 42513626Sjairo.balart@metempsy.com 42613626Sjairo.balart@metempsy.comvoid 42713685Sjavier.bueno@metempsy.comTAGEBase::adjustAlloc(bool & alloc, bool taken, bool pred_taken) 42813626Sjairo.balart@metempsy.com{ 42913626Sjairo.balart@metempsy.com // Nothing for this base class implementation 43013626Sjairo.balart@metempsy.com} 43113626Sjairo.balart@metempsy.com 43213626Sjairo.balart@metempsy.comvoid 43313626Sjairo.balart@metempsy.comTAGEBase::handleAllocAndUReset(bool alloc, bool taken, BranchInfo* bi, 43413626Sjairo.balart@metempsy.com int nrand) 43513626Sjairo.balart@metempsy.com{ 43613626Sjairo.balart@metempsy.com if (alloc) { 43713626Sjairo.balart@metempsy.com // is there some "unuseful" entry to allocate 43813626Sjairo.balart@metempsy.com uint8_t min = 1; 43913626Sjairo.balart@metempsy.com for (int i = nHistoryTables; i > bi->hitBank; i--) { 44013626Sjairo.balart@metempsy.com if (gtable[i][bi->tableIndices[i]].u < min) { 44113626Sjairo.balart@metempsy.com min = gtable[i][bi->tableIndices[i]].u; 44213626Sjairo.balart@metempsy.com } 44313626Sjairo.balart@metempsy.com } 44413626Sjairo.balart@metempsy.com 44513626Sjairo.balart@metempsy.com // we allocate an entry with a longer history 44613626Sjairo.balart@metempsy.com // to avoid ping-pong, we do not choose systematically the next 44713626Sjairo.balart@metempsy.com // entry, but among the 3 next entries 44813626Sjairo.balart@metempsy.com int Y = nrand & 44913626Sjairo.balart@metempsy.com ((ULL(1) << (nHistoryTables - bi->hitBank - 1)) - 1); 45013626Sjairo.balart@metempsy.com int X = bi->hitBank + 1; 45113626Sjairo.balart@metempsy.com if (Y & 1) { 45213626Sjairo.balart@metempsy.com X++; 45313626Sjairo.balart@metempsy.com if (Y & 2) 45413626Sjairo.balart@metempsy.com X++; 45513626Sjairo.balart@metempsy.com } 45613626Sjairo.balart@metempsy.com // No entry available, forces one to be available 45713626Sjairo.balart@metempsy.com if (min > 0) { 45813626Sjairo.balart@metempsy.com gtable[X][bi->tableIndices[X]].u = 0; 45913626Sjairo.balart@metempsy.com } 46013626Sjairo.balart@metempsy.com 46113626Sjairo.balart@metempsy.com 46213626Sjairo.balart@metempsy.com //Allocate entries 46313626Sjairo.balart@metempsy.com unsigned numAllocated = 0; 46413626Sjairo.balart@metempsy.com for (int i = X; i <= nHistoryTables; i++) { 46513626Sjairo.balart@metempsy.com if ((gtable[i][bi->tableIndices[i]].u == 0)) { 46613626Sjairo.balart@metempsy.com gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; 46713626Sjairo.balart@metempsy.com gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1; 46813626Sjairo.balart@metempsy.com ++numAllocated; 46913626Sjairo.balart@metempsy.com if (numAllocated == maxNumAlloc) { 47013626Sjairo.balart@metempsy.com break; 47113626Sjairo.balart@metempsy.com } 47213626Sjairo.balart@metempsy.com } 47313626Sjairo.balart@metempsy.com } 47413626Sjairo.balart@metempsy.com } 47513626Sjairo.balart@metempsy.com 47613626Sjairo.balart@metempsy.com tCounter++; 47713626Sjairo.balart@metempsy.com 47813626Sjairo.balart@metempsy.com handleUReset(); 47913626Sjairo.balart@metempsy.com} 48013626Sjairo.balart@metempsy.com 48113626Sjairo.balart@metempsy.comvoid 48213626Sjairo.balart@metempsy.comTAGEBase::handleUReset() 48313626Sjairo.balart@metempsy.com{ 48413626Sjairo.balart@metempsy.com //periodic reset of u: reset is not complete but bit by bit 48513626Sjairo.balart@metempsy.com if ((tCounter & ((ULL(1) << logUResetPeriod) - 1)) == 0) { 48613626Sjairo.balart@metempsy.com // reset least significant bit 48713626Sjairo.balart@metempsy.com // most significant bit becomes least significant bit 48813626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 48913626Sjairo.balart@metempsy.com for (int j = 0; j < (ULL(1) << logTagTableSizes[i]); j++) { 49013626Sjairo.balart@metempsy.com resetUctr(gtable[i][j].u); 49113626Sjairo.balart@metempsy.com } 49213626Sjairo.balart@metempsy.com } 49313626Sjairo.balart@metempsy.com } 49413626Sjairo.balart@metempsy.com} 49513626Sjairo.balart@metempsy.com 49613626Sjairo.balart@metempsy.comvoid 49713626Sjairo.balart@metempsy.comTAGEBase::resetUctr(uint8_t & u) 49813626Sjairo.balart@metempsy.com{ 49913626Sjairo.balart@metempsy.com u >>= 1; 50013626Sjairo.balart@metempsy.com} 50113626Sjairo.balart@metempsy.com 50213626Sjairo.balart@metempsy.comvoid 50313626Sjairo.balart@metempsy.comTAGEBase::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, 50413685Sjavier.bueno@metempsy.com BranchInfo* bi, int nrand, Addr corrTarget, bool pred) 50513626Sjairo.balart@metempsy.com{ 50613626Sjairo.balart@metempsy.com // TAGE UPDATE 50713626Sjairo.balart@metempsy.com // try to allocate a new entries only if prediction was wrong 50813626Sjairo.balart@metempsy.com bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables); 50913626Sjairo.balart@metempsy.com if (bi->hitBank > 0) { 51013626Sjairo.balart@metempsy.com // Manage the selection between longest matching and alternate 51113626Sjairo.balart@metempsy.com // matching for "pseudo"-newly allocated longest matching entry 51213626Sjairo.balart@metempsy.com bool PseudoNewAlloc = bi->pseudoNewAlloc; 51313626Sjairo.balart@metempsy.com // an entry is considered as newly allocated if its prediction 51413626Sjairo.balart@metempsy.com // counter is weak 51513626Sjairo.balart@metempsy.com if (PseudoNewAlloc) { 51613626Sjairo.balart@metempsy.com if (bi->longestMatchPred == taken) { 51713626Sjairo.balart@metempsy.com alloc = false; 51813626Sjairo.balart@metempsy.com } 51913626Sjairo.balart@metempsy.com // if it was delivering the correct prediction, no need to 52013626Sjairo.balart@metempsy.com // allocate new entry even if the overall prediction was false 52113626Sjairo.balart@metempsy.com if (bi->longestMatchPred != bi->altTaken) { 52213626Sjairo.balart@metempsy.com ctrUpdate(useAltPredForNewlyAllocated[getUseAltIdx(bi)], 52313626Sjairo.balart@metempsy.com bi->altTaken == taken, useAltOnNaBits); 52413626Sjairo.balart@metempsy.com } 52513626Sjairo.balart@metempsy.com } 52613626Sjairo.balart@metempsy.com } 52713626Sjairo.balart@metempsy.com 52813685Sjavier.bueno@metempsy.com adjustAlloc(alloc, taken, pred); 52913626Sjairo.balart@metempsy.com 53013626Sjairo.balart@metempsy.com handleAllocAndUReset(alloc, taken, bi, nrand); 53113626Sjairo.balart@metempsy.com 53213626Sjairo.balart@metempsy.com handleTAGEUpdate(branch_pc, taken, bi); 53313626Sjairo.balart@metempsy.com} 53413626Sjairo.balart@metempsy.com 53513626Sjairo.balart@metempsy.comvoid 53613626Sjairo.balart@metempsy.comTAGEBase::handleTAGEUpdate(Addr branch_pc, bool taken, BranchInfo* bi) 53713626Sjairo.balart@metempsy.com{ 53813626Sjairo.balart@metempsy.com if (bi->hitBank > 0) { 53913626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating tag table entry (%d,%d) for branch %lx\n", 54013626Sjairo.balart@metempsy.com bi->hitBank, bi->hitBankIndex, branch_pc); 54113626Sjairo.balart@metempsy.com ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken, 54213626Sjairo.balart@metempsy.com tagTableCounterBits); 54313626Sjairo.balart@metempsy.com // if the provider entry is not certified to be useful also update 54413626Sjairo.balart@metempsy.com // the alternate prediction 54513626Sjairo.balart@metempsy.com if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) { 54613626Sjairo.balart@metempsy.com if (bi->altBank > 0) { 54713626Sjairo.balart@metempsy.com ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken, 54813626Sjairo.balart@metempsy.com tagTableCounterBits); 54913626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating tag table entry (%d,%d) for" 55013626Sjairo.balart@metempsy.com " branch %lx\n", bi->hitBank, bi->hitBankIndex, 55113626Sjairo.balart@metempsy.com branch_pc); 55213626Sjairo.balart@metempsy.com } 55313626Sjairo.balart@metempsy.com if (bi->altBank == 0) { 55413626Sjairo.balart@metempsy.com baseUpdate(branch_pc, taken, bi); 55513626Sjairo.balart@metempsy.com } 55613626Sjairo.balart@metempsy.com } 55713626Sjairo.balart@metempsy.com 55813626Sjairo.balart@metempsy.com // update the u counter 55913626Sjairo.balart@metempsy.com if (bi->tagePred != bi->altTaken) { 56013626Sjairo.balart@metempsy.com unsignedCtrUpdate(gtable[bi->hitBank][bi->hitBankIndex].u, 56113626Sjairo.balart@metempsy.com bi->tagePred == taken, tagTableUBits); 56213626Sjairo.balart@metempsy.com } 56313626Sjairo.balart@metempsy.com } else { 56413626Sjairo.balart@metempsy.com baseUpdate(branch_pc, taken, bi); 56513626Sjairo.balart@metempsy.com } 56613626Sjairo.balart@metempsy.com} 56713626Sjairo.balart@metempsy.com 56813626Sjairo.balart@metempsy.comvoid 56913626Sjairo.balart@metempsy.comTAGEBase::updateHistories(ThreadID tid, Addr branch_pc, bool taken, 57013626Sjairo.balart@metempsy.com BranchInfo* bi, bool speculative, 57113626Sjairo.balart@metempsy.com const StaticInstPtr &inst, Addr target) 57213626Sjairo.balart@metempsy.com{ 57313626Sjairo.balart@metempsy.com if (speculative != speculativeHistUpdate) { 57413626Sjairo.balart@metempsy.com return; 57513626Sjairo.balart@metempsy.com } 57613626Sjairo.balart@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 57713626Sjairo.balart@metempsy.com // UPDATE HISTORIES 57813626Sjairo.balart@metempsy.com bool pathbit = ((branch_pc >> instShiftAmt) & 1); 57913626Sjairo.balart@metempsy.com //on a squash, return pointers to this and recompute indices. 58013626Sjairo.balart@metempsy.com //update user history 58113626Sjairo.balart@metempsy.com updateGHist(tHist.gHist, taken, tHist.globalHistory, tHist.ptGhist); 58213626Sjairo.balart@metempsy.com tHist.pathHist = (tHist.pathHist << 1) + pathbit; 58313626Sjairo.balart@metempsy.com tHist.pathHist = (tHist.pathHist & ((ULL(1) << pathHistBits) - 1)); 58413626Sjairo.balart@metempsy.com 58513626Sjairo.balart@metempsy.com if (speculative) { 58613626Sjairo.balart@metempsy.com bi->ptGhist = tHist.ptGhist; 58713626Sjairo.balart@metempsy.com bi->pathHist = tHist.pathHist; 58813626Sjairo.balart@metempsy.com } 58913626Sjairo.balart@metempsy.com 59013626Sjairo.balart@metempsy.com //prepare next index and tag computations for user branchs 59113626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) 59213626Sjairo.balart@metempsy.com { 59313626Sjairo.balart@metempsy.com if (speculative) { 59413626Sjairo.balart@metempsy.com bi->ci[i] = tHist.computeIndices[i].comp; 59513626Sjairo.balart@metempsy.com bi->ct0[i] = tHist.computeTags[0][i].comp; 59613626Sjairo.balart@metempsy.com bi->ct1[i] = tHist.computeTags[1][i].comp; 59713626Sjairo.balart@metempsy.com } 59813626Sjairo.balart@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 59913626Sjairo.balart@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 60013626Sjairo.balart@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 60113626Sjairo.balart@metempsy.com } 60213626Sjairo.balart@metempsy.com DPRINTF(Tage, "Updating global histories with branch:%lx; taken?:%d, " 60313626Sjairo.balart@metempsy.com "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist, 60413626Sjairo.balart@metempsy.com tHist.ptGhist); 60513626Sjairo.balart@metempsy.com assert(threadHistory[tid].gHist == 60613626Sjairo.balart@metempsy.com &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]); 60713626Sjairo.balart@metempsy.com} 60813626Sjairo.balart@metempsy.com 60913626Sjairo.balart@metempsy.comvoid 61013626Sjairo.balart@metempsy.comTAGEBase::squash(ThreadID tid, bool taken, TAGEBase::BranchInfo *bi, 61113626Sjairo.balart@metempsy.com Addr target) 61213626Sjairo.balart@metempsy.com{ 61313626Sjairo.balart@metempsy.com if (!speculativeHistUpdate) { 61413626Sjairo.balart@metempsy.com /* If there are no speculative updates, no actions are needed */ 61513626Sjairo.balart@metempsy.com return; 61613626Sjairo.balart@metempsy.com } 61713626Sjairo.balart@metempsy.com 61813626Sjairo.balart@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 61913626Sjairo.balart@metempsy.com DPRINTF(Tage, "Restoring branch info: %lx; taken? %d; PathHistory:%x, " 62013626Sjairo.balart@metempsy.com "pointer:%d\n", bi->branchPC,taken, bi->pathHist, bi->ptGhist); 62113626Sjairo.balart@metempsy.com tHist.pathHist = bi->pathHist; 62213626Sjairo.balart@metempsy.com tHist.ptGhist = bi->ptGhist; 62313626Sjairo.balart@metempsy.com tHist.gHist = &(tHist.globalHistory[tHist.ptGhist]); 62413626Sjairo.balart@metempsy.com tHist.gHist[0] = (taken ? 1 : 0); 62513626Sjairo.balart@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 62613626Sjairo.balart@metempsy.com tHist.computeIndices[i].comp = bi->ci[i]; 62713626Sjairo.balart@metempsy.com tHist.computeTags[0][i].comp = bi->ct0[i]; 62813626Sjairo.balart@metempsy.com tHist.computeTags[1][i].comp = bi->ct1[i]; 62913626Sjairo.balart@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 63013626Sjairo.balart@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 63113626Sjairo.balart@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 63213626Sjairo.balart@metempsy.com } 63313626Sjairo.balart@metempsy.com} 63413626Sjairo.balart@metempsy.com 63513626Sjairo.balart@metempsy.comvoid 63613626Sjairo.balart@metempsy.comTAGEBase::extraAltCalc(BranchInfo* bi) 63713626Sjairo.balart@metempsy.com{ 63813626Sjairo.balart@metempsy.com // do nothing. This is only used in some derived classes 63913626Sjairo.balart@metempsy.com return; 64013626Sjairo.balart@metempsy.com} 64113626Sjairo.balart@metempsy.com 64213626Sjairo.balart@metempsy.comvoid 64313626Sjairo.balart@metempsy.comTAGEBase::updateStats(bool taken, BranchInfo* bi) 64413626Sjairo.balart@metempsy.com{ 64513626Sjairo.balart@metempsy.com if (taken == bi->tagePred) { 64613626Sjairo.balart@metempsy.com // correct prediction 64713626Sjairo.balart@metempsy.com switch (bi->provider) { 64813626Sjairo.balart@metempsy.com case BIMODAL_ONLY: tageBimodalProviderCorrect++; break; 64913626Sjairo.balart@metempsy.com case TAGE_LONGEST_MATCH: tageLongestMatchProviderCorrect++; break; 65013626Sjairo.balart@metempsy.com case BIMODAL_ALT_MATCH: bimodalAltMatchProviderCorrect++; break; 65113626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: tageAltMatchProviderCorrect++; break; 65213626Sjairo.balart@metempsy.com } 65313626Sjairo.balart@metempsy.com } else { 65413626Sjairo.balart@metempsy.com // wrong prediction 65513626Sjairo.balart@metempsy.com switch (bi->provider) { 65613626Sjairo.balart@metempsy.com case BIMODAL_ONLY: tageBimodalProviderWrong++; break; 65713626Sjairo.balart@metempsy.com case TAGE_LONGEST_MATCH: 65813626Sjairo.balart@metempsy.com tageLongestMatchProviderWrong++; 65913626Sjairo.balart@metempsy.com if (bi->altTaken == taken) { 66013626Sjairo.balart@metempsy.com tageAltMatchProviderWouldHaveHit++; 66113626Sjairo.balart@metempsy.com } 66213626Sjairo.balart@metempsy.com break; 66313626Sjairo.balart@metempsy.com case BIMODAL_ALT_MATCH: 66413626Sjairo.balart@metempsy.com bimodalAltMatchProviderWrong++; 66513626Sjairo.balart@metempsy.com break; 66613626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: 66713626Sjairo.balart@metempsy.com tageAltMatchProviderWrong++; 66813626Sjairo.balart@metempsy.com break; 66913626Sjairo.balart@metempsy.com } 67013626Sjairo.balart@metempsy.com 67113626Sjairo.balart@metempsy.com switch (bi->provider) { 67213626Sjairo.balart@metempsy.com case BIMODAL_ALT_MATCH: 67313626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: 67413626Sjairo.balart@metempsy.com if (bi->longestMatchPred == taken) { 67513626Sjairo.balart@metempsy.com tageLongestMatchProviderWouldHaveHit++; 67613626Sjairo.balart@metempsy.com } 67713626Sjairo.balart@metempsy.com } 67813626Sjairo.balart@metempsy.com } 67913626Sjairo.balart@metempsy.com 68013626Sjairo.balart@metempsy.com switch (bi->provider) { 68113626Sjairo.balart@metempsy.com case TAGE_LONGEST_MATCH: 68213626Sjairo.balart@metempsy.com case TAGE_ALT_MATCH: 68313626Sjairo.balart@metempsy.com tageLongestMatchProvider[bi->hitBank]++; 68413626Sjairo.balart@metempsy.com tageAltMatchProvider[bi->altBank]++; 68513626Sjairo.balart@metempsy.com break; 68613626Sjairo.balart@metempsy.com } 68713626Sjairo.balart@metempsy.com} 68813626Sjairo.balart@metempsy.com 68913626Sjairo.balart@metempsy.comunsigned 69013626Sjairo.balart@metempsy.comTAGEBase::getGHR(ThreadID tid, BranchInfo *bi) const 69113626Sjairo.balart@metempsy.com{ 69213626Sjairo.balart@metempsy.com unsigned val = 0; 69313626Sjairo.balart@metempsy.com for (unsigned i = 0; i < 32; i++) { 69413626Sjairo.balart@metempsy.com // Make sure we don't go out of bounds 69513626Sjairo.balart@metempsy.com int gh_offset = bi->ptGhist + i; 69613626Sjairo.balart@metempsy.com assert(&(threadHistory[tid].globalHistory[gh_offset]) < 69713626Sjairo.balart@metempsy.com threadHistory[tid].globalHistory + histBufferSize); 69813626Sjairo.balart@metempsy.com val |= ((threadHistory[tid].globalHistory[gh_offset] & 0x1) << i); 69913626Sjairo.balart@metempsy.com } 70013626Sjairo.balart@metempsy.com 70113626Sjairo.balart@metempsy.com return val; 70213626Sjairo.balart@metempsy.com} 70313626Sjairo.balart@metempsy.com 70413626Sjairo.balart@metempsy.comvoid 70513626Sjairo.balart@metempsy.comTAGEBase::regStats() 70613626Sjairo.balart@metempsy.com{ 70713626Sjairo.balart@metempsy.com tageLongestMatchProviderCorrect 70813626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProviderCorrect") 70913626Sjairo.balart@metempsy.com .desc("Number of times TAGE Longest Match is the provider and " 71013626Sjairo.balart@metempsy.com "the prediction is correct"); 71113626Sjairo.balart@metempsy.com 71213626Sjairo.balart@metempsy.com tageAltMatchProviderCorrect 71313626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProviderCorrect") 71413626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the provider and " 71513626Sjairo.balart@metempsy.com "the prediction is correct"); 71613626Sjairo.balart@metempsy.com 71713626Sjairo.balart@metempsy.com bimodalAltMatchProviderCorrect 71813626Sjairo.balart@metempsy.com .name(name() + ".bimodalAltMatchProviderCorrect") 71913626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the bimodal and it is the " 72013626Sjairo.balart@metempsy.com "provider and the prediction is correct"); 72113626Sjairo.balart@metempsy.com 72213626Sjairo.balart@metempsy.com tageBimodalProviderCorrect 72313626Sjairo.balart@metempsy.com .name(name() + ".tageBimodalProviderCorrect") 72413626Sjairo.balart@metempsy.com .desc("Number of times there are no hits on the TAGE tables " 72513626Sjairo.balart@metempsy.com "and the bimodal prediction is correct"); 72613626Sjairo.balart@metempsy.com 72713626Sjairo.balart@metempsy.com tageLongestMatchProviderWrong 72813626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProviderWrong") 72913626Sjairo.balart@metempsy.com .desc("Number of times TAGE Longest Match is the provider and " 73013626Sjairo.balart@metempsy.com "the prediction is wrong"); 73113626Sjairo.balart@metempsy.com 73213626Sjairo.balart@metempsy.com tageAltMatchProviderWrong 73313626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProviderWrong") 73413626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the provider and " 73513626Sjairo.balart@metempsy.com "the prediction is wrong"); 73613626Sjairo.balart@metempsy.com 73713626Sjairo.balart@metempsy.com bimodalAltMatchProviderWrong 73813626Sjairo.balart@metempsy.com .name(name() + ".bimodalAltMatchProviderWrong") 73913626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the bimodal and it is the " 74013626Sjairo.balart@metempsy.com "provider and the prediction is wrong"); 74113626Sjairo.balart@metempsy.com 74213626Sjairo.balart@metempsy.com tageBimodalProviderWrong 74313626Sjairo.balart@metempsy.com .name(name() + ".tageBimodalProviderWrong") 74413626Sjairo.balart@metempsy.com .desc("Number of times there are no hits on the TAGE tables " 74513626Sjairo.balart@metempsy.com "and the bimodal prediction is wrong"); 74613626Sjairo.balart@metempsy.com 74713626Sjairo.balart@metempsy.com tageAltMatchProviderWouldHaveHit 74813626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProviderWouldHaveHit") 74913626Sjairo.balart@metempsy.com .desc("Number of times TAGE Longest Match is the provider, " 75013626Sjairo.balart@metempsy.com "the prediction is wrong and Alt Match prediction was correct"); 75113626Sjairo.balart@metempsy.com 75213626Sjairo.balart@metempsy.com tageLongestMatchProviderWouldHaveHit 75313626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProviderWouldHaveHit") 75413626Sjairo.balart@metempsy.com .desc("Number of times TAGE Alt Match is the provider, the " 75513626Sjairo.balart@metempsy.com "prediction is wrong and Longest Match prediction was correct"); 75613626Sjairo.balart@metempsy.com 75713626Sjairo.balart@metempsy.com tageLongestMatchProvider 75813626Sjairo.balart@metempsy.com .init(nHistoryTables + 1) 75913626Sjairo.balart@metempsy.com .name(name() + ".tageLongestMatchProvider") 76013626Sjairo.balart@metempsy.com .desc("TAGE provider for longest match"); 76113626Sjairo.balart@metempsy.com 76213626Sjairo.balart@metempsy.com tageAltMatchProvider 76313626Sjairo.balart@metempsy.com .init(nHistoryTables + 1) 76413626Sjairo.balart@metempsy.com .name(name() + ".tageAltMatchProvider") 76513626Sjairo.balart@metempsy.com .desc("TAGE provider for alt match"); 76613626Sjairo.balart@metempsy.com} 76713626Sjairo.balart@metempsy.com 76813626Sjairo.balart@metempsy.comint8_t 76913626Sjairo.balart@metempsy.comTAGEBase::getCtr(int hitBank, int hitBankIndex) const 77013626Sjairo.balart@metempsy.com{ 77113626Sjairo.balart@metempsy.com return gtable[hitBank][hitBankIndex].ctr; 77213626Sjairo.balart@metempsy.com} 77313626Sjairo.balart@metempsy.com 77413626Sjairo.balart@metempsy.comunsigned 77513626Sjairo.balart@metempsy.comTAGEBase::getTageCtrBits() const 77613626Sjairo.balart@metempsy.com{ 77713626Sjairo.balart@metempsy.com return tagTableCounterBits; 77813626Sjairo.balart@metempsy.com} 77913626Sjairo.balart@metempsy.com 78013626Sjairo.balart@metempsy.comint 78113626Sjairo.balart@metempsy.comTAGEBase::getPathHist(ThreadID tid) const 78213626Sjairo.balart@metempsy.com{ 78313626Sjairo.balart@metempsy.com return threadHistory[tid].pathHist; 78413626Sjairo.balart@metempsy.com} 78513626Sjairo.balart@metempsy.com 78613626Sjairo.balart@metempsy.combool 78713626Sjairo.balart@metempsy.comTAGEBase::isSpeculativeUpdateEnabled() const 78813626Sjairo.balart@metempsy.com{ 78913626Sjairo.balart@metempsy.com return speculativeHistUpdate; 79013626Sjairo.balart@metempsy.com} 79113626Sjairo.balart@metempsy.com 79213626Sjairo.balart@metempsy.comTAGEBase* 79313626Sjairo.balart@metempsy.comTAGEBaseParams::create() 79413626Sjairo.balart@metempsy.com{ 79513626Sjairo.balart@metempsy.com return new TAGEBase(this); 79613626Sjairo.balart@metempsy.com} 797