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