114034Sjavier.bueno@metempsy.com/*
214034Sjavier.bueno@metempsy.com * Copyright 2019 Texas A&M University
314034Sjavier.bueno@metempsy.com *
414034Sjavier.bueno@metempsy.com * Redistribution and use in source and binary forms, with or without
514034Sjavier.bueno@metempsy.com * modification, are permitted provided that the following conditions are met:
614034Sjavier.bueno@metempsy.com *
714034Sjavier.bueno@metempsy.com * 1. Redistributions of source code must retain the above copyright notice,
814034Sjavier.bueno@metempsy.com *    this list of conditions and the following disclaimer.
914034Sjavier.bueno@metempsy.com *
1014034Sjavier.bueno@metempsy.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1114034Sjavier.bueno@metempsy.com *    this list of conditions and the following disclaimer in the documentation
1214034Sjavier.bueno@metempsy.com *    and/or other materials provided with the distribution.
1314034Sjavier.bueno@metempsy.com *
1414034Sjavier.bueno@metempsy.com * 3. Neither the name of the copyright holder nor the names of its
1514034Sjavier.bueno@metempsy.com *    contributors may be used to endorse or promote products derived from this
1614034Sjavier.bueno@metempsy.com *    software without specific prior written permission.
1714034Sjavier.bueno@metempsy.com *
1814034Sjavier.bueno@metempsy.com *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1914034Sjavier.bueno@metempsy.com *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2014034Sjavier.bueno@metempsy.com *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2114034Sjavier.bueno@metempsy.com *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2214034Sjavier.bueno@metempsy.com *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2314034Sjavier.bueno@metempsy.com *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2414034Sjavier.bueno@metempsy.com *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2514034Sjavier.bueno@metempsy.com *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2614034Sjavier.bueno@metempsy.com *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2714034Sjavier.bueno@metempsy.com *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2814034Sjavier.bueno@metempsy.com *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2914034Sjavier.bueno@metempsy.com *
3014034Sjavier.bueno@metempsy.com *  Author: Daniel A. Jiménez
3114034Sjavier.bueno@metempsy.com *  Adapted to gem5 by: Javier Bueno Hedo
3214034Sjavier.bueno@metempsy.com *
3314034Sjavier.bueno@metempsy.com */
3414034Sjavier.bueno@metempsy.com
3514034Sjavier.bueno@metempsy.com/*
3614034Sjavier.bueno@metempsy.com * Multiperspective Perceptron Predictor (by Daniel A. Jiménez)
3714034Sjavier.bueno@metempsy.com */
3814034Sjavier.bueno@metempsy.com
3914034Sjavier.bueno@metempsy.com#ifndef __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__
4014034Sjavier.bueno@metempsy.com#define __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__
4114034Sjavier.bueno@metempsy.com
4214034Sjavier.bueno@metempsy.com#include <array>
4314034Sjavier.bueno@metempsy.com#include <vector>
4414034Sjavier.bueno@metempsy.com
4514034Sjavier.bueno@metempsy.com#include "cpu/pred/bpred_unit.hh"
4614034Sjavier.bueno@metempsy.com#include "params/MultiperspectivePerceptron.hh"
4714034Sjavier.bueno@metempsy.com
4814034Sjavier.bueno@metempsy.comclass MultiperspectivePerceptron : public BPredUnit
4914034Sjavier.bueno@metempsy.com{
5014034Sjavier.bueno@metempsy.com  protected:
5114034Sjavier.bueno@metempsy.com    /**
5214034Sjavier.bueno@metempsy.com     * Branch information data
5314034Sjavier.bueno@metempsy.com     */
5414034Sjavier.bueno@metempsy.com    class MPPBranchInfo {
5514034Sjavier.bueno@metempsy.com        /** pc of the branch */
5614034Sjavier.bueno@metempsy.com        const unsigned int pc;
5714034Sjavier.bueno@metempsy.com        /** pc of the branch, shifted 2 bits to the right */
5814034Sjavier.bueno@metempsy.com        const unsigned short int pc2;
5914034Sjavier.bueno@metempsy.com        /** pc of the branch, hashed */
6014034Sjavier.bueno@metempsy.com        const unsigned short int hpc;
6114034Sjavier.bueno@metempsy.com        /** Whether this is a conditional branch */
6214034Sjavier.bueno@metempsy.com        const bool condBranch;
6314034Sjavier.bueno@metempsy.com
6414034Sjavier.bueno@metempsy.com        /**
6514034Sjavier.bueno@metempsy.com         * PC Hash functions
6614034Sjavier.bueno@metempsy.com         */
6714034Sjavier.bueno@metempsy.com        static inline unsigned int hash1(unsigned int a)
6814034Sjavier.bueno@metempsy.com        {
6914034Sjavier.bueno@metempsy.com            a = (a ^ 0xdeadbeef) + (a<<4);
7014034Sjavier.bueno@metempsy.com            a = a ^ (a>>10);
7114034Sjavier.bueno@metempsy.com            a = a + (a<<7);
7214034Sjavier.bueno@metempsy.com            a = a ^ (a>>13);
7314034Sjavier.bueno@metempsy.com            return a;
7414034Sjavier.bueno@metempsy.com        }
7514034Sjavier.bueno@metempsy.com
7614034Sjavier.bueno@metempsy.com        static inline unsigned int hash2(unsigned int key)
7714034Sjavier.bueno@metempsy.com        {
7814034Sjavier.bueno@metempsy.com            int c2 = 0x27d4eb2d; // a prime or an odd constant
7914034Sjavier.bueno@metempsy.com            key = (key ^ 61) ^ (key >> 16);
8014034Sjavier.bueno@metempsy.com            key = key + (key << 3);
8114034Sjavier.bueno@metempsy.com            key = key ^ (key >> 4);
8214034Sjavier.bueno@metempsy.com            key = key * c2;
8314034Sjavier.bueno@metempsy.com            key = key ^ (key >> 15);
8414034Sjavier.bueno@metempsy.com            return key;
8514034Sjavier.bueno@metempsy.com        }
8614034Sjavier.bueno@metempsy.com
8714034Sjavier.bueno@metempsy.com        static inline unsigned int hash(unsigned int key, unsigned int i)
8814034Sjavier.bueno@metempsy.com        {
8914034Sjavier.bueno@metempsy.com            return hash2(key) * i + hash1(key);
9014034Sjavier.bueno@metempsy.com        }
9114034Sjavier.bueno@metempsy.com
9214034Sjavier.bueno@metempsy.com        static inline unsigned int hashPC(unsigned int pc, int pcshift)
9314034Sjavier.bueno@metempsy.com        {
9414034Sjavier.bueno@metempsy.com            if (pcshift < 0) {
9514034Sjavier.bueno@metempsy.com                return hash(pc, -pcshift);
9614034Sjavier.bueno@metempsy.com            } else if (pcshift < 11) {
9714034Sjavier.bueno@metempsy.com                unsigned int x = pc;
9814034Sjavier.bueno@metempsy.com                x ^= (pc >> pcshift);
9914034Sjavier.bueno@metempsy.com                return x;
10014034Sjavier.bueno@metempsy.com            } else {
10114034Sjavier.bueno@metempsy.com                return pc >> (pcshift-11);
10214034Sjavier.bueno@metempsy.com            }
10314034Sjavier.bueno@metempsy.com        }
10414034Sjavier.bueno@metempsy.com
10514034Sjavier.bueno@metempsy.com      public:
10614034Sjavier.bueno@metempsy.com        /** Whether this branch has been filtered by the prefetcher */
10714034Sjavier.bueno@metempsy.com        bool filtered;
10814034Sjavier.bueno@metempsy.com        /** Result of the prediction (true is taken) */
10914034Sjavier.bueno@metempsy.com        bool prediction;
11014034Sjavier.bueno@metempsy.com        /** Score of the perceptron */
11114034Sjavier.bueno@metempsy.com        int yout;
11214034Sjavier.bueno@metempsy.com
11314034Sjavier.bueno@metempsy.com        MPPBranchInfo(Addr _pc, int pcshift, bool cb) : pc((unsigned int)_pc),
11414034Sjavier.bueno@metempsy.com        pc2(pc >> 2), hpc(hashPC(pc, pcshift)), condBranch(cb),
11514034Sjavier.bueno@metempsy.com        filtered(false), prediction(false), yout(0)
11614034Sjavier.bueno@metempsy.com        { }
11714034Sjavier.bueno@metempsy.com
11814034Sjavier.bueno@metempsy.com        unsigned int getPC() const
11914034Sjavier.bueno@metempsy.com        {
12014034Sjavier.bueno@metempsy.com            return pc;
12114034Sjavier.bueno@metempsy.com        }
12214034Sjavier.bueno@metempsy.com        unsigned short int getPC2() const
12314034Sjavier.bueno@metempsy.com        {
12414034Sjavier.bueno@metempsy.com            return pc2;
12514034Sjavier.bueno@metempsy.com        }
12614034Sjavier.bueno@metempsy.com        unsigned short int getHPC() const
12714034Sjavier.bueno@metempsy.com        {
12814034Sjavier.bueno@metempsy.com            return hpc;
12914034Sjavier.bueno@metempsy.com        }
13014034Sjavier.bueno@metempsy.com        unsigned int getHashFilter(bool last_ghist_bit) const
13114034Sjavier.bueno@metempsy.com        {
13214034Sjavier.bueno@metempsy.com            return last_ghist_bit ^ hpc;
13314034Sjavier.bueno@metempsy.com        }
13414034Sjavier.bueno@metempsy.com        bool isUnconditional() const
13514034Sjavier.bueno@metempsy.com        {
13614034Sjavier.bueno@metempsy.com            return !condBranch;
13714034Sjavier.bueno@metempsy.com        }
13814034Sjavier.bueno@metempsy.com    };
13914034Sjavier.bueno@metempsy.com
14014034Sjavier.bueno@metempsy.com    /**
14114034Sjavier.bueno@metempsy.com     * Entry of the branch filter
14214034Sjavier.bueno@metempsy.com     */
14314034Sjavier.bueno@metempsy.com    struct FilterEntry {
14414034Sjavier.bueno@metempsy.com        /** Has this branch been taken at least once? */
14514034Sjavier.bueno@metempsy.com        bool seenTaken;
14614034Sjavier.bueno@metempsy.com        /** Has this branch been not taken at least once? */
14714034Sjavier.bueno@metempsy.com        bool seenUntaken;
14814034Sjavier.bueno@metempsy.com
14914034Sjavier.bueno@metempsy.com        FilterEntry() : seenTaken(false), seenUntaken(false) {}
15014034Sjavier.bueno@metempsy.com
15114034Sjavier.bueno@metempsy.com        /** Whether this branch has always been observed as not taken */
15214034Sjavier.bueno@metempsy.com        bool alwaysNotTakenSoFar() const {
15314034Sjavier.bueno@metempsy.com            return seenUntaken & !seenTaken;
15414034Sjavier.bueno@metempsy.com        }
15514034Sjavier.bueno@metempsy.com        /** Whether this branch has always been observed as taken */
15614034Sjavier.bueno@metempsy.com        bool alwaysTakenSoFar() const {
15714034Sjavier.bueno@metempsy.com            return seenTaken & !seenUntaken;
15814034Sjavier.bueno@metempsy.com        }
15914034Sjavier.bueno@metempsy.com        /** Whether this branch has been observed before */
16014034Sjavier.bueno@metempsy.com        bool neverSeen() const {
16114034Sjavier.bueno@metempsy.com            return !seenTaken && !seenUntaken;
16214034Sjavier.bueno@metempsy.com        }
16314034Sjavier.bueno@metempsy.com    };
16414034Sjavier.bueno@metempsy.com
16514034Sjavier.bueno@metempsy.com
16614034Sjavier.bueno@metempsy.com    /**
16714034Sjavier.bueno@metempsy.com     * Local history entries, each enty contains the history of directions
16814034Sjavier.bueno@metempsy.com     * taken by a given branch.
16914034Sjavier.bueno@metempsy.com     */
17014034Sjavier.bueno@metempsy.com    class LocalHistories {
17114034Sjavier.bueno@metempsy.com        /** The array of histories */
17214034Sjavier.bueno@metempsy.com        std::vector<unsigned int> localHistories;
17314034Sjavier.bueno@metempsy.com        /** Size in bits of each history entry */
17414034Sjavier.bueno@metempsy.com        const int localHistoryLength;
17514034Sjavier.bueno@metempsy.com
17614034Sjavier.bueno@metempsy.com        /** Index function given the pc of the branch */
17714034Sjavier.bueno@metempsy.com        unsigned int index(Addr pc) const {
17814034Sjavier.bueno@metempsy.com            return (pc >> 2) % localHistories.size();
17914034Sjavier.bueno@metempsy.com        }
18014034Sjavier.bueno@metempsy.com        public:
18114034Sjavier.bueno@metempsy.com        LocalHistories(int nlocal_histories, int histo_len) :
18214034Sjavier.bueno@metempsy.com            localHistories(nlocal_histories), localHistoryLength(histo_len) {}
18314034Sjavier.bueno@metempsy.com
18414034Sjavier.bueno@metempsy.com        /** Obtains the local history entry of a given branch */
18514034Sjavier.bueno@metempsy.com        unsigned int operator[](Addr pc) const
18614034Sjavier.bueno@metempsy.com        {
18714034Sjavier.bueno@metempsy.com            return localHistories[index(pc)];
18814034Sjavier.bueno@metempsy.com        }
18914034Sjavier.bueno@metempsy.com
19014034Sjavier.bueno@metempsy.com        /** Adds a history bit to the local history entry of a given branch */
19114034Sjavier.bueno@metempsy.com        void update(Addr pc, bool value)
19214034Sjavier.bueno@metempsy.com        {
19314034Sjavier.bueno@metempsy.com            assert(localHistories.size() > 0);
19414034Sjavier.bueno@metempsy.com            unsigned int &pos = localHistories[index(pc)];
19514034Sjavier.bueno@metempsy.com            pos <<= 1;
19614034Sjavier.bueno@metempsy.com            pos |= value;
19714034Sjavier.bueno@metempsy.com            pos &= ((1<<localHistoryLength)-1);
19814034Sjavier.bueno@metempsy.com        }
19914034Sjavier.bueno@metempsy.com
20014034Sjavier.bueno@metempsy.com        /** Returns the number of bits of each local history entry */
20114034Sjavier.bueno@metempsy.com        int getLocalHistoryLength() const
20214034Sjavier.bueno@metempsy.com        {
20314034Sjavier.bueno@metempsy.com            return localHistoryLength;
20414034Sjavier.bueno@metempsy.com        }
20514034Sjavier.bueno@metempsy.com
20614034Sjavier.bueno@metempsy.com        /** Size in bits required by all history entries */
20714034Sjavier.bueno@metempsy.com        int getSize() const
20814034Sjavier.bueno@metempsy.com        {
20914034Sjavier.bueno@metempsy.com            return localHistoryLength * localHistories.size();
21014034Sjavier.bueno@metempsy.com        }
21114034Sjavier.bueno@metempsy.com    };
21214034Sjavier.bueno@metempsy.com
21314034Sjavier.bueno@metempsy.com    /**
21414034Sjavier.bueno@metempsy.com     * Base class to implement the predictor tables.
21514034Sjavier.bueno@metempsy.com     */
21614034Sjavier.bueno@metempsy.com    struct HistorySpec {
21714034Sjavier.bueno@metempsy.com        /** First parameter */
21814034Sjavier.bueno@metempsy.com        const int p1;
21914034Sjavier.bueno@metempsy.com        /** Second parameter */
22014034Sjavier.bueno@metempsy.com        const int p2;
22114034Sjavier.bueno@metempsy.com        /** Third parameter */
22214034Sjavier.bueno@metempsy.com        const int p3;
22314034Sjavier.bueno@metempsy.com        /** Coefficient of the feature, models the accuracy of the feature */
22414034Sjavier.bueno@metempsy.com        const double coeff;
22514034Sjavier.bueno@metempsy.com        /** Pre-assigned size in bits assigned to this feature */
22614034Sjavier.bueno@metempsy.com        const int size;
22714034Sjavier.bueno@metempsy.com        /** Width of the table in bits  */
22814034Sjavier.bueno@metempsy.com        const int width;
22914034Sjavier.bueno@metempsy.com        /** Reference to the branch predictor class */
23014034Sjavier.bueno@metempsy.com        MultiperspectivePerceptron &mpp;
23114034Sjavier.bueno@metempsy.com
23214034Sjavier.bueno@metempsy.com        HistorySpec(int _p1, int _p2, int _p3, double _coeff, int _size,
23314034Sjavier.bueno@metempsy.com                int _width, MultiperspectivePerceptron &_mpp) : p1(_p1),
23414034Sjavier.bueno@metempsy.com        p2(_p2), p3(_p3), coeff(_coeff), size(_size), width(_width),
23514034Sjavier.bueno@metempsy.com        mpp(_mpp)
23614034Sjavier.bueno@metempsy.com        {}
23714034Sjavier.bueno@metempsy.com
23814034Sjavier.bueno@metempsy.com        /**
23914034Sjavier.bueno@metempsy.com         * Gets the hash to index the table, using the pc of the branch,
24014034Sjavier.bueno@metempsy.com         * and the index of the table.
24114034Sjavier.bueno@metempsy.com         * @param tid Thread ID of the branch
24214034Sjavier.bueno@metempsy.com         * @param pc address of the branch
24314034Sjavier.bueno@metempsy.com         * @param pc2 address of the branch shifted 2 bits to the right
24414034Sjavier.bueno@metempsy.com         * @param t integer index of the table
24514034Sjavier.bueno@metempsy.com         * @result resulting hash value that will be used to index the table
24614034Sjavier.bueno@metempsy.com         */
24714034Sjavier.bueno@metempsy.com        virtual unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t)
24814034Sjavier.bueno@metempsy.com            const = 0;
24914034Sjavier.bueno@metempsy.com        /**
25014034Sjavier.bueno@metempsy.com         * Sets the size requirements of the table, used when initializing
25114034Sjavier.bueno@metempsy.com         * to set the proper size of the tables
25214034Sjavier.bueno@metempsy.com         */
25314034Sjavier.bueno@metempsy.com        virtual void setBitRequirements() const {}
25414034Sjavier.bueno@metempsy.com    };
25514034Sjavier.bueno@metempsy.com
25614034Sjavier.bueno@metempsy.com    /** Predictor parameters */
25714034Sjavier.bueno@metempsy.com    const int blockSize;
25814034Sjavier.bueno@metempsy.com    const int pcshift;
25914034Sjavier.bueno@metempsy.com    const int threshold;
26014034Sjavier.bueno@metempsy.com    const int bias0;
26114034Sjavier.bueno@metempsy.com    const int bias1;
26214034Sjavier.bueno@metempsy.com    const int biasmostly0;
26314034Sjavier.bueno@metempsy.com    const int biasmostly1;
26414034Sjavier.bueno@metempsy.com    const int nbest;
26514034Sjavier.bueno@metempsy.com    const int tunebits;
26614034Sjavier.bueno@metempsy.com    const int hshift;
26714034Sjavier.bueno@metempsy.com    const unsigned long long int imli_mask1;
26814034Sjavier.bueno@metempsy.com    const unsigned long long int imli_mask4;
26914034Sjavier.bueno@metempsy.com    const unsigned long long int recencypos_mask;
27014034Sjavier.bueno@metempsy.com    const double fudge;
27114034Sjavier.bueno@metempsy.com    const int n_sign_bits;
27214034Sjavier.bueno@metempsy.com    const int pcbit;
27314034Sjavier.bueno@metempsy.com    const int decay;
27414034Sjavier.bueno@metempsy.com    const unsigned int record_mask;
27514034Sjavier.bueno@metempsy.com    const bool hash_taken;
27614034Sjavier.bueno@metempsy.com    const bool tuneonly;
27714034Sjavier.bueno@metempsy.com    const int extra_rounds;
27814034Sjavier.bueno@metempsy.com    const int speed;
27914034Sjavier.bueno@metempsy.com    const int budgetbits;
28014034Sjavier.bueno@metempsy.com    const bool speculative_update;
28114034Sjavier.bueno@metempsy.com
28214034Sjavier.bueno@metempsy.com    /** Transfer function for 6-width tables */
28314034Sjavier.bueno@metempsy.com    static int xlat[];
28414034Sjavier.bueno@metempsy.com    /** Transfer function for 5-width tables */
28514034Sjavier.bueno@metempsy.com    static int xlat4[];
28614034Sjavier.bueno@metempsy.com
28714034Sjavier.bueno@metempsy.com    /** History data is kept for each thread */
28814034Sjavier.bueno@metempsy.com    struct ThreadData {
28914034Sjavier.bueno@metempsy.com        ThreadData(int num_filter, int n_local_histories,
29014034Sjavier.bueno@metempsy.com            int local_history_length, int assoc,
29114034Sjavier.bueno@metempsy.com            const std::vector<std::vector<int>> &blurrypath_bits,
29214034Sjavier.bueno@metempsy.com            int path_length, int ghist_length, int block_size,
29314034Sjavier.bueno@metempsy.com            const std::vector<std::vector<std::vector<bool>>> &acyclic_bits,
29414034Sjavier.bueno@metempsy.com            const std::vector<int> &modhist_indices,
29514034Sjavier.bueno@metempsy.com            const std::vector<int> &modhist_lengths,
29614034Sjavier.bueno@metempsy.com            const std::vector<int> &modpath_indices,
29714034Sjavier.bueno@metempsy.com            const std::vector<int> &modpath_lengths,
29814034Sjavier.bueno@metempsy.com            const std::vector<int> &table_sizes, int n_sign_bits);
29914034Sjavier.bueno@metempsy.com
30014034Sjavier.bueno@metempsy.com        std::vector<FilterEntry> filterTable;
30114034Sjavier.bueno@metempsy.com        std::vector<std::vector<bool>> acyclic_histories;
30214034Sjavier.bueno@metempsy.com        std::vector<std::vector<unsigned int>> acyclic2_histories;
30314034Sjavier.bueno@metempsy.com
30414034Sjavier.bueno@metempsy.com        void updateAcyclic(bool hashed_taken, unsigned int hpc) {
30514034Sjavier.bueno@metempsy.com            for (int i = 0; i < acyclic_histories.size(); i += 1) {
30614034Sjavier.bueno@metempsy.com                if (acyclic_histories[i].size() > 0) {
30714034Sjavier.bueno@metempsy.com                    acyclic_histories[i][hpc%(i+2)] = hashed_taken;
30814034Sjavier.bueno@metempsy.com                    acyclic2_histories[i][hpc%(i+2)] = hpc;
30914034Sjavier.bueno@metempsy.com                }
31014034Sjavier.bueno@metempsy.com            }
31114034Sjavier.bueno@metempsy.com        }
31214034Sjavier.bueno@metempsy.com
31314034Sjavier.bueno@metempsy.com        std::vector<std::vector<unsigned int>> blurrypath_histories;
31414034Sjavier.bueno@metempsy.com        std::vector<unsigned int> ghist_words;
31514034Sjavier.bueno@metempsy.com        std::vector<std::vector<unsigned short int>> modpath_histories;
31614034Sjavier.bueno@metempsy.com        std::vector<std::vector<bool>> mod_histories;
31714034Sjavier.bueno@metempsy.com        std::vector<unsigned short int> path_history;
31814034Sjavier.bueno@metempsy.com        std::vector<unsigned int> imli_counter;
31914034Sjavier.bueno@metempsy.com        LocalHistories localHistories;
32014034Sjavier.bueno@metempsy.com        std::vector<unsigned int short> recency_stack;
32114034Sjavier.bueno@metempsy.com
32214034Sjavier.bueno@metempsy.com        void insertRecency(unsigned int pc, int assoc) {
32314034Sjavier.bueno@metempsy.com            int i = 0;
32414034Sjavier.bueno@metempsy.com            for (i = 0; i < assoc; i += 1) {
32514034Sjavier.bueno@metempsy.com                if (recency_stack[i] == pc) {
32614034Sjavier.bueno@metempsy.com                    break;
32714034Sjavier.bueno@metempsy.com                }
32814034Sjavier.bueno@metempsy.com            }
32914034Sjavier.bueno@metempsy.com            if (i == assoc) {
33014034Sjavier.bueno@metempsy.com                i = assoc-1;
33114034Sjavier.bueno@metempsy.com                recency_stack[i] = pc;
33214034Sjavier.bueno@metempsy.com            }
33314034Sjavier.bueno@metempsy.com            int j;
33414034Sjavier.bueno@metempsy.com            unsigned int b = recency_stack[i];
33514034Sjavier.bueno@metempsy.com            for (j = i; j >= 1; j -= 1) {
33614034Sjavier.bueno@metempsy.com                recency_stack[j] = recency_stack[j-1];
33714034Sjavier.bueno@metempsy.com            }
33814034Sjavier.bueno@metempsy.com            recency_stack[0] = b;
33914034Sjavier.bueno@metempsy.com        }
34014034Sjavier.bueno@metempsy.com
34114034Sjavier.bueno@metempsy.com        bool last_ghist_bit;
34214034Sjavier.bueno@metempsy.com        int occupancy;
34314034Sjavier.bueno@metempsy.com
34414034Sjavier.bueno@metempsy.com        std::vector<int> mpreds;
34514034Sjavier.bueno@metempsy.com        std::vector<std::vector<short int>> tables;
34614034Sjavier.bueno@metempsy.com        std::vector<std::vector<std::array<bool, 2>>> sign_bits;
34714034Sjavier.bueno@metempsy.com    };
34814034Sjavier.bueno@metempsy.com    std::vector<ThreadData *> threadData;
34914034Sjavier.bueno@metempsy.com
35014034Sjavier.bueno@metempsy.com    /** Predictor tables */
35114034Sjavier.bueno@metempsy.com    std::vector<HistorySpec *> specs;
35214034Sjavier.bueno@metempsy.com    std::vector<int> table_sizes;
35314034Sjavier.bueno@metempsy.com
35414034Sjavier.bueno@metempsy.com    /** runtime values and data used to count the size in bits */
35514034Sjavier.bueno@metempsy.com    bool doing_local;
35614034Sjavier.bueno@metempsy.com    bool doing_recency;
35714034Sjavier.bueno@metempsy.com    int assoc;
35814034Sjavier.bueno@metempsy.com    int ghist_length;
35914034Sjavier.bueno@metempsy.com    int modghist_length;
36014034Sjavier.bueno@metempsy.com    int path_length;
36114034Sjavier.bueno@metempsy.com    int thresholdCounter;
36214034Sjavier.bueno@metempsy.com    int theta;
36314081Sjavier.bueno@metempsy.com    int extrabits;
36414034Sjavier.bueno@metempsy.com    std::vector<int> imli_counter_bits;
36514034Sjavier.bueno@metempsy.com    std::vector<int> modhist_indices;
36614034Sjavier.bueno@metempsy.com    std::vector<int> modhist_lengths;
36714034Sjavier.bueno@metempsy.com    std::vector<int> modpath_indices;
36814034Sjavier.bueno@metempsy.com    std::vector<int> modpath_lengths;
36914034Sjavier.bueno@metempsy.com    std::vector<std::vector<int>> blurrypath_bits;
37014034Sjavier.bueno@metempsy.com    std::vector<std::vector<std::vector<bool>>> acyclic_bits;
37114034Sjavier.bueno@metempsy.com
37214034Sjavier.bueno@metempsy.com    /** Auxiliary function for MODHIST and GHISTMODPATH features */
37314034Sjavier.bueno@metempsy.com    void insertModhistSpec(int p1, int p2) {
37414034Sjavier.bueno@metempsy.com        int j = insert(modhist_indices, p1);
37514034Sjavier.bueno@metempsy.com        if (modhist_lengths.size() < (j + 1)) {
37614034Sjavier.bueno@metempsy.com            modhist_lengths.resize(j + 1);
37714034Sjavier.bueno@metempsy.com        }
37814034Sjavier.bueno@metempsy.com        if (modhist_lengths[j] < p2 + 1) {
37914034Sjavier.bueno@metempsy.com            modhist_lengths[j] = p2 + 1;
38014034Sjavier.bueno@metempsy.com        }
38114034Sjavier.bueno@metempsy.com        if (p2 >= modghist_length) {
38214034Sjavier.bueno@metempsy.com            modghist_length = p2 + 1;
38314034Sjavier.bueno@metempsy.com        }
38414034Sjavier.bueno@metempsy.com    }
38514034Sjavier.bueno@metempsy.com
38614034Sjavier.bueno@metempsy.com    /** Auxiliary function for MODPATH and GHISTMODPATH features */
38714034Sjavier.bueno@metempsy.com    void insertModpathSpec(int p1, int p2) {
38814034Sjavier.bueno@metempsy.com        int j = insert(modpath_indices, p1);
38914034Sjavier.bueno@metempsy.com        if (modpath_lengths.size() < (j + 1)) {
39014034Sjavier.bueno@metempsy.com            modpath_lengths.resize(j + 1);
39114034Sjavier.bueno@metempsy.com        }
39214034Sjavier.bueno@metempsy.com        if (modpath_lengths[j] < p2 + 1) {
39314034Sjavier.bueno@metempsy.com            modpath_lengths[j] = p2 + 1;
39414034Sjavier.bueno@metempsy.com        }
39514034Sjavier.bueno@metempsy.com        if (p2 >= path_length) {
39614034Sjavier.bueno@metempsy.com            path_length = p2 + 1;
39714034Sjavier.bueno@metempsy.com        }
39814034Sjavier.bueno@metempsy.com    }
39914034Sjavier.bueno@metempsy.com
40014034Sjavier.bueno@metempsy.com    /** Auxiliary function used by insertModhistSpec and insertModpathSpec*/
40114034Sjavier.bueno@metempsy.com    int insert(std::vector<int> &v, int x)
40214034Sjavier.bueno@metempsy.com    {
40314034Sjavier.bueno@metempsy.com        for (int i = 0; i < v.size(); i += 1) {
40414034Sjavier.bueno@metempsy.com            if (v[i] == x) {
40514034Sjavier.bueno@metempsy.com                return i;
40614034Sjavier.bueno@metempsy.com            }
40714034Sjavier.bueno@metempsy.com        }
40814034Sjavier.bueno@metempsy.com        v.push_back(x);
40914034Sjavier.bueno@metempsy.com        return v.size()-1;
41014034Sjavier.bueno@metempsy.com    }
41114034Sjavier.bueno@metempsy.com
41214034Sjavier.bueno@metempsy.com    /**
41314034Sjavier.bueno@metempsy.com     * Computes the size in bits of the structures needed to keep track
41414034Sjavier.bueno@metempsy.com     * of the history and the predictor tables and assigns the sizes of
41514034Sjavier.bueno@metempsy.com     * those tables that did not had their size specified.
41614034Sjavier.bueno@metempsy.com     * @param num_filter_entries number of entries of the filter
41714034Sjavier.bueno@metempsy.com     * @param nlocal_histories number of local history entries
41814034Sjavier.bueno@metempsy.com     * @param local_history_length size of each local history entry
41914081Sjavier.bueno@metempsy.com     * @param ignore_path_size ignore the path length storage
42014034Sjavier.bueno@metempsy.com     */
42114034Sjavier.bueno@metempsy.com    void computeBits(int num_filter_entries, int nlocal_histories,
42214081Sjavier.bueno@metempsy.com            int local_history_length, bool ignore_path_size);
42314034Sjavier.bueno@metempsy.com
42414034Sjavier.bueno@metempsy.com    /**
42514034Sjavier.bueno@metempsy.com     * Creates the tables of the predictor
42614034Sjavier.bueno@metempsy.com     */
42714034Sjavier.bueno@metempsy.com    virtual void createSpecs() = 0;
42814034Sjavier.bueno@metempsy.com
42914034Sjavier.bueno@metempsy.com    /**
43014034Sjavier.bueno@metempsy.com     * Get the position index of a predictor table
43114034Sjavier.bueno@metempsy.com     * @param tid Thread ID of the branch
43214034Sjavier.bueno@metempsy.com     * @param bi branch informaiton data
43314034Sjavier.bueno@metempsy.com     * @param spec predictor table
43414034Sjavier.bueno@metempsy.com     * @param index integer index of the predictor table
43514034Sjavier.bueno@metempsy.com     * @result index to access the predictor table
43614034Sjavier.bueno@metempsy.com     */
43714034Sjavier.bueno@metempsy.com    unsigned int getIndex(ThreadID tid, const MPPBranchInfo &bi,
43814034Sjavier.bueno@metempsy.com            const HistorySpec &spec, int index) const;
43914034Sjavier.bueno@metempsy.com    /**
44014034Sjavier.bueno@metempsy.com     * Finds the best subset of features to use in case of a low-confidence
44114034Sjavier.bueno@metempsy.com     * branch, returns the result as an ordered vector of the indices to the
44214034Sjavier.bueno@metempsy.com     * predictor tables
44314034Sjavier.bueno@metempsy.com     * @param tid Thread ID of the branch
44414034Sjavier.bueno@metempsy.com     * @param vector to write the ordered list of indices of the best tables
44514034Sjavier.bueno@metempsy.com     */
44614034Sjavier.bueno@metempsy.com    void findBest(ThreadID tid, std::vector<int> &best_preds) const;
44714034Sjavier.bueno@metempsy.com
44814034Sjavier.bueno@metempsy.com    /**
44914034Sjavier.bueno@metempsy.com     * Computes the output of the predictor for a given branch and the
45014034Sjavier.bueno@metempsy.com     * resulting best value in case the prediction has low confidence
45114034Sjavier.bueno@metempsy.com     * @param tid Thread ID of the branch
45214034Sjavier.bueno@metempsy.com     * @param bi branch informaiton data
45314034Sjavier.bueno@metempsy.com     * @return resulting sum for low-confidence branch
45414034Sjavier.bueno@metempsy.com     */
45514034Sjavier.bueno@metempsy.com    int computeOutput(ThreadID tid, MPPBranchInfo &bi);
45614034Sjavier.bueno@metempsy.com
45714034Sjavier.bueno@metempsy.com    /**
45814034Sjavier.bueno@metempsy.com     * Trains the branch predictor with the given branch and direction
45914034Sjavier.bueno@metempsy.com     * @param tid Thread ID of the branch
46014034Sjavier.bueno@metempsy.com     * @param bi branch informaiton data
46114034Sjavier.bueno@metempsy.com     * @param taken whether the branch was taken
46214034Sjavier.bueno@metempsy.com     */
46314034Sjavier.bueno@metempsy.com    void train(ThreadID tid, MPPBranchInfo &bi, bool taken);
46414034Sjavier.bueno@metempsy.com
46514034Sjavier.bueno@metempsy.com    /**
46614034Sjavier.bueno@metempsy.com     * Auxiliary function to increase a table counter depending on the
46714034Sjavier.bueno@metempsy.com     * direction of the branch
46814034Sjavier.bueno@metempsy.com     * @param taken whether the branch was taken
46914034Sjavier.bueno@metempsy.com     * @param sign current sign of the table
47014034Sjavier.bueno@metempsy.com     * @param c current value of the table
47114034Sjavier.bueno@metempsy.com     * @param max_weight maximum value of the counter
47214034Sjavier.bueno@metempsy.com     */
47314034Sjavier.bueno@metempsy.com    void satIncDec(bool taken, bool &sign, int &c, int max_weight) const;
47414034Sjavier.bueno@metempsy.com
47514034Sjavier.bueno@metempsy.com    /** Add a table spec to the prefetcher */
47614034Sjavier.bueno@metempsy.com    void addSpec(HistorySpec *spec)
47714034Sjavier.bueno@metempsy.com    {
47814034Sjavier.bueno@metempsy.com        specs.push_back(spec);
47914034Sjavier.bueno@metempsy.com    }
48014034Sjavier.bueno@metempsy.com
48114034Sjavier.bueno@metempsy.com    /** Available features */
48214034Sjavier.bueno@metempsy.com
48314034Sjavier.bueno@metempsy.com    class GHIST : public HistorySpec {
48414034Sjavier.bueno@metempsy.com      public:
48514034Sjavier.bueno@metempsy.com        GHIST(int p1, int p2, double coeff, int size, int width,
48614034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
48714034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, 0, coeff, size, width, mpp)
48814034Sjavier.bueno@metempsy.com        {}
48914034Sjavier.bueno@metempsy.com
49014034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
49114034Sjavier.bueno@metempsy.com            override
49214034Sjavier.bueno@metempsy.com        {
49314034Sjavier.bueno@metempsy.com            return hash(mpp.threadData[tid]->ghist_words, mpp.blockSize, p1,
49414034Sjavier.bueno@metempsy.com                        p2);
49514034Sjavier.bueno@metempsy.com        }
49614034Sjavier.bueno@metempsy.com
49714034Sjavier.bueno@metempsy.com        static unsigned int hash(const std::vector<unsigned int> &ghist_words,
49814034Sjavier.bueno@metempsy.com                int block_size, int start_pos, int end_pos)
49914034Sjavier.bueno@metempsy.com        {
50014034Sjavier.bueno@metempsy.com            int a = start_pos;
50114034Sjavier.bueno@metempsy.com            int b = end_pos;
50214034Sjavier.bueno@metempsy.com
50314034Sjavier.bueno@metempsy.com            unsigned int x = 0;
50414034Sjavier.bueno@metempsy.com            // am is the next multiple of block_size after a
50514034Sjavier.bueno@metempsy.com            int am = (((a/block_size)*block_size)+block_size);
50614034Sjavier.bueno@metempsy.com            // bm is the previous multiple of block_size before b
50714034Sjavier.bueno@metempsy.com            int bm = (b/block_size)*block_size;
50814034Sjavier.bueno@metempsy.com
50914034Sjavier.bueno@metempsy.com            // the 0th bit of ghist_words[a/block_size] is the most recent bit.
51014034Sjavier.bueno@metempsy.com            // so the number of bits between a and am is the number to shift
51114034Sjavier.bueno@metempsy.com            // right?
51214034Sjavier.bueno@metempsy.com
51314034Sjavier.bueno@metempsy.com            // start out x as remainder bits from the beginning:
51414034Sjavier.bueno@metempsy.com            // x = [ . . . . . b b b b b ]
51514034Sjavier.bueno@metempsy.com            x += ghist_words[a / block_size] >> (a-am);
51614034Sjavier.bueno@metempsy.com            // add in bits from the middle
51714034Sjavier.bueno@metempsy.com            for (int i=am; i<bm; i+=block_size) {
51814034Sjavier.bueno@metempsy.com                x += ghist_words[i / block_size];
51914034Sjavier.bueno@metempsy.com            }
52014034Sjavier.bueno@metempsy.com            // add in remainder bits from end:
52114034Sjavier.bueno@metempsy.com            // x += [ b b b b b . . . . . ]
52214034Sjavier.bueno@metempsy.com            unsigned int y = ghist_words[bm / block_size] & ((1<<(b - bm))-1);
52314034Sjavier.bueno@metempsy.com            x += y << (block_size - (b - bm));
52414034Sjavier.bueno@metempsy.com            return x;
52514034Sjavier.bueno@metempsy.com        }
52614034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
52714034Sjavier.bueno@metempsy.com        {
52814034Sjavier.bueno@metempsy.com            if (mpp.ghist_length <= p2) {
52914034Sjavier.bueno@metempsy.com                mpp.ghist_length = p2 + 1;
53014034Sjavier.bueno@metempsy.com            }
53114034Sjavier.bueno@metempsy.com        }
53214034Sjavier.bueno@metempsy.com    };
53314034Sjavier.bueno@metempsy.com
53414034Sjavier.bueno@metempsy.com    class ACYCLIC : public HistorySpec {
53514034Sjavier.bueno@metempsy.com      public:
53614034Sjavier.bueno@metempsy.com        ACYCLIC(int p1, int p2, int p3, double coeff, int size, int width,
53714034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
53814034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
53914034Sjavier.bueno@metempsy.com        {}
54014034Sjavier.bueno@metempsy.com
54114034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
54214034Sjavier.bueno@metempsy.com            override
54314034Sjavier.bueno@metempsy.com        {
54414034Sjavier.bueno@metempsy.com            int a = p1;
54514034Sjavier.bueno@metempsy.com            int shift = p2;
54614034Sjavier.bueno@metempsy.com            int style = p3;
54714034Sjavier.bueno@metempsy.com            std::vector<std::vector<bool>> &acyclic_histories =
54814034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->acyclic_histories;
54914034Sjavier.bueno@metempsy.com            std::vector<std::vector<unsigned int>> &acyclic2_histories =
55014034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->acyclic2_histories;
55114034Sjavier.bueno@metempsy.com
55214034Sjavier.bueno@metempsy.com            unsigned int x = 0;
55314034Sjavier.bueno@metempsy.com            if (style == -1) {
55414034Sjavier.bueno@metempsy.com                unsigned int k = 0;
55514034Sjavier.bueno@metempsy.com                for (int i = 0; i < a + 2; i += 1) {
55614034Sjavier.bueno@metempsy.com                    x ^= acyclic_histories[a][i] << k;
55714034Sjavier.bueno@metempsy.com                    k += 1;
55814034Sjavier.bueno@metempsy.com                    k %= mpp.blockSize;
55914034Sjavier.bueno@metempsy.com                }
56014034Sjavier.bueno@metempsy.com            } else {
56114034Sjavier.bueno@metempsy.com                for (int i = 0; i < a + 2; i += 1) {
56214034Sjavier.bueno@metempsy.com                    x <<= shift;
56314034Sjavier.bueno@metempsy.com                    x += acyclic2_histories[a][i];
56414034Sjavier.bueno@metempsy.com                }
56514034Sjavier.bueno@metempsy.com            }
56614034Sjavier.bueno@metempsy.com            return x;
56714034Sjavier.bueno@metempsy.com        }
56814034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
56914034Sjavier.bueno@metempsy.com        {
57014034Sjavier.bueno@metempsy.com            if (mpp.acyclic_bits.size() < (p1 + 1)) {
57114034Sjavier.bueno@metempsy.com                mpp.acyclic_bits.resize(p1 + 1);
57214034Sjavier.bueno@metempsy.com            }
57314034Sjavier.bueno@metempsy.com            if (mpp.acyclic_bits[p1].size() < (p1 + 2)) {
57414034Sjavier.bueno@metempsy.com                mpp.acyclic_bits[p1].resize(p1 + 2, std::vector<bool>(2));
57514034Sjavier.bueno@metempsy.com            }
57614034Sjavier.bueno@metempsy.com            for (int j = 0; j < p1 + 2; j += 1) {
57714034Sjavier.bueno@metempsy.com                mpp.acyclic_bits[p1][j][!p3] = true;
57814034Sjavier.bueno@metempsy.com            }
57914034Sjavier.bueno@metempsy.com        }
58014034Sjavier.bueno@metempsy.com    };
58114034Sjavier.bueno@metempsy.com
58214034Sjavier.bueno@metempsy.com    class MODHIST : public HistorySpec {
58314034Sjavier.bueno@metempsy.com      public:
58414034Sjavier.bueno@metempsy.com        MODHIST(int p1, int p2, double coeff, int size, int width,
58514034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
58614034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, 0, coeff, size, width, mpp)
58714034Sjavier.bueno@metempsy.com        {}
58814034Sjavier.bueno@metempsy.com
58914034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
59014034Sjavier.bueno@metempsy.com            override
59114034Sjavier.bueno@metempsy.com        {
59214034Sjavier.bueno@metempsy.com            int a = p1;
59314034Sjavier.bueno@metempsy.com            int b = p2;
59414034Sjavier.bueno@metempsy.com            std::vector<std::vector<bool>> &mod_histories =
59514034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->mod_histories;
59614034Sjavier.bueno@metempsy.com
59714034Sjavier.bueno@metempsy.com            unsigned int x = 0, k = 0;
59814034Sjavier.bueno@metempsy.com            for (int i = 0; i < b; i += 1) {
59914034Sjavier.bueno@metempsy.com                x ^= mod_histories[a][i] << k;
60014034Sjavier.bueno@metempsy.com                k += 1;
60114034Sjavier.bueno@metempsy.com                k %= mpp.blockSize;
60214034Sjavier.bueno@metempsy.com            }
60314034Sjavier.bueno@metempsy.com            return x;
60414034Sjavier.bueno@metempsy.com        }
60514034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
60614034Sjavier.bueno@metempsy.com        {
60714034Sjavier.bueno@metempsy.com            mpp.insertModhistSpec(p1, p2);
60814034Sjavier.bueno@metempsy.com        }
60914034Sjavier.bueno@metempsy.com    };
61014034Sjavier.bueno@metempsy.com
61114034Sjavier.bueno@metempsy.com    class BIAS : public HistorySpec {
61214034Sjavier.bueno@metempsy.com      public:
61314034Sjavier.bueno@metempsy.com        BIAS(double coeff, int size, int width,
61414034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
61514034Sjavier.bueno@metempsy.com            : HistorySpec(0, 0, 0, coeff, size, width, mpp)
61614034Sjavier.bueno@metempsy.com        {}
61714034Sjavier.bueno@metempsy.com
61814034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
61914034Sjavier.bueno@metempsy.com            override
62014034Sjavier.bueno@metempsy.com        {
62114034Sjavier.bueno@metempsy.com            return 0;
62214034Sjavier.bueno@metempsy.com        }
62314034Sjavier.bueno@metempsy.com    };
62414034Sjavier.bueno@metempsy.com
62514034Sjavier.bueno@metempsy.com
62614034Sjavier.bueno@metempsy.com    class RECENCY : public HistorySpec {
62714034Sjavier.bueno@metempsy.com      public:
62814034Sjavier.bueno@metempsy.com        RECENCY(int p1, int p2, int p3, double coeff, int size, int width,
62914034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
63014034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
63114034Sjavier.bueno@metempsy.com        {}
63214034Sjavier.bueno@metempsy.com
63314034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
63414034Sjavier.bueno@metempsy.com            override
63514034Sjavier.bueno@metempsy.com        {
63614034Sjavier.bueno@metempsy.com            int depth = p1;
63714034Sjavier.bueno@metempsy.com            int shift = p2;
63814034Sjavier.bueno@metempsy.com            int style = p3;
63914034Sjavier.bueno@metempsy.com            std::vector<unsigned int short> &recency_stack =
64014034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->recency_stack;
64114034Sjavier.bueno@metempsy.com
64214034Sjavier.bueno@metempsy.com            if (style == -1) {
64314034Sjavier.bueno@metempsy.com                unsigned int x = 0;
64414034Sjavier.bueno@metempsy.com                for (int i = 0; i < depth; i += 1) {
64514034Sjavier.bueno@metempsy.com                    x <<= shift;
64614034Sjavier.bueno@metempsy.com                    x += recency_stack[i];
64714034Sjavier.bueno@metempsy.com                }
64814034Sjavier.bueno@metempsy.com                return x;
64914034Sjavier.bueno@metempsy.com            } else {
65014034Sjavier.bueno@metempsy.com                unsigned int x = 0, k = 0;
65114034Sjavier.bueno@metempsy.com                for (int i = 0; i < depth; i += 1) {
65214034Sjavier.bueno@metempsy.com                    x ^= (!!(recency_stack[i] & (1 << shift))) << k;
65314034Sjavier.bueno@metempsy.com                    k += 1;
65414034Sjavier.bueno@metempsy.com                    k %= mpp.blockSize;
65514034Sjavier.bueno@metempsy.com                }
65614034Sjavier.bueno@metempsy.com                return x;
65714034Sjavier.bueno@metempsy.com            }
65814034Sjavier.bueno@metempsy.com        }
65914034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
66014034Sjavier.bueno@metempsy.com        {
66114034Sjavier.bueno@metempsy.com            if (mpp.assoc < p1) {
66214034Sjavier.bueno@metempsy.com                mpp.assoc = p1;
66314034Sjavier.bueno@metempsy.com            }
66414034Sjavier.bueno@metempsy.com            mpp.doing_recency = true;
66514034Sjavier.bueno@metempsy.com        }
66614034Sjavier.bueno@metempsy.com    };
66714034Sjavier.bueno@metempsy.com
66814034Sjavier.bueno@metempsy.com    class IMLI : public HistorySpec {
66914034Sjavier.bueno@metempsy.com        public:
67014034Sjavier.bueno@metempsy.com            IMLI(int p1, double coeff, int size, int width,
67114034Sjavier.bueno@metempsy.com                    MultiperspectivePerceptron &mpp)
67214034Sjavier.bueno@metempsy.com                : HistorySpec(p1, 0, 0, coeff, size, width, mpp)
67314034Sjavier.bueno@metempsy.com            {}
67414034Sjavier.bueno@metempsy.com
67514034Sjavier.bueno@metempsy.com            unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
67614034Sjavier.bueno@metempsy.com                override
67714034Sjavier.bueno@metempsy.com                {
67814034Sjavier.bueno@metempsy.com                    assert(p1 >= 1);
67914034Sjavier.bueno@metempsy.com                    assert(p1 <= 4);
68014034Sjavier.bueno@metempsy.com                    return mpp.threadData[tid]->imli_counter[p1-1];
68114034Sjavier.bueno@metempsy.com                }
68214034Sjavier.bueno@metempsy.com
68314034Sjavier.bueno@metempsy.com            void setBitRequirements() const override
68414034Sjavier.bueno@metempsy.com            {
68514034Sjavier.bueno@metempsy.com                mpp.imli_counter_bits[p1 - 1] = 32;
68614034Sjavier.bueno@metempsy.com            }
68714034Sjavier.bueno@metempsy.com    };
68814034Sjavier.bueno@metempsy.com
68914034Sjavier.bueno@metempsy.com    class PATH : public HistorySpec {
69014034Sjavier.bueno@metempsy.com      public:
69114034Sjavier.bueno@metempsy.com        PATH(int p1, int p2, int p3, double coeff, int size, int width,
69214034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
69314034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
69414034Sjavier.bueno@metempsy.com        {}
69514034Sjavier.bueno@metempsy.com
69614034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
69714034Sjavier.bueno@metempsy.com            override
69814034Sjavier.bueno@metempsy.com        {
69914034Sjavier.bueno@metempsy.com            int depth = p1;
70014034Sjavier.bueno@metempsy.com            int shift = p2;
70114034Sjavier.bueno@metempsy.com            int style = p3;
70214034Sjavier.bueno@metempsy.com            std::vector<unsigned short int> &path_history =
70314034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->path_history;
70414034Sjavier.bueno@metempsy.com
70514034Sjavier.bueno@metempsy.com            if (style == -1) {
70614034Sjavier.bueno@metempsy.com                unsigned int x = 0;
70714034Sjavier.bueno@metempsy.com                for (int i = 0; i < depth; i += 1) {
70814034Sjavier.bueno@metempsy.com                    x <<= shift;
70914034Sjavier.bueno@metempsy.com                    x += path_history[i];
71014034Sjavier.bueno@metempsy.com                }
71114034Sjavier.bueno@metempsy.com                return x;
71214034Sjavier.bueno@metempsy.com            } else {
71314034Sjavier.bueno@metempsy.com                unsigned int x = 0;
71414034Sjavier.bueno@metempsy.com                int bm = (depth / mpp.blockSize) * mpp.blockSize;
71514034Sjavier.bueno@metempsy.com                for (int i = 0; i < bm; i += mpp.blockSize) {
71614034Sjavier.bueno@metempsy.com                    for (int j = 0; j < mpp.blockSize; j += 1) {
71714034Sjavier.bueno@metempsy.com                        x ^= (!!(path_history[i + j] & (1 << shift))) << j;
71814034Sjavier.bueno@metempsy.com                    }
71914034Sjavier.bueno@metempsy.com                }
72014034Sjavier.bueno@metempsy.com                int k = 0;
72114034Sjavier.bueno@metempsy.com                for (int i = bm; i < depth; i += 1) {
72214034Sjavier.bueno@metempsy.com                    x ^= (!!(path_history[i] & (1 << shift))) << k++;
72314034Sjavier.bueno@metempsy.com                }
72414034Sjavier.bueno@metempsy.com                return x;
72514034Sjavier.bueno@metempsy.com            }
72614034Sjavier.bueno@metempsy.com        }
72714034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
72814034Sjavier.bueno@metempsy.com        {
72914034Sjavier.bueno@metempsy.com            if (mpp.path_length <= p1) {
73014034Sjavier.bueno@metempsy.com                mpp.path_length = p1 + 1;
73114034Sjavier.bueno@metempsy.com            }
73214034Sjavier.bueno@metempsy.com        }
73314034Sjavier.bueno@metempsy.com    };
73414034Sjavier.bueno@metempsy.com
73514034Sjavier.bueno@metempsy.com    class LOCAL : public HistorySpec {
73614034Sjavier.bueno@metempsy.com      public:
73714034Sjavier.bueno@metempsy.com        LOCAL(int p1, double coeff, int size, int width,
73814034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
73914034Sjavier.bueno@metempsy.com            : HistorySpec(p1, 0, 0, coeff, size, width, mpp)
74014034Sjavier.bueno@metempsy.com        {}
74114034Sjavier.bueno@metempsy.com
74214034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
74314034Sjavier.bueno@metempsy.com            override
74414034Sjavier.bueno@metempsy.com        {
74514034Sjavier.bueno@metempsy.com            unsigned int x = mpp.threadData[tid]->localHistories[pc];
74614034Sjavier.bueno@metempsy.com            if (p1 != -1) {
74714034Sjavier.bueno@metempsy.com                x &= ((1 << p1) - 1);
74814034Sjavier.bueno@metempsy.com            }
74914034Sjavier.bueno@metempsy.com            return x;
75014034Sjavier.bueno@metempsy.com        }
75114034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
75214034Sjavier.bueno@metempsy.com        {
75314034Sjavier.bueno@metempsy.com            mpp.doing_local = true;
75414034Sjavier.bueno@metempsy.com        }
75514034Sjavier.bueno@metempsy.com    };
75614034Sjavier.bueno@metempsy.com
75714034Sjavier.bueno@metempsy.com    class MODPATH : public HistorySpec {
75814034Sjavier.bueno@metempsy.com      public:
75914034Sjavier.bueno@metempsy.com        MODPATH(int p1, int p2, int p3, double coeff, int size, int width,
76014034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
76114034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
76214034Sjavier.bueno@metempsy.com        {}
76314034Sjavier.bueno@metempsy.com
76414034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
76514034Sjavier.bueno@metempsy.com            override
76614034Sjavier.bueno@metempsy.com        {
76714034Sjavier.bueno@metempsy.com            int a = p1;
76814034Sjavier.bueno@metempsy.com            int depth = p2;
76914034Sjavier.bueno@metempsy.com            int shift = p3;
77014034Sjavier.bueno@metempsy.com
77114034Sjavier.bueno@metempsy.com            unsigned int x = 0;
77214034Sjavier.bueno@metempsy.com            for (int i=0; i<depth; i += 1) {
77314034Sjavier.bueno@metempsy.com                x <<= shift;
77414034Sjavier.bueno@metempsy.com                x += mpp.threadData[tid]->modpath_histories[a][i];
77514034Sjavier.bueno@metempsy.com            }
77614034Sjavier.bueno@metempsy.com            return x;
77714034Sjavier.bueno@metempsy.com        }
77814034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
77914034Sjavier.bueno@metempsy.com        {
78014034Sjavier.bueno@metempsy.com            mpp.insertModpathSpec(p1, p2);
78114034Sjavier.bueno@metempsy.com        }
78214034Sjavier.bueno@metempsy.com    };
78314034Sjavier.bueno@metempsy.com
78414034Sjavier.bueno@metempsy.com    class GHISTPATH : public HistorySpec {
78514034Sjavier.bueno@metempsy.com      public:
78614034Sjavier.bueno@metempsy.com        GHISTPATH(int p1, int p2, int p3, double coeff, int size, int width,
78714034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
78814034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
78914034Sjavier.bueno@metempsy.com        {}
79014034Sjavier.bueno@metempsy.com
79114034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
79214034Sjavier.bueno@metempsy.com            override
79314034Sjavier.bueno@metempsy.com        {
79414034Sjavier.bueno@metempsy.com            int depth = p1;
79514034Sjavier.bueno@metempsy.com            int shift = p2;
79614034Sjavier.bueno@metempsy.com            int style = p3;
79714034Sjavier.bueno@metempsy.com            std::vector<unsigned int> &ghist_words =
79814034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->ghist_words;
79914034Sjavier.bueno@metempsy.com            std::vector<unsigned short int> &path_history =
80014034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->path_history;
80114034Sjavier.bueno@metempsy.com
80214034Sjavier.bueno@metempsy.com            if (style == -1) {
80314034Sjavier.bueno@metempsy.com                unsigned int x = 0;
80414034Sjavier.bueno@metempsy.com                int bm = (depth / mpp.blockSize) * mpp.blockSize;
80514034Sjavier.bueno@metempsy.com                unsigned int w;
80614034Sjavier.bueno@metempsy.com                for (int i = 0; i < bm; i += mpp.blockSize) {
80714034Sjavier.bueno@metempsy.com                    w = ghist_words[i / mpp.blockSize];
80814034Sjavier.bueno@metempsy.com                    for (int j = 0; j < mpp.blockSize; j += 1) {
80914034Sjavier.bueno@metempsy.com                        x <<= shift;
81014034Sjavier.bueno@metempsy.com                        x += (path_history[i + j] << 1) | (w & 1);
81114034Sjavier.bueno@metempsy.com                        w >>= 1;
81214034Sjavier.bueno@metempsy.com                    }
81314034Sjavier.bueno@metempsy.com                }
81414034Sjavier.bueno@metempsy.com                w = ghist_words[bm / mpp.blockSize];
81514034Sjavier.bueno@metempsy.com                for (int i = bm; i < depth; i += 1) {
81614034Sjavier.bueno@metempsy.com                    x <<= shift;
81714034Sjavier.bueno@metempsy.com                    x += (path_history[i] << 1) | (w & 1);
81814034Sjavier.bueno@metempsy.com                    w >>= 1;
81914034Sjavier.bueno@metempsy.com                }
82014034Sjavier.bueno@metempsy.com                return x;
82114034Sjavier.bueno@metempsy.com            } else {
82214034Sjavier.bueno@metempsy.com                unsigned int x = 0;
82314034Sjavier.bueno@metempsy.com                int bm = (depth / mpp.blockSize) * mpp.blockSize;
82414034Sjavier.bueno@metempsy.com                unsigned int w = 0;
82514034Sjavier.bueno@metempsy.com                for (int i = 0; i < bm; i += mpp.blockSize) {
82614034Sjavier.bueno@metempsy.com                    w = ghist_words[i / mpp.blockSize];
82714034Sjavier.bueno@metempsy.com                    for (int j = 0; j < mpp.blockSize; j += 1) {
82814034Sjavier.bueno@metempsy.com                        x ^= (!!(path_history[i + j] & (1 << shift))) << j;
82914034Sjavier.bueno@metempsy.com                        x ^= (w & 1) << j;
83014034Sjavier.bueno@metempsy.com                        w >>= 1;
83114034Sjavier.bueno@metempsy.com                    }
83214034Sjavier.bueno@metempsy.com                }
83314034Sjavier.bueno@metempsy.com                w = ghist_words[bm/mpp.blockSize];
83414034Sjavier.bueno@metempsy.com                int k = 0;
83514034Sjavier.bueno@metempsy.com                for (int i = bm; i < depth; i += 1) {
83614034Sjavier.bueno@metempsy.com                    x ^= (!!(path_history[i] & (1 << shift))) << k;
83714034Sjavier.bueno@metempsy.com                    x ^= (w & 1) << k;
83814034Sjavier.bueno@metempsy.com                    w >>= 1;
83914034Sjavier.bueno@metempsy.com                    k += 1;
84014034Sjavier.bueno@metempsy.com                }
84114034Sjavier.bueno@metempsy.com                return x;
84214034Sjavier.bueno@metempsy.com            }
84314034Sjavier.bueno@metempsy.com        }
84414034Sjavier.bueno@metempsy.com
84514034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
84614034Sjavier.bueno@metempsy.com        {
84714034Sjavier.bueno@metempsy.com            if (mpp.ghist_length <= p1) {
84814034Sjavier.bueno@metempsy.com                mpp.ghist_length = p1 + 1;
84914034Sjavier.bueno@metempsy.com            }
85014034Sjavier.bueno@metempsy.com            if (mpp.path_length <= p1) {
85114034Sjavier.bueno@metempsy.com                mpp.path_length = p1 + 1;
85214034Sjavier.bueno@metempsy.com            }
85314034Sjavier.bueno@metempsy.com        }
85414034Sjavier.bueno@metempsy.com    };
85514034Sjavier.bueno@metempsy.com
85614034Sjavier.bueno@metempsy.com    class GHISTMODPATH : public HistorySpec {
85714034Sjavier.bueno@metempsy.com      public:
85814034Sjavier.bueno@metempsy.com        GHISTMODPATH(int p1, int p2, int p3, double coeff, int size, int width,
85914034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
86014034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
86114034Sjavier.bueno@metempsy.com        {}
86214034Sjavier.bueno@metempsy.com
86314034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
86414034Sjavier.bueno@metempsy.com            override
86514034Sjavier.bueno@metempsy.com        {
86614034Sjavier.bueno@metempsy.com            int a = p1;
86714034Sjavier.bueno@metempsy.com            int depth = p2;
86814034Sjavier.bueno@metempsy.com            int shift = p3;
86914034Sjavier.bueno@metempsy.com            std::vector<std::vector<unsigned short int>> &modpath_histories =
87014034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->modpath_histories;
87114034Sjavier.bueno@metempsy.com            std::vector<std::vector<bool>> &mod_histories =
87214034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->mod_histories;
87314034Sjavier.bueno@metempsy.com
87414034Sjavier.bueno@metempsy.com            unsigned int x = 0;
87514034Sjavier.bueno@metempsy.com            for (int i = 0; i < depth; i += 1) {
87614034Sjavier.bueno@metempsy.com                x <<= shift;
87714034Sjavier.bueno@metempsy.com                x += (modpath_histories[a][i] << 1) | mod_histories[a][i];
87814034Sjavier.bueno@metempsy.com            }
87914034Sjavier.bueno@metempsy.com            return x;
88014034Sjavier.bueno@metempsy.com        }
88114034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
88214034Sjavier.bueno@metempsy.com        {
88314034Sjavier.bueno@metempsy.com            mpp.insertModhistSpec(p1, p2);
88414034Sjavier.bueno@metempsy.com            mpp.insertModpathSpec(p1, p2);
88514034Sjavier.bueno@metempsy.com        }
88614034Sjavier.bueno@metempsy.com    };
88714034Sjavier.bueno@metempsy.com
88814034Sjavier.bueno@metempsy.com    class BLURRYPATH : public HistorySpec {
88914034Sjavier.bueno@metempsy.com      public:
89014034Sjavier.bueno@metempsy.com        BLURRYPATH(int p1, int p2, int p3, double coeff, int size, int width,
89114034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
89214034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
89314034Sjavier.bueno@metempsy.com        {}
89414034Sjavier.bueno@metempsy.com
89514034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
89614034Sjavier.bueno@metempsy.com            override
89714034Sjavier.bueno@metempsy.com        {
89814034Sjavier.bueno@metempsy.com            int scale = p1;
89914034Sjavier.bueno@metempsy.com            int depth = p2;
90014034Sjavier.bueno@metempsy.com            int shiftdelta = p3;
90114034Sjavier.bueno@metempsy.com
90214034Sjavier.bueno@metempsy.com            if (shiftdelta == -1) shiftdelta = 0;
90314034Sjavier.bueno@metempsy.com            int sdint = shiftdelta >> 2;
90414034Sjavier.bueno@metempsy.com            int sdfrac = shiftdelta & 3;
90514034Sjavier.bueno@metempsy.com            unsigned int x = 0;
90614034Sjavier.bueno@metempsy.com            int shift = 0;
90714034Sjavier.bueno@metempsy.com            int count = 0;
90814034Sjavier.bueno@metempsy.com            for (int i = 0; i < depth; i += 1) {
90914034Sjavier.bueno@metempsy.com                x += mpp.threadData[tid]->blurrypath_histories[scale][i] >>
91014034Sjavier.bueno@metempsy.com                    shift;
91114034Sjavier.bueno@metempsy.com                count += 1;
91214034Sjavier.bueno@metempsy.com                if (count == sdfrac) {
91314034Sjavier.bueno@metempsy.com                    shift += sdint;
91414034Sjavier.bueno@metempsy.com                    count = 0;
91514034Sjavier.bueno@metempsy.com                }
91614034Sjavier.bueno@metempsy.com            }
91714034Sjavier.bueno@metempsy.com            return x;
91814034Sjavier.bueno@metempsy.com
91914034Sjavier.bueno@metempsy.com        }
92014034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
92114034Sjavier.bueno@metempsy.com        {
92214034Sjavier.bueno@metempsy.com            if (mpp.blurrypath_bits.size() < (p1 + 1)) {
92314034Sjavier.bueno@metempsy.com                mpp.blurrypath_bits.resize(p1 + 1);
92414034Sjavier.bueno@metempsy.com            }
92514034Sjavier.bueno@metempsy.com            if (mpp.blurrypath_bits[p1].size() < p2) {
92614034Sjavier.bueno@metempsy.com                mpp.blurrypath_bits[p1].resize(p2);
92714034Sjavier.bueno@metempsy.com            }
92814034Sjavier.bueno@metempsy.com            for (int j = 0; j < p2; j += 1) {
92914034Sjavier.bueno@metempsy.com                mpp.blurrypath_bits[p1][j] = 32 - p1;
93014034Sjavier.bueno@metempsy.com            }
93114034Sjavier.bueno@metempsy.com        }
93214034Sjavier.bueno@metempsy.com    };
93314034Sjavier.bueno@metempsy.com
93414034Sjavier.bueno@metempsy.com    class RECENCYPOS : public HistorySpec {
93514034Sjavier.bueno@metempsy.com      public:
93614034Sjavier.bueno@metempsy.com        RECENCYPOS(int p1, double coeff, int size, int width,
93714034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
93814034Sjavier.bueno@metempsy.com            : HistorySpec(p1, 0, 0, coeff, size, width, mpp)
93914034Sjavier.bueno@metempsy.com        {}
94014034Sjavier.bueno@metempsy.com
94114034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
94214034Sjavier.bueno@metempsy.com            override
94314034Sjavier.bueno@metempsy.com        {
94414034Sjavier.bueno@metempsy.com            return hash(mpp.threadData[tid]->recency_stack, mpp.table_sizes,
94514034Sjavier.bueno@metempsy.com                    pc2, p1, t);
94614034Sjavier.bueno@metempsy.com        }
94714034Sjavier.bueno@metempsy.com
94814034Sjavier.bueno@metempsy.com        static unsigned int hash(
94914034Sjavier.bueno@metempsy.com            const std::vector<unsigned int short> &recency_stack,
95014034Sjavier.bueno@metempsy.com            const std::vector<int> &table_sizes, unsigned short int pc, int l,
95114034Sjavier.bueno@metempsy.com            int t)
95214034Sjavier.bueno@metempsy.com        {
95314034Sjavier.bueno@metempsy.com            // search for the PC
95414034Sjavier.bueno@metempsy.com
95514034Sjavier.bueno@metempsy.com            for (int i = 0; i < l; i += 1) {
95614034Sjavier.bueno@metempsy.com                if (recency_stack[i] == pc) {
95714034Sjavier.bueno@metempsy.com                    return i * table_sizes[t] / l;
95814034Sjavier.bueno@metempsy.com                }
95914034Sjavier.bueno@metempsy.com            }
96014034Sjavier.bueno@metempsy.com
96114034Sjavier.bueno@metempsy.com            // return last index in table on a miss
96214034Sjavier.bueno@metempsy.com
96314034Sjavier.bueno@metempsy.com            return table_sizes[t] - 1;
96414034Sjavier.bueno@metempsy.com        }
96514034Sjavier.bueno@metempsy.com
96614034Sjavier.bueno@metempsy.com        void setBitRequirements() const override
96714034Sjavier.bueno@metempsy.com        {
96814034Sjavier.bueno@metempsy.com            if (mpp.assoc < p1) {
96914034Sjavier.bueno@metempsy.com                mpp.assoc = p1;
97014034Sjavier.bueno@metempsy.com            }
97114034Sjavier.bueno@metempsy.com            mpp.doing_recency = true;
97214034Sjavier.bueno@metempsy.com        }
97314034Sjavier.bueno@metempsy.com    };
97414034Sjavier.bueno@metempsy.com
97514034Sjavier.bueno@metempsy.com    class SGHISTPATH : public HistorySpec {
97614034Sjavier.bueno@metempsy.com      public:
97714034Sjavier.bueno@metempsy.com        SGHISTPATH(int p1, int p2, int p3, double coeff, int size, int width,
97814034Sjavier.bueno@metempsy.com                MultiperspectivePerceptron &mpp)
97914034Sjavier.bueno@metempsy.com            : HistorySpec(p1, p2, p3, coeff, size, width, mpp)
98014034Sjavier.bueno@metempsy.com        {}
98114034Sjavier.bueno@metempsy.com
98214034Sjavier.bueno@metempsy.com        unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
98314034Sjavier.bueno@metempsy.com            override
98414034Sjavier.bueno@metempsy.com        {
98514034Sjavier.bueno@metempsy.com            int a = p1;
98614034Sjavier.bueno@metempsy.com            int b = p2;
98714034Sjavier.bueno@metempsy.com            int shift = p3;
98814034Sjavier.bueno@metempsy.com            std::vector<unsigned int> &ghist_words =
98914034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->ghist_words;
99014034Sjavier.bueno@metempsy.com            std::vector<unsigned short int> &path_history =
99114034Sjavier.bueno@metempsy.com                mpp.threadData[tid]->path_history;
99214034Sjavier.bueno@metempsy.com
99314034Sjavier.bueno@metempsy.com            unsigned int x = 0;
99414034Sjavier.bueno@metempsy.com            int bm = (b / mpp.blockSize) * mpp.blockSize;
99514034Sjavier.bueno@metempsy.com            unsigned int w;
99614034Sjavier.bueno@metempsy.com            for (int i = a; i < bm; i += mpp.blockSize) {
99714034Sjavier.bueno@metempsy.com                w = ghist_words[i / mpp.blockSize];
99814034Sjavier.bueno@metempsy.com                for (int j = 0; j < mpp.blockSize; j += 1) {
99914034Sjavier.bueno@metempsy.com                    x <<= shift;
100014034Sjavier.bueno@metempsy.com                    x += (path_history[i+j] << 1) | (w & 1);
100114034Sjavier.bueno@metempsy.com                    w >>= 1;
100214034Sjavier.bueno@metempsy.com                }
100314034Sjavier.bueno@metempsy.com            }
100414034Sjavier.bueno@metempsy.com            w = ghist_words[bm / mpp.blockSize];
100514034Sjavier.bueno@metempsy.com            for (int i = bm; i < b; i += 1) {
100614034Sjavier.bueno@metempsy.com                x <<= shift;
100714034Sjavier.bueno@metempsy.com                x += (path_history[i] << 1) | (w & 1);
100814034Sjavier.bueno@metempsy.com                w >>= 1;
100914034Sjavier.bueno@metempsy.com            }
101014034Sjavier.bueno@metempsy.com            return x;
101114034Sjavier.bueno@metempsy.com        }
101214034Sjavier.bueno@metempsy.com    };
101314034Sjavier.bueno@metempsy.com
101414034Sjavier.bueno@metempsy.com    public:
101514034Sjavier.bueno@metempsy.com    MultiperspectivePerceptron(const MultiperspectivePerceptronParams *params);
101614034Sjavier.bueno@metempsy.com
101714081Sjavier.bueno@metempsy.com    /**
101814081Sjavier.bueno@metempsy.com     * Sets the starting number of storage bits to compute the number of
101914081Sjavier.bueno@metempsy.com     * table entries
102014081Sjavier.bueno@metempsy.com     * @param bits number of bits used
102114081Sjavier.bueno@metempsy.com     */
102214081Sjavier.bueno@metempsy.com    void setExtraBits(int bits);
102314081Sjavier.bueno@metempsy.com
102414034Sjavier.bueno@metempsy.com    void init() override;
102514034Sjavier.bueno@metempsy.com
102614034Sjavier.bueno@metempsy.com    void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) override;
102714034Sjavier.bueno@metempsy.com    void squash(ThreadID tid, void *bp_history) override;
102814034Sjavier.bueno@metempsy.com    bool lookup(ThreadID tid, Addr instPC, void * &bp_history) override;
102914034Sjavier.bueno@metempsy.com    void update(ThreadID tid, Addr instPC, bool taken,
103014034Sjavier.bueno@metempsy.com            void *bp_history, bool squashed,
103114034Sjavier.bueno@metempsy.com            const StaticInstPtr & inst,
103214034Sjavier.bueno@metempsy.com            Addr corrTarget = MaxAddr) override;
103314034Sjavier.bueno@metempsy.com    void btbUpdate(ThreadID tid, Addr branch_addr, void* &bp_history) override;
103414034Sjavier.bueno@metempsy.com};
103514034Sjavier.bueno@metempsy.com#endif//__CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__
1036