ltage.cc revision 13443
111784Sarthur.perais@inria.fr/*
211784Sarthur.perais@inria.fr * Copyright (c) 2014 The University of Wisconsin
311784Sarthur.perais@inria.fr *
411784Sarthur.perais@inria.fr * Copyright (c) 2006 INRIA (Institut National de Recherche en
511784Sarthur.perais@inria.fr * Informatique et en Automatique  / French National Research Institute
611784Sarthur.perais@inria.fr * for Computer Science and Applied Mathematics)
711784Sarthur.perais@inria.fr *
811784Sarthur.perais@inria.fr * All rights reserved.
911784Sarthur.perais@inria.fr *
1011784Sarthur.perais@inria.fr * Redistribution and use in source and binary forms, with or without
1111784Sarthur.perais@inria.fr * modification, are permitted provided that the following conditions are
1211784Sarthur.perais@inria.fr * met: redistributions of source code must retain the above copyright
1311784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer;
1411784Sarthur.perais@inria.fr * redistributions in binary form must reproduce the above copyright
1511784Sarthur.perais@inria.fr * notice, this list of conditions and the following disclaimer in the
1611784Sarthur.perais@inria.fr * documentation and/or other materials provided with the distribution;
1711784Sarthur.perais@inria.fr * neither the name of the copyright holders nor the names of its
1811784Sarthur.perais@inria.fr * contributors may be used to endorse or promote products derived from
1911784Sarthur.perais@inria.fr * this software without specific prior written permission.
2011784Sarthur.perais@inria.fr *
2111784Sarthur.perais@inria.fr * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2211784Sarthur.perais@inria.fr * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2311784Sarthur.perais@inria.fr * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2411784Sarthur.perais@inria.fr * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2511784Sarthur.perais@inria.fr * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2611784Sarthur.perais@inria.fr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2711784Sarthur.perais@inria.fr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2811784Sarthur.perais@inria.fr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2911784Sarthur.perais@inria.fr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3011784Sarthur.perais@inria.fr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3111784Sarthur.perais@inria.fr * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3211784Sarthur.perais@inria.fr *
3311784Sarthur.perais@inria.fr * Authors: Vignyan Reddy, Dibakar Gope and Arthur Perais,
3411784Sarthur.perais@inria.fr * from André Seznec's code.
3511784Sarthur.perais@inria.fr */
3611784Sarthur.perais@inria.fr
3711784Sarthur.perais@inria.fr/* @file
3811784Sarthur.perais@inria.fr * Implementation of a L-TAGE branch predictor
3911784Sarthur.perais@inria.fr */
4011784Sarthur.perais@inria.fr
4111784Sarthur.perais@inria.fr#include "cpu/pred/ltage.hh"
4211784Sarthur.perais@inria.fr
4311784Sarthur.perais@inria.fr#include "base/intmath.hh"
4412334Sgabeblack@google.com#include "base/logging.hh"
4511784Sarthur.perais@inria.fr#include "base/random.hh"
4611784Sarthur.perais@inria.fr#include "base/trace.hh"
4711784Sarthur.perais@inria.fr#include "debug/Fetch.hh"
4811784Sarthur.perais@inria.fr#include "debug/LTage.hh"
4911784Sarthur.perais@inria.fr
5011784Sarthur.perais@inria.frLTAGE::LTAGE(const LTAGEParams *params)
5111784Sarthur.perais@inria.fr  : BPredUnit(params),
5211784Sarthur.perais@inria.fr    logSizeBiMP(params->logSizeBiMP),
5313420Spau.cabre@metempsy.com    logRatioBiModalHystEntries(params->logRatioBiModalHystEntries),
5411784Sarthur.perais@inria.fr    logSizeTagTables(params->logSizeTagTables),
5511784Sarthur.perais@inria.fr    logSizeLoopPred(params->logSizeLoopPred),
5611784Sarthur.perais@inria.fr    nHistoryTables(params->nHistoryTables),
5711784Sarthur.perais@inria.fr    tagTableCounterBits(params->tagTableCounterBits),
5813443Spau.cabre@metempsy.com    tagTableUBits(params->tagTableUBits),
5911784Sarthur.perais@inria.fr    histBufferSize(params->histBufferSize),
6011784Sarthur.perais@inria.fr    minHist(params->minHist),
6111784Sarthur.perais@inria.fr    maxHist(params->maxHist),
6211784Sarthur.perais@inria.fr    minTagWidth(params->minTagWidth),
6313442Spau.cabre@metempsy.com    loopTableAgeBits(params->loopTableAgeBits),
6413442Spau.cabre@metempsy.com    loopTableConfidenceBits(params->loopTableConfidenceBits),
6513442Spau.cabre@metempsy.com    loopTableTagBits(params->loopTableTagBits),
6613442Spau.cabre@metempsy.com    loopTableIterBits(params->loopTableIterBits),
6713442Spau.cabre@metempsy.com    confidenceThreshold((1 << loopTableConfidenceBits) - 1),
6813442Spau.cabre@metempsy.com    loopTagMask((1 << loopTableTagBits) - 1),
6913442Spau.cabre@metempsy.com    loopNumIterMask((1 << loopTableIterBits) - 1),
7011784Sarthur.perais@inria.fr    threadHistory(params->numThreads)
7111784Sarthur.perais@inria.fr{
7213443Spau.cabre@metempsy.com    // Current method for periodically resetting the u counter bits only
7313443Spau.cabre@metempsy.com    // works for 1 or 2 bits
7413443Spau.cabre@metempsy.com    // Also make sure that it is not 0
7513443Spau.cabre@metempsy.com    assert(tagTableUBits <= 2 && (tagTableUBits > 0));
7613443Spau.cabre@metempsy.com
7713442Spau.cabre@metempsy.com    // we use uint16_t type for these vales, so they cannot be more than
7813442Spau.cabre@metempsy.com    // 16 bits
7913442Spau.cabre@metempsy.com    assert(loopTableTagBits <= 16);
8013442Spau.cabre@metempsy.com    assert(loopTableIterBits <= 16);
8113442Spau.cabre@metempsy.com
8211784Sarthur.perais@inria.fr    assert(params->histBufferSize > params->maxHist * 2);
8311784Sarthur.perais@inria.fr    useAltPredForNewlyAllocated = 0;
8411784Sarthur.perais@inria.fr    logTick = 19;
8511784Sarthur.perais@inria.fr    tCounter = ULL(1) << (logTick - 1);
8611784Sarthur.perais@inria.fr
8711784Sarthur.perais@inria.fr    for (auto& history : threadHistory) {
8811784Sarthur.perais@inria.fr        history.pathHist = 0;
8911784Sarthur.perais@inria.fr        history.globalHistory = new uint8_t[histBufferSize];
9011784Sarthur.perais@inria.fr        history.gHist = history.globalHistory;
9111784Sarthur.perais@inria.fr        memset(history.gHist, 0, histBufferSize);
9211784Sarthur.perais@inria.fr        history.ptGhist = 0;
9311784Sarthur.perais@inria.fr    }
9411784Sarthur.perais@inria.fr
9511784Sarthur.perais@inria.fr    histLengths = new int [nHistoryTables+1];
9611784Sarthur.perais@inria.fr    histLengths[1] = minHist;
9711784Sarthur.perais@inria.fr    histLengths[nHistoryTables] = maxHist;
9811784Sarthur.perais@inria.fr
9911784Sarthur.perais@inria.fr    for (int i = 2; i <= nHistoryTables; i++) {
10011784Sarthur.perais@inria.fr        histLengths[i] = (int) (((double) minHist *
10111784Sarthur.perais@inria.fr                    pow ((double) (maxHist) / (double) minHist,
10211784Sarthur.perais@inria.fr                        (double) (i - 1) / (double) ((nHistoryTables- 1))))
10311784Sarthur.perais@inria.fr                    + 0.5);
10411784Sarthur.perais@inria.fr    }
10511784Sarthur.perais@inria.fr
10611784Sarthur.perais@inria.fr    tagWidths[1] = minTagWidth;
10711784Sarthur.perais@inria.fr    tagWidths[2] = minTagWidth;
10811784Sarthur.perais@inria.fr    tagWidths[3] = minTagWidth + 1;
10911784Sarthur.perais@inria.fr    tagWidths[4] = minTagWidth + 1;
11011784Sarthur.perais@inria.fr    tagWidths[5] = minTagWidth + 2;
11111784Sarthur.perais@inria.fr    tagWidths[6] = minTagWidth + 3;
11211784Sarthur.perais@inria.fr    tagWidths[7] = minTagWidth + 4;
11311784Sarthur.perais@inria.fr    tagWidths[8] = minTagWidth + 5;
11411784Sarthur.perais@inria.fr    tagWidths[9] = minTagWidth + 5;
11511784Sarthur.perais@inria.fr    tagWidths[10] = minTagWidth + 6;
11611784Sarthur.perais@inria.fr    tagWidths[11] = minTagWidth + 7;
11711784Sarthur.perais@inria.fr    tagWidths[12] = minTagWidth + 8;
11811784Sarthur.perais@inria.fr
11911784Sarthur.perais@inria.fr    for (int i = 1; i <= 2; i++)
12011784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables - 1;
12111784Sarthur.perais@inria.fr    for (int i = 3; i <= 6; i++)
12211784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables;
12311784Sarthur.perais@inria.fr    for (int i = 7; i <= 10; i++)
12411784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables - 1;
12511784Sarthur.perais@inria.fr    for (int i = 11; i <= 12; i++)
12611784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables - 2;
12711784Sarthur.perais@inria.fr
12811784Sarthur.perais@inria.fr    for (auto& history : threadHistory) {
12911784Sarthur.perais@inria.fr        history.computeIndices = new FoldedHistory[nHistoryTables+1];
13011784Sarthur.perais@inria.fr        history.computeTags[0] = new FoldedHistory[nHistoryTables+1];
13111784Sarthur.perais@inria.fr        history.computeTags[1] = new FoldedHistory[nHistoryTables+1];
13211784Sarthur.perais@inria.fr
13311784Sarthur.perais@inria.fr        for (int i = 1; i <= nHistoryTables; i++) {
13411784Sarthur.perais@inria.fr            history.computeIndices[i].init(histLengths[i], (tagTableSizes[i]));
13511784Sarthur.perais@inria.fr            history.computeTags[0][i].init(
13611784Sarthur.perais@inria.fr                history.computeIndices[i].origLength, tagWidths[i]);
13711784Sarthur.perais@inria.fr            history.computeTags[1][i].init(
13811784Sarthur.perais@inria.fr                history.computeIndices[i].origLength, tagWidths[i] - 1);
13911784Sarthur.perais@inria.fr            DPRINTF(LTage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n",
14011784Sarthur.perais@inria.fr                    histLengths[i], tagTableSizes[i], tagWidths[i]);
14111784Sarthur.perais@inria.fr        }
14211784Sarthur.perais@inria.fr    }
14311784Sarthur.perais@inria.fr
14413420Spau.cabre@metempsy.com    const uint64_t bimodalTableSize = ULL(1) << logSizeBiMP;
14513420Spau.cabre@metempsy.com    btablePrediction.resize(bimodalTableSize, false);
14613420Spau.cabre@metempsy.com    btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries,
14713420Spau.cabre@metempsy.com                            true);
14813420Spau.cabre@metempsy.com
14911784Sarthur.perais@inria.fr    ltable = new LoopEntry[ULL(1) << logSizeLoopPred];
15011784Sarthur.perais@inria.fr    gtable = new TageEntry*[nHistoryTables + 1];
15111784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++) {
15211784Sarthur.perais@inria.fr        gtable[i] = new TageEntry[1<<(tagTableSizes[i])];
15311784Sarthur.perais@inria.fr    }
15411784Sarthur.perais@inria.fr
15511784Sarthur.perais@inria.fr    tableIndices = new int [nHistoryTables+1];
15611784Sarthur.perais@inria.fr    tableTags = new int [nHistoryTables+1];
15711784Sarthur.perais@inria.fr
15811784Sarthur.perais@inria.fr    loopUseCounter = 0;
15911784Sarthur.perais@inria.fr}
16011784Sarthur.perais@inria.fr
16111784Sarthur.perais@inria.frint
16211784Sarthur.perais@inria.frLTAGE::bindex(Addr pc_in) const
16311784Sarthur.perais@inria.fr{
16413413Spau.cabre@metempsy.com    return ((pc_in >> instShiftAmt) & ((ULL(1) << (logSizeBiMP)) - 1));
16511784Sarthur.perais@inria.fr}
16611784Sarthur.perais@inria.fr
16711784Sarthur.perais@inria.frint
16811784Sarthur.perais@inria.frLTAGE::lindex(Addr pc_in) const
16911784Sarthur.perais@inria.fr{
17013413Spau.cabre@metempsy.com    return (((pc_in >> instShiftAmt) &
17113413Spau.cabre@metempsy.com             ((ULL(1) << (logSizeLoopPred - 2)) - 1)) << 2);
17211784Sarthur.perais@inria.fr}
17311784Sarthur.perais@inria.fr
17411784Sarthur.perais@inria.frint
17511784Sarthur.perais@inria.frLTAGE::F(int A, int size, int bank) const
17611784Sarthur.perais@inria.fr{
17711784Sarthur.perais@inria.fr    int A1, A2;
17811784Sarthur.perais@inria.fr
17911784Sarthur.perais@inria.fr    A = A & ((ULL(1) << size) - 1);
18011784Sarthur.perais@inria.fr    A1 = (A & ((ULL(1) << tagTableSizes[bank]) - 1));
18111784Sarthur.perais@inria.fr    A2 = (A >> tagTableSizes[bank]);
18211784Sarthur.perais@inria.fr    A2 = ((A2 << bank) & ((ULL(1) << tagTableSizes[bank]) - 1))
18311784Sarthur.perais@inria.fr       + (A2 >> (tagTableSizes[bank] - bank));
18411784Sarthur.perais@inria.fr    A = A1 ^ A2;
18511784Sarthur.perais@inria.fr    A = ((A << bank) & ((ULL(1) << tagTableSizes[bank]) - 1))
18611784Sarthur.perais@inria.fr      + (A >> (tagTableSizes[bank] - bank));
18711784Sarthur.perais@inria.fr    return (A);
18811784Sarthur.perais@inria.fr}
18911784Sarthur.perais@inria.fr
19011784Sarthur.perais@inria.fr
19111784Sarthur.perais@inria.fr// gindex computes a full hash of pc, ghist and pathHist
19211784Sarthur.perais@inria.frint
19311784Sarthur.perais@inria.frLTAGE::gindex(ThreadID tid, Addr pc, int bank) const
19411784Sarthur.perais@inria.fr{
19511784Sarthur.perais@inria.fr    int index;
19611784Sarthur.perais@inria.fr    int hlen = (histLengths[bank] > 16) ? 16 : histLengths[bank];
19711784Sarthur.perais@inria.fr    index =
19813413Spau.cabre@metempsy.com        (pc >> instShiftAmt) ^
19913413Spau.cabre@metempsy.com        ((pc >> instShiftAmt) >> ((int) abs(tagTableSizes[bank] - bank) + 1)) ^
20011784Sarthur.perais@inria.fr        threadHistory[tid].computeIndices[bank].comp ^
20111784Sarthur.perais@inria.fr        F(threadHistory[tid].pathHist, hlen, bank);
20211784Sarthur.perais@inria.fr
20311784Sarthur.perais@inria.fr    return (index & ((ULL(1) << (tagTableSizes[bank])) - 1));
20411784Sarthur.perais@inria.fr}
20511784Sarthur.perais@inria.fr
20611784Sarthur.perais@inria.fr
20711784Sarthur.perais@inria.fr// Tag computation
20811784Sarthur.perais@inria.fruint16_t
20911784Sarthur.perais@inria.frLTAGE::gtag(ThreadID tid, Addr pc, int bank) const
21011784Sarthur.perais@inria.fr{
21113413Spau.cabre@metempsy.com    int tag = (pc >> instShiftAmt) ^
21213413Spau.cabre@metempsy.com              threadHistory[tid].computeTags[0][bank].comp ^
21313413Spau.cabre@metempsy.com              (threadHistory[tid].computeTags[1][bank].comp << 1);
21411784Sarthur.perais@inria.fr
21511784Sarthur.perais@inria.fr    return (tag & ((ULL(1) << tagWidths[bank]) - 1));
21611784Sarthur.perais@inria.fr}
21711784Sarthur.perais@inria.fr
21811784Sarthur.perais@inria.fr
21911784Sarthur.perais@inria.fr// Up-down saturating counter
22011784Sarthur.perais@inria.frvoid
22111784Sarthur.perais@inria.frLTAGE::ctrUpdate(int8_t & ctr, bool taken, int nbits)
22211784Sarthur.perais@inria.fr{
22311784Sarthur.perais@inria.fr    assert(nbits <= sizeof(int8_t) << 3);
22411784Sarthur.perais@inria.fr    if (taken) {
22511784Sarthur.perais@inria.fr        if (ctr < ((1 << (nbits - 1)) - 1))
22611784Sarthur.perais@inria.fr            ctr++;
22711784Sarthur.perais@inria.fr    } else {
22811784Sarthur.perais@inria.fr        if (ctr > -(1 << (nbits - 1)))
22911784Sarthur.perais@inria.fr            ctr--;
23011784Sarthur.perais@inria.fr    }
23111784Sarthur.perais@inria.fr}
23211784Sarthur.perais@inria.fr
23313442Spau.cabre@metempsy.com// Up-down unsigned saturating counter
23413442Spau.cabre@metempsy.comvoid
23513442Spau.cabre@metempsy.comLTAGE::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits)
23613442Spau.cabre@metempsy.com{
23713442Spau.cabre@metempsy.com    assert(nbits <= sizeof(uint8_t) << 3);
23813442Spau.cabre@metempsy.com    if (up) {
23913442Spau.cabre@metempsy.com        if (ctr < ((1 << nbits) - 1))
24013442Spau.cabre@metempsy.com            ctr++;
24113442Spau.cabre@metempsy.com    } else {
24213442Spau.cabre@metempsy.com        if (ctr)
24313442Spau.cabre@metempsy.com            ctr--;
24413442Spau.cabre@metempsy.com    }
24513442Spau.cabre@metempsy.com}
24613442Spau.cabre@metempsy.com
24711784Sarthur.perais@inria.fr// Bimodal prediction
24811784Sarthur.perais@inria.frbool
24911784Sarthur.perais@inria.frLTAGE::getBimodePred(Addr pc, BranchInfo* bi) const
25011784Sarthur.perais@inria.fr{
25113420Spau.cabre@metempsy.com    return btablePrediction[bi->bimodalIndex];
25211784Sarthur.perais@inria.fr}
25311784Sarthur.perais@inria.fr
25411784Sarthur.perais@inria.fr
25513420Spau.cabre@metempsy.com// Update the bimodal predictor: a hysteresis bit is shared among N prediction
25613420Spau.cabre@metempsy.com// bits (N = 2 ^ logRatioBiModalHystEntries)
25711784Sarthur.perais@inria.frvoid
25811784Sarthur.perais@inria.frLTAGE::baseUpdate(Addr pc, bool taken, BranchInfo* bi)
25911784Sarthur.perais@inria.fr{
26013420Spau.cabre@metempsy.com    int inter = (btablePrediction[bi->bimodalIndex] << 1)
26113420Spau.cabre@metempsy.com        + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries];
26211784Sarthur.perais@inria.fr    if (taken) {
26311784Sarthur.perais@inria.fr        if (inter < 3)
26411784Sarthur.perais@inria.fr            inter++;
26511784Sarthur.perais@inria.fr    } else if (inter > 0) {
26611784Sarthur.perais@inria.fr        inter--;
26711784Sarthur.perais@inria.fr    }
26813420Spau.cabre@metempsy.com    const bool pred = inter >> 1;
26913420Spau.cabre@metempsy.com    const bool hyst = inter & 1;
27013420Spau.cabre@metempsy.com    btablePrediction[bi->bimodalIndex] = pred;
27113420Spau.cabre@metempsy.com    btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst;
27213420Spau.cabre@metempsy.com    DPRINTF(LTage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst);
27311784Sarthur.perais@inria.fr}
27411784Sarthur.perais@inria.fr
27511784Sarthur.perais@inria.fr
27611784Sarthur.perais@inria.fr//loop prediction: only used if high confidence
27711784Sarthur.perais@inria.frbool
27811784Sarthur.perais@inria.frLTAGE::getLoop(Addr pc, BranchInfo* bi) const
27911784Sarthur.perais@inria.fr{
28011784Sarthur.perais@inria.fr    bi->loopHit = -1;
28111784Sarthur.perais@inria.fr    bi->loopPredValid = false;
28211784Sarthur.perais@inria.fr    bi->loopIndex = lindex(pc);
28313442Spau.cabre@metempsy.com    bi->loopTag = ((pc) >> (instShiftAmt + logSizeLoopPred - 2)) & loopTagMask;
28411784Sarthur.perais@inria.fr
28511784Sarthur.perais@inria.fr    for (int i = 0; i < 4; i++) {
28611784Sarthur.perais@inria.fr        if (ltable[bi->loopIndex + i].tag == bi->loopTag) {
28711784Sarthur.perais@inria.fr            bi->loopHit = i;
28813442Spau.cabre@metempsy.com            bi->loopPredValid =
28913442Spau.cabre@metempsy.com                ltable[bi->loopIndex + i].confidence == confidenceThreshold;
29011784Sarthur.perais@inria.fr            bi->currentIter = ltable[bi->loopIndex + i].currentIterSpec;
29111784Sarthur.perais@inria.fr            if (ltable[bi->loopIndex + i].currentIterSpec + 1 ==
29211784Sarthur.perais@inria.fr                ltable[bi->loopIndex + i].numIter) {
29311784Sarthur.perais@inria.fr                return !(ltable[bi->loopIndex + i].dir);
29411784Sarthur.perais@inria.fr            }else {
29511784Sarthur.perais@inria.fr                return (ltable[bi->loopIndex + i].dir);
29611784Sarthur.perais@inria.fr            }
29711784Sarthur.perais@inria.fr        }
29811784Sarthur.perais@inria.fr    }
29911784Sarthur.perais@inria.fr    return false;
30011784Sarthur.perais@inria.fr}
30111784Sarthur.perais@inria.fr
30211784Sarthur.perais@inria.frvoid
30311784Sarthur.perais@inria.frLTAGE::specLoopUpdate(Addr pc, bool taken, BranchInfo* bi)
30411784Sarthur.perais@inria.fr{
30511784Sarthur.perais@inria.fr    if (bi->loopHit>=0) {
30611784Sarthur.perais@inria.fr        int index = lindex(pc);
30711784Sarthur.perais@inria.fr        if (taken != ltable[index].dir) {
30811784Sarthur.perais@inria.fr            ltable[index].currentIterSpec = 0;
30911784Sarthur.perais@inria.fr        } else {
31013442Spau.cabre@metempsy.com            ltable[index].currentIterSpec =
31113442Spau.cabre@metempsy.com                (ltable[index].currentIterSpec + 1) & loopNumIterMask;
31211784Sarthur.perais@inria.fr        }
31311784Sarthur.perais@inria.fr    }
31411784Sarthur.perais@inria.fr}
31511784Sarthur.perais@inria.fr
31611784Sarthur.perais@inria.frvoid
31711784Sarthur.perais@inria.frLTAGE::loopUpdate(Addr pc, bool taken, BranchInfo* bi)
31811784Sarthur.perais@inria.fr{
31911784Sarthur.perais@inria.fr    int idx = bi->loopIndex + bi->loopHit;
32011784Sarthur.perais@inria.fr    if (bi->loopHit >= 0) {
32111784Sarthur.perais@inria.fr        //already a hit
32211784Sarthur.perais@inria.fr        if (bi->loopPredValid) {
32311784Sarthur.perais@inria.fr            if (taken != bi->loopPred) {
32411784Sarthur.perais@inria.fr                // free the entry
32511784Sarthur.perais@inria.fr                ltable[idx].numIter = 0;
32611784Sarthur.perais@inria.fr                ltable[idx].age = 0;
32711784Sarthur.perais@inria.fr                ltable[idx].confidence = 0;
32811784Sarthur.perais@inria.fr                ltable[idx].currentIter = 0;
32911784Sarthur.perais@inria.fr                return;
33011784Sarthur.perais@inria.fr            } else if (bi->loopPred != bi->tagePred) {
33111784Sarthur.perais@inria.fr                DPRINTF(LTage, "Loop Prediction success:%lx\n",pc);
33213442Spau.cabre@metempsy.com                unsignedCtrUpdate(ltable[idx].age, true, loopTableAgeBits);
33311784Sarthur.perais@inria.fr            }
33411784Sarthur.perais@inria.fr        }
33511784Sarthur.perais@inria.fr
33613442Spau.cabre@metempsy.com        ltable[idx].currentIter =
33713442Spau.cabre@metempsy.com            (ltable[idx].currentIter + 1) & loopNumIterMask;
33811784Sarthur.perais@inria.fr        if (ltable[idx].currentIter > ltable[idx].numIter) {
33911784Sarthur.perais@inria.fr            ltable[idx].confidence = 0;
34011784Sarthur.perais@inria.fr            if (ltable[idx].numIter != 0) {
34111784Sarthur.perais@inria.fr                // free the entry
34211784Sarthur.perais@inria.fr                ltable[idx].numIter = 0;
34311784Sarthur.perais@inria.fr                ltable[idx].age = 0;
34411784Sarthur.perais@inria.fr                ltable[idx].confidence = 0;
34511784Sarthur.perais@inria.fr            }
34611784Sarthur.perais@inria.fr        }
34711784Sarthur.perais@inria.fr
34811784Sarthur.perais@inria.fr        if (taken != ltable[idx].dir) {
34911784Sarthur.perais@inria.fr            if (ltable[idx].currentIter == ltable[idx].numIter) {
35011784Sarthur.perais@inria.fr                DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc);
35111784Sarthur.perais@inria.fr
35213442Spau.cabre@metempsy.com                unsignedCtrUpdate(ltable[idx].confidence, true,
35313442Spau.cabre@metempsy.com                                  loopTableConfidenceBits);
35411784Sarthur.perais@inria.fr                //just do not predict when the loop count is 1 or 2
35511784Sarthur.perais@inria.fr                if (ltable[idx].numIter < 3) {
35611784Sarthur.perais@inria.fr                    // free the entry
35711784Sarthur.perais@inria.fr                    ltable[idx].dir = taken;
35811784Sarthur.perais@inria.fr                    ltable[idx].numIter = 0;
35911784Sarthur.perais@inria.fr                    ltable[idx].age = 0;
36011784Sarthur.perais@inria.fr                    ltable[idx].confidence = 0;
36111784Sarthur.perais@inria.fr                }
36211784Sarthur.perais@inria.fr            } else {
36311784Sarthur.perais@inria.fr                DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc);
36411784Sarthur.perais@inria.fr                if (ltable[idx].numIter == 0) {
36511784Sarthur.perais@inria.fr                    // first complete nest;
36611784Sarthur.perais@inria.fr                    ltable[idx].confidence = 0;
36711784Sarthur.perais@inria.fr                    ltable[idx].numIter = ltable[idx].currentIter;
36811784Sarthur.perais@inria.fr                } else {
36911784Sarthur.perais@inria.fr                    //not the same number of iterations as last time: free the
37011784Sarthur.perais@inria.fr                    //entry
37111784Sarthur.perais@inria.fr                    ltable[idx].numIter = 0;
37211784Sarthur.perais@inria.fr                    ltable[idx].age = 0;
37311784Sarthur.perais@inria.fr                    ltable[idx].confidence = 0;
37411784Sarthur.perais@inria.fr                }
37511784Sarthur.perais@inria.fr            }
37611784Sarthur.perais@inria.fr            ltable[idx].currentIter = 0;
37711784Sarthur.perais@inria.fr        }
37811784Sarthur.perais@inria.fr
37911784Sarthur.perais@inria.fr    } else if (taken) {
38011784Sarthur.perais@inria.fr        //try to allocate an entry on taken branch
38111784Sarthur.perais@inria.fr        int nrand = random_mt.random<int>();
38211784Sarthur.perais@inria.fr        for (int i = 0; i < 4; i++) {
38311784Sarthur.perais@inria.fr            int loop_hit = (nrand + i) & 3;
38411784Sarthur.perais@inria.fr            idx = bi->loopIndex + loop_hit;
38511784Sarthur.perais@inria.fr            if (ltable[idx].age == 0) {
38611784Sarthur.perais@inria.fr                DPRINTF(LTage, "Allocating loop pred entry for branch %lx\n",
38711784Sarthur.perais@inria.fr                        pc);
38811784Sarthur.perais@inria.fr                ltable[idx].dir = !taken;
38911784Sarthur.perais@inria.fr                ltable[idx].tag = bi->loopTag;
39011784Sarthur.perais@inria.fr                ltable[idx].numIter = 0;
39113442Spau.cabre@metempsy.com                ltable[idx].age = (1 << loopTableAgeBits) - 1;
39211784Sarthur.perais@inria.fr                ltable[idx].confidence = 0;
39311784Sarthur.perais@inria.fr                ltable[idx].currentIter = 1;
39411784Sarthur.perais@inria.fr                break;
39511784Sarthur.perais@inria.fr
39611784Sarthur.perais@inria.fr            }
39711784Sarthur.perais@inria.fr            else
39811784Sarthur.perais@inria.fr                ltable[idx].age--;
39911784Sarthur.perais@inria.fr        }
40011784Sarthur.perais@inria.fr    }
40111784Sarthur.perais@inria.fr
40211784Sarthur.perais@inria.fr}
40311784Sarthur.perais@inria.fr
40411784Sarthur.perais@inria.fr// shifting the global history:  we manage the history in a big table in order
40511784Sarthur.perais@inria.fr// to reduce simulation time
40611784Sarthur.perais@inria.frvoid
40711784Sarthur.perais@inria.frLTAGE::updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &pt)
40811784Sarthur.perais@inria.fr{
40911784Sarthur.perais@inria.fr    if (pt == 0) {
41011784Sarthur.perais@inria.fr        DPRINTF(LTage, "Rolling over the histories\n");
41111784Sarthur.perais@inria.fr         // Copy beginning of globalHistoryBuffer to end, such that
41211784Sarthur.perais@inria.fr         // the last maxHist outcomes are still reachable
41311784Sarthur.perais@inria.fr         // through pt[0 .. maxHist - 1].
41411784Sarthur.perais@inria.fr         for (int i = 0; i < maxHist; i++)
41511784Sarthur.perais@inria.fr             tab[histBufferSize - maxHist + i] = tab[i];
41611784Sarthur.perais@inria.fr         pt =  histBufferSize - maxHist;
41711784Sarthur.perais@inria.fr         h = &tab[pt];
41811784Sarthur.perais@inria.fr    }
41911784Sarthur.perais@inria.fr    pt--;
42011784Sarthur.perais@inria.fr    h--;
42111784Sarthur.perais@inria.fr    h[0] = (dir) ? 1 : 0;
42211784Sarthur.perais@inria.fr}
42311784Sarthur.perais@inria.fr
42411784Sarthur.perais@inria.fr// Get GHR for hashing indirect predictor
42511784Sarthur.perais@inria.fr// Build history backwards from pointer in
42611784Sarthur.perais@inria.fr// bp_history.
42711784Sarthur.perais@inria.frunsigned
42811784Sarthur.perais@inria.frLTAGE::getGHR(ThreadID tid, void *bp_history) const
42911784Sarthur.perais@inria.fr{
43011784Sarthur.perais@inria.fr    BranchInfo* bi = static_cast<BranchInfo*>(bp_history);
43111784Sarthur.perais@inria.fr    unsigned val = 0;
43211784Sarthur.perais@inria.fr    for (unsigned i = 0; i < 32; i++) {
43311784Sarthur.perais@inria.fr        // Make sure we don't go out of bounds
43411784Sarthur.perais@inria.fr        int gh_offset = bi->ptGhist + i;
43511784Sarthur.perais@inria.fr        assert(&(threadHistory[tid].globalHistory[gh_offset]) <
43611784Sarthur.perais@inria.fr               threadHistory[tid].globalHistory + histBufferSize);
43711784Sarthur.perais@inria.fr        val |= ((threadHistory[tid].globalHistory[gh_offset] & 0x1) << i);
43811784Sarthur.perais@inria.fr    }
43911784Sarthur.perais@inria.fr
44011784Sarthur.perais@inria.fr    return val;
44111784Sarthur.perais@inria.fr}
44211784Sarthur.perais@inria.fr
44311784Sarthur.perais@inria.fr//prediction
44411784Sarthur.perais@inria.frbool
44511784Sarthur.perais@inria.frLTAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b)
44611784Sarthur.perais@inria.fr{
44711784Sarthur.perais@inria.fr    BranchInfo *bi = new BranchInfo(nHistoryTables+1);
44811784Sarthur.perais@inria.fr    b = (void*)(bi);
44911784Sarthur.perais@inria.fr    Addr pc = branch_pc;
45011784Sarthur.perais@inria.fr    bool pred_taken = true;
45111784Sarthur.perais@inria.fr    bi->loopHit = -1;
45211784Sarthur.perais@inria.fr
45311784Sarthur.perais@inria.fr    if (cond_branch) {
45411784Sarthur.perais@inria.fr        // TAGE prediction
45511784Sarthur.perais@inria.fr
45611784Sarthur.perais@inria.fr        // computes the table addresses and the partial tags
45711784Sarthur.perais@inria.fr        for (int i = 1; i <= nHistoryTables; i++) {
45811784Sarthur.perais@inria.fr            tableIndices[i] = gindex(tid, pc, i);
45911784Sarthur.perais@inria.fr            bi->tableIndices[i] = tableIndices[i];
46011784Sarthur.perais@inria.fr            tableTags[i] = gtag(tid, pc, i);
46111784Sarthur.perais@inria.fr            bi->tableTags[i] = tableTags[i];
46211784Sarthur.perais@inria.fr        }
46311784Sarthur.perais@inria.fr
46411784Sarthur.perais@inria.fr        bi->bimodalIndex = bindex(pc);
46511784Sarthur.perais@inria.fr
46611784Sarthur.perais@inria.fr        bi->hitBank = 0;
46711784Sarthur.perais@inria.fr        bi->altBank = 0;
46811784Sarthur.perais@inria.fr        //Look for the bank with longest matching history
46911784Sarthur.perais@inria.fr        for (int i = nHistoryTables; i > 0; i--) {
47011784Sarthur.perais@inria.fr            if (gtable[i][tableIndices[i]].tag == tableTags[i]) {
47111784Sarthur.perais@inria.fr                bi->hitBank = i;
47211784Sarthur.perais@inria.fr                bi->hitBankIndex = tableIndices[bi->hitBank];
47311784Sarthur.perais@inria.fr                break;
47411784Sarthur.perais@inria.fr            }
47511784Sarthur.perais@inria.fr        }
47611784Sarthur.perais@inria.fr        //Look for the alternate bank
47711784Sarthur.perais@inria.fr        for (int i = bi->hitBank - 1; i > 0; i--) {
47811784Sarthur.perais@inria.fr            if (gtable[i][tableIndices[i]].tag == tableTags[i]) {
47911784Sarthur.perais@inria.fr                bi->altBank = i;
48011784Sarthur.perais@inria.fr                bi->altBankIndex = tableIndices[bi->altBank];
48111784Sarthur.perais@inria.fr                break;
48211784Sarthur.perais@inria.fr            }
48311784Sarthur.perais@inria.fr        }
48411784Sarthur.perais@inria.fr        //computes the prediction and the alternate prediction
48511784Sarthur.perais@inria.fr        if (bi->hitBank > 0) {
48611784Sarthur.perais@inria.fr            if (bi->altBank > 0) {
48711784Sarthur.perais@inria.fr                bi->altTaken =
48811784Sarthur.perais@inria.fr                    gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0;
48911784Sarthur.perais@inria.fr            }else {
49011784Sarthur.perais@inria.fr                bi->altTaken = getBimodePred(pc, bi);
49111784Sarthur.perais@inria.fr            }
49211784Sarthur.perais@inria.fr
49311784Sarthur.perais@inria.fr            bi->longestMatchPred =
49411784Sarthur.perais@inria.fr                gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0;
49511784Sarthur.perais@inria.fr            bi->pseudoNewAlloc =
49611784Sarthur.perais@inria.fr                abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1;
49711784Sarthur.perais@inria.fr
49811784Sarthur.perais@inria.fr            //if the entry is recognized as a newly allocated entry and
49911784Sarthur.perais@inria.fr            //useAltPredForNewlyAllocated is positive use the alternate
50011784Sarthur.perais@inria.fr            //prediction
50111784Sarthur.perais@inria.fr            if ((useAltPredForNewlyAllocated < 0)
50211784Sarthur.perais@inria.fr                   || abs(2 *
50311784Sarthur.perais@inria.fr                   gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr + 1) > 1)
50411784Sarthur.perais@inria.fr                bi->tagePred = bi->longestMatchPred;
50511784Sarthur.perais@inria.fr            else
50611784Sarthur.perais@inria.fr                bi->tagePred = bi->altTaken;
50711784Sarthur.perais@inria.fr        } else {
50811784Sarthur.perais@inria.fr            bi->altTaken = getBimodePred(pc, bi);
50911784Sarthur.perais@inria.fr            bi->tagePred = bi->altTaken;
51011784Sarthur.perais@inria.fr            bi->longestMatchPred = bi->altTaken;
51111784Sarthur.perais@inria.fr        }
51211784Sarthur.perais@inria.fr        //end TAGE prediction
51311784Sarthur.perais@inria.fr
51411784Sarthur.perais@inria.fr        bi->loopPred = getLoop(pc, bi);	// loop prediction
51511784Sarthur.perais@inria.fr
51611784Sarthur.perais@inria.fr        pred_taken = (((loopUseCounter >= 0) && bi->loopPredValid)) ?
51711784Sarthur.perais@inria.fr                     (bi->loopPred): (bi->tagePred);
51811784Sarthur.perais@inria.fr        DPRINTF(LTage, "Predict for %lx: taken?:%d, loopTaken?:%d, "
51911784Sarthur.perais@inria.fr                "loopValid?:%d, loopUseCounter:%d, tagePred:%d, altPred:%d\n",
52011784Sarthur.perais@inria.fr                branch_pc, pred_taken, bi->loopPred, bi->loopPredValid,
52111784Sarthur.perais@inria.fr                loopUseCounter, bi->tagePred, bi->altTaken);
52211784Sarthur.perais@inria.fr    }
52311784Sarthur.perais@inria.fr    bi->branchPC = branch_pc;
52411784Sarthur.perais@inria.fr    bi->condBranch = cond_branch;
52511784Sarthur.perais@inria.fr    specLoopUpdate(branch_pc, pred_taken, bi);
52611784Sarthur.perais@inria.fr    return pred_taken;
52711784Sarthur.perais@inria.fr}
52811784Sarthur.perais@inria.fr
52911784Sarthur.perais@inria.fr// PREDICTOR UPDATE
53011784Sarthur.perais@inria.frvoid
53111784Sarthur.perais@inria.frLTAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history,
53211784Sarthur.perais@inria.fr              bool squashed)
53311784Sarthur.perais@inria.fr{
53411784Sarthur.perais@inria.fr    assert(bp_history);
53511784Sarthur.perais@inria.fr
53611784Sarthur.perais@inria.fr    BranchInfo *bi = static_cast<BranchInfo*>(bp_history);
53711784Sarthur.perais@inria.fr
53811784Sarthur.perais@inria.fr    if (squashed) {
53911784Sarthur.perais@inria.fr        // This restores the global history, then update it
54011784Sarthur.perais@inria.fr        // and recomputes the folded histories.
54111784Sarthur.perais@inria.fr        squash(tid, taken, bp_history);
54211784Sarthur.perais@inria.fr        return;
54311784Sarthur.perais@inria.fr    }
54411784Sarthur.perais@inria.fr
54511784Sarthur.perais@inria.fr    int nrand  = random_mt.random<int>(0,3);
54611784Sarthur.perais@inria.fr    Addr pc = branch_pc;
54711784Sarthur.perais@inria.fr    if (bi->condBranch) {
54811784Sarthur.perais@inria.fr        DPRINTF(LTage, "Updating tables for branch:%lx; taken?:%d\n",
54911784Sarthur.perais@inria.fr                branch_pc, taken);
55011784Sarthur.perais@inria.fr        // first update the loop predictor
55111784Sarthur.perais@inria.fr        loopUpdate(pc, taken, bi);
55211784Sarthur.perais@inria.fr
55311784Sarthur.perais@inria.fr        if (bi->loopPredValid) {
55411784Sarthur.perais@inria.fr            if (bi->tagePred != bi->loopPred) {
55511784Sarthur.perais@inria.fr                ctrUpdate(loopUseCounter, (bi->loopPred== taken), 7);
55611784Sarthur.perais@inria.fr            }
55711784Sarthur.perais@inria.fr        }
55811784Sarthur.perais@inria.fr
55911784Sarthur.perais@inria.fr        // TAGE UPDATE
56011784Sarthur.perais@inria.fr        // try to allocate a  new entries only if prediction was wrong
56111784Sarthur.perais@inria.fr        bool longest_match_pred = false;
56211784Sarthur.perais@inria.fr        bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables);
56311784Sarthur.perais@inria.fr        if (bi->hitBank > 0) {
56411784Sarthur.perais@inria.fr            // Manage the selection between longest matching and alternate
56511784Sarthur.perais@inria.fr            // matching for "pseudo"-newly allocated longest matching entry
56611784Sarthur.perais@inria.fr             longest_match_pred = bi->longestMatchPred;
56711784Sarthur.perais@inria.fr            bool PseudoNewAlloc = bi->pseudoNewAlloc;
56811784Sarthur.perais@inria.fr            // an entry is considered as newly allocated if its prediction
56911784Sarthur.perais@inria.fr            // counter is weak
57011784Sarthur.perais@inria.fr            if (PseudoNewAlloc) {
57111784Sarthur.perais@inria.fr                if (longest_match_pred == taken) {
57211784Sarthur.perais@inria.fr                    alloc = false;
57311784Sarthur.perais@inria.fr                }
57411784Sarthur.perais@inria.fr                // if it was delivering the correct prediction, no need to
57511784Sarthur.perais@inria.fr                // allocate new entry even if the overall prediction was false
57611784Sarthur.perais@inria.fr                if (longest_match_pred != bi->altTaken) {
57711784Sarthur.perais@inria.fr                    ctrUpdate(useAltPredForNewlyAllocated,
57811784Sarthur.perais@inria.fr                         bi->altTaken == taken, 4);
57911784Sarthur.perais@inria.fr                }
58011784Sarthur.perais@inria.fr            }
58111784Sarthur.perais@inria.fr        }
58211784Sarthur.perais@inria.fr
58311784Sarthur.perais@inria.fr        if (alloc) {
58411784Sarthur.perais@inria.fr            // is there some "unuseful" entry to allocate
58513443Spau.cabre@metempsy.com            uint8_t min = 1;
58611784Sarthur.perais@inria.fr            for (int i = nHistoryTables; i > bi->hitBank; i--) {
58711784Sarthur.perais@inria.fr                if (gtable[i][bi->tableIndices[i]].u < min) {
58811784Sarthur.perais@inria.fr                    min = gtable[i][bi->tableIndices[i]].u;
58911784Sarthur.perais@inria.fr                }
59011784Sarthur.perais@inria.fr            }
59111784Sarthur.perais@inria.fr
59211784Sarthur.perais@inria.fr            // we allocate an entry with a longer history
59311784Sarthur.perais@inria.fr            // to  avoid ping-pong, we do not choose systematically the next
59411784Sarthur.perais@inria.fr            // entry, but among the 3 next entries
59511784Sarthur.perais@inria.fr            int Y = nrand &
59611784Sarthur.perais@inria.fr                ((ULL(1) << (nHistoryTables - bi->hitBank - 1)) - 1);
59711784Sarthur.perais@inria.fr            int X = bi->hitBank + 1;
59811784Sarthur.perais@inria.fr            if (Y & 1) {
59911784Sarthur.perais@inria.fr                X++;
60011784Sarthur.perais@inria.fr                if (Y & 2)
60111784Sarthur.perais@inria.fr                    X++;
60211784Sarthur.perais@inria.fr            }
60311784Sarthur.perais@inria.fr            // No entry available, forces one to be available
60411784Sarthur.perais@inria.fr            if (min > 0) {
60511784Sarthur.perais@inria.fr                gtable[X][bi->tableIndices[X]].u = 0;
60611784Sarthur.perais@inria.fr            }
60711784Sarthur.perais@inria.fr
60811784Sarthur.perais@inria.fr
60911784Sarthur.perais@inria.fr            //Allocate only  one entry
61011784Sarthur.perais@inria.fr            for (int i = X; i <= nHistoryTables; i++) {
61111784Sarthur.perais@inria.fr                if ((gtable[i][bi->tableIndices[i]].u == 0)) {
61211784Sarthur.perais@inria.fr                    gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i];
61311784Sarthur.perais@inria.fr                    gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1;
61413433Spau.cabre@metempsy.com                    break;
61511784Sarthur.perais@inria.fr                }
61611784Sarthur.perais@inria.fr            }
61711784Sarthur.perais@inria.fr        }
61811784Sarthur.perais@inria.fr        //periodic reset of u: reset is not complete but bit by bit
61911784Sarthur.perais@inria.fr        tCounter++;
62011784Sarthur.perais@inria.fr        if ((tCounter & ((ULL(1) << logTick) - 1)) == 0) {
62111784Sarthur.perais@inria.fr            // reset least significant bit
62211784Sarthur.perais@inria.fr            // most significant bit becomes least significant bit
62311784Sarthur.perais@inria.fr            for (int i = 1; i <= nHistoryTables; i++) {
62411784Sarthur.perais@inria.fr                for (int j = 0; j < (ULL(1) << tagTableSizes[i]); j++) {
62511784Sarthur.perais@inria.fr                    gtable[i][j].u = gtable[i][j].u >> 1;
62611784Sarthur.perais@inria.fr                }
62711784Sarthur.perais@inria.fr            }
62811784Sarthur.perais@inria.fr        }
62911784Sarthur.perais@inria.fr
63011784Sarthur.perais@inria.fr        if (bi->hitBank > 0) {
63111784Sarthur.perais@inria.fr            DPRINTF(LTage, "Updating tag table entry (%d,%d) for branch %lx\n",
63211784Sarthur.perais@inria.fr                    bi->hitBank, bi->hitBankIndex, branch_pc);
63311784Sarthur.perais@inria.fr            ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken,
63411784Sarthur.perais@inria.fr                      tagTableCounterBits);
63511784Sarthur.perais@inria.fr            // if the provider entry is not certified to be useful also update
63611784Sarthur.perais@inria.fr            // the alternate prediction
63711784Sarthur.perais@inria.fr            if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) {
63811784Sarthur.perais@inria.fr                if (bi->altBank > 0) {
63911784Sarthur.perais@inria.fr                    ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken,
64011784Sarthur.perais@inria.fr                              tagTableCounterBits);
64111784Sarthur.perais@inria.fr                    DPRINTF(LTage, "Updating tag table entry (%d,%d) for"
64211784Sarthur.perais@inria.fr                            " branch %lx\n", bi->hitBank, bi->hitBankIndex,
64311784Sarthur.perais@inria.fr                            branch_pc);
64411784Sarthur.perais@inria.fr                }
64511784Sarthur.perais@inria.fr                if (bi->altBank == 0) {
64611784Sarthur.perais@inria.fr                    baseUpdate(pc, taken, bi);
64711784Sarthur.perais@inria.fr                }
64811784Sarthur.perais@inria.fr            }
64911784Sarthur.perais@inria.fr
65011784Sarthur.perais@inria.fr            // update the u counter
65113443Spau.cabre@metempsy.com            if (bi->tagePred != bi->altTaken) {
65213443Spau.cabre@metempsy.com                unsignedCtrUpdate(gtable[bi->hitBank][bi->hitBankIndex].u,
65313443Spau.cabre@metempsy.com                                  bi->tagePred == taken, tagTableUBits);
65411784Sarthur.perais@inria.fr            }
65511784Sarthur.perais@inria.fr        } else {
65611784Sarthur.perais@inria.fr            baseUpdate(pc, taken, bi);
65711784Sarthur.perais@inria.fr        }
65811784Sarthur.perais@inria.fr
65911784Sarthur.perais@inria.fr        //END PREDICTOR UPDATE
66011784Sarthur.perais@inria.fr    }
66111784Sarthur.perais@inria.fr    if (!squashed) {
66211784Sarthur.perais@inria.fr        delete bi;
66311784Sarthur.perais@inria.fr    }
66411784Sarthur.perais@inria.fr}
66511784Sarthur.perais@inria.fr
66611784Sarthur.perais@inria.frvoid
66711784Sarthur.perais@inria.frLTAGE::updateHistories(ThreadID tid, Addr branch_pc, bool taken, void* b)
66811784Sarthur.perais@inria.fr{
66911784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*)(b);
67011784Sarthur.perais@inria.fr    ThreadHistory& tHist = threadHistory[tid];
67111784Sarthur.perais@inria.fr    //  UPDATE HISTORIES
67213413Spau.cabre@metempsy.com    bool pathbit = ((branch_pc >> instShiftAmt) & 1);
67311784Sarthur.perais@inria.fr    //on a squash, return pointers to this and recompute indices.
67411784Sarthur.perais@inria.fr    //update user history
67511784Sarthur.perais@inria.fr    updateGHist(tHist.gHist, taken, tHist.globalHistory, tHist.ptGhist);
67611784Sarthur.perais@inria.fr    tHist.pathHist = (tHist.pathHist << 1) + pathbit;
67711784Sarthur.perais@inria.fr    tHist.pathHist = (tHist.pathHist & ((ULL(1) << 16) - 1));
67811784Sarthur.perais@inria.fr
67911784Sarthur.perais@inria.fr    bi->ptGhist = tHist.ptGhist;
68011784Sarthur.perais@inria.fr    bi->pathHist = tHist.pathHist;
68111784Sarthur.perais@inria.fr    //prepare next index and tag computations for user branchs
68211784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++)
68311784Sarthur.perais@inria.fr    {
68411784Sarthur.perais@inria.fr        bi->ci[i]  = tHist.computeIndices[i].comp;
68511784Sarthur.perais@inria.fr        bi->ct0[i] = tHist.computeTags[0][i].comp;
68611784Sarthur.perais@inria.fr        bi->ct1[i] = tHist.computeTags[1][i].comp;
68711784Sarthur.perais@inria.fr        tHist.computeIndices[i].update(tHist.gHist);
68811784Sarthur.perais@inria.fr        tHist.computeTags[0][i].update(tHist.gHist);
68911784Sarthur.perais@inria.fr        tHist.computeTags[1][i].update(tHist.gHist);
69011784Sarthur.perais@inria.fr    }
69111784Sarthur.perais@inria.fr    DPRINTF(LTage, "Updating global histories with branch:%lx; taken?:%d, "
69211784Sarthur.perais@inria.fr            "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist,
69311784Sarthur.perais@inria.fr            tHist.ptGhist);
69411784Sarthur.perais@inria.fr}
69511784Sarthur.perais@inria.fr
69611784Sarthur.perais@inria.frvoid
69711784Sarthur.perais@inria.frLTAGE::squash(ThreadID tid, bool taken, void *bp_history)
69811784Sarthur.perais@inria.fr{
69911784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*)(bp_history);
70011784Sarthur.perais@inria.fr    ThreadHistory& tHist = threadHistory[tid];
70111784Sarthur.perais@inria.fr    DPRINTF(LTage, "Restoring branch info: %lx; taken? %d; PathHistory:%x, "
70211784Sarthur.perais@inria.fr            "pointer:%d\n", bi->branchPC,taken, bi->pathHist, bi->ptGhist);
70311784Sarthur.perais@inria.fr    tHist.pathHist = bi->pathHist;
70411784Sarthur.perais@inria.fr    tHist.ptGhist = bi->ptGhist;
70511784Sarthur.perais@inria.fr    tHist.gHist = &(tHist.globalHistory[tHist.ptGhist]);
70611784Sarthur.perais@inria.fr    tHist.gHist[0] = (taken ? 1 : 0);
70711784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++) {
70811784Sarthur.perais@inria.fr        tHist.computeIndices[i].comp = bi->ci[i];
70911784Sarthur.perais@inria.fr        tHist.computeTags[0][i].comp = bi->ct0[i];
71011784Sarthur.perais@inria.fr        tHist.computeTags[1][i].comp = bi->ct1[i];
71111784Sarthur.perais@inria.fr        tHist.computeIndices[i].update(tHist.gHist);
71211784Sarthur.perais@inria.fr        tHist.computeTags[0][i].update(tHist.gHist);
71311784Sarthur.perais@inria.fr        tHist.computeTags[1][i].update(tHist.gHist);
71411784Sarthur.perais@inria.fr    }
71511784Sarthur.perais@inria.fr
71611784Sarthur.perais@inria.fr    if (bi->condBranch) {
71711784Sarthur.perais@inria.fr        if (bi->loopHit >= 0) {
71811784Sarthur.perais@inria.fr            int idx = bi->loopIndex + bi->loopHit;
71911784Sarthur.perais@inria.fr            ltable[idx].currentIterSpec = bi->currentIter;
72011784Sarthur.perais@inria.fr        }
72111784Sarthur.perais@inria.fr    }
72211784Sarthur.perais@inria.fr
72311784Sarthur.perais@inria.fr}
72411784Sarthur.perais@inria.fr
72511784Sarthur.perais@inria.frvoid
72611784Sarthur.perais@inria.frLTAGE::squash(ThreadID tid, void *bp_history)
72711784Sarthur.perais@inria.fr{
72811784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*)(bp_history);
72911784Sarthur.perais@inria.fr    DPRINTF(LTage, "Deleting branch info: %lx\n", bi->branchPC);
73011784Sarthur.perais@inria.fr    if (bi->condBranch) {
73111784Sarthur.perais@inria.fr        if (bi->loopHit >= 0) {
73211784Sarthur.perais@inria.fr            int idx = bi->loopIndex + bi->loopHit;
73311784Sarthur.perais@inria.fr            ltable[idx].currentIterSpec = bi->currentIter;
73411784Sarthur.perais@inria.fr        }
73511784Sarthur.perais@inria.fr    }
73611784Sarthur.perais@inria.fr
73711784Sarthur.perais@inria.fr    delete bi;
73811784Sarthur.perais@inria.fr}
73911784Sarthur.perais@inria.fr
74011784Sarthur.perais@inria.frbool
74111784Sarthur.perais@inria.frLTAGE::lookup(ThreadID tid, Addr branch_pc, void* &bp_history)
74211784Sarthur.perais@inria.fr{
74311784Sarthur.perais@inria.fr    bool retval = predict(tid, branch_pc, true, bp_history);
74411784Sarthur.perais@inria.fr
74511784Sarthur.perais@inria.fr    DPRINTF(LTage, "Lookup branch: %lx; predict:%d\n", branch_pc, retval);
74611784Sarthur.perais@inria.fr    updateHistories(tid, branch_pc, retval, bp_history);
74711784Sarthur.perais@inria.fr    assert(threadHistory[tid].gHist ==
74811784Sarthur.perais@inria.fr           &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]);
74911784Sarthur.perais@inria.fr
75011784Sarthur.perais@inria.fr    return retval;
75111784Sarthur.perais@inria.fr}
75211784Sarthur.perais@inria.fr
75311784Sarthur.perais@inria.frvoid
75411784Sarthur.perais@inria.frLTAGE::btbUpdate(ThreadID tid, Addr branch_pc, void* &bp_history)
75511784Sarthur.perais@inria.fr{
75611784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*) bp_history;
75711784Sarthur.perais@inria.fr    ThreadHistory& tHist = threadHistory[tid];
75811784Sarthur.perais@inria.fr    DPRINTF(LTage, "BTB miss resets prediction: %lx\n", branch_pc);
75911784Sarthur.perais@inria.fr    assert(tHist.gHist == &tHist.globalHistory[tHist.ptGhist]);
76011784Sarthur.perais@inria.fr    tHist.gHist[0] = 0;
76111784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++) {
76211784Sarthur.perais@inria.fr        tHist.computeIndices[i].comp = bi->ci[i];
76311784Sarthur.perais@inria.fr        tHist.computeTags[0][i].comp = bi->ct0[i];
76411784Sarthur.perais@inria.fr        tHist.computeTags[1][i].comp = bi->ct1[i];
76511784Sarthur.perais@inria.fr        tHist.computeIndices[i].update(tHist.gHist);
76611784Sarthur.perais@inria.fr        tHist.computeTags[0][i].update(tHist.gHist);
76711784Sarthur.perais@inria.fr        tHist.computeTags[1][i].update(tHist.gHist);
76811784Sarthur.perais@inria.fr    }
76911784Sarthur.perais@inria.fr}
77011784Sarthur.perais@inria.fr
77111784Sarthur.perais@inria.frvoid
77211784Sarthur.perais@inria.frLTAGE::uncondBranch(ThreadID tid, Addr br_pc, void* &bp_history)
77311784Sarthur.perais@inria.fr{
77411784Sarthur.perais@inria.fr    DPRINTF(LTage, "UnConditionalBranch: %lx\n", br_pc);
77511784Sarthur.perais@inria.fr    predict(tid, br_pc, false, bp_history);
77611784Sarthur.perais@inria.fr    updateHistories(tid, br_pc, true, bp_history);
77711784Sarthur.perais@inria.fr    assert(threadHistory[tid].gHist ==
77811784Sarthur.perais@inria.fr           &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]);
77911784Sarthur.perais@inria.fr}
78011784Sarthur.perais@inria.fr
78111784Sarthur.perais@inria.frLTAGE*
78211784Sarthur.perais@inria.frLTAGEParams::create()
78311784Sarthur.perais@inria.fr{
78411784Sarthur.perais@inria.fr    return new LTAGE(this);
78511784Sarthur.perais@inria.fr}
786