Deleted Added
sdiff udiff text old ( 13454:19a5b4fb1f1f ) new ( 13455:56e25a5f9603 )
full compact
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
37/* @file
38 * Implementation of a TAGE branch predictor. TAGE is a global-history based
39 * branch predictor. It features a PC-indexed bimodal predictor and N
40 * partially tagged tables, indexed with a hash of the PC and the global
41 * branch history. The different lengths of global branch history used to
42 * index the partially tagged tables grow geometrically. A small path history
43 * is also used in the hash.
44 *
45 * All TAGE tables are accessed in parallel, and the one using the longest
46 * history that matches provides the prediction (some exceptions apply).
47 * Entries are allocated in components using a longer history than the
48 * one that predicted when the prediction is incorrect.
49 */
50
51#ifndef __CPU_PRED_TAGE
52#define __CPU_PRED_TAGE
53
54#include <vector>
55
56#include "base/types.hh"
57#include "cpu/pred/bpred_unit.hh"
58#include "params/TAGE.hh"
59
60class TAGE: public BPredUnit
61{
62 public:
63 TAGE(const TAGEParams *params);
64
65 // Base class methods.
66 void uncondBranch(ThreadID tid, Addr br_pc, void* &bp_history) override;
67 bool lookup(ThreadID tid, Addr branch_addr, void* &bp_history) override;
68 void btbUpdate(ThreadID tid, Addr branch_addr, void* &bp_history) override;
69 void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
70 bool squashed) override;
71 virtual void squash(ThreadID tid, void *bp_history) override;
72 unsigned getGHR(ThreadID tid, void *bp_history) const override;
73
74 protected:
75 // Prediction Structures
76
77 // Tage Entry
78 struct TageEntry
79 {
80 int8_t ctr;
81 uint16_t tag;
82 uint8_t u;
83 TageEntry() : ctr(0), tag(0), u(0) { }
84 };
85
86 // Folded History Table - compressed history
87 // to mix with instruction PC to index partially
88 // tagged tables.
89 struct FoldedHistory
90 {
91 unsigned comp;
92 int compLength;
93 int origLength;
94 int outpoint;
95
96 void init(int original_length, int compressed_length)
97 {
98 comp = 0;
99 origLength = original_length;
100 compLength = compressed_length;
101 outpoint = original_length % compressed_length;
102 }
103
104 void update(uint8_t * h)
105 {
106 comp = (comp << 1) | h[0];
107 comp ^= h[origLength] << outpoint;
108 comp ^= (comp >> compLength);
109 comp &= (ULL(1) << compLength) - 1;
110 }
111 };
112
113 // Primary branch history entry
114 struct TageBranchInfo
115 {
116 int pathHist;
117 int ptGhist;
118 int hitBank;
119 int hitBankIndex;
120 int altBank;
121 int altBankIndex;
122 int bimodalIndex;
123
124 bool tagePred;
125 bool altTaken;
126 bool condBranch;
127 bool longestMatchPred;
128 bool pseudoNewAlloc;
129 Addr branchPC;
130
131 // Pointer to dynamically allocated storage
132 // to save table indices and folded histories.
133 // To do one call to new instead of five.
134 int *storage;
135
136 // Pointers to actual saved array within the dynamically
137 // allocated storage.
138 int *tableIndices;
139 int *tableTags;
140 int *ci;
141 int *ct0;
142 int *ct1;
143
144 TageBranchInfo(int sz)
145 : pathHist(0), ptGhist(0),
146 hitBank(0), hitBankIndex(0),
147 altBank(0), altBankIndex(0),
148 bimodalIndex(0),
149 tagePred(false), altTaken(false),
150 condBranch(false), longestMatchPred(false),
151 pseudoNewAlloc(false), branchPC(0)
152 {
153 storage = new int [sz * 5];
154 tableIndices = storage;
155 tableTags = storage + sz;
156 ci = tableTags + sz;
157 ct0 = ci + sz;
158 ct1 = ct0 + sz;
159 }
160
161 virtual ~TageBranchInfo()
162 {
163 delete[] storage;
164 }
165 };
166
167 /**
168 * Computes the index used to access the
169 * bimodal table.
170 * @param pc_in The unshifted branch PC.
171 */
172 int bindex(Addr pc_in) const;
173
174 /**
175 * Computes the index used to access a
176 * partially tagged table.
177 * @param tid The thread ID used to select the
178 * global histories to use.
179 * @param pc The unshifted branch PC.
180 * @param bank The partially tagged table to access.
181 */
182 inline int gindex(ThreadID tid, Addr pc, int bank) const;
183
184 /**
185 * Utility function to shuffle the path history
186 * depending on which tagged table we are accessing.
187 * @param phist The path history.
188 * @param size Number of path history bits to use.
189 * @param bank The partially tagged table to access.
190 */
191 int F(int phist, int size, int bank) const;
192
193 /**
194 * Computes the partial tag of a tagged table.
195 * @param tid the thread ID used to select the
196 * global histories to use.
197 * @param pc The unshifted branch PC.
198 * @param bank The partially tagged table to access.
199 */
200 inline uint16_t gtag(ThreadID tid, Addr pc, int bank) const;
201
202 /**
203 * Updates a direction counter based on the actual
204 * branch outcome.
205 * @param ctr Reference to counter to update.
206 * @param taken Actual branch outcome.
207 * @param nbits Counter width.
208 */
209 void ctrUpdate(int8_t & ctr, bool taken, int nbits);
210
211 /**
212 * Updates an unsigned counter based on up/down parameter
213 * @param ctr Reference to counter to update.
214 * @param up Boolean indicating if the counter is incremented/decremented
215 * If true it is incremented, if false it is decremented
216 * @param nbits Counter width.
217 */
218 void unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits);
219
220 /**
221 * Get a branch prediction from the bimodal
222 * predictor.
223 * @param pc The unshifted branch PC.
224 * @param bi Pointer to information on the
225 * prediction.
226 */
227 bool getBimodePred(Addr pc, TageBranchInfo* bi) const;
228
229 /**
230 * Updates the bimodal predictor.
231 * @param pc The unshifted branch PC.
232 * @param taken The actual branch outcome.
233 * @param bi Pointer to information on the prediction
234 * recorded at prediction time.
235 */
236 void baseUpdate(Addr pc, bool taken, TageBranchInfo* bi);
237
238 /**
239 * (Speculatively) updates the global branch history.
240 * @param h Reference to pointer to global branch history.
241 * @param dir (Predicted) outcome to update the histories
242 * with.
243 * @param tab
244 * @param PT Reference to path history.
245 */
246 void updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &PT);
247
248 /**
249 * Get a branch prediction from TAGE. *NOT* an override of
250 * BpredUnit::predict().
251 * @param tid The thread ID to select the global
252 * histories to use.
253 * @param branch_pc The unshifted branch PC.
254 * @param cond_branch True if the branch is conditional.
255 * @param b Reference to wrapping pointer to allow storing
256 * derived class prediction information in the base class.
257 */
258 virtual bool predict(
259 ThreadID tid, Addr branch_pc, bool cond_branch, void* &b);
260
261 /**
262 * Update TAGE. Called at execute to repair histories on a misprediction
263 * and at commit to update the tables.
264 * @param tid The thread ID to select the global
265 * histories to use.
266 * @param branch_pc The unshifted branch PC.
267 * @param taken Actual branch outcome.
268 * @param bi Pointer to information on the prediction
269 * recorded at prediction time.
270 */
271 void update(ThreadID tid, Addr branch_pc, bool taken, TageBranchInfo* bi);
272
273 /**
274 * (Speculatively) updates global histories (path and direction).
275 * Also recomputes compressed (folded) histories based on the
276 * branch direction.
277 * @param tid The thread ID to select the histories
278 * to update.
279 * @param branch_pc The unshifted branch PC.
280 * @param taken (Predicted) branch direction.
281 * @param b Wrapping pointer to TageBranchInfo (to allow
282 * storing derived class prediction information in the
283 * base class).
284 */
285 void updateHistories(ThreadID tid, Addr branch_pc, bool taken, void* b);
286
287 /**
288 * Restores speculatively updated path and direction histories.
289 * Also recomputes compressed (folded) histories based on the
290 * correct branch outcome.
291 * This version of squash() is called once on a branch misprediction.
292 * @param tid The Thread ID to select the histories to rollback.
293 * @param taken The correct branch outcome.
294 * @param bp_history Wrapping pointer to TageBranchInfo (to allow
295 * storing derived class prediction information in the
296 * base class).
297 * @post bp_history points to valid memory.
298 */
299 virtual void squash(ThreadID tid, bool taken, void *bp_history);
300
301 /**
302 * Update TAGE for conditional branches.
303 * @param branch_pc The unshifted branch PC.
304 * @param taken Actual branch outcome.
305 * @param bi Pointer to information on the prediction
306 * recorded at prediction time.
307 * @nrand Random int number from 0 to 3
308 */
309 virtual void condBranchUpdate(
310 Addr branch_pc, bool taken, TageBranchInfo* bi, int nrand);
311
312 /**
313 * TAGE prediction called from TAGE::predict
314 * @param tid The thread ID to select the global
315 * histories to use.
316 * @param branch_pc The unshifted branch PC.
317 * @param cond_branch True if the branch is conditional.
318 * @param bi Pointer to the TageBranchInfo
319 */
320 bool tagePredict(
321 ThreadID tid, Addr branch_pc, bool cond_branch, TageBranchInfo* bi);
322
323 const unsigned logRatioBiModalHystEntries;
324 const unsigned nHistoryTables;
325 const unsigned tagTableCounterBits;
326 const unsigned tagTableUBits;
327 const unsigned histBufferSize;
328 const unsigned minHist;
329 const unsigned maxHist;
330 const unsigned pathHistBits;
331
332 const std::vector<unsigned> tagTableTagWidths;
333 const std::vector<int> logTagTableSizes;
334
335 std::vector<bool> btablePrediction;
336 std::vector<bool> btableHysteresis;
337 TageEntry **gtable;
338
339 // Keep per-thread histories to
340 // support SMT.
341 struct ThreadHistory {
342 // Speculative path history
343 // (LSB of branch address)
344 int pathHist;
345
346 // Speculative branch direction
347 // history (circular buffer)
348 // @TODO Convert to std::vector<bool>
349 uint8_t *globalHistory;
350
351 // Pointer to most recent branch outcome
352 uint8_t* gHist;
353
354 // Index to most recent branch outcome
355 int ptGhist;
356
357 // Speculative folded histories.
358 FoldedHistory *computeIndices;
359 FoldedHistory *computeTags[2];
360 };
361
362 std::vector<ThreadHistory> threadHistory;
363
364 int *histLengths;
365 int *tableIndices;
366 int *tableTags;
367
368 int8_t useAltPredForNewlyAllocated;
369 uint64_t tCounter;
370 uint64_t logUResetPeriod;
371 unsigned useAltOnNaBits;
372};
373
374#endif // __CPU_PRED_TAGE