bpred_unit.cc (11427:fb512311295e) bpred_unit.cc (11429:cf5af0cc3be4)
1/*
2 * Copyright (c) 2011-2012, 2014 ARM Limited
3 * Copyright (c) 2010 The University of Edinburgh
4 * Copyright (c) 2012 Mark D. Hill and David A. Wood
5 * All rights reserved
6 *
7 * The license below extends only to copyright in the software and shall
8 * not be construed as granting a license to any other intellectual

--- 45 unchanged lines hidden (view full) ---

54#include "debug/Branch.hh"
55
56BPredUnit::BPredUnit(const Params *params)
57 : SimObject(params),
58 numThreads(params->numThreads),
59 predHist(numThreads),
60 BTB(params->BTBEntries,
61 params->BTBTagSize,
1/*
2 * Copyright (c) 2011-2012, 2014 ARM Limited
3 * Copyright (c) 2010 The University of Edinburgh
4 * Copyright (c) 2012 Mark D. Hill and David A. Wood
5 * All rights reserved
6 *
7 * The license below extends only to copyright in the software and shall
8 * not be construed as granting a license to any other intellectual

--- 45 unchanged lines hidden (view full) ---

54#include "debug/Branch.hh"
55
56BPredUnit::BPredUnit(const Params *params)
57 : SimObject(params),
58 numThreads(params->numThreads),
59 predHist(numThreads),
60 BTB(params->BTBEntries,
61 params->BTBTagSize,
62 params->instShiftAmt,
63 params->numThreads),
62 params->instShiftAmt),
64 RAS(numThreads),
63 RAS(numThreads),
65 useIndirect(params->useIndirect),
66 iPred(params->indirectHashGHR,
67 params->indirectHashTargets,
68 params->indirectSets,
69 params->indirectWays,
70 params->indirectTagSize,
71 params->indirectPathLength,
72 params->instShiftAmt,
73 params->numThreads),
74 instShiftAmt(params->instShiftAmt)
75{
76 for (auto& r : RAS)
77 r.init(params->RASSize);
78}
79
80void
81BPredUnit::regStats()

--- 39 unchanged lines hidden (view full) ---

121 .name(name() + ".usedRAS")
122 .desc("Number of times the RAS was used to get a target.")
123 ;
124
125 RASIncorrect
126 .name(name() + ".RASInCorrect")
127 .desc("Number of incorrect RAS predictions.")
128 ;
64 instShiftAmt(params->instShiftAmt)
65{
66 for (auto& r : RAS)
67 r.init(params->RASSize);
68}
69
70void
71BPredUnit::regStats()

--- 39 unchanged lines hidden (view full) ---

111 .name(name() + ".usedRAS")
112 .desc("Number of times the RAS was used to get a target.")
113 ;
114
115 RASIncorrect
116 .name(name() + ".RASInCorrect")
117 .desc("Number of incorrect RAS predictions.")
118 ;
129
130 indirectLookups
131 .name(name() + ".indirectLookups")
132 .desc("Number of indirect predictor lookups.")
133 ;
134
135 indirectHits
136 .name(name() + ".indirectHits")
137 .desc("Number of indirect target hits.")
138 ;
139
140 indirectMisses
141 .name(name() + ".indirectMisses")
142 .desc("Number of indirect misses.")
143 ;
144
145 indirectMispredicted
146 .name(name() + "indirectMispredcited")
147 .desc("Number of mispredicted indirect branches.")
148 ;
149
150}
151
152ProbePoints::PMUUPtr
153BPredUnit::pmuProbePoint(const char *name)
154{
155 ProbePoints::PMUUPtr ptr;
156 ptr.reset(new ProbePoints::PMU(getProbeManager(), name));
157

--- 32 unchanged lines hidden (view full) ---

190 ppBranches->notify(1);
191
192 void *bp_history = NULL;
193
194 if (inst->isUncondCtrl()) {
195 DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid);
196 pred_taken = true;
197 // Tell the BP there was an unconditional branch.
119}
120
121ProbePoints::PMUUPtr
122BPredUnit::pmuProbePoint(const char *name)
123{
124 ProbePoints::PMUUPtr ptr;
125 ptr.reset(new ProbePoints::PMU(getProbeManager(), name));
126

--- 32 unchanged lines hidden (view full) ---

159 ppBranches->notify(1);
160
161 void *bp_history = NULL;
162
163 if (inst->isUncondCtrl()) {
164 DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid);
165 pred_taken = true;
166 // Tell the BP there was an unconditional branch.
198 uncondBranch(tid, pc.instAddr(), bp_history);
167 uncondBranch(pc.instAddr(), bp_history);
199 } else {
200 ++condPredicted;
168 } else {
169 ++condPredicted;
201 pred_taken = lookup(tid, pc.instAddr(), bp_history);
170 pred_taken = lookup(pc.instAddr(), bp_history);
202
203 DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
204 " predicted %i for PC %s\n", tid, seqNum, pred_taken, pc);
205 }
206
207 DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history "
208 "for PC %s\n", tid, seqNum, pc);
209

--- 31 unchanged lines hidden (view full) ---

241 // be popped off if the speculation is incorrect.
242 predict_record.wasCall = true;
243
244 DPRINTF(Branch, "[tid:%i]: Instruction %s was a "
245 "call, adding %s to the RAS index: %i.\n",
246 tid, pc, pc, RAS[tid].topIdx());
247 }
248
171
172 DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
173 " predicted %i for PC %s\n", tid, seqNum, pred_taken, pc);
174 }
175
176 DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history "
177 "for PC %s\n", tid, seqNum, pc);
178

--- 31 unchanged lines hidden (view full) ---

210 // be popped off if the speculation is incorrect.
211 predict_record.wasCall = true;
212
213 DPRINTF(Branch, "[tid:%i]: Instruction %s was a "
214 "call, adding %s to the RAS index: %i.\n",
215 tid, pc, pc, RAS[tid].topIdx());
216 }
217
249 if (inst->isDirectCtrl() || !useIndirect) {
250 // Check BTB on direct branches
251 if (BTB.valid(pc.instAddr(), tid)) {
252 ++BTBHits;
218 if (BTB.valid(pc.instAddr(), tid)) {
219 ++BTBHits;
253
220
254 // If it's not a return, use the BTB to get target addr.
255 target = BTB.lookup(pc.instAddr(), tid);
221 // If it's not a return, use the BTB to get the target addr.
222 target = BTB.lookup(pc.instAddr(), tid);
256
223
257 DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
258 " target is %s.\n", tid, pc, target);
224 DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
225 " target is %s.\n", tid, pc, target);
259
226
260 } else {
261 DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
262 "valid entry.\n",tid);
263 pred_taken = false;
264 // The Direction of the branch predictor is altered
265 // because the BTB did not have an entry
266 // The predictor needs to be updated accordingly
267 if (!inst->isCall() && !inst->isReturn()) {
268 btbUpdate(tid, pc.instAddr(), bp_history);
269 DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
270 " called for %s\n", tid, seqNum, pc);
271 } else if (inst->isCall() && !inst->isUncondCtrl()) {
272 RAS[tid].pop();
273 predict_record.pushedRAS = false;
274 }
275 TheISA::advancePC(target, inst);
276 }
277 } else {
227 } else {
278 predict_record.wasIndirect = true;
279 ++indirectLookups;
280 //Consult indirect predictor on indirect control
281 if (iPred.lookup(pc.instAddr(), getGHR(tid, bp_history),
282 target, tid)) {
283 // Indirect predictor hit
284 ++indirectHits;
285 DPRINTF(Branch, "[tid:%i]: Instruction %s predicted "
286 "indirect target is %s.\n", tid, pc, target);
287 } else {
288 ++indirectMisses;
289 pred_taken = false;
290 DPRINTF(Branch, "[tid:%i]: Instruction %s no indirect "
291 "target.\n", tid, pc);
292 if (!inst->isCall() && !inst->isReturn()) {
293
294 } else if (inst->isCall() && !inst->isUncondCtrl()) {
295 RAS[tid].pop();
296 predict_record.pushedRAS = false;
297 }
298 TheISA::advancePC(target, inst);
228 DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
229 "valid entry.\n",tid);
230 pred_taken = false;
231 // The Direction of the branch predictor is altered because the
232 // BTB did not have an entry
233 // The predictor needs to be updated accordingly
234 if (!inst->isCall() && !inst->isReturn()) {
235 btbUpdate(pc.instAddr(), bp_history);
236 DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
237 " called for %s\n", tid, seqNum, pc);
238 } else if (inst->isCall() && !inst->isUncondCtrl()) {
239 RAS[tid].pop();
240 predict_record.pushedRAS = false;
299 }
241 }
300 iPred.recordIndirect(pc.instAddr(), target.instAddr(), seqNum,
301 tid);
242 TheISA::advancePC(target, inst);
302 }
303 }
304 } else {
305 if (inst->isReturn()) {
306 predict_record.wasReturn = true;
307 }
308 TheISA::advancePC(target, inst);
309 }

--- 31 unchanged lines hidden (view full) ---

341 inst->disassemble(instPC.instAddr()), instPC);
342
343 void *bp_history = NULL;
344
345 if (inst->isUncondCtrl()) {
346 DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid);
347 pred_taken = true;
348 // Tell the BP there was an unconditional branch.
243 }
244 }
245 } else {
246 if (inst->isReturn()) {
247 predict_record.wasReturn = true;
248 }
249 TheISA::advancePC(target, inst);
250 }

--- 31 unchanged lines hidden (view full) ---

282 inst->disassemble(instPC.instAddr()), instPC);
283
284 void *bp_history = NULL;
285
286 if (inst->isUncondCtrl()) {
287 DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid);
288 pred_taken = true;
289 // Tell the BP there was an unconditional branch.
349 uncondBranch(tid, instPC.instAddr(), bp_history);
290 uncondBranch(instPC.instAddr(), bp_history);
350
351 if (inst->isReturn() && RAS[tid].empty()) {
352 DPRINTF(Branch, "[tid:%i] RAS is empty, predicting "
353 "false.\n", tid);
354 pred_taken = false;
355 }
356 } else {
357 ++condPredicted;
358
291
292 if (inst->isReturn() && RAS[tid].empty()) {
293 DPRINTF(Branch, "[tid:%i] RAS is empty, predicting "
294 "false.\n", tid);
295 pred_taken = false;
296 }
297 } else {
298 ++condPredicted;
299
359 pred_taken = lookup(tid, predPC.instAddr(), bp_history);
300 pred_taken = lookup(predPC.instAddr(), bp_history);
360 }
361
362 PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken,
363 bp_history, tid);
364
365 // Now lookup in the BTB or RAS.
366 if (pred_taken) {
367 if (inst->isReturn()) {

--- 73 unchanged lines hidden (view full) ---

441}
442
443void
444BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
445{
446 DPRINTF(Branch, "[tid:%i]: Committing branches until "
447 "[sn:%lli].\n", tid, done_sn);
448
301 }
302
303 PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken,
304 bp_history, tid);
305
306 // Now lookup in the BTB or RAS.
307 if (pred_taken) {
308 if (inst->isReturn()) {

--- 73 unchanged lines hidden (view full) ---

382}
383
384void
385BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
386{
387 DPRINTF(Branch, "[tid:%i]: Committing branches until "
388 "[sn:%lli].\n", tid, done_sn);
389
449 iPred.commit(done_sn, tid);
450 while (!predHist[tid].empty() &&
451 predHist[tid].back().seqNum <= done_sn) {
452 // Update the branch predictor with the correct results.
453 if (!predHist[tid].back().wasSquashed) {
390 while (!predHist[tid].empty() &&
391 predHist[tid].back().seqNum <= done_sn) {
392 // Update the branch predictor with the correct results.
393 if (!predHist[tid].back().wasSquashed) {
454 update(tid, predHist[tid].back().pc,
455 predHist[tid].back().predTaken,
456 predHist[tid].back().bpHistory, false);
394 update(predHist[tid].back().pc, predHist[tid].back().predTaken,
395 predHist[tid].back().bpHistory, false);
457 } else {
396 } else {
458 retireSquashed(tid, predHist[tid].back().bpHistory);
397 retireSquashed(predHist[tid].back().bpHistory);
459 }
460
461 predHist[tid].pop_back();
462 }
463}
464
465void
466BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
467{
468 History &pred_hist = predHist[tid];
469
398 }
399
400 predHist[tid].pop_back();
401 }
402}
403
404void
405BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
406{
407 History &pred_hist = predHist[tid];
408
470 iPred.squash(squashed_sn, tid);
471 while (!pred_hist.empty() &&
472 pred_hist.front().seqNum > squashed_sn) {
473 if (pred_hist.front().usedRAS) {
474 DPRINTF(Branch, "[tid:%i]: Restoring top of RAS to: %i,"
475 " target: %s.\n", tid,
476 pred_hist.front().RASIndex, pred_hist.front().RASTarget);
477
478 RAS[tid].restore(pred_hist.front().RASIndex,
479 pred_hist.front().RASTarget);
480 } else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
481 // Was a call but predicated false. Pop RAS here
482 DPRINTF(Branch, "[tid: %i] Squashing"
483 " Call [sn:%i] PC: %s Popping RAS\n", tid,
484 pred_hist.front().seqNum, pred_hist.front().pc);
485 RAS[tid].pop();
486 }
487
488 // This call should delete the bpHistory.
409 while (!pred_hist.empty() &&
410 pred_hist.front().seqNum > squashed_sn) {
411 if (pred_hist.front().usedRAS) {
412 DPRINTF(Branch, "[tid:%i]: Restoring top of RAS to: %i,"
413 " target: %s.\n", tid,
414 pred_hist.front().RASIndex, pred_hist.front().RASTarget);
415
416 RAS[tid].restore(pred_hist.front().RASIndex,
417 pred_hist.front().RASTarget);
418 } else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
419 // Was a call but predicated false. Pop RAS here
420 DPRINTF(Branch, "[tid: %i] Squashing"
421 " Call [sn:%i] PC: %s Popping RAS\n", tid,
422 pred_hist.front().seqNum, pred_hist.front().pc);
423 RAS[tid].pop();
424 }
425
426 // This call should delete the bpHistory.
489 squash(tid, pred_hist.front().bpHistory);
427 squash(pred_hist.front().bpHistory);
490
491 DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] "
492 "PC %s.\n", tid, pred_hist.front().seqNum,
493 pred_hist.front().pc);
494
495 pred_hist.pop_front();
496
497 DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n",

--- 43 unchanged lines hidden (view full) ---

541 pred_hist.front().seqNum, squashed_sn);
542
543 assert(pred_hist.front().seqNum == squashed_sn);
544 }
545
546
547 if ((*hist_it).usedRAS) {
548 ++RASIncorrect;
428
429 DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] "
430 "PC %s.\n", tid, pred_hist.front().seqNum,
431 pred_hist.front().pc);
432
433 pred_hist.pop_front();
434
435 DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n",

--- 43 unchanged lines hidden (view full) ---

479 pred_hist.front().seqNum, squashed_sn);
480
481 assert(pred_hist.front().seqNum == squashed_sn);
482 }
483
484
485 if ((*hist_it).usedRAS) {
486 ++RASIncorrect;
549 DPRINTF(Branch, "[tid:%i]: Incorrect RAS [sn:%i]\n",
550 tid, hist_it->seqNum);
551 }
552
487 }
488
553 // Have to get GHR here because the update deletes bpHistory
554 unsigned ghr = getGHR(tid, hist_it->bpHistory);
555
556 update(tid, (*hist_it).pc, actually_taken,
489 update((*hist_it).pc, actually_taken,
557 pred_hist.front().bpHistory, true);
558 hist_it->wasSquashed = true;
559
560 if (actually_taken) {
561 if (hist_it->wasReturn && !hist_it->usedRAS) {
562 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
563 " return [sn:%i] PC: %s\n", tid, hist_it->seqNum,
564 hist_it->pc);
565 RAS[tid].pop();
566 hist_it->usedRAS = true;
567 }
490 pred_hist.front().bpHistory, true);
491 hist_it->wasSquashed = true;
492
493 if (actually_taken) {
494 if (hist_it->wasReturn && !hist_it->usedRAS) {
495 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
496 " return [sn:%i] PC: %s\n", tid, hist_it->seqNum,
497 hist_it->pc);
498 RAS[tid].pop();
499 hist_it->usedRAS = true;
500 }
568 if (hist_it->wasIndirect) {
569 ++indirectMispredicted;
570 iPred.recordTarget(hist_it->seqNum, ghr, corrTarget, tid);
571 } else {
572 DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]"
573 " PC: %s\n", tid,hist_it->seqNum, hist_it->pc);
574
501
575 BTB.update((*hist_it).pc, corrTarget, tid);
576 }
502 DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]"
503 " PC: %s\n", tid,hist_it->seqNum, hist_it->pc);
504
505 BTB.update((*hist_it).pc, corrTarget, tid);
506
577 } else {
578 //Actually not Taken
579 if (hist_it->usedRAS) {
580 DPRINTF(Branch,"[tid: %i] Incorrectly predicted"
581 " return [sn:%i] PC: %s Restoring RAS\n", tid,
582 hist_it->seqNum, hist_it->pc);
583 DPRINTF(Branch, "[tid:%i]: Restoring top of RAS"
584 " to: %i, target: %s.\n", tid,

--- 42 unchanged lines hidden ---
507 } else {
508 //Actually not Taken
509 if (hist_it->usedRAS) {
510 DPRINTF(Branch,"[tid: %i] Incorrectly predicted"
511 " return [sn:%i] PC: %s Restoring RAS\n", tid,
512 hist_it->seqNum, hist_it->pc);
513 DPRINTF(Branch, "[tid:%i]: Restoring top of RAS"
514 " to: %i, target: %s.\n", tid,

--- 42 unchanged lines hidden ---