gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
loop_predictor.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 The University of Wisconsin
3  *
4  * Copyright (c) 2006 INRIA (Institut National de Recherche en
5  * Informatique et en Automatique / French National Research Institute
6  * for Computer Science and Applied Mathematics)
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are
12  * met: redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer;
14  * redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution;
17  * neither the name of the copyright holders nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais,
34  * from André Seznec's code.
35  */
36 
38 
39 #include "base/random.hh"
40 #include "debug/LTage.hh"
41 #include "params/LoopPredictor.hh"
42 
43 LoopPredictor::LoopPredictor(LoopPredictorParams *p)
44  : SimObject(p), logSizeLoopPred(p->logSizeLoopPred),
45  loopTableAgeBits(p->loopTableAgeBits),
46  loopTableConfidenceBits(p->loopTableConfidenceBits),
47  loopTableTagBits(p->loopTableTagBits),
48  loopTableIterBits(p->loopTableIterBits),
49  logLoopTableAssoc(p->logLoopTableAssoc),
50  confidenceThreshold((1 << loopTableConfidenceBits) - 1),
51  loopTagMask((1 << loopTableTagBits) - 1),
52  loopNumIterMask((1 << loopTableIterBits) - 1),
53  loopSetMask((1 << (logSizeLoopPred - logLoopTableAssoc)) - 1),
54  loopUseCounter(-1),
55  withLoopBits(p->withLoopBits),
56  useDirectionBit(p->useDirectionBit),
57  useSpeculation(p->useSpeculation),
58  useHashing(p->useHashing),
59  restrictAllocation(p->restrictAllocation),
60  initialLoopIter(p->initialLoopIter),
61  initialLoopAge(p->initialLoopAge),
62  optionalAgeReset(p->optionalAgeReset)
63 {
64  assert(initialLoopAge <= ((1 << loopTableAgeBits) - 1));
65 }
66 
67 void
69 {
70  // we use uint16_t type for these vales, so they cannot be more than
71  // 16 bits
72  assert(loopTableTagBits <= 16);
73  assert(loopTableIterBits <= 16);
74 
76 
77  ltable = new LoopEntry[ULL(1) << logSizeLoopPred];
78 }
79 
82 {
83  return new BranchInfo();
84 }
85 
86 int
87 LoopPredictor::lindex(Addr pc_in, unsigned instShiftAmt) const
88 {
89  // The loop table is implemented as a linear table
90  // If associativity is N (N being 1 << logLoopTableAssoc),
91  // the first N entries are for set 0, the next N entries are for set 1,
92  // and so on.
93  // Thus, this function calculates the set and then it gets left shifted
94  // by logLoopTableAssoc in order to return the index of the first of the
95  // N entries of the set
96  Addr pc = pc_in >> instShiftAmt;
97  if (useHashing) {
98  pc ^= pc_in;
99  }
100  return ((pc & loopSetMask) << logLoopTableAssoc);
101 }
102 
103 int
104 LoopPredictor::finallindex(int index, int lowPcBits, int way) const
105 {
106  return (useHashing ? (index ^ ((lowPcBits >> way) << logLoopTableAssoc)) :
107  (index))
108  + way;
109 }
110 
111 //loop prediction: only used if high confidence
112 bool
114  unsigned instShiftAmt) const
115 {
116  bi->loopHit = -1;
117  bi->loopPredValid = false;
118  bi->loopIndex = lindex(pc, instShiftAmt);
119 
120  if (useHashing) {
121  unsigned pcShift = logSizeLoopPred - logLoopTableAssoc;
122  bi->loopIndexB = (pc >> pcShift) & loopSetMask;
123  bi->loopTag = (pc >> pcShift) ^ (pc >> (pcShift + loopTableTagBits));
124  bi->loopTag &= loopTagMask;
125  } else {
126  unsigned pcShift = instShiftAmt + logSizeLoopPred - logLoopTableAssoc;
127  bi->loopTag = (pc >> pcShift) & loopTagMask;
128  // bi->loopIndexB is not used without hash
129  }
130 
131  for (int i = 0; i < (1 << logLoopTableAssoc); i++) {
132  int idx = finallindex(bi->loopIndex, bi->loopIndexB, i);
133  if (ltable[idx].tag == bi->loopTag) {
134  bi->loopHit = i;
135  bi->loopPredValid = calcConf(idx);
136 
137  uint16_t iter = speculative ? ltable[idx].currentIterSpec
138  : ltable[idx].currentIter;
139 
140  if ((iter + 1) == ltable[idx].numIter) {
141  return useDirectionBit ? !(ltable[idx].dir) : false;
142  } else {
143  return useDirectionBit ? (ltable[idx].dir) : true;
144  }
145  }
146  }
147  return false;
148 }
149 
150 bool
152 {
154 }
155 
156 void
158 {
159  if (bi->loopHit>=0) {
160  int index = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit);
161  if (taken != ltable[index].dir) {
163  } else {
166  }
167  }
168 }
169 
170 bool
172 {
173  return false;
174 }
175 
176 void
177 LoopPredictor::loopUpdate(Addr pc, bool taken, BranchInfo* bi, bool tage_pred)
178 {
179  int idx = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit);
180  if (bi->loopHit >= 0) {
181  //already a hit
182  if (bi->loopPredValid) {
183  if (taken != bi->loopPred) {
184  // free the entry
185  ltable[idx].numIter = 0;
186  ltable[idx].age = 0;
187  ltable[idx].confidence = 0;
188  ltable[idx].currentIter = 0;
189  return;
190  } else if (bi->loopPred != tage_pred || optionalAgeInc()) {
191  DPRINTF(LTage, "Loop Prediction success:%lx\n",pc);
192  unsignedCtrUpdate(ltable[idx].age, true, loopTableAgeBits);
193  }
194  }
195 
196  ltable[idx].currentIter =
197  (ltable[idx].currentIter + 1) & loopNumIterMask;
198  if (ltable[idx].currentIter > ltable[idx].numIter) {
199  ltable[idx].confidence = 0;
200  if (ltable[idx].numIter != 0) {
201  // free the entry
202  ltable[idx].numIter = 0;
203  if (optionalAgeReset) {
204  ltable[idx].age = 0;
205  }
206  }
207  }
208 
209  if (taken != (useDirectionBit ? ltable[idx].dir : true)) {
210  if (ltable[idx].currentIter == ltable[idx].numIter) {
211  DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc);
212  unsignedCtrUpdate(ltable[idx].confidence, true,
214  //just do not predict when the loop count is 1 or 2
215  if (ltable[idx].numIter < 3) {
216  // free the entry
217  ltable[idx].dir = taken; // ignored if no useDirectionBit
218  ltable[idx].numIter = 0;
219  ltable[idx].age = 0;
220  ltable[idx].confidence = 0;
221  }
222  } else {
223  DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc);
224  if (ltable[idx].numIter == 0) {
225  // first complete nest;
226  ltable[idx].confidence = 0;
227  ltable[idx].numIter = ltable[idx].currentIter;
228  } else {
229  //not the same number of iterations as last time: free the
230  //entry
231  ltable[idx].numIter = 0;
232  if (optionalAgeReset) {
233  ltable[idx].age = 0;
234  }
235  ltable[idx].confidence = 0;
236  }
237  }
238  ltable[idx].currentIter = 0;
239  }
240 
241  } else if (useDirectionBit ? (bi->predTaken != taken) : taken) {
242  if ((random_mt.random<int>() & 3) == 0 || !restrictAllocation) {
243  //try to allocate an entry on taken branch
244  int nrand = random_mt.random<int>();
245  for (int i = 0; i < (1 << logLoopTableAssoc); i++) {
246  int loop_hit = (nrand + i) & ((1 << logLoopTableAssoc) - 1);
247  idx = finallindex(bi->loopIndex, bi->loopIndexB, loop_hit);
248  if (ltable[idx].age == 0) {
249  DPRINTF(LTage,
250  "Allocating loop pred entry for branch %lx\n",
251  pc);
252  ltable[idx].dir = !taken; // ignored if no useDirectionBit
253  ltable[idx].tag = bi->loopTag;
254  ltable[idx].numIter = 0;
255  ltable[idx].age = initialLoopAge;
256  ltable[idx].confidence = 0;
258  break;
259 
260  } else {
261  ltable[idx].age--;
262  }
263  if (restrictAllocation) {
264  break;
265  }
266  }
267  }
268  }
269 }
270 
271 bool
272 LoopPredictor::loopPredict(ThreadID tid, Addr branch_pc, bool cond_branch,
273  BranchInfo* bi, bool prev_pred_taken, unsigned instShiftAmt)
274 {
275  bool pred_taken = prev_pred_taken;
276  if (cond_branch) {
277  // loop prediction
278  bi->loopPred = getLoop(branch_pc, bi, useSpeculation, instShiftAmt);
279 
280  if ((loopUseCounter >= 0) && bi->loopPredValid) {
281  pred_taken = bi->loopPred;
282  bi->loopPredUsed = true;
283  }
284 
285  if (useSpeculation) {
286  specLoopUpdate(pred_taken, bi);
287  }
288  }
289 
290  return pred_taken;
291 }
292 
293 void
295 {
296  if (bi->loopHit >= 0) {
297  int idx = finallindex(bi->loopIndex,
298  bi->loopIndexB,
299  bi->loopHit);
301  }
302 }
303 
304 void
306 {
307  if (bi->loopHit >= 0) {
308  int idx = finallindex(bi->loopIndex,
309  bi->loopIndexB,
310  bi->loopHit);
312  }
313 }
314 
315 void
317 {
318  if (taken == bi->loopPred) {
320  } else {
322  }
323 }
324 
325 void
326 LoopPredictor::condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken,
327  bool tage_pred, BranchInfo* bi,
328  unsigned instShiftAmt)
329 {
330  if (useSpeculation) {
331  // recalculate loop prediction without speculation
332  // It is ok to overwrite the loop prediction fields in bi
333  // as the stats have already been updated with the previous
334  // values
335  bi->loopPred = getLoop(branch_pc, bi, false, instShiftAmt);
336  }
337 
338  if (bi->loopPredValid) {
339  if (bi->predTaken != bi->loopPred) {
341  (bi->loopPred == taken),
342  withLoopBits);
343  }
344  }
345 
346  loopUpdate(branch_pc, taken, bi, tage_pred);
347 }
348 
349 void
351 {
353  .name(name() + ".loopPredictorCorrect")
354  .desc("Number of times the loop predictor is the provider and "
355  "the prediction is correct");
356 
358  .name(name() + ".loopPredictorWrong")
359  .desc("Number of times the loop predictor is the provider and "
360  "the prediction is wrong");
361 }
362 
363 size_t
365 {
366  return (1ULL << logSizeLoopPred) *
367  ((useSpeculation ? 3 : 2) * loopTableIterBits +
370 }
371 
373 LoopPredictorParams::create()
374 {
375  return new LoopPredictor(this);
376 }
#define DPRINTF(x,...)
Definition: trace.hh:229
bool getLoop(Addr pc, BranchInfo *bi, bool speculative, unsigned instShiftAmt) const
Get a branch prediction from the loop predictor.
LoopEntry * ltable
void squashLoop(BranchInfo *bi)
const bool optionalAgeReset
Bitfield< 30, 0 > index
void squash(ThreadID tid, BranchInfo *bi)
Bitfield< 7 > i
Stats::Scalar loopPredictorCorrect
void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, bool tage_pred, BranchInfo *bi, unsigned instShiftAmt)
Update LTAGE for conditional branches.
virtual BranchInfo * makeBranchInfo()
const unsigned loopTableAgeBits
const int loopSetMask
const bool useDirectionBit
Bitfield< 20, 16 > bi
Definition: types.hh:65
std::enable_if< std::is_integral< T >::value, T >::type random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:83
void init() override
Initialize the loop predictor.
Stats::Scalar loopPredictorWrong
const uint16_t loopNumIterMask
const unsigned loopTableConfidenceBits
const unsigned logLoopTableAssoc
Bitfield< 4 > pc
static void unsignedCtrUpdate(uint8_t &ctr, bool up, unsigned nbits)
Updates an unsigned counter based on up/down parameter.
virtual bool calcConf(int index) const
int lindex(Addr pc_in, unsigned instShiftAmt) const
Computes the index used to access the loop predictor.
int finallindex(int lindex, int lowPcBits, int way) const
Computes the index used to access the ltable structures.
size_t getSizeInBits() const
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
#define ULL(N)
uint64_t constant
Definition: types.hh:50
virtual const std::string name() const
Definition: sim_object.hh:120
static void signedCtrUpdate(int8_t &ctr, bool up, unsigned nbits)
const unsigned loopTableIterBits
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:279
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:227
const uint8_t confidenceThreshold
const bool useHashing
void specLoopUpdate(bool taken, BranchInfo *bi)
Speculatively updates the loop predictor iteration count (only for useSpeculation).
void regStats() override
Register stats for this object.
LoopPredictor(LoopPredictorParams *p)
const unsigned loopTableTagBits
Random random_mt
Definition: random.cc:100
const unsigned initialLoopAge
const uint16_t loopTagMask
const unsigned logSizeLoopPred
const unsigned initialLoopIter
const bool useSpeculation
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:312
unsigned withLoopBits
Bitfield< 0 > p
bool loopPredict(ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo *bi, bool prev_pred_taken, unsigned instShiftAmt)
Get the loop prediction.
int8_t loopUseCounter
Abstract superclass for simulation objects.
Definition: sim_object.hh:96
void loopUpdate(Addr pc, bool Taken, BranchInfo *bi, bool tage_pred)
Updates the loop predictor.
const bool restrictAllocation
void updateStats(bool taken, BranchInfo *bi)
Update the stats.
virtual bool optionalAgeInc() const

Generated on Fri Feb 28 2020 16:26:59 for gem5 by doxygen 1.8.13