bpred_unit.cc revision 11434
16167SN/A/* 26167SN/A * Copyright (c) 2011-2012, 2014 ARM Limited 36167SN/A * Copyright (c) 2010 The University of Edinburgh 48835SAli.Saidi@ARM.com * Copyright (c) 2012 Mark D. Hill and David A. Wood 57935SN/A * All rights reserved 67935SN/A * 77935SN/A * The license below extends only to copyright in the software and shall 86167SN/A * not be construed as granting a license to any other intellectual 96167SN/A * property including but not limited to intellectual property relating 106167SN/A * to a hardware implementation of the functionality of the software 119469Snilay@cs.wisc.edu * licensed hereunder. You may use the software subject to the license 128835SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 139207Snilay@cs.wisc.edu * unmodified and in its entirety in all distributions of the software, 148835SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 158835SAli.Saidi@ARM.com * 168835SAli.Saidi@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 177935SN/A * All rights reserved. 189469Snilay@cs.wisc.edu * 198540SN/A * Redistribution and use in source and binary forms, with or without 208721SN/A * modification, are permitted provided that the following conditions are 218835SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 228835SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 237935SN/A * redistributions in binary form must reproduce the above copyright 247935SN/A * notice, this list of conditions and the following disclaimer in the 257935SN/A * documentation and/or other materials provided with the distribution; 267935SN/A * neither the name of the copyright holders nor the names of its 277935SN/A * contributors may be used to endorse or promote products derived from 287935SN/A * this software without specific prior written permission. 297935SN/A * 308983Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 316167SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 326167SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 336167SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 349469Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 359481Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 366167SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 376928SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 386167SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 396167SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 408835SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 416167SN/A * 426167SN/A * Authors: Kevin Lim 436167SN/A */ 446167SN/A 458835SAli.Saidi@ARM.com#include "cpu/pred/bpred_unit.hh" 469469Snilay@cs.wisc.edu 476167SN/A#include <algorithm> 486167SN/A 496167SN/A#include "arch/isa_traits.hh" 506167SN/A#include "arch/types.hh" 516167SN/A#include "arch/utility.hh" 526167SN/A#include "base/trace.hh" 538835SAli.Saidi@ARM.com#include "config/the_isa.hh" 546167SN/A#include "debug/Branch.hh" 559469Snilay@cs.wisc.edu 566167SN/ABPredUnit::BPredUnit(const Params *params) 576167SN/A : SimObject(params), 586167SN/A numThreads(params->numThreads), 599469Snilay@cs.wisc.edu predHist(numThreads), 609469Snilay@cs.wisc.edu BTB(params->BTBEntries, 616167SN/A params->BTBTagSize, 626167SN/A params->instShiftAmt, 636167SN/A params->numThreads), 646167SN/A RAS(numThreads), 656167SN/A useIndirect(params->useIndirect), 668835SAli.Saidi@ARM.com iPred(params->indirectHashGHR, 678835SAli.Saidi@ARM.com params->indirectHashTargets, 688835SAli.Saidi@ARM.com params->indirectSets, 699469Snilay@cs.wisc.edu params->indirectWays, 709469Snilay@cs.wisc.edu params->indirectTagSize, 719469Snilay@cs.wisc.edu params->indirectPathLength, 729469Snilay@cs.wisc.edu params->instShiftAmt, 739469Snilay@cs.wisc.edu params->numThreads), 746167SN/A instShiftAmt(params->instShiftAmt) 756167SN/A{ 766167SN/A for (auto& r : RAS) 776167SN/A r.init(params->RASSize); 786167SN/A} 796167SN/A 806167SN/Avoid 816167SN/ABPredUnit::regStats() 826167SN/A{ 836167SN/A lookups 846167SN/A .name(name() + ".lookups") 856167SN/A .desc("Number of BP lookups") 866167SN/A ; 876167SN/A 886167SN/A condPredicted 899207Snilay@cs.wisc.edu .name(name() + ".condPredicted") 906167SN/A .desc("Number of conditional branches predicted") 916167SN/A ; 926167SN/A 936167SN/A condIncorrect 946167SN/A .name(name() + ".condIncorrect") 956167SN/A .desc("Number of conditional branches incorrect") 966167SN/A ; 976167SN/A 986167SN/A BTBLookups 996167SN/A .name(name() + ".BTBLookups") 1009469Snilay@cs.wisc.edu .desc("Number of BTB lookups") 1019469Snilay@cs.wisc.edu ; 1029469Snilay@cs.wisc.edu 1039469Snilay@cs.wisc.edu BTBHits 1049469Snilay@cs.wisc.edu .name(name() + ".BTBHits") 1059469Snilay@cs.wisc.edu .desc("Number of BTB hits") 1069469Snilay@cs.wisc.edu ; 1079469Snilay@cs.wisc.edu 1089578Snilay@cs.wisc.edu BTBCorrect 1099469Snilay@cs.wisc.edu .name(name() + ".BTBCorrect") 1109469Snilay@cs.wisc.edu .desc("Number of correct BTB predictions (this stat may not " 1119469Snilay@cs.wisc.edu "work properly.") 1129469Snilay@cs.wisc.edu ; 1139469Snilay@cs.wisc.edu 1149469Snilay@cs.wisc.edu BTBHitPct 1159469Snilay@cs.wisc.edu .name(name() + ".BTBHitPct") 1169469Snilay@cs.wisc.edu .desc("BTB Hit Percentage") 1179469Snilay@cs.wisc.edu .precision(6); 1189469Snilay@cs.wisc.edu BTBHitPct = (BTBHits / BTBLookups) * 100; 1199469Snilay@cs.wisc.edu 1209469Snilay@cs.wisc.edu usedRAS 1219469Snilay@cs.wisc.edu .name(name() + ".usedRAS") 1229469Snilay@cs.wisc.edu .desc("Number of times the RAS was used to get a target.") 1239469Snilay@cs.wisc.edu ; 1246928SN/A 1256928SN/A RASIncorrect 1266928SN/A .name(name() + ".RASInCorrect") 1279469Snilay@cs.wisc.edu .desc("Number of incorrect RAS predictions.") 1288540SN/A ; 1299469Snilay@cs.wisc.edu 1306928SN/A indirectLookups 1319469Snilay@cs.wisc.edu .name(name() + ".indirectLookups") 1326928SN/A .desc("Number of indirect predictor lookups.") 1336928SN/A ; 1348540SN/A 1356928SN/A indirectHits 1366928SN/A .name(name() + ".indirectHits") 1376928SN/A .desc("Number of indirect target hits.") 1389469Snilay@cs.wisc.edu ; 1396928SN/A 1407935SN/A indirectMisses 1419469Snilay@cs.wisc.edu .name(name() + ".indirectMisses") 1426928SN/A .desc("Number of indirect misses.") 1437935SN/A ; 1446928SN/A 1456928SN/A indirectMispredicted 1469469Snilay@cs.wisc.edu .name(name() + "indirectMispredicted") 1476928SN/A .desc("Number of mispredicted indirect branches.") 1486928SN/A ; 1496928SN/A 1506928SN/A} 1516928SN/A 1526928SN/AProbePoints::PMUUPtr 1539207Snilay@cs.wisc.eduBPredUnit::pmuProbePoint(const char *name) 1546928SN/A{ 1556928SN/A ProbePoints::PMUUPtr ptr; 1566928SN/A ptr.reset(new ProbePoints::PMU(getProbeManager(), name)); 1576928SN/A 1586928SN/A return ptr; 1596928SN/A} 1606928SN/A 1616928SN/Avoid 1626928SN/ABPredUnit::regProbePoints() 1636928SN/A{ 1649207Snilay@cs.wisc.edu ppBranches = pmuProbePoint("Branches"); 1656928SN/A ppMisses = pmuProbePoint("Misses"); 1666928SN/A} 1676928SN/A 1689469Snilay@cs.wisc.eduvoid 1697935SN/ABPredUnit::drainSanityCheck() const 1708540SN/A{ 1717935SN/A // We shouldn't have any outstanding requests when we resume from 1729469Snilay@cs.wisc.edu // a drained system. 1737935SN/A for (const auto& ph M5_VAR_USED : predHist) 1749469Snilay@cs.wisc.edu assert(ph.empty()); 1758540SN/A} 1767935SN/A 1777935SN/Abool 1787935SN/ABPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, 1798540SN/A TheISA::PCState &pc, ThreadID tid) 1808835SAli.Saidi@ARM.com{ 1819469Snilay@cs.wisc.edu // See if branch predictor predicts taken. 1827935SN/A // If so, get its target addr either from the BTB or the RAS. 1837935SN/A // Save off record of branch stuff so the RAS can be fixed 1847935SN/A // up once it's done. 1859469Snilay@cs.wisc.edu 1868540SN/A bool pred_taken = false; 1878540SN/A TheISA::PCState target = pc; 1889113SBrad.Beckmann@amd.com 1899113SBrad.Beckmann@amd.com ++lookups; 1908721SN/A ppBranches->notify(1); 1918540SN/A 1928540SN/A void *bp_history = NULL; 1939113SBrad.Beckmann@amd.com 1948540SN/A if (inst->isUncondCtrl()) { 1958540SN/A DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid); 1969113SBrad.Beckmann@amd.com pred_taken = true; 1979113SBrad.Beckmann@amd.com // Tell the BP there was an unconditional branch. 1988540SN/A uncondBranch(tid, pc.instAddr(), bp_history); 1999469Snilay@cs.wisc.edu } else { 2008540SN/A ++condPredicted; 2019578Snilay@cs.wisc.edu pred_taken = lookup(tid, pc.instAddr(), bp_history); 2029207Snilay@cs.wisc.edu 2039469Snilay@cs.wisc.edu DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor" 2048540SN/A " predicted %i for PC %s\n", tid, seqNum, pred_taken, pc); 2059469Snilay@cs.wisc.edu } 2068540SN/A 2078540SN/A DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history " 2088983Snate@binkert.org "for PC %s\n", tid, seqNum, pc); 2098983Snate@binkert.org 2108983Snate@binkert.org PredictorHistory predict_record(seqNum, pc.instAddr(), 2118540SN/A pred_taken, bp_history, tid); 2128540SN/A 2138540SN/A // Now lookup in the BTB or RAS. 2148983Snate@binkert.org if (pred_taken) { 2158540SN/A if (inst->isReturn()) { 2167935SN/A ++usedRAS; 2177935SN/A predict_record.wasReturn = true; 2187935SN/A // If it's a function return call, then look up the address 2197935SN/A // in the RAS. 2207935SN/A TheISA::PCState rasTop = RAS[tid].top(); 2219469Snilay@cs.wisc.edu target = TheISA::buildRetPC(pc, rasTop); 2227935SN/A 2238540SN/A // Record the top entry of the RAS, and its index. 2247935SN/A predict_record.usedRAS = true; 2258540SN/A predict_record.RASIndex = RAS[tid].topIdx(); 2267935SN/A predict_record.RASTarget = rasTop; 2277935SN/A 2287935SN/A RAS[tid].pop(); 2297935SN/A 2309113SBrad.Beckmann@amd.com DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, " 2317935SN/A "RAS predicted target: %s, RAS index: %i.\n", 2327935SN/A tid, pc, target, predict_record.RASIndex); 2337935SN/A } else { 2347935SN/A ++BTBLookups; 2359113SBrad.Beckmann@amd.com 2367935SN/A if (inst->isCall()) { 2377935SN/A RAS[tid].push(pc); 2388540SN/A predict_record.pushedRAS = true; 2399113SBrad.Beckmann@amd.com 2408540SN/A // Record that it was a call so that the top RAS entry can 2419469Snilay@cs.wisc.edu // be popped off if the speculation is incorrect. 2429113SBrad.Beckmann@amd.com predict_record.wasCall = true; 2437935SN/A 2448540SN/A DPRINTF(Branch, "[tid:%i]: Instruction %s was a " 2457935SN/A "call, adding %s to the RAS index: %i.\n", 2467935SN/A tid, pc, pc, RAS[tid].topIdx()); 2479113SBrad.Beckmann@amd.com } 2489276Snilay@cs.wisc.edu 2499469Snilay@cs.wisc.edu if (inst->isDirectCtrl() || !useIndirect) { 2509113SBrad.Beckmann@amd.com // Check BTB on direct branches 2519276Snilay@cs.wisc.edu if (BTB.valid(pc.instAddr(), tid)) { 2529113SBrad.Beckmann@amd.com ++BTBHits; 2537935SN/A 2548540SN/A // If it's not a return, use the BTB to get target addr. 2559113SBrad.Beckmann@amd.com target = BTB.lookup(pc.instAddr(), tid); 2568540SN/A 2579469Snilay@cs.wisc.edu DPRINTF(Branch, "[tid:%i]: Instruction %s predicted" 2589113SBrad.Beckmann@amd.com " target is %s.\n", tid, pc, target); 2597935SN/A 2608540SN/A } else { 2617935SN/A DPRINTF(Branch, "[tid:%i]: BTB doesn't have a " 2627935SN/A "valid entry.\n",tid); 2639113SBrad.Beckmann@amd.com pred_taken = false; 2649276Snilay@cs.wisc.edu // The Direction of the branch predictor is altered 2659469Snilay@cs.wisc.edu // because the BTB did not have an entry 2669113SBrad.Beckmann@amd.com // The predictor needs to be updated accordingly 2679276Snilay@cs.wisc.edu if (!inst->isCall() && !inst->isReturn()) { 2689113SBrad.Beckmann@amd.com btbUpdate(tid, pc.instAddr(), bp_history); 2696928SN/A DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate" 2708540SN/A " called for %s\n", tid, seqNum, pc); 2719113SBrad.Beckmann@amd.com } else if (inst->isCall() && !inst->isUncondCtrl()) { 2728540SN/A RAS[tid].pop(); 2736928SN/A predict_record.pushedRAS = false; 2748540SN/A } 2759113SBrad.Beckmann@amd.com TheISA::advancePC(target, inst); 2769113SBrad.Beckmann@amd.com } 2776928SN/A } else { 2786928SN/A predict_record.wasIndirect = true; 2799113SBrad.Beckmann@amd.com ++indirectLookups; 2809276Snilay@cs.wisc.edu //Consult indirect predictor on indirect control 2819469Snilay@cs.wisc.edu if (iPred.lookup(pc.instAddr(), getGHR(tid, bp_history), 2829113SBrad.Beckmann@amd.com target, tid)) { 2839276Snilay@cs.wisc.edu // Indirect predictor hit 2849113SBrad.Beckmann@amd.com ++indirectHits; 2856928SN/A DPRINTF(Branch, "[tid:%i]: Instruction %s predicted " 2868540SN/A "indirect target is %s.\n", tid, pc, target); 2878540SN/A } else { 2886928SN/A ++indirectMisses; 2898540SN/A pred_taken = false; 2909113SBrad.Beckmann@amd.com DPRINTF(Branch, "[tid:%i]: Instruction %s no indirect " 2919113SBrad.Beckmann@amd.com "target.\n", tid, pc); 2926928SN/A if (!inst->isCall() && !inst->isReturn()) { 2936928SN/A 2946928SN/A } else if (inst->isCall() && !inst->isUncondCtrl()) { 2956928SN/A RAS[tid].pop(); 2966928SN/A predict_record.pushedRAS = false; 2976928SN/A } 2986928SN/A TheISA::advancePC(target, inst); 2998540SN/A } 3006928SN/A iPred.recordIndirect(pc.instAddr(), target.instAddr(), seqNum, 3018721SN/A tid); 3028721SN/A } 3038721SN/A } 3049207Snilay@cs.wisc.edu } else { 3058540SN/A if (inst->isReturn()) { 3068983Snate@binkert.org predict_record.wasReturn = true; 3078983Snate@binkert.org } 3088983Snate@binkert.org TheISA::advancePC(target, inst); 3098721SN/A } 3108721SN/A 3118721SN/A pc = target; 3128983Snate@binkert.org 3136928SN/A predHist[tid].push_front(predict_record); 314 315 DPRINTF(Branch, "[tid:%i]: [sn:%i]: History entry added." 316 "predHist.size(): %i\n", tid, seqNum, predHist[tid].size()); 317 318 return pred_taken; 319} 320 321bool 322BPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum, 323 int asid, TheISA::PCState &instPC, 324 TheISA::PCState &predPC, ThreadID tid) 325{ 326 // See if branch predictor predicts taken. 327 // If so, get its target addr either from the BTB or the RAS. 328 // Save off record of branch stuff so the RAS can be fixed 329 // up once it's done. 330 331 using TheISA::MachInst; 332 333 bool pred_taken = false; 334 TheISA::PCState target; 335 336 ++lookups; 337 ppBranches->notify(1); 338 339 DPRINTF(Branch, "[tid:%i] [sn:%i] %s ... PC %s doing branch " 340 "prediction\n", tid, seqNum, 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. 349 uncondBranch(tid, 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 359 pred_taken = lookup(tid, 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()) { 368 ++usedRAS; 369 370 // If it's a function return call, then look up the address 371 // in the RAS. 372 TheISA::PCState rasTop = RAS[tid].top(); 373 target = TheISA::buildRetPC(instPC, rasTop); 374 375 // Record the top entry of the RAS, and its index. 376 predict_record.usedRAS = true; 377 predict_record.RASIndex = RAS[tid].topIdx(); 378 predict_record.RASTarget = rasTop; 379 380 assert(predict_record.RASIndex < 16); 381 382 RAS[tid].pop(); 383 384 DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, " 385 "RAS predicted target: %s, RAS index: %i.\n", 386 tid, instPC, target, 387 predict_record.RASIndex); 388 } else { 389 ++BTBLookups; 390 391 if (inst->isCall()) { 392 393 RAS[tid].push(instPC); 394 predict_record.pushedRAS = true; 395 396 // Record that it was a call so that the top RAS entry can 397 // be popped off if the speculation is incorrect. 398 predict_record.wasCall = true; 399 400 DPRINTF(Branch, "[tid:%i]: Instruction %s was a call" 401 ", adding %s to the RAS index: %i.\n", 402 tid, instPC, predPC, 403 RAS[tid].topIdx()); 404 } 405 406 if (inst->isCall() && 407 inst->isUncondCtrl() && 408 inst->isDirectCtrl()) { 409 target = inst->branchTarget(instPC); 410 } else if (BTB.valid(predPC.instAddr(), asid)) { 411 ++BTBHits; 412 413 // If it's not a return, use the BTB to get the target addr. 414 target = BTB.lookup(predPC.instAddr(), asid); 415 416 DPRINTF(Branch, "[tid:%i]: [asid:%i] Instruction %s " 417 "predicted target is %s.\n", 418 tid, asid, instPC, target); 419 } else { 420 DPRINTF(Branch, "[tid:%i]: BTB doesn't have a " 421 "valid entry, predicting false.\n",tid); 422 pred_taken = false; 423 } 424 } 425 } 426 427 if (pred_taken) { 428 // Set the PC and the instruction's predicted target. 429 predPC = target; 430 } 431 DPRINTF(Branch, "[tid:%i]: [sn:%i]: Setting Predicted PC to %s.\n", 432 tid, seqNum, predPC); 433 434 predHist[tid].push_front(predict_record); 435 436 DPRINTF(Branch, "[tid:%i] [sn:%i] pushed onto front of predHist " 437 "...predHist.size(): %i\n", 438 tid, seqNum, predHist[tid].size()); 439 440 return pred_taken; 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 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) { 454 update(tid, predHist[tid].back().pc, 455 predHist[tid].back().predTaken, 456 predHist[tid].back().bpHistory, false); 457 } else { 458 retireSquashed(tid, 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 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. 489 squash(tid, 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", 498 tid, predHist[tid].size()); 499 } 500} 501 502void 503BPredUnit::squash(const InstSeqNum &squashed_sn, 504 const TheISA::PCState &corrTarget, 505 bool actually_taken, ThreadID tid) 506{ 507 // Now that we know that a branch was mispredicted, we need to undo 508 // all the branches that have been seen up until this branch and 509 // fix up everything. 510 // NOTE: This should be call conceivably in 2 scenarios: 511 // (1) After an branch is executed, it updates its status in the ROB 512 // The commit stage then checks the ROB update and sends a signal to 513 // the fetch stage to squash history after the mispredict 514 // (2) In the decode stage, you can find out early if a unconditional 515 // PC-relative, branch was predicted incorrectly. If so, a signal 516 // to the fetch stage is sent to squash history after the mispredict 517 518 History &pred_hist = predHist[tid]; 519 520 ++condIncorrect; 521 ppMisses->notify(1); 522 523 DPRINTF(Branch, "[tid:%i]: Squashing from sequence number %i, " 524 "setting target to %s.\n", tid, squashed_sn, corrTarget); 525 526 // Squash All Branches AFTER this mispredicted branch 527 squash(squashed_sn, tid); 528 529 // If there's a squash due to a syscall, there may not be an entry 530 // corresponding to the squash. In that case, don't bother trying to 531 // fix up the entry. 532 if (!pred_hist.empty()) { 533 534 auto hist_it = pred_hist.begin(); 535 //HistoryIt hist_it = find(pred_hist.begin(), pred_hist.end(), 536 // squashed_sn); 537 538 //assert(hist_it != pred_hist.end()); 539 if (pred_hist.front().seqNum != squashed_sn) { 540 DPRINTF(Branch, "Front sn %i != Squash sn %i\n", 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; 549 DPRINTF(Branch, "[tid:%i]: Incorrect RAS [sn:%i]\n", 550 tid, hist_it->seqNum); 551 } 552 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, 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 } 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 575 BTB.update((*hist_it).pc, corrTarget, tid); 576 } 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, 585 hist_it->RASIndex, hist_it->RASTarget); 586 RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget); 587 hist_it->usedRAS = false; 588 } else if (hist_it->wasCall && hist_it->pushedRAS) { 589 //Was a Call but predicated false. Pop RAS here 590 DPRINTF(Branch, "[tid: %i] Incorrectly predicted" 591 " Call [sn:%i] PC: %s Popping RAS\n", tid, 592 hist_it->seqNum, hist_it->pc); 593 RAS[tid].pop(); 594 hist_it->pushedRAS = false; 595 } 596 } 597 } else { 598 DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't " 599 "update.\n", tid, squashed_sn); 600 } 601} 602 603void 604BPredUnit::dump() 605{ 606 int i = 0; 607 for (const auto& ph : predHist) { 608 if (!ph.empty()) { 609 auto pred_hist_it = ph.begin(); 610 611 cprintf("predHist[%i].size(): %i\n", i++, ph.size()); 612 613 while (pred_hist_it != ph.end()) { 614 cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, " 615 "bpHistory:%#x\n", 616 pred_hist_it->seqNum, pred_hist_it->pc, 617 pred_hist_it->tid, pred_hist_it->predTaken, 618 pred_hist_it->bpHistory); 619 pred_hist_it++; 620 } 621 622 cprintf("\n"); 623 } 624 } 625} 626 627