39 #ifndef __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__ 40 #define __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__ 46 #include "params/MultiperspectivePerceptron.hh" 56 const unsigned int pc;
58 const unsigned short int pc2;
60 const unsigned short int hpc;
67 static inline unsigned int hash1(
unsigned int a)
69 a = (a ^ 0xdeadbeef) + (a<<4);
76 static inline unsigned int hash2(
unsigned int key)
79 key = (key ^ 61) ^ (key >> 16);
80 key = key + (key << 3);
81 key = key ^ (key >> 4);
83 key = key ^ (key >> 15);
87 static inline unsigned int hash(
unsigned int key,
unsigned int i)
95 return hash(pc, -pcshift);
96 }
else if (pcshift < 11) {
101 return pc >> (pcshift-11);
114 pc2(pc >> 2), hpc(
hashPC(pc, pcshift)), condBranch(cb),
115 filtered(false), prediction(false), yout(0)
132 return last_ghist_bit ^
hpc;
153 return seenUntaken & !seenTaken;
157 return seenTaken & !seenUntaken;
161 return !seenTaken && !seenUntaken;
178 return (pc >> 2) % localHistories.size();
182 localHistories(nlocal_histories), localHistoryLength(histo_len) {}
187 return localHistories[
index(pc)];
193 assert(localHistories.size() > 0);
194 unsigned int &pos = localHistories[
index(pc)];
197 pos &= ((1<<localHistoryLength)-1);
203 return localHistoryLength;
209 return localHistoryLength * localHistories.size();
234 p2(_p2), p3(_p3), coeff(_coeff), size(_size), width(_width),
289 ThreadData(
int num_filter,
int n_local_histories,
290 int local_history_length,
int assoc,
305 for (
int i = 0;
i < acyclic_histories.size();
i += 1) {
306 if (acyclic_histories[
i].size() > 0) {
307 acyclic_histories[
i][hpc%(
i+2)] = hashed_taken;
308 acyclic2_histories[
i][hpc%(
i+2)] = hpc;
324 for (i = 0; i <
assoc; i += 1) {
325 if (recency_stack[i] == pc) {
331 recency_stack[
i] =
pc;
334 unsigned int b = recency_stack[
i];
335 for (j = i; j >= 1; j -= 1) {
336 recency_stack[
j] = recency_stack[j-1];
338 recency_stack[0] =
b;
374 int j =
insert(modhist_indices, p1);
375 if (modhist_lengths.size() < (j + 1)) {
376 modhist_lengths.resize(j + 1);
378 if (modhist_lengths[j] < p2 + 1) {
379 modhist_lengths[
j] = p2 + 1;
381 if (p2 >= modghist_length) {
382 modghist_length = p2 + 1;
388 int j =
insert(modpath_indices, p1);
389 if (modpath_lengths.size() < (j + 1)) {
390 modpath_lengths.resize(j + 1);
392 if (modpath_lengths[j] < p2 + 1) {
393 modpath_lengths[
j] = p2 + 1;
395 if (p2 >= path_length) {
396 path_length = p2 + 1;
403 for (
int i = 0;
i < v.size();
i += 1) {
421 void computeBits(
int num_filter_entries,
int nlocal_histories,
422 int local_history_length,
bool ignore_path_size);
473 void satIncDec(
bool taken,
bool &sign,
int &
c,
int max_weight)
const;
478 specs.push_back(spec);
493 return hash(
mpp.threadData[tid]->ghist_words,
mpp.blockSize, p1,
498 int block_size,
int start_pos,
int end_pos)
505 int am = (((a/block_size)*block_size)+block_size);
507 int bm = (b/block_size)*block_size;
515 x += ghist_words[a / block_size] >> (a-
am);
517 for (
int i=am;
i<bm;
i+=block_size) {
518 x += ghist_words[
i / block_size];
522 unsigned int y = ghist_words[bm / block_size] & ((1<<(b - bm))-1);
523 x += y << (block_size - (b - bm));
528 if (
mpp.ghist_length <= p2) {
529 mpp.ghist_length = p2 + 1;
548 mpp.threadData[tid]->acyclic_histories;
550 mpp.threadData[tid]->acyclic2_histories;
555 for (
int i = 0;
i < a + 2;
i += 1) {
556 x ^= acyclic_histories[
a][
i] <<
k;
561 for (
int i = 0;
i < a + 2;
i += 1) {
563 x += acyclic2_histories[
a][
i];
570 if (
mpp.acyclic_bits.size() < (p1 + 1)) {
571 mpp.acyclic_bits.resize(p1 + 1);
573 if (
mpp.acyclic_bits[p1].size() < (p1 + 2)) {
576 for (
int j = 0;
j < p1 + 2;
j += 1) {
577 mpp.acyclic_bits[p1][
j][!p3] =
true;
595 mpp.threadData[tid]->mod_histories;
597 unsigned int x = 0,
k = 0;
598 for (
int i = 0;
i <
b;
i += 1) {
599 x ^= mod_histories[
a][
i] <<
k;
607 mpp.insertModhistSpec(p1, p2);
640 mpp.threadData[tid]->recency_stack;
644 for (
int i = 0;
i < depth;
i += 1) {
646 x += recency_stack[
i];
650 unsigned int x = 0,
k = 0;
651 for (
int i = 0;
i < depth;
i += 1) {
652 x ^= (!!(recency_stack[
i] & (1 <<
shift))) <<
k;
661 if (
mpp.assoc < p1) {
664 mpp.doing_recency =
true;
680 return mpp.threadData[tid]->imli_counter[p1-1];
685 mpp.imli_counter_bits[p1 - 1] = 32;
691 PATH(
int p1,
int p2,
int p3,
double coeff,
int size,
int width,
703 mpp.threadData[tid]->path_history;
707 for (
int i = 0;
i < depth;
i += 1) {
709 x += path_history[
i];
714 int bm = (depth /
mpp.blockSize) *
mpp.blockSize;
715 for (
int i = 0;
i < bm;
i +=
mpp.blockSize) {
716 for (
int j = 0;
j <
mpp.blockSize;
j += 1) {
717 x ^= (!!(path_history[
i +
j] & (1 <<
shift))) <<
j;
721 for (
int i = bm;
i < depth;
i += 1) {
722 x ^= (!!(path_history[
i] & (1 <<
shift))) << k++;
729 if (
mpp.path_length <= p1) {
730 mpp.path_length = p1 + 1;
745 unsigned int x =
mpp.threadData[tid]->localHistories[
pc];
747 x &= ((1 << p1) - 1);
753 mpp.doing_local =
true;
772 for (
int i=0;
i<depth;
i += 1) {
774 x +=
mpp.threadData[tid]->modpath_histories[
a][
i];
780 mpp.insertModpathSpec(p1, p2);
798 mpp.threadData[tid]->ghist_words;
800 mpp.threadData[tid]->path_history;
804 int bm = (depth /
mpp.blockSize) *
mpp.blockSize;
806 for (
int i = 0;
i < bm;
i +=
mpp.blockSize) {
807 w = ghist_words[
i /
mpp.blockSize];
808 for (
int j = 0;
j <
mpp.blockSize;
j += 1) {
810 x += (path_history[
i +
j] << 1) | (
w & 1);
814 w = ghist_words[bm /
mpp.blockSize];
815 for (
int i = bm;
i < depth;
i += 1) {
817 x += (path_history[
i] << 1) | (
w & 1);
823 int bm = (depth /
mpp.blockSize) *
mpp.blockSize;
825 for (
int i = 0;
i < bm;
i +=
mpp.blockSize) {
826 w = ghist_words[
i /
mpp.blockSize];
827 for (
int j = 0;
j <
mpp.blockSize;
j += 1) {
828 x ^= (!!(path_history[
i +
j] & (1 <<
shift))) <<
j;
833 w = ghist_words[bm/
mpp.blockSize];
835 for (
int i = bm;
i < depth;
i += 1) {
836 x ^= (!!(path_history[
i] & (1 <<
shift))) << k;
847 if (
mpp.ghist_length <= p1) {
848 mpp.ghist_length = p1 + 1;
850 if (
mpp.path_length <= p1) {
851 mpp.path_length = p1 + 1;
870 mpp.threadData[tid]->modpath_histories;
872 mpp.threadData[tid]->mod_histories;
875 for (
int i = 0;
i < depth;
i += 1) {
877 x += (modpath_histories[
a][
i] << 1) | mod_histories[a][
i];
883 mpp.insertModhistSpec(p1, p2);
884 mpp.insertModpathSpec(p1, p2);
902 if (shiftdelta == -1) shiftdelta = 0;
903 int sdint = shiftdelta >> 2;
904 int sdfrac = shiftdelta & 3;
908 for (
int i = 0;
i < depth;
i += 1) {
909 x +=
mpp.threadData[tid]->blurrypath_histories[
scale][
i] >>
912 if (count == sdfrac) {
922 if (
mpp.blurrypath_bits.size() < (p1 + 1)) {
923 mpp.blurrypath_bits.resize(p1 + 1);
925 if (
mpp.blurrypath_bits[p1].size() < p2) {
926 mpp.blurrypath_bits[p1].resize(p2);
928 for (
int j = 0;
j < p2;
j += 1) {
929 mpp.blurrypath_bits[p1][
j] = 32 - p1;
944 return hash(
mpp.threadData[tid]->recency_stack,
mpp.table_sizes,
955 for (
int i = 0;
i <
l;
i += 1) {
956 if (recency_stack[
i] == pc) {
957 return i * table_sizes[
t] /
l;
963 return table_sizes[
t] - 1;
968 if (
mpp.assoc < p1) {
971 mpp.doing_recency =
true;
989 mpp.threadData[tid]->ghist_words;
991 mpp.threadData[tid]->path_history;
994 int bm = (b /
mpp.blockSize) *
mpp.blockSize;
996 for (
int i = a;
i < bm;
i +=
mpp.blockSize) {
997 w = ghist_words[
i /
mpp.blockSize];
998 for (
int j = 0;
j <
mpp.blockSize;
j += 1) {
1000 x += (path_history[
i+
j] << 1) | (
w & 1);
1004 w = ghist_words[bm /
mpp.blockSize];
1005 for (
int i = bm;
i <
b;
i += 1) {
1007 x += (path_history[
i] << 1) | (
w & 1);
1024 void init()
override;
1030 void *bp_history,
bool squashed,
1035 #endif//__CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__ void updateAcyclic(bool hashed_taken, unsigned int hpc)
Base class to implement the predictor tables.
MODPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
const unsigned short int pc2
pc of the branch, shifted 2 bits to the right
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
std::vector< unsigned int > ghist_words
void uncondBranch(ThreadID tid, Addr pc, void *&bp_history) override
unsigned short int getPC2() const
BLURRYPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
const unsigned int record_mask
MODHIST(int p1, int p2, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
unsigned int index(Addr pc) const
Index function given the pc of the branch.
bool neverSeen() const
Whether this branch has been observed before.
std::vector< std::vector< unsigned int > > blurrypath_histories
unsigned int getHashFilter(bool last_ghist_bit) const
const double coeff
Coefficient of the feature, models the accuracy of the feature.
const unsigned int pc
pc of the branch
const int blockSize
Predictor parameters.
MultiperspectivePerceptron(const MultiperspectivePerceptronParams *params)
static int xlat4[]
Transfer function for 5-width tables.
LocalHistories localHistories
std::vector< std::vector< unsigned int > > acyclic2_histories
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
const bool speculative_update
MPPBranchInfo(Addr _pc, int pcshift, bool cb)
std::vector< std::vector< bool > > acyclic_histories
unsigned int getPC() const
std::vector< unsigned int > imli_counter
std::vector< FilterEntry > filterTable
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
bool prediction
Result of the prediction (true is taken)
const bool condBranch
Whether this is a conditional branch.
void insertRecency(unsigned int pc, int assoc)
LOCAL(int p1, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
void update(Addr pc, bool value)
Adds a history bit to the local history entry of a given branch.
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
std::vector< std::vector< short int > > tables
int yout
Score of the perceptron.
History data is kept for each thread.
static unsigned int hash1(unsigned int a)
PC Hash functions.
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
void setExtraBits(int bits)
Sets the starting number of storage bits to compute the number of table entries.
bool alwaysTakenSoFar() const
Whether this branch has always been observed as taken.
void insertModhistSpec(int p1, int p2)
Auxiliary function for MODHIST and GHISTMODPATH features.
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
void btbUpdate(ThreadID tid, Addr branch_addr, void *&bp_history) override
If a branch is not taken, because the BTB address is invalid or missing, this function sets the appro...
void addSpec(HistorySpec *spec)
Add a table spec to the prefetcher.
static unsigned int hashPC(unsigned int pc, int pcshift)
RECENCYPOS(int p1, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
std::vector< std::vector< std::array< bool, 2 > > > sign_bits
std::vector< int > modhist_indices
PATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
std::vector< int > imli_counter_bits
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
virtual void createSpecs()=0
Creates the tables of the predictor.
const Params * params() const
static int xlat[]
Transfer function for 6-width tables.
bool seenUntaken
Has this branch been not taken at least once?
static unsigned int hash2(unsigned int key)
const unsigned long long int imli_mask1
const int size
Pre-assigned size in bits assigned to this feature.
std::vector< int > table_sizes
void update(ThreadID tid, Addr instPC, bool taken, void *bp_history, bool squashed, const StaticInstPtr &inst, Addr corrTarget=MaxAddr) override
Updates the BP with taken/not taken information.
std::vector< std::vector< bool > > mod_histories
bool isUnconditional() const
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
void squash(ThreadID tid, void *bp_history) override
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
GHIST(int p1, int p2, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
const unsigned short int hpc
pc of the branch, hashed
std::vector< ThreadData * > threadData
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
const unsigned long long int recencypos_mask
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
int getSize() const
Size in bits required by all history entries.
unsigned short int getHPC() const
bool seenTaken
Has this branch been taken at least once?
void findBest(ThreadID tid, std::vector< int > &best_preds) const
Finds the best subset of features to use in case of a low-confidence branch, returns the result as an...
std::vector< int > modhist_lengths
std::vector< unsigned int short > recency_stack
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
bool filtered
Whether this branch has been filtered by the prefetcher.
Basically a wrapper class to hold both the branch predictor and the BTB.
int16_t ThreadID
Thread index/ID type.
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
RECENCY(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
GHISTPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
unsigned int getIndex(ThreadID tid, const MPPBranchInfo &bi, const HistorySpec &spec, int index) const
Get the position index of a predictor table.
Local history entries, each enty contains the history of directions taken by a given branch...
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
IMLI(int p1, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
const unsigned long long int imli_mask4
HistorySpec(int _p1, int _p2, int _p3, double _coeff, int _size, int _width, MultiperspectivePerceptron &_mpp)
void computeBits(int num_filter_entries, int nlocal_histories, int local_history_length, bool ignore_path_size)
Computes the size in bits of the structures needed to keep track of the history and the predictor tab...
bool doing_local
runtime values and data used to count the size in bits
GHISTMODPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
const int localHistoryLength
Size in bits of each history entry.
std::vector< unsigned int > localHistories
The array of histories.
std::vector< HistorySpec * > specs
Predictor tables.
bool alwaysNotTakenSoFar() const
Whether this branch has always been observed as not taken.
std::vector< std::vector< unsigned short int > > modpath_histories
unsigned int operator[](Addr pc) const
Obtains the local history entry of a given branch.
void satIncDec(bool taken, bool &sign, int &c, int max_weight) const
Auxiliary function to increase a table counter depending on the direction of the branch.
BIAS(double coeff, int size, int width, MultiperspectivePerceptron &mpp)
static unsigned int hash(const std::vector< unsigned int short > &recency_stack, const std::vector< int > &table_sizes, unsigned short int pc, int l, int t)
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
const int width
Width of the table in bits.
Entry of the branch filter.
void train(ThreadID tid, MPPBranchInfo &bi, bool taken)
Trains the branch predictor with the given branch and direction.
const int p3
Third parameter.
int computeOutput(ThreadID tid, MPPBranchInfo &bi)
Computes the output of the predictor for a given branch and the resulting best value in case the pred...
MultiperspectivePerceptron & mpp
Reference to the branch predictor class.
static unsigned int hash(unsigned int key, unsigned int i)
const int p1
First parameter.
std::vector< int > modpath_lengths
std::vector< int > mpreds
ACYCLIC(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
bool lookup(ThreadID tid, Addr instPC, void *&bp_history) override
Looks up a given PC in the BP to see if it is taken or not taken.
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
std::vector< std::vector< int > > blurrypath_bits
std::vector< std::vector< std::vector< bool > > > acyclic_bits
static unsigned int hash(const std::vector< unsigned int > &ghist_words, int block_size, int start_pos, int end_pos)
int insert(std::vector< int > &v, int x)
Auxiliary function used by insertModhistSpec and insertModpathSpec.
int getLocalHistoryLength() const
Returns the number of bits of each local history entry.
const int p2
Second parameter.
virtual void setBitRequirements() const
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
SGHISTPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
std::vector< unsigned short int > path_history
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const override
Gets the hash to index the table, using the pc of the branch, and the index of the table...
std::vector< int > modpath_indices
void insertModpathSpec(int p1, int p2)
Auxiliary function for MODPATH and GHISTMODPATH features.
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...
LocalHistories(int nlocal_histories, int histo_len)
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables...