gem5 v24.0.0.0
Loading...
Searching...
No Matches
loop_predictor.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 (c) 2014 The University of Wisconsin
15 *
16 * Copyright (c) 2006 INRIA (Institut National de Recherche en
17 * Informatique et en Automatique / French National Research Institute
18 * for Computer Science and Applied Mathematics)
19 *
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions are
24 * met: redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer;
26 * redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution;
29 * neither the name of the copyright holders nor the names of its
30 * contributors may be used to endorse or promote products derived from
31 * this software without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
40 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
43 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 */
45
47
48#include "base/random.hh"
49#include "base/trace.hh"
50#include "debug/LTage.hh"
51#include "params/LoopPredictor.hh"
52
53namespace gem5
54{
55
56namespace branch_prediction
57{
58
59LoopPredictor::LoopPredictor(const LoopPredictorParams &p)
60 : SimObject(p), logSizeLoopPred(p.logSizeLoopPred),
61 loopTableAgeBits(p.loopTableAgeBits),
62 loopTableConfidenceBits(p.loopTableConfidenceBits),
63 loopTableTagBits(p.loopTableTagBits),
64 loopTableIterBits(p.loopTableIterBits),
65 logLoopTableAssoc(p.logLoopTableAssoc),
66 confidenceThreshold((1 << loopTableConfidenceBits) - 1),
67 loopTagMask((1 << loopTableTagBits) - 1),
68 loopNumIterMask((1 << loopTableIterBits) - 1),
69 loopSetMask((1 << (logSizeLoopPred - logLoopTableAssoc)) - 1),
70 loopUseCounter(-1),
71 withLoopBits(p.withLoopBits),
72 useDirectionBit(p.useDirectionBit),
73 useSpeculation(p.useSpeculation),
74 useHashing(p.useHashing),
75 restrictAllocation(p.restrictAllocation),
76 initialLoopIter(p.initialLoopIter),
77 initialLoopAge(p.initialLoopAge),
78 optionalAgeReset(p.optionalAgeReset),
79 stats(this)
80{
81 assert(initialLoopAge <= ((1 << loopTableAgeBits) - 1));
82}
83
84void
86{
87 // we use uint16_t type for these vales, so they cannot be more than
88 // 16 bits
89 assert(loopTableTagBits <= 16);
90 assert(loopTableIterBits <= 16);
91
93
94 ltable = new LoopEntry[1ULL << logSizeLoopPred];
95}
96
99{
100 return new BranchInfo();
101}
102
103int
104LoopPredictor::lindex(Addr pc_in, unsigned instShiftAmt) const
105{
106 // The loop table is implemented as a linear table
107 // If associativity is N (N being 1 << logLoopTableAssoc),
108 // the first N entries are for set 0, the next N entries are for set 1,
109 // and so on.
110 // Thus, this function calculates the set and then it gets left shifted
111 // by logLoopTableAssoc in order to return the index of the first of the
112 // N entries of the set
113 Addr pc = pc_in >> instShiftAmt;
114 if (useHashing) {
115 pc ^= pc_in;
116 }
117 return ((pc & loopSetMask) << logLoopTableAssoc);
118}
119
120int
121LoopPredictor::finallindex(int index, int lowPcBits, int way) const
122{
123 return (useHashing ? (index ^ ((lowPcBits >> way) << logLoopTableAssoc)) :
124 (index))
125 + way;
126}
127
128//loop prediction: only used if high confidence
129bool
131 unsigned instShiftAmt) const
132{
133 bi->loopHit = -1;
134 bi->loopPredValid = false;
135 bi->loopIndex = lindex(pc, instShiftAmt);
136
137 if (useHashing) {
138 unsigned pcShift = logSizeLoopPred - logLoopTableAssoc;
139 bi->loopIndexB = (pc >> pcShift) & loopSetMask;
140 bi->loopTag = (pc >> pcShift) ^ (pc >> (pcShift + loopTableTagBits));
141 bi->loopTag &= loopTagMask;
142 } else {
143 unsigned pcShift = instShiftAmt + logSizeLoopPred - logLoopTableAssoc;
144 bi->loopTag = (pc >> pcShift) & loopTagMask;
145 // bi->loopIndexB is not used without hash
146 }
147
148 for (int i = 0; i < (1 << logLoopTableAssoc); i++) {
149 int idx = finallindex(bi->loopIndex, bi->loopIndexB, i);
150 if (ltable[idx].tag == bi->loopTag) {
151 bi->loopHit = i;
152 bi->loopPredValid = calcConf(idx);
153
154 uint16_t iter = speculative ? ltable[idx].currentIterSpec
155 : ltable[idx].currentIter;
156
157 if ((iter + 1) == ltable[idx].numIter) {
158 return useDirectionBit ? !(ltable[idx].dir) : false;
159 } else {
160 return useDirectionBit ? (ltable[idx].dir) : true;
161 }
162 }
163 }
164 return false;
165}
166
167bool
172
173void
175{
176 if (bi->loopHit>=0) {
177 int index = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit);
178 if (taken != ltable[index].dir) {
180 } else {
183 }
184 }
185}
186
187bool
189{
190 return false;
191}
192
193void
194LoopPredictor::loopUpdate(Addr pc, bool taken, BranchInfo* bi, bool tage_pred)
195{
196 int idx = finallindex(bi->loopIndex, bi->loopIndexB, bi->loopHit);
197 if (bi->loopHit >= 0) {
198 //already a hit
199 if (bi->loopPredValid) {
200 if (taken != bi->loopPred) {
201 // free the entry
202 ltable[idx].numIter = 0;
203 ltable[idx].age = 0;
204 ltable[idx].confidence = 0;
205 ltable[idx].currentIter = 0;
206 return;
207 } else if (bi->loopPred != tage_pred || optionalAgeInc()) {
208 DPRINTF(LTage, "Loop Prediction success:%lx\n",pc);
210 }
211 }
212
213 ltable[idx].currentIter =
215 if (ltable[idx].currentIter > ltable[idx].numIter) {
216 ltable[idx].confidence = 0;
217 if (ltable[idx].numIter != 0) {
218 // free the entry
219 ltable[idx].numIter = 0;
220 if (optionalAgeReset) {
221 ltable[idx].age = 0;
222 }
223 }
224 }
225
226 if (taken != (useDirectionBit ? ltable[idx].dir : true)) {
227 if (ltable[idx].currentIter == ltable[idx].numIter) {
228 DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc);
229 unsignedCtrUpdate(ltable[idx].confidence, true,
231 //just do not predict when the loop count is 1 or 2
232 if (ltable[idx].numIter < 3) {
233 // free the entry
234 ltable[idx].dir = taken; // ignored if no useDirectionBit
235 ltable[idx].numIter = 0;
236 ltable[idx].age = 0;
237 ltable[idx].confidence = 0;
238 }
239 } else {
240 DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc);
241 if (ltable[idx].numIter == 0) {
242 // first complete nest;
243 ltable[idx].confidence = 0;
244 ltable[idx].numIter = ltable[idx].currentIter;
245 } else {
246 //not the same number of iterations as last time: free the
247 //entry
248 ltable[idx].numIter = 0;
249 if (optionalAgeReset) {
250 ltable[idx].age = 0;
251 }
252 ltable[idx].confidence = 0;
253 }
254 }
255 ltable[idx].currentIter = 0;
256 }
257
258 } else if (useDirectionBit ? (bi->predTaken != taken) : taken) {
259 if ((random_mt.random<int>() & 3) == 0 || !restrictAllocation) {
260 //try to allocate an entry on taken branch
261 int nrand = random_mt.random<int>();
262 for (int i = 0; i < (1 << logLoopTableAssoc); i++) {
263 int loop_hit = (nrand + i) & ((1 << logLoopTableAssoc) - 1);
264 idx = finallindex(bi->loopIndex, bi->loopIndexB, loop_hit);
265 if (ltable[idx].age == 0) {
266 DPRINTF(LTage,
267 "Allocating loop pred entry for branch %lx\n",
268 pc);
269 ltable[idx].dir = !taken; // ignored if no useDirectionBit
270 ltable[idx].tag = bi->loopTag;
271 ltable[idx].numIter = 0;
273 ltable[idx].confidence = 0;
275 break;
276
277 } else {
278 ltable[idx].age--;
279 }
280 if (restrictAllocation) {
281 break;
282 }
283 }
284 }
285 }
286}
287
288bool
289LoopPredictor::loopPredict(ThreadID tid, Addr branch_pc, bool cond_branch,
290 BranchInfo* bi, bool prev_pred_taken, unsigned instShiftAmt)
291{
292 bool pred_taken = prev_pred_taken;
293 if (cond_branch) {
294 // loop prediction
295 bi->loopPred = getLoop(branch_pc, bi, useSpeculation, instShiftAmt);
296
297 if ((loopUseCounter >= 0) && bi->loopPredValid) {
298 pred_taken = bi->loopPred;
299 bi->loopPredUsed = true;
300 }
301
302 if (useSpeculation) {
303 specLoopUpdate(pred_taken, bi);
304 }
305 }
306
307 return pred_taken;
308}
309
310void
312{
313 if (bi->loopHit >= 0) {
314 int idx = finallindex(bi->loopIndex,
315 bi->loopIndexB,
316 bi->loopHit);
317 ltable[idx].currentIterSpec = bi->currentIter;
318 }
319}
320
321void
323{
324 if (bi->loopHit >= 0) {
325 int idx = finallindex(bi->loopIndex,
326 bi->loopIndexB,
327 bi->loopHit);
328 ltable[idx].currentIterSpec = bi->currentIter;
329 }
330}
331
332void
334{
335 if (bi->loopPredUsed) {
336 stats.used++;
337 if (taken == bi->loopPred) {
338 stats.correct++;
339 } else {
340 stats.wrong++;
341 }
342 }
343}
344
345void
347 bool tage_pred, BranchInfo* bi,
348 unsigned instShiftAmt)
349{
350 if (useSpeculation) {
351 // recalculate loop prediction without speculation
352 // It is ok to overwrite the loop prediction fields in bi
353 // as the stats have already been updated with the previous
354 // values
355 bi->loopPred = getLoop(branch_pc, bi, false, instShiftAmt);
356 }
357
358 if (bi->loopPredValid) {
359 if (bi->predTaken != bi->loopPred) {
361 (bi->loopPred == taken),
363 }
364 }
365
366 loopUpdate(branch_pc, taken, bi, tage_pred);
367}
368
370 statistics::Group *parent)
371 : statistics::Group(parent),
372 ADD_STAT(used, statistics::units::Count::get(),
373 "Number of times the loop predictor is the provider."),
374 ADD_STAT(correct, statistics::units::Count::get(),
375 "Number of times the loop predictor is the provider and the "
376 "prediction is correct"),
377 ADD_STAT(wrong, statistics::units::Count::get(),
378 "Number of times the loop predictor is the provider and the "
379 "prediction is wrong")
380{
381}
382
383size_t
391
392} // namespace branch_prediction
393} // 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
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

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0