113685Sjavier.bueno@metempsy.com/*
213685Sjavier.bueno@metempsy.com * Copyright (c) 2018 Metempsy Technology Consulting
313685Sjavier.bueno@metempsy.com * All rights reserved.
413685Sjavier.bueno@metempsy.com *
513685Sjavier.bueno@metempsy.com * Copyright (c) 2006 INRIA (Institut National de Recherche en
613685Sjavier.bueno@metempsy.com * Informatique et en Automatique  / French National Research Institute
713685Sjavier.bueno@metempsy.com * for Computer Science and Applied Mathematics)
813685Sjavier.bueno@metempsy.com *
913685Sjavier.bueno@metempsy.com * All rights reserved.
1013685Sjavier.bueno@metempsy.com *
1113685Sjavier.bueno@metempsy.com * Redistribution and use in source and binary forms, with or without
1213685Sjavier.bueno@metempsy.com * modification, are permitted provided that the following conditions are
1313685Sjavier.bueno@metempsy.com * met: redistributions of source code must retain the above copyright
1413685Sjavier.bueno@metempsy.com * notice, this list of conditions and the following disclaimer;
1513685Sjavier.bueno@metempsy.com * redistributions in binary form must reproduce the above copyright
1613685Sjavier.bueno@metempsy.com * notice, this list of conditions and the following disclaimer in the
1713685Sjavier.bueno@metempsy.com * documentation and/or other materials provided with the distribution;
1813685Sjavier.bueno@metempsy.com * neither the name of the copyright holders nor the names of its
1913685Sjavier.bueno@metempsy.com * contributors may be used to endorse or promote products derived from
2013685Sjavier.bueno@metempsy.com * this software without specific prior written permission.
2113685Sjavier.bueno@metempsy.com *
2213685Sjavier.bueno@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2313685Sjavier.bueno@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2413685Sjavier.bueno@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2513685Sjavier.bueno@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2613685Sjavier.bueno@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2713685Sjavier.bueno@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2813685Sjavier.bueno@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2913685Sjavier.bueno@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3013685Sjavier.bueno@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3113685Sjavier.bueno@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3213685Sjavier.bueno@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3313685Sjavier.bueno@metempsy.com *
3413685Sjavier.bueno@metempsy.com * Author: André Seznec, Pau Cabre, Javier Bueno
3513685Sjavier.bueno@metempsy.com *
3613685Sjavier.bueno@metempsy.com */
3713685Sjavier.bueno@metempsy.com
3813685Sjavier.bueno@metempsy.com/*
3913685Sjavier.bueno@metempsy.com * Statistical corrector base class
4013685Sjavier.bueno@metempsy.com */
4113685Sjavier.bueno@metempsy.com
4213685Sjavier.bueno@metempsy.com#ifndef __CPU_PRED_STATISTICAL_CORRECTOR_HH
4313685Sjavier.bueno@metempsy.com#define __CPU_PRED_STATISTICAL_CORRECTOR_HH
4413685Sjavier.bueno@metempsy.com
4513685Sjavier.bueno@metempsy.com#include "base/statistics.hh"
4613685Sjavier.bueno@metempsy.com#include "base/types.hh"
4714081Sjavier.bueno@metempsy.com#include "cpu/static_inst.hh"
4813685Sjavier.bueno@metempsy.com#include "sim/sim_object.hh"
4913685Sjavier.bueno@metempsy.com
5013685Sjavier.bueno@metempsy.comstruct StatisticalCorrectorParams;
5113685Sjavier.bueno@metempsy.com
5213685Sjavier.bueno@metempsy.comclass StatisticalCorrector : public SimObject
5313685Sjavier.bueno@metempsy.com{
5414081Sjavier.bueno@metempsy.com  protected:
5513685Sjavier.bueno@metempsy.com    template<typename T>
5613685Sjavier.bueno@metempsy.com    inline void ctrUpdate(T & ctr, bool taken, int nbits) {
5713685Sjavier.bueno@metempsy.com        assert(nbits <= sizeof(T) << 3);
5814081Sjavier.bueno@metempsy.com        if (nbits > 0) {
5914081Sjavier.bueno@metempsy.com            if (taken) {
6014081Sjavier.bueno@metempsy.com                if (ctr < ((1 << (nbits - 1)) - 1))
6114081Sjavier.bueno@metempsy.com                    ctr++;
6214081Sjavier.bueno@metempsy.com            } else {
6314081Sjavier.bueno@metempsy.com                if (ctr > -(1 << (nbits - 1)))
6414081Sjavier.bueno@metempsy.com                    ctr--;
6514081Sjavier.bueno@metempsy.com            }
6613685Sjavier.bueno@metempsy.com        }
6713685Sjavier.bueno@metempsy.com    }
6813685Sjavier.bueno@metempsy.com    // histories used for the statistical corrector
6913685Sjavier.bueno@metempsy.com    struct SCThreadHistory {
7013685Sjavier.bueno@metempsy.com        SCThreadHistory() {
7113685Sjavier.bueno@metempsy.com            bwHist = 0;
7213685Sjavier.bueno@metempsy.com            numOrdinalHistories = 0;
7313685Sjavier.bueno@metempsy.com            imliCount = 0;
7413685Sjavier.bueno@metempsy.com        }
7513685Sjavier.bueno@metempsy.com        int64_t bwHist;  // backward global history
7613685Sjavier.bueno@metempsy.com        int64_t imliCount;
7713685Sjavier.bueno@metempsy.com
7813685Sjavier.bueno@metempsy.com        void setNumOrdinalHistories(unsigned num)
7913685Sjavier.bueno@metempsy.com        {
8013685Sjavier.bueno@metempsy.com            numOrdinalHistories = num;
8113685Sjavier.bueno@metempsy.com            assert(num > 0);
8213685Sjavier.bueno@metempsy.com            shifts.resize(num);
8313685Sjavier.bueno@metempsy.com            localHistories = new std::vector<int64_t> [num];
8413685Sjavier.bueno@metempsy.com        }
8513685Sjavier.bueno@metempsy.com
8613685Sjavier.bueno@metempsy.com        void initLocalHistory(int ordinal, int numHistories, int shift)
8713685Sjavier.bueno@metempsy.com        {
8813685Sjavier.bueno@metempsy.com            assert((ordinal >= 1) && (ordinal <= numOrdinalHistories));
8913685Sjavier.bueno@metempsy.com            shifts[ordinal - 1] = shift;
9013685Sjavier.bueno@metempsy.com            assert(isPowerOf2(numHistories));
9113685Sjavier.bueno@metempsy.com            localHistories[ordinal - 1].resize(numHistories, 0);
9213685Sjavier.bueno@metempsy.com        }
9313685Sjavier.bueno@metempsy.com
9413685Sjavier.bueno@metempsy.com        int64_t getLocalHistory(int ordinal, Addr pc)
9513685Sjavier.bueno@metempsy.com        {
9613685Sjavier.bueno@metempsy.com            assert((ordinal >= 1) && (ordinal <= numOrdinalHistories));
9713685Sjavier.bueno@metempsy.com            unsigned idx = ordinal - 1;
9813685Sjavier.bueno@metempsy.com            return localHistories[idx][getEntry(pc, idx)];
9913685Sjavier.bueno@metempsy.com        }
10013685Sjavier.bueno@metempsy.com
10113685Sjavier.bueno@metempsy.com        void updateLocalHistory(
10213685Sjavier.bueno@metempsy.com            int ordinal, Addr branch_pc, bool taken, Addr extraXor = 0)
10313685Sjavier.bueno@metempsy.com        {
10413685Sjavier.bueno@metempsy.com            assert((ordinal >= 1) && (ordinal <= numOrdinalHistories));
10513685Sjavier.bueno@metempsy.com            unsigned idx = ordinal - 1;
10613685Sjavier.bueno@metempsy.com
10713685Sjavier.bueno@metempsy.com            unsigned entry = getEntry(branch_pc, idx);
10813685Sjavier.bueno@metempsy.com            int64_t hist =  (localHistories[idx][entry] << 1) + taken;
10913685Sjavier.bueno@metempsy.com
11013685Sjavier.bueno@metempsy.com            if (extraXor) {
11113685Sjavier.bueno@metempsy.com                hist = hist ^ extraXor;
11213685Sjavier.bueno@metempsy.com            }
11313685Sjavier.bueno@metempsy.com
11413685Sjavier.bueno@metempsy.com            localHistories[idx][entry] = hist;
11513685Sjavier.bueno@metempsy.com        }
11613685Sjavier.bueno@metempsy.com
11713685Sjavier.bueno@metempsy.com      private:
11813685Sjavier.bueno@metempsy.com        std::vector<int64_t> * localHistories;
11913685Sjavier.bueno@metempsy.com        std::vector<int> shifts;
12013685Sjavier.bueno@metempsy.com        unsigned numOrdinalHistories;
12113685Sjavier.bueno@metempsy.com
12213685Sjavier.bueno@metempsy.com        unsigned getEntry(Addr pc, unsigned idx)
12313685Sjavier.bueno@metempsy.com        {
12413685Sjavier.bueno@metempsy.com            return (pc ^ (pc >> shifts[idx])) & (localHistories[idx].size()-1);
12513685Sjavier.bueno@metempsy.com        }
12613685Sjavier.bueno@metempsy.com    };
12713685Sjavier.bueno@metempsy.com
12813685Sjavier.bueno@metempsy.com    // For SC history we use global (i.e. not per thread) non speculative
12913685Sjavier.bueno@metempsy.com    // histories, as some of the strucures needed are quite big and it is not
13013685Sjavier.bueno@metempsy.com    // reasonable to make them per thread and it would be difficult to
13113685Sjavier.bueno@metempsy.com    // rollback on miss-predictions
13213685Sjavier.bueno@metempsy.com    SCThreadHistory * scHistory;
13313685Sjavier.bueno@metempsy.com
13413685Sjavier.bueno@metempsy.com    const unsigned logBias;
13513685Sjavier.bueno@metempsy.com
13613685Sjavier.bueno@metempsy.com    const unsigned logSizeUp;
13713685Sjavier.bueno@metempsy.com    const unsigned logSizeUps;
13813685Sjavier.bueno@metempsy.com
13913685Sjavier.bueno@metempsy.com    const unsigned numEntriesFirstLocalHistories;
14013685Sjavier.bueno@metempsy.com
14113685Sjavier.bueno@metempsy.com    // global backward branch history GEHL
14213685Sjavier.bueno@metempsy.com    const unsigned bwnb;
14313685Sjavier.bueno@metempsy.com    const unsigned logBwnb;
14413685Sjavier.bueno@metempsy.com    std::vector<int> bwm;
14513685Sjavier.bueno@metempsy.com    std::vector<int8_t> * bwgehl;
14613685Sjavier.bueno@metempsy.com    std::vector<int8_t> wbw;
14713685Sjavier.bueno@metempsy.com
14813685Sjavier.bueno@metempsy.com    // First local history GEHL
14913685Sjavier.bueno@metempsy.com    const unsigned lnb;
15013685Sjavier.bueno@metempsy.com    const unsigned logLnb;
15113685Sjavier.bueno@metempsy.com    std::vector<int> lm;
15213685Sjavier.bueno@metempsy.com    std::vector<int8_t> * lgehl;
15313685Sjavier.bueno@metempsy.com    std::vector<int8_t> wl;
15413685Sjavier.bueno@metempsy.com
15513685Sjavier.bueno@metempsy.com    // IMLI GEHL
15613685Sjavier.bueno@metempsy.com    const unsigned inb;
15713685Sjavier.bueno@metempsy.com    const unsigned logInb;
15813685Sjavier.bueno@metempsy.com    std::vector<int> im;
15913685Sjavier.bueno@metempsy.com    std::vector<int8_t> * igehl;
16013685Sjavier.bueno@metempsy.com    std::vector<int8_t> wi;
16113685Sjavier.bueno@metempsy.com
16213685Sjavier.bueno@metempsy.com    std::vector<int8_t> bias;
16313685Sjavier.bueno@metempsy.com    std::vector<int8_t> biasSK;
16413685Sjavier.bueno@metempsy.com    std::vector<int8_t> biasBank;
16513685Sjavier.bueno@metempsy.com
16613685Sjavier.bueno@metempsy.com    std::vector<int8_t> wb;
16713685Sjavier.bueno@metempsy.com
16813685Sjavier.bueno@metempsy.com    int updateThreshold;
16913685Sjavier.bueno@metempsy.com    std::vector<int> pUpdateThreshold;
17013685Sjavier.bueno@metempsy.com
17113685Sjavier.bueno@metempsy.com    // The two counters used to choose between TAGE ang SC on High Conf
17213685Sjavier.bueno@metempsy.com    // TAGE/Low Conf SC
17313685Sjavier.bueno@metempsy.com    const unsigned chooserConfWidth;
17413685Sjavier.bueno@metempsy.com
17513685Sjavier.bueno@metempsy.com    const unsigned updateThresholdWidth;
17613685Sjavier.bueno@metempsy.com    const unsigned pUpdateThresholdWidth;
17713685Sjavier.bueno@metempsy.com
17813685Sjavier.bueno@metempsy.com    const unsigned extraWeightsWidth;
17913685Sjavier.bueno@metempsy.com
18013685Sjavier.bueno@metempsy.com    const unsigned scCountersWidth;
18113685Sjavier.bueno@metempsy.com
18213685Sjavier.bueno@metempsy.com    int8_t firstH;
18313685Sjavier.bueno@metempsy.com    int8_t secondH;
18413685Sjavier.bueno@metempsy.com
18513685Sjavier.bueno@metempsy.com    // stats
18613685Sjavier.bueno@metempsy.com    Stats::Scalar scPredictorCorrect;
18713685Sjavier.bueno@metempsy.com    Stats::Scalar scPredictorWrong;
18813685Sjavier.bueno@metempsy.com  public:
18913685Sjavier.bueno@metempsy.com    struct BranchInfo
19013685Sjavier.bueno@metempsy.com    {
19113685Sjavier.bueno@metempsy.com        BranchInfo() : lowConf(false), highConf(false), altConf(false),
19213685Sjavier.bueno@metempsy.com              medConf(false), scPred(false), lsum(0), thres(0),
19313685Sjavier.bueno@metempsy.com              predBeforeSC(false), usedScPred(false)
19413685Sjavier.bueno@metempsy.com        {}
19513685Sjavier.bueno@metempsy.com
19613685Sjavier.bueno@metempsy.com        // confidences calculated on tage and used on the statistical
19713685Sjavier.bueno@metempsy.com        // correction
19813685Sjavier.bueno@metempsy.com        bool lowConf;
19913685Sjavier.bueno@metempsy.com        bool highConf;
20013685Sjavier.bueno@metempsy.com        bool altConf;
20113685Sjavier.bueno@metempsy.com        bool medConf;
20213685Sjavier.bueno@metempsy.com
20313685Sjavier.bueno@metempsy.com        bool scPred;
20413685Sjavier.bueno@metempsy.com        int lsum;
20513685Sjavier.bueno@metempsy.com        int thres;
20613685Sjavier.bueno@metempsy.com        bool predBeforeSC;
20713685Sjavier.bueno@metempsy.com        bool usedScPred;
20813685Sjavier.bueno@metempsy.com    };
20913685Sjavier.bueno@metempsy.com
21013685Sjavier.bueno@metempsy.com    StatisticalCorrector(const StatisticalCorrectorParams *p);
21113685Sjavier.bueno@metempsy.com
21213685Sjavier.bueno@metempsy.com    virtual BranchInfo *makeBranchInfo();
21313685Sjavier.bueno@metempsy.com    virtual SCThreadHistory *makeThreadHistory();
21413685Sjavier.bueno@metempsy.com
21514081Sjavier.bueno@metempsy.com    virtual void initBias();
21614081Sjavier.bueno@metempsy.com
21714081Sjavier.bueno@metempsy.com    virtual bool scPredict(
21813685Sjavier.bueno@metempsy.com        ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo* bi,
21913685Sjavier.bueno@metempsy.com        bool prev_pred_taken, bool bias_bit, bool use_conf_ctr,
22013685Sjavier.bueno@metempsy.com        int8_t conf_ctr, unsigned conf_bits, int hitBank, int altBank,
22114081Sjavier.bueno@metempsy.com        int64_t phist, int init_lsum = 0);
22213685Sjavier.bueno@metempsy.com
22314081Sjavier.bueno@metempsy.com    virtual unsigned getIndBias(Addr branch_pc, BranchInfo* bi, bool b) const;
22413685Sjavier.bueno@metempsy.com
22514081Sjavier.bueno@metempsy.com    virtual unsigned getIndBiasSK(Addr branch_pc, BranchInfo* bi) const;
22613685Sjavier.bueno@metempsy.com
22713685Sjavier.bueno@metempsy.com    virtual unsigned getIndBiasBank( Addr branch_pc, BranchInfo* bi,
22813685Sjavier.bueno@metempsy.com        int hitBank, int altBank) const = 0;
22913685Sjavier.bueno@metempsy.com
23014081Sjavier.bueno@metempsy.com    virtual unsigned getIndUpd(Addr branch_pc) const;
23113685Sjavier.bueno@metempsy.com    unsigned getIndUpds(Addr branch_pc) const;
23213685Sjavier.bueno@metempsy.com
23313685Sjavier.bueno@metempsy.com    virtual int gPredictions(ThreadID tid, Addr branch_pc, BranchInfo* bi,
23413685Sjavier.bueno@metempsy.com        int & lsum, int64_t phist) = 0;
23513685Sjavier.bueno@metempsy.com
23613685Sjavier.bueno@metempsy.com    int64_t gIndex(Addr branch_pc, int64_t bhist, int logs, int nbr, int i);
23713685Sjavier.bueno@metempsy.com
23813685Sjavier.bueno@metempsy.com    virtual int gIndexLogsSubstr(int nbr, int i) = 0;
23913685Sjavier.bueno@metempsy.com
24013685Sjavier.bueno@metempsy.com    int gPredict(
24113685Sjavier.bueno@metempsy.com        Addr branch_pc, int64_t hist, std::vector<int> & length,
24213685Sjavier.bueno@metempsy.com        std::vector<int8_t> * tab, int nbr, int logs,
24313685Sjavier.bueno@metempsy.com        std::vector<int8_t> & w);
24413685Sjavier.bueno@metempsy.com
24514081Sjavier.bueno@metempsy.com    virtual void gUpdate(
24613685Sjavier.bueno@metempsy.com        Addr branch_pc, bool taken, int64_t hist, std::vector<int> & length,
24713685Sjavier.bueno@metempsy.com        std::vector<int8_t> * tab, int nbr, int logs,
24813685Sjavier.bueno@metempsy.com        std::vector<int8_t> & w, BranchInfo* bi);
24913685Sjavier.bueno@metempsy.com
25013685Sjavier.bueno@metempsy.com    void initGEHLTable(
25113685Sjavier.bueno@metempsy.com        unsigned numLenghts, std::vector<int> lengths,
25213685Sjavier.bueno@metempsy.com        std::vector<int8_t> * & table, unsigned logNumEntries,
25313685Sjavier.bueno@metempsy.com        std::vector<int8_t> & w, int8_t wInitValue);
25413685Sjavier.bueno@metempsy.com
25513685Sjavier.bueno@metempsy.com    virtual void scHistoryUpdate(
25614081Sjavier.bueno@metempsy.com        Addr branch_pc, const StaticInstPtr &inst , bool taken,
25714081Sjavier.bueno@metempsy.com        BranchInfo * tage_bi, Addr corrTarget);
25813685Sjavier.bueno@metempsy.com
25913685Sjavier.bueno@metempsy.com    virtual void gUpdates( ThreadID tid, Addr pc, bool taken, BranchInfo* bi,
26013685Sjavier.bueno@metempsy.com        int64_t phist) = 0;
26113685Sjavier.bueno@metempsy.com
26213685Sjavier.bueno@metempsy.com    void init() override;
26313685Sjavier.bueno@metempsy.com    void regStats() override;
26413685Sjavier.bueno@metempsy.com    void updateStats(bool taken, BranchInfo *bi);
26513685Sjavier.bueno@metempsy.com
26614081Sjavier.bueno@metempsy.com    virtual void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken,
26713685Sjavier.bueno@metempsy.com                          BranchInfo *bi, Addr corrTarget, bool bias_bit,
26813685Sjavier.bueno@metempsy.com                          int hitBank, int altBank, int64_t phist);
26914081Sjavier.bueno@metempsy.com
27014081Sjavier.bueno@metempsy.com    virtual size_t getSizeInBits() const;
27113685Sjavier.bueno@metempsy.com};
27213685Sjavier.bueno@metempsy.com#endif//__CPU_PRED_STATISTICAL_CORRECTOR_HH
273