/* * Copyright (c) 2018 Metempsy Technology Consulting * All rights reserved. * * Copyright (c) 2006 INRIA (Institut National de Recherche en * Informatique et en Automatique / French National Research Institute * for Computer Science and Applied Mathematics) * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Author: André Seznec, Pau Cabre, Javier Bueno * */ /* * 8KB TAGE-SC-L branch predictor (devised by Andre Seznec) */ #include "cpu/pred/tage_sc_l_8KB.hh" #include "base/random.hh" #include "debug/TageSCL.hh" TAGE_SC_L_8KB_StatisticalCorrector::TAGE_SC_L_8KB_StatisticalCorrector( TAGE_SC_L_8KB_StatisticalCorrectorParams *p) : StatisticalCorrector(p), gnb(p->gnb), logGnb(p->logGnb), gm(p->gm) { initGEHLTable(gnb, gm, ggehl, logGnb, wg, 7); } TAGE_SC_L_8KB_StatisticalCorrector::SCThreadHistory * TAGE_SC_L_8KB_StatisticalCorrector::makeThreadHistory() { SC_8KB_ThreadHistory *sh = new SC_8KB_ThreadHistory(); sh->setNumOrdinalHistories(1); sh->initLocalHistory(1, numEntriesFirstLocalHistories, 2); return sh; } unsigned TAGE_SC_L_8KB_StatisticalCorrector::getIndBiasBank(Addr branch_pc, BranchInfo* bi, int hitBank, int altBank) const { return (bi->predBeforeSC + (((hitBank+1)/4)<<4) + (bi->highConf<<1) + (bi->lowConf <<2) +((altBank!=0)<<3)) & ((1<(scHistory); lsum += gPredict( branch_pc, sh->globalHist, gm, ggehl, gnb, logGnb, wg); lsum += gPredict( branch_pc, sh->bwHist, bwm, bwgehl, bwnb, logBwnb, wbw); // only 1 local history here lsum += gPredict( branch_pc, sh->getLocalHistory(1, branch_pc), lm, lgehl, lnb, logLnb, wl); lsum += gPredict( branch_pc, sh->imliCount, im, igehl, inb, logInb, wi); int thres = (updateThreshold>>3)+pUpdateThreshold[getIndUpd(branch_pc)]; return thres; } int TAGE_SC_L_8KB_StatisticalCorrector::gIndexLogsSubstr(int nbr, int i) { return 0; } void TAGE_SC_L_8KB_StatisticalCorrector::scHistoryUpdate(Addr branch_pc, const StaticInstPtr &inst, bool taken, BranchInfo *tage_bi, Addr corrTarget) { int brtype = inst->isDirectCtrl() ? 0 : 2; if (! inst->isUncondCtrl()) { ++brtype; } // Non speculative SC histories update if (brtype & 1) { SC_8KB_ThreadHistory *sh = static_cast(scHistory); sh->globalHist = (sh->globalHist << 1) + taken; } StatisticalCorrector::scHistoryUpdate(branch_pc, inst, taken, tage_bi, corrTarget); } void TAGE_SC_L_8KB_StatisticalCorrector::gUpdates(ThreadID tid, Addr pc, bool taken, BranchInfo* bi, int64_t phist) { SC_8KB_ThreadHistory *sh = static_cast(scHistory); gUpdate(pc, taken, sh->globalHist, gm, ggehl, gnb, logGnb, wg, bi); gUpdate(pc, taken, sh->bwHist, bwm, bwgehl, bwnb, logBwnb, wbw, bi); gUpdate(pc, taken, sh->getLocalHistory(1, pc), lm, lgehl, lnb, logLnb, wl, bi); gUpdate(pc, taken, sh->imliCount, im, igehl, inb, logInb, wi, bi); } TAGE_SC_L_8KB_StatisticalCorrector* TAGE_SC_L_8KB_StatisticalCorrectorParams::create() { return new TAGE_SC_L_8KB_StatisticalCorrector(this); } TAGE_SC_L_8KB::TAGE_SC_L_8KB(const TAGE_SC_L_8KBParams *params) : TAGE_SC_L(params) { } void TAGE_SC_L_TAGE_8KB::initFoldedHistories(ThreadHistory & history) { // Some hardcoded values are used here // (they do not seem to depend on any parameter) for (int i = 1; i <= nHistoryTables; i++) { history.computeIndices[i].init( histLengths[i], 17 + (2 * ((i - 1) / 2) % 4)); history.computeTags[0][i].init( history.computeIndices[i].origLength, 13); history.computeTags[1][i].init( history.computeIndices[i].origLength, 11); DPRINTF(TageSCL, "HistLength:%d, TTSize:%d, TTTWidth:%d\n", histLengths[i], logTagTableSizes[i], tagTableTagWidths[i]); } } int TAGE_SC_L_TAGE_8KB::gindex_ext(int index, int bank) const { return (index ^ (index >> logTagTableSizes[bank]) ^ (index >> 2 * logTagTableSizes[bank])); } uint16_t TAGE_SC_L_TAGE_8KB::gtag(ThreadID tid, Addr pc, int bank) const { int tag = (threadHistory[tid].computeIndices[bank - 1].comp << 2) ^ pc ^ (pc >> instShiftAmt) ^ threadHistory[tid].computeIndices[bank].comp; int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits : histLengths[bank]; tag = (tag >> 1) ^ ((tag & 1) << 10) ^ F(threadHistory[tid].pathHist, hlen, bank); tag ^= threadHistory[tid].computeTags[0][bank].comp ^ (threadHistory[tid].computeTags[1][bank].comp << 1); return ((tag ^ (tag >> tagTableTagWidths[bank])) & ((ULL(1) << tagTableTagWidths[bank]) - 1)); } void TAGE_SC_L_TAGE_8KB::handleAllocAndUReset( bool alloc, bool taken, TAGEBase::BranchInfo* bi, int nrand) { if (!alloc) { return; } int penalty = 0; int truePen = 0; int numAllocated = 0; bool maxAllocReached = false; for (int I = calcDep(bi); I < nHistoryTables; I += 2) { // Handle the 2-way associativity for allocation for (int j = 0; j < 2; ++j) { int i = ((j == 0) ? I : (I ^ 1)) + 1; if (i > nHistoryTables) { break; } if (noSkip[i]) { if (gtable[i][bi->tableIndices[i]].u == 0) { gtable[i][bi->tableIndices[i]].u = ((random_mt.random() & 31) == 0); // protect randomly from fast replacement gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; gtable[i][bi->tableIndices[i]].ctr = taken ? 0 : -1; numAllocated++; if (numAllocated == maxNumAlloc) { maxAllocReached = true; break; } I += 2; } else { int8_t ctr = gtable[i][bi->tableIndices[i]].ctr; if ((gtable[i][bi->tableIndices[i]].u == 1) & (abs (2 * ctr + 1) == 1)) { if ((random_mt.random() & 7) == 0) { gtable[i][bi->tableIndices[i]].u = 0; } } else { truePen++; } penalty++; } } else { break; } } if (maxAllocReached) { break; } } tCounter += (truePen + penalty - 5 * numAllocated); handleUReset(); } void TAGE_SC_L_TAGE_8KB::resetUctr(uint8_t & u) { // On real HW it should be u >>= 1 instead of if > 0 then u-- if (u > 0) { u--; } } void TAGE_SC_L_TAGE_8KB::handleTAGEUpdate(Addr branch_pc, bool taken, TAGEBase::BranchInfo* bi) { if (bi->hitBank > 0) { if (abs (2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) == 1) { if (bi->longestMatchPred != taken) { // acts as a protection if (bi->altBank > 0) { int8_t ctr = gtable[bi->altBank][bi->altBankIndex].ctr; if (abs (2 * ctr + 1) == 1) { gtable[bi->altBank][bi->altBankIndex].u = 0; } //just mute from protected to unprotected ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken, tagTableCounterBits); ctr = gtable[bi->altBank][bi->altBankIndex].ctr; if (abs (2 * ctr + 1) == 1) { gtable[bi->altBank][bi->altBankIndex].u = 0; } } if (bi->altBank == 0) { baseUpdate(branch_pc, taken, bi); } } } //just mute from protected to unprotected if (abs (2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) == 1) { gtable[bi->hitBank][bi->hitBankIndex].u = 0; } ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken, tagTableCounterBits); //sign changes: no way it can have been useful if (abs (2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) == 1) { gtable[bi->hitBank][bi->hitBankIndex].u = 0; } if (bi->altTaken == taken) { if (bi->altBank > 0) { int8_t ctr = gtable[bi->altBank][bi->altBankIndex].ctr; if (abs (2*ctr + 1) == 7) { if (gtable[bi->hitBank][bi->hitBankIndex].u == 1) { if (bi->longestMatchPred == taken) { gtable[bi->hitBank][bi->hitBankIndex].u = 0; } } } } } } else { baseUpdate(branch_pc, taken, bi); } if ((bi->longestMatchPred != bi->altTaken) && (bi->longestMatchPred == taken) && (gtable[bi->hitBank][bi->hitBankIndex].u < (1 << tagTableUBits) -1)) { gtable[bi->hitBank][bi->hitBankIndex].u++; } } TAGE_SC_L_TAGE_8KB* TAGE_SC_L_TAGE_8KBParams::create() { return new TAGE_SC_L_TAGE_8KB(this); } TAGE_SC_L_8KB* TAGE_SC_L_8KBParams::create() { return new TAGE_SC_L_8KB(this); }