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