bpred_unit.cc revision 11523
14776Sgblack@eecs.umich.edu/* 213610Sgiacomo.gabrielli@arm.com * Copyright (c) 2011-2012, 2014 ARM Limited 310665SAli.Saidi@ARM.com * Copyright (c) 2010 The University of Edinburgh 410665SAli.Saidi@ARM.com * Copyright (c) 2012 Mark D. Hill and David A. Wood 510665SAli.Saidi@ARM.com * All rights reserved 610665SAli.Saidi@ARM.com * 710665SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 810665SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 910665SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 1010665SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 1110665SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 1210665SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 1310665SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 144776Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 154776Sgblack@eecs.umich.edu * 164776Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 174776Sgblack@eecs.umich.edu * All rights reserved. 184776Sgblack@eecs.umich.edu * 194776Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 204776Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 214776Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 224776Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 234776Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 244776Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 254776Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 264776Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 274776Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 284776Sgblack@eecs.umich.edu * this software without specific prior written permission. 294776Sgblack@eecs.umich.edu * 304776Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 314776Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 324776Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 334776Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 344776Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 354776Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 364776Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 374776Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 384776Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 394776Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 404776Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 414776Sgblack@eecs.umich.edu * 424776Sgblack@eecs.umich.edu * Authors: Kevin Lim 434776Sgblack@eecs.umich.edu */ 444776Sgblack@eecs.umich.edu 454776Sgblack@eecs.umich.edu#include "cpu/pred/bpred_unit.hh" 464776Sgblack@eecs.umich.edu 4713610Sgiacomo.gabrielli@arm.com#include <algorithm> 4813610Sgiacomo.gabrielli@arm.com 496216Snate@binkert.org#include "arch/isa_traits.hh" 5011800Sbrandon.potter@amd.com#include "arch/types.hh" 514776Sgblack@eecs.umich.edu#include "arch/utility.hh" 524776Sgblack@eecs.umich.edu#include "base/trace.hh" 534776Sgblack@eecs.umich.edu#include "config/the_isa.hh" 544776Sgblack@eecs.umich.edu#include "debug/Branch.hh" 554776Sgblack@eecs.umich.edu 564776Sgblack@eecs.umich.eduBPredUnit::BPredUnit(const Params *params) 574776Sgblack@eecs.umich.edu : SimObject(params), 584776Sgblack@eecs.umich.edu numThreads(params->numThreads), 594776Sgblack@eecs.umich.edu predHist(numThreads), 604776Sgblack@eecs.umich.edu BTB(params->BTBEntries, 614776Sgblack@eecs.umich.edu params->BTBTagSize, 624776Sgblack@eecs.umich.edu params->instShiftAmt, 634776Sgblack@eecs.umich.edu params->numThreads), 644776Sgblack@eecs.umich.edu RAS(numThreads), 654776Sgblack@eecs.umich.edu useIndirect(params->useIndirect), 664776Sgblack@eecs.umich.edu iPred(params->indirectHashGHR, 674776Sgblack@eecs.umich.edu params->indirectHashTargets, 684776Sgblack@eecs.umich.edu params->indirectSets, 697720Sgblack@eecs.umich.edu params->indirectWays, 705784Sgblack@eecs.umich.edu params->indirectTagSize, 714776Sgblack@eecs.umich.edu params->indirectPathLength, 724776Sgblack@eecs.umich.edu params->instShiftAmt, 734776Sgblack@eecs.umich.edu params->numThreads), 744776Sgblack@eecs.umich.edu instShiftAmt(params->instShiftAmt) 754776Sgblack@eecs.umich.edu{ 764776Sgblack@eecs.umich.edu for (auto& r : RAS) 774776Sgblack@eecs.umich.edu r.init(params->RASSize); 7810665SAli.Saidi@ARM.com} 7910665SAli.Saidi@ARM.com 8010665SAli.Saidi@ARM.comvoid 8110665SAli.Saidi@ARM.comBPredUnit::regStats() 8210665SAli.Saidi@ARM.com{ 8310665SAli.Saidi@ARM.com SimObject::regStats(); 8410665SAli.Saidi@ARM.com 8510665SAli.Saidi@ARM.com lookups 8610665SAli.Saidi@ARM.com .name(name() + ".lookups") 8710665SAli.Saidi@ARM.com .desc("Number of BP lookups") 8810665SAli.Saidi@ARM.com ; 8910665SAli.Saidi@ARM.com 9010665SAli.Saidi@ARM.com condPredicted 9110665SAli.Saidi@ARM.com .name(name() + ".condPredicted") 9210665SAli.Saidi@ARM.com .desc("Number of conditional branches predicted") 9310665SAli.Saidi@ARM.com ; 9410665SAli.Saidi@ARM.com 9510665SAli.Saidi@ARM.com condIncorrect 9610665SAli.Saidi@ARM.com .name(name() + ".condIncorrect") 974776Sgblack@eecs.umich.edu .desc("Number of conditional branches incorrect") 984776Sgblack@eecs.umich.edu ; 994776Sgblack@eecs.umich.edu 10013610Sgiacomo.gabrielli@arm.com BTBLookups 10113610Sgiacomo.gabrielli@arm.com .name(name() + ".BTBLookups") 10213610Sgiacomo.gabrielli@arm.com .desc("Number of BTB lookups") 1034776Sgblack@eecs.umich.edu ; 10410665SAli.Saidi@ARM.com 10510665SAli.Saidi@ARM.com BTBHits 10610665SAli.Saidi@ARM.com .name(name() + ".BTBHits") 10710665SAli.Saidi@ARM.com .desc("Number of BTB hits") 10810665SAli.Saidi@ARM.com ; 10910665SAli.Saidi@ARM.com 11010665SAli.Saidi@ARM.com BTBCorrect 11110665SAli.Saidi@ARM.com .name(name() + ".BTBCorrect") 11210665SAli.Saidi@ARM.com .desc("Number of correct BTB predictions (this stat may not " 11310665SAli.Saidi@ARM.com "work properly.") 11410665SAli.Saidi@ARM.com ; 11510665SAli.Saidi@ARM.com 11610665SAli.Saidi@ARM.com BTBHitPct 11710665SAli.Saidi@ARM.com .name(name() + ".BTBHitPct") 11810665SAli.Saidi@ARM.com .desc("BTB Hit Percentage") 11910665SAli.Saidi@ARM.com .precision(6); 12012386Sgabeblack@google.com BTBHitPct = (BTBHits / BTBLookups) * 100; 1214776Sgblack@eecs.umich.edu 1225543Ssaidi@eecs.umich.edu usedRAS 1234776Sgblack@eecs.umich.edu .name(name() + ".usedRAS") 1244776Sgblack@eecs.umich.edu .desc("Number of times the RAS was used to get a target.") 1254776Sgblack@eecs.umich.edu ; 12613610Sgiacomo.gabrielli@arm.com 12713610Sgiacomo.gabrielli@arm.com RASIncorrect 12813610Sgiacomo.gabrielli@arm.com .name(name() + ".RASInCorrect") 1294776Sgblack@eecs.umich.edu .desc("Number of incorrect RAS predictions.") 1304776Sgblack@eecs.umich.edu ; 13110665SAli.Saidi@ARM.com 13210665SAli.Saidi@ARM.com indirectLookups 13310665SAli.Saidi@ARM.com .name(name() + ".indirectLookups") 13410665SAli.Saidi@ARM.com .desc("Number of indirect predictor lookups.") 13510665SAli.Saidi@ARM.com ; 13610665SAli.Saidi@ARM.com 13710665SAli.Saidi@ARM.com indirectHits 13810665SAli.Saidi@ARM.com .name(name() + ".indirectHits") 1394776Sgblack@eecs.umich.edu .desc("Number of indirect target hits.") 14010665SAli.Saidi@ARM.com ; 14110665SAli.Saidi@ARM.com 14210665SAli.Saidi@ARM.com indirectMisses 14310665SAli.Saidi@ARM.com .name(name() + ".indirectMisses") 1444776Sgblack@eecs.umich.edu .desc("Number of indirect misses.") 14510665SAli.Saidi@ARM.com ; 14610665SAli.Saidi@ARM.com 14710665SAli.Saidi@ARM.com indirectMispredicted 1484776Sgblack@eecs.umich.edu .name(name() + "indirectMispredicted") 1494776Sgblack@eecs.umich.edu .desc("Number of mispredicted indirect branches.") 1504776Sgblack@eecs.umich.edu ; 1515784Sgblack@eecs.umich.edu 15210664SAli.Saidi@ARM.com} 1537720Sgblack@eecs.umich.edu 15410665SAli.Saidi@ARM.comProbePoints::PMUUPtr 15510665SAli.Saidi@ARM.comBPredUnit::pmuProbePoint(const char *name) 15610665SAli.Saidi@ARM.com{ 15710665SAli.Saidi@ARM.com ProbePoints::PMUUPtr ptr; 15810665SAli.Saidi@ARM.com ptr.reset(new ProbePoints::PMU(getProbeManager(), name)); 1594776Sgblack@eecs.umich.edu 16013610Sgiacomo.gabrielli@arm.com return ptr; 16113610Sgiacomo.gabrielli@arm.com} 16213610Sgiacomo.gabrielli@arm.com 16313610Sgiacomo.gabrielli@arm.comvoid 16413610Sgiacomo.gabrielli@arm.comBPredUnit::regProbePoints() 16513610Sgiacomo.gabrielli@arm.com{ 16613610Sgiacomo.gabrielli@arm.com ppBranches = pmuProbePoint("Branches"); 16713610Sgiacomo.gabrielli@arm.com ppMisses = pmuProbePoint("Misses"); 16813610Sgiacomo.gabrielli@arm.com} 16913610Sgiacomo.gabrielli@arm.com 1704776Sgblack@eecs.umich.eduvoid 17110198SAndrew.Bardsley@arm.comBPredUnit::drainSanityCheck() const 17210665SAli.Saidi@ARM.com{ 17310665SAli.Saidi@ARM.com // We shouldn't have any outstanding requests when we resume from 17410665SAli.Saidi@ARM.com // a drained system. 17510665SAli.Saidi@ARM.com for (const auto& ph M5_VAR_USED : predHist) 1764776Sgblack@eecs.umich.edu assert(ph.empty()); 17712386Sgabeblack@google.com} 17812386Sgabeblack@google.com 17912386Sgabeblack@google.combool 18012386Sgabeblack@google.comBPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, 18112386Sgabeblack@google.com TheISA::PCState &pc, ThreadID tid) 18212386Sgabeblack@google.com{ 18312386Sgabeblack@google.com // See if branch predictor predicts taken. 18412386Sgabeblack@google.com // If so, get its target addr either from the BTB or the RAS. 18512386Sgabeblack@google.com // Save off record of branch stuff so the RAS can be fixed 18612386Sgabeblack@google.com // up once it's done. 18712386Sgabeblack@google.com 1884776Sgblack@eecs.umich.edu bool pred_taken = false; 1894776Sgblack@eecs.umich.edu TheISA::PCState target = pc; 1904776Sgblack@eecs.umich.edu 1914776Sgblack@eecs.umich.edu ++lookups; 1924776Sgblack@eecs.umich.edu ppBranches->notify(1); 1934776Sgblack@eecs.umich.edu 1944776Sgblack@eecs.umich.edu void *bp_history = NULL; 1954776Sgblack@eecs.umich.edu 1964776Sgblack@eecs.umich.edu if (inst->isUncondCtrl()) { 1974776Sgblack@eecs.umich.edu DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid); 1984776Sgblack@eecs.umich.edu pred_taken = true; 1994776Sgblack@eecs.umich.edu // Tell the BP there was an unconditional branch. 20013610Sgiacomo.gabrielli@arm.com uncondBranch(tid, pc.instAddr(), bp_history); 20113610Sgiacomo.gabrielli@arm.com } else { 20213610Sgiacomo.gabrielli@arm.com ++condPredicted; 20313610Sgiacomo.gabrielli@arm.com pred_taken = lookup(tid, pc.instAddr(), bp_history); 20413610Sgiacomo.gabrielli@arm.com 20513610Sgiacomo.gabrielli@arm.com DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor" 20613610Sgiacomo.gabrielli@arm.com " predicted %i for PC %s\n", tid, seqNum, pred_taken, pc); 20713610Sgiacomo.gabrielli@arm.com } 20813610Sgiacomo.gabrielli@arm.com 20913610Sgiacomo.gabrielli@arm.com DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history " 21013610Sgiacomo.gabrielli@arm.com "for PC %s\n", tid, seqNum, pc); 21113610Sgiacomo.gabrielli@arm.com 21213610Sgiacomo.gabrielli@arm.com PredictorHistory predict_record(seqNum, pc.instAddr(), 21313610Sgiacomo.gabrielli@arm.com pred_taken, bp_history, tid); 21413610Sgiacomo.gabrielli@arm.com 21513610Sgiacomo.gabrielli@arm.com // Now lookup in the BTB or RAS. 2164776Sgblack@eecs.umich.edu if (pred_taken) { 2174776Sgblack@eecs.umich.edu if (inst->isReturn()) { 2184776Sgblack@eecs.umich.edu ++usedRAS; 2194776Sgblack@eecs.umich.edu predict_record.wasReturn = true; 2204776Sgblack@eecs.umich.edu // If it's a function return call, then look up the address 2214776Sgblack@eecs.umich.edu // in the RAS. 2227600Sminkyu.jeong@arm.com TheISA::PCState rasTop = RAS[tid].top(); 2237600Sminkyu.jeong@arm.com target = TheISA::buildRetPC(pc, rasTop); 2244776Sgblack@eecs.umich.edu 22511320Ssteve.reinhardt@amd.com // Record the top entry of the RAS, and its index. 2266364Sgblack@eecs.umich.edu predict_record.usedRAS = true; 22710665SAli.Saidi@ARM.com predict_record.RASIndex = RAS[tid].topIdx(); 22810665SAli.Saidi@ARM.com predict_record.RASTarget = rasTop; 22910665SAli.Saidi@ARM.com 23010665SAli.Saidi@ARM.com RAS[tid].pop(); 23110665SAli.Saidi@ARM.com 2326364Sgblack@eecs.umich.edu DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, " 23310665SAli.Saidi@ARM.com "RAS predicted target: %s, RAS index: %i.\n", 23410665SAli.Saidi@ARM.com tid, pc, target, predict_record.RASIndex); 23510665SAli.Saidi@ARM.com } else { 23610665SAli.Saidi@ARM.com ++BTBLookups; 2376364Sgblack@eecs.umich.edu 23810665SAli.Saidi@ARM.com if (inst->isCall()) { 23910665SAli.Saidi@ARM.com RAS[tid].push(pc); 24010665SAli.Saidi@ARM.com predict_record.pushedRAS = true; 2416364Sgblack@eecs.umich.edu 24210665SAli.Saidi@ARM.com // Record that it was a call so that the top RAS entry can 24310665SAli.Saidi@ARM.com // be popped off if the speculation is incorrect. 2446364Sgblack@eecs.umich.edu predict_record.wasCall = true; 24510665SAli.Saidi@ARM.com 24610665SAli.Saidi@ARM.com DPRINTF(Branch, "[tid:%i]: Instruction %s was a " 2474776Sgblack@eecs.umich.edu "call, adding %s to the RAS index: %i.\n", 2484776Sgblack@eecs.umich.edu tid, pc, pc, RAS[tid].topIdx()); 2494776Sgblack@eecs.umich.edu } 2504776Sgblack@eecs.umich.edu 2514776Sgblack@eecs.umich.edu if (inst->isDirectCtrl() || !useIndirect) { 2525034Smilesck@eecs.umich.edu // Check BTB on direct branches 2534776Sgblack@eecs.umich.edu if (BTB.valid(pc.instAddr(), tid)) { 2544776Sgblack@eecs.umich.edu ++BTBHits; 2554776Sgblack@eecs.umich.edu 2564776Sgblack@eecs.umich.edu // If it's not a return, use the BTB to get target addr. 2574776Sgblack@eecs.umich.edu target = BTB.lookup(pc.instAddr(), tid); 2584776Sgblack@eecs.umich.edu 2594776Sgblack@eecs.umich.edu DPRINTF(Branch, "[tid:%i]: Instruction %s predicted" 2607720Sgblack@eecs.umich.edu " target is %s.\n", tid, pc, target); 2617720Sgblack@eecs.umich.edu 2624776Sgblack@eecs.umich.edu } else { 2634776Sgblack@eecs.umich.edu DPRINTF(Branch, "[tid:%i]: BTB doesn't have a " 2644776Sgblack@eecs.umich.edu "valid entry.\n",tid); 2654776Sgblack@eecs.umich.edu pred_taken = false; 2667811Ssteve.reinhardt@amd.com // The Direction of the branch predictor is altered 2674776Sgblack@eecs.umich.edu // because the BTB did not have an entry 2684776Sgblack@eecs.umich.edu // The predictor needs to be updated accordingly 269 if (!inst->isCall() && !inst->isReturn()) { 270 btbUpdate(tid, pc.instAddr(), bp_history); 271 DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate" 272 " called for %s\n", tid, seqNum, pc); 273 } else if (inst->isCall() && !inst->isUncondCtrl()) { 274 RAS[tid].pop(); 275 predict_record.pushedRAS = false; 276 } 277 TheISA::advancePC(target, inst); 278 } 279 } else { 280 predict_record.wasIndirect = true; 281 ++indirectLookups; 282 //Consult indirect predictor on indirect control 283 if (iPred.lookup(pc.instAddr(), getGHR(tid, bp_history), 284 target, tid)) { 285 // Indirect predictor hit 286 ++indirectHits; 287 DPRINTF(Branch, "[tid:%i]: Instruction %s predicted " 288 "indirect target is %s.\n", tid, pc, target); 289 } else { 290 ++indirectMisses; 291 pred_taken = false; 292 DPRINTF(Branch, "[tid:%i]: Instruction %s no indirect " 293 "target.\n", tid, pc); 294 if (!inst->isCall() && !inst->isReturn()) { 295 296 } else if (inst->isCall() && !inst->isUncondCtrl()) { 297 RAS[tid].pop(); 298 predict_record.pushedRAS = false; 299 } 300 TheISA::advancePC(target, inst); 301 } 302 iPred.recordIndirect(pc.instAddr(), target.instAddr(), seqNum, 303 tid); 304 } 305 } 306 } else { 307 if (inst->isReturn()) { 308 predict_record.wasReturn = true; 309 } 310 TheISA::advancePC(target, inst); 311 } 312 313 pc = target; 314 315 predHist[tid].push_front(predict_record); 316 317 DPRINTF(Branch, "[tid:%i]: [sn:%i]: History entry added." 318 "predHist.size(): %i\n", tid, seqNum, predHist[tid].size()); 319 320 return pred_taken; 321} 322 323bool 324BPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum, 325 int asid, TheISA::PCState &instPC, 326 TheISA::PCState &predPC, ThreadID tid) 327{ 328 // See if branch predictor predicts taken. 329 // If so, get its target addr either from the BTB or the RAS. 330 // Save off record of branch stuff so the RAS can be fixed 331 // up once it's done. 332 333 using TheISA::MachInst; 334 335 bool pred_taken = false; 336 TheISA::PCState target; 337 338 ++lookups; 339 ppBranches->notify(1); 340 341 DPRINTF(Branch, "[tid:%i] [sn:%i] %s ... PC %s doing branch " 342 "prediction\n", tid, seqNum, 343 inst->disassemble(instPC.instAddr()), instPC); 344 345 void *bp_history = NULL; 346 347 if (inst->isUncondCtrl()) { 348 DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid); 349 pred_taken = true; 350 // Tell the BP there was an unconditional branch. 351 uncondBranch(tid, instPC.instAddr(), bp_history); 352 353 if (inst->isReturn() && RAS[tid].empty()) { 354 DPRINTF(Branch, "[tid:%i] RAS is empty, predicting " 355 "false.\n", tid); 356 pred_taken = false; 357 } 358 } else { 359 ++condPredicted; 360 361 pred_taken = lookup(tid, predPC.instAddr(), bp_history); 362 } 363 364 PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken, 365 bp_history, tid); 366 367 // Now lookup in the BTB or RAS. 368 if (pred_taken) { 369 if (inst->isReturn()) { 370 ++usedRAS; 371 372 // If it's a function return call, then look up the address 373 // in the RAS. 374 TheISA::PCState rasTop = RAS[tid].top(); 375 target = TheISA::buildRetPC(instPC, rasTop); 376 377 // Record the top entry of the RAS, and its index. 378 predict_record.usedRAS = true; 379 predict_record.RASIndex = RAS[tid].topIdx(); 380 predict_record.RASTarget = rasTop; 381 382 assert(predict_record.RASIndex < 16); 383 384 RAS[tid].pop(); 385 386 DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, " 387 "RAS predicted target: %s, RAS index: %i.\n", 388 tid, instPC, target, 389 predict_record.RASIndex); 390 } else { 391 ++BTBLookups; 392 393 if (inst->isCall()) { 394 395 RAS[tid].push(instPC); 396 predict_record.pushedRAS = true; 397 398 // Record that it was a call so that the top RAS entry can 399 // be popped off if the speculation is incorrect. 400 predict_record.wasCall = true; 401 402 DPRINTF(Branch, "[tid:%i]: Instruction %s was a call" 403 ", adding %s to the RAS index: %i.\n", 404 tid, instPC, predPC, 405 RAS[tid].topIdx()); 406 } 407 408 if (inst->isCall() && 409 inst->isUncondCtrl() && 410 inst->isDirectCtrl()) { 411 target = inst->branchTarget(instPC); 412 } else if (BTB.valid(predPC.instAddr(), asid)) { 413 ++BTBHits; 414 415 // If it's not a return, use the BTB to get the target addr. 416 target = BTB.lookup(predPC.instAddr(), asid); 417 418 DPRINTF(Branch, "[tid:%i]: [asid:%i] Instruction %s " 419 "predicted target is %s.\n", 420 tid, asid, instPC, target); 421 } else { 422 DPRINTF(Branch, "[tid:%i]: BTB doesn't have a " 423 "valid entry, predicting false.\n",tid); 424 pred_taken = false; 425 } 426 } 427 } 428 429 if (pred_taken) { 430 // Set the PC and the instruction's predicted target. 431 predPC = target; 432 } 433 DPRINTF(Branch, "[tid:%i]: [sn:%i]: Setting Predicted PC to %s.\n", 434 tid, seqNum, predPC); 435 436 predHist[tid].push_front(predict_record); 437 438 DPRINTF(Branch, "[tid:%i] [sn:%i] pushed onto front of predHist " 439 "...predHist.size(): %i\n", 440 tid, seqNum, predHist[tid].size()); 441 442 return pred_taken; 443} 444 445void 446BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid) 447{ 448 DPRINTF(Branch, "[tid:%i]: Committing branches until " 449 "[sn:%lli].\n", tid, done_sn); 450 451 iPred.commit(done_sn, tid); 452 while (!predHist[tid].empty() && 453 predHist[tid].back().seqNum <= done_sn) { 454 // Update the branch predictor with the correct results. 455 if (!predHist[tid].back().wasSquashed) { 456 update(tid, predHist[tid].back().pc, 457 predHist[tid].back().predTaken, 458 predHist[tid].back().bpHistory, false); 459 } else { 460 retireSquashed(tid, predHist[tid].back().bpHistory); 461 } 462 463 predHist[tid].pop_back(); 464 } 465} 466 467void 468BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid) 469{ 470 History &pred_hist = predHist[tid]; 471 472 iPred.squash(squashed_sn, tid); 473 while (!pred_hist.empty() && 474 pred_hist.front().seqNum > squashed_sn) { 475 if (pred_hist.front().usedRAS) { 476 DPRINTF(Branch, "[tid:%i]: Restoring top of RAS to: %i," 477 " target: %s.\n", tid, 478 pred_hist.front().RASIndex, pred_hist.front().RASTarget); 479 480 RAS[tid].restore(pred_hist.front().RASIndex, 481 pred_hist.front().RASTarget); 482 } else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) { 483 // Was a call but predicated false. Pop RAS here 484 DPRINTF(Branch, "[tid: %i] Squashing" 485 " Call [sn:%i] PC: %s Popping RAS\n", tid, 486 pred_hist.front().seqNum, pred_hist.front().pc); 487 RAS[tid].pop(); 488 } 489 490 // This call should delete the bpHistory. 491 squash(tid, pred_hist.front().bpHistory); 492 493 DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] " 494 "PC %s.\n", tid, pred_hist.front().seqNum, 495 pred_hist.front().pc); 496 497 pred_hist.pop_front(); 498 499 DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n", 500 tid, predHist[tid].size()); 501 } 502} 503 504void 505BPredUnit::squash(const InstSeqNum &squashed_sn, 506 const TheISA::PCState &corrTarget, 507 bool actually_taken, ThreadID tid) 508{ 509 // Now that we know that a branch was mispredicted, we need to undo 510 // all the branches that have been seen up until this branch and 511 // fix up everything. 512 // NOTE: This should be call conceivably in 2 scenarios: 513 // (1) After an branch is executed, it updates its status in the ROB 514 // The commit stage then checks the ROB update and sends a signal to 515 // the fetch stage to squash history after the mispredict 516 // (2) In the decode stage, you can find out early if a unconditional 517 // PC-relative, branch was predicted incorrectly. If so, a signal 518 // to the fetch stage is sent to squash history after the mispredict 519 520 History &pred_hist = predHist[tid]; 521 522 ++condIncorrect; 523 ppMisses->notify(1); 524 525 DPRINTF(Branch, "[tid:%i]: Squashing from sequence number %i, " 526 "setting target to %s.\n", tid, squashed_sn, corrTarget); 527 528 // Squash All Branches AFTER this mispredicted branch 529 squash(squashed_sn, tid); 530 531 // If there's a squash due to a syscall, there may not be an entry 532 // corresponding to the squash. In that case, don't bother trying to 533 // fix up the entry. 534 if (!pred_hist.empty()) { 535 536 auto hist_it = pred_hist.begin(); 537 //HistoryIt hist_it = find(pred_hist.begin(), pred_hist.end(), 538 // squashed_sn); 539 540 //assert(hist_it != pred_hist.end()); 541 if (pred_hist.front().seqNum != squashed_sn) { 542 DPRINTF(Branch, "Front sn %i != Squash sn %i\n", 543 pred_hist.front().seqNum, squashed_sn); 544 545 assert(pred_hist.front().seqNum == squashed_sn); 546 } 547 548 549 if ((*hist_it).usedRAS) { 550 ++RASIncorrect; 551 DPRINTF(Branch, "[tid:%i]: Incorrect RAS [sn:%i]\n", 552 tid, hist_it->seqNum); 553 } 554 555 // Have to get GHR here because the update deletes bpHistory 556 unsigned ghr = getGHR(tid, hist_it->bpHistory); 557 558 update(tid, (*hist_it).pc, actually_taken, 559 pred_hist.front().bpHistory, true); 560 hist_it->wasSquashed = true; 561 562 if (actually_taken) { 563 if (hist_it->wasReturn && !hist_it->usedRAS) { 564 DPRINTF(Branch, "[tid: %i] Incorrectly predicted" 565 " return [sn:%i] PC: %s\n", tid, hist_it->seqNum, 566 hist_it->pc); 567 RAS[tid].pop(); 568 hist_it->usedRAS = true; 569 } 570 if (hist_it->wasIndirect) { 571 ++indirectMispredicted; 572 iPred.recordTarget(hist_it->seqNum, ghr, corrTarget, tid); 573 } else { 574 DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]" 575 " PC: %s\n", tid,hist_it->seqNum, hist_it->pc); 576 577 BTB.update((*hist_it).pc, corrTarget, tid); 578 } 579 } else { 580 //Actually not Taken 581 if (hist_it->usedRAS) { 582 DPRINTF(Branch,"[tid: %i] Incorrectly predicted" 583 " return [sn:%i] PC: %s Restoring RAS\n", tid, 584 hist_it->seqNum, hist_it->pc); 585 DPRINTF(Branch, "[tid:%i]: Restoring top of RAS" 586 " to: %i, target: %s.\n", tid, 587 hist_it->RASIndex, hist_it->RASTarget); 588 RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget); 589 hist_it->usedRAS = false; 590 } else if (hist_it->wasCall && hist_it->pushedRAS) { 591 //Was a Call but predicated false. Pop RAS here 592 DPRINTF(Branch, "[tid: %i] Incorrectly predicted" 593 " Call [sn:%i] PC: %s Popping RAS\n", tid, 594 hist_it->seqNum, hist_it->pc); 595 RAS[tid].pop(); 596 hist_it->pushedRAS = false; 597 } 598 } 599 } else { 600 DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't " 601 "update.\n", tid, squashed_sn); 602 } 603} 604 605void 606BPredUnit::dump() 607{ 608 int i = 0; 609 for (const auto& ph : predHist) { 610 if (!ph.empty()) { 611 auto pred_hist_it = ph.begin(); 612 613 cprintf("predHist[%i].size(): %i\n", i++, ph.size()); 614 615 while (pred_hist_it != ph.end()) { 616 cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, " 617 "bpHistory:%#x\n", 618 pred_hist_it->seqNum, pred_hist_it->pc, 619 pred_hist_it->tid, pred_hist_it->predTaken, 620 pred_hist_it->bpHistory); 621 pred_hist_it++; 622 } 623 624 cprintf("\n"); 625 } 626 } 627} 628 629