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 --- |