bpred_unit.cc revision 13626
12686Sksewell@umich.edu/*
22686Sksewell@umich.edu * Copyright (c) 2011-2012, 2014 ARM Limited
35268Sksewell@umich.edu * Copyright (c) 2010 The University of Edinburgh
45268Sksewell@umich.edu * Copyright (c) 2012 Mark D. Hill and David A. Wood
55268Sksewell@umich.edu * All rights reserved
65268Sksewell@umich.edu *
75268Sksewell@umich.edu * The license below extends only to copyright in the software and shall
85268Sksewell@umich.edu * not be construed as granting a license to any other intellectual
95268Sksewell@umich.edu * property including but not limited to intellectual property relating
105268Sksewell@umich.edu * to a hardware implementation of the functionality of the software
115268Sksewell@umich.edu * licensed hereunder.  You may use the software subject to the license
125268Sksewell@umich.edu * terms below provided that you ensure that this notice is replicated
135268Sksewell@umich.edu * unmodified and in its entirety in all distributions of the software,
145268Sksewell@umich.edu * modified or unmodified, in source code or in binary form.
155268Sksewell@umich.edu *
165268Sksewell@umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan
175268Sksewell@umich.edu * All rights reserved.
185268Sksewell@umich.edu *
195268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
205268Sksewell@umich.edu * modification, are permitted provided that the following conditions are
215268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
225268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
235268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
245268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
255268Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
265268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
275268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
285268Sksewell@umich.edu * this software without specific prior written permission.
295268Sksewell@umich.edu *
302706Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
312686Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
322686Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
332686Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
342686Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
352686Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
362686Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
372686Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
382741Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
392686Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
404661Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
412686Sksewell@umich.edu *
422686Sksewell@umich.edu * Authors: Kevin Lim
432686Sksewell@umich.edu */
442686Sksewell@umich.edu
454661Sksewell@umich.edu#include "cpu/pred/bpred_unit.hh"
464661Sksewell@umich.edu
472686Sksewell@umich.edu#include <algorithm>
482686Sksewell@umich.edu
492686Sksewell@umich.edu#include "arch/isa_traits.hh"
504661Sksewell@umich.edu#include "arch/types.hh"
514661Sksewell@umich.edu#include "arch/utility.hh"
524661Sksewell@umich.edu#include "base/trace.hh"
534661Sksewell@umich.edu#include "config/the_isa.hh"
544661Sksewell@umich.edu#include "debug/Branch.hh"
554661Sksewell@umich.edu
564661Sksewell@umich.eduBPredUnit::BPredUnit(const Params *params)
574661Sksewell@umich.edu    : SimObject(params),
584661Sksewell@umich.edu      numThreads(params->numThreads),
594661Sksewell@umich.edu      predHist(numThreads),
604661Sksewell@umich.edu      BTB(params->BTBEntries,
614661Sksewell@umich.edu          params->BTBTagSize,
624661Sksewell@umich.edu          params->instShiftAmt,
634661Sksewell@umich.edu          params->numThreads),
644661Sksewell@umich.edu      RAS(numThreads),
654661Sksewell@umich.edu      useIndirect(params->useIndirect),
664661Sksewell@umich.edu      iPred(params->indirectHashGHR,
672686Sksewell@umich.edu            params->indirectHashTargets,
682686Sksewell@umich.edu            params->indirectSets,
692686Sksewell@umich.edu            params->indirectWays,
702686Sksewell@umich.edu            params->indirectTagSize,
714661Sksewell@umich.edu            params->indirectPathLength,
724661Sksewell@umich.edu            params->instShiftAmt,
734661Sksewell@umich.edu            params->numThreads),
744661Sksewell@umich.edu      instShiftAmt(params->instShiftAmt)
755269Sksewell@umich.edu{
764661Sksewell@umich.edu    for (auto& r : RAS)
775269Sksewell@umich.edu        r.init(params->RASSize);
784661Sksewell@umich.edu}
794661Sksewell@umich.edu
804661Sksewell@umich.eduvoid
814661Sksewell@umich.eduBPredUnit::regStats()
824661Sksewell@umich.edu{
834661Sksewell@umich.edu    SimObject::regStats();
844661Sksewell@umich.edu
854661Sksewell@umich.edu    lookups
864661Sksewell@umich.edu        .name(name() + ".lookups")
879554Sandreas.hansson@arm.com        .desc("Number of BP lookups")
889554Sandreas.hansson@arm.com        ;
899554Sandreas.hansson@arm.com
909554Sandreas.hansson@arm.com    condPredicted
919554Sandreas.hansson@arm.com        .name(name() + ".condPredicted")
929554Sandreas.hansson@arm.com        .desc("Number of conditional branches predicted")
939554Sandreas.hansson@arm.com        ;
949554Sandreas.hansson@arm.com
959554Sandreas.hansson@arm.com    condIncorrect
969554Sandreas.hansson@arm.com        .name(name() + ".condIncorrect")
979554Sandreas.hansson@arm.com        .desc("Number of conditional branches incorrect")
984661Sksewell@umich.edu        ;
996376Sgblack@eecs.umich.edu
1006376Sgblack@eecs.umich.edu    BTBLookups
1016376Sgblack@eecs.umich.edu        .name(name() + ".BTBLookups")
1026376Sgblack@eecs.umich.edu        .desc("Number of BTB lookups")
1034661Sksewell@umich.edu        ;
1046383Sgblack@eecs.umich.edu
1056383Sgblack@eecs.umich.edu    BTBHits
1066383Sgblack@eecs.umich.edu        .name(name() + ".BTBHits")
1076383Sgblack@eecs.umich.edu        .desc("Number of BTB hits")
1086383Sgblack@eecs.umich.edu        ;
1094661Sksewell@umich.edu
1104661Sksewell@umich.edu    BTBCorrect
1116376Sgblack@eecs.umich.edu        .name(name() + ".BTBCorrect")
1124661Sksewell@umich.edu        .desc("Number of correct BTB predictions (this stat may not "
1136383Sgblack@eecs.umich.edu              "work properly.")
1144661Sksewell@umich.edu        ;
1154661Sksewell@umich.edu
1164661Sksewell@umich.edu    BTBHitPct
1174661Sksewell@umich.edu        .name(name() + ".BTBHitPct")
1184661Sksewell@umich.edu        .desc("BTB Hit Percentage")
1192686Sksewell@umich.edu        .precision(6);
1204661Sksewell@umich.edu    BTBHitPct = (BTBHits / BTBLookups) * 100;
1218607Sgblack@eecs.umich.edu
1224661Sksewell@umich.edu    usedRAS
1234661Sksewell@umich.edu        .name(name() + ".usedRAS")
1244661Sksewell@umich.edu        .desc("Number of times the RAS was used to get a target.")
1256376Sgblack@eecs.umich.edu        ;
1266376Sgblack@eecs.umich.edu
1276376Sgblack@eecs.umich.edu    RASIncorrect
1286376Sgblack@eecs.umich.edu        .name(name() + ".RASInCorrect")
1296376Sgblack@eecs.umich.edu        .desc("Number of incorrect RAS predictions.")
1304661Sksewell@umich.edu        ;
1316376Sgblack@eecs.umich.edu
1326376Sgblack@eecs.umich.edu    indirectLookups
1334661Sksewell@umich.edu        .name(name() + ".indirectLookups")
1344661Sksewell@umich.edu        .desc("Number of indirect predictor lookups.")
1356376Sgblack@eecs.umich.edu        ;
1364661Sksewell@umich.edu
1376376Sgblack@eecs.umich.edu    indirectHits
1384661Sksewell@umich.edu        .name(name() + ".indirectHits")
1394661Sksewell@umich.edu        .desc("Number of indirect target hits.")
1404661Sksewell@umich.edu        ;
1414661Sksewell@umich.edu
1424661Sksewell@umich.edu    indirectMisses
1435222Sksewell@umich.edu        .name(name() + ".indirectMisses")
1444661Sksewell@umich.edu        .desc("Number of indirect misses.")
1454661Sksewell@umich.edu        ;
1464661Sksewell@umich.edu
1474661Sksewell@umich.edu    indirectMispredicted
1484661Sksewell@umich.edu        .name(name() + "indirectMispredicted")
1494661Sksewell@umich.edu        .desc("Number of mispredicted indirect branches.")
1504661Sksewell@umich.edu        ;
1514661Sksewell@umich.edu
1522686Sksewell@umich.edu}
1532686Sksewell@umich.edu
1542686Sksewell@umich.eduProbePoints::PMUUPtr
1554661Sksewell@umich.eduBPredUnit::pmuProbePoint(const char *name)
1562686Sksewell@umich.edu{
1572686Sksewell@umich.edu    ProbePoints::PMUUPtr ptr;
1584661Sksewell@umich.edu    ptr.reset(new ProbePoints::PMU(getProbeManager(), name));
1594661Sksewell@umich.edu
1604661Sksewell@umich.edu    return ptr;
1612686Sksewell@umich.edu}
1626376Sgblack@eecs.umich.edu
1634661Sksewell@umich.eduvoid
1644661Sksewell@umich.eduBPredUnit::regProbePoints()
1654661Sksewell@umich.edu{
1664661Sksewell@umich.edu    ppBranches = pmuProbePoint("Branches");
1676376Sgblack@eecs.umich.edu    ppMisses = pmuProbePoint("Misses");
1684661Sksewell@umich.edu}
1694661Sksewell@umich.edu
1704661Sksewell@umich.eduvoid
1714661Sksewell@umich.eduBPredUnit::drainSanityCheck() const
1724661Sksewell@umich.edu{
1735222Sksewell@umich.edu    // We shouldn't have any outstanding requests when we resume from
1744661Sksewell@umich.edu    // a drained system.
1754661Sksewell@umich.edu    for (const auto& ph M5_VAR_USED : predHist)
1764661Sksewell@umich.edu        assert(ph.empty());
1774661Sksewell@umich.edu}
1784661Sksewell@umich.edu
1794661Sksewell@umich.edubool
1804661Sksewell@umich.eduBPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
1812686Sksewell@umich.edu                   TheISA::PCState &pc, ThreadID tid)
1822686Sksewell@umich.edu{
1832686Sksewell@umich.edu    // See if branch predictor predicts taken.
1842686Sksewell@umich.edu    // If so, get its target addr either from the BTB or the RAS.
1854661Sksewell@umich.edu    // Save off record of branch stuff so the RAS can be fixed
1864661Sksewell@umich.edu    // up once it's done.
1874661Sksewell@umich.edu
1884661Sksewell@umich.edu    bool pred_taken = false;
1894661Sksewell@umich.edu    TheISA::PCState target = pc;
1904661Sksewell@umich.edu
1914661Sksewell@umich.edu    ++lookups;
1924661Sksewell@umich.edu    ppBranches->notify(1);
1934661Sksewell@umich.edu
1944661Sksewell@umich.edu    void *bp_history = NULL;
1954661Sksewell@umich.edu
1962686Sksewell@umich.edu    if (inst->isUncondCtrl()) {
1972686Sksewell@umich.edu        DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid);
1982686Sksewell@umich.edu        pred_taken = true;
1994661Sksewell@umich.edu        // Tell the BP there was an unconditional branch.
2002686Sksewell@umich.edu        uncondBranch(tid, pc.instAddr(), bp_history);
2014661Sksewell@umich.edu    } else {
2024661Sksewell@umich.edu        ++condPredicted;
2034661Sksewell@umich.edu        pred_taken = lookup(tid, pc.instAddr(), bp_history);
2047823Ssteve.reinhardt@amd.com
2054661Sksewell@umich.edu        DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
2068607Sgblack@eecs.umich.edu                " predicted %i for PC %s\n", tid, seqNum,  pred_taken, pc);
2078607Sgblack@eecs.umich.edu    }
2088607Sgblack@eecs.umich.edu
2098607Sgblack@eecs.umich.edu    DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history "
2108607Sgblack@eecs.umich.edu            "for PC %s\n", tid, seqNum, pc);
2114661Sksewell@umich.edu
2124661Sksewell@umich.edu    PredictorHistory predict_record(seqNum, pc.instAddr(),
2134661Sksewell@umich.edu                                    pred_taken, bp_history, tid, inst);
2144661Sksewell@umich.edu
2154661Sksewell@umich.edu    // Now lookup in the BTB or RAS.
2164661Sksewell@umich.edu    if (pred_taken) {
2174661Sksewell@umich.edu        if (inst->isReturn()) {
2184661Sksewell@umich.edu            ++usedRAS;
2194661Sksewell@umich.edu            predict_record.wasReturn = true;
2204661Sksewell@umich.edu            // If it's a function return call, then look up the address
2217823Ssteve.reinhardt@amd.com            // in the RAS.
2224661Sksewell@umich.edu            TheISA::PCState rasTop = RAS[tid].top();
2234661Sksewell@umich.edu            target = TheISA::buildRetPC(pc, rasTop);
2244661Sksewell@umich.edu
2254661Sksewell@umich.edu            // Record the top entry of the RAS, and its index.
2264661Sksewell@umich.edu            predict_record.usedRAS = true;
2274661Sksewell@umich.edu            predict_record.RASIndex = RAS[tid].topIdx();
228            predict_record.RASTarget = rasTop;
229
230            RAS[tid].pop();
231
232            DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, "
233                    "RAS predicted target: %s, RAS index: %i.\n",
234                    tid, pc, target, predict_record.RASIndex);
235        } else {
236            ++BTBLookups;
237
238            if (inst->isCall()) {
239                RAS[tid].push(pc);
240                predict_record.pushedRAS = true;
241
242                // Record that it was a call so that the top RAS entry can
243                // be popped off if the speculation is incorrect.
244                predict_record.wasCall = true;
245
246                DPRINTF(Branch, "[tid:%i]: Instruction %s was a "
247                        "call, adding %s to the RAS index: %i.\n",
248                        tid, pc, pc, RAS[tid].topIdx());
249            }
250
251            if (inst->isDirectCtrl() || !useIndirect) {
252                // Check BTB on direct branches
253                if (BTB.valid(pc.instAddr(), tid)) {
254                    ++BTBHits;
255
256                    // If it's not a return, use the BTB to get target addr.
257                    target = BTB.lookup(pc.instAddr(), tid);
258
259                    DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
260                            " target is %s.\n", tid, pc, target);
261
262                } else {
263                    DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
264                            "valid entry.\n",tid);
265                    pred_taken = false;
266                    // The Direction of the branch predictor is altered
267                    // because the BTB did not have an entry
268                    // 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    predict_record.target = target.instAddr();
313
314    pc = target;
315
316    predHist[tid].push_front(predict_record);
317
318    DPRINTF(Branch, "[tid:%i]: [sn:%i]: History entry added."
319            "predHist.size(): %i\n", tid, seqNum, predHist[tid].size());
320
321    return pred_taken;
322}
323
324void
325BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
326{
327    DPRINTF(Branch, "[tid:%i]: Committing branches until "
328            "[sn:%lli].\n", tid, done_sn);
329
330    iPred.commit(done_sn, tid);
331    while (!predHist[tid].empty() &&
332           predHist[tid].back().seqNum <= done_sn) {
333        // Update the branch predictor with the correct results.
334        update(tid, predHist[tid].back().pc,
335                    predHist[tid].back().predTaken,
336                    predHist[tid].back().bpHistory, false,
337                    predHist[tid].back().inst,
338                    predHist[tid].back().target);
339
340        predHist[tid].pop_back();
341    }
342}
343
344void
345BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
346{
347    History &pred_hist = predHist[tid];
348
349    iPred.squash(squashed_sn, tid);
350    while (!pred_hist.empty() &&
351           pred_hist.front().seqNum > squashed_sn) {
352        if (pred_hist.front().usedRAS) {
353            DPRINTF(Branch, "[tid:%i]: Restoring top of RAS to: %i,"
354                    " target: %s.\n", tid,
355                    pred_hist.front().RASIndex, pred_hist.front().RASTarget);
356
357            RAS[tid].restore(pred_hist.front().RASIndex,
358                             pred_hist.front().RASTarget);
359        } else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
360             // Was a call but predicated false. Pop RAS here
361             DPRINTF(Branch, "[tid: %i] Squashing"
362                     "  Call [sn:%i] PC: %s Popping RAS\n", tid,
363                     pred_hist.front().seqNum, pred_hist.front().pc);
364             RAS[tid].pop();
365        }
366
367        // This call should delete the bpHistory.
368        squash(tid, pred_hist.front().bpHistory);
369
370        DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] "
371                "PC %s.\n", tid, pred_hist.front().seqNum,
372                pred_hist.front().pc);
373
374        pred_hist.pop_front();
375
376        DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n",
377                tid, predHist[tid].size());
378    }
379}
380
381void
382BPredUnit::squash(const InstSeqNum &squashed_sn,
383                  const TheISA::PCState &corrTarget,
384                  bool actually_taken, ThreadID tid)
385{
386    // Now that we know that a branch was mispredicted, we need to undo
387    // all the branches that have been seen up until this branch and
388    // fix up everything.
389    // NOTE: This should be call conceivably in 2 scenarios:
390    // (1) After an branch is executed, it updates its status in the ROB
391    //     The commit stage then checks the ROB update and sends a signal to
392    //     the fetch stage to squash history after the mispredict
393    // (2) In the decode stage, you can find out early if a unconditional
394    //     PC-relative, branch was predicted incorrectly. If so, a signal
395    //     to the fetch stage is sent to squash history after the mispredict
396
397    History &pred_hist = predHist[tid];
398
399    ++condIncorrect;
400    ppMisses->notify(1);
401
402    DPRINTF(Branch, "[tid:%i]: Squashing from sequence number %i, "
403            "setting target to %s.\n", tid, squashed_sn, corrTarget);
404
405    // Squash All Branches AFTER this mispredicted branch
406    squash(squashed_sn, tid);
407
408    // If there's a squash due to a syscall, there may not be an entry
409    // corresponding to the squash.  In that case, don't bother trying to
410    // fix up the entry.
411    if (!pred_hist.empty()) {
412
413        auto hist_it = pred_hist.begin();
414        //HistoryIt hist_it = find(pred_hist.begin(), pred_hist.end(),
415        //                       squashed_sn);
416
417        //assert(hist_it != pred_hist.end());
418        if (pred_hist.front().seqNum != squashed_sn) {
419            DPRINTF(Branch, "Front sn %i != Squash sn %i\n",
420                    pred_hist.front().seqNum, squashed_sn);
421
422            assert(pred_hist.front().seqNum == squashed_sn);
423        }
424
425
426        if ((*hist_it).usedRAS) {
427            ++RASIncorrect;
428            DPRINTF(Branch, "[tid:%i]: Incorrect RAS [sn:%i]\n",
429                    tid, hist_it->seqNum);
430        }
431
432        // Get the underlying Global History Register
433        unsigned ghr = getGHR(tid, hist_it->bpHistory);
434
435        // There are separate functions for in-order and out-of-order
436        // branch prediction, but not for update. Therefore, this
437        // call should take into account that the mispredicted branch may
438        // be on the wrong path (i.e., OoO execution), and that the counter
439        // counter table(s) should not be updated. Thus, this call should
440        // restore the state of the underlying predictor, for instance the
441        // local/global histories. The counter tables will be updated when
442        // the branch actually commits.
443
444        // Remember the correct direction for the update at commit.
445        pred_hist.front().predTaken = actually_taken;
446        pred_hist.front().target = corrTarget.instAddr();
447
448        update(tid, (*hist_it).pc, actually_taken,
449               pred_hist.front().bpHistory, true, pred_hist.front().inst,
450               corrTarget.instAddr());
451
452        if (actually_taken) {
453            if (hist_it->wasReturn && !hist_it->usedRAS) {
454                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
455                         "  return [sn:%i] PC: %s\n", tid, hist_it->seqNum,
456                         hist_it->pc);
457                 RAS[tid].pop();
458                 hist_it->usedRAS = true;
459            }
460            if (hist_it->wasIndirect) {
461                ++indirectMispredicted;
462                iPred.recordTarget(hist_it->seqNum, ghr, corrTarget, tid);
463            } else {
464                DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]"
465                        " PC: %s\n", tid,hist_it->seqNum, hist_it->pc);
466
467                BTB.update((*hist_it).pc, corrTarget, tid);
468            }
469        } else {
470           //Actually not Taken
471           if (hist_it->usedRAS) {
472                DPRINTF(Branch,"[tid: %i] Incorrectly predicted"
473                        "  return [sn:%i] PC: %s Restoring RAS\n", tid,
474                        hist_it->seqNum, hist_it->pc);
475                DPRINTF(Branch, "[tid:%i]: Restoring top of RAS"
476                        " to: %i, target: %s.\n", tid,
477                        hist_it->RASIndex, hist_it->RASTarget);
478                RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget);
479                hist_it->usedRAS = false;
480           } else if (hist_it->wasCall && hist_it->pushedRAS) {
481                 //Was a Call but predicated false. Pop RAS here
482                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
483                         "  Call [sn:%i] PC: %s Popping RAS\n", tid,
484                         hist_it->seqNum, hist_it->pc);
485                 RAS[tid].pop();
486                 hist_it->pushedRAS = false;
487           }
488        }
489    } else {
490        DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't "
491                "update.\n", tid, squashed_sn);
492    }
493}
494
495void
496BPredUnit::dump()
497{
498    int i = 0;
499    for (const auto& ph : predHist) {
500        if (!ph.empty()) {
501            auto pred_hist_it = ph.begin();
502
503            cprintf("predHist[%i].size(): %i\n", i++, ph.size());
504
505            while (pred_hist_it != ph.end()) {
506                cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
507                        "bpHistory:%#x\n",
508                        pred_hist_it->seqNum, pred_hist_it->pc,
509                        pred_hist_it->tid, pred_hist_it->predTaken,
510                        pred_hist_it->bpHistory);
511                pred_hist_it++;
512            }
513
514            cprintf("\n");
515        }
516    }
517}
518
519