bpred_unit.cc revision 11426
11689SN/A/*
210785Sgope@wisc.edu * Copyright (c) 2011-2012, 2014 ARM Limited
39480Snilay@cs.wisc.edu * Copyright (c) 2010 The University of Edinburgh
49480Snilay@cs.wisc.edu * Copyright (c) 2012 Mark D. Hill and David A. Wood
510785Sgope@wisc.edu * All rights reserved
610785Sgope@wisc.edu *
710785Sgope@wisc.edu * The license below extends only to copyright in the software and shall
810785Sgope@wisc.edu * not be construed as granting a license to any other intellectual
910785Sgope@wisc.edu * property including but not limited to intellectual property relating
1010785Sgope@wisc.edu * to a hardware implementation of the functionality of the software
1110785Sgope@wisc.edu * licensed hereunder.  You may use the software subject to the license
1210785Sgope@wisc.edu * terms below provided that you ensure that this notice is replicated
1310785Sgope@wisc.edu * unmodified and in its entirety in all distributions of the software,
1410785Sgope@wisc.edu * modified or unmodified, in source code or in binary form.
1510785Sgope@wisc.edu *
1610785Sgope@wisc.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan
171689SN/A * All rights reserved.
181689SN/A *
191689SN/A * Redistribution and use in source and binary forms, with or without
201689SN/A * modification, are permitted provided that the following conditions are
211689SN/A * met: redistributions of source code must retain the above copyright
221689SN/A * notice, this list of conditions and the following disclaimer;
231689SN/A * redistributions in binary form must reproduce the above copyright
241689SN/A * notice, this list of conditions and the following disclaimer in the
251689SN/A * documentation and/or other materials provided with the distribution;
261689SN/A * neither the name of the copyright holders nor the names of its
271689SN/A * contributors may be used to endorse or promote products derived from
281689SN/A * this software without specific prior written permission.
291689SN/A *
301689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
311689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
321689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
331689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
341689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
351689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
361689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
371689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
381689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
391689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
401689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
412665SN/A *
422665SN/A * Authors: Kevin Lim
431689SN/A */
441061SN/A
4510785Sgope@wisc.edu#include "cpu/pred/bpred_unit.hh"
461061SN/A
4710785Sgope@wisc.edu#include <algorithm>
4810785Sgope@wisc.edu
4910785Sgope@wisc.edu#include "arch/isa_traits.hh"
5010785Sgope@wisc.edu#include "arch/types.hh"
5110785Sgope@wisc.edu#include "arch/utility.hh"
5210785Sgope@wisc.edu#include "base/trace.hh"
5310785Sgope@wisc.edu#include "config/the_isa.hh"
5410785Sgope@wisc.edu#include "debug/Branch.hh"
5510785Sgope@wisc.edu
5610785Sgope@wisc.eduBPredUnit::BPredUnit(const Params *params)
5710785Sgope@wisc.edu    : SimObject(params),
5810785Sgope@wisc.edu      numThreads(params->numThreads),
5910785Sgope@wisc.edu      predHist(numThreads),
6010785Sgope@wisc.edu      BTB(params->BTBEntries,
6110785Sgope@wisc.edu          params->BTBTagSize,
6211425Smitch.hayenga@arm.com          params->instShiftAmt,
6311425Smitch.hayenga@arm.com          params->numThreads),
6410785Sgope@wisc.edu      RAS(numThreads),
6511426Smitch.hayenga@arm.com      useIndirect(params->useIndirect),
6611426Smitch.hayenga@arm.com      iPred(params->indirectHashGHR,
6711426Smitch.hayenga@arm.com            params->indirectHashTargets,
6811426Smitch.hayenga@arm.com            params->indirectSets,
6911426Smitch.hayenga@arm.com            params->indirectWays,
7011426Smitch.hayenga@arm.com            params->indirectTagSize,
7111426Smitch.hayenga@arm.com            params->indirectPathLength,
7211426Smitch.hayenga@arm.com            params->instShiftAmt,
7311426Smitch.hayenga@arm.com            params->numThreads),
7410785Sgope@wisc.edu      instShiftAmt(params->instShiftAmt)
759480Snilay@cs.wisc.edu{
7610785Sgope@wisc.edu    for (auto& r : RAS)
7710785Sgope@wisc.edu        r.init(params->RASSize);
7810785Sgope@wisc.edu}
7910785Sgope@wisc.edu
8010785Sgope@wisc.eduvoid
8110785Sgope@wisc.eduBPredUnit::regStats()
8210785Sgope@wisc.edu{
8310785Sgope@wisc.edu    lookups
8410785Sgope@wisc.edu        .name(name() + ".lookups")
8510785Sgope@wisc.edu        .desc("Number of BP lookups")
8610785Sgope@wisc.edu        ;
8710785Sgope@wisc.edu
8810785Sgope@wisc.edu    condPredicted
8910785Sgope@wisc.edu        .name(name() + ".condPredicted")
9010785Sgope@wisc.edu        .desc("Number of conditional branches predicted")
9110785Sgope@wisc.edu        ;
9210785Sgope@wisc.edu
9310785Sgope@wisc.edu    condIncorrect
9410785Sgope@wisc.edu        .name(name() + ".condIncorrect")
9510785Sgope@wisc.edu        .desc("Number of conditional branches incorrect")
9610785Sgope@wisc.edu        ;
9710785Sgope@wisc.edu
9810785Sgope@wisc.edu    BTBLookups
9910785Sgope@wisc.edu        .name(name() + ".BTBLookups")
10010785Sgope@wisc.edu        .desc("Number of BTB lookups")
10110785Sgope@wisc.edu        ;
10210785Sgope@wisc.edu
10310785Sgope@wisc.edu    BTBHits
10410785Sgope@wisc.edu        .name(name() + ".BTBHits")
10510785Sgope@wisc.edu        .desc("Number of BTB hits")
10610785Sgope@wisc.edu        ;
10710785Sgope@wisc.edu
10810785Sgope@wisc.edu    BTBCorrect
10910785Sgope@wisc.edu        .name(name() + ".BTBCorrect")
11010785Sgope@wisc.edu        .desc("Number of correct BTB predictions (this stat may not "
11110785Sgope@wisc.edu              "work properly.")
11210785Sgope@wisc.edu        ;
11310785Sgope@wisc.edu
11410785Sgope@wisc.edu    BTBHitPct
11510785Sgope@wisc.edu        .name(name() + ".BTBHitPct")
11610785Sgope@wisc.edu        .desc("BTB Hit Percentage")
11710785Sgope@wisc.edu        .precision(6);
11810785Sgope@wisc.edu    BTBHitPct = (BTBHits / BTBLookups) * 100;
11910785Sgope@wisc.edu
12010785Sgope@wisc.edu    usedRAS
12110785Sgope@wisc.edu        .name(name() + ".usedRAS")
12210785Sgope@wisc.edu        .desc("Number of times the RAS was used to get a target.")
12310785Sgope@wisc.edu        ;
12410785Sgope@wisc.edu
12510785Sgope@wisc.edu    RASIncorrect
12610785Sgope@wisc.edu        .name(name() + ".RASInCorrect")
12710785Sgope@wisc.edu        .desc("Number of incorrect RAS predictions.")
12810785Sgope@wisc.edu        ;
12911426Smitch.hayenga@arm.com
13011426Smitch.hayenga@arm.com    indirectLookups
13111426Smitch.hayenga@arm.com        .name(name() + ".indirectLookups")
13211426Smitch.hayenga@arm.com        .desc("Number of indirect predictor lookups.")
13311426Smitch.hayenga@arm.com        ;
13411426Smitch.hayenga@arm.com
13511426Smitch.hayenga@arm.com    indirectHits
13611426Smitch.hayenga@arm.com        .name(name() + ".indirectHits")
13711426Smitch.hayenga@arm.com        .desc("Number of indirect target hits.")
13811426Smitch.hayenga@arm.com        ;
13911426Smitch.hayenga@arm.com
14011426Smitch.hayenga@arm.com    indirectMisses
14111426Smitch.hayenga@arm.com        .name(name() + ".indirectMisses")
14211426Smitch.hayenga@arm.com        .desc("Number of indirect misses.")
14311426Smitch.hayenga@arm.com        ;
14411426Smitch.hayenga@arm.com
14511426Smitch.hayenga@arm.com    indirectMispredicted
14611426Smitch.hayenga@arm.com        .name(name() + "indirectMispredcited")
14711426Smitch.hayenga@arm.com        .desc("Number of mispredicted indirect branches.")
14811426Smitch.hayenga@arm.com        ;
14911426Smitch.hayenga@arm.com
15010785Sgope@wisc.edu}
15110785Sgope@wisc.edu
15210785Sgope@wisc.eduProbePoints::PMUUPtr
15310785Sgope@wisc.eduBPredUnit::pmuProbePoint(const char *name)
15410785Sgope@wisc.edu{
15510785Sgope@wisc.edu    ProbePoints::PMUUPtr ptr;
15610785Sgope@wisc.edu    ptr.reset(new ProbePoints::PMU(getProbeManager(), name));
15710785Sgope@wisc.edu
15810785Sgope@wisc.edu    return ptr;
15910785Sgope@wisc.edu}
16010785Sgope@wisc.edu
16110785Sgope@wisc.eduvoid
16210785Sgope@wisc.eduBPredUnit::regProbePoints()
16310785Sgope@wisc.edu{
16410785Sgope@wisc.edu    ppBranches = pmuProbePoint("Branches");
16510785Sgope@wisc.edu    ppMisses = pmuProbePoint("Misses");
16610785Sgope@wisc.edu}
16710785Sgope@wisc.edu
16810785Sgope@wisc.eduvoid
16910785Sgope@wisc.eduBPredUnit::drainSanityCheck() const
17010785Sgope@wisc.edu{
17110785Sgope@wisc.edu    // We shouldn't have any outstanding requests when we resume from
17210785Sgope@wisc.edu    // a drained system.
17310785Sgope@wisc.edu    for (const auto& ph M5_VAR_USED : predHist)
17410785Sgope@wisc.edu        assert(ph.empty());
17510785Sgope@wisc.edu}
17610785Sgope@wisc.edu
17710785Sgope@wisc.edubool
17810785Sgope@wisc.eduBPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
17910785Sgope@wisc.edu                   TheISA::PCState &pc, ThreadID tid)
18010785Sgope@wisc.edu{
18110785Sgope@wisc.edu    // See if branch predictor predicts taken.
18210785Sgope@wisc.edu    // If so, get its target addr either from the BTB or the RAS.
18310785Sgope@wisc.edu    // Save off record of branch stuff so the RAS can be fixed
18410785Sgope@wisc.edu    // up once it's done.
18510785Sgope@wisc.edu
18610785Sgope@wisc.edu    bool pred_taken = false;
18710785Sgope@wisc.edu    TheISA::PCState target = pc;
18810785Sgope@wisc.edu
18910785Sgope@wisc.edu    ++lookups;
19010785Sgope@wisc.edu    ppBranches->notify(1);
19110785Sgope@wisc.edu
19210785Sgope@wisc.edu    void *bp_history = NULL;
19310785Sgope@wisc.edu
19410785Sgope@wisc.edu    if (inst->isUncondCtrl()) {
19510785Sgope@wisc.edu        DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid);
19610785Sgope@wisc.edu        pred_taken = true;
19710785Sgope@wisc.edu        // Tell the BP there was an unconditional branch.
19810785Sgope@wisc.edu        uncondBranch(pc.instAddr(), bp_history);
1999480Snilay@cs.wisc.edu    } else {
20010785Sgope@wisc.edu        ++condPredicted;
20110785Sgope@wisc.edu        pred_taken = lookup(pc.instAddr(), bp_history);
20210785Sgope@wisc.edu
20310785Sgope@wisc.edu        DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
20410785Sgope@wisc.edu                " predicted %i for PC %s\n", tid, seqNum,  pred_taken, pc);
20510785Sgope@wisc.edu    }
20610785Sgope@wisc.edu
20710785Sgope@wisc.edu    DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history "
20810785Sgope@wisc.edu            "for PC %s\n", tid, seqNum, pc);
20910785Sgope@wisc.edu
21010785Sgope@wisc.edu    PredictorHistory predict_record(seqNum, pc.instAddr(),
21110785Sgope@wisc.edu                                    pred_taken, bp_history, tid);
21210785Sgope@wisc.edu
21310785Sgope@wisc.edu    // Now lookup in the BTB or RAS.
21410785Sgope@wisc.edu    if (pred_taken) {
21510785Sgope@wisc.edu        if (inst->isReturn()) {
21610785Sgope@wisc.edu            ++usedRAS;
21710785Sgope@wisc.edu            predict_record.wasReturn = true;
21810785Sgope@wisc.edu            // If it's a function return call, then look up the address
21910785Sgope@wisc.edu            // in the RAS.
22010785Sgope@wisc.edu            TheISA::PCState rasTop = RAS[tid].top();
22110785Sgope@wisc.edu            target = TheISA::buildRetPC(pc, rasTop);
22210785Sgope@wisc.edu
22310785Sgope@wisc.edu            // Record the top entry of the RAS, and its index.
22410785Sgope@wisc.edu            predict_record.usedRAS = true;
22510785Sgope@wisc.edu            predict_record.RASIndex = RAS[tid].topIdx();
22610785Sgope@wisc.edu            predict_record.RASTarget = rasTop;
22710785Sgope@wisc.edu
22810785Sgope@wisc.edu            RAS[tid].pop();
22910785Sgope@wisc.edu
23010785Sgope@wisc.edu            DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, "
23110785Sgope@wisc.edu                    "RAS predicted target: %s, RAS index: %i.\n",
23210785Sgope@wisc.edu                    tid, pc, target, predict_record.RASIndex);
23310785Sgope@wisc.edu        } else {
23410785Sgope@wisc.edu            ++BTBLookups;
23510785Sgope@wisc.edu
23610785Sgope@wisc.edu            if (inst->isCall()) {
23710785Sgope@wisc.edu                RAS[tid].push(pc);
23810785Sgope@wisc.edu                predict_record.pushedRAS = true;
23910785Sgope@wisc.edu
24010785Sgope@wisc.edu                // Record that it was a call so that the top RAS entry can
24110785Sgope@wisc.edu                // be popped off if the speculation is incorrect.
24210785Sgope@wisc.edu                predict_record.wasCall = true;
24310785Sgope@wisc.edu
24410785Sgope@wisc.edu                DPRINTF(Branch, "[tid:%i]: Instruction %s was a "
24510785Sgope@wisc.edu                        "call, adding %s to the RAS index: %i.\n",
24610785Sgope@wisc.edu                        tid, pc, pc, RAS[tid].topIdx());
24710785Sgope@wisc.edu            }
24810785Sgope@wisc.edu
24911426Smitch.hayenga@arm.com            if (inst->isDirectCtrl() || !useIndirect) {
25011426Smitch.hayenga@arm.com                // Check BTB on direct branches
25111426Smitch.hayenga@arm.com                if (BTB.valid(pc.instAddr(), tid)) {
25211426Smitch.hayenga@arm.com                    ++BTBHits;
25310785Sgope@wisc.edu
25411426Smitch.hayenga@arm.com                    // If it's not a return, use the BTB to get target addr.
25511426Smitch.hayenga@arm.com                    target = BTB.lookup(pc.instAddr(), tid);
25610785Sgope@wisc.edu
25711426Smitch.hayenga@arm.com                    DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
25811426Smitch.hayenga@arm.com                            " target is %s.\n", tid, pc, target);
25910785Sgope@wisc.edu
26011426Smitch.hayenga@arm.com                } else {
26111426Smitch.hayenga@arm.com                    DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
26211426Smitch.hayenga@arm.com                            "valid entry.\n",tid);
26311426Smitch.hayenga@arm.com                    pred_taken = false;
26411426Smitch.hayenga@arm.com                    // The Direction of the branch predictor is altered
26511426Smitch.hayenga@arm.com                    // because the BTB did not have an entry
26611426Smitch.hayenga@arm.com                    // The predictor needs to be updated accordingly
26711426Smitch.hayenga@arm.com                    if (!inst->isCall() && !inst->isReturn()) {
26811426Smitch.hayenga@arm.com                        btbUpdate(pc.instAddr(), bp_history);
26911426Smitch.hayenga@arm.com                        DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
27011426Smitch.hayenga@arm.com                                " called for %s\n", tid, seqNum, pc);
27111426Smitch.hayenga@arm.com                    } else if (inst->isCall() && !inst->isUncondCtrl()) {
27211426Smitch.hayenga@arm.com                        RAS[tid].pop();
27311426Smitch.hayenga@arm.com                        predict_record.pushedRAS = false;
27411426Smitch.hayenga@arm.com                    }
27511426Smitch.hayenga@arm.com                    TheISA::advancePC(target, inst);
27611426Smitch.hayenga@arm.com                }
27710785Sgope@wisc.edu            } else {
27811426Smitch.hayenga@arm.com                predict_record.wasIndirect = true;
27911426Smitch.hayenga@arm.com                ++indirectLookups;
28011426Smitch.hayenga@arm.com                //Consult indirect predictor on indirect control
28111426Smitch.hayenga@arm.com                if (iPred.lookup(pc.instAddr(), getGHR(bp_history), target,
28211426Smitch.hayenga@arm.com                        tid)) {
28311426Smitch.hayenga@arm.com                    // Indirect predictor hit
28411426Smitch.hayenga@arm.com                    ++indirectHits;
28511426Smitch.hayenga@arm.com                    DPRINTF(Branch, "[tid:%i]: Instruction %s predicted "
28611426Smitch.hayenga@arm.com                            "indirect target is %s.\n", tid, pc, target);
28711426Smitch.hayenga@arm.com                } else {
28811426Smitch.hayenga@arm.com                    ++indirectMisses;
28911426Smitch.hayenga@arm.com                    pred_taken = false;
29011426Smitch.hayenga@arm.com                    DPRINTF(Branch, "[tid:%i]: Instruction %s no indirect "
29111426Smitch.hayenga@arm.com                            "target.\n", tid, pc);
29211426Smitch.hayenga@arm.com                    if (!inst->isCall() && !inst->isReturn()) {
29311426Smitch.hayenga@arm.com
29411426Smitch.hayenga@arm.com                    } else if (inst->isCall() && !inst->isUncondCtrl()) {
29511426Smitch.hayenga@arm.com                        RAS[tid].pop();
29611426Smitch.hayenga@arm.com                        predict_record.pushedRAS = false;
29711426Smitch.hayenga@arm.com                    }
29811426Smitch.hayenga@arm.com                    TheISA::advancePC(target, inst);
29910785Sgope@wisc.edu                }
30011426Smitch.hayenga@arm.com                iPred.recordIndirect(pc.instAddr(), target.instAddr(), seqNum,
30111426Smitch.hayenga@arm.com                        tid);
30210785Sgope@wisc.edu            }
30310785Sgope@wisc.edu        }
30410785Sgope@wisc.edu    } else {
30510785Sgope@wisc.edu        if (inst->isReturn()) {
30610785Sgope@wisc.edu           predict_record.wasReturn = true;
30710785Sgope@wisc.edu        }
30810785Sgope@wisc.edu        TheISA::advancePC(target, inst);
30910785Sgope@wisc.edu    }
31010785Sgope@wisc.edu
31110785Sgope@wisc.edu    pc = target;
31210785Sgope@wisc.edu
31310785Sgope@wisc.edu    predHist[tid].push_front(predict_record);
31410785Sgope@wisc.edu
31510785Sgope@wisc.edu    DPRINTF(Branch, "[tid:%i]: [sn:%i]: History entry added."
31610785Sgope@wisc.edu            "predHist.size(): %i\n", tid, seqNum, predHist[tid].size());
31710785Sgope@wisc.edu
31810785Sgope@wisc.edu    return pred_taken;
31910785Sgope@wisc.edu}
32010785Sgope@wisc.edu
32110785Sgope@wisc.edubool
32210785Sgope@wisc.eduBPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum,
32310785Sgope@wisc.edu                          int asid, TheISA::PCState &instPC,
32410785Sgope@wisc.edu                          TheISA::PCState &predPC, ThreadID tid)
32510785Sgope@wisc.edu{
32610785Sgope@wisc.edu    // See if branch predictor predicts taken.
32710785Sgope@wisc.edu    // If so, get its target addr either from the BTB or the RAS.
32810785Sgope@wisc.edu    // Save off record of branch stuff so the RAS can be fixed
32910785Sgope@wisc.edu    // up once it's done.
33010785Sgope@wisc.edu
33110785Sgope@wisc.edu    using TheISA::MachInst;
33210785Sgope@wisc.edu
33310785Sgope@wisc.edu    bool pred_taken = false;
33410785Sgope@wisc.edu    TheISA::PCState target;
33510785Sgope@wisc.edu
33610785Sgope@wisc.edu    ++lookups;
33710785Sgope@wisc.edu    ppBranches->notify(1);
33810785Sgope@wisc.edu
33910785Sgope@wisc.edu    DPRINTF(Branch, "[tid:%i] [sn:%i] %s ... PC %s doing branch "
34010785Sgope@wisc.edu            "prediction\n", tid, seqNum,
34110785Sgope@wisc.edu            inst->disassemble(instPC.instAddr()), instPC);
34210785Sgope@wisc.edu
34310785Sgope@wisc.edu    void *bp_history = NULL;
34410785Sgope@wisc.edu
34510785Sgope@wisc.edu    if (inst->isUncondCtrl()) {
34610785Sgope@wisc.edu        DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid);
34710785Sgope@wisc.edu        pred_taken = true;
34810785Sgope@wisc.edu        // Tell the BP there was an unconditional branch.
34910785Sgope@wisc.edu        uncondBranch(instPC.instAddr(), bp_history);
35010785Sgope@wisc.edu
35110785Sgope@wisc.edu        if (inst->isReturn() && RAS[tid].empty()) {
35210785Sgope@wisc.edu            DPRINTF(Branch, "[tid:%i] RAS is empty, predicting "
35310785Sgope@wisc.edu                    "false.\n", tid);
35410785Sgope@wisc.edu            pred_taken = false;
35510785Sgope@wisc.edu        }
35610785Sgope@wisc.edu    } else {
35710785Sgope@wisc.edu        ++condPredicted;
35810785Sgope@wisc.edu
35910785Sgope@wisc.edu        pred_taken = lookup(predPC.instAddr(), bp_history);
36010785Sgope@wisc.edu    }
36110785Sgope@wisc.edu
36210785Sgope@wisc.edu    PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken,
36310785Sgope@wisc.edu                                    bp_history, tid);
36410785Sgope@wisc.edu
36510785Sgope@wisc.edu    // Now lookup in the BTB or RAS.
36610785Sgope@wisc.edu    if (pred_taken) {
36710785Sgope@wisc.edu        if (inst->isReturn()) {
36810785Sgope@wisc.edu            ++usedRAS;
36910785Sgope@wisc.edu
37010785Sgope@wisc.edu            // If it's a function return call, then look up the address
37110785Sgope@wisc.edu            // in the RAS.
37210785Sgope@wisc.edu            TheISA::PCState rasTop = RAS[tid].top();
37310785Sgope@wisc.edu            target = TheISA::buildRetPC(instPC, rasTop);
37410785Sgope@wisc.edu
37510785Sgope@wisc.edu            // Record the top entry of the RAS, and its index.
37610785Sgope@wisc.edu            predict_record.usedRAS = true;
37710785Sgope@wisc.edu            predict_record.RASIndex = RAS[tid].topIdx();
37810785Sgope@wisc.edu            predict_record.RASTarget = rasTop;
37910785Sgope@wisc.edu
38010785Sgope@wisc.edu            assert(predict_record.RASIndex < 16);
38110785Sgope@wisc.edu
38210785Sgope@wisc.edu            RAS[tid].pop();
38310785Sgope@wisc.edu
38410785Sgope@wisc.edu            DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, "
38510785Sgope@wisc.edu                    "RAS predicted target: %s, RAS index: %i.\n",
38610785Sgope@wisc.edu                    tid, instPC, target,
38710785Sgope@wisc.edu                    predict_record.RASIndex);
38810785Sgope@wisc.edu        } else {
38910785Sgope@wisc.edu            ++BTBLookups;
39010785Sgope@wisc.edu
39110785Sgope@wisc.edu            if (inst->isCall()) {
39210785Sgope@wisc.edu
39310785Sgope@wisc.edu                RAS[tid].push(instPC);
39410785Sgope@wisc.edu                predict_record.pushedRAS = true;
39510785Sgope@wisc.edu
39610785Sgope@wisc.edu                // Record that it was a call so that the top RAS entry can
39710785Sgope@wisc.edu                // be popped off if the speculation is incorrect.
39810785Sgope@wisc.edu                predict_record.wasCall = true;
39910785Sgope@wisc.edu
40010785Sgope@wisc.edu                DPRINTF(Branch, "[tid:%i]: Instruction %s was a call"
40110785Sgope@wisc.edu                        ", adding %s to the RAS index: %i.\n",
40210785Sgope@wisc.edu                        tid, instPC, predPC,
40310785Sgope@wisc.edu                        RAS[tid].topIdx());
40410785Sgope@wisc.edu            }
40510785Sgope@wisc.edu
40610785Sgope@wisc.edu            if (inst->isCall() &&
40710785Sgope@wisc.edu                inst->isUncondCtrl() &&
40810785Sgope@wisc.edu                inst->isDirectCtrl()) {
40910785Sgope@wisc.edu                target = inst->branchTarget(instPC);
41010785Sgope@wisc.edu            } else if (BTB.valid(predPC.instAddr(), asid)) {
41110785Sgope@wisc.edu                ++BTBHits;
41210785Sgope@wisc.edu
41310785Sgope@wisc.edu                // If it's not a return, use the BTB to get the target addr.
41410785Sgope@wisc.edu                target = BTB.lookup(predPC.instAddr(), asid);
41510785Sgope@wisc.edu
41610785Sgope@wisc.edu                DPRINTF(Branch, "[tid:%i]: [asid:%i] Instruction %s "
41710785Sgope@wisc.edu                        "predicted target is %s.\n",
41810785Sgope@wisc.edu                        tid, asid, instPC, target);
41910785Sgope@wisc.edu            } else {
42010785Sgope@wisc.edu                DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
42110785Sgope@wisc.edu                        "valid entry, predicting false.\n",tid);
42210785Sgope@wisc.edu                pred_taken = false;
42310785Sgope@wisc.edu            }
42410785Sgope@wisc.edu        }
42510785Sgope@wisc.edu    }
42610785Sgope@wisc.edu
42710785Sgope@wisc.edu    if (pred_taken) {
42810785Sgope@wisc.edu        // Set the PC and the instruction's predicted target.
42910785Sgope@wisc.edu        predPC = target;
43010785Sgope@wisc.edu    }
43110785Sgope@wisc.edu    DPRINTF(Branch, "[tid:%i]: [sn:%i]: Setting Predicted PC to %s.\n",
43210785Sgope@wisc.edu            tid, seqNum, predPC);
43310785Sgope@wisc.edu
43410785Sgope@wisc.edu    predHist[tid].push_front(predict_record);
43510785Sgope@wisc.edu
43610785Sgope@wisc.edu    DPRINTF(Branch, "[tid:%i] [sn:%i] pushed onto front of predHist "
43710785Sgope@wisc.edu            "...predHist.size(): %i\n",
43810785Sgope@wisc.edu            tid, seqNum, predHist[tid].size());
43910785Sgope@wisc.edu
44010785Sgope@wisc.edu    return pred_taken;
44110785Sgope@wisc.edu}
44210785Sgope@wisc.edu
44310785Sgope@wisc.eduvoid
44410785Sgope@wisc.eduBPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
44510785Sgope@wisc.edu{
44610785Sgope@wisc.edu    DPRINTF(Branch, "[tid:%i]: Committing branches until "
44710785Sgope@wisc.edu            "[sn:%lli].\n", tid, done_sn);
44810785Sgope@wisc.edu
44911426Smitch.hayenga@arm.com    iPred.commit(done_sn, tid);
45010785Sgope@wisc.edu    while (!predHist[tid].empty() &&
45110785Sgope@wisc.edu           predHist[tid].back().seqNum <= done_sn) {
45210785Sgope@wisc.edu        // Update the branch predictor with the correct results.
45310785Sgope@wisc.edu        if (!predHist[tid].back().wasSquashed) {
45410785Sgope@wisc.edu            update(predHist[tid].back().pc, predHist[tid].back().predTaken,
45510785Sgope@wisc.edu                predHist[tid].back().bpHistory, false);
45610785Sgope@wisc.edu        } else {
45710785Sgope@wisc.edu            retireSquashed(predHist[tid].back().bpHistory);
45810785Sgope@wisc.edu        }
45910785Sgope@wisc.edu
46010785Sgope@wisc.edu        predHist[tid].pop_back();
4619480Snilay@cs.wisc.edu    }
4629480Snilay@cs.wisc.edu}
46310785Sgope@wisc.edu
46410785Sgope@wisc.eduvoid
46510785Sgope@wisc.eduBPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
46610785Sgope@wisc.edu{
46710785Sgope@wisc.edu    History &pred_hist = predHist[tid];
46810785Sgope@wisc.edu
46911426Smitch.hayenga@arm.com    iPred.squash(squashed_sn, tid);
47010785Sgope@wisc.edu    while (!pred_hist.empty() &&
47110785Sgope@wisc.edu           pred_hist.front().seqNum > squashed_sn) {
47210785Sgope@wisc.edu        if (pred_hist.front().usedRAS) {
47310785Sgope@wisc.edu            DPRINTF(Branch, "[tid:%i]: Restoring top of RAS to: %i,"
47410785Sgope@wisc.edu                    " target: %s.\n", tid,
47510785Sgope@wisc.edu                    pred_hist.front().RASIndex, pred_hist.front().RASTarget);
47610785Sgope@wisc.edu
47710785Sgope@wisc.edu            RAS[tid].restore(pred_hist.front().RASIndex,
47810785Sgope@wisc.edu                             pred_hist.front().RASTarget);
47911321Ssteve.reinhardt@amd.com        } else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
48010785Sgope@wisc.edu             // Was a call but predicated false. Pop RAS here
48110785Sgope@wisc.edu             DPRINTF(Branch, "[tid: %i] Squashing"
48210785Sgope@wisc.edu                     "  Call [sn:%i] PC: %s Popping RAS\n", tid,
48310785Sgope@wisc.edu                     pred_hist.front().seqNum, pred_hist.front().pc);
48410785Sgope@wisc.edu             RAS[tid].pop();
48510785Sgope@wisc.edu        }
48610785Sgope@wisc.edu
48710785Sgope@wisc.edu        // This call should delete the bpHistory.
48810785Sgope@wisc.edu        squash(pred_hist.front().bpHistory);
48910785Sgope@wisc.edu
49010785Sgope@wisc.edu        DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] "
49110785Sgope@wisc.edu                "PC %s.\n", tid, pred_hist.front().seqNum,
49210785Sgope@wisc.edu                pred_hist.front().pc);
49310785Sgope@wisc.edu
49410785Sgope@wisc.edu        pred_hist.pop_front();
49510785Sgope@wisc.edu
49610785Sgope@wisc.edu        DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n",
49710785Sgope@wisc.edu                tid, predHist[tid].size());
49810785Sgope@wisc.edu    }
49910785Sgope@wisc.edu}
50010785Sgope@wisc.edu
50110785Sgope@wisc.eduvoid
50210785Sgope@wisc.eduBPredUnit::squash(const InstSeqNum &squashed_sn,
50310785Sgope@wisc.edu                  const TheISA::PCState &corrTarget,
50410785Sgope@wisc.edu                  bool actually_taken, ThreadID tid)
50510785Sgope@wisc.edu{
50610785Sgope@wisc.edu    // Now that we know that a branch was mispredicted, we need to undo
50710785Sgope@wisc.edu    // all the branches that have been seen up until this branch and
50810785Sgope@wisc.edu    // fix up everything.
50910785Sgope@wisc.edu    // NOTE: This should be call conceivably in 2 scenarios:
51010785Sgope@wisc.edu    // (1) After an branch is executed, it updates its status in the ROB
51110785Sgope@wisc.edu    //     The commit stage then checks the ROB update and sends a signal to
51210785Sgope@wisc.edu    //     the fetch stage to squash history after the mispredict
51310785Sgope@wisc.edu    // (2) In the decode stage, you can find out early if a unconditional
51410785Sgope@wisc.edu    //     PC-relative, branch was predicted incorrectly. If so, a signal
51510785Sgope@wisc.edu    //     to the fetch stage is sent to squash history after the mispredict
51610785Sgope@wisc.edu
51710785Sgope@wisc.edu    History &pred_hist = predHist[tid];
51810785Sgope@wisc.edu
51910785Sgope@wisc.edu    ++condIncorrect;
52010785Sgope@wisc.edu    ppMisses->notify(1);
52110785Sgope@wisc.edu
52210785Sgope@wisc.edu    DPRINTF(Branch, "[tid:%i]: Squashing from sequence number %i, "
52310785Sgope@wisc.edu            "setting target to %s.\n", tid, squashed_sn, corrTarget);
52410785Sgope@wisc.edu
52510785Sgope@wisc.edu    // Squash All Branches AFTER this mispredicted branch
52610785Sgope@wisc.edu    squash(squashed_sn, tid);
52710785Sgope@wisc.edu
52810785Sgope@wisc.edu    // If there's a squash due to a syscall, there may not be an entry
52910785Sgope@wisc.edu    // corresponding to the squash.  In that case, don't bother trying to
53010785Sgope@wisc.edu    // fix up the entry.
53110785Sgope@wisc.edu    if (!pred_hist.empty()) {
53210785Sgope@wisc.edu
53310785Sgope@wisc.edu        auto hist_it = pred_hist.begin();
53410785Sgope@wisc.edu        //HistoryIt hist_it = find(pred_hist.begin(), pred_hist.end(),
53510785Sgope@wisc.edu        //                       squashed_sn);
53610785Sgope@wisc.edu
53710785Sgope@wisc.edu        //assert(hist_it != pred_hist.end());
53810785Sgope@wisc.edu        if (pred_hist.front().seqNum != squashed_sn) {
53910785Sgope@wisc.edu            DPRINTF(Branch, "Front sn %i != Squash sn %i\n",
54010785Sgope@wisc.edu                    pred_hist.front().seqNum, squashed_sn);
54110785Sgope@wisc.edu
54210785Sgope@wisc.edu            assert(pred_hist.front().seqNum == squashed_sn);
54310785Sgope@wisc.edu        }
54410785Sgope@wisc.edu
54510785Sgope@wisc.edu
54610785Sgope@wisc.edu        if ((*hist_it).usedRAS) {
54710785Sgope@wisc.edu            ++RASIncorrect;
54811426Smitch.hayenga@arm.com            DPRINTF(Branch, "[tid:%i]: Incorrect RAS [sn:%i]\n",
54911426Smitch.hayenga@arm.com                    tid, hist_it->seqNum);
55010785Sgope@wisc.edu        }
55110785Sgope@wisc.edu
55211426Smitch.hayenga@arm.com        // Have to get GHR here because the update deletes bpHistory
55311426Smitch.hayenga@arm.com        unsigned ghr = getGHR(hist_it->bpHistory);
55411426Smitch.hayenga@arm.com
55510785Sgope@wisc.edu        update((*hist_it).pc, actually_taken,
55610785Sgope@wisc.edu               pred_hist.front().bpHistory, true);
55710785Sgope@wisc.edu        hist_it->wasSquashed = true;
55810785Sgope@wisc.edu
55910785Sgope@wisc.edu        if (actually_taken) {
56010785Sgope@wisc.edu            if (hist_it->wasReturn && !hist_it->usedRAS) {
56110785Sgope@wisc.edu                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
56210785Sgope@wisc.edu                         "  return [sn:%i] PC: %s\n", tid, hist_it->seqNum,
56310785Sgope@wisc.edu                         hist_it->pc);
56410785Sgope@wisc.edu                 RAS[tid].pop();
56510785Sgope@wisc.edu                 hist_it->usedRAS = true;
56610785Sgope@wisc.edu            }
56711426Smitch.hayenga@arm.com            if (hist_it->wasIndirect) {
56811426Smitch.hayenga@arm.com                ++indirectMispredicted;
56911426Smitch.hayenga@arm.com                iPred.recordTarget(hist_it->seqNum, ghr, corrTarget, tid);
57011426Smitch.hayenga@arm.com            } else {
57111426Smitch.hayenga@arm.com                DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]"
57211426Smitch.hayenga@arm.com                        " PC: %s\n", tid,hist_it->seqNum, hist_it->pc);
57310785Sgope@wisc.edu
57411426Smitch.hayenga@arm.com                BTB.update((*hist_it).pc, corrTarget, tid);
57511426Smitch.hayenga@arm.com            }
57610785Sgope@wisc.edu        } else {
57710785Sgope@wisc.edu           //Actually not Taken
57810785Sgope@wisc.edu           if (hist_it->usedRAS) {
57910785Sgope@wisc.edu                DPRINTF(Branch,"[tid: %i] Incorrectly predicted"
58010785Sgope@wisc.edu                        "  return [sn:%i] PC: %s Restoring RAS\n", tid,
58110785Sgope@wisc.edu                        hist_it->seqNum, hist_it->pc);
58210785Sgope@wisc.edu                DPRINTF(Branch, "[tid:%i]: Restoring top of RAS"
58310785Sgope@wisc.edu                        " to: %i, target: %s.\n", tid,
58410785Sgope@wisc.edu                        hist_it->RASIndex, hist_it->RASTarget);
58510785Sgope@wisc.edu                RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget);
58610785Sgope@wisc.edu                hist_it->usedRAS = false;
58710785Sgope@wisc.edu           } else if (hist_it->wasCall && hist_it->pushedRAS) {
58810785Sgope@wisc.edu                 //Was a Call but predicated false. Pop RAS here
58910785Sgope@wisc.edu                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
59010785Sgope@wisc.edu                         "  Call [sn:%i] PC: %s Popping RAS\n", tid,
59110785Sgope@wisc.edu                         hist_it->seqNum, hist_it->pc);
59210785Sgope@wisc.edu                 RAS[tid].pop();
59310785Sgope@wisc.edu                 hist_it->pushedRAS = false;
59410785Sgope@wisc.edu           }
59510785Sgope@wisc.edu        }
59610785Sgope@wisc.edu    } else {
59710785Sgope@wisc.edu        DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't "
59810785Sgope@wisc.edu                "update.\n", tid, squashed_sn);
59910785Sgope@wisc.edu    }
60010785Sgope@wisc.edu}
60110785Sgope@wisc.edu
60210785Sgope@wisc.eduvoid
60310785Sgope@wisc.eduBPredUnit::dump()
60410785Sgope@wisc.edu{
60510785Sgope@wisc.edu    int i = 0;
60610785Sgope@wisc.edu    for (const auto& ph : predHist) {
60710785Sgope@wisc.edu        if (!ph.empty()) {
60810785Sgope@wisc.edu            auto pred_hist_it = ph.begin();
60910785Sgope@wisc.edu
61010785Sgope@wisc.edu            cprintf("predHist[%i].size(): %i\n", i++, ph.size());
61110785Sgope@wisc.edu
61210785Sgope@wisc.edu            while (pred_hist_it != ph.end()) {
61310785Sgope@wisc.edu                cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
61410785Sgope@wisc.edu                        "bpHistory:%#x\n",
61510785Sgope@wisc.edu                        pred_hist_it->seqNum, pred_hist_it->pc,
61610785Sgope@wisc.edu                        pred_hist_it->tid, pred_hist_it->predTaken,
61710785Sgope@wisc.edu                        pred_hist_it->bpHistory);
61810785Sgope@wisc.edu                pred_hist_it++;
61910785Sgope@wisc.edu            }
62010785Sgope@wisc.edu
62110785Sgope@wisc.edu            cprintf("\n");
62210785Sgope@wisc.edu        }
62310785Sgope@wisc.edu    }
62410785Sgope@wisc.edu}
62510785Sgope@wisc.edu
626