gem5 v24.1.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
multiperspective_perceptron.cc
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
52
53#include "debug/Branch.hh"
54
55namespace gem5
56{
57
58namespace branch_prediction
59{
60
61int
63 {1,3,4,5,7,8,9,11,12,14,15,17,19,21,23,25,27,29,32,34,37,41,45,49,53,58,63,
64 69,76,85,94,106,};
65int
67 {0,4,5,7,9,11,12,14,16,17,19,22,28,33,39,45,};
68
70 int n_local_histories, int local_history_length, int assoc,
71 const std::vector<std::vector<int>> &blurrypath_bits, int path_length,
72 int ghist_length, int block_size,
73 const std::vector<std::vector<std::vector<bool>>> &acyclic_bits,
74 const std::vector<int> &modhist_indices,
75 const std::vector<int> &modhist_lengths,
76 const std::vector<int> &modpath_indices,
77 const std::vector<int> &modpath_lengths,
78 const std::vector<int> &table_sizes, int n_sign_bits)
79 : filterTable(num_filters), acyclic_histories(acyclic_bits.size()),
80 acyclic2_histories(acyclic_bits.size()),
81 blurrypath_histories(blurrypath_bits.size()),
82 ghist_words(ghist_length/block_size+1, 0),
83 path_history(path_length, 0), imli_counter(4,0),
84 localHistories(n_local_histories, local_history_length),
85 recency_stack(assoc), last_ghist_bit(false), occupancy(0)
86{
87 for (int i = 0; i < blurrypath_bits.size(); i+= 1) {
88 blurrypath_histories[i].resize(blurrypath_bits[i].size());
89 }
90
91 for (int i = 0; i < acyclic_bits.size(); i += 1) {
92 acyclic_histories[i].resize(acyclic_bits[i].size());
93 acyclic2_histories[i].resize(acyclic_bits[i].size());
94 }
95
96 int max_modhist_idx = -1;
97 for (auto &elem : modhist_indices) {
98 max_modhist_idx = (max_modhist_idx < elem) ? elem : max_modhist_idx;
99 }
100 if (max_modhist_idx >= 0) {
101 mod_histories.resize(max_modhist_idx + 1);
102 }
103 for (int i = 0; i < modhist_lengths.size(); i+= 1) {
105 }
106
107 int max_modpath_idx = -1;
108 for (auto &elem : modpath_indices) {
109 max_modpath_idx = (max_modpath_idx < elem) ? elem : max_modpath_idx;
110 }
111 if (max_modpath_idx >= 0) {
112 modpath_histories.resize(max_modpath_idx + 1);
113 }
114 for (int i = 0; i < modpath_lengths.size(); i+= 1) {
116 }
117
118 for (int i = 0; i < table_sizes.size(); i += 1) {
119 mpreds.push_back(0);
121 sign_bits.push_back(std::vector<std::array<bool, 2>>(table_sizes[i]));
122 for (int j = 0; j < table_sizes[i]; j += 1) {
123 for (int k = 0; k < n_sign_bits; k += 1) {
124 sign_bits[i][j][k] = (i & 1) | (k & 1);
125 }
126 }
127 }
128}
129
149
150void
155
156void
158{
159 createSpecs();
160
161 for (auto &spec : specs) {
162 // initial assignation of values
163 table_sizes.push_back(spec->size);
164 }
165
166 // Update bit requirements and runtime values
167 for (auto &spec : specs) {
168 spec->setBitRequirements();
169 }
170 const MultiperspectivePerceptronParams &p =
171 static_cast<const MultiperspectivePerceptronParams &>(params());
172
173 computeBits(p.num_filter_entries, p.num_local_histories,
174 p.local_history_length, p.ignore_path_size);
175
176 for (int i = 0; i < threadData.size(); i += 1) {
177 threadData[i] = new ThreadData(p.num_filter_entries,
178 p.num_local_histories,
179 p.local_history_length, assoc,
185 }
186}
187
188void
190 int nlocal_histories, int local_history_length, bool ignore_path_size)
191{
192 int totalbits = extrabits;
193 for (auto &imli_bits : imli_counter_bits) {
194 totalbits += imli_bits;
195 }
196 totalbits += ghist_length;
197 if (!ignore_path_size) {
198 totalbits += path_length * 16;
199 }
200 totalbits += (threshold >= 0) ? (tunebits * specs.size()) : 0;
201 for (auto &len : modhist_lengths) {
202 totalbits += len;
203 }
204 if (!ignore_path_size) {
205 for (auto &len : modpath_lengths) {
206 totalbits += 16 * len;
207 }
208 }
209 totalbits += doing_local ? (nlocal_histories * local_history_length) : 0;
210 totalbits += doing_recency ? (assoc * 16) : 0;
211
212 for (auto &bv : blurrypath_bits) {
213 for (auto &bve : bv) {
214 totalbits += bve;
215 }
216 }
217 totalbits += num_filter_entries * 2;
218
219 for (auto &abi : acyclic_bits) {
220 for (auto &abj : abi) {
221 for (auto abk : abj) {
222 totalbits += abk;
223 }
224 }
225 }
226
227 int remaining = budgetbits - totalbits;
228
229 // count the tables that have already been assigned sizes
230 int num_sized = 0;
231 for (int i = 0; i < specs.size(); i +=1) {
232 if (table_sizes[i] != 0) {
233 int sz = table_sizes[i] * (specs[i]->width + (n_sign_bits - 1));
234 totalbits += sz;
235 remaining -= sz;
236 num_sized += 1;
237 }
238 }
239
240 // whatever is left, we divide among the rest of the tables
241 int table_size_bits = (remaining / (specs.size()-num_sized));
242 for (int i = 0; i < specs.size(); i += 1) {
243 // if a table doesn't have a size yet, give it one and count those bits
244 if (!table_sizes[i]) {
245 int my_table_size = table_size_bits /
246 (specs[i]->width + (n_sign_bits - 1)); // extra sign bits
247 table_sizes[i] = my_table_size;
248 totalbits += my_table_size * (specs[i]->width + (n_sign_bits - 1));
249 }
250 }
251
252 DPRINTF(Branch, "%d bits of metadata so far, %d left out of "
253 "%d total budget\n", totalbits, remaining, budgetbits);
254 DPRINTF(Branch, "table size is %d bits, %d entries for 5 bit, %d entries "
255 "for 6 bit\n", table_size_bits,
256 table_size_bits / (5 + (n_sign_bits - 1)),
257 table_size_bits / (6 + (n_sign_bits - 1)));
258 DPRINTF(Branch, "%d total bits (%0.2fKB)\n", totalbits,
259 totalbits / 8192.0);
260}
261
262void
264 std::vector<int> &best_preds) const
265{
266 if (threshold < 0) {
267 return;
268 }
269 struct BestPair
270 {
271 int index;
272 int mpreds;
273 bool operator<(BestPair const &bp) const
274 {
275 return mpreds < bp.mpreds;
276 }
277 };
278 std::vector<BestPair> pairs(best_preds.size());
279 for (int i = 0; i < best_preds.size(); i += 1) {
280 pairs[i].index = i;
281 pairs[i].mpreds = threadData[tid]->mpreds[i];
282 }
283 std::sort(pairs.begin(), pairs.end());
284 for (int i = 0; i < (std::min(nbest, (int) best_preds.size())); i += 1) {
285 best_preds[i] = pairs[i].index;
286 }
287}
288
289unsigned int
291 const HistorySpec &spec, int index) const
292{
293 unsigned int g = spec.getHash(tid, bi.getPC(), bi.getPC2(), index);
294 unsigned long long int h = g;
295 // shift the hash from the feature to xor with the hashed PC
296 if (hshift < 0) {
297 h <<= -hshift;
298 h ^= bi.getPC2();
299 } else {
300 h <<= hshift;
301 h ^= bi.getHPC();
302 }
303 // xor in the imli counter(s) and/or recency position based on the masks
304 if ((1ull<<index) & imli_mask1) {
305 h ^= threadData[tid]->imli_counter[0];
306 }
307 if ((1ull<<index) & imli_mask4) {
308 h ^= threadData[tid]->imli_counter[3];
309 }
310 if (doing_recency) {
311 if ((1ull<<index) & recencypos_mask) {
312 h ^= RECENCYPOS::hash(threadData[tid]->recency_stack, table_sizes,
313 bi.getPC2(), 31, index);
314 }
315 }
316 h %= table_sizes[index];
317 return h;
318}
319
320int
322{
323 // list of best predictors
324 std::vector<int> best_preds(specs.size(), -1);
325
326 // initialize sum
327 bi.yout = 0;
328
329 // bias the prediction by whether the local history is
330 // one of four distinctive patterns
331 int lhist = threadData[tid]->localHistories[bi.getPC()];
332 int history_len = threadData[tid]->localHistories.getLocalHistoryLength();
333 if (lhist == 0) {
334 bi.yout = bias0;
335 } else if (lhist == ((1<<history_len)-1)) {
336 bi.yout = bias1;
337 } else if (lhist == (1<<(history_len-1))) {
338 bi.yout = biasmostly0;
339 } else if (lhist == ((1<<(history_len-1))-1)) {
340 bi.yout = biasmostly1;
341 }
342 // find the best subset of features to use in case of a low-confidence
343 // branch
344 findBest(tid, best_preds);
345
346 // begin computation of the sum for low-confidence branch
347 int bestval = 0;
348
349 for (int i = 0; i < specs.size(); i += 1) {
350 HistorySpec const &spec = *specs[i];
351 // get the hash to index the table
352 unsigned int hashed_idx = getIndex(tid, bi, spec, i);
353 // add the weight; first get the weight's magnitude
354 int counter = threadData[tid]->tables[i][hashed_idx];
355 // get the sign
356 bool sign =
357 threadData[tid]->sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
358 // apply the transfer function and multiply by a coefficient
359 int weight = spec.coeff * ((spec.width == 5) ?
360 xlat4[counter] : xlat[counter]);
361 // apply the sign
362 int val = sign ? -weight : weight;
363 // add the value
364 bi.yout += val;
365 // if this is one of those good features, add the value to bestval
366 if (threshold >= 0) {
367 for (int j = 0;
368 j < std::min(nbest, (int) best_preds.size());
369 j += 1)
370 {
371 if (best_preds[j] == i) {
372 bestval += val;
373 break;
374 }
375 }
376 }
377 }
378 // apply a fudge factor to affect when training is triggered
379 bi.yout *= fudge;
380 return bestval;
381}
382
383void
384MultiperspectivePerceptron::satIncDec(bool taken, bool &sign, int &counter,
385 int max_weight) const
386{
387 if (taken) {
388 // increment sign/magnitude
389 if (sign) {
390 // go toward 0 away from negative max weight
391 if (counter == 0) {
392 sign = false; // moved to positive 0
393 } else {
394 counter -= 1;
395 }
396 } else {
397 // go toward max weight away from 0
398 if (counter < max_weight) {
399 counter += 1;
400 }
401 }
402 } else {
403 // decrement sign/magnitude
404 if (sign) {
405 // go toward negative max weight down from 0
406 if (counter < max_weight) {
407 counter += 1;
408 }
409 } else {
410 // go toward 0 away from max weight
411 if (counter == 0) {
412 sign = true; // negative 0
413 } else {
414 counter -= 1;
415 }
416 }
417 }
418}
419
420void
422{
423 std::vector<std::vector<short int>> &tables = threadData[tid]->tables;
425 threadData[tid]->sign_bits;
426 std::vector<int> &mpreds = threadData[tid]->mpreds;
427 // was the prediction correct?
428 bool correct = (bi.yout >= 1) == taken;
429 // what is the magnitude of yout?
430 int abs_yout = abs(bi.yout);
431 // keep track of mispredictions per table
432 if (threshold >= 0) if (!tuneonly || (abs_yout <= threshold)) {
433 bool halve = false;
434
435 // for each table, figure out if there was a misprediction
436 for (int i = 0; i < specs.size(); i += 1) {
437 HistorySpec const &spec = *specs[i];
438 // get the hash to index the table
439 unsigned int hashed_idx = getIndex(tid, bi, spec, i);
440 bool sign = sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
441 int counter = tables[i][hashed_idx];
442 int weight = spec.coeff * ((spec.width == 5) ?
443 xlat4[counter] : xlat[counter]);
444 if (sign) weight = -weight;
445 bool pred = weight >= 1;
446 if (pred != taken) {
447 mpreds[i] += 1;
448 if (mpreds[i] == (1 << tunebits) - 1) {
449 halve = true;
450 }
451 }
452 }
453 // if we reach the maximum counter value, halve all the counters
454 if (halve) {
455 for (int i = 0; i < specs.size(); i += 1) {
456 mpreds[i] /= 2;
457 }
458 }
459 }
460 // if the branch was predicted incorrectly or the correct
461 // prediction was weak, update the weights
462 bool do_train = !correct || (abs_yout <= theta);
463 if (!do_train) return;
464
465 // adaptive theta training, adapted from O-GEHL
466 if (!correct) {
467 thresholdCounter += 1;
468 if (thresholdCounter >= speed) {
469 theta += 1;
471 }
472 }
473 if (correct && abs_yout < theta) {
474 thresholdCounter -= 1;
475 if (thresholdCounter <= -speed) {
476 theta -= 1;
478 }
479 }
480
481 // train the weights, computing what the value of yout
482 // would have been if these updates had been applied before
483 int newyout = 0;
484 for (int i = 0; i < specs.size(); i += 1) {
485 HistorySpec const &spec = *specs[i];
486 // get the magnitude
487 unsigned int hashed_idx = getIndex(tid, bi, spec, i);
488 int counter = tables[i][hashed_idx];
489 // get the sign
490 bool sign = sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
491 // increment/decrement if taken/not taken
492 satIncDec(taken, sign, counter, (1 << (spec.width - 1)) - 1);
493 // update the magnitude and sign
494 tables[i][hashed_idx] = counter;
495 sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits] = sign;
496 int weight = ((spec.width == 5) ? xlat4[counter] : xlat[counter]);
497 // update the new version of yout
498 if (sign) {
499 newyout -= weight;
500 } else {
501 newyout += weight;
502 }
503 }
504
505 // if the prediction still would have been incorrect even
506 // with the updated weights, update some more weights to
507 // try to fix the problem
508 if ((newyout >= 1) != taken) {
509 if (extra_rounds != -1) {
510 int round_counter = 0;
511 bool found;
512 do {
513 // udpate a random weight
514 int besti = -1;
515 int nrand = rng->random<int>() % specs.size();
516 int pout;
517 found = false;
518 for (int j = 0; j < specs.size(); j += 1) {
519 int i = (nrand + j) % specs.size();
520 HistorySpec const &spec = *specs[i];
521 unsigned int hashed_idx = getIndex(tid, bi, spec, i);
522 int counter = tables[i][hashed_idx];
523 bool sign =
524 sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
525 int weight = ((spec.width == 5) ?
526 xlat4[counter] : xlat[counter]);
527 int signed_weight = sign ? -weight : weight;
528 pout = newyout - signed_weight;
529 if ((pout >= 1) == taken) {
530 // we have found a weight that if we blow
531 // it away will help!
532 besti = i;
533 break;
534 }
535 }
536 if (besti != -1) {
537 int i = besti;
538 HistorySpec const &spec = *specs[i];
539 unsigned int hashed_idx = getIndex(tid, bi, spec, i);
540 int counter = tables[i][hashed_idx];
541 bool sign =
542 sign_bits[i][hashed_idx][bi.getHPC() % n_sign_bits];
543 if (counter > 1) {
544 counter--;
545 tables[i][hashed_idx] = counter;
546 }
547 int weight = ((spec.width == 5) ?
548 xlat4[counter] : xlat[counter]);
549 int signed_weight = sign ? -weight : weight;
550 int out = pout + signed_weight;
551 round_counter += 1;
552 if ((out >= 1) != taken) {
553 found = true;
554 }
555 }
556 } while (found && round_counter < extra_rounds);
557 }
558 }
559}
560
561
562void
564 bool uncond, bool taken, Addr target, void * &bp_history)
565{
566 assert(uncond || bp_history);
567
568 // For perceptron there is no speculative history correction.
569 // Conditional branches are done.
570 if (!uncond)
571 return;
572
573 // For uncondition branches create branch info.
574 MPPBranchInfo *bi = new MPPBranchInfo(pc, pcshift, false);
575 std::vector<unsigned int> &ghist_words = threadData[tid]->ghist_words;
576
577 bp_history = (void *)bi;
578 unsigned short int pc2 = pc >> 2;
579 bool ab = !(pc & (1<<pcbit));
580 for (int i = 0; i < ghist_length / blockSize + 1; i += 1) {
581 bool ab_new = (ghist_words[i] >> (blockSize - 1)) & 1;
582 ghist_words[i] <<= 1;
583 ghist_words[i] |= ab;
584 ghist_words[i] &= (1 << blockSize) - 1;
585 ab = ab_new;
586 }
587 memmove(&threadData[tid]->path_history[1],
588 &threadData[tid]->path_history[0],
589 sizeof(unsigned short int) * (path_length - 1));
590 threadData[tid]->path_history[0] = pc2;
591}
592
593bool
595 void * &bp_history)
596{
597 MPPBranchInfo *bi = new MPPBranchInfo(instPC, pcshift, true);
598 bp_history = (void *)bi;
599
600 bool use_static = false;
601
602 if (!threadData[tid]->filterTable.empty()) {
603 unsigned int findex =
604 bi->getHashFilter(threadData[tid]->last_ghist_bit) %
605 threadData[tid]->filterTable.size();
606 FilterEntry &f = threadData[tid]->filterTable[findex];
607 if (f.alwaysNotTakenSoFar()) {
608 bi->filtered = true;
609 bi->prediction = false;
610 return false;
611 } else if (f.alwaysTakenSoFar()) {
612 bi->filtered = true;
613 bi->prediction = true;
614 return true;
615 }
616 if (f.neverSeen()) {
617 use_static = true;
618 }
619 }
620
621 int bestval = computeOutput(tid, *bi);
622 if (use_static) {
623 bi->prediction = false;
624 } else {
625 if (abs(bi->yout) <= threshold) {
626 bi->prediction = (bestval >= 1);
627 } else {
628 bi->prediction = (bi->yout >= 1);
629 }
630 }
631
632 return bi->prediction;
633}
634
635void
637 void * &bp_history, bool squashed,
638 const StaticInstPtr & inst,
639 Addr target)
640{
641 assert(bp_history);
642 MPPBranchInfo *bi = static_cast<MPPBranchInfo*>(bp_history);
643 if (squashed) {
644 //delete bi;
645 return;
646 }
647
648 if (bi->isUnconditional()) {
649 delete bi;
650 bp_history = nullptr;
651 return;
652 }
653
654 bool do_train = true;
655
656 if (!threadData[tid]->filterTable.empty()) {
657 int findex = bi->getHashFilter(threadData[tid]->last_ghist_bit) %
658 threadData[tid]->filterTable.size();
659 FilterEntry &f = threadData[tid]->filterTable[findex];
660
661 // compute this first, so we don't not train on the
662 // first time a branch is seen.
663 bool transition = false;
664 if (f.alwaysNotTakenSoFar() || f.alwaysTakenSoFar()) {
665 do_train = false;
666 }
667 if (taken) {
668 if (f.alwaysNotTakenSoFar()) {
669 transition = true;
670 }
671 f.seenTaken = true;
672 } else {
673 if (f.alwaysTakenSoFar()) {
674 transition = true;
675 }
676 f.seenUntaken = true;
677 }
678 // is this the first time time the branch has gone both ways?
679 if (transition) {
680 threadData[tid]->occupancy += 1;
681 }
682 // for every new dynamic branch, when there ar
683 // more than 'decay' number of branches in the
684 // filter, blow a random filter entry away
685 if (decay && transition &&
686 ((threadData[tid]->occupancy > decay) || (decay == 1))) {
687 int rnd = rng->random<int>() %
688 threadData[tid]->filterTable.size();
689 FilterEntry &frand = threadData[tid]->filterTable[rnd];
690 if (frand.seenTaken && frand.seenUntaken) {
691 threadData[tid]->occupancy -= 1;
692 }
693 frand.seenTaken = false;
694 frand.seenUntaken = false;
695 }
696 }
697
698 if (do_train) {
699 train(tid, *bi, taken);
700 }
701
702 enum RecordFiltered
703 {
704 Imli = 1,
705 GHist = 2,
706 Path = 4,
707 Acyclic = 8,
708 Mod = 16,
709 Blurry = 32,
710 // Should never record a filtered local branch - duh!
711 Local = 64,
712 Recency = 128
713 };
714
715 // four different styles of IMLI
716 if (!bi->filtered || (record_mask & Imli)) {
717 if (target < bi->getPC()) {
718 if (taken) {
719 threadData[tid]->imli_counter[0] += 1;
720 } else {
721 threadData[tid]->imli_counter[0] = 0;
722 }
723 if (!taken) {
724 threadData[tid]->imli_counter[1] += 1;
725 } else {
726 threadData[tid]->imli_counter[1] = 0;
727 }
728 } else {
729 if (taken) {
730 threadData[tid]->imli_counter[2] += 1;
731 } else {
732 threadData[tid]->imli_counter[2] = 0;
733 }
734 if (!taken) {
735 threadData[tid]->imli_counter[3] += 1;
736 } else {
737 threadData[tid]->imli_counter[3] = 0;
738 }
739 }
740 }
741
742 bool hashed_taken = hash_taken ? (taken ^ !!(bi->getPC() & (1<<pcbit)))
743 : taken;
744 // record into ghist
745 if (!bi->filtered || (record_mask & GHist)) {
746 bool ab = hashed_taken;
747 assert(threadData[tid]->ghist_words.size() > 0);
748 for (int i = 0; i < ghist_length / blockSize + 1; i += 1) {
749 unsigned int a = threadData[tid]->ghist_words[i];
750 bool ab_new = (a >> (blockSize - 1)) & 1;
751 a <<= 1;
752 a |= ab;
753 ab = ab_new;
754 a &= (1 << blockSize) - 1;
755 threadData[tid]->ghist_words[i] = a;
756 }
757 }
758
759 // record into path history
760 if (!bi->filtered || (record_mask & Path)) {
761 assert(threadData[tid]->path_history.size() > 0);
762 memmove(&threadData[tid]->path_history[1],
763 &threadData[tid]->path_history[0],
764 sizeof(unsigned short int) * (path_length - 1));
765 threadData[tid]->path_history[0] = bi->getPC2();
766 }
767
768 // record into acyclic history
769 if (!bi->filtered || (record_mask & Acyclic)) {
770 threadData[tid]->updateAcyclic(hashed_taken, bi->getHPC());
771 }
772
773 // record into modulo path history
774 if (!bi->filtered || (record_mask & Mod)) {
775 for (int ii = 0; ii < modpath_indices.size(); ii += 1) {
776 int i = modpath_indices[ii];
777 if (bi->getHPC() % (i + 2) == 0) {
778 memmove(&threadData[tid]->modpath_histories[i][1],
779 &threadData[tid]->modpath_histories[i][0],
780 sizeof(unsigned short int) * (modpath_lengths[ii]-1));
781 threadData[tid]->modpath_histories[i][0] = bi->getPC2();
782 }
783 }
784 }
785
786 // update blurry history
787 if (!bi->filtered || (record_mask & Blurry)) {
788 std::vector<std::vector<unsigned int>> &blurrypath_histories =
789 threadData[tid]->blurrypath_histories;
790
791 for (int i = 0; i < blurrypath_histories.size(); i += 1)
792 {
793 if (blurrypath_histories[i].size() > 0) {
794 unsigned int z = bi->getPC() >> i;
795 if (blurrypath_histories[i][0] != z) {
796 memmove(&blurrypath_histories[i][1],
797 &blurrypath_histories[i][0],
798 sizeof(unsigned int) *
799 (blurrypath_histories[i].size() - 1));
800 blurrypath_histories[i][0] = z;
801 }
802 }
803 }
804 }
805
806 // record into modulo pattern history
807 if (!bi->filtered || (record_mask & Mod)) {
808 for (int ii = 0; ii < modhist_indices.size(); ii += 1) {
809 int i = modhist_indices[ii];
810 if (bi->getHPC() % (i + 2) == 0) {
811 for (int j = modhist_lengths[ii] - 1; j > 0; j -= 1) {
812 threadData[tid]->mod_histories[i][j] =
813 threadData[tid]->mod_histories[i][j-1];
814 }
815 threadData[tid]->mod_histories[i][0] = hashed_taken;
816 }
817 }
818 }
819
820 // insert this PC into the recency stack
821 if (doing_recency) {
822 if (!bi->filtered || (record_mask & Recency)) {
823 threadData[tid]->insertRecency(bi->getPC2(), assoc);
824 }
825 }
826
827 // record into a local history
828 if (!bi->filtered || (record_mask & Local)) {
829 threadData[tid]->localHistories.update(bi->getPC(), hashed_taken);
830 }
831
832 // update last ghist bit, used to index filter
833 threadData[tid]->last_ghist_bit = taken;
834
835 delete bi;
836 bp_history = nullptr;
837}
838
839void
841{
842 assert(bp_history);
843 MPPBranchInfo *bi = static_cast<MPPBranchInfo*>(bp_history);
844 delete bi;
845 bp_history = nullptr;
846}
847
848} // namespace branch_prediction
849} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
Base class for branch operations.
Definition branch.hh:49
Basically a wrapper class to hold both the branch predictor and the BTB.
Definition bpred_unit.hh:71
const unsigned numThreads
Number of the threads for which the branch history is maintained.
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)
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 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
MultiperspectivePerceptron(const MultiperspectivePerceptronParams &params)
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
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
const Params & params() const
Bitfield< 18, 16 > len
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 11 > z
Bitfield< 8 > a
Definition misc_types.hh:66
Bitfield< 6 > f
Definition misc_types.hh:68
Bitfield< 4 > pc
Bitfield< 30, 0 > index
Bitfield< 4 > g
Bitfield< 0 > p
Bitfield< 23 > k
Bitfield< 20, 16 > bi
Definition types.hh:80
Bitfield< 27, 24 > pred
Definition types.hh:91
Bitfield< 63 > val
Definition misc.hh:804
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
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.
const double coeff
Coefficient of the feature, models the accuracy of the feature.
ThreadData(int num_filter, int n_local_histories, int local_history_length, int assoc, const std::vector< std::vector< int > > &blurrypath_bits, int path_length, int ghist_length, int block_size, const std::vector< std::vector< std::vector< bool > > > &acyclic_bits, const std::vector< int > &modhist_indices, const std::vector< int > &modhist_lengths, const std::vector< int > &modpath_indices, const std::vector< int > &modpath_lengths, const std::vector< int > &table_sizes, int n_sign_bits)
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