tage.cc revision 13455
113454Spau.cabre@metempsy.com/* 213454Spau.cabre@metempsy.com * Copyright (c) 2014 The University of Wisconsin 313454Spau.cabre@metempsy.com * 413454Spau.cabre@metempsy.com * Copyright (c) 2006 INRIA (Institut National de Recherche en 513454Spau.cabre@metempsy.com * Informatique et en Automatique / French National Research Institute 613454Spau.cabre@metempsy.com * for Computer Science and Applied Mathematics) 713454Spau.cabre@metempsy.com * 813454Spau.cabre@metempsy.com * All rights reserved. 913454Spau.cabre@metempsy.com * 1013454Spau.cabre@metempsy.com * Redistribution and use in source and binary forms, with or without 1113454Spau.cabre@metempsy.com * modification, are permitted provided that the following conditions are 1213454Spau.cabre@metempsy.com * met: redistributions of source code must retain the above copyright 1313454Spau.cabre@metempsy.com * notice, this list of conditions and the following disclaimer; 1413454Spau.cabre@metempsy.com * redistributions in binary form must reproduce the above copyright 1513454Spau.cabre@metempsy.com * notice, this list of conditions and the following disclaimer in the 1613454Spau.cabre@metempsy.com * documentation and/or other materials provided with the distribution; 1713454Spau.cabre@metempsy.com * neither the name of the copyright holders nor the names of its 1813454Spau.cabre@metempsy.com * contributors may be used to endorse or promote products derived from 1913454Spau.cabre@metempsy.com * this software without specific prior written permission. 2013454Spau.cabre@metempsy.com * 2113454Spau.cabre@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2213454Spau.cabre@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2313454Spau.cabre@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2413454Spau.cabre@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2513454Spau.cabre@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2613454Spau.cabre@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2713454Spau.cabre@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2813454Spau.cabre@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2913454Spau.cabre@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3013454Spau.cabre@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3113454Spau.cabre@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3213454Spau.cabre@metempsy.com * 3313454Spau.cabre@metempsy.com * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais, 3413454Spau.cabre@metempsy.com * from André Seznec's code. 3513454Spau.cabre@metempsy.com */ 3613454Spau.cabre@metempsy.com 3713454Spau.cabre@metempsy.com/* @file 3813454Spau.cabre@metempsy.com * Implementation of a TAGE branch predictor 3913454Spau.cabre@metempsy.com */ 4013454Spau.cabre@metempsy.com 4113454Spau.cabre@metempsy.com#include "cpu/pred/tage.hh" 4213454Spau.cabre@metempsy.com 4313454Spau.cabre@metempsy.com#include "base/intmath.hh" 4413454Spau.cabre@metempsy.com#include "base/logging.hh" 4513454Spau.cabre@metempsy.com#include "base/random.hh" 4613454Spau.cabre@metempsy.com#include "base/trace.hh" 4713454Spau.cabre@metempsy.com#include "debug/Fetch.hh" 4813454Spau.cabre@metempsy.com#include "debug/Tage.hh" 4913454Spau.cabre@metempsy.com 5013454Spau.cabre@metempsy.comTAGE::TAGE(const TAGEParams *params) 5113454Spau.cabre@metempsy.com : BPredUnit(params), 5213454Spau.cabre@metempsy.com logRatioBiModalHystEntries(params->logRatioBiModalHystEntries), 5313454Spau.cabre@metempsy.com nHistoryTables(params->nHistoryTables), 5413454Spau.cabre@metempsy.com tagTableCounterBits(params->tagTableCounterBits), 5513454Spau.cabre@metempsy.com tagTableUBits(params->tagTableUBits), 5613454Spau.cabre@metempsy.com histBufferSize(params->histBufferSize), 5713454Spau.cabre@metempsy.com minHist(params->minHist), 5813454Spau.cabre@metempsy.com maxHist(params->maxHist), 5913454Spau.cabre@metempsy.com pathHistBits(params->pathHistBits), 6013454Spau.cabre@metempsy.com tagTableTagWidths(params->tagTableTagWidths), 6113454Spau.cabre@metempsy.com logTagTableSizes(params->logTagTableSizes), 6213454Spau.cabre@metempsy.com threadHistory(params->numThreads), 6313454Spau.cabre@metempsy.com logUResetPeriod(params->logUResetPeriod), 6413454Spau.cabre@metempsy.com useAltOnNaBits(params->useAltOnNaBits) 6513454Spau.cabre@metempsy.com{ 6613454Spau.cabre@metempsy.com // Current method for periodically resetting the u counter bits only 6713454Spau.cabre@metempsy.com // works for 1 or 2 bits 6813454Spau.cabre@metempsy.com // Also make sure that it is not 0 6913454Spau.cabre@metempsy.com assert(tagTableUBits <= 2 && (tagTableUBits > 0)); 7013454Spau.cabre@metempsy.com 7113454Spau.cabre@metempsy.com // we use int type for the path history, so it cannot be more than 7213454Spau.cabre@metempsy.com // its size 7313454Spau.cabre@metempsy.com assert(pathHistBits <= (sizeof(int)*8)); 7413454Spau.cabre@metempsy.com 7513454Spau.cabre@metempsy.com // initialize the counter to half of the period 7613454Spau.cabre@metempsy.com assert(logUResetPeriod != 0); 7713454Spau.cabre@metempsy.com tCounter = ULL(1) << (logUResetPeriod - 1); 7813454Spau.cabre@metempsy.com 7913454Spau.cabre@metempsy.com assert(params->histBufferSize > params->maxHist * 2); 8013454Spau.cabre@metempsy.com useAltPredForNewlyAllocated = 0; 8113454Spau.cabre@metempsy.com 8213454Spau.cabre@metempsy.com for (auto& history : threadHistory) { 8313454Spau.cabre@metempsy.com history.pathHist = 0; 8413454Spau.cabre@metempsy.com history.globalHistory = new uint8_t[histBufferSize]; 8513454Spau.cabre@metempsy.com history.gHist = history.globalHistory; 8613454Spau.cabre@metempsy.com memset(history.gHist, 0, histBufferSize); 8713454Spau.cabre@metempsy.com history.ptGhist = 0; 8813454Spau.cabre@metempsy.com } 8913454Spau.cabre@metempsy.com 9013454Spau.cabre@metempsy.com histLengths = new int [nHistoryTables+1]; 9113454Spau.cabre@metempsy.com histLengths[1] = minHist; 9213454Spau.cabre@metempsy.com histLengths[nHistoryTables] = maxHist; 9313454Spau.cabre@metempsy.com 9413454Spau.cabre@metempsy.com for (int i = 2; i <= nHistoryTables; i++) { 9513454Spau.cabre@metempsy.com histLengths[i] = (int) (((double) minHist * 9613454Spau.cabre@metempsy.com pow ((double) (maxHist) / (double) minHist, 9713454Spau.cabre@metempsy.com (double) (i - 1) / (double) ((nHistoryTables- 1)))) 9813454Spau.cabre@metempsy.com + 0.5); 9913454Spau.cabre@metempsy.com } 10013454Spau.cabre@metempsy.com 10113454Spau.cabre@metempsy.com assert(tagTableTagWidths.size() == (nHistoryTables+1)); 10213454Spau.cabre@metempsy.com assert(logTagTableSizes.size() == (nHistoryTables+1)); 10313454Spau.cabre@metempsy.com 10413454Spau.cabre@metempsy.com // First entry is for the Bimodal table and it is untagged in this 10513454Spau.cabre@metempsy.com // implementation 10613454Spau.cabre@metempsy.com assert(tagTableTagWidths[0] == 0); 10713454Spau.cabre@metempsy.com 10813454Spau.cabre@metempsy.com for (auto& history : threadHistory) { 10913454Spau.cabre@metempsy.com history.computeIndices = new FoldedHistory[nHistoryTables+1]; 11013454Spau.cabre@metempsy.com history.computeTags[0] = new FoldedHistory[nHistoryTables+1]; 11113454Spau.cabre@metempsy.com history.computeTags[1] = new FoldedHistory[nHistoryTables+1]; 11213454Spau.cabre@metempsy.com 11313454Spau.cabre@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 11413454Spau.cabre@metempsy.com history.computeIndices[i].init( 11513454Spau.cabre@metempsy.com histLengths[i], (logTagTableSizes[i])); 11613454Spau.cabre@metempsy.com history.computeTags[0][i].init( 11713454Spau.cabre@metempsy.com history.computeIndices[i].origLength, tagTableTagWidths[i]); 11813454Spau.cabre@metempsy.com history.computeTags[1][i].init( 11913454Spau.cabre@metempsy.com history.computeIndices[i].origLength, tagTableTagWidths[i]-1); 12013454Spau.cabre@metempsy.com DPRINTF(Tage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n", 12113454Spau.cabre@metempsy.com histLengths[i], logTagTableSizes[i], tagTableTagWidths[i]); 12213454Spau.cabre@metempsy.com } 12313454Spau.cabre@metempsy.com } 12413454Spau.cabre@metempsy.com 12513454Spau.cabre@metempsy.com const uint64_t bimodalTableSize = ULL(1) << logTagTableSizes[0]; 12613454Spau.cabre@metempsy.com btablePrediction.resize(bimodalTableSize, false); 12713454Spau.cabre@metempsy.com btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries, 12813454Spau.cabre@metempsy.com true); 12913454Spau.cabre@metempsy.com 13013454Spau.cabre@metempsy.com gtable = new TageEntry*[nHistoryTables + 1]; 13113454Spau.cabre@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 13213454Spau.cabre@metempsy.com gtable[i] = new TageEntry[1<<(logTagTableSizes[i])]; 13313454Spau.cabre@metempsy.com } 13413454Spau.cabre@metempsy.com 13513454Spau.cabre@metempsy.com tableIndices = new int [nHistoryTables+1]; 13613454Spau.cabre@metempsy.com tableTags = new int [nHistoryTables+1]; 13713454Spau.cabre@metempsy.com} 13813454Spau.cabre@metempsy.com 13913454Spau.cabre@metempsy.comint 14013454Spau.cabre@metempsy.comTAGE::bindex(Addr pc_in) const 14113454Spau.cabre@metempsy.com{ 14213454Spau.cabre@metempsy.com return ((pc_in >> instShiftAmt) & ((ULL(1) << (logTagTableSizes[0])) - 1)); 14313454Spau.cabre@metempsy.com} 14413454Spau.cabre@metempsy.com 14513454Spau.cabre@metempsy.comint 14613454Spau.cabre@metempsy.comTAGE::F(int A, int size, int bank) const 14713454Spau.cabre@metempsy.com{ 14813454Spau.cabre@metempsy.com int A1, A2; 14913454Spau.cabre@metempsy.com 15013454Spau.cabre@metempsy.com A = A & ((ULL(1) << size) - 1); 15113454Spau.cabre@metempsy.com A1 = (A & ((ULL(1) << logTagTableSizes[bank]) - 1)); 15213454Spau.cabre@metempsy.com A2 = (A >> logTagTableSizes[bank]); 15313454Spau.cabre@metempsy.com A2 = ((A2 << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 15413454Spau.cabre@metempsy.com + (A2 >> (logTagTableSizes[bank] - bank)); 15513454Spau.cabre@metempsy.com A = A1 ^ A2; 15613454Spau.cabre@metempsy.com A = ((A << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1)) 15713454Spau.cabre@metempsy.com + (A >> (logTagTableSizes[bank] - bank)); 15813454Spau.cabre@metempsy.com return (A); 15913454Spau.cabre@metempsy.com} 16013454Spau.cabre@metempsy.com 16113454Spau.cabre@metempsy.com 16213454Spau.cabre@metempsy.com// gindex computes a full hash of pc, ghist and pathHist 16313454Spau.cabre@metempsy.comint 16413454Spau.cabre@metempsy.comTAGE::gindex(ThreadID tid, Addr pc, int bank) const 16513454Spau.cabre@metempsy.com{ 16613454Spau.cabre@metempsy.com int index; 16713454Spau.cabre@metempsy.com int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits : 16813454Spau.cabre@metempsy.com histLengths[bank]; 16913454Spau.cabre@metempsy.com const Addr shiftedPc = pc >> instShiftAmt; 17013454Spau.cabre@metempsy.com index = 17113454Spau.cabre@metempsy.com shiftedPc ^ 17213454Spau.cabre@metempsy.com (shiftedPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^ 17313454Spau.cabre@metempsy.com threadHistory[tid].computeIndices[bank].comp ^ 17413454Spau.cabre@metempsy.com F(threadHistory[tid].pathHist, hlen, bank); 17513454Spau.cabre@metempsy.com 17613454Spau.cabre@metempsy.com return (index & ((ULL(1) << (logTagTableSizes[bank])) - 1)); 17713454Spau.cabre@metempsy.com} 17813454Spau.cabre@metempsy.com 17913454Spau.cabre@metempsy.com 18013454Spau.cabre@metempsy.com// Tag computation 18113454Spau.cabre@metempsy.comuint16_t 18213454Spau.cabre@metempsy.comTAGE::gtag(ThreadID tid, Addr pc, int bank) const 18313454Spau.cabre@metempsy.com{ 18413454Spau.cabre@metempsy.com int tag = (pc >> instShiftAmt) ^ 18513454Spau.cabre@metempsy.com threadHistory[tid].computeTags[0][bank].comp ^ 18613454Spau.cabre@metempsy.com (threadHistory[tid].computeTags[1][bank].comp << 1); 18713454Spau.cabre@metempsy.com 18813454Spau.cabre@metempsy.com return (tag & ((ULL(1) << tagTableTagWidths[bank]) - 1)); 18913454Spau.cabre@metempsy.com} 19013454Spau.cabre@metempsy.com 19113454Spau.cabre@metempsy.com 19213454Spau.cabre@metempsy.com// Up-down saturating counter 19313454Spau.cabre@metempsy.comvoid 19413454Spau.cabre@metempsy.comTAGE::ctrUpdate(int8_t & ctr, bool taken, int nbits) 19513454Spau.cabre@metempsy.com{ 19613454Spau.cabre@metempsy.com assert(nbits <= sizeof(int8_t) << 3); 19713454Spau.cabre@metempsy.com if (taken) { 19813454Spau.cabre@metempsy.com if (ctr < ((1 << (nbits - 1)) - 1)) 19913454Spau.cabre@metempsy.com ctr++; 20013454Spau.cabre@metempsy.com } else { 20113454Spau.cabre@metempsy.com if (ctr > -(1 << (nbits - 1))) 20213454Spau.cabre@metempsy.com ctr--; 20313454Spau.cabre@metempsy.com } 20413454Spau.cabre@metempsy.com} 20513454Spau.cabre@metempsy.com 20613454Spau.cabre@metempsy.com// Up-down unsigned saturating counter 20713454Spau.cabre@metempsy.comvoid 20813454Spau.cabre@metempsy.comTAGE::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits) 20913454Spau.cabre@metempsy.com{ 21013454Spau.cabre@metempsy.com assert(nbits <= sizeof(uint8_t) << 3); 21113454Spau.cabre@metempsy.com if (up) { 21213454Spau.cabre@metempsy.com if (ctr < ((1 << nbits) - 1)) 21313454Spau.cabre@metempsy.com ctr++; 21413454Spau.cabre@metempsy.com } else { 21513454Spau.cabre@metempsy.com if (ctr) 21613454Spau.cabre@metempsy.com ctr--; 21713454Spau.cabre@metempsy.com } 21813454Spau.cabre@metempsy.com} 21913454Spau.cabre@metempsy.com 22013454Spau.cabre@metempsy.com// Bimodal prediction 22113454Spau.cabre@metempsy.combool 22213454Spau.cabre@metempsy.comTAGE::getBimodePred(Addr pc, TageBranchInfo* bi) const 22313454Spau.cabre@metempsy.com{ 22413454Spau.cabre@metempsy.com return btablePrediction[bi->bimodalIndex]; 22513454Spau.cabre@metempsy.com} 22613454Spau.cabre@metempsy.com 22713454Spau.cabre@metempsy.com 22813454Spau.cabre@metempsy.com// Update the bimodal predictor: a hysteresis bit is shared among N prediction 22913454Spau.cabre@metempsy.com// bits (N = 2 ^ logRatioBiModalHystEntries) 23013454Spau.cabre@metempsy.comvoid 23113454Spau.cabre@metempsy.comTAGE::baseUpdate(Addr pc, bool taken, TageBranchInfo* bi) 23213454Spau.cabre@metempsy.com{ 23313454Spau.cabre@metempsy.com int inter = (btablePrediction[bi->bimodalIndex] << 1) 23413454Spau.cabre@metempsy.com + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries]; 23513454Spau.cabre@metempsy.com if (taken) { 23613454Spau.cabre@metempsy.com if (inter < 3) 23713454Spau.cabre@metempsy.com inter++; 23813454Spau.cabre@metempsy.com } else if (inter > 0) { 23913454Spau.cabre@metempsy.com inter--; 24013454Spau.cabre@metempsy.com } 24113454Spau.cabre@metempsy.com const bool pred = inter >> 1; 24213454Spau.cabre@metempsy.com const bool hyst = inter & 1; 24313454Spau.cabre@metempsy.com btablePrediction[bi->bimodalIndex] = pred; 24413454Spau.cabre@metempsy.com btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst; 24513454Spau.cabre@metempsy.com DPRINTF(Tage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst); 24613454Spau.cabre@metempsy.com} 24713454Spau.cabre@metempsy.com 24813454Spau.cabre@metempsy.com// shifting the global history: we manage the history in a big table in order 24913454Spau.cabre@metempsy.com// to reduce simulation time 25013454Spau.cabre@metempsy.comvoid 25113454Spau.cabre@metempsy.comTAGE::updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &pt) 25213454Spau.cabre@metempsy.com{ 25313454Spau.cabre@metempsy.com if (pt == 0) { 25413454Spau.cabre@metempsy.com DPRINTF(Tage, "Rolling over the histories\n"); 25513454Spau.cabre@metempsy.com // Copy beginning of globalHistoryBuffer to end, such that 25613454Spau.cabre@metempsy.com // the last maxHist outcomes are still reachable 25713454Spau.cabre@metempsy.com // through pt[0 .. maxHist - 1]. 25813454Spau.cabre@metempsy.com for (int i = 0; i < maxHist; i++) 25913454Spau.cabre@metempsy.com tab[histBufferSize - maxHist + i] = tab[i]; 26013454Spau.cabre@metempsy.com pt = histBufferSize - maxHist; 26113454Spau.cabre@metempsy.com h = &tab[pt]; 26213454Spau.cabre@metempsy.com } 26313454Spau.cabre@metempsy.com pt--; 26413454Spau.cabre@metempsy.com h--; 26513454Spau.cabre@metempsy.com h[0] = (dir) ? 1 : 0; 26613454Spau.cabre@metempsy.com} 26713454Spau.cabre@metempsy.com 26813454Spau.cabre@metempsy.com// Get GHR for hashing indirect predictor 26913454Spau.cabre@metempsy.com// Build history backwards from pointer in 27013454Spau.cabre@metempsy.com// bp_history. 27113454Spau.cabre@metempsy.comunsigned 27213454Spau.cabre@metempsy.comTAGE::getGHR(ThreadID tid, void *bp_history) const 27313454Spau.cabre@metempsy.com{ 27413454Spau.cabre@metempsy.com TageBranchInfo* bi = static_cast<TageBranchInfo*>(bp_history); 27513454Spau.cabre@metempsy.com unsigned val = 0; 27613454Spau.cabre@metempsy.com for (unsigned i = 0; i < 32; i++) { 27713454Spau.cabre@metempsy.com // Make sure we don't go out of bounds 27813454Spau.cabre@metempsy.com int gh_offset = bi->ptGhist + i; 27913454Spau.cabre@metempsy.com assert(&(threadHistory[tid].globalHistory[gh_offset]) < 28013454Spau.cabre@metempsy.com threadHistory[tid].globalHistory + histBufferSize); 28113454Spau.cabre@metempsy.com val |= ((threadHistory[tid].globalHistory[gh_offset] & 0x1) << i); 28213454Spau.cabre@metempsy.com } 28313454Spau.cabre@metempsy.com 28413454Spau.cabre@metempsy.com return val; 28513454Spau.cabre@metempsy.com} 28613454Spau.cabre@metempsy.com 28713454Spau.cabre@metempsy.com//prediction 28813454Spau.cabre@metempsy.combool 28913454Spau.cabre@metempsy.comTAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) 29013454Spau.cabre@metempsy.com{ 29113454Spau.cabre@metempsy.com TageBranchInfo *bi = new TageBranchInfo(nHistoryTables+1); 29213454Spau.cabre@metempsy.com b = (void*)(bi); 29313454Spau.cabre@metempsy.com return tagePredict(tid, branch_pc, cond_branch, bi); 29413454Spau.cabre@metempsy.com} 29513454Spau.cabre@metempsy.com 29613454Spau.cabre@metempsy.combool 29713454Spau.cabre@metempsy.comTAGE::tagePredict(ThreadID tid, Addr branch_pc, 29813454Spau.cabre@metempsy.com bool cond_branch, TageBranchInfo* bi) 29913454Spau.cabre@metempsy.com{ 30013454Spau.cabre@metempsy.com Addr pc = branch_pc; 30113454Spau.cabre@metempsy.com bool pred_taken = true; 30213454Spau.cabre@metempsy.com 30313454Spau.cabre@metempsy.com if (cond_branch) { 30413454Spau.cabre@metempsy.com // TAGE prediction 30513454Spau.cabre@metempsy.com 30613454Spau.cabre@metempsy.com // computes the table addresses and the partial tags 30713454Spau.cabre@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 30813454Spau.cabre@metempsy.com tableIndices[i] = gindex(tid, pc, i); 30913454Spau.cabre@metempsy.com bi->tableIndices[i] = tableIndices[i]; 31013454Spau.cabre@metempsy.com tableTags[i] = gtag(tid, pc, i); 31113454Spau.cabre@metempsy.com bi->tableTags[i] = tableTags[i]; 31213454Spau.cabre@metempsy.com } 31313454Spau.cabre@metempsy.com 31413454Spau.cabre@metempsy.com bi->bimodalIndex = bindex(pc); 31513454Spau.cabre@metempsy.com 31613454Spau.cabre@metempsy.com bi->hitBank = 0; 31713454Spau.cabre@metempsy.com bi->altBank = 0; 31813454Spau.cabre@metempsy.com //Look for the bank with longest matching history 31913454Spau.cabre@metempsy.com for (int i = nHistoryTables; i > 0; i--) { 32013454Spau.cabre@metempsy.com if (gtable[i][tableIndices[i]].tag == tableTags[i]) { 32113454Spau.cabre@metempsy.com bi->hitBank = i; 32213454Spau.cabre@metempsy.com bi->hitBankIndex = tableIndices[bi->hitBank]; 32313454Spau.cabre@metempsy.com break; 32413454Spau.cabre@metempsy.com } 32513454Spau.cabre@metempsy.com } 32613454Spau.cabre@metempsy.com //Look for the alternate bank 32713454Spau.cabre@metempsy.com for (int i = bi->hitBank - 1; i > 0; i--) { 32813454Spau.cabre@metempsy.com if (gtable[i][tableIndices[i]].tag == tableTags[i]) { 32913454Spau.cabre@metempsy.com bi->altBank = i; 33013454Spau.cabre@metempsy.com bi->altBankIndex = tableIndices[bi->altBank]; 33113454Spau.cabre@metempsy.com break; 33213454Spau.cabre@metempsy.com } 33313454Spau.cabre@metempsy.com } 33413454Spau.cabre@metempsy.com //computes the prediction and the alternate prediction 33513454Spau.cabre@metempsy.com if (bi->hitBank > 0) { 33613454Spau.cabre@metempsy.com if (bi->altBank > 0) { 33713454Spau.cabre@metempsy.com bi->altTaken = 33813454Spau.cabre@metempsy.com gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0; 33913454Spau.cabre@metempsy.com }else { 34013454Spau.cabre@metempsy.com bi->altTaken = getBimodePred(pc, bi); 34113454Spau.cabre@metempsy.com } 34213454Spau.cabre@metempsy.com 34313454Spau.cabre@metempsy.com bi->longestMatchPred = 34413454Spau.cabre@metempsy.com gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0; 34513454Spau.cabre@metempsy.com bi->pseudoNewAlloc = 34613454Spau.cabre@metempsy.com abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1; 34713454Spau.cabre@metempsy.com 34813454Spau.cabre@metempsy.com //if the entry is recognized as a newly allocated entry and 34913454Spau.cabre@metempsy.com //useAltPredForNewlyAllocated is positive use the alternate 35013454Spau.cabre@metempsy.com //prediction 35113455Spau.cabre@metempsy.com if ((useAltPredForNewlyAllocated < 0) || ! bi->pseudoNewAlloc) { 35213454Spau.cabre@metempsy.com bi->tagePred = bi->longestMatchPred; 35313455Spau.cabre@metempsy.com bi->provider = TAGE_LONGEST_MATCH; 35413455Spau.cabre@metempsy.com } else { 35513454Spau.cabre@metempsy.com bi->tagePred = bi->altTaken; 35613455Spau.cabre@metempsy.com bi->provider = bi->altBank ? TAGE_ALT_MATCH 35713455Spau.cabre@metempsy.com : BIMODAL_ALT_MATCH; 35813455Spau.cabre@metempsy.com } 35913454Spau.cabre@metempsy.com } else { 36013454Spau.cabre@metempsy.com bi->altTaken = getBimodePred(pc, bi); 36113454Spau.cabre@metempsy.com bi->tagePred = bi->altTaken; 36213454Spau.cabre@metempsy.com bi->longestMatchPred = bi->altTaken; 36313455Spau.cabre@metempsy.com bi->provider = BIMODAL_ONLY; 36413454Spau.cabre@metempsy.com } 36513454Spau.cabre@metempsy.com //end TAGE prediction 36613454Spau.cabre@metempsy.com 36713454Spau.cabre@metempsy.com pred_taken = (bi->tagePred); 36813454Spau.cabre@metempsy.com DPRINTF(Tage, "Predict for %lx: taken?:%d, tagePred:%d, altPred:%d\n", 36913454Spau.cabre@metempsy.com branch_pc, pred_taken, bi->tagePred, bi->altTaken); 37013454Spau.cabre@metempsy.com } 37113454Spau.cabre@metempsy.com bi->branchPC = branch_pc; 37213454Spau.cabre@metempsy.com bi->condBranch = cond_branch; 37313454Spau.cabre@metempsy.com return pred_taken; 37413454Spau.cabre@metempsy.com} 37513454Spau.cabre@metempsy.com 37613454Spau.cabre@metempsy.com// PREDICTOR UPDATE 37713454Spau.cabre@metempsy.comvoid 37813454Spau.cabre@metempsy.comTAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history, 37913454Spau.cabre@metempsy.com bool squashed) 38013454Spau.cabre@metempsy.com{ 38113454Spau.cabre@metempsy.com assert(bp_history); 38213454Spau.cabre@metempsy.com 38313454Spau.cabre@metempsy.com TageBranchInfo *bi = static_cast<TageBranchInfo*>(bp_history); 38413454Spau.cabre@metempsy.com 38513454Spau.cabre@metempsy.com if (squashed) { 38613454Spau.cabre@metempsy.com // This restores the global history, then update it 38713454Spau.cabre@metempsy.com // and recomputes the folded histories. 38813454Spau.cabre@metempsy.com squash(tid, taken, bp_history); 38913454Spau.cabre@metempsy.com return; 39013454Spau.cabre@metempsy.com } 39113454Spau.cabre@metempsy.com 39213454Spau.cabre@metempsy.com int nrand = random_mt.random<int>(0,3); 39313454Spau.cabre@metempsy.com if (bi->condBranch) { 39413454Spau.cabre@metempsy.com DPRINTF(Tage, "Updating tables for branch:%lx; taken?:%d\n", 39513454Spau.cabre@metempsy.com branch_pc, taken); 39613455Spau.cabre@metempsy.com updateStats(taken, bi); 39713454Spau.cabre@metempsy.com condBranchUpdate(branch_pc, taken, bi, nrand); 39813454Spau.cabre@metempsy.com } 39913454Spau.cabre@metempsy.com if (!squashed) { 40013454Spau.cabre@metempsy.com delete bi; 40113454Spau.cabre@metempsy.com } 40213454Spau.cabre@metempsy.com} 40313454Spau.cabre@metempsy.com 40413454Spau.cabre@metempsy.comvoid 40513454Spau.cabre@metempsy.comTAGE::condBranchUpdate(Addr branch_pc, bool taken, 40613454Spau.cabre@metempsy.com TageBranchInfo* bi, int nrand) 40713454Spau.cabre@metempsy.com{ 40813454Spau.cabre@metempsy.com // TAGE UPDATE 40913454Spau.cabre@metempsy.com // try to allocate a new entries only if prediction was wrong 41013454Spau.cabre@metempsy.com bool longest_match_pred = false; 41113454Spau.cabre@metempsy.com bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables); 41213454Spau.cabre@metempsy.com if (bi->hitBank > 0) { 41313454Spau.cabre@metempsy.com // Manage the selection between longest matching and alternate 41413454Spau.cabre@metempsy.com // matching for "pseudo"-newly allocated longest matching entry 41513454Spau.cabre@metempsy.com longest_match_pred = bi->longestMatchPred; 41613454Spau.cabre@metempsy.com bool PseudoNewAlloc = bi->pseudoNewAlloc; 41713454Spau.cabre@metempsy.com // an entry is considered as newly allocated if its prediction 41813454Spau.cabre@metempsy.com // counter is weak 41913454Spau.cabre@metempsy.com if (PseudoNewAlloc) { 42013454Spau.cabre@metempsy.com if (longest_match_pred == taken) { 42113454Spau.cabre@metempsy.com alloc = false; 42213454Spau.cabre@metempsy.com } 42313454Spau.cabre@metempsy.com // if it was delivering the correct prediction, no need to 42413454Spau.cabre@metempsy.com // allocate new entry even if the overall prediction was false 42513454Spau.cabre@metempsy.com if (longest_match_pred != bi->altTaken) { 42613454Spau.cabre@metempsy.com ctrUpdate(useAltPredForNewlyAllocated, 42713454Spau.cabre@metempsy.com bi->altTaken == taken, useAltOnNaBits); 42813454Spau.cabre@metempsy.com } 42913454Spau.cabre@metempsy.com } 43013454Spau.cabre@metempsy.com } 43113454Spau.cabre@metempsy.com 43213454Spau.cabre@metempsy.com if (alloc) { 43313454Spau.cabre@metempsy.com // is there some "unuseful" entry to allocate 43413454Spau.cabre@metempsy.com uint8_t min = 1; 43513454Spau.cabre@metempsy.com for (int i = nHistoryTables; i > bi->hitBank; i--) { 43613454Spau.cabre@metempsy.com if (gtable[i][bi->tableIndices[i]].u < min) { 43713454Spau.cabre@metempsy.com min = gtable[i][bi->tableIndices[i]].u; 43813454Spau.cabre@metempsy.com } 43913454Spau.cabre@metempsy.com } 44013454Spau.cabre@metempsy.com 44113454Spau.cabre@metempsy.com // we allocate an entry with a longer history 44213454Spau.cabre@metempsy.com // to avoid ping-pong, we do not choose systematically the next 44313454Spau.cabre@metempsy.com // entry, but among the 3 next entries 44413454Spau.cabre@metempsy.com int Y = nrand & 44513454Spau.cabre@metempsy.com ((ULL(1) << (nHistoryTables - bi->hitBank - 1)) - 1); 44613454Spau.cabre@metempsy.com int X = bi->hitBank + 1; 44713454Spau.cabre@metempsy.com if (Y & 1) { 44813454Spau.cabre@metempsy.com X++; 44913454Spau.cabre@metempsy.com if (Y & 2) 45013454Spau.cabre@metempsy.com X++; 45113454Spau.cabre@metempsy.com } 45213454Spau.cabre@metempsy.com // No entry available, forces one to be available 45313454Spau.cabre@metempsy.com if (min > 0) { 45413454Spau.cabre@metempsy.com gtable[X][bi->tableIndices[X]].u = 0; 45513454Spau.cabre@metempsy.com } 45613454Spau.cabre@metempsy.com 45713454Spau.cabre@metempsy.com 45813454Spau.cabre@metempsy.com //Allocate only one entry 45913454Spau.cabre@metempsy.com for (int i = X; i <= nHistoryTables; i++) { 46013454Spau.cabre@metempsy.com if ((gtable[i][bi->tableIndices[i]].u == 0)) { 46113454Spau.cabre@metempsy.com gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; 46213454Spau.cabre@metempsy.com gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1; 46313454Spau.cabre@metempsy.com break; 46413454Spau.cabre@metempsy.com } 46513454Spau.cabre@metempsy.com } 46613454Spau.cabre@metempsy.com } 46713454Spau.cabre@metempsy.com //periodic reset of u: reset is not complete but bit by bit 46813454Spau.cabre@metempsy.com tCounter++; 46913454Spau.cabre@metempsy.com if ((tCounter & ((ULL(1) << logUResetPeriod) - 1)) == 0) { 47013454Spau.cabre@metempsy.com // reset least significant bit 47113454Spau.cabre@metempsy.com // most significant bit becomes least significant bit 47213454Spau.cabre@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 47313454Spau.cabre@metempsy.com for (int j = 0; j < (ULL(1) << logTagTableSizes[i]); j++) { 47413454Spau.cabre@metempsy.com gtable[i][j].u = gtable[i][j].u >> 1; 47513454Spau.cabre@metempsy.com } 47613454Spau.cabre@metempsy.com } 47713454Spau.cabre@metempsy.com } 47813454Spau.cabre@metempsy.com 47913454Spau.cabre@metempsy.com if (bi->hitBank > 0) { 48013454Spau.cabre@metempsy.com DPRINTF(Tage, "Updating tag table entry (%d,%d) for branch %lx\n", 48113454Spau.cabre@metempsy.com bi->hitBank, bi->hitBankIndex, branch_pc); 48213454Spau.cabre@metempsy.com ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken, 48313454Spau.cabre@metempsy.com tagTableCounterBits); 48413454Spau.cabre@metempsy.com // if the provider entry is not certified to be useful also update 48513454Spau.cabre@metempsy.com // the alternate prediction 48613454Spau.cabre@metempsy.com if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) { 48713454Spau.cabre@metempsy.com if (bi->altBank > 0) { 48813454Spau.cabre@metempsy.com ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken, 48913454Spau.cabre@metempsy.com tagTableCounterBits); 49013454Spau.cabre@metempsy.com DPRINTF(Tage, "Updating tag table entry (%d,%d) for" 49113454Spau.cabre@metempsy.com " branch %lx\n", bi->hitBank, bi->hitBankIndex, 49213454Spau.cabre@metempsy.com branch_pc); 49313454Spau.cabre@metempsy.com } 49413454Spau.cabre@metempsy.com if (bi->altBank == 0) { 49513454Spau.cabre@metempsy.com baseUpdate(branch_pc, taken, bi); 49613454Spau.cabre@metempsy.com } 49713454Spau.cabre@metempsy.com } 49813454Spau.cabre@metempsy.com 49913454Spau.cabre@metempsy.com // update the u counter 50013454Spau.cabre@metempsy.com if (bi->tagePred != bi->altTaken) { 50113454Spau.cabre@metempsy.com unsignedCtrUpdate(gtable[bi->hitBank][bi->hitBankIndex].u, 50213454Spau.cabre@metempsy.com bi->tagePred == taken, tagTableUBits); 50313454Spau.cabre@metempsy.com } 50413454Spau.cabre@metempsy.com } else { 50513454Spau.cabre@metempsy.com baseUpdate(branch_pc, taken, bi); 50613454Spau.cabre@metempsy.com } 50713454Spau.cabre@metempsy.com} 50813454Spau.cabre@metempsy.com 50913454Spau.cabre@metempsy.comvoid 51013454Spau.cabre@metempsy.comTAGE::updateHistories(ThreadID tid, Addr branch_pc, bool taken, void* b) 51113454Spau.cabre@metempsy.com{ 51213454Spau.cabre@metempsy.com TageBranchInfo* bi = (TageBranchInfo*)(b); 51313454Spau.cabre@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 51413454Spau.cabre@metempsy.com // UPDATE HISTORIES 51513454Spau.cabre@metempsy.com bool pathbit = ((branch_pc >> instShiftAmt) & 1); 51613454Spau.cabre@metempsy.com //on a squash, return pointers to this and recompute indices. 51713454Spau.cabre@metempsy.com //update user history 51813454Spau.cabre@metempsy.com updateGHist(tHist.gHist, taken, tHist.globalHistory, tHist.ptGhist); 51913454Spau.cabre@metempsy.com tHist.pathHist = (tHist.pathHist << 1) + pathbit; 52013454Spau.cabre@metempsy.com tHist.pathHist = (tHist.pathHist & ((ULL(1) << pathHistBits) - 1)); 52113454Spau.cabre@metempsy.com 52213454Spau.cabre@metempsy.com bi->ptGhist = tHist.ptGhist; 52313454Spau.cabre@metempsy.com bi->pathHist = tHist.pathHist; 52413454Spau.cabre@metempsy.com //prepare next index and tag computations for user branchs 52513454Spau.cabre@metempsy.com for (int i = 1; i <= nHistoryTables; i++) 52613454Spau.cabre@metempsy.com { 52713454Spau.cabre@metempsy.com bi->ci[i] = tHist.computeIndices[i].comp; 52813454Spau.cabre@metempsy.com bi->ct0[i] = tHist.computeTags[0][i].comp; 52913454Spau.cabre@metempsy.com bi->ct1[i] = tHist.computeTags[1][i].comp; 53013454Spau.cabre@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 53113454Spau.cabre@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 53213454Spau.cabre@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 53313454Spau.cabre@metempsy.com } 53413454Spau.cabre@metempsy.com DPRINTF(Tage, "Updating global histories with branch:%lx; taken?:%d, " 53513454Spau.cabre@metempsy.com "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist, 53613454Spau.cabre@metempsy.com tHist.ptGhist); 53713454Spau.cabre@metempsy.com} 53813454Spau.cabre@metempsy.com 53913454Spau.cabre@metempsy.comvoid 54013454Spau.cabre@metempsy.comTAGE::squash(ThreadID tid, bool taken, void *bp_history) 54113454Spau.cabre@metempsy.com{ 54213454Spau.cabre@metempsy.com TageBranchInfo* bi = (TageBranchInfo*)(bp_history); 54313454Spau.cabre@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 54413454Spau.cabre@metempsy.com DPRINTF(Tage, "Restoring branch info: %lx; taken? %d; PathHistory:%x, " 54513454Spau.cabre@metempsy.com "pointer:%d\n", bi->branchPC,taken, bi->pathHist, bi->ptGhist); 54613454Spau.cabre@metempsy.com tHist.pathHist = bi->pathHist; 54713454Spau.cabre@metempsy.com tHist.ptGhist = bi->ptGhist; 54813454Spau.cabre@metempsy.com tHist.gHist = &(tHist.globalHistory[tHist.ptGhist]); 54913454Spau.cabre@metempsy.com tHist.gHist[0] = (taken ? 1 : 0); 55013454Spau.cabre@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 55113454Spau.cabre@metempsy.com tHist.computeIndices[i].comp = bi->ci[i]; 55213454Spau.cabre@metempsy.com tHist.computeTags[0][i].comp = bi->ct0[i]; 55313454Spau.cabre@metempsy.com tHist.computeTags[1][i].comp = bi->ct1[i]; 55413454Spau.cabre@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 55513454Spau.cabre@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 55613454Spau.cabre@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 55713454Spau.cabre@metempsy.com } 55813454Spau.cabre@metempsy.com} 55913454Spau.cabre@metempsy.com 56013454Spau.cabre@metempsy.comvoid 56113454Spau.cabre@metempsy.comTAGE::squash(ThreadID tid, void *bp_history) 56213454Spau.cabre@metempsy.com{ 56313454Spau.cabre@metempsy.com TageBranchInfo* bi = (TageBranchInfo*)(bp_history); 56413454Spau.cabre@metempsy.com DPRINTF(Tage, "Deleting branch info: %lx\n", bi->branchPC); 56513454Spau.cabre@metempsy.com delete bi; 56613454Spau.cabre@metempsy.com} 56713454Spau.cabre@metempsy.com 56813454Spau.cabre@metempsy.combool 56913454Spau.cabre@metempsy.comTAGE::lookup(ThreadID tid, Addr branch_pc, void* &bp_history) 57013454Spau.cabre@metempsy.com{ 57113454Spau.cabre@metempsy.com bool retval = predict(tid, branch_pc, true, bp_history); 57213454Spau.cabre@metempsy.com 57313454Spau.cabre@metempsy.com DPRINTF(Tage, "Lookup branch: %lx; predict:%d\n", branch_pc, retval); 57413454Spau.cabre@metempsy.com updateHistories(tid, branch_pc, retval, bp_history); 57513454Spau.cabre@metempsy.com assert(threadHistory[tid].gHist == 57613454Spau.cabre@metempsy.com &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]); 57713454Spau.cabre@metempsy.com 57813454Spau.cabre@metempsy.com return retval; 57913454Spau.cabre@metempsy.com} 58013454Spau.cabre@metempsy.com 58113454Spau.cabre@metempsy.comvoid 58213454Spau.cabre@metempsy.comTAGE::btbUpdate(ThreadID tid, Addr branch_pc, void* &bp_history) 58313454Spau.cabre@metempsy.com{ 58413454Spau.cabre@metempsy.com TageBranchInfo* bi = (TageBranchInfo*) bp_history; 58513454Spau.cabre@metempsy.com ThreadHistory& tHist = threadHistory[tid]; 58613454Spau.cabre@metempsy.com DPRINTF(Tage, "BTB miss resets prediction: %lx\n", branch_pc); 58713454Spau.cabre@metempsy.com assert(tHist.gHist == &tHist.globalHistory[tHist.ptGhist]); 58813454Spau.cabre@metempsy.com tHist.gHist[0] = 0; 58913454Spau.cabre@metempsy.com for (int i = 1; i <= nHistoryTables; i++) { 59013454Spau.cabre@metempsy.com tHist.computeIndices[i].comp = bi->ci[i]; 59113454Spau.cabre@metempsy.com tHist.computeTags[0][i].comp = bi->ct0[i]; 59213454Spau.cabre@metempsy.com tHist.computeTags[1][i].comp = bi->ct1[i]; 59313454Spau.cabre@metempsy.com tHist.computeIndices[i].update(tHist.gHist); 59413454Spau.cabre@metempsy.com tHist.computeTags[0][i].update(tHist.gHist); 59513454Spau.cabre@metempsy.com tHist.computeTags[1][i].update(tHist.gHist); 59613454Spau.cabre@metempsy.com } 59713454Spau.cabre@metempsy.com} 59813454Spau.cabre@metempsy.com 59913454Spau.cabre@metempsy.comvoid 60013454Spau.cabre@metempsy.comTAGE::uncondBranch(ThreadID tid, Addr br_pc, void* &bp_history) 60113454Spau.cabre@metempsy.com{ 60213454Spau.cabre@metempsy.com DPRINTF(Tage, "UnConditionalBranch: %lx\n", br_pc); 60313454Spau.cabre@metempsy.com predict(tid, br_pc, false, bp_history); 60413454Spau.cabre@metempsy.com updateHistories(tid, br_pc, true, bp_history); 60513454Spau.cabre@metempsy.com assert(threadHistory[tid].gHist == 60613454Spau.cabre@metempsy.com &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]); 60713454Spau.cabre@metempsy.com} 60813454Spau.cabre@metempsy.com 60913455Spau.cabre@metempsy.comvoid 61013455Spau.cabre@metempsy.comTAGE::updateStats(bool taken, TageBranchInfo* bi) 61113455Spau.cabre@metempsy.com{ 61213455Spau.cabre@metempsy.com if (taken == bi->tagePred) { 61313455Spau.cabre@metempsy.com // correct prediction 61413455Spau.cabre@metempsy.com switch (bi->provider) { 61513455Spau.cabre@metempsy.com case BIMODAL_ONLY: tageBimodalProviderCorrect++; break; 61613455Spau.cabre@metempsy.com case TAGE_LONGEST_MATCH: tageLongestMatchProviderCorrect++; break; 61713455Spau.cabre@metempsy.com case BIMODAL_ALT_MATCH: bimodalAltMatchProviderCorrect++; break; 61813455Spau.cabre@metempsy.com case TAGE_ALT_MATCH: tageAltMatchProviderCorrect++; break; 61913455Spau.cabre@metempsy.com } 62013455Spau.cabre@metempsy.com } else { 62113455Spau.cabre@metempsy.com // wrong prediction 62213455Spau.cabre@metempsy.com switch (bi->provider) { 62313455Spau.cabre@metempsy.com case BIMODAL_ONLY: tageBimodalProviderWrong++; break; 62413455Spau.cabre@metempsy.com case TAGE_LONGEST_MATCH: 62513455Spau.cabre@metempsy.com tageLongestMatchProviderWrong++; 62613455Spau.cabre@metempsy.com if (bi->altTaken == taken) { 62713455Spau.cabre@metempsy.com tageAltMatchProviderWouldHaveHit++; 62813455Spau.cabre@metempsy.com } 62913455Spau.cabre@metempsy.com break; 63013455Spau.cabre@metempsy.com case BIMODAL_ALT_MATCH: 63113455Spau.cabre@metempsy.com bimodalAltMatchProviderWrong++; 63213455Spau.cabre@metempsy.com break; 63313455Spau.cabre@metempsy.com case TAGE_ALT_MATCH: 63413455Spau.cabre@metempsy.com tageAltMatchProviderWrong++; 63513455Spau.cabre@metempsy.com break; 63613455Spau.cabre@metempsy.com } 63713455Spau.cabre@metempsy.com 63813455Spau.cabre@metempsy.com switch (bi->provider) { 63913455Spau.cabre@metempsy.com case BIMODAL_ALT_MATCH: 64013455Spau.cabre@metempsy.com case TAGE_ALT_MATCH: 64113455Spau.cabre@metempsy.com if (bi->longestMatchPred == taken) { 64213455Spau.cabre@metempsy.com tageLongestMatchProviderWouldHaveHit++; 64313455Spau.cabre@metempsy.com } 64413455Spau.cabre@metempsy.com } 64513455Spau.cabre@metempsy.com } 64613455Spau.cabre@metempsy.com 64713455Spau.cabre@metempsy.com switch (bi->provider) { 64813455Spau.cabre@metempsy.com case TAGE_LONGEST_MATCH: 64913455Spau.cabre@metempsy.com case TAGE_ALT_MATCH: 65013455Spau.cabre@metempsy.com tageLongestMatchProvider[bi->hitBank]++; 65113455Spau.cabre@metempsy.com tageAltMatchProvider[bi->altBank]++; 65213455Spau.cabre@metempsy.com break; 65313455Spau.cabre@metempsy.com } 65413455Spau.cabre@metempsy.com} 65513455Spau.cabre@metempsy.com 65613455Spau.cabre@metempsy.comvoid 65713455Spau.cabre@metempsy.comTAGE::regStats() 65813455Spau.cabre@metempsy.com{ 65913455Spau.cabre@metempsy.com BPredUnit::regStats(); 66013455Spau.cabre@metempsy.com 66113455Spau.cabre@metempsy.com tageLongestMatchProviderCorrect 66213455Spau.cabre@metempsy.com .name(name() + ".tageLongestMatchProviderCorrect") 66313455Spau.cabre@metempsy.com .desc("Number of times TAGE Longest Match is the provider and " 66413455Spau.cabre@metempsy.com "the prediction is correct"); 66513455Spau.cabre@metempsy.com 66613455Spau.cabre@metempsy.com tageAltMatchProviderCorrect 66713455Spau.cabre@metempsy.com .name(name() + ".tageAltMatchProviderCorrect") 66813455Spau.cabre@metempsy.com .desc("Number of times TAGE Alt Match is the provider and " 66913455Spau.cabre@metempsy.com "the prediction is correct"); 67013455Spau.cabre@metempsy.com 67113455Spau.cabre@metempsy.com bimodalAltMatchProviderCorrect 67213455Spau.cabre@metempsy.com .name(name() + ".bimodalAltMatchProviderCorrect") 67313455Spau.cabre@metempsy.com .desc("Number of times TAGE Alt Match is the bimodal and it is the " 67413455Spau.cabre@metempsy.com "provider and the prediction is correct"); 67513455Spau.cabre@metempsy.com 67613455Spau.cabre@metempsy.com tageBimodalProviderCorrect 67713455Spau.cabre@metempsy.com .name(name() + ".tageBimodalProviderCorrect") 67813455Spau.cabre@metempsy.com .desc("Number of times there are no hits on the TAGE tables " 67913455Spau.cabre@metempsy.com "and the bimodal prediction is correct"); 68013455Spau.cabre@metempsy.com 68113455Spau.cabre@metempsy.com tageLongestMatchProviderWrong 68213455Spau.cabre@metempsy.com .name(name() + ".tageLongestMatchProviderWrong") 68313455Spau.cabre@metempsy.com .desc("Number of times TAGE Longest Match is the provider and " 68413455Spau.cabre@metempsy.com "the prediction is wrong"); 68513455Spau.cabre@metempsy.com 68613455Spau.cabre@metempsy.com tageAltMatchProviderWrong 68713455Spau.cabre@metempsy.com .name(name() + ".tageAltMatchProviderWrong") 68813455Spau.cabre@metempsy.com .desc("Number of times TAGE Alt Match is the provider and " 68913455Spau.cabre@metempsy.com "the prediction is wrong"); 69013455Spau.cabre@metempsy.com 69113455Spau.cabre@metempsy.com bimodalAltMatchProviderWrong 69213455Spau.cabre@metempsy.com .name(name() + ".bimodalAltMatchProviderWrong") 69313455Spau.cabre@metempsy.com .desc("Number of times TAGE Alt Match is the bimodal and it is the " 69413455Spau.cabre@metempsy.com "provider and the prediction is wrong"); 69513455Spau.cabre@metempsy.com 69613455Spau.cabre@metempsy.com tageBimodalProviderWrong 69713455Spau.cabre@metempsy.com .name(name() + ".tageBimodalProviderWrong") 69813455Spau.cabre@metempsy.com .desc("Number of times there are no hits on the TAGE tables " 69913455Spau.cabre@metempsy.com "and the bimodal prediction is wrong"); 70013455Spau.cabre@metempsy.com 70113455Spau.cabre@metempsy.com tageAltMatchProviderWouldHaveHit 70213455Spau.cabre@metempsy.com .name(name() + ".tageAltMatchProviderWouldHaveHit") 70313455Spau.cabre@metempsy.com .desc("Number of times TAGE Longest Match is the provider, " 70413455Spau.cabre@metempsy.com "the prediction is wrong and Alt Match prediction was correct"); 70513455Spau.cabre@metempsy.com 70613455Spau.cabre@metempsy.com tageLongestMatchProviderWouldHaveHit 70713455Spau.cabre@metempsy.com .name(name() + ".tageLongestMatchProviderWouldHaveHit") 70813455Spau.cabre@metempsy.com .desc("Number of times TAGE Alt Match is the provider, the " 70913455Spau.cabre@metempsy.com "prediction is wrong and Longest Match prediction was correct"); 71013455Spau.cabre@metempsy.com 71113455Spau.cabre@metempsy.com tageLongestMatchProvider 71213455Spau.cabre@metempsy.com .init(nHistoryTables + 1) 71313455Spau.cabre@metempsy.com .name(name() + ".tageLongestMatchProvider") 71413455Spau.cabre@metempsy.com .desc("TAGE provider for longest match"); 71513455Spau.cabre@metempsy.com 71613455Spau.cabre@metempsy.com tageAltMatchProvider 71713455Spau.cabre@metempsy.com .init(nHistoryTables + 1) 71813455Spau.cabre@metempsy.com .name(name() + ".tageAltMatchProvider") 71913455Spau.cabre@metempsy.com .desc("TAGE provider for alt match"); 72013455Spau.cabre@metempsy.com} 72113455Spau.cabre@metempsy.com 72213454Spau.cabre@metempsy.comTAGE* 72313454Spau.cabre@metempsy.comTAGEParams::create() 72413454Spau.cabre@metempsy.com{ 72513454Spau.cabre@metempsy.com return new TAGE(this); 72613454Spau.cabre@metempsy.com} 727