blob: d5b32cc506bee78e8185812a90c6ff5b6b7813e4 [file] [log] [blame]
/*
* 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"
namespace gem5
{
namespace branch_prediction
{
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),
stats(this)
{
wb.resize(1 << logSizeUps, 4);
initGEHLTable(lnb, lm, lgehl, logLnb, wl, p.lWeightInitValue);
initGEHLTable(bwnb, bwm, bwgehl, logBwnb, wbw, p.bwWeightInitValue);
initGEHLTable(inb, im, igehl, logInb, wi, p.iWeightInitValue);
updateThreshold = 35 << 3;
pUpdateThreshold.resize(1 << logSizeUp, p.initialUpdateThresholdValue);
bias.resize(1 << logBias);
biasSK.resize(1 << logBias);
biasBank.resize(1 << logBias);
}
StatisticalCorrector::BranchInfo*
StatisticalCorrector::makeBranchInfo()
{
return new BranchInfo();
}
StatisticalCorrector::SCThreadHistory*
StatisticalCorrector::makeThreadHistory()
{
return new SCThreadHistory();
}
void
StatisticalCorrector::initBias()
{
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;
}
}
}
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, int init_lsum)
{
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 = init_lsum;
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,
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) {
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) {
stats.correct++;
} else {
stats.wrong++;
}
}
void
StatisticalCorrector::init()
{
scHistory = makeThreadHistory();
initBias();
}
size_t
StatisticalCorrector::getSizeInBits() const
{
// Not implemented
return 0;
}
StatisticalCorrector::StatisticalCorrectorStats::StatisticalCorrectorStats(
statistics::Group *parent)
: statistics::Group(parent),
ADD_STAT(correct, statistics::units::Count::get(),
"Number of time the SC predictor is the provider and the "
"prediction is correct"),
ADD_STAT(wrong, statistics::units::Count::get(),
"Number of time the SC predictor is the provider and the "
"prediction is wrong")
{
}
} // namespace branch_prediction
} // namespace gem5