bi_mode.cc revision 11783
110244Satgutier@umich.edu/*
210244Satgutier@umich.edu * Copyright (c) 2014 The Regents of The University of Michigan
310244Satgutier@umich.edu * All rights reserved.
410244Satgutier@umich.edu *
510244Satgutier@umich.edu * Redistribution and use in source and binary forms, with or without
610244Satgutier@umich.edu * modification, are permitted provided that the following conditions are
710244Satgutier@umich.edu * met: redistributions of source code must retain the above copyright
810244Satgutier@umich.edu * notice, this list of conditions and the following disclaimer;
910244Satgutier@umich.edu * redistributions in binary form must reproduce the above copyright
1010244Satgutier@umich.edu * notice, this list of conditions and the following disclaimer in the
1110244Satgutier@umich.edu * documentation and/or other materials provided with the distribution;
1210244Satgutier@umich.edu * neither the name of the copyright holders nor the names of its
1310244Satgutier@umich.edu * contributors may be used to endorse or promote products derived from
1410244Satgutier@umich.edu * this software without specific prior written permission.
1510244Satgutier@umich.edu *
1610244Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710244Satgutier@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810244Satgutier@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910244Satgutier@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010244Satgutier@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110244Satgutier@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210244Satgutier@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310244Satgutier@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410244Satgutier@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510244Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610244Satgutier@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710244Satgutier@umich.edu *
2810244Satgutier@umich.edu * Authors: Anthony Gutierrez
2910244Satgutier@umich.edu */
3010244Satgutier@umich.edu
3110244Satgutier@umich.edu/* @file
3210244Satgutier@umich.edu * Implementation of a bi-mode branch predictor
3310244Satgutier@umich.edu */
3410244Satgutier@umich.edu
3510244Satgutier@umich.edu#include "base/bitfield.hh"
3610244Satgutier@umich.edu#include "base/intmath.hh"
3710244Satgutier@umich.edu#include "cpu/pred/bi_mode.hh"
3810244Satgutier@umich.edu
3910785Sgope@wisc.eduBiModeBP::BiModeBP(const BiModeBPParams *params)
4010785Sgope@wisc.edu    : BPredUnit(params),
4111434Smitch.hayenga@arm.com      globalHistoryReg(params->numThreads, 0),
4210244Satgutier@umich.edu      globalHistoryBits(ceilLog2(params->globalPredictorSize)),
4310244Satgutier@umich.edu      choicePredictorSize(params->choicePredictorSize),
4410244Satgutier@umich.edu      choiceCtrBits(params->choiceCtrBits),
4510244Satgutier@umich.edu      globalPredictorSize(params->globalPredictorSize),
4610244Satgutier@umich.edu      globalCtrBits(params->globalCtrBits)
4710244Satgutier@umich.edu{
4810244Satgutier@umich.edu    if (!isPowerOf2(choicePredictorSize))
4910244Satgutier@umich.edu        fatal("Invalid choice predictor size.\n");
5010244Satgutier@umich.edu    if (!isPowerOf2(globalPredictorSize))
5110244Satgutier@umich.edu        fatal("Invalid global history predictor size.\n");
5210244Satgutier@umich.edu
5310244Satgutier@umich.edu    choiceCounters.resize(choicePredictorSize);
5410244Satgutier@umich.edu    takenCounters.resize(globalPredictorSize);
5510244Satgutier@umich.edu    notTakenCounters.resize(globalPredictorSize);
5610244Satgutier@umich.edu
5710244Satgutier@umich.edu    for (int i = 0; i < choicePredictorSize; ++i) {
5810244Satgutier@umich.edu        choiceCounters[i].setBits(choiceCtrBits);
5910244Satgutier@umich.edu    }
6010244Satgutier@umich.edu    for (int i = 0; i < globalPredictorSize; ++i) {
6110244Satgutier@umich.edu        takenCounters[i].setBits(globalCtrBits);
6210244Satgutier@umich.edu        notTakenCounters[i].setBits(globalCtrBits);
6310244Satgutier@umich.edu    }
6410244Satgutier@umich.edu
6510244Satgutier@umich.edu    historyRegisterMask = mask(globalHistoryBits);
6610244Satgutier@umich.edu    choiceHistoryMask = choicePredictorSize - 1;
6710244Satgutier@umich.edu    globalHistoryMask = globalPredictorSize - 1;
6810244Satgutier@umich.edu
6910244Satgutier@umich.edu    choiceThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
7010244Satgutier@umich.edu    takenThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
7110244Satgutier@umich.edu    notTakenThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
7210244Satgutier@umich.edu}
7310244Satgutier@umich.edu
7410244Satgutier@umich.edu/*
7510244Satgutier@umich.edu * For an unconditional branch we set its history such that
7610244Satgutier@umich.edu * everything is set to taken. I.e., its choice predictor
7710244Satgutier@umich.edu * chooses the taken array and the taken array predicts taken.
7810244Satgutier@umich.edu */
7910244Satgutier@umich.eduvoid
8011434Smitch.hayenga@arm.comBiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bpHistory)
8110244Satgutier@umich.edu{
8210244Satgutier@umich.edu    BPHistory *history = new BPHistory;
8311434Smitch.hayenga@arm.com    history->globalHistoryReg = globalHistoryReg[tid];
8410244Satgutier@umich.edu    history->takenUsed = true;
8510244Satgutier@umich.edu    history->takenPred = true;
8610244Satgutier@umich.edu    history->notTakenPred = true;
8710244Satgutier@umich.edu    history->finalPred = true;
8810244Satgutier@umich.edu    bpHistory = static_cast<void*>(history);
8911434Smitch.hayenga@arm.com    updateGlobalHistReg(tid, true);
9010244Satgutier@umich.edu}
9110244Satgutier@umich.edu
9210244Satgutier@umich.eduvoid
9311434Smitch.hayenga@arm.comBiModeBP::squash(ThreadID tid, void *bpHistory)
9410244Satgutier@umich.edu{
9510244Satgutier@umich.edu    BPHistory *history = static_cast<BPHistory*>(bpHistory);
9611434Smitch.hayenga@arm.com    globalHistoryReg[tid] = history->globalHistoryReg;
9710244Satgutier@umich.edu
9810244Satgutier@umich.edu    delete history;
9910244Satgutier@umich.edu}
10010244Satgutier@umich.edu
10110244Satgutier@umich.edu/*
10210244Satgutier@umich.edu * Here we lookup the actual branch prediction. We use the PC to
10310244Satgutier@umich.edu * identify the bias of a particular branch, which is based on the
10410244Satgutier@umich.edu * prediction in the choice array. A hash of the global history
10510244Satgutier@umich.edu * register and a branch's PC is used to index into both the taken
10610244Satgutier@umich.edu * and not-taken predictors, which both present a prediction. The
10710244Satgutier@umich.edu * choice array's prediction is used to select between the two
10810244Satgutier@umich.edu * direction predictors for the final branch prediction.
10910244Satgutier@umich.edu */
11010244Satgutier@umich.edubool
11111434Smitch.hayenga@arm.comBiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory)
11210244Satgutier@umich.edu{
11310244Satgutier@umich.edu    unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
11410244Satgutier@umich.edu                                & choiceHistoryMask);
11510244Satgutier@umich.edu    unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
11611434Smitch.hayenga@arm.com                                ^ globalHistoryReg[tid])
11710244Satgutier@umich.edu                                & globalHistoryMask);
11810244Satgutier@umich.edu
11910244Satgutier@umich.edu    assert(choiceHistoryIdx < choicePredictorSize);
12010244Satgutier@umich.edu    assert(globalHistoryIdx < globalPredictorSize);
12110244Satgutier@umich.edu
12210244Satgutier@umich.edu    bool choicePrediction = choiceCounters[choiceHistoryIdx].read()
12310244Satgutier@umich.edu                            > choiceThreshold;
12410244Satgutier@umich.edu    bool takenGHBPrediction = takenCounters[globalHistoryIdx].read()
12510244Satgutier@umich.edu                              > takenThreshold;
12610244Satgutier@umich.edu    bool notTakenGHBPrediction = notTakenCounters[globalHistoryIdx].read()
12710244Satgutier@umich.edu                                 > notTakenThreshold;
12810244Satgutier@umich.edu    bool finalPrediction;
12910244Satgutier@umich.edu
13010244Satgutier@umich.edu    BPHistory *history = new BPHistory;
13111434Smitch.hayenga@arm.com    history->globalHistoryReg = globalHistoryReg[tid];
13210244Satgutier@umich.edu    history->takenUsed = choicePrediction;
13310244Satgutier@umich.edu    history->takenPred = takenGHBPrediction;
13410244Satgutier@umich.edu    history->notTakenPred = notTakenGHBPrediction;
13510244Satgutier@umich.edu
13610244Satgutier@umich.edu    if (choicePrediction) {
13710244Satgutier@umich.edu        finalPrediction = takenGHBPrediction;
13810244Satgutier@umich.edu    } else {
13910244Satgutier@umich.edu        finalPrediction = notTakenGHBPrediction;
14010244Satgutier@umich.edu    }
14110244Satgutier@umich.edu
14210244Satgutier@umich.edu    history->finalPred = finalPrediction;
14310244Satgutier@umich.edu    bpHistory = static_cast<void*>(history);
14411434Smitch.hayenga@arm.com    updateGlobalHistReg(tid, finalPrediction);
14510244Satgutier@umich.edu
14610244Satgutier@umich.edu    return finalPrediction;
14710244Satgutier@umich.edu}
14810244Satgutier@umich.edu
14910244Satgutier@umich.eduvoid
15011434Smitch.hayenga@arm.comBiModeBP::btbUpdate(ThreadID tid, Addr branchAddr, void * &bpHistory)
15110244Satgutier@umich.edu{
15211434Smitch.hayenga@arm.com    globalHistoryReg[tid] &= (historyRegisterMask & ~ULL(1));
15310244Satgutier@umich.edu}
15410244Satgutier@umich.edu
15510244Satgutier@umich.edu/* Only the selected direction predictor will be updated with the final
15610244Satgutier@umich.edu * outcome; the status of the unselected one will not be altered. The choice
15710244Satgutier@umich.edu * predictor is always updated with the branch outcome, except when the
15810244Satgutier@umich.edu * choice is opposite to the branch outcome but the selected counter of
15910244Satgutier@umich.edu * the direction predictors makes a correct final prediction.
16010244Satgutier@umich.edu */
16110244Satgutier@umich.eduvoid
16211434Smitch.hayenga@arm.comBiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory,
16311434Smitch.hayenga@arm.com                 bool squashed)
16410244Satgutier@umich.edu{
16511783Sarthur.perais@inria.fr    assert(bpHistory);
16610244Satgutier@umich.edu
16711783Sarthur.perais@inria.fr    BPHistory *history = static_cast<BPHistory*>(bpHistory);
16810244Satgutier@umich.edu
16911783Sarthur.perais@inria.fr    // We do not update the counters speculatively on a squash.
17011783Sarthur.perais@inria.fr    // We just restore the global history register.
17111783Sarthur.perais@inria.fr    if (squashed) {
17211783Sarthur.perais@inria.fr        globalHistoryReg[tid] = (history->globalHistoryReg << 1) | taken;
17311783Sarthur.perais@inria.fr        return;
17411783Sarthur.perais@inria.fr    }
17510244Satgutier@umich.edu
17611783Sarthur.perais@inria.fr    unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
17711783Sarthur.perais@inria.fr                                & choiceHistoryMask);
17811783Sarthur.perais@inria.fr    unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
17911783Sarthur.perais@inria.fr                                ^ history->globalHistoryReg)
18011783Sarthur.perais@inria.fr                                & globalHistoryMask);
18111783Sarthur.perais@inria.fr
18211783Sarthur.perais@inria.fr    assert(choiceHistoryIdx < choicePredictorSize);
18311783Sarthur.perais@inria.fr    assert(globalHistoryIdx < globalPredictorSize);
18411783Sarthur.perais@inria.fr
18511783Sarthur.perais@inria.fr    if (history->takenUsed) {
18611783Sarthur.perais@inria.fr        // if the taken array's prediction was used, update it
18711783Sarthur.perais@inria.fr        if (taken) {
18811783Sarthur.perais@inria.fr            takenCounters[globalHistoryIdx].increment();
18910244Satgutier@umich.edu        } else {
19011783Sarthur.perais@inria.fr            takenCounters[globalHistoryIdx].decrement();
19110244Satgutier@umich.edu        }
19211783Sarthur.perais@inria.fr    } else {
19311783Sarthur.perais@inria.fr        // if the not-taken array's prediction was used, update it
19411783Sarthur.perais@inria.fr        if (taken) {
19511783Sarthur.perais@inria.fr            notTakenCounters[globalHistoryIdx].increment();
19611783Sarthur.perais@inria.fr        } else {
19711783Sarthur.perais@inria.fr            notTakenCounters[globalHistoryIdx].decrement();
19811783Sarthur.perais@inria.fr        }
19911783Sarthur.perais@inria.fr    }
20010244Satgutier@umich.edu
20111783Sarthur.perais@inria.fr    if (history->finalPred == taken) {
20211783Sarthur.perais@inria.fr       /* If the final prediction matches the actual branch's
20311783Sarthur.perais@inria.fr        * outcome and the choice predictor matches the final
20411783Sarthur.perais@inria.fr        * outcome, we update the choice predictor, otherwise it
20511783Sarthur.perais@inria.fr        * is not updated. While the designers of the bi-mode
20611783Sarthur.perais@inria.fr        * predictor don't explicity say why this is done, one
20711783Sarthur.perais@inria.fr        * can infer that it is to preserve the choice predictor's
20811783Sarthur.perais@inria.fr        * bias with respect to the branch being predicted; afterall,
20911783Sarthur.perais@inria.fr        * the whole point of the bi-mode predictor is to identify the
21011783Sarthur.perais@inria.fr        * atypical case when a branch deviates from its bias.
21111783Sarthur.perais@inria.fr        */
21211783Sarthur.perais@inria.fr        if (history->finalPred == history->takenUsed) {
21310244Satgutier@umich.edu            if (taken) {
21410244Satgutier@umich.edu                choiceCounters[choiceHistoryIdx].increment();
21510244Satgutier@umich.edu            } else {
21610244Satgutier@umich.edu                choiceCounters[choiceHistoryIdx].decrement();
21710244Satgutier@umich.edu            }
21810244Satgutier@umich.edu        }
21911783Sarthur.perais@inria.fr    } else {
22011783Sarthur.perais@inria.fr        // always update the choice predictor on an incorrect prediction
22111783Sarthur.perais@inria.fr        if (taken) {
22211783Sarthur.perais@inria.fr            choiceCounters[choiceHistoryIdx].increment();
22310244Satgutier@umich.edu        } else {
22411783Sarthur.perais@inria.fr            choiceCounters[choiceHistoryIdx].decrement();
22510244Satgutier@umich.edu        }
22610244Satgutier@umich.edu    }
22710244Satgutier@umich.edu
22810244Satgutier@umich.edu    delete history;
22910244Satgutier@umich.edu}
23010244Satgutier@umich.edu
23111433Smitch.hayenga@arm.comunsigned
23211434Smitch.hayenga@arm.comBiModeBP::getGHR(ThreadID tid, void *bp_history) const
23311433Smitch.hayenga@arm.com{
23411433Smitch.hayenga@arm.com    return static_cast<BPHistory*>(bp_history)->globalHistoryReg;
23511433Smitch.hayenga@arm.com}
23611433Smitch.hayenga@arm.com
23711429Sandreas.sandberg@arm.comvoid
23811434Smitch.hayenga@arm.comBiModeBP::updateGlobalHistReg(ThreadID tid, bool taken)
23911426Smitch.hayenga@arm.com{
24011434Smitch.hayenga@arm.com    globalHistoryReg[tid] = taken ? (globalHistoryReg[tid] << 1) | 1 :
24111434Smitch.hayenga@arm.com                               (globalHistoryReg[tid] << 1);
24211434Smitch.hayenga@arm.com    globalHistoryReg[tid] &= historyRegisterMask;
24310244Satgutier@umich.edu}
24410785Sgope@wisc.edu
24510785Sgope@wisc.eduBiModeBP*
24610785Sgope@wisc.eduBiModeBPParams::create()
24710785Sgope@wisc.edu{
24810785Sgope@wisc.edu    return new BiModeBP(this);
24910785Sgope@wisc.edu}
250