gem5 v23.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
35
36#include "base/random.hh"
37#include "base/trace.hh"
38#include "debug/LTage.hh"
39#include "params/LoopPredictor.hh"
40
41namespace gem5
42{
43
44namespace branch_prediction
45{
46
47LoopPredictor::LoopPredictor(const LoopPredictorParams &p)
48 : SimObject(p), logSizeLoopPred(p.logSizeLoopPred),
49 loopTableAgeBits(p.loopTableAgeBits),
50 loopTableConfidenceBits(p.loopTableConfidenceBits),
51 loopTableTagBits(p.loopTableTagBits),
52 loopTableIterBits(p.loopTableIterBits),
53 logLoopTableAssoc(p.logLoopTableAssoc),
54 confidenceThreshold((1 << loopTableConfidenceBits) - 1),
55 loopTagMask((1 << loopTableTagBits) - 1),
56 loopNumIterMask((1 << loopTableIterBits) - 1),
57 loopSetMask((1 << (logSizeLoopPred - logLoopTableAssoc)) - 1),
58 loopUseCounter(-1),
59 withLoopBits(p.withLoopBits),
60 useDirectionBit(p.useDirectionBit),
61 useSpeculation(p.useSpeculation),
62 useHashing(p.useHashing),
63 restrictAllocation(p.restrictAllocation),
64 initialLoopIter(p.initialLoopIter),
65 initialLoopAge(p.initialLoopAge),
66 optionalAgeReset(p.optionalAgeReset),
67 stats(this)
68{
69 assert(initialLoopAge <= ((1 << loopTableAgeBits) - 1));
70}
71
72void
74{
75 // we use uint16_t type for these vales, so they cannot be more than
76 // 16 bits
77 assert(loopTableTagBits <= 16);
78 assert(loopTableIterBits <= 16);
79
81
82 ltable = new LoopEntry[1ULL << logSizeLoopPred];
83}
84
87{
88 return new BranchInfo();
89}
90
91int
92LoopPredictor::lindex(Addr pc_in, unsigned instShiftAmt) const
93{
94 // The loop table is implemented as a linear table
95 // If associativity is N (N being 1 << logLoopTableAssoc),
96 // the first N entries are for set 0, the next N entries are for set 1,
97 // and so on.
98 // Thus, this function calculates the set and then it gets left shifted
99 // by logLoopTableAssoc in order to return the index of the first of the
100 // N entries of the set
101 Addr pc = pc_in >> instShiftAmt;
102 if (useHashing) {
103 pc ^= pc_in;
104 }
105 return ((pc & loopSetMask) << logLoopTableAssoc);
106}
107
108int
109LoopPredictor::finallindex(int index, int lowPcBits, int way) const
110{
111 return (useHashing ? (index ^ ((lowPcBits >> way) << logLoopTableAssoc)) :
112 (index))
113 + way;
114}
115
116//loop prediction: only used if high confidence
117bool
119 unsigned instShiftAmt) const
120{
121 bi->loopHit = -1;
122 bi->loopPredValid = false;
123 bi->loopIndex = lindex(pc, instShiftAmt);
124
125 if (useHashing) {
126 unsigned pcShift = logSizeLoopPred - logLoopTableAssoc;
127 bi->loopIndexB = (pc >> pcShift) & loopSetMask;
128 bi->loopTag = (pc >> pcShift) ^ (pc >> (pcShift + loopTableTagBits));
129 bi->loopTag &= loopTagMask;
130 } else {
131 unsigned pcShift = instShiftAmt + logSizeLoopPred - logLoopTableAssoc;
132 bi->loopTag = (pc >> pcShift) & loopTagMask;
133 // bi->loopIndexB is not used without hash
134 }
135
136 for (int i = 0; i < (1 << logLoopTableAssoc); i++) {
137 int idx = finallindex(bi->loopIndex, bi->loopIndexB, i);
138 if (ltable[idx].tag == bi->loopTag) {
139 bi->loopHit = i;
140 bi->loopPredValid = calcConf(idx);
141
142 uint16_t iter = speculative ? ltable[idx].currentIterSpec
143 : ltable[idx].currentIter;
144
145 if ((iter + 1) == ltable[idx].numIter) {
146 return useDirectionBit ? !(ltable[idx].dir) : false;
147 } else {
148 return useDirectionBit ? (ltable[idx].dir) : true;
149 }
150 }
151 }
152 return false;
153}
154
155bool
157{
159}
160
161void
163{
164 if (bi->loopHit>=0) {
165 int index = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit);
166 if (taken != ltable[index].dir) {
168 } else {
171 }
172 }
173}
174
175bool
177{
178 return false;
179}
180
181void
182LoopPredictor::loopUpdate(Addr pc, bool taken, BranchInfo* bi, bool tage_pred)
183{
184 int idx = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit);
185 if (bi->loopHit >= 0) {
186 //already a hit
187 if (bi->loopPredValid) {
188 if (taken != bi->loopPred) {
189 // free the entry
190 ltable[idx].numIter = 0;
191 ltable[idx].age = 0;
192 ltable[idx].confidence = 0;
193 ltable[idx].currentIter = 0;
194 return;
195 } else if (bi->loopPred != tage_pred || optionalAgeInc()) {
196 DPRINTF(LTage, "Loop Prediction success:%lx\n",pc);
198 }
199 }
200
201 ltable[idx].currentIter =
203 if (ltable[idx].currentIter > ltable[idx].numIter) {
204 ltable[idx].confidence = 0;
205 if (ltable[idx].numIter != 0) {
206 // free the entry
207 ltable[idx].numIter = 0;
208 if (optionalAgeReset) {
209 ltable[idx].age = 0;
210 }
211 }
212 }
213
214 if (taken != (useDirectionBit ? ltable[idx].dir : true)) {
215 if (ltable[idx].currentIter == ltable[idx].numIter) {
216 DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc);
217 unsignedCtrUpdate(ltable[idx].confidence, true,
219 //just do not predict when the loop count is 1 or 2
220 if (ltable[idx].numIter < 3) {
221 // free the entry
222 ltable[idx].dir = taken; // ignored if no useDirectionBit
223 ltable[idx].numIter = 0;
224 ltable[idx].age = 0;
225 ltable[idx].confidence = 0;
226 }
227 } else {
228 DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc);
229 if (ltable[idx].numIter == 0) {
230 // first complete nest;
231 ltable[idx].confidence = 0;
232 ltable[idx].numIter = ltable[idx].currentIter;
233 } else {
234 //not the same number of iterations as last time: free the
235 //entry
236 ltable[idx].numIter = 0;
237 if (optionalAgeReset) {
238 ltable[idx].age = 0;
239 }
240 ltable[idx].confidence = 0;
241 }
242 }
243 ltable[idx].currentIter = 0;
244 }
245
246 } else if (useDirectionBit ? (bi->predTaken != taken) : taken) {
247 if ((random_mt.random<int>() & 3) == 0 || !restrictAllocation) {
248 //try to allocate an entry on taken branch
249 int nrand = random_mt.random<int>();
250 for (int i = 0; i < (1 << logLoopTableAssoc); i++) {
251 int loop_hit = (nrand + i) & ((1 << logLoopTableAssoc) - 1);
252 idx = finallindex(bi->loopIndex, bi->loopIndexB, loop_hit);
253 if (ltable[idx].age == 0) {
254 DPRINTF(LTage,
255 "Allocating loop pred entry for branch %lx\n",
256 pc);
257 ltable[idx].dir = !taken; // ignored if no useDirectionBit
258 ltable[idx].tag = bi->loopTag;
259 ltable[idx].numIter = 0;
261 ltable[idx].confidence = 0;
263 break;
264
265 } else {
266 ltable[idx].age--;
267 }
268 if (restrictAllocation) {
269 break;
270 }
271 }
272 }
273 }
274}
275
276bool
277LoopPredictor::loopPredict(ThreadID tid, Addr branch_pc, bool cond_branch,
278 BranchInfo* bi, bool prev_pred_taken, unsigned instShiftAmt)
279{
280 bool pred_taken = prev_pred_taken;
281 if (cond_branch) {
282 // loop prediction
283 bi->loopPred = getLoop(branch_pc, bi, useSpeculation, instShiftAmt);
284
285 if ((loopUseCounter >= 0) && bi->loopPredValid) {
286 pred_taken = bi->loopPred;
287 bi->loopPredUsed = true;
288 }
289
290 if (useSpeculation) {
291 specLoopUpdate(pred_taken, bi);
292 }
293 }
294
295 return pred_taken;
296}
297
298void
300{
301 if (bi->loopHit >= 0) {
302 int idx = finallindex(bi->loopIndex,
303 bi->loopIndexB,
304 bi->loopHit);
305 ltable[idx].currentIterSpec = bi->currentIter;
306 }
307}
308
309void
311{
312 if (bi->loopHit >= 0) {
313 int idx = finallindex(bi->loopIndex,
314 bi->loopIndexB,
315 bi->loopHit);
316 ltable[idx].currentIterSpec = bi->currentIter;
317 }
318}
319
320void
322{
323 if (taken == bi->loopPred) {
324 stats.correct++;
325 } else {
326 stats.wrong++;
327 }
328}
329
330void
332 bool tage_pred, BranchInfo* bi,
333 unsigned instShiftAmt)
334{
335 if (useSpeculation) {
336 // recalculate loop prediction without speculation
337 // It is ok to overwrite the loop prediction fields in bi
338 // as the stats have already been updated with the previous
339 // values
340 bi->loopPred = getLoop(branch_pc, bi, false, instShiftAmt);
341 }
342
343 if (bi->loopPredValid) {
344 if (bi->predTaken != bi->loopPred) {
346 (bi->loopPred == taken),
348 }
349 }
350
351 loopUpdate(branch_pc, taken, bi, tage_pred);
352}
353
355 statistics::Group *parent)
356 : statistics::Group(parent),
357 ADD_STAT(correct, statistics::units::Count::get(),
358 "Number of times the loop predictor is the provider and the "
359 "prediction is correct"),
360 ADD_STAT(wrong, statistics::units::Count::get(),
361 "Number of times the loop predictor is the provider and the "
362 "prediction is wrong")
363{
364}
365
366size_t
368{
369 return (1ULL << logSizeLoopPred) *
370 ((useSpeculation ? 3 : 2) * loopTableIterBits +
373}
374
375} // namespace branch_prediction
376} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Abstract superclass for simulation objects.
LoopPredictor(const LoopPredictorParams &p)
void updateStats(bool taken, BranchInfo *bi)
Update the stats.
int finallindex(int lindex, int lowPcBits, int way) const
Computes the index used to access the ltable structures.
static void unsignedCtrUpdate(uint8_t &ctr, bool up, unsigned nbits)
Updates an unsigned counter based on up/down parameter.
static void signedCtrUpdate(int8_t &ctr, bool up, unsigned nbits)
void specLoopUpdate(bool taken, BranchInfo *bi)
Speculatively updates the loop predictor iteration count (only for useSpeculation).
gem5::branch_prediction::LoopPredictor::LoopPredictorStats stats
int lindex(Addr pc_in, unsigned instShiftAmt) const
Computes the index used to access the loop predictor.
void init() override
Initialize the loop predictor.
void condBranchUpdate(ThreadID tid, Addr branch_pc, bool taken, bool tage_pred, BranchInfo *bi, unsigned instShiftAmt)
Update LTAGE for conditional branches.
virtual bool calcConf(int index) const
bool getLoop(Addr pc, BranchInfo *bi, bool speculative, unsigned instShiftAmt) const
Get a branch prediction from the loop predictor.
bool loopPredict(ThreadID tid, Addr branch_pc, bool cond_branch, BranchInfo *bi, bool prev_pred_taken, unsigned instShiftAmt)
Get the loop prediction.
void loopUpdate(Addr pc, bool Taken, BranchInfo *bi, bool tage_pred)
Updates the loop predictor.
void squash(ThreadID tid, BranchInfo *bi)
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
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
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 4 > pc
Bitfield< 30, 0 > index
Bitfield< 0 > p
Bitfield< 20, 16 > bi
Definition types.hh:80
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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

Generated on Mon Jul 10 2023 14:24:29 for gem5 by doxygen 1.9.7