logUResetPeriod = Param.Unsigned(18,
"Log period in number of branches to reset TAGE useful counters")
numUseAltOnNa = Param.Unsigned(1, "Number of USE_ALT_ON_NA counters")
- useAltOnNaBits = Param.Unsigned(4, "Size of the USE_ALT_ON_NA counter")
+ useAltOnNaBits = Param.Unsigned(4, "Size of the USE_ALT_ON_NA counter(s)")
maxNumAlloc = Param.Unsigned(1,
"Max number of TAGE entries allocted on mispredict")
optionalAgeReset = Param.Bool(True,
"Reset age bits optionally in some cases")
+class TAGE_SC_L_TAGE(TAGEBase):
+ type = 'TAGE_SC_L_TAGE'
+ cxx_class = 'TAGE_SC_L_TAGE'
+ cxx_header = "cpu/pred/tage_sc_l.hh"
+ abstract = True
+ tagTableTagWidths = [0]
+ numUseAltOnNa = 16
+ pathHistBits = 27
+ maxNumAlloc = 2
+ logUResetPeriod = 10
+ useAltOnNaBits = 5
+ # TODO No speculation implemented as of now
+ speculativeHistUpdate = False
+
+ # This size does not set the final sizes of the tables (it is just used
+ # for some calculations)
+ # Instead, the number of TAGE entries comes from shortTagsTageEntries and
+ # longTagsTageEntries
+ logTagTableSize = Param.Unsigned("Log size of each tag table")
+
+ shortTagsTageFactor = Param.Unsigned(
+ "Factor for calculating the total number of short tags TAGE entries")
+
+ longTagsTageFactor = Param.Unsigned(
+ "Factor for calculating the total number of long tags TAGE entries")
+
+ shortTagsSize = Param.Unsigned(8, "Size of the short tags")
+
+ longTagsSize = Param.Unsigned("Size of the long tags")
+
+ firstLongTagTable = Param.Unsigned("First table with long tags")
+
+ truncatePathHist = Param.Bool(True,
+ "Truncate the path history to its configured size")
+
+
+class TAGE_SC_L_TAGE_64KB(TAGE_SC_L_TAGE):
+ type = 'TAGE_SC_L_TAGE_64KB'
+ cxx_class = 'TAGE_SC_L_TAGE_64KB'
+ cxx_header = "cpu/pred/tage_sc_l_64KB.hh"
+ nHistoryTables = 36
+
+ minHist = 6
+ maxHist = 3000
+
+ tagTableUBits = 1
+
+ logTagTableSizes = [13]
+
+ # This is used to handle the 2-way associativity
+ # (all odd entries are set to one, and if the corresponding even entry
+ # is set to one, then there is a 2-way associativity for this pair)
+ # Entry 0 is for the bimodal and it is ignored
+ # Note: For this implementation, some odd entries are also set to 0 to save
+ # some bits
+ noSkip = [0,0,1,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,0,1,0,1,0,1,0,0,0,1,0,0,0,1]
+
+ logTagTableSize = 10
+ shortTagsTageFactor = 10
+ longTagsTageFactor = 20
+
+ longTagsSize = 12
+
+ firstLongTagTable = 13
+
+class TAGE_SC_L_TAGE_8KB(TAGE_SC_L_TAGE):
+ type = 'TAGE_SC_L_TAGE_8KB'
+ cxx_class = 'TAGE_SC_L_TAGE_8KB'
+ cxx_header = "cpu/pred/tage_sc_l_8KB.hh"
+
+ nHistoryTables = 30
+
+ minHist = 4
+ maxHist = 1000
+
+ logTagTableSize = 7
+ shortTagsTageFactor = 9
+ longTagsTageFactor = 17
+ longTagsSize = 12
+
+ logTagTableSizes = [12]
+
+ firstLongTagTable = 11
+
+ truncatePathHist = False
+
+ noSkip = [0,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1]
+
+ tagTableUBits = 2
# LTAGE branch predictor as described in
# https://www.irisa.fr/caps/people/seznec/L-TAGE.pdf
cxx_header = "cpu/pred/ltage.hh"
tage = LTAGE_TAGE()
+
loop_predictor = Param.LoopPredictor(LoopPredictor(), "Loop predictor")
+
+class TAGE_SC_L_LoopPredictor(LoopPredictor):
+ type = 'TAGE_SC_L_LoopPredictor'
+ cxx_class = 'TAGE_SC_L_LoopPredictor'
+ cxx_header = "cpu/pred/tage_sc_l.hh"
+ loopTableAgeBits = 4
+ loopTableConfidenceBits = 4
+ loopTableTagBits = 10
+ loopTableIterBits = 10
+ useSpeculation = False
+ useHashing = True
+ useDirectionBit = True
+ restrictAllocation = True
+ initialLoopIter = 0
+ initialLoopAge = 7
+ optionalAgeReset = False
+
+class StatisticalCorrector(SimObject):
+ type = 'StatisticalCorrector'
+ cxx_class = 'StatisticalCorrector'
+ cxx_header = "cpu/pred/statistical_corrector.hh"
+ abstract = True
+
+ # Statistical corrector parameters
+
+ numEntriesFirstLocalHistories = Param.Unsigned(
+ "Number of entries for first local histories")
+
+ bwnb = Param.Unsigned("Num global backward branch GEHL lengths")
+ bwm = VectorParam.Int("Global backward branch GEHL lengths")
+ logBwnb = Param.Unsigned("Log num of global backward branch GEHL entries")
+
+ lnb = Param.Unsigned("Num first local history GEHL lenghts")
+ lm = VectorParam.Int("First local history GEHL lengths")
+ logLnb = Param.Unsigned("Log number of first local history GEHL entries")
+
+ inb = Param.Unsigned(1, "Num IMLI GEHL lenghts")
+ im = VectorParam.Int([8], "IMLI history GEHL lengths")
+ logInb = Param.Unsigned("Log number of IMLI GEHL entries")
+
+ logBias = Param.Unsigned("Log size of Bias tables")
+
+ logSizeUp = Param.Unsigned(6,
+ "Log size of update threshold counters tables")
+
+ chooserConfWidth = Param.Unsigned(7,
+ "Number of bits for the chooser counters")
+
+ updateThresholdWidth = Param.Unsigned(12,
+ "Number of bits for the update threshold counter")
+
+ pUpdateThresholdWidth = Param.Unsigned(8,
+ "Number of bits for the pUpdate threshold counters")
+
+ extraWeightsWidth = Param.Unsigned(6,
+ "Number of bits for the extra weights")
+
+ scCountersWidth = Param.Unsigned(6, "Statistical corrector counters width")
+
+# TAGE-SC-L branch predictor as desribed in
+# https://www.jilp.org/cbp2016/paper/AndreSeznecLimited.pdf
+# It is a modified LTAGE predictor plus a statistical corrector predictor
+# The TAGE modifications include bank interleaving and partial associativity
+# Two different sizes are proposed in the paper:
+# 8KB => See TAGE_SC_L_8KB below
+# 64KB => See TAGE_SC_L_64KB below
+# The TAGE_SC_L_8KB and TAGE_SC_L_64KB classes differ not only on the values
+# of some parameters, but also in some implementation details
+# Given this, the TAGE_SC_L class is left abstract
+# Note that as it is now, this branch predictor does not handle any type
+# of speculation: All the structures/histories are updated at commit time
+class TAGE_SC_L(LTAGE):
+ type = 'TAGE_SC_L'
+ cxx_class = 'TAGE_SC_L'
+ cxx_header = "cpu/pred/tage_sc_l.hh"
+ abstract = True
+
+ statistical_corrector = Param.StatisticalCorrector(
+ "Statistical Corrector")
+
+class TAGE_SC_L_64KB_LoopPredictor(TAGE_SC_L_LoopPredictor):
+ logSizeLoopPred = 5
+
+class TAGE_SC_L_8KB_LoopPredictor(TAGE_SC_L_LoopPredictor):
+ logSizeLoopPred = 3
+
+class TAGE_SC_L_64KB_StatisticalCorrector(StatisticalCorrector):
+ type = 'TAGE_SC_L_64KB_StatisticalCorrector'
+ cxx_class = 'TAGE_SC_L_64KB_StatisticalCorrector'
+ cxx_header = "cpu/pred/tage_sc_l_64KB.hh"
+
+ pnb = Param.Unsigned(3, "Num variation global branch GEHL lengths")
+ pm = VectorParam.Int([25, 16, 9], "Variation global branch GEHL lengths")
+ logPnb = Param.Unsigned(9,
+ "Log number of variation global branch GEHL entries")
+
+ snb = Param.Unsigned(3, "Num second local history GEHL lenghts")
+ sm = VectorParam.Int([16, 11, 6], "Second local history GEHL lengths")
+ logSnb = Param.Unsigned(9,
+ "Log number of second local history GEHL entries")
+
+ tnb = Param.Unsigned(2, "Num third local history GEHL lenghts")
+ tm = VectorParam.Int([9, 4], "Third local history GEHL lengths")
+ logTnb = Param.Unsigned(10,
+ "Log number of third local history GEHL entries")
+
+ imnb = Param.Unsigned(2, "Num second IMLI GEHL lenghts")
+ imm = VectorParam.Int([10, 4], "Second IMLI history GEHL lengths")
+ logImnb = Param.Unsigned(9, "Log number of second IMLI GEHL entries")
+
+ numEntriesSecondLocalHistories = Param.Unsigned(16,
+ "Number of entries for second local histories")
+ numEntriesThirdLocalHistories = Param.Unsigned(16,
+ "Number of entries for second local histories")
+
+ numEntriesFirstLocalHistories = 256
+
+ logBias = 8
+
+ bwnb = 3
+ bwm = [40, 24, 10]
+ logBwnb = 10
+
+ lnb = 3
+ lm = [11, 6, 3]
+ logLnb = 10
+
+ logInb = 8
+
+class TAGE_SC_L_8KB_StatisticalCorrector(StatisticalCorrector):
+ type = 'TAGE_SC_L_8KB_StatisticalCorrector'
+ cxx_class = 'TAGE_SC_L_8KB_StatisticalCorrector'
+ cxx_header = "cpu/pred/tage_sc_l_8KB.hh"
+ gnb = Param.Unsigned(2, "Num global branch GEHL lengths")
+ gm = VectorParam.Int([6, 3], "Global branch GEHL lengths")
+ logGnb = Param.Unsigned(7, "Log number of global branch GEHL entries")
+
+ numEntriesFirstLocalHistories = 64
+
+ logBias = 7
+
+ bwnb = 2
+ logBwnb = 7
+ bwm = [16, 8]
+
+ lnb = 2
+ logLnb = 7
+ lm = [6, 3]
+
+ logInb = 7
+
+# 64KB TAGE-SC-L branch predictor as described in
+# http://www.jilp.org/cbp2016/paper/AndreSeznecLimited.pdf
+class TAGE_SC_L_64KB(TAGE_SC_L):
+ type = 'TAGE_SC_L_64KB'
+ cxx_class = 'TAGE_SC_L_64KB'
+ cxx_header = "cpu/pred/tage_sc_l_64KB.hh"
+
+ tage = TAGE_SC_L_TAGE_64KB()
+ loop_predictor = TAGE_SC_L_64KB_LoopPredictor()
+ statistical_corrector = TAGE_SC_L_64KB_StatisticalCorrector()
+
+# 8KB TAGE-SC-L branch predictor as described in
+# http://www.jilp.org/cbp2016/paper/AndreSeznecLimited.pdf
+class TAGE_SC_L_8KB(TAGE_SC_L):
+ type = 'TAGE_SC_L_8KB'
+ cxx_class = 'TAGE_SC_L_8KB'
+ cxx_header = "cpu/pred/tage_sc_l_8KB.hh"
+
+ tage = TAGE_SC_L_TAGE_8KB()
+ loop_predictor = TAGE_SC_L_8KB_LoopPredictor()
+ statistical_corrector = TAGE_SC_L_8KB_StatisticalCorrector()
Source('tage.cc')
Source('loop_predictor.cc')
Source('ltage.cc')
+Source('statistical_corrector.cc')
+Source('tage_sc_l.cc')
+Source('tage_sc_l_8KB.cc')
+Source('tage_sc_l_64KB.cc')
DebugFlag('FreeList')
DebugFlag('Branch')
DebugFlag('Tage')
DebugFlag('LTage')
+DebugFlag('TageSCL')
#include "cpu/pred/loop_predictor.hh"
+#include "base/random.hh"
+#include "debug/LTage.hh"
#include "params/LoopPredictor.hh"
LoopPredictor::LoopPredictor(LoopPredictorParams *p)
}
bool
-LoopPredictor::optionalAgeInc(int nrand) const
+LoopPredictor::optionalAgeInc() const
{
return false;
}
void
-LoopPredictor::loopUpdate(Addr pc, bool taken, BranchInfo* bi, bool tage_pred,
- int random0, int random1, int random2)
+LoopPredictor::loopUpdate(Addr pc, bool taken, BranchInfo* bi, bool tage_pred)
{
int idx = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit);
if (bi->loopHit >= 0) {
ltable[idx].confidence = 0;
ltable[idx].currentIter = 0;
return;
- } else if (bi->loopPred != tage_pred || optionalAgeInc(random0)) {
+ } else if (bi->loopPred != tage_pred || optionalAgeInc()) {
+ DPRINTF(LTage, "Loop Prediction success:%lx\n",pc);
unsignedCtrUpdate(ltable[idx].age, true, loopTableAgeBits);
}
}
if (taken != (useDirectionBit ? ltable[idx].dir : true)) {
if (ltable[idx].currentIter == ltable[idx].numIter) {
+ DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc);
unsignedCtrUpdate(ltable[idx].confidence, true,
loopTableConfidenceBits);
//just do not predict when the loop count is 1 or 2
ltable[idx].confidence = 0;
}
} else {
+ DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc);
if (ltable[idx].numIter == 0) {
// first complete nest;
ltable[idx].confidence = 0;
}
} else if (useDirectionBit ? (bi->predTaken != taken) : taken) {
- if ((random2 & 3) == 0 || !restrictAllocation) {
+ if ((random_mt.random<int>() & 3) == 0 || !restrictAllocation) {
//try to allocate an entry on taken branch
- int nrand = random1;
+ int nrand = random_mt.random<int>();
for (int i = 0; i < (1 << logLoopTableAssoc); i++) {
int loop_hit = (nrand + i) & ((1 << logLoopTableAssoc) - 1);
idx = finallindex(bi->loopIndex, bi->loopIndexB, loop_hit);
if (ltable[idx].age == 0) {
+ DPRINTF(LTage,
+ "Allocating loop pred entry for branch %lx\n",
+ pc);
ltable[idx].dir = !taken; // ignored if no useDirectionBit
ltable[idx].tag = bi->loopTag;
ltable[idx].numIter = 0;
void
LoopPredictor::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken,
bool tage_pred, BranchInfo* bi,
- unsigned instShiftAmt, int rand0, int rand1,
- int rand2)
+ unsigned instShiftAmt)
{
if (useSpeculation) {
// recalculate loop prediction without speculation
}
}
- loopUpdate(branch_pc, taken, bi, tage_pred, rand0, rand1, rand2);
+ loopUpdate(branch_pc, taken, bi, tage_pred);
}
void
* @param bi Pointer to information on the
* prediction recorded at prediction time.
* @param tage_pred tage prediction of the branch
- * @param random0 random value
- * @param random1 random value
- * @param random2 random value
*/
- void loopUpdate(Addr pc, bool Taken, BranchInfo* bi, bool tage_pred,
- int random0, int random1, int random2);
+ void loopUpdate(Addr pc, bool Taken, BranchInfo* bi, bool tage_pred);
/**
* Speculatively updates the loop predictor
* @param bi Pointer to information on the prediction
* recorded at prediction time.
* @param instShiftAmt Number of bits to shift instructions
- * @param rand0 Random integer value
- * @param rand1 Random integer value
- * @param rand2 Random integer value
*/
- void condBranchUpdate(
- ThreadID tid, Addr branch_pc, bool taken, bool tage_pred,
- BranchInfo* bi, unsigned instShiftAmt, int rand0, int rand1,
- int rand2);
+ void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken,
+ bool tage_pred, BranchInfo* bi, unsigned instShiftAmt);
/**
* Get the loop prediction
virtual bool calcConf(int index) const;
- virtual bool optionalAgeInc(int nrand) const;
+ virtual bool optionalAgeInc() const;
virtual BranchInfo *makeBranchInfo();
#include "base/intmath.hh"
#include "base/logging.hh"
+#include "base/random.hh"
#include "base/trace.hh"
#include "debug/Fetch.hh"
#include "debug/LTage.hh"
{
}
+void
+LTAGE::init()
+{
+ TAGE::init();
+}
+
//prediction
bool
LTAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b)
return pred_taken;
}
+// PREDICTOR UPDATE
void
LTAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history,
bool squashed, const StaticInstPtr & inst, Addr corrTarget)
return;
}
- int nrand = TAGEBase::getRandom() & 3;
+ int nrand = random_mt.random<int>() & 3;
if (bi->tageBranchInfo->condBranch) {
DPRINTF(LTage, "Updating tables for branch:%lx; taken?:%d\n",
branch_pc, taken);
loopPredictor->updateStats(taken, bi->lpBranchInfo);
loopPredictor->condBranchUpdate(tid, branch_pc, taken,
- bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt,
- TAGEBase::getRandom(), TAGEBase::getRandom(),
- TAGEBase::getRandom());
+ bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt);
tage->condBranchUpdate(tid, branch_pc, taken, bi->tageBranchInfo,
- nrand, corrTarget);
+ nrand, corrTarget, bi->lpBranchInfo->predTaken);
}
tage->updateHistories(tid, branch_pc, taken, bi->tageBranchInfo, false,
void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
bool squashed, const StaticInstPtr & inst,
Addr corrTarget = MaxAddr) override;
+
+ void init() override;
virtual void regStats() override;
protected:
--- /dev/null
+/*
+ * 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
+ *
+ */
+
+/*
+ * Statistical corrector base class
+ */
+
+ #include "cpu/pred/statistical_corrector.hh"
+
+ #include "params/StatisticalCorrector.hh"
+
+ StatisticalCorrector::StatisticalCorrector(
+ const StatisticalCorrectorParams *p)
+ : SimObject(p),
+ logBias(p->logBias),
+ logSizeUp(p->logSizeUp),
+ logSizeUps(logSizeUp / 2),
+ numEntriesFirstLocalHistories(p->numEntriesFirstLocalHistories),
+ bwnb(p->bwnb),
+ logBwnb(p->logBwnb),
+ bwm(p->bwm),
+ lnb(p->lnb),
+ logLnb(p->logLnb),
+ lm(p->lm),
+ inb(p->inb),
+ logInb(p->logInb),
+ im(p->im),
+ chooserConfWidth(p->chooserConfWidth),
+ updateThresholdWidth(p->updateThresholdWidth),
+ pUpdateThresholdWidth(p->pUpdateThresholdWidth),
+ extraWeightsWidth(p->extraWeightsWidth),
+ scCountersWidth(p->scCountersWidth),
+ firstH(0),
+ secondH(0)
+{
+ wb.resize(1 << logSizeUps, 4);
+
+ initGEHLTable(lnb, lm, lgehl, logLnb, wl, 7);
+ initGEHLTable(bwnb, bwm, bwgehl, logBwnb, wbw, 7);
+ initGEHLTable(inb, im, igehl, logInb, wi, 7);
+
+ updateThreshold = 35 << 3;
+
+ pUpdateThreshold.resize(1 << logSizeUp, 0);
+
+ bias.resize(1 << logBias);
+ biasSK.resize(1 << logBias);
+ biasBank.resize(1 << logBias);
+ for (int j = 0; j < (1 << logBias); j++) {
+ switch (j & 3) {
+ case 0:
+ bias[j] = -32;
+ biasSK[j] = -8;
+ biasBank[j] = -32;
+ break;
+ case 1:
+ bias[j] = 31;
+ biasSK[j] = 7;
+ biasBank[j] = 31;
+ break;
+ case 2:
+ bias[j] = -1;
+ biasSK[j] = -32;
+ biasBank[j] = -1;
+ break;
+ case 3:
+ bias[j] = 0;
+ biasSK[j] = 31;
+ biasBank[j] = 0;
+ break;
+ }
+ }
+}
+
+StatisticalCorrector::BranchInfo*
+StatisticalCorrector::makeBranchInfo()
+{
+ return new BranchInfo();
+}
+
+StatisticalCorrector::SCThreadHistory*
+StatisticalCorrector::makeThreadHistory()
+{
+ return new SCThreadHistory();
+}
+
+void
+StatisticalCorrector::initGEHLTable(unsigned numLenghts,
+ std::vector<int> lengths, std::vector<int8_t> * & table,
+ unsigned logNumEntries, std::vector<int8_t> & w, int8_t wInitValue)
+{
+ assert(lengths.size() == numLenghts);
+ if (numLenghts == 0) {
+ return;
+ }
+ table = new std::vector<int8_t> [numLenghts];
+ for (int i = 0; i < numLenghts; ++i) {
+ table[i].resize(1 << logNumEntries, 0);
+ for (int j = 0; j < ((1 << logNumEntries) - 1); ++j) {
+ if (! (j & 1)) {
+ table[i][j] = -1;
+ }
+ }
+ }
+
+ w.resize(1 << logSizeUps, wInitValue);
+}
+
+unsigned
+StatisticalCorrector::getIndBias(Addr branch_pc, BranchInfo* bi,
+ bool bias) const
+{
+ return (((((branch_pc ^(branch_pc >>2))<<1) ^ (bi->lowConf & bias)) <<1)
+ + bi->predBeforeSC) & ((1<<logBias) -1);
+}
+
+unsigned
+StatisticalCorrector::getIndBiasSK(Addr branch_pc, BranchInfo* bi) const
+{
+ return (((((branch_pc ^ (branch_pc >> (logBias-2)))<<1) ^
+ (bi->highConf))<<1) + bi->predBeforeSC) & ((1<<logBias) -1);
+}
+
+unsigned
+StatisticalCorrector::getIndUpd(Addr branch_pc) const
+{
+ return ((branch_pc ^ (branch_pc >>2)) & ((1 << (logSizeUp)) - 1));
+}
+
+unsigned
+StatisticalCorrector::getIndUpds(Addr branch_pc) const
+{
+ return ((branch_pc ^ (branch_pc >>2)) & ((1 << (logSizeUps)) - 1));
+}
+
+int64_t
+StatisticalCorrector::gIndex(Addr branch_pc, int64_t bhist, int logs, int nbr,
+ int i)
+{
+ return (((int64_t) branch_pc) ^ bhist ^ (bhist >> (8 - i)) ^
+ (bhist >> (16 - 2 * i)) ^ (bhist >> (24 - 3 * i)) ^
+ (bhist >> (32 - 3 * i)) ^ (bhist >> (40 - 4 * i))) &
+ ((1 << (logs - gIndexLogsSubstr(nbr, i))) - 1);
+}
+
+int
+StatisticalCorrector::gPredict(Addr branch_pc, int64_t hist,
+ std::vector<int> & length, std::vector<int8_t> * tab, int nbr,
+ int logs, std::vector<int8_t> & w)
+{
+ int percsum = 0;
+ for (int i = 0; i < nbr; i++) {
+ int64_t bhist = hist & ((int64_t) ((1 << length[i]) - 1));
+ int64_t index = gIndex(branch_pc, bhist, logs, nbr, i);
+ int8_t ctr = tab[i][index];
+ percsum += (2 * ctr + 1);
+ }
+ percsum = (1 + (w[getIndUpds(branch_pc)] >= 0)) * percsum;
+ return percsum;
+}
+
+void
+StatisticalCorrector::gUpdate(Addr branch_pc, bool taken, int64_t hist,
+ std::vector<int> & length, std::vector<int8_t> * tab,
+ int nbr, int logs, std::vector<int8_t> & w,
+ BranchInfo* bi)
+{
+ int percsum = 0;
+ for (int i = 0; i < nbr; i++) {
+ int64_t bhist = hist & ((int64_t) ((1 << length[i]) - 1));
+ int64_t index = gIndex(branch_pc, bhist, logs, nbr, i);
+ percsum += (2 * tab[i][index] + 1);
+ ctrUpdate(tab[i][index], taken, scCountersWidth);
+ }
+
+ int xsum = bi->lsum - ((w[getIndUpds(branch_pc)] >= 0)) * percsum;
+ if ((xsum + percsum >= 0) != (xsum >= 0)) {
+ ctrUpdate(w[getIndUpds(branch_pc)], ((percsum >= 0) == taken),
+ extraWeightsWidth);
+ }
+}
+
+bool
+StatisticalCorrector::scPredict(ThreadID tid, Addr branch_pc, bool cond_branch,
+ BranchInfo* bi, bool prev_pred_taken, bool bias_bit,
+ bool use_conf_ctr, int8_t conf_ctr, unsigned conf_bits,
+ int hitBank, int altBank, int64_t phist)
+{
+ bool pred_taken = prev_pred_taken;
+ if (cond_branch) {
+
+ bi->predBeforeSC = prev_pred_taken;
+
+ // first calc/update the confidences from the TAGE prediction
+ if (use_conf_ctr) {
+ bi->lowConf = (abs(2 * conf_ctr + 1) == 1);
+ bi->medConf = (abs(2 * conf_ctr + 1) == 5);
+ bi->highConf = (abs(2 * conf_ctr + 1) >= (1<<conf_bits) - 1);
+ }
+
+ int lsum = 0;
+
+ int8_t ctr = bias[getIndBias(branch_pc, bi, bias_bit)];
+ lsum += (2 * ctr + 1);
+ ctr = biasSK[getIndBiasSK(branch_pc, bi)];
+ lsum += (2 * ctr + 1);
+ ctr = biasBank[getIndBiasBank(branch_pc, bi, hitBank, altBank)];
+ lsum += (2 * ctr + 1);
+
+ lsum = (1 + (wb[getIndUpds(branch_pc)] >= 0)) * lsum;
+
+ int thres = gPredictions(tid, branch_pc, bi, lsum, phist);
+
+ // These will be needed at update time
+ bi->lsum = lsum;
+ bi->thres = thres;
+
+ bool scPred = (lsum >= 0);
+
+ if (pred_taken != scPred) {
+ bool useScPred = true;
+ //Choser uses TAGE confidence and |LSUM|
+ if (bi->highConf) {
+ if (abs (lsum) < (thres / 4)) {
+ useScPred = false;
+ } else if (abs (lsum) < (thres / 2)) {
+ useScPred = (secondH < 0);
+ }
+ }
+
+ if (bi->medConf) {
+ if (abs (lsum) < (thres / 4)) {
+ useScPred = (firstH < 0);
+ }
+ }
+
+ bi->usedScPred = useScPred;
+ if (useScPred) {
+ pred_taken = scPred;
+ bi->scPred = scPred;
+ }
+ }
+ }
+
+ return pred_taken;
+}
+
+void
+StatisticalCorrector::scHistoryUpdate(Addr branch_pc, int brtype, bool taken,
+ BranchInfo * tage_bi, Addr corrTarget)
+{
+ // Non speculative SC histories update
+ if (brtype & 1) {
+ if (corrTarget < branch_pc) {
+ //This branch corresponds to a loop
+ if (!taken) {
+ //exit of the "loop"
+ scHistory->imliCount = 0;
+ } else {
+ if (scHistory->imliCount < ((1 << im[0]) - 1)) {
+ scHistory->imliCount++;
+ }
+ }
+ }
+
+ scHistory->bwHist = (scHistory->bwHist << 1) +
+ (taken & (corrTarget < branch_pc));
+ scHistory->updateLocalHistory(1, branch_pc, taken);
+ }
+}
+
+void
+StatisticalCorrector::condBranchUpdate(ThreadID tid, Addr branch_pc,
+ bool taken, BranchInfo *bi, Addr corrTarget, bool b, int hitBank,
+ int altBank, int64_t phist)
+{
+ bool scPred = (bi->lsum >= 0);
+
+ if (bi->predBeforeSC != scPred) {
+ if (abs(bi->lsum) < bi->thres) {
+ if (bi->highConf) {
+ if ((abs(bi->lsum) < bi->thres / 2)) {
+ if ((abs(bi->lsum) >= bi->thres / 4)) {
+ ctrUpdate(secondH, (bi->predBeforeSC == taken),
+ chooserConfWidth);
+ }
+ }
+ }
+ }
+ if (bi->medConf) {
+ if ((abs(bi->lsum) < bi->thres / 4)) {
+ ctrUpdate(firstH, (bi->predBeforeSC == taken),
+ chooserConfWidth);
+ }
+ }
+ }
+
+ if ((scPred != taken) || ((abs(bi->lsum) < bi->thres))) {
+ ctrUpdate(updateThreshold, (scPred != taken), updateThresholdWidth);
+ ctrUpdate(pUpdateThreshold[getIndUpd(branch_pc)], (scPred != taken),
+ pUpdateThresholdWidth);
+
+ unsigned indUpds = getIndUpds(branch_pc);
+ unsigned indBias = getIndBias(branch_pc, bi, b);
+ unsigned indBiasSK = getIndBiasSK(branch_pc, bi);
+ unsigned indBiasBank = getIndBiasBank(branch_pc, bi, hitBank, altBank);
+
+ int xsum = bi->lsum -
+ ((wb[indUpds] >= 0) * ((2 * bias[indBias] + 1) +
+ (2 * biasSK[indBiasSK] + 1) +
+ (2 * biasBank[indBiasBank] + 1)));
+
+ if ((xsum + ((2 * bias[indBias] + 1) + (2 * biasSK[indBiasSK] + 1) +
+ (2 * biasBank[indBiasBank] + 1)) >= 0) != (xsum >= 0))
+ {
+ ctrUpdate(wb[indUpds],
+ (((2 * bias[indBias] + 1) +
+ (2 * biasSK[indBiasSK] + 1) +
+ (2 * biasBank[indBiasBank] + 1) >= 0) == taken),
+ extraWeightsWidth);
+ }
+
+ ctrUpdate(bias[indBias], taken, scCountersWidth);
+ ctrUpdate(biasSK[indBiasSK], taken, scCountersWidth);
+ ctrUpdate(biasBank[indBiasBank], taken, scCountersWidth);
+
+ gUpdates(tid, branch_pc, taken, bi, phist);
+ }
+}
+
+void
+StatisticalCorrector::updateStats(bool taken, BranchInfo *bi)
+{
+ if (taken == bi->scPred) {
+ scPredictorCorrect++;
+ } else {
+ scPredictorWrong++;
+ }
+}
+
+void
+StatisticalCorrector::init()
+{
+ scHistory = makeThreadHistory();
+}
+
+void
+StatisticalCorrector::regStats()
+{
+ scPredictorCorrect
+ .name(name() + ".scPredictorCorrect")
+ .desc("Number of time the SC predictor is the provider and "
+ "the prediction is correct");
+
+ scPredictorWrong
+ .name(name() + ".scPredictorWrong")
+ .desc("Number of time the SC predictor is the provider and "
+ "the prediction is wrong");
+}
--- /dev/null
+/*
+ * 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
+ *
+ */
+
+/*
+ * Statistical corrector base class
+ */
+
+#ifndef __CPU_PRED_STATISTICAL_CORRECTOR_HH
+#define __CPU_PRED_STATISTICAL_CORRECTOR_HH
+
+#include "base/statistics.hh"
+#include "base/types.hh"
+#include "sim/sim_object.hh"
+
+struct StatisticalCorrectorParams;
+
+class StatisticalCorrector : public SimObject
+{
+ template<typename T>
+ inline void ctrUpdate(T & ctr, bool taken, int nbits) {
+ assert(nbits <= sizeof(T) << 3);
+ if (taken) {
+ if (ctr < ((1 << (nbits - 1)) - 1))
+ ctr++;
+ } else {
+ if (ctr > -(1 << (nbits - 1)))
+ ctr--;
+ }
+ }
+ protected:
+ // histories used for the statistical corrector
+ struct SCThreadHistory {
+ SCThreadHistory() {
+ bwHist = 0;
+ numOrdinalHistories = 0;
+ imliCount = 0;
+ }
+ int64_t bwHist; // backward global history
+ int64_t imliCount;
+
+ void setNumOrdinalHistories(unsigned num)
+ {
+ numOrdinalHistories = num;
+ assert(num > 0);
+ shifts.resize(num);
+ localHistories = new std::vector<int64_t> [num];
+ }
+
+ void initLocalHistory(int ordinal, int numHistories, int shift)
+ {
+ assert((ordinal >= 1) && (ordinal <= numOrdinalHistories));
+ shifts[ordinal - 1] = shift;
+ assert(isPowerOf2(numHistories));
+ localHistories[ordinal - 1].resize(numHistories, 0);
+ }
+
+ int64_t getLocalHistory(int ordinal, Addr pc)
+ {
+ assert((ordinal >= 1) && (ordinal <= numOrdinalHistories));
+ unsigned idx = ordinal - 1;
+ return localHistories[idx][getEntry(pc, idx)];
+ }
+
+ void updateLocalHistory(
+ int ordinal, Addr branch_pc, bool taken, Addr extraXor = 0)
+ {
+ assert((ordinal >= 1) && (ordinal <= numOrdinalHistories));
+ unsigned idx = ordinal - 1;
+
+ unsigned entry = getEntry(branch_pc, idx);
+ int64_t hist = (localHistories[idx][entry] << 1) + taken;
+
+ if (extraXor) {
+ hist = hist ^ extraXor;
+ }
+
+ localHistories[idx][entry] = hist;
+ }
+
+ private:
+ std::vector<int64_t> * localHistories;
+ std::vector<int> shifts;
+ unsigned numOrdinalHistories;
+
+ unsigned getEntry(Addr pc, unsigned idx)
+ {
+ return (pc ^ (pc >> shifts[idx])) & (localHistories[idx].size()-1);
+ }
+ };
+
+ // For SC history we use global (i.e. not per thread) non speculative
+ // histories, as some of the strucures needed are quite big and it is not
+ // reasonable to make them per thread and it would be difficult to
+ // rollback on miss-predictions
+ SCThreadHistory * scHistory;
+
+ const unsigned logBias;
+
+ const unsigned logSizeUp;
+ const unsigned logSizeUps;
+
+ const unsigned numEntriesFirstLocalHistories;
+
+ // global backward branch history GEHL
+ const unsigned bwnb;
+ const unsigned logBwnb;
+ std::vector<int> bwm;
+ std::vector<int8_t> * bwgehl;
+ std::vector<int8_t> wbw;
+
+ // First local history GEHL
+ const unsigned lnb;
+ const unsigned logLnb;
+ std::vector<int> lm;
+ std::vector<int8_t> * lgehl;
+ std::vector<int8_t> wl;
+
+ // IMLI GEHL
+ const unsigned inb;
+ const unsigned logInb;
+ std::vector<int> im;
+ std::vector<int8_t> * igehl;
+ std::vector<int8_t> wi;
+
+ std::vector<int8_t> bias;
+ std::vector<int8_t> biasSK;
+ std::vector<int8_t> biasBank;
+
+ std::vector<int8_t> wb;
+
+ int updateThreshold;
+ std::vector<int> pUpdateThreshold;
+
+ // The two counters used to choose between TAGE ang SC on High Conf
+ // TAGE/Low Conf SC
+ const unsigned chooserConfWidth;
+
+ const unsigned updateThresholdWidth;
+ const unsigned pUpdateThresholdWidth;
+
+ const unsigned extraWeightsWidth;
+
+ const unsigned scCountersWidth;
+
+ int8_t firstH;
+ int8_t secondH;
+
+ // stats
+ Stats::Scalar scPredictorCorrect;
+ Stats::Scalar scPredictorWrong;
+ public:
+ struct BranchInfo
+ {
+ BranchInfo() : lowConf(false), highConf(false), altConf(false),
+ medConf(false), scPred(false), lsum(0), thres(0),
+ predBeforeSC(false), usedScPred(false)
+ {}
+
+ // confidences calculated on tage and used on the statistical
+ // correction
+ bool lowConf;
+ bool highConf;
+ bool altConf;
+ bool medConf;
+
+ bool scPred;
+ int lsum;
+ int thres;
+ bool predBeforeSC;
+ bool usedScPred;
+ };
+
+ StatisticalCorrector(const StatisticalCorrectorParams *p);
+
+ virtual BranchInfo *makeBranchInfo();
+ virtual SCThreadHistory *makeThreadHistory();
+
+ bool scPredict(
+ ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo* bi,
+ bool prev_pred_taken, bool bias_bit, bool use_conf_ctr,
+ int8_t conf_ctr, unsigned conf_bits, int hitBank, int altBank,
+ int64_t phist);
+
+ unsigned getIndBias(Addr branch_pc, BranchInfo* bi, bool b) const;
+
+ unsigned getIndBiasSK(Addr branch_pc, BranchInfo* bi) const;
+
+ virtual unsigned getIndBiasBank( Addr branch_pc, BranchInfo* bi,
+ int hitBank, int altBank) const = 0;
+
+ unsigned getIndUpd(Addr branch_pc) const;
+ unsigned getIndUpds(Addr branch_pc) const;
+
+ virtual int gPredictions(ThreadID tid, Addr branch_pc, BranchInfo* bi,
+ int & lsum, int64_t phist) = 0;
+
+ int64_t gIndex(Addr branch_pc, int64_t bhist, int logs, int nbr, int i);
+
+ virtual int gIndexLogsSubstr(int nbr, int i) = 0;
+
+ int gPredict(
+ Addr branch_pc, int64_t hist, std::vector<int> & length,
+ std::vector<int8_t> * tab, int nbr, int logs,
+ std::vector<int8_t> & w);
+
+ void gUpdate(
+ Addr branch_pc, bool taken, int64_t hist, std::vector<int> & length,
+ std::vector<int8_t> * tab, int nbr, int logs,
+ std::vector<int8_t> & w, BranchInfo* bi);
+
+ void initGEHLTable(
+ unsigned numLenghts, std::vector<int> lengths,
+ std::vector<int8_t> * & table, unsigned logNumEntries,
+ std::vector<int8_t> & w, int8_t wInitValue);
+
+ virtual void scHistoryUpdate(
+ Addr branch_pc, int brtype, bool taken, BranchInfo * tage_bi,
+ Addr corrTarget);
+
+ virtual void gUpdates( ThreadID tid, Addr pc, bool taken, BranchInfo* bi,
+ int64_t phist) = 0;
+
+ void init() override;
+ void regStats() override;
+ void updateStats(bool taken, BranchInfo *bi);
+
+ void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken,
+ BranchInfo *bi, Addr corrTarget, bool bias_bit,
+ int hitBank, int altBank, int64_t phist);
+};
+#endif//__CPU_PRED_STATISTICAL_CORRECTOR_HH
assert(bp_history);
TageBranchInfo *bi = static_cast<TageBranchInfo*>(bp_history);
+ TAGEBase::BranchInfo *tage_bi = bi->tageBranchInfo;
assert(corrTarget != MaxAddr);
if (squashed) {
// This restores the global history, then update it
// and recomputes the folded histories.
- tage->squash(tid, taken, bi->tageBranchInfo, corrTarget);
+ tage->squash(tid, taken, tage_bi, corrTarget);
return;
}
- int nrand = TAGEBase::getRandom() & 3;
+ int nrand = random_mt.random<int>() & 3;
if (bi->tageBranchInfo->condBranch) {
DPRINTF(Tage, "Updating tables for branch:%lx; taken?:%d\n",
branch_pc, taken);
tage->updateStats(taken, bi->tageBranchInfo);
- tage->condBranchUpdate(tid, branch_pc, taken, bi->tageBranchInfo,
- nrand, corrTarget);
+ tage->condBranchUpdate(tid, branch_pc, taken, tage_bi, nrand,
+ corrTarget, bi->tageBranchInfo->tagePred);
}
- tage->updateHistories(tid, branch_pc, taken, bi->tageBranchInfo, false,
- inst, corrTarget);
-
+ // optional non speculative update of the histories
+ tage->updateHistories(tid, branch_pc, taken, tage_bi, false, inst,
+ corrTarget);
delete bi;
}
bool
TAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b)
{
- TageBranchInfo *bi = new TageBranchInfo(*tage);
+ TageBranchInfo *bi = new TageBranchInfo(*tage);//nHistoryTables+1);
b = (void*)(bi);
return tage->tagePredict(tid, branch_pc, cond_branch, bi->tageBranchInfo);
}
virtual bool predict(ThreadID tid, Addr branch_pc, bool cond_branch,
void* &b);
+
public:
TAGE(const TAGEParams *params);
void btbUpdate(ThreadID tid, Addr branch_addr, void* &bp_history) override;
void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
bool squashed, const StaticInstPtr & inst,
- Addr corrTarget) override;
+ Addr corrTarget = MaxAddr) override;
virtual void squash(ThreadID tid, void *bp_history) override;
};
#include "base/intmath.hh"
#include "base/logging.hh"
-#include "base/random.hh"
#include "debug/Fetch.hh"
#include "debug/Tage.hh"
}
void
-TAGEBase::adjustAlloc(bool & alloc, bool taken)
+TAGEBase::adjustAlloc(bool & alloc, bool taken, bool pred_taken)
{
// Nothing for this base class implementation
}
void
TAGEBase::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken,
- BranchInfo* bi, int nrand, Addr corrTarget)
+ BranchInfo* bi, int nrand, Addr corrTarget, bool pred)
{
// TAGE UPDATE
// try to allocate a new entries only if prediction was wrong
}
}
- adjustAlloc(alloc, taken);
+ adjustAlloc(alloc, taken, pred);
handleAllocAndUReset(alloc, taken, bi, nrand);
return;
}
-int
-TAGEBase::getRandom()
-{
- return random_mt.random<int>();
-}
-
void
TAGEBase::updateStats(bool taken, BranchInfo* bi)
{
* recorded at prediction time.
* @nrand Random int number from 0 to 3
* @param corrTarget The correct branch target
+ * @param pred Final prediction for this branch
*/
virtual void condBranchUpdate(
ThreadID tid, Addr branch_pc, bool taken, BranchInfo* bi,
- int nrand, Addr corrTarget);
+ int nrand, Addr corrTarget, bool pred);
/**
* TAGE prediction called from TAGE::predict
* on an update
* For this base TAGE implementation it does nothing
*/
- virtual void adjustAlloc(bool & alloc, bool taken);
+ virtual void adjustAlloc(bool & alloc, bool taken, bool pred_taken);
/**
* Handles Allocation and U bits reset on an update
*/
virtual void extraAltCalc(BranchInfo* bi);
- /**
- * Algorithm for returning a random number
- * This base TAGE class just uses random_mt, but some derived classes
- * may want to use a more realistic implementation or force some values
- */
- static int getRandom();
-
void btbUpdate(ThreadID tid, Addr branch_addr, BranchInfo* &bi);
unsigned getGHR(ThreadID tid, BranchInfo *bi) const;
int8_t getCtr(int hitBank, int hitBankIndex) const;
--- /dev/null
+/*
+ * 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
+ *
+ */
+
+/*
+ * TAGE-SC-L branch predictor base class (devised by Andre Seznec)
+ * It consits of a TAGE + a statistical corrector (SC) + a loop predictor (L)
+ */
+
+#include "cpu/pred/tage_sc_l.hh"
+
+#include "base/random.hh"
+#include "debug/TageSCL.hh"
+
+bool
+TAGE_SC_L_LoopPredictor::calcConf(int index) const
+{
+ return LoopPredictor::calcConf(index) ||
+ (ltable[index].confidence * ltable[index].numIter > 128);
+}
+
+bool
+TAGE_SC_L_LoopPredictor::optionalAgeInc() const
+{
+ return (random_mt.random<int>() & 7) == 0;
+}
+
+TAGE_SC_L_LoopPredictor *
+TAGE_SC_L_LoopPredictorParams::create()
+{
+ return new TAGE_SC_L_LoopPredictor(this);
+}
+
+TAGE_SC_L::TAGE_SC_L(const TAGE_SC_LParams *p)
+ : LTAGE(p), statisticalCorrector(p->statistical_corrector)
+{
+}
+
+TAGEBase::BranchInfo*
+TAGE_SC_L_TAGE::makeBranchInfo()
+{
+ return new BranchInfo(*this);
+}
+void
+TAGE_SC_L_TAGE::calculateParameters()
+{
+ unsigned numHistLengths = nHistoryTables/2;
+ histLengths[1] = minHist;
+ histLengths[numHistLengths] = maxHist;
+
+ // This calculates the different history lenghts
+ // there are only numHistLengths different lengths
+ // They are initially set to the lower half of histLengths
+ for (int i = 2; i <= numHistLengths; i++) {
+ histLengths[i] = (int) (((double) minHist *
+ pow ((double) (maxHist) / (double) minHist,
+ (double) (i - 1) / (double) ((numHistLengths - 1))))
+ + 0.5);
+ }
+
+ // This copies and duplicates the values from the lower half of the table
+ // Ex: 4, 6, 9, 13 would get exanded to 4, 4, 6, 6, 9, 9, 13, 13
+ for (int i = nHistoryTables; i > 1; i--)
+ {
+ histLengths[i] = histLengths[(i + 1) / 2];
+ }
+
+ for (int i = 1; i <= nHistoryTables; i++)
+ {
+ tagTableTagWidths.push_back(
+ (i < firstLongTagTable) ? shortTagsSize : longTagsSize);
+
+ logTagTableSizes.push_back(logTagTableSize);
+ }
+}
+
+void
+TAGE_SC_L_TAGE::buildTageTables()
+{
+ // Trick! We only allocate entries for tables 1 and firstLongTagTable and
+ // make the other tables point to these allocated entries
+
+ gtable[1] = new TageEntry[shortTagsTageFactor * (1 << logTagTableSize)];
+ gtable[firstLongTagTable] =
+ new TageEntry[longTagsTageFactor * (1 << logTagTableSize)];
+ for (int i = 2; i < firstLongTagTable; ++i) {
+ gtable[i] = gtable[1];
+ }
+ for (int i = firstLongTagTable + 1; i <= nHistoryTables; ++i) {
+ gtable[i] = gtable[firstLongTagTable];
+ }
+}
+
+void
+TAGE_SC_L_TAGE::calculateIndicesAndTags(
+ ThreadID tid, Addr pc, TAGEBase::BranchInfo* bi)
+{
+ // computes the table addresses and the partial tags
+
+ for (int i = 1; i <= nHistoryTables; i += 2) {
+ tableIndices[i] = gindex(tid, pc, i);
+ tableTags[i] = gtag(tid, pc, i);
+ tableTags[i + 1] = tableTags[i];
+ tableIndices[i + 1] = tableIndices[i] ^
+ (tableTags[i] & ((1 << logTagTableSizes[i]) - 1));
+
+ bi->tableTags[i] = tableTags[i];
+ bi->tableTags[i+1] = tableTags[i+1];
+ }
+
+ Addr t = (pc ^ (threadHistory[tid].pathHist &
+ ((1 << histLengths[firstLongTagTable]) - 1)))
+ % longTagsTageFactor;
+
+ for (int i = firstLongTagTable; i <= nHistoryTables; i++) {
+ if (noSkip[i]) {
+ tableIndices[i] += (t << logTagTableSizes[i]);
+ bi->tableIndices[i] = tableIndices[i];
+ t++;
+ t = t % longTagsTageFactor;
+ }
+ }
+
+ t = (pc ^ (threadHistory[tid].pathHist & ((1 << histLengths[1]) - 1)))
+ % shortTagsTageFactor;
+
+ for (int i = 1; i <= firstLongTagTable - 1; i++) {
+ if (noSkip[i]) {
+ tableIndices[i] += (t << logTagTableSizes[i]);
+ bi->tableIndices[i] = tableIndices[i];
+ t++;
+ t = t % shortTagsTageFactor;
+ }
+ }
+}
+
+unsigned
+TAGE_SC_L_TAGE::getUseAltIdx(TAGEBase::BranchInfo* bi)
+{
+ BranchInfo *tbi = static_cast<BranchInfo *>(bi);
+ unsigned idx;
+ idx = ((((bi->hitBank-1)/8)<<1)+tbi->altConf) % (numUseAltOnNa-1);
+ return idx;
+}
+
+int
+TAGE_SC_L_TAGE::gindex(ThreadID tid, Addr pc, int bank) const
+{
+ int index;
+ int hlen = (histLengths[bank] > pathHistBits) ? pathHistBits :
+ histLengths[bank];
+ unsigned int shortPc = pc;
+
+ // pc is not shifted by instShiftAmt in this implementation
+ index = shortPc ^
+ (shortPc >> ((int) abs(logTagTableSizes[bank] - bank) + 1)) ^
+ threadHistory[tid].computeIndices[bank].comp ^
+ F(threadHistory[tid].pathHist, hlen, bank);
+
+ index = gindex_ext(index, bank);
+
+ return (index & ((ULL(1) << (logTagTableSizes[bank])) - 1));
+}
+
+int
+TAGE_SC_L_TAGE::F(int a, int size, int bank) const
+{
+ int a1, a2;
+
+ a = a & ((ULL(1) << size) - 1);
+ a1 = (a & ((ULL(1) << logTagTableSizes[bank]) - 1));
+ a2 = (a >> logTagTableSizes[bank]);
+
+ if (bank < logTagTableSizes[bank]) {
+ a2 = ((a2 << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1))
+ + (a2 >> (logTagTableSizes[bank] - bank));
+ }
+
+ a = a1 ^ a2;
+
+ if (bank < logTagTableSizes[bank]) {
+ a = ((a << bank) & ((ULL(1) << logTagTableSizes[bank]) - 1))
+ + (a >> (logTagTableSizes[bank] - bank));
+ }
+
+ return a;
+}
+
+int
+TAGE_SC_L_TAGE::bindex(Addr pc) const
+{
+ return ((pc ^ (pc >> instShiftAmt)) &
+ ((ULL(1) << (logTagTableSizes[0])) - 1));
+}
+
+void
+TAGE_SC_L_TAGE::updatePathAndGlobalHistory(
+ ThreadHistory& tHist, int brtype, bool taken, Addr branch_pc, Addr target)
+{
+ // TAGE update
+ int tmp = ((branch_pc ^ (branch_pc >> instShiftAmt))) ^ taken;
+ int path = branch_pc ^ (branch_pc >> instShiftAmt)
+ ^ (branch_pc >> (instShiftAmt+2));
+ if ((brtype == 3) & taken) {
+ tmp = (tmp ^ (target >> instShiftAmt));
+ path = path ^ (target >> instShiftAmt) ^ (target >> (instShiftAmt+2));
+ }
+
+ // some branch types use 3 bits in global history, the others just 2
+ int maxt = (brtype == 2) ? 3 : 2;
+
+ for (int t = 0; t < maxt; t++) {
+ bool dir = (tmp & 1);
+ tmp >>= 1;
+ int pathbit = (path & 127);
+ path >>= 1;
+ updateGHist(tHist.gHist, dir, tHist.globalHistory, tHist.ptGhist);
+ tHist.pathHist = (tHist.pathHist << 1) ^ pathbit;
+ if (truncatePathHist) {
+ // The 8KB implementation does not do this truncation
+ tHist.pathHist = (tHist.pathHist & ((ULL(1) << pathHistBits) - 1));
+ }
+ for (int i = 1; i <= nHistoryTables; i++) {
+ tHist.computeIndices[i].update(tHist.gHist);
+ tHist.computeTags[0][i].update(tHist.gHist);
+ tHist.computeTags[1][i].update(tHist.gHist);
+ }
+ }
+}
+
+void
+TAGE_SC_L_TAGE::updateHistories(
+ ThreadID tid, Addr branch_pc, bool taken, TAGEBase::BranchInfo* b,
+ bool speculative, const StaticInstPtr &inst, Addr target)
+{
+ if (speculative != speculativeHistUpdate) {
+ return;
+ }
+ // speculation is not implemented
+ assert(! speculative);
+
+ ThreadHistory& tHist = threadHistory[tid];
+
+ int brtype = inst->isDirectCtrl() ? 0 : 2;
+ if (! inst->isUncondCtrl()) {
+ ++brtype;
+ }
+ updatePathAndGlobalHistory(tHist, brtype, taken, branch_pc, target);
+
+ DPRINTF(TageSCL, "Updating global histories with branch:%lx; taken?:%d, "
+ "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist,
+ tHist.ptGhist);
+}
+
+void
+TAGE_SC_L_TAGE::squash(ThreadID tid, bool taken, TAGEBase::BranchInfo *bi,
+ Addr target)
+{
+ fatal("Speculation is not implemented");
+}
+
+void
+TAGE_SC_L_TAGE::adjustAlloc(bool & alloc, bool taken, bool pred_taken)
+{
+ // Do not allocate too often if the prediction is ok
+ if ((taken == pred_taken) && ((random_mt.random<int>() & 31) != 0)) {
+ alloc = false;
+ }
+}
+
+int
+TAGE_SC_L_TAGE::calcDep(TAGEBase::BranchInfo* bi)
+{
+ int a = 1;
+ if ((random_mt.random<int>() & 127) < 32) {
+ a = 2;
+ }
+ return ((((bi->hitBank - 1 + 2 * a) & 0xffe)) ^
+ (random_mt.random<int>() & 1));
+}
+
+void
+TAGE_SC_L_TAGE::handleUReset()
+{
+ //just the best formula for the Championship:
+ //In practice when one out of two entries are useful
+ if (tCounter < 0) {
+ tCounter = 0;
+ }
+
+ if (tCounter >= ((ULL(1) << logUResetPeriod))) {
+ // Update the u bits for the short tags table
+ for (int j = 0; j < (shortTagsTageFactor*(1<<logTagTableSize)); j++) {
+ resetUctr(gtable[1][j].u);
+ }
+
+ // Update the u bits for the long tags table
+ for (int j = 0; j < (longTagsTageFactor*(1<<logTagTableSize)); j++) {
+ resetUctr(gtable[firstLongTagTable][j].u);
+ }
+
+ tCounter = 0;
+ }
+}
+
+bool
+TAGE_SC_L_TAGE::getBimodePred(Addr pc, TAGEBase::BranchInfo* tage_bi) const
+{
+ TAGE_SC_L_TAGE::BranchInfo *bi =
+ static_cast<TAGE_SC_L_TAGE::BranchInfo *>(tage_bi);
+
+ int bim = (btablePrediction[bi->bimodalIndex] << 1)
+ + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries];
+
+ bi->highConf = (bim == 0) || (bim == 3);
+ bi->lowConf = ! bi->highConf;
+ bi->altConf = bi->highConf;
+ bi->medConf = false;
+ return TAGEBase::getBimodePred(pc, tage_bi);
+}
+
+void
+TAGE_SC_L_TAGE::extraAltCalc(TAGEBase::BranchInfo* bi)
+{
+ TAGE_SC_L_TAGE::BranchInfo *tage_scl_bi =
+ static_cast<TAGE_SC_L_TAGE::BranchInfo *>(bi);
+ int8_t ctr = gtable[bi->altBank][bi->altBankIndex].ctr;
+ tage_scl_bi->altConf = (abs(2*ctr + 1) > 1);
+}
+
+bool
+TAGE_SC_L::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b)
+{
+ TageSCLBranchInfo *bi = new TageSCLBranchInfo(*tage,
+ *statisticalCorrector,
+ *loopPredictor);
+ b = (void*)(bi);
+
+ bool pred_taken = tage->tagePredict(tid, branch_pc, cond_branch,
+ bi->tageBranchInfo);
+ pred_taken = loopPredictor->loopPredict(tid, branch_pc, cond_branch,
+ bi->lpBranchInfo, pred_taken,
+ instShiftAmt);
+
+ if (bi->lpBranchInfo->loopPredUsed) {
+ bi->tageBranchInfo->provider = LOOP;
+ }
+
+ TAGE_SC_L_TAGE::BranchInfo* tage_scl_bi =
+ static_cast<TAGE_SC_L_TAGE::BranchInfo *>(bi->tageBranchInfo);
+
+ // Copy the confidences computed by TAGE
+ bi->scBranchInfo->lowConf = tage_scl_bi->lowConf;
+ bi->scBranchInfo->highConf = tage_scl_bi->highConf;
+ bi->scBranchInfo->altConf = tage_scl_bi->altConf;
+ bi->scBranchInfo->medConf = tage_scl_bi->medConf;
+
+ bool use_tage_ctr = bi->tageBranchInfo->hitBank > 0;
+ int8_t tage_ctr = use_tage_ctr ?
+ tage->getCtr(tage_scl_bi->hitBank, tage_scl_bi->hitBankIndex) : 0;
+ bool bias = (bi->tageBranchInfo->longestMatchPred !=
+ bi->tageBranchInfo->altTaken);
+
+ pred_taken = statisticalCorrector->scPredict(tid, branch_pc, cond_branch,
+ bi->scBranchInfo, pred_taken, bias, use_tage_ctr, tage_ctr,
+ tage->getTageCtrBits(), bi->tageBranchInfo->hitBank,
+ bi->tageBranchInfo->altBank, tage->getPathHist(tid));
+
+ if (bi->scBranchInfo->usedScPred) {
+ bi->tageBranchInfo->provider = SC;
+ }
+
+ // record final prediction
+ bi->lpBranchInfo->predTaken = pred_taken;
+
+ return pred_taken;
+}
+
+void
+TAGE_SC_L::update(ThreadID tid, Addr branch_pc, bool taken, void *bp_history,
+ bool squashed, const StaticInstPtr & inst, Addr corrTarget)
+{
+ assert(bp_history);
+
+ TageSCLBranchInfo* bi = static_cast<TageSCLBranchInfo*>(bp_history);
+ TAGE_SC_L_TAGE::BranchInfo* tage_bi =
+ static_cast<TAGE_SC_L_TAGE::BranchInfo *>(bi->tageBranchInfo);
+
+ assert(corrTarget != MaxAddr);
+
+ if (squashed) {
+ if (tage->isSpeculativeUpdateEnabled()) {
+ // This restores the global history, then update it
+ // and recomputes the folded histories.
+ tage->squash(tid, taken, tage_bi, corrTarget);
+ if (bi->tageBranchInfo->condBranch) {
+ loopPredictor->squashLoop(bi->lpBranchInfo);
+ }
+ }
+ return;
+ }
+
+ int nrand = random_mt.random<int>() & 3;
+ if (tage_bi->condBranch) {
+ DPRINTF(TageSCL, "Updating tables for branch:%lx; taken?:%d\n",
+ branch_pc, taken);
+ tage->updateStats(taken, bi->tageBranchInfo);
+
+ loopPredictor->updateStats(taken, bi->lpBranchInfo);
+
+ statisticalCorrector->updateStats(taken, bi->scBranchInfo);
+
+ bool bias = (bi->tageBranchInfo->longestMatchPred !=
+ bi->tageBranchInfo->altTaken);
+ statisticalCorrector->condBranchUpdate(tid, branch_pc, taken,
+ bi->scBranchInfo, corrTarget, bias, bi->tageBranchInfo->hitBank,
+ bi->tageBranchInfo->altBank, tage->getPathHist(tid));
+
+ loopPredictor->condBranchUpdate(tid, branch_pc, taken,
+ bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt);
+
+ tage->condBranchUpdate(tid, branch_pc, taken, bi->tageBranchInfo,
+ nrand, corrTarget, bi->lpBranchInfo->predTaken);
+ }
+
+ if (!tage->isSpeculativeUpdateEnabled()) {
+ int brtype = inst->isDirectCtrl() ? 0 : 2;
+ if (! inst->isUncondCtrl()) {
+ ++brtype;
+ }
+
+ statisticalCorrector->scHistoryUpdate(branch_pc, brtype, taken,
+ bi->scBranchInfo, corrTarget);
+
+ tage->updateHistories(tid, branch_pc, taken, bi->tageBranchInfo, false,
+ inst, corrTarget);
+ }
+
+ delete bi;
+}
+
+void
+TAGE_SC_L::regStats()
+{
+ LTAGE::regStats();
+}
--- /dev/null
+/*
+ * 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
+ *
+ */
+
+/*
+ * TAGE-SC-L branch predictor base class (devised by Andre Seznec)
+ * It consits of a TAGE + a statistical corrector (SC) + a loop predictor (L)
+ */
+
+#ifndef __CPU_PRED_TAGE_SC_L
+#define __CPU_PRED_TAGE_SC_L
+
+#include "cpu/pred/ltage.hh"
+#include "cpu/pred/statistical_corrector.hh"
+#include "params/TAGE_SC_L.hh"
+#include "params/TAGE_SC_L_LoopPredictor.hh"
+#include "params/TAGE_SC_L_TAGE.hh"
+
+class TAGE_SC_L_TAGE : public TAGEBase {
+ const unsigned firstLongTagTable;
+ const unsigned longTagsSize;
+ const unsigned shortTagsSize;
+
+ const unsigned logTagTableSize;
+
+ const unsigned shortTagsTageFactor;
+ const unsigned longTagsTageFactor;
+
+ const bool truncatePathHist;
+
+ public:
+ struct BranchInfo : public TAGEBase::BranchInfo {
+ bool lowConf;
+ bool highConf;
+ bool altConf;
+ bool medConf;
+ BranchInfo(TAGEBase &tage) : TAGEBase::BranchInfo(tage),
+ lowConf(false), highConf(false), altConf(false), medConf(false)
+ {}
+ virtual ~BranchInfo()
+ {}
+ };
+
+ virtual TAGEBase::BranchInfo *makeBranchInfo() override;
+
+ TAGE_SC_L_TAGE(const TAGE_SC_L_TAGEParams *p)
+ : TAGEBase(p),
+ firstLongTagTable(p->firstLongTagTable),
+ longTagsSize(p->longTagsSize),
+ shortTagsSize(p->shortTagsSize),
+ logTagTableSize(p->logTagTableSize),
+ shortTagsTageFactor(p->shortTagsTageFactor),
+ longTagsTageFactor(p->longTagsTageFactor),
+ truncatePathHist(p->truncatePathHist)
+ {}
+
+ void calculateParameters() override;
+
+ void buildTageTables() override;
+
+ void calculateIndicesAndTags(
+ ThreadID tid, Addr branch_pc, TAGEBase::BranchInfo* bi) override;
+
+ unsigned getUseAltIdx(TAGEBase::BranchInfo* bi) override;
+
+ void updateHistories(
+ ThreadID tid, Addr branch_pc, bool taken, TAGEBase::BranchInfo* b,
+ bool speculative, const StaticInstPtr &inst,
+ Addr target) override;
+
+ int bindex(Addr pc_in) const override;
+ int gindex(ThreadID tid, Addr pc, int bank) const override;
+ virtual int gindex_ext(int index, int bank) const = 0;
+ int F(int phist, int size, int bank) const override;
+
+ virtual uint16_t gtag(ThreadID tid, Addr pc, int bank) const override = 0;
+
+ void squash(ThreadID tid, bool taken, TAGEBase::BranchInfo *bi,
+ Addr target) override;
+
+ void updatePathAndGlobalHistory(
+ ThreadHistory & tHist, int brtype, bool taken,
+ Addr branch_pc, Addr target);
+
+ void adjustAlloc(bool & alloc, bool taken, bool pred_taken) override;
+
+ virtual void handleAllocAndUReset(bool alloc, bool taken,
+ TAGEBase::BranchInfo* bi, int nrand) override = 0;
+
+ void handleUReset() override;
+
+ virtual void handleTAGEUpdate(
+ Addr branch_pc, bool taken, TAGEBase::BranchInfo* bi) override = 0;
+
+ int calcDep(TAGEBase::BranchInfo* bi);
+
+ bool getBimodePred(Addr branch_pc,
+ TAGEBase::BranchInfo* tage_bi) const override;
+
+ void extraAltCalc(TAGEBase::BranchInfo* bi) override;
+
+};
+
+class TAGE_SC_L_LoopPredictor : public LoopPredictor
+{
+ public:
+ TAGE_SC_L_LoopPredictor(TAGE_SC_L_LoopPredictorParams *p)
+ : LoopPredictor(p)
+ {}
+
+ virtual bool calcConf(int index) const override;
+ virtual bool optionalAgeInc() const override;
+};
+
+class TAGE_SC_L: public LTAGE
+{
+ StatisticalCorrector *statisticalCorrector;
+ public:
+ TAGE_SC_L(const TAGE_SC_LParams *params);
+
+ bool predict(
+ ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) override;
+
+ void regStats() override;
+
+ void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
+ bool squashed, const StaticInstPtr & inst,
+ Addr corrTarget = MaxAddr) override;
+
+ protected:
+
+ struct TageSCLBranchInfo : public LTageBranchInfo
+ {
+ StatisticalCorrector::BranchInfo *scBranchInfo;
+
+ TageSCLBranchInfo(TAGEBase &tage, StatisticalCorrector &sc,
+ LoopPredictor &lp)
+ : LTageBranchInfo(tage, lp), scBranchInfo(sc.makeBranchInfo())
+ {}
+
+ virtual ~TageSCLBranchInfo()
+ {
+ delete scBranchInfo;
+ }
+ };
+
+ // more provider types
+ enum {
+ SC = LAST_LTAGE_PROVIDER_TYPE + 1
+ };
+
+};
+
+#endif // __CPU_PRED_TAGE_SC_L
+
--- /dev/null
+/*
+ * 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
+ *
+ */
+
+/*
+ * 64KB TAGE-SC-L branch predictor (devised by Andre Seznec)
+ */
+
+#include "cpu/pred/tage_sc_l_64KB.hh"
+
+TAGE_SC_L_64KB_StatisticalCorrector::TAGE_SC_L_64KB_StatisticalCorrector(
+ TAGE_SC_L_64KB_StatisticalCorrectorParams *p)
+ : StatisticalCorrector(p),
+ numEntriesSecondLocalHistories(p->numEntriesSecondLocalHistories),
+ numEntriesThirdLocalHistories(p->numEntriesThirdLocalHistories),
+ pnb(p->pnb),
+ logPnb(p->logPnb),
+ pm(p->pm),
+ snb(p->snb),
+ logSnb(p->logSnb),
+ sm(p->sm),
+ tnb(p->tnb),
+ logTnb(p->logTnb),
+ tm(p->tm),
+ imnb(p->imnb),
+ logImnb(p->logImnb),
+ imm(p->imm)
+{
+ initGEHLTable(pnb, pm, pgehl, logPnb, wp, 7);
+ initGEHLTable(snb, sm, sgehl, logSnb, ws, 7);
+ initGEHLTable(tnb, tm, tgehl, logTnb, wt, 7);
+ initGEHLTable(imnb, imm, imgehl, logImnb, wim, 0);
+
+}
+
+TAGE_SC_L_64KB_StatisticalCorrector::SCThreadHistory*
+TAGE_SC_L_64KB_StatisticalCorrector::makeThreadHistory()
+{
+ SC_64KB_ThreadHistory *sh = new SC_64KB_ThreadHistory();
+
+ sh->setNumOrdinalHistories(3);
+ sh->initLocalHistory(1, numEntriesFirstLocalHistories, 2);
+ sh->initLocalHistory(2, numEntriesSecondLocalHistories, 5);
+ sh->initLocalHistory(3, numEntriesThirdLocalHistories, logTnb);
+
+ sh->imHist.resize(1 << im[0]);
+ return sh;
+}
+
+unsigned
+TAGE_SC_L_64KB_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) +
+ ((branch_pc^(branch_pc>>2))<<7)) & ((1<<logBias) -1);
+}
+
+int
+TAGE_SC_L_64KB_StatisticalCorrector::gPredictions(ThreadID tid, Addr branch_pc,
+ BranchInfo* bi, int & lsum, int64_t pathHist)
+{
+ SC_64KB_ThreadHistory *sh =
+ static_cast<SC_64KB_ThreadHistory *>(scHistory);
+
+ lsum += gPredict(
+ (branch_pc << 1) + bi->predBeforeSC, sh->bwHist, bwm,
+ bwgehl, bwnb, logBwnb, wbw);
+
+ lsum += gPredict(
+ branch_pc, pathHist, pm, pgehl, pnb, logPnb, wp);
+
+ lsum += gPredict(
+ branch_pc, sh->getLocalHistory(1, branch_pc), lm,
+ lgehl, lnb, logLnb, wl);
+
+ lsum += gPredict(
+ branch_pc, sh->getLocalHistory(2, branch_pc), sm,
+ sgehl, snb, logSnb, ws);
+
+ lsum += gPredict(
+ branch_pc, sh->getLocalHistory(3, branch_pc), tm,
+ tgehl, tnb, logTnb, wt);
+
+ lsum += gPredict(
+ branch_pc, sh->imHist[scHistory->imliCount], imm,
+ imgehl, imnb, logImnb, wim);
+
+ lsum += gPredict(
+ branch_pc, sh->imliCount, im, igehl, inb, logInb, wi);
+
+ int thres = (updateThreshold>>3) + pUpdateThreshold[getIndUpd(branch_pc)]
+ + 12*((wb[getIndUpds(branch_pc)] >= 0) + (wp[getIndUpds(branch_pc)] >= 0)
+ + (ws[getIndUpds(branch_pc)] >= 0) + (wt[getIndUpds(branch_pc)] >= 0)
+ + (wl[getIndUpds(branch_pc)] >= 0) + (wbw[getIndUpds(branch_pc)] >= 0)
+ + (wi[getIndUpds(branch_pc)] >= 0));
+
+ return thres;
+}
+
+int
+TAGE_SC_L_64KB_StatisticalCorrector::gIndexLogsSubstr(int nbr, int i)
+{
+ return (i >= (nbr - 2)) ? 1 : 0;
+}
+
+void
+TAGE_SC_L_64KB_StatisticalCorrector::scHistoryUpdate(Addr branch_pc,
+ int brtype, bool taken, BranchInfo* tage_bi, Addr corrTarget)
+{
+ // Non speculative SC histories update
+ if (brtype & 1) {
+ SC_64KB_ThreadHistory *sh =
+ static_cast<SC_64KB_ThreadHistory *>(scHistory);
+ int64_t imliCount = sh->imliCount;
+ sh->imHist[imliCount] = (sh->imHist[imliCount] << 1)
+ + taken;
+ sh->updateLocalHistory(2, branch_pc, taken, branch_pc & 15);
+ sh->updateLocalHistory(3, branch_pc, taken);
+ }
+
+ StatisticalCorrector::scHistoryUpdate(branch_pc, brtype, taken, tage_bi,
+ corrTarget);
+}
+
+void
+TAGE_SC_L_64KB_StatisticalCorrector::gUpdates(ThreadID tid, Addr pc,
+ bool taken, BranchInfo* bi, int64_t phist)
+{
+ SC_64KB_ThreadHistory *sh =
+ static_cast<SC_64KB_ThreadHistory *>(scHistory);
+
+ gUpdate((pc << 1) + bi->predBeforeSC, taken, sh->bwHist, bwm,
+ bwgehl, bwnb, logBwnb, wbw, bi);
+
+ gUpdate(pc, taken, phist, pm,
+ pgehl, pnb, logPnb, wp, bi);
+
+ gUpdate(pc, taken, sh->getLocalHistory(1, pc), lm,
+ lgehl, lnb, logLnb, wl, bi);
+
+ gUpdate(pc, taken, sh->getLocalHistory(2, pc), sm,
+ sgehl, snb, logSnb, ws, bi);
+
+ gUpdate(pc, taken, sh->getLocalHistory(3, pc), tm,
+ tgehl, tnb, logTnb, wt, bi);
+
+ gUpdate(pc, taken, sh->imHist[scHistory->imliCount], imm,
+ imgehl, imnb, logImnb, wim, bi);
+
+ gUpdate(pc, taken, sh->imliCount, im,
+ igehl, inb, logInb, wi, bi);
+}
+
+TAGE_SC_L_64KB_StatisticalCorrector*
+TAGE_SC_L_64KB_StatisticalCorrectorParams::create()
+{
+ return new TAGE_SC_L_64KB_StatisticalCorrector(this);
+}
+
+int
+TAGE_SC_L_TAGE_64KB::gindex_ext(int index, int bank) const
+{
+ return index;
+}
+
+uint16_t
+TAGE_SC_L_TAGE_64KB::gtag(ThreadID tid, Addr pc, int bank) const
+{
+ // very similar to the TAGE implementation, but w/o shifting the pc
+ int tag = pc ^ threadHistory[tid].computeTags[0][bank].comp ^
+ (threadHistory[tid].computeTags[1][bank].comp << 1);
+
+ return (tag & ((ULL(1) << tagTableTagWidths[bank]) - 1));
+}
+
+void
+TAGE_SC_L_TAGE_64KB::handleAllocAndUReset(
+ bool alloc, bool taken, TAGEBase::BranchInfo* bi, int nrand)
+{
+ if (! alloc) {
+ return;
+ }
+
+ int penalty = 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 (noSkip[i]) {
+ if (gtable[i][bi->tableIndices[i]].u == 0) {
+ int8_t ctr = gtable[i][bi->tableIndices[i]].ctr;
+ if (abs (2 * ctr + 1) <= 3) {
+ gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i];
+ gtable[i][bi->tableIndices[i]].ctr = taken ? 0 : -1;
+ numAllocated++;
+ maxAllocReached = (numAllocated == maxNumAlloc);
+ I += 2;
+ break;
+ } else {
+ if (gtable[i][bi->tableIndices[i]].ctr > 0) {
+ gtable[i][bi->tableIndices[i]].ctr--;
+ } else {
+ gtable[i][bi->tableIndices[i]].ctr++;
+ }
+ }
+ } else {
+ penalty++;
+ }
+ }
+ }
+ if (maxAllocReached) {
+ break;
+ }
+ }
+
+ tCounter += (penalty - 2 * numAllocated);
+
+ handleUReset();
+}
+
+void
+TAGE_SC_L_TAGE_64KB::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) {
+ ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken,
+ tagTableCounterBits);
+ }
+ if (bi->altBank == 0){
+ baseUpdate(branch_pc, taken, bi);
+ }
+ }
+ }
+
+ 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_64KB*
+TAGE_SC_L_TAGE_64KBParams::create()
+{
+ return new TAGE_SC_L_TAGE_64KB(this);
+}
+
+TAGE_SC_L_64KB::TAGE_SC_L_64KB(const TAGE_SC_L_64KBParams *params)
+ : TAGE_SC_L(params)
+{
+}
+
+TAGE_SC_L_64KB*
+TAGE_SC_L_64KBParams::create()
+{
+ return new TAGE_SC_L_64KB(this);
+}
--- /dev/null
+/*
+ * 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
+ *
+ */
+
+/*
+ * 64KB TAGE-SC-L branch predictor (devised by Andre Seznec)
+ *
+ * Most of the code in this file has been adapted from cbp64KB/predictor.h in
+ * http://www.jilp.org/cbp2016/code/AndreSeznecLimited.tar.gz
+ */
+
+#ifndef __CPU_PRED_TAGE_SC_L_64KB
+#define __CPU_PRED_TAGE_SC_L_64KB
+
+#include "cpu/pred/tage_sc_l.hh"
+#include "params/TAGE_SC_L_64KB.hh"
+#include "params/TAGE_SC_L_64KB_StatisticalCorrector.hh"
+#include "params/TAGE_SC_L_TAGE_64KB.hh"
+
+class TAGE_SC_L_TAGE_64KB : public TAGE_SC_L_TAGE {
+ public:
+ TAGE_SC_L_TAGE_64KB(const TAGE_SC_L_TAGE_64KBParams *p) : TAGE_SC_L_TAGE(p)
+ {}
+
+ int gindex_ext(int index, int bank) const override;
+
+ uint16_t gtag(ThreadID tid, Addr pc, int bank) const override;
+
+ void handleAllocAndUReset(
+ bool alloc, bool taken, TAGEBase::BranchInfo* bi, int nrand) override;
+
+ void handleTAGEUpdate(
+ Addr branch_pc, bool taken, TAGEBase::BranchInfo* bi) override;
+};
+
+class TAGE_SC_L_64KB_StatisticalCorrector : public StatisticalCorrector
+{
+ const unsigned numEntriesSecondLocalHistories;
+ const unsigned numEntriesThirdLocalHistories;
+
+ // global branch history variation GEHL
+ const unsigned pnb;
+ const unsigned logPnb;
+ std::vector<int> pm;
+ std::vector<int8_t> * pgehl;
+ std::vector<int8_t> wp;
+
+ // Second local history GEHL
+ const unsigned snb;
+ const unsigned logSnb;
+ std::vector<int> sm;
+ std::vector<int8_t> * sgehl;
+ std::vector<int8_t> ws;
+
+ // Third local history GEHL
+ const unsigned tnb;
+ const unsigned logTnb;
+ std::vector<int> tm;
+ std::vector<int8_t> * tgehl;
+ std::vector<int8_t> wt;
+
+ // Second IMLI GEHL
+ const unsigned imnb;
+ const unsigned logImnb;
+ std::vector<int> imm;
+ std::vector<int8_t> * imgehl;
+ std::vector<int8_t> wim;
+
+ struct SC_64KB_ThreadHistory : public SCThreadHistory
+ {
+ std::vector<int64_t> imHist;
+ };
+
+ SCThreadHistory *makeThreadHistory() override;
+
+ public:
+ TAGE_SC_L_64KB_StatisticalCorrector(
+ TAGE_SC_L_64KB_StatisticalCorrectorParams *p);
+
+ unsigned getIndBiasBank(Addr branch_pc, BranchInfo* bi, int hitBank,
+ int altBank) const override;
+
+ int gPredictions(ThreadID tid, Addr branch_pc, BranchInfo* bi,
+ int & lsum, int64_t phist) override;
+
+ int gIndexLogsSubstr(int nbr, int i) override;
+
+ void scHistoryUpdate(Addr branch_pc, int brtype, bool taken,
+ BranchInfo * tage_bi, Addr corrTarget) override;
+
+ void gUpdates(ThreadID tid, Addr pc, bool taken, BranchInfo* bi,
+ int64_t phist) override;
+};
+
+class TAGE_SC_L_64KB : public TAGE_SC_L
+{
+ public:
+ TAGE_SC_L_64KB(const TAGE_SC_L_64KBParams *params);
+};
+
+#endif // __CPU_PRED_TAGE_SC_L_64KB
+
--- /dev/null
+/*
+ * 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<<logBias) -1);
+}
+
+int
+TAGE_SC_L_8KB_StatisticalCorrector::gPredictions(
+ ThreadID tid, Addr branch_pc, BranchInfo* bi, int & lsum, int64_t phist)
+{
+ SC_8KB_ThreadHistory *sh = static_cast<SC_8KB_ThreadHistory *>(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, int brtype,
+ bool taken, BranchInfo * tage_bi, Addr corrTarget)
+{
+ // Non speculative SC histories update
+ if (brtype & 1) {
+ SC_8KB_ThreadHistory *sh =
+ static_cast<SC_8KB_ThreadHistory *>(scHistory);
+ sh->globalHist = (sh->globalHist << 1) + taken;
+ }
+
+ StatisticalCorrector::scHistoryUpdate(branch_pc, brtype, 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<SC_8KB_ThreadHistory *>(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<int>() & 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<int>() & 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);
+}
--- /dev/null
+/*
+ * 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)
+ */
+
+#ifndef __CPU_PRED_TAGE_SC_L_8KB
+#define __CPU_PRED_TAGE_SC_L_8KB
+
+#include "cpu/pred/tage_sc_l.hh"
+#include "params/TAGE_SC_L_8KB.hh"
+#include "params/TAGE_SC_L_8KB_StatisticalCorrector.hh"
+#include "params/TAGE_SC_L_TAGE_8KB.hh"
+
+class TAGE_SC_L_TAGE_8KB : public TAGE_SC_L_TAGE
+{
+ public:
+ TAGE_SC_L_TAGE_8KB(const TAGE_SC_L_TAGE_8KBParams *p) : TAGE_SC_L_TAGE(p)
+ {}
+
+ void initFoldedHistories(ThreadHistory & history) override;
+ int gindex_ext(int index, int bank) const override;
+
+ uint16_t gtag(ThreadID tid, Addr pc, int bank) const override;
+
+ void handleAllocAndUReset(
+ bool alloc, bool taken, TAGEBase::BranchInfo* bi, int nrand) override;
+
+ void handleTAGEUpdate(
+ Addr branch_pc, bool taken, TAGEBase::BranchInfo* bi) override;
+
+ void resetUctr(uint8_t & u) override;
+};
+
+class TAGE_SC_L_8KB_StatisticalCorrector : public StatisticalCorrector
+{
+ // global branch history GEHL
+ const unsigned gnb;
+ const unsigned logGnb;
+ std::vector<int> gm;
+ std::vector<int8_t> * ggehl;
+ std::vector<int8_t> wg;
+
+ struct SC_8KB_ThreadHistory : public SCThreadHistory
+ {
+ SC_8KB_ThreadHistory() {
+ globalHist = 0;
+ }
+ int64_t globalHist; // global history
+ };
+
+ SCThreadHistory *makeThreadHistory() override;
+
+ public:
+ TAGE_SC_L_8KB_StatisticalCorrector(
+ TAGE_SC_L_8KB_StatisticalCorrectorParams *p);
+
+ unsigned getIndBiasBank( Addr branch_pc, BranchInfo* bi, int hitBank,
+ int altBank) const override;
+
+ int gPredictions( ThreadID tid, Addr branch_pc,
+ BranchInfo* bi, int & lsum, int64_t phist) override;
+
+ int gIndexLogsSubstr(int nbr, int i) override;
+
+ void scHistoryUpdate(
+ Addr branch_pc, int brtype, bool taken, BranchInfo * tage_bi,
+ Addr corrTarget) override;
+
+ void gUpdates(ThreadID tid, Addr pc, bool taken, BranchInfo* bi,
+ int64_t phist) override;
+};
+
+class TAGE_SC_L_8KB : public TAGE_SC_L
+{
+ public:
+ TAGE_SC_L_8KB(const TAGE_SC_L_8KBParams *params);
+};
+
+#endif // __CPU_PRED_TAGE_SC_L_8KB
+