/* * 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 "cpu/static_inst.hh" #include "sim/sim_object.hh" struct StatisticalCorrectorParams; class StatisticalCorrector : public SimObject { protected: template inline void ctrUpdate(T & ctr, bool taken, int nbits) { assert(nbits <= sizeof(T) << 3); if (nbits > 0) { if (taken) { if (ctr < ((1 << (nbits - 1)) - 1)) ctr++; } else { if (ctr > -(1 << (nbits - 1))) ctr--; } } } // 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 [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 * localHistories; std::vector 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 bwm; std::vector * bwgehl; std::vector wbw; // First local history GEHL const unsigned lnb; const unsigned logLnb; std::vector lm; std::vector * lgehl; std::vector wl; // IMLI GEHL const unsigned inb; const unsigned logInb; std::vector im; std::vector * igehl; std::vector wi; std::vector bias; std::vector biasSK; std::vector biasBank; std::vector wb; int updateThreshold; std::vector 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(); virtual void initBias(); virtual 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, int init_lsum = 0); virtual unsigned getIndBias(Addr branch_pc, BranchInfo* bi, bool b) const; virtual unsigned getIndBiasSK(Addr branch_pc, BranchInfo* bi) const; virtual unsigned getIndBiasBank( Addr branch_pc, BranchInfo* bi, int hitBank, int altBank) const = 0; virtual 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 & length, std::vector * tab, int nbr, int logs, std::vector & w); virtual void gUpdate( Addr branch_pc, bool taken, int64_t hist, std::vector & length, std::vector * tab, int nbr, int logs, std::vector & w, BranchInfo* bi); void initGEHLTable( unsigned numLenghts, std::vector lengths, std::vector * & table, unsigned logNumEntries, std::vector & w, int8_t wInitValue); virtual void scHistoryUpdate( Addr branch_pc, const StaticInstPtr &inst , 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); virtual void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, BranchInfo *bi, Addr corrTarget, bool bias_bit, int hitBank, int altBank, int64_t phist); virtual size_t getSizeInBits() const; }; #endif//__CPU_PRED_STATISTICAL_CORRECTOR_HH