gem5 v24.1.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
multiperspective_perceptron.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022-2023 The University of Edinburgh
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright 2019 Texas A&M University
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright notice,
20 * this list of conditions and the following disclaimer.
21 *
22 * 2. Redistributions in binary form must reproduce the above copyright notice,
23 * this list of conditions and the following disclaimer in the documentation
24 * and/or other materials provided with the distribution.
25 *
26 * 3. Neither the name of the copyright holder nor the names of its
27 * contributors may be used to endorse or promote products derived from this
28 * software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 * Author: Daniel A. Jiménez
43 * Adapted to gem5 by: Javier Bueno Hedo
44 *
45 */
46
47/*
48 * Multiperspective Perceptron Predictor (by Daniel A. Jiménez)
49 */
50
51#ifndef __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__
52#define __CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__
53
54#include <array>
55#include <vector>
56
57#include "base/random.hh"
59#include "params/MultiperspectivePerceptron.hh"
60
61namespace gem5
62{
63
64namespace branch_prediction
65{
66
68{
69 protected:
74 {
76 const unsigned int pc;
78 const unsigned short int pc2;
80 const unsigned short int hpc;
82 const bool condBranch;
83
87 static inline unsigned int hash1(unsigned int a)
88 {
89 a = (a ^ 0xdeadbeef) + (a<<4);
90 a = a ^ (a>>10);
91 a = a + (a<<7);
92 a = a ^ (a>>13);
93 return a;
94 }
95
96 static inline unsigned int hash2(unsigned int key)
97 {
98 int c2 = 0x27d4eb2d; // a prime or an odd constant
99 key = (key ^ 61) ^ (key >> 16);
100 key = key + (key << 3);
101 key = key ^ (key >> 4);
102 key = key * c2;
103 key = key ^ (key >> 15);
104 return key;
105 }
106
107 static inline unsigned int hash(unsigned int key, unsigned int i)
108 {
109 return hash2(key) * i + hash1(key);
110 }
111
112 static inline unsigned int hashPC(unsigned int pc, int pcshift)
113 {
114 if (pcshift < 0) {
115 return hash(pc, -pcshift);
116 } else if (pcshift < 11) {
117 unsigned int x = pc;
118 x ^= (pc >> pcshift);
119 return x;
120 } else {
121 return pc >> (pcshift-11);
122 }
123 }
124
125 public:
131 int yout;
132
133 MPPBranchInfo(Addr _pc, int pcshift, bool cb) : pc((unsigned int)_pc),
134 pc2(pc >> 2), hpc(hashPC(pc, pcshift)), condBranch(cb),
135 filtered(false), prediction(false), yout(0)
136 { }
137
138 unsigned int getPC() const
139 {
140 return pc;
141 }
142 unsigned short int getPC2() const
143 {
144 return pc2;
145 }
146 unsigned short int getHPC() const
147 {
148 return hpc;
149 }
150 unsigned int getHashFilter(bool last_ghist_bit) const
151 {
152 return last_ghist_bit ^ hpc;
153 }
154 bool isUnconditional() const
155 {
156 return !condBranch;
157 }
158 };
159
164 {
169
170 FilterEntry() : seenTaken(false), seenUntaken(false) {}
171
173 bool alwaysNotTakenSoFar() const {
174 return seenUntaken & !seenTaken;
175 }
177 bool alwaysTakenSoFar() const {
178 return seenTaken & !seenUntaken;
179 }
181 bool neverSeen() const {
182 return !seenTaken && !seenUntaken;
183 }
184 };
185
186
192 {
197
199 unsigned int index(Addr pc) const {
200 return (pc >> 2) % localHistories.size();
201 }
202 public:
203 LocalHistories(int nlocal_histories, int histo_len) :
204 localHistories(nlocal_histories), localHistoryLength(histo_len) {}
205
207 unsigned int operator[](Addr pc) const
208 {
209 return localHistories[index(pc)];
210 }
211
213 void update(Addr pc, bool value)
214 {
215 assert(localHistories.size() > 0);
216 unsigned int &pos = localHistories[index(pc)];
217 pos <<= 1;
218 pos |= value;
219 pos &= ((1<<localHistoryLength)-1);
220 }
221
224 {
225 return localHistoryLength;
226 }
227
229 int getSize() const
230 {
231 return localHistoryLength * localHistories.size();
232 }
233 };
234
239 {
241 const int p1;
243 const int p2;
245 const int p3;
247 const double coeff;
249 const int size;
251 const int width;
254
255 HistorySpec(int _p1, int _p2, int _p3, double _coeff, int _size,
256 int _width, MultiperspectivePerceptron &_mpp) : p1(_p1),
257 p2(_p2), p3(_p3), coeff(_coeff), size(_size), width(_width),
258 mpp(_mpp)
259 {}
260
270 virtual unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t)
271 const = 0;
276 virtual void setBitRequirements() const {}
277 };
278
280 const int blockSize;
281 const int pcshift;
282 const int threshold;
283 const int bias0;
284 const int bias1;
285 const int biasmostly0;
286 const int biasmostly1;
287 const int nbest;
288 const int tunebits;
289 const int hshift;
290 const unsigned long long int imli_mask1;
291 const unsigned long long int imli_mask4;
292 const unsigned long long int recencypos_mask;
293 const double fudge;
294 const int n_sign_bits;
295 const int pcbit;
296 const int decay;
297 const unsigned int record_mask;
298 const bool hash_taken;
299 const bool tuneonly;
300 const int extra_rounds;
301 const int speed;
302 const int budgetbits;
304
306 static int xlat[];
308 static int xlat4[];
309
311
314 {
315 ThreadData(int num_filter, int n_local_histories,
316 int local_history_length, int assoc,
318 int path_length, int ghist_length, int block_size,
325
329
330 void updateAcyclic(bool hashed_taken, unsigned int hpc) {
331 for (int i = 0; i < acyclic_histories.size(); i += 1) {
332 if (acyclic_histories[i].size() > 0) {
333 acyclic_histories[i][hpc%(i+2)] = hashed_taken;
334 acyclic2_histories[i][hpc%(i+2)] = hpc;
335 }
336 }
337 }
338
347
348 void insertRecency(unsigned int pc, int assoc) {
349 int i = 0;
350 for (i = 0; i < assoc; i += 1) {
351 if (recency_stack[i] == pc) {
352 break;
353 }
354 }
355 if (i == assoc) {
356 i = assoc-1;
357 recency_stack[i] = pc;
358 }
359 int j;
360 unsigned int b = recency_stack[i];
361 for (j = i; j >= 1; j -= 1) {
363 }
364 recency_stack[0] = b;
365 }
366
369
373 };
375
379
383 int assoc;
388 int theta;
397
399 void insertModhistSpec(int p1, int p2) {
400 int j = insert(modhist_indices, p1);
401 if (modhist_lengths.size() < (j + 1)) {
402 modhist_lengths.resize(j + 1);
403 }
404 if (modhist_lengths[j] < p2 + 1) {
405 modhist_lengths[j] = p2 + 1;
406 }
407 if (p2 >= modghist_length) {
408 modghist_length = p2 + 1;
409 }
410 }
411
413 void insertModpathSpec(int p1, int p2) {
414 int j = insert(modpath_indices, p1);
415 if (modpath_lengths.size() < (j + 1)) {
416 modpath_lengths.resize(j + 1);
417 }
418 if (modpath_lengths[j] < p2 + 1) {
419 modpath_lengths[j] = p2 + 1;
420 }
421 if (p2 >= path_length) {
422 path_length = p2 + 1;
423 }
424 }
425
428 {
429 for (int i = 0; i < v.size(); i += 1) {
430 if (v[i] == x) {
431 return i;
432 }
433 }
434 v.push_back(x);
435 return v.size()-1;
436 }
437
447 void computeBits(int num_filter_entries, int nlocal_histories,
448 int local_history_length, bool ignore_path_size);
449
453 virtual void createSpecs() = 0;
454
463 unsigned int getIndex(ThreadID tid, const MPPBranchInfo &bi,
464 const HistorySpec &spec, int index) const;
472 void findBest(ThreadID tid, std::vector<int> &best_preds) const;
473
482
489 void train(ThreadID tid, MPPBranchInfo &bi, bool taken);
490
499 void satIncDec(bool taken, bool &sign, int &c, int max_weight) const;
500
503 {
504 specs.push_back(spec);
505 }
506
509 class GHIST : public HistorySpec
510 {
511 public:
512 GHIST(int p1, int p2, double coeff, int size, int width,
514 : HistorySpec(p1, p2, 0, coeff, size, width, mpp)
515 {}
516
517 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
518 override
519 {
520 return hash(mpp.threadData[tid]->ghist_words, mpp.blockSize, p1,
521 p2);
522 }
523
524 static unsigned int hash(const std::vector<unsigned int> &ghist_words,
525 int block_size, int start_pos, int end_pos)
526 {
527 int a = start_pos;
528 int b = end_pos;
529
530 unsigned int x = 0;
531 // am is the next multiple of block_size after a
532 int am = (((a/block_size)*block_size)+block_size);
533 // bm is the previous multiple of block_size before b
534 int bm = (b/block_size)*block_size;
535
536 // the 0th bit of ghist_words[a/block_size] is the most recent bit.
537 // so the number of bits between a and am is the number to shift
538 // right?
539
540 // start out x as remainder bits from the beginning:
541 // x = [ . . . . . b b b b b ]
542 x += ghist_words[a / block_size] >> (a-am);
543 // add in bits from the middle
544 for (int i=am; i<bm; i+=block_size) {
545 x += ghist_words[i / block_size];
546 }
547 // add in remainder bits from end:
548 // x += [ b b b b b . . . . . ]
549 unsigned int y = ghist_words[bm / block_size] & ((1<<(b - bm))-1);
550 x += y << (block_size - (b - bm));
551 return x;
552 }
553 void setBitRequirements() const override
554 {
555 if (mpp.ghist_length <= p2) {
556 mpp.ghist_length = p2 + 1;
557 }
558 }
559 };
560
561 class ACYCLIC : public HistorySpec
562 {
563 public:
564 ACYCLIC(int p1, int p2, int p3, double coeff, int size, int width,
567 {}
568
569 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
570 override
571 {
572 int a = p1;
573 int shift = p2;
574 int style = p3;
575 std::vector<std::vector<bool>> &acyclic_histories =
576 mpp.threadData[tid]->acyclic_histories;
577 std::vector<std::vector<unsigned int>> &acyclic2_histories =
578 mpp.threadData[tid]->acyclic2_histories;
579
580 unsigned int x = 0;
581 if (style == -1) {
582 unsigned int k = 0;
583 for (int i = 0; i < a + 2; i += 1) {
584 x ^= acyclic_histories[a][i] << k;
585 k += 1;
586 k %= mpp.blockSize;
587 }
588 } else {
589 for (int i = 0; i < a + 2; i += 1) {
590 x <<= shift;
591 x += acyclic2_histories[a][i];
592 }
593 }
594 return x;
595 }
596 void setBitRequirements() const override
597 {
598 if (mpp.acyclic_bits.size() < (p1 + 1)) {
599 mpp.acyclic_bits.resize(p1 + 1);
600 }
601 if (mpp.acyclic_bits[p1].size() < (p1 + 2)) {
602 mpp.acyclic_bits[p1].resize(p1 + 2, std::vector<bool>(2));
603 }
604 for (int j = 0; j < p1 + 2; j += 1) {
605 mpp.acyclic_bits[p1][j][!p3] = true;
606 }
607 }
608 };
609
610 class MODHIST : public HistorySpec
611 {
612 public:
613 MODHIST(int p1, int p2, double coeff, int size, int width,
615 : HistorySpec(p1, p2, 0, coeff, size, width, mpp)
616 {}
617
618 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
619 override
620 {
621 int a = p1;
622 int b = p2;
623 std::vector<std::vector<bool>> &mod_histories =
624 mpp.threadData[tid]->mod_histories;
625
626 unsigned int x = 0, k = 0;
627 for (int i = 0; i < b; i += 1) {
628 x ^= mod_histories[a][i] << k;
629 k += 1;
630 k %= mpp.blockSize;
631 }
632 return x;
633 }
634 void setBitRequirements() const override
635 {
637 }
638 };
639
640 class BIAS : public HistorySpec
641 {
642 public:
643 BIAS(double coeff, int size, int width,
645 : HistorySpec(0, 0, 0, coeff, size, width, mpp)
646 {}
647
648 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
649 override
650 {
651 return 0;
652 }
653 };
654
655
656 class RECENCY : public HistorySpec
657 {
658 public:
659 RECENCY(int p1, int p2, int p3, double coeff, int size, int width,
662 {}
663
664 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
665 override
666 {
667 int depth = p1;
668 int shift = p2;
669 int style = p3;
670 std::vector<unsigned int short> &recency_stack =
671 mpp.threadData[tid]->recency_stack;
672
673 if (style == -1) {
674 unsigned int x = 0;
675 for (int i = 0; i < depth; i += 1) {
676 x <<= shift;
677 x += recency_stack[i];
678 }
679 return x;
680 } else {
681 unsigned int x = 0, k = 0;
682 for (int i = 0; i < depth; i += 1) {
683 x ^= (!!(recency_stack[i] & (1 << shift))) << k;
684 k += 1;
685 k %= mpp.blockSize;
686 }
687 return x;
688 }
689 }
690 void setBitRequirements() const override
691 {
692 if (mpp.assoc < p1) {
693 mpp.assoc = p1;
694 }
695 mpp.doing_recency = true;
696 }
697 };
698
699 class IMLI : public HistorySpec
700 {
701 public:
702 IMLI(int p1, double coeff, int size, int width,
704 : HistorySpec(p1, 0, 0, coeff, size, width, mpp)
705 {}
706
707 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
708 override
709 {
710 assert(p1 >= 1);
711 assert(p1 <= 4);
712 return mpp.threadData[tid]->imli_counter[p1-1];
713 }
714
715 void setBitRequirements() const override
716 {
717 mpp.imli_counter_bits[p1 - 1] = 32;
718 }
719 };
720
721 class PATH : public HistorySpec
722 {
723 public:
724 PATH(int p1, int p2, int p3, double coeff, int size, int width,
727 {}
728
729 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
730 override
731 {
732 int depth = p1;
733 int shift = p2;
734 int style = p3;
735 std::vector<unsigned short int> &path_history =
736 mpp.threadData[tid]->path_history;
737
738 if (style == -1) {
739 unsigned int x = 0;
740 for (int i = 0; i < depth; i += 1) {
741 x <<= shift;
742 x += path_history[i];
743 }
744 return x;
745 } else {
746 unsigned int x = 0;
747 int bm = (depth / mpp.blockSize) * mpp.blockSize;
748 for (int i = 0; i < bm; i += mpp.blockSize) {
749 for (int j = 0; j < mpp.blockSize; j += 1) {
750 x ^= (!!(path_history[i + j] & (1 << shift))) << j;
751 }
752 }
753 int k = 0;
754 for (int i = bm; i < depth; i += 1) {
755 x ^= (!!(path_history[i] & (1 << shift))) << k++;
756 }
757 return x;
758 }
759 }
760 void setBitRequirements() const override
761 {
762 if (mpp.path_length <= p1) {
763 mpp.path_length = p1 + 1;
764 }
765 }
766 };
767
768 class LOCAL : public HistorySpec
769 {
770 public:
771 LOCAL(int p1, double coeff, int size, int width,
773 : HistorySpec(p1, 0, 0, coeff, size, width, mpp)
774 {}
775
776 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
777 override
778 {
779 unsigned int x = mpp.threadData[tid]->localHistories[pc];
780 if (p1 != -1) {
781 x &= ((1 << p1) - 1);
782 }
783 return x;
784 }
785 void setBitRequirements() const override
786 {
787 mpp.doing_local = true;
788 }
789 };
790
791 class MODPATH : public HistorySpec
792 {
793 public:
794 MODPATH(int p1, int p2, int p3, double coeff, int size, int width,
797 {}
798
799 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
800 override
801 {
802 int a = p1;
803 int depth = p2;
804 int shift = p3;
805
806 unsigned int x = 0;
807 for (int i=0; i<depth; i += 1) {
808 x <<= shift;
809 x += mpp.threadData[tid]->modpath_histories[a][i];
810 }
811 return x;
812 }
813 void setBitRequirements() const override
814 {
816 }
817 };
818
819 class GHISTPATH : public HistorySpec
820 {
821 public:
822 GHISTPATH(int p1, int p2, int p3, double coeff, int size, int width,
825 {}
826
827 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
828 override
829 {
830 int depth = p1;
831 int shift = p2;
832 int style = p3;
833 std::vector<unsigned int> &ghist_words =
834 mpp.threadData[tid]->ghist_words;
835 std::vector<unsigned short int> &path_history =
836 mpp.threadData[tid]->path_history;
837
838 if (style == -1) {
839 unsigned int x = 0;
840 int bm = (depth / mpp.blockSize) * mpp.blockSize;
841 unsigned int w;
842 for (int i = 0; i < bm; i += mpp.blockSize) {
843 w = ghist_words[i / mpp.blockSize];
844 for (int j = 0; j < mpp.blockSize; j += 1) {
845 x <<= shift;
846 x += (path_history[i + j] << 1) | (w & 1);
847 w >>= 1;
848 }
849 }
850 w = ghist_words[bm / mpp.blockSize];
851 for (int i = bm; i < depth; i += 1) {
852 x <<= shift;
853 x += (path_history[i] << 1) | (w & 1);
854 w >>= 1;
855 }
856 return x;
857 } else {
858 unsigned int x = 0;
859 int bm = (depth / mpp.blockSize) * mpp.blockSize;
860 unsigned int w = 0;
861 for (int i = 0; i < bm; i += mpp.blockSize) {
862 w = ghist_words[i / mpp.blockSize];
863 for (int j = 0; j < mpp.blockSize; j += 1) {
864 x ^= (!!(path_history[i + j] & (1 << shift))) << j;
865 x ^= (w & 1) << j;
866 w >>= 1;
867 }
868 }
869 w = ghist_words[bm/mpp.blockSize];
870 int k = 0;
871 for (int i = bm; i < depth; i += 1) {
872 x ^= (!!(path_history[i] & (1 << shift))) << k;
873 x ^= (w & 1) << k;
874 w >>= 1;
875 k += 1;
876 }
877 return x;
878 }
879 }
880
881 void setBitRequirements() const override
882 {
883 if (mpp.ghist_length <= p1) {
884 mpp.ghist_length = p1 + 1;
885 }
886 if (mpp.path_length <= p1) {
887 mpp.path_length = p1 + 1;
888 }
889 }
890 };
891
893 {
894 public:
895 GHISTMODPATH(int p1, int p2, int p3, double coeff, int size, int width,
898 {}
899
900 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
901 override
902 {
903 int a = p1;
904 int depth = p2;
905 int shift = p3;
907 mpp.threadData[tid]->modpath_histories;
908 std::vector<std::vector<bool>> &mod_histories =
909 mpp.threadData[tid]->mod_histories;
910
911 unsigned int x = 0;
912 for (int i = 0; i < depth; i += 1) {
913 x <<= shift;
914 x += (modpath_histories[a][i] << 1) | mod_histories[a][i];
915 }
916 return x;
917 }
918 void setBitRequirements() const override
919 {
922 }
923 };
924
925 class BLURRYPATH : public HistorySpec
926 {
927 public:
928 BLURRYPATH(int p1, int p2, int p3, double coeff, int size, int width,
931 {}
932
933 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
934 override
935 {
936 int scale = p1;
937 int depth = p2;
938 int shiftdelta = p3;
939
940 if (shiftdelta == -1) shiftdelta = 0;
941 int sdint = shiftdelta >> 2;
942 int sdfrac = shiftdelta & 3;
943 unsigned int x = 0;
944 int shift = 0;
945 int count = 0;
946 for (int i = 0; i < depth; i += 1) {
947 x += mpp.threadData[tid]->blurrypath_histories[scale][i] >>
948 shift;
949 count += 1;
950 if (count == sdfrac) {
951 shift += sdint;
952 count = 0;
953 }
954 }
955 return x;
956
957 }
958 void setBitRequirements() const override
959 {
960 if (mpp.blurrypath_bits.size() < (p1 + 1)) {
961 mpp.blurrypath_bits.resize(p1 + 1);
962 }
963 if (mpp.blurrypath_bits[p1].size() < p2) {
964 mpp.blurrypath_bits[p1].resize(p2);
965 }
966 for (int j = 0; j < p2; j += 1) {
967 mpp.blurrypath_bits[p1][j] = 32 - p1;
968 }
969 }
970 };
971
972 class RECENCYPOS : public HistorySpec
973 {
974 public:
975 RECENCYPOS(int p1, double coeff, int size, int width,
977 : HistorySpec(p1, 0, 0, coeff, size, width, mpp)
978 {}
979
980 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
981 override
982 {
983 return hash(mpp.threadData[tid]->recency_stack, mpp.table_sizes,
984 pc2, p1, t);
985 }
986
987 static unsigned int hash(
988 const std::vector<unsigned int short> &recency_stack,
989 const std::vector<int> &table_sizes, unsigned short int pc, int l,
990 int t)
991 {
992 // search for the PC
993
994 for (int i = 0; i < l; i += 1) {
995 if (recency_stack[i] == pc) {
996 return i * table_sizes[t] / l;
997 }
998 }
999
1000 // return last index in table on a miss
1001
1002 return table_sizes[t] - 1;
1003 }
1004
1005 void setBitRequirements() const override
1006 {
1007 if (mpp.assoc < p1) {
1008 mpp.assoc = p1;
1009 }
1010 mpp.doing_recency = true;
1011 }
1012 };
1013
1015 {
1016 public:
1017 SGHISTPATH(int p1, int p2, int p3, double coeff, int size, int width,
1020 {}
1021
1022 unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const
1023 override
1024 {
1025 int a = p1;
1026 int b = p2;
1027 int shift = p3;
1028 std::vector<unsigned int> &ghist_words =
1029 mpp.threadData[tid]->ghist_words;
1030 std::vector<unsigned short int> &path_history =
1031 mpp.threadData[tid]->path_history;
1032
1033 unsigned int x = 0;
1034 int bm = (b / mpp.blockSize) * mpp.blockSize;
1035 unsigned int w;
1036 for (int i = a; i < bm; i += mpp.blockSize) {
1037 w = ghist_words[i / mpp.blockSize];
1038 for (int j = 0; j < mpp.blockSize; j += 1) {
1039 x <<= shift;
1040 x += (path_history[i+j] << 1) | (w & 1);
1041 w >>= 1;
1042 }
1043 }
1044 w = ghist_words[bm / mpp.blockSize];
1045 for (int i = bm; i < b; i += 1) {
1046 x <<= shift;
1047 x += (path_history[i] << 1) | (w & 1);
1048 w >>= 1;
1049 }
1050 return x;
1051 }
1052 };
1053
1054 public:
1055 MultiperspectivePerceptron(const MultiperspectivePerceptronParams &params);
1056
1062 void setExtraBits(int bits);
1063
1064 void init() override;
1065
1066 // Base class methods.
1067 bool lookup(ThreadID tid, Addr branch_addr, void* &bp_history) override;
1068 void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken,
1069 Addr target, void * &bp_history) override;
1070 void update(ThreadID tid, Addr pc, bool taken,
1071 void * &bp_history, bool squashed,
1072 const StaticInstPtr & inst, Addr target) override;
1073 void squash(ThreadID tid, void * &bp_history) override;
1074};
1075
1076} // namespace branch_prediction
1077} // namespace gem5
1078
1079#endif//__CPU_PRED_MULTIPERSPECTIVE_PERCEPTRON_HH__
std::shared_ptr< Random > RandomPtr
Definition random.hh:65
static RandomPtr genRandom()
Definition random.hh:68
Basically a wrapper class to hold both the branch predictor and the BTB.
Definition bpred_unit.hh:71
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables.
ACYCLIC(int p1, int p2, int p3, 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.
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.
BIAS(double coeff, int size, int width, MultiperspectivePerceptron &mpp)
BLURRYPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
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.
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.
GHISTMODPATH(int p1, int p2, int p3, 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.
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables.
GHISTPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
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.
static unsigned int hash(const std::vector< unsigned int > &ghist_words, int block_size, int start_pos, int end_pos)
GHIST(int p1, int p2, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables.
IMLI(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.
LOCAL(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.
void setBitRequirements() const override
Sets the size requirements of the table, used when initializing to set the proper size of the tables.
Local history entries, each enty contains the history of directions taken by a given branch.
int getSize() const
Size in bits required by all history entries.
unsigned int operator[](Addr pc) const
Obtains the local history entry of a given branch.
void update(Addr pc, bool value)
Adds a history bit to the local history entry of a given branch.
int getLocalHistoryLength() const
Returns the number of bits of each local history entry.
unsigned int index(Addr pc) const
Index function given the pc of the branch.
MODHIST(int p1, int p2, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
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.
MODPATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
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.
bool filtered
Whether this branch has been filtered by the prefetcher.
const unsigned short int pc2
pc of the branch, shifted 2 bits to the right
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.
PATH(int p1, int p2, int p3, double coeff, int size, int width, MultiperspectivePerceptron &mpp)
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.
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.
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.
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)
SGHISTPATH(int p1, int p2, int p3, 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.
void insertModhistSpec(int p1, int p2)
Auxiliary function for MODHIST and GHISTMODPATH features.
void insertModpathSpec(int p1, int p2)
Auxiliary function for MODPATH and GHISTMODPATH features.
std::vector< std::vector< std::vector< bool > > > acyclic_bits
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...
void addSpec(HistorySpec *spec)
Add a table spec to the prefetcher.
int insert(std::vector< int > &v, int x)
Auxiliary function used by insertModhistSpec and insertModpathSpec.
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...
static int xlat[]
Transfer function for 6-width tables.
bool doing_local
runtime values and data used to count the size in bits
unsigned int getIndex(ThreadID tid, const MPPBranchInfo &bi, const HistorySpec &spec, int index) const
Get the position index of a predictor table.
virtual void createSpecs()=0
Creates the tables of the predictor.
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.
bool lookup(ThreadID tid, Addr branch_addr, void *&bp_history) override
Looks up a given conditional branch PC of in the BP to see if it is taken or not taken.
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...
static int xlat4[]
Transfer function for 5-width tables.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
void update(ThreadID tid, Addr pc, bool taken, void *&bp_history, bool squashed, const StaticInstPtr &inst, Addr target) override
Updates the BP with taken/not taken information.
void train(ThreadID tid, MPPBranchInfo &bi, bool taken)
Trains the branch predictor with the given branch and direction.
void setExtraBits(int bits)
Sets the starting number of storage bits to compute the number of table entries.
std::vector< HistorySpec * > specs
Predictor tables.
void updateHistories(ThreadID tid, Addr pc, bool uncond, bool taken, Addr target, void *&bp_history) override
Ones done with the prediction this function updates the path and global history.
void squash(ThreadID tid, void *&bp_history) override
STL vector class.
Definition stl.hh:37
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
const Params & params() const
Bitfield< 28 > v
Definition misc_types.hh:54
Bitfield< 5 > t
Definition misc_types.hh:71
Bitfield< 7 > b
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 29 > c
Definition misc_types.hh:53
Bitfield< 8 > a
Definition misc_types.hh:66
Bitfield< 6, 5 > shift
Definition types.hh:117
Bitfield< 4 > pc
Bitfield< 5 > l
Bitfield< 30, 0 > index
Bitfield< 23 > k
Bitfield< 6 > c2
Bitfield< 0 > w
Bitfield< 20, 16 > bi
Definition types.hh:80
Bitfield< 3 > x
Definition pagetable.hh:74
Bitfield< 3 > am
Definition misc.hh:132
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
bool alwaysTakenSoFar() const
Whether this branch has always been observed as taken.
bool neverSeen() const
Whether this branch has been observed before.
bool alwaysNotTakenSoFar() const
Whether this branch has always been observed as not taken.
const int size
Pre-assigned size in bits assigned to this feature.
virtual unsigned int getHash(ThreadID tid, Addr pc, Addr pc2, int t) const =0
Gets the hash to index the table, using the pc of the branch, and the index of the table.
MultiperspectivePerceptron & mpp
Reference to the branch predictor class.
virtual void setBitRequirements() const
Sets the size requirements of the table, used when initializing to set the proper size of the tables.
HistorySpec(int _p1, int _p2, int _p3, double _coeff, int _size, int _width, MultiperspectivePerceptron &_mpp)
const double coeff
Coefficient of the feature, models the accuracy of the feature.
std::vector< std::vector< std::array< bool, 2 > > > sign_bits

Generated on Mon Jan 13 2025 04:28:32 for gem5 by doxygen 1.9.8