gem5  v20.1.0.0
bi_mode.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /* @file
30  * Implementation of a bi-mode branch predictor
31  */
32 
33 #include "cpu/pred/bi_mode.hh"
34 
35 #include "base/bitfield.hh"
36 #include "base/intmath.hh"
37 
38 BiModeBP::BiModeBP(const BiModeBPParams *params)
39  : BPredUnit(params),
40  globalHistoryReg(params->numThreads, 0),
41  globalHistoryBits(ceilLog2(params->globalPredictorSize)),
42  choicePredictorSize(params->choicePredictorSize),
43  choiceCtrBits(params->choiceCtrBits),
44  globalPredictorSize(params->globalPredictorSize),
45  globalCtrBits(params->globalCtrBits),
46  choiceCounters(choicePredictorSize, SatCounter(choiceCtrBits)),
47  takenCounters(globalPredictorSize, SatCounter(globalCtrBits)),
48  notTakenCounters(globalPredictorSize, SatCounter(globalCtrBits))
49 {
51  fatal("Invalid choice predictor size.\n");
53  fatal("Invalid global history predictor size.\n");
54 
58 
59  choiceThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
60  takenThreshold = (ULL(1) << (globalCtrBits - 1)) - 1;
61  notTakenThreshold = (ULL(1) << (globalCtrBits - 1)) - 1;
62 }
63 
64 /*
65  * For an unconditional branch we set its history such that
66  * everything is set to taken. I.e., its choice predictor
67  * chooses the taken array and the taken array predicts taken.
68  */
69 void
70 BiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bpHistory)
71 {
72  BPHistory *history = new BPHistory;
73  history->globalHistoryReg = globalHistoryReg[tid];
74  history->takenUsed = true;
75  history->takenPred = true;
76  history->notTakenPred = true;
77  history->finalPred = true;
78  bpHistory = static_cast<void*>(history);
79  updateGlobalHistReg(tid, true);
80 }
81 
82 void
83 BiModeBP::squash(ThreadID tid, void *bpHistory)
84 {
85  BPHistory *history = static_cast<BPHistory*>(bpHistory);
86  globalHistoryReg[tid] = history->globalHistoryReg;
87 
88  delete history;
89 }
90 
91 /*
92  * Here we lookup the actual branch prediction. We use the PC to
93  * identify the bias of a particular branch, which is based on the
94  * prediction in the choice array. A hash of the global history
95  * register and a branch's PC is used to index into both the taken
96  * and not-taken predictors, which both present a prediction. The
97  * choice array's prediction is used to select between the two
98  * direction predictors for the final branch prediction.
99  */
100 bool
101 BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory)
102 {
103  unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
105  unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
106  ^ globalHistoryReg[tid])
108 
109  assert(choiceHistoryIdx < choicePredictorSize);
110  assert(globalHistoryIdx < globalPredictorSize);
111 
112  bool choicePrediction = choiceCounters[choiceHistoryIdx]
113  > choiceThreshold;
114  bool takenGHBPrediction = takenCounters[globalHistoryIdx]
115  > takenThreshold;
116  bool notTakenGHBPrediction = notTakenCounters[globalHistoryIdx]
118  bool finalPrediction;
119 
120  BPHistory *history = new BPHistory;
121  history->globalHistoryReg = globalHistoryReg[tid];
122  history->takenUsed = choicePrediction;
123  history->takenPred = takenGHBPrediction;
124  history->notTakenPred = notTakenGHBPrediction;
125 
126  if (choicePrediction) {
127  finalPrediction = takenGHBPrediction;
128  } else {
129  finalPrediction = notTakenGHBPrediction;
130  }
131 
132  history->finalPred = finalPrediction;
133  bpHistory = static_cast<void*>(history);
134  updateGlobalHistReg(tid, finalPrediction);
135 
136  return finalPrediction;
137 }
138 
139 void
140 BiModeBP::btbUpdate(ThreadID tid, Addr branchAddr, void * &bpHistory)
141 {
142  globalHistoryReg[tid] &= (historyRegisterMask & ~ULL(1));
143 }
144 
145 /* Only the selected direction predictor will be updated with the final
146  * outcome; the status of the unselected one will not be altered. The choice
147  * predictor is always updated with the branch outcome, except when the
148  * choice is opposite to the branch outcome but the selected counter of
149  * the direction predictors makes a correct final prediction.
150  */
151 void
152 BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory,
153  bool squashed, const StaticInstPtr & inst, Addr corrTarget)
154 {
155  assert(bpHistory);
156 
157  BPHistory *history = static_cast<BPHistory*>(bpHistory);
158 
159  // We do not update the counters speculatively on a squash.
160  // We just restore the global history register.
161  if (squashed) {
162  globalHistoryReg[tid] = (history->globalHistoryReg << 1) | taken;
163  return;
164  }
165 
166  unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
168  unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
169  ^ history->globalHistoryReg)
171 
172  assert(choiceHistoryIdx < choicePredictorSize);
173  assert(globalHistoryIdx < globalPredictorSize);
174 
175  if (history->takenUsed) {
176  // if the taken array's prediction was used, update it
177  if (taken) {
178  takenCounters[globalHistoryIdx]++;
179  } else {
180  takenCounters[globalHistoryIdx]--;
181  }
182  } else {
183  // if the not-taken array's prediction was used, update it
184  if (taken) {
185  notTakenCounters[globalHistoryIdx]++;
186  } else {
187  notTakenCounters[globalHistoryIdx]--;
188  }
189  }
190 
191  if (history->finalPred == taken) {
192  /* If the final prediction matches the actual branch's
193  * outcome and the choice predictor matches the final
194  * outcome, we update the choice predictor, otherwise it
195  * is not updated. While the designers of the bi-mode
196  * predictor don't explicity say why this is done, one
197  * can infer that it is to preserve the choice predictor's
198  * bias with respect to the branch being predicted; afterall,
199  * the whole point of the bi-mode predictor is to identify the
200  * atypical case when a branch deviates from its bias.
201  */
202  if (history->finalPred == history->takenUsed) {
203  if (taken) {
204  choiceCounters[choiceHistoryIdx]++;
205  } else {
206  choiceCounters[choiceHistoryIdx]--;
207  }
208  }
209  } else {
210  // always update the choice predictor on an incorrect prediction
211  if (taken) {
212  choiceCounters[choiceHistoryIdx]++;
213  } else {
214  choiceCounters[choiceHistoryIdx]--;
215  }
216  }
217 
218  delete history;
219 }
220 
221 void
223 {
224  globalHistoryReg[tid] = taken ? (globalHistoryReg[tid] << 1) | 1 :
225  (globalHistoryReg[tid] << 1);
227 }
228 
229 BiModeBP*
230 BiModeBPParams::create()
231 {
232  return new BiModeBP(this);
233 }
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
BiModeBP::choiceCtrBits
unsigned choiceCtrBits
Definition: bi_mode.hh:93
ThreadID
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:227
BiModeBP::globalHistoryBits
unsigned globalHistoryBits
Definition: bi_mode.hh:89
BiModeBP::choiceCounters
std::vector< SatCounter > choiceCounters
Definition: bi_mode.hh:100
BiModeBP::BPHistory::takenPred
bool takenPred
Definition: bi_mode.hh:77
BiModeBP::lookup
bool lookup(ThreadID tid, Addr branch_addr, void *&bp_history)
Looks up a given PC in the BP to see if it is taken or not taken.
Definition: bi_mode.cc:101
BiModeBP::globalPredictorSize
unsigned globalPredictorSize
Definition: bi_mode.hh:95
BiModeBP::globalHistoryReg
std::vector< unsigned > globalHistoryReg
Definition: bi_mode.hh:88
BiModeBP::BPHistory::globalHistoryReg
unsigned globalHistoryReg
Definition: bi_mode.hh:69
BiModeBP::globalCtrBits
unsigned globalCtrBits
Definition: bi_mode.hh:96
BiModeBP::updateGlobalHistReg
void updateGlobalHistReg(ThreadID tid, bool taken)
Definition: bi_mode.cc:222
BiModeBP::BPHistory::takenUsed
bool takenUsed
Definition: bi_mode.hh:73
BiModeBP::BPHistory::finalPred
bool finalPred
Definition: bi_mode.hh:85
BiModeBP
Implements a bi-mode branch predictor.
Definition: bi_mode.hh:54
BiModeBP::choiceThreshold
unsigned choiceThreshold
Definition: bi_mode.hh:106
BPredUnit::instShiftAmt
const unsigned instShiftAmt
Number of bits to shift instructions by for predictor addresses.
Definition: bpred_unit.hh:312
ceilLog2
int ceilLog2(const T &n)
Definition: intmath.hh:88
bitfield.hh
MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:240
BiModeBP::choiceHistoryMask
unsigned choiceHistoryMask
Definition: bi_mode.hh:94
BPredUnit
Basically a wrapper class to hold both the branch predictor and the BTB.
Definition: bpred_unit.hh:62
BiModeBP::BPHistory
Definition: bi_mode.hh:68
BiModeBP::takenThreshold
unsigned takenThreshold
Definition: bi_mode.hh:107
BiModeBP::historyRegisterMask
unsigned historyRegisterMask
Definition: bi_mode.hh:90
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
BiModeBP::takenCounters
std::vector< SatCounter > takenCounters
Definition: bi_mode.hh:102
BiModeBP::BPHistory::notTakenPred
bool notTakenPred
Definition: bi_mode.hh:81
SatCounter
Implements an n bit saturating counter and provides methods to increment, decrement,...
Definition: sat_counter.hh:54
BiModeBP::choicePredictorSize
unsigned choicePredictorSize
Definition: bi_mode.hh:92
BiModeBP::update
void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history, bool squashed, const StaticInstPtr &inst, Addr corrTarget)
Updates the BP with taken/not taken information.
Definition: bi_mode.cc:152
BiModeBP::globalHistoryMask
unsigned globalHistoryMask
Definition: bi_mode.hh:97
BiModeBP::notTakenCounters
std::vector< SatCounter > notTakenCounters
Definition: bi_mode.hh:104
bi_mode.hh
BiModeBP::squash
void squash(ThreadID tid, void *bp_history)
Definition: bi_mode.cc:83
BiModeBP::notTakenThreshold
unsigned notTakenThreshold
Definition: bi_mode.hh:108
RefCountingPtr< StaticInst >
BiModeBP::uncondBranch
void uncondBranch(ThreadID tid, Addr pc, void *&bp_history)
Definition: bi_mode.cc:70
intmath.hh
BiModeBP::btbUpdate
void btbUpdate(ThreadID tid, Addr branch_addr, void *&bp_history)
If a branch is not taken, because the BTB address is invalid or missing, this function sets the appro...
Definition: bi_mode.cc:140
isPowerOf2
bool isPowerOf2(const T &n)
Definition: intmath.hh:102
BiModeBP::BiModeBP
BiModeBP(const BiModeBPParams *params)
Definition: bi_mode.cc:38
ULL
#define ULL(N)
uint64_t constant
Definition: types.hh:50
ArmISA::mask
Bitfield< 28, 24 > mask
Definition: miscregs_types.hh:711

Generated on Wed Sep 30 2020 14:02:09 for gem5 by doxygen 1.8.17