blob: f96684346bce842189b2ad1d55905db70fb35200 [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
*/
#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