tournament.cc revision 13626
16184SN/A/*
210330Smitch.hayenga@arm.com * Copyright (c) 2011, 2014 ARM Limited
38842Smrinmoy.ghosh@arm.com * All rights reserved
48842Smrinmoy.ghosh@arm.com *
58842Smrinmoy.ghosh@arm.com * The license below extends only to copyright in the software and shall
68842Smrinmoy.ghosh@arm.com * not be construed as granting a license to any other intellectual
78842Smrinmoy.ghosh@arm.com * property including but not limited to intellectual property relating
88842Smrinmoy.ghosh@arm.com * to a hardware implementation of the functionality of the software
98842Smrinmoy.ghosh@arm.com * licensed hereunder.  You may use the software subject to the license
108842Smrinmoy.ghosh@arm.com * terms below provided that you ensure that this notice is replicated
118842Smrinmoy.ghosh@arm.com * unmodified and in its entirety in all distributions of the software,
128842Smrinmoy.ghosh@arm.com * modified or unmodified, in source code or in binary form.
138842Smrinmoy.ghosh@arm.com *
146184SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan
156184SN/A * All rights reserved.
166184SN/A *
176184SN/A * Redistribution and use in source and binary forms, with or without
186184SN/A * modification, are permitted provided that the following conditions are
196184SN/A * met: redistributions of source code must retain the above copyright
206184SN/A * notice, this list of conditions and the following disclaimer;
216184SN/A * redistributions in binary form must reproduce the above copyright
226184SN/A * notice, this list of conditions and the following disclaimer in the
236184SN/A * documentation and/or other materials provided with the distribution;
246184SN/A * neither the name of the copyright holders nor the names of its
256184SN/A * contributors may be used to endorse or promote products derived from
266184SN/A * this software without specific prior written permission.
276184SN/A *
286184SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
296184SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
306184SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
316184SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
326184SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
336184SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346184SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
356184SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
366184SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376184SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386184SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396184SN/A *
406184SN/A * Authors: Kevin Lim
416184SN/A */
426184SN/A
4311793Sbrandon.potter@amd.com#include "cpu/pred/tournament.hh"
4411793Sbrandon.potter@amd.com
459360SE.Tomusk@sms.ed.ac.uk#include "base/bitfield.hh"
466184SN/A#include "base/intmath.hh"
476184SN/A
4810785Sgope@wisc.eduTournamentBP::TournamentBP(const TournamentBPParams *params)
499480Snilay@cs.wisc.edu    : BPredUnit(params),
509691Satgutier@umich.edu      localPredictorSize(params->localPredictorSize),
519480Snilay@cs.wisc.edu      localCtrBits(params->localCtrBits),
529480Snilay@cs.wisc.edu      localHistoryTableSize(params->localHistoryTableSize),
539691Satgutier@umich.edu      localHistoryBits(ceilLog2(params->localPredictorSize)),
549480Snilay@cs.wisc.edu      globalPredictorSize(params->globalPredictorSize),
559480Snilay@cs.wisc.edu      globalCtrBits(params->globalCtrBits),
5611434Smitch.hayenga@arm.com      globalHistory(params->numThreads, 0),
579691Satgutier@umich.edu      globalHistoryBits(
589691Satgutier@umich.edu          ceilLog2(params->globalPredictorSize) >
599691Satgutier@umich.edu          ceilLog2(params->choicePredictorSize) ?
609691Satgutier@umich.edu          ceilLog2(params->globalPredictorSize) :
619691Satgutier@umich.edu          ceilLog2(params->choicePredictorSize)),
629480Snilay@cs.wisc.edu      choicePredictorSize(params->choicePredictorSize),
6310785Sgope@wisc.edu      choiceCtrBits(params->choiceCtrBits)
646184SN/A{
659691Satgutier@umich.edu    if (!isPowerOf2(localPredictorSize)) {
669691Satgutier@umich.edu        fatal("Invalid local predictor size!\n");
679691Satgutier@umich.edu    }
689691Satgutier@umich.edu
699691Satgutier@umich.edu    if (!isPowerOf2(globalPredictorSize)) {
709691Satgutier@umich.edu        fatal("Invalid global predictor size!\n");
719691Satgutier@umich.edu    }
726184SN/A
739360SE.Tomusk@sms.ed.ac.uk    //Set up the array of counters for the local predictor
746184SN/A    localCtrs.resize(localPredictorSize);
756184SN/A
766184SN/A    for (int i = 0; i < localPredictorSize; ++i)
776184SN/A        localCtrs[i].setBits(localCtrBits);
786184SN/A
799360SE.Tomusk@sms.ed.ac.uk    localPredictorMask = mask(localHistoryBits);
806184SN/A
816184SN/A    if (!isPowerOf2(localHistoryTableSize)) {
826184SN/A        fatal("Invalid local history table size!\n");
836184SN/A    }
846184SN/A
856184SN/A    //Setup the history table for the local table
866184SN/A    localHistoryTable.resize(localHistoryTableSize);
876184SN/A
886184SN/A    for (int i = 0; i < localHistoryTableSize; ++i)
896184SN/A        localHistoryTable[i] = 0;
906184SN/A
916184SN/A    //Setup the array of counters for the global predictor
926184SN/A    globalCtrs.resize(globalPredictorSize);
936184SN/A
946184SN/A    for (int i = 0; i < globalPredictorSize; ++i)
956184SN/A        globalCtrs[i].setBits(globalCtrBits);
966184SN/A
979360SE.Tomusk@sms.ed.ac.uk    // Set up the global history mask
989360SE.Tomusk@sms.ed.ac.uk    // this is equivalent to mask(log2(globalPredictorSize)
999360SE.Tomusk@sms.ed.ac.uk    globalHistoryMask = globalPredictorSize - 1;
1006184SN/A
1016184SN/A    if (!isPowerOf2(choicePredictorSize)) {
1026184SN/A        fatal("Invalid choice predictor size!\n");
1036184SN/A    }
1046184SN/A
1059360SE.Tomusk@sms.ed.ac.uk    // Set up choiceHistoryMask
1069360SE.Tomusk@sms.ed.ac.uk    // this is equivalent to mask(log2(choicePredictorSize)
1079360SE.Tomusk@sms.ed.ac.uk    choiceHistoryMask = choicePredictorSize - 1;
1089360SE.Tomusk@sms.ed.ac.uk
1096184SN/A    //Setup the array of counters for the choice predictor
1106184SN/A    choiceCtrs.resize(choicePredictorSize);
1116184SN/A
1126184SN/A    for (int i = 0; i < choicePredictorSize; ++i)
1136184SN/A        choiceCtrs[i].setBits(choiceCtrBits);
1146184SN/A
1159360SE.Tomusk@sms.ed.ac.uk    //Set up historyRegisterMask
1169360SE.Tomusk@sms.ed.ac.uk    historyRegisterMask = mask(globalHistoryBits);
1179360SE.Tomusk@sms.ed.ac.uk
1189360SE.Tomusk@sms.ed.ac.uk    //Check that predictors don't use more bits than they have available
1199360SE.Tomusk@sms.ed.ac.uk    if (globalHistoryMask > historyRegisterMask) {
1209360SE.Tomusk@sms.ed.ac.uk        fatal("Global predictor too large for global history bits!\n");
1219360SE.Tomusk@sms.ed.ac.uk    }
1229360SE.Tomusk@sms.ed.ac.uk    if (choiceHistoryMask > historyRegisterMask) {
1239360SE.Tomusk@sms.ed.ac.uk        fatal("Choice predictor too large for global history bits!\n");
1249360SE.Tomusk@sms.ed.ac.uk    }
1259360SE.Tomusk@sms.ed.ac.uk
1269360SE.Tomusk@sms.ed.ac.uk    if (globalHistoryMask < historyRegisterMask &&
1279360SE.Tomusk@sms.ed.ac.uk        choiceHistoryMask < historyRegisterMask) {
1289360SE.Tomusk@sms.ed.ac.uk        inform("More global history bits than required by predictors\n");
1299360SE.Tomusk@sms.ed.ac.uk    }
1309360SE.Tomusk@sms.ed.ac.uk
1319360SE.Tomusk@sms.ed.ac.uk    // Set thresholds for the three predictors' counters
1329360SE.Tomusk@sms.ed.ac.uk    // This is equivalent to (2^(Ctr))/2 - 1
1339360SE.Tomusk@sms.ed.ac.uk    localThreshold  = (ULL(1) << (localCtrBits  - 1)) - 1;
1349360SE.Tomusk@sms.ed.ac.uk    globalThreshold = (ULL(1) << (globalCtrBits - 1)) - 1;
1359360SE.Tomusk@sms.ed.ac.uk    choiceThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
1366184SN/A}
1376184SN/A
1386184SN/Ainline
1396184SN/Aunsigned
1406184SN/ATournamentBP::calcLocHistIdx(Addr &branch_addr)
1416184SN/A{
1426184SN/A    // Get low order bits after removing instruction offset.
1436184SN/A    return (branch_addr >> instShiftAmt) & (localHistoryTableSize - 1);
1446184SN/A}
1456184SN/A
1466184SN/Ainline
1476184SN/Avoid
14811434Smitch.hayenga@arm.comTournamentBP::updateGlobalHistTaken(ThreadID tid)
1496184SN/A{
15011434Smitch.hayenga@arm.com    globalHistory[tid] = (globalHistory[tid] << 1) | 1;
15111434Smitch.hayenga@arm.com    globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
1526184SN/A}
1536184SN/A
1546184SN/Ainline
1556184SN/Avoid
15611434Smitch.hayenga@arm.comTournamentBP::updateGlobalHistNotTaken(ThreadID tid)
1576184SN/A{
15811434Smitch.hayenga@arm.com    globalHistory[tid] = (globalHistory[tid] << 1);
15911434Smitch.hayenga@arm.com    globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
1606184SN/A}
1616184SN/A
1626184SN/Ainline
1636184SN/Avoid
1646184SN/ATournamentBP::updateLocalHistTaken(unsigned local_history_idx)
1656184SN/A{
1666184SN/A    localHistoryTable[local_history_idx] =
1676184SN/A        (localHistoryTable[local_history_idx] << 1) | 1;
1686184SN/A}
1696184SN/A
1706184SN/Ainline
1716184SN/Avoid
1726184SN/ATournamentBP::updateLocalHistNotTaken(unsigned local_history_idx)
1736184SN/A{
1746184SN/A    localHistoryTable[local_history_idx] =
1756184SN/A        (localHistoryTable[local_history_idx] << 1);
1766184SN/A}
1776184SN/A
1788842Smrinmoy.ghosh@arm.com
1798842Smrinmoy.ghosh@arm.comvoid
18011434Smitch.hayenga@arm.comTournamentBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history)
1818842Smrinmoy.ghosh@arm.com{
1828842Smrinmoy.ghosh@arm.com    unsigned local_history_idx = calcLocHistIdx(branch_addr);
1839360SE.Tomusk@sms.ed.ac.uk    //Update Global History to Not Taken (clear LSB)
18411434Smitch.hayenga@arm.com    globalHistory[tid] &= (historyRegisterMask & ~ULL(1));
1858842Smrinmoy.ghosh@arm.com    //Update Local History to Not Taken
1868842Smrinmoy.ghosh@arm.com    localHistoryTable[local_history_idx] =
1879327Smrinmoy.ghosh@arm.com       localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1));
1888842Smrinmoy.ghosh@arm.com}
1898842Smrinmoy.ghosh@arm.com
1906184SN/Abool
19111434Smitch.hayenga@arm.comTournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history)
1926184SN/A{
1936184SN/A    bool local_prediction;
1946184SN/A    unsigned local_history_idx;
1956184SN/A    unsigned local_predictor_idx;
1966184SN/A
1976184SN/A    bool global_prediction;
1986184SN/A    bool choice_prediction;
1996184SN/A
2006184SN/A    //Lookup in the local predictor to get its branch prediction
2016184SN/A    local_history_idx = calcLocHistIdx(branch_addr);
2026184SN/A    local_predictor_idx = localHistoryTable[local_history_idx]
2036184SN/A        & localPredictorMask;
2049360SE.Tomusk@sms.ed.ac.uk    local_prediction = localCtrs[local_predictor_idx].read() > localThreshold;
2056184SN/A
2066184SN/A    //Lookup in the global predictor to get its branch prediction
20711434Smitch.hayenga@arm.com    global_prediction = globalThreshold <
20811434Smitch.hayenga@arm.com      globalCtrs[globalHistory[tid] & globalHistoryMask].read();
2096184SN/A
2106184SN/A    //Lookup in the choice predictor to see which one to use
21111434Smitch.hayenga@arm.com    choice_prediction = choiceThreshold <
21211434Smitch.hayenga@arm.com      choiceCtrs[globalHistory[tid] & choiceHistoryMask].read();
2136184SN/A
2146184SN/A    // Create BPHistory and pass it back to be recorded.
2156184SN/A    BPHistory *history = new BPHistory;
21611434Smitch.hayenga@arm.com    history->globalHistory = globalHistory[tid];
2176184SN/A    history->localPredTaken = local_prediction;
2186184SN/A    history->globalPredTaken = global_prediction;
2196184SN/A    history->globalUsed = choice_prediction;
22011098Slukefahr@umich.edu    history->localHistoryIdx = local_history_idx;
2218842Smrinmoy.ghosh@arm.com    history->localHistory = local_predictor_idx;
2226184SN/A    bp_history = (void *)history;
2236184SN/A
2249360SE.Tomusk@sms.ed.ac.uk    assert(local_history_idx < localHistoryTableSize);
2256184SN/A
22611782Sarthur.perais@inria.fr    // Speculative update of the global history and the
22711782Sarthur.perais@inria.fr    // selected local history.
2286184SN/A    if (choice_prediction) {
2296184SN/A        if (global_prediction) {
23011434Smitch.hayenga@arm.com            updateGlobalHistTaken(tid);
2318842Smrinmoy.ghosh@arm.com            updateLocalHistTaken(local_history_idx);
2326184SN/A            return true;
2336184SN/A        } else {
23411434Smitch.hayenga@arm.com            updateGlobalHistNotTaken(tid);
2358842Smrinmoy.ghosh@arm.com            updateLocalHistNotTaken(local_history_idx);
2366184SN/A            return false;
2376184SN/A        }
2386184SN/A    } else {
2396184SN/A        if (local_prediction) {
24011434Smitch.hayenga@arm.com            updateGlobalHistTaken(tid);
2418842Smrinmoy.ghosh@arm.com            updateLocalHistTaken(local_history_idx);
2426184SN/A            return true;
2436184SN/A        } else {
24411434Smitch.hayenga@arm.com            updateGlobalHistNotTaken(tid);
2458842Smrinmoy.ghosh@arm.com            updateLocalHistNotTaken(local_history_idx);
2466184SN/A            return false;
2476184SN/A        }
2486184SN/A    }
2496184SN/A}
2506184SN/A
2516184SN/Avoid
25211434Smitch.hayenga@arm.comTournamentBP::uncondBranch(ThreadID tid, Addr pc, void * &bp_history)
2536184SN/A{
2546184SN/A    // Create BPHistory and pass it back to be recorded.
2556184SN/A    BPHistory *history = new BPHistory;
25611434Smitch.hayenga@arm.com    history->globalHistory = globalHistory[tid];
2576184SN/A    history->localPredTaken = true;
2586184SN/A    history->globalPredTaken = true;
2598487SAli.Saidi@ARM.com    history->globalUsed = true;
26011098Slukefahr@umich.edu    history->localHistoryIdx = invalidPredictorIndex;
2618842Smrinmoy.ghosh@arm.com    history->localHistory = invalidPredictorIndex;
2626184SN/A    bp_history = static_cast<void *>(history);
2636184SN/A
26411434Smitch.hayenga@arm.com    updateGlobalHistTaken(tid);
2656184SN/A}
2666184SN/A
2676184SN/Avoid
26811434Smitch.hayenga@arm.comTournamentBP::update(ThreadID tid, Addr branch_addr, bool taken,
26913626Sjairo.balart@metempsy.com                     void *bp_history, bool squashed,
27013626Sjairo.balart@metempsy.com                     const StaticInstPtr & inst, Addr corrTarget)
2716184SN/A{
27211783Sarthur.perais@inria.fr    assert(bp_history);
2736184SN/A
27411783Sarthur.perais@inria.fr    BPHistory *history = static_cast<BPHistory *>(bp_history);
2756184SN/A
27611783Sarthur.perais@inria.fr    unsigned local_history_idx = calcLocHistIdx(branch_addr);
2776184SN/A
2789360SE.Tomusk@sms.ed.ac.uk    assert(local_history_idx < localHistoryTableSize);
2796184SN/A
28011783Sarthur.perais@inria.fr    // Unconditional branches do not use local history.
28111783Sarthur.perais@inria.fr    bool old_local_pred_valid = history->localHistory !=
28211783Sarthur.perais@inria.fr            invalidPredictorIndex;
2836184SN/A
28411783Sarthur.perais@inria.fr    // If this is a misprediction, restore the speculatively
28511783Sarthur.perais@inria.fr    // updated state (global history register and local history)
28611783Sarthur.perais@inria.fr    // and update again.
28711783Sarthur.perais@inria.fr    if (squashed) {
28811783Sarthur.perais@inria.fr        // Global history restore and update
28911783Sarthur.perais@inria.fr        globalHistory[tid] = (history->globalHistory << 1) | taken;
29011783Sarthur.perais@inria.fr        globalHistory[tid] &= historyRegisterMask;
2916184SN/A
29211783Sarthur.perais@inria.fr        // Local history restore and update.
29311783Sarthur.perais@inria.fr        if (old_local_pred_valid) {
29411783Sarthur.perais@inria.fr            localHistoryTable[local_history_idx] =
29511783Sarthur.perais@inria.fr                        (history->localHistory << 1) | taken;
29611783Sarthur.perais@inria.fr        }
29711783Sarthur.perais@inria.fr
29811783Sarthur.perais@inria.fr        return;
29911783Sarthur.perais@inria.fr    }
30011783Sarthur.perais@inria.fr
30111783Sarthur.perais@inria.fr    unsigned old_local_pred_index = history->localHistory &
30211783Sarthur.perais@inria.fr        localPredictorMask;
30311783Sarthur.perais@inria.fr
30411783Sarthur.perais@inria.fr    assert(old_local_pred_index < localPredictorSize);
30511783Sarthur.perais@inria.fr
30611783Sarthur.perais@inria.fr    // Update the choice predictor to tell it which one was correct if
30711783Sarthur.perais@inria.fr    // there was a prediction.
30811783Sarthur.perais@inria.fr    if (history->localPredTaken != history->globalPredTaken &&
30911783Sarthur.perais@inria.fr        old_local_pred_valid)
31011783Sarthur.perais@inria.fr    {
31111783Sarthur.perais@inria.fr         // If the local prediction matches the actual outcome,
31211783Sarthur.perais@inria.fr         // decrement the counter. Otherwise increment the
31311783Sarthur.perais@inria.fr         // counter.
31411783Sarthur.perais@inria.fr         unsigned choice_predictor_idx =
31511783Sarthur.perais@inria.fr           history->globalHistory & choiceHistoryMask;
31611783Sarthur.perais@inria.fr         if (history->localPredTaken == taken) {
31711783Sarthur.perais@inria.fr             choiceCtrs[choice_predictor_idx].decrement();
31811783Sarthur.perais@inria.fr         } else if (history->globalPredTaken == taken) {
31911783Sarthur.perais@inria.fr             choiceCtrs[choice_predictor_idx].increment();
32011783Sarthur.perais@inria.fr         }
32111783Sarthur.perais@inria.fr    }
32211783Sarthur.perais@inria.fr
32311783Sarthur.perais@inria.fr    // Update the counters with the proper
32411783Sarthur.perais@inria.fr    // resolution of the branch. Histories are updated
32511783Sarthur.perais@inria.fr    // speculatively, restored upon squash() calls, and
32611783Sarthur.perais@inria.fr    // recomputed upon update(squash = true) calls,
32711783Sarthur.perais@inria.fr    // so they do not need to be updated.
32811783Sarthur.perais@inria.fr    unsigned global_predictor_idx =
32911783Sarthur.perais@inria.fr            history->globalHistory & globalHistoryMask;
33011783Sarthur.perais@inria.fr    if (taken) {
33111783Sarthur.perais@inria.fr          globalCtrs[global_predictor_idx].increment();
33211783Sarthur.perais@inria.fr          if (old_local_pred_valid) {
33311783Sarthur.perais@inria.fr                 localCtrs[old_local_pred_index].increment();
33411783Sarthur.perais@inria.fr          }
33511783Sarthur.perais@inria.fr    } else {
33611783Sarthur.perais@inria.fr          globalCtrs[global_predictor_idx].decrement();
33711783Sarthur.perais@inria.fr          if (old_local_pred_valid) {
33811783Sarthur.perais@inria.fr              localCtrs[old_local_pred_index].decrement();
33911783Sarthur.perais@inria.fr          }
34011783Sarthur.perais@inria.fr    }
34111783Sarthur.perais@inria.fr
34211783Sarthur.perais@inria.fr    // We're done with this history, now delete it.
34310330Smitch.hayenga@arm.com    delete history;
34410330Smitch.hayenga@arm.com}
34510330Smitch.hayenga@arm.com
34610330Smitch.hayenga@arm.comvoid
34711434Smitch.hayenga@arm.comTournamentBP::squash(ThreadID tid, void *bp_history)
3486184SN/A{
3496184SN/A    BPHistory *history = static_cast<BPHistory *>(bp_history);
3506184SN/A
3516184SN/A    // Restore global history to state prior to this branch.
35211434Smitch.hayenga@arm.com    globalHistory[tid] = history->globalHistory;
3536184SN/A
35411098Slukefahr@umich.edu    // Restore local history
35511098Slukefahr@umich.edu    if (history->localHistoryIdx != invalidPredictorIndex) {
35611098Slukefahr@umich.edu        localHistoryTable[history->localHistoryIdx] = history->localHistory;
35711098Slukefahr@umich.edu    }
35811098Slukefahr@umich.edu
3596184SN/A    // Delete this BPHistory now that we're done with it.
3606184SN/A    delete history;
3616184SN/A}
3626184SN/A
36310785Sgope@wisc.eduTournamentBP*
36410785Sgope@wisc.eduTournamentBPParams::create()
36510785Sgope@wisc.edu{
36610785Sgope@wisc.edu    return new TournamentBP(this);
36710785Sgope@wisc.edu}
36810785Sgope@wisc.edu
36911433Smitch.hayenga@arm.comunsigned
37011434Smitch.hayenga@arm.comTournamentBP::getGHR(ThreadID tid, void *bp_history) const
37111433Smitch.hayenga@arm.com{
37211433Smitch.hayenga@arm.com    return static_cast<BPHistory *>(bp_history)->globalHistory;
37311433Smitch.hayenga@arm.com}
37411433Smitch.hayenga@arm.com
3756184SN/A#ifdef DEBUG
3766184SN/Aint
3776184SN/ATournamentBP::BPHistory::newCount = 0;
3786184SN/A#endif
379