Change-Id: I387b2e9f6ecf62757242056f732bd443c457ebea Signed-off-by: Hoa Nguyen <hoanguyen@ucdavis.edu> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/39095 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu> Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
411 lines
13 KiB
C++
411 lines
13 KiB
C++
/*
|
|
* 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),
|
|
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(
|
|
Stats::Group *parent)
|
|
: Stats::Group(parent),
|
|
ADD_STAT(correct, UNIT_COUNT,
|
|
"Number of time the SC predictor is the provider and the "
|
|
"prediction is correct"),
|
|
ADD_STAT(wrong, UNIT_COUNT,
|
|
"Number of time the SC predictor is the provider and the "
|
|
"prediction is wrong")
|
|
{
|
|
}
|