ltage.cc revision 13442
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),
5811784Sarthur.perais@inria.fr    histBufferSize(params->histBufferSize),
5911784Sarthur.perais@inria.fr    minHist(params->minHist),
6011784Sarthur.perais@inria.fr    maxHist(params->maxHist),
6111784Sarthur.perais@inria.fr    minTagWidth(params->minTagWidth),
6213442Spau.cabre@metempsy.com    loopTableAgeBits(params->loopTableAgeBits),
6313442Spau.cabre@metempsy.com    loopTableConfidenceBits(params->loopTableConfidenceBits),
6413442Spau.cabre@metempsy.com    loopTableTagBits(params->loopTableTagBits),
6513442Spau.cabre@metempsy.com    loopTableIterBits(params->loopTableIterBits),
6613442Spau.cabre@metempsy.com    confidenceThreshold((1 << loopTableConfidenceBits) - 1),
6713442Spau.cabre@metempsy.com    loopTagMask((1 << loopTableTagBits) - 1),
6813442Spau.cabre@metempsy.com    loopNumIterMask((1 << loopTableIterBits) - 1),
6911784Sarthur.perais@inria.fr    threadHistory(params->numThreads)
7011784Sarthur.perais@inria.fr{
7113442Spau.cabre@metempsy.com    // we use uint16_t type for these vales, so they cannot be more than
7213442Spau.cabre@metempsy.com    // 16 bits
7313442Spau.cabre@metempsy.com    assert(loopTableTagBits <= 16);
7413442Spau.cabre@metempsy.com    assert(loopTableIterBits <= 16);
7513442Spau.cabre@metempsy.com
7611784Sarthur.perais@inria.fr    assert(params->histBufferSize > params->maxHist * 2);
7711784Sarthur.perais@inria.fr    useAltPredForNewlyAllocated = 0;
7811784Sarthur.perais@inria.fr    logTick = 19;
7911784Sarthur.perais@inria.fr    tCounter = ULL(1) << (logTick - 1);
8011784Sarthur.perais@inria.fr
8111784Sarthur.perais@inria.fr    for (auto& history : threadHistory) {
8211784Sarthur.perais@inria.fr        history.pathHist = 0;
8311784Sarthur.perais@inria.fr        history.globalHistory = new uint8_t[histBufferSize];
8411784Sarthur.perais@inria.fr        history.gHist = history.globalHistory;
8511784Sarthur.perais@inria.fr        memset(history.gHist, 0, histBufferSize);
8611784Sarthur.perais@inria.fr        history.ptGhist = 0;
8711784Sarthur.perais@inria.fr    }
8811784Sarthur.perais@inria.fr
8911784Sarthur.perais@inria.fr    histLengths = new int [nHistoryTables+1];
9011784Sarthur.perais@inria.fr    histLengths[1] = minHist;
9111784Sarthur.perais@inria.fr    histLengths[nHistoryTables] = maxHist;
9211784Sarthur.perais@inria.fr
9311784Sarthur.perais@inria.fr    for (int i = 2; i <= nHistoryTables; i++) {
9411784Sarthur.perais@inria.fr        histLengths[i] = (int) (((double) minHist *
9511784Sarthur.perais@inria.fr                    pow ((double) (maxHist) / (double) minHist,
9611784Sarthur.perais@inria.fr                        (double) (i - 1) / (double) ((nHistoryTables- 1))))
9711784Sarthur.perais@inria.fr                    + 0.5);
9811784Sarthur.perais@inria.fr    }
9911784Sarthur.perais@inria.fr
10011784Sarthur.perais@inria.fr    tagWidths[1] = minTagWidth;
10111784Sarthur.perais@inria.fr    tagWidths[2] = minTagWidth;
10211784Sarthur.perais@inria.fr    tagWidths[3] = minTagWidth + 1;
10311784Sarthur.perais@inria.fr    tagWidths[4] = minTagWidth + 1;
10411784Sarthur.perais@inria.fr    tagWidths[5] = minTagWidth + 2;
10511784Sarthur.perais@inria.fr    tagWidths[6] = minTagWidth + 3;
10611784Sarthur.perais@inria.fr    tagWidths[7] = minTagWidth + 4;
10711784Sarthur.perais@inria.fr    tagWidths[8] = minTagWidth + 5;
10811784Sarthur.perais@inria.fr    tagWidths[9] = minTagWidth + 5;
10911784Sarthur.perais@inria.fr    tagWidths[10] = minTagWidth + 6;
11011784Sarthur.perais@inria.fr    tagWidths[11] = minTagWidth + 7;
11111784Sarthur.perais@inria.fr    tagWidths[12] = minTagWidth + 8;
11211784Sarthur.perais@inria.fr
11311784Sarthur.perais@inria.fr    for (int i = 1; i <= 2; i++)
11411784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables - 1;
11511784Sarthur.perais@inria.fr    for (int i = 3; i <= 6; i++)
11611784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables;
11711784Sarthur.perais@inria.fr    for (int i = 7; i <= 10; i++)
11811784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables - 1;
11911784Sarthur.perais@inria.fr    for (int i = 11; i <= 12; i++)
12011784Sarthur.perais@inria.fr        tagTableSizes[i] = logSizeTagTables - 2;
12111784Sarthur.perais@inria.fr
12211784Sarthur.perais@inria.fr    for (auto& history : threadHistory) {
12311784Sarthur.perais@inria.fr        history.computeIndices = new FoldedHistory[nHistoryTables+1];
12411784Sarthur.perais@inria.fr        history.computeTags[0] = new FoldedHistory[nHistoryTables+1];
12511784Sarthur.perais@inria.fr        history.computeTags[1] = new FoldedHistory[nHistoryTables+1];
12611784Sarthur.perais@inria.fr
12711784Sarthur.perais@inria.fr        for (int i = 1; i <= nHistoryTables; i++) {
12811784Sarthur.perais@inria.fr            history.computeIndices[i].init(histLengths[i], (tagTableSizes[i]));
12911784Sarthur.perais@inria.fr            history.computeTags[0][i].init(
13011784Sarthur.perais@inria.fr                history.computeIndices[i].origLength, tagWidths[i]);
13111784Sarthur.perais@inria.fr            history.computeTags[1][i].init(
13211784Sarthur.perais@inria.fr                history.computeIndices[i].origLength, tagWidths[i] - 1);
13311784Sarthur.perais@inria.fr            DPRINTF(LTage, "HistLength:%d, TTSize:%d, TTTWidth:%d\n",
13411784Sarthur.perais@inria.fr                    histLengths[i], tagTableSizes[i], tagWidths[i]);
13511784Sarthur.perais@inria.fr        }
13611784Sarthur.perais@inria.fr    }
13711784Sarthur.perais@inria.fr
13813420Spau.cabre@metempsy.com    const uint64_t bimodalTableSize = ULL(1) << logSizeBiMP;
13913420Spau.cabre@metempsy.com    btablePrediction.resize(bimodalTableSize, false);
14013420Spau.cabre@metempsy.com    btableHysteresis.resize(bimodalTableSize >> logRatioBiModalHystEntries,
14113420Spau.cabre@metempsy.com                            true);
14213420Spau.cabre@metempsy.com
14311784Sarthur.perais@inria.fr    ltable = new LoopEntry[ULL(1) << logSizeLoopPred];
14411784Sarthur.perais@inria.fr    gtable = new TageEntry*[nHistoryTables + 1];
14511784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++) {
14611784Sarthur.perais@inria.fr        gtable[i] = new TageEntry[1<<(tagTableSizes[i])];
14711784Sarthur.perais@inria.fr    }
14811784Sarthur.perais@inria.fr
14911784Sarthur.perais@inria.fr    tableIndices = new int [nHistoryTables+1];
15011784Sarthur.perais@inria.fr    tableTags = new int [nHistoryTables+1];
15111784Sarthur.perais@inria.fr
15211784Sarthur.perais@inria.fr    loopUseCounter = 0;
15311784Sarthur.perais@inria.fr}
15411784Sarthur.perais@inria.fr
15511784Sarthur.perais@inria.frint
15611784Sarthur.perais@inria.frLTAGE::bindex(Addr pc_in) const
15711784Sarthur.perais@inria.fr{
15813413Spau.cabre@metempsy.com    return ((pc_in >> instShiftAmt) & ((ULL(1) << (logSizeBiMP)) - 1));
15911784Sarthur.perais@inria.fr}
16011784Sarthur.perais@inria.fr
16111784Sarthur.perais@inria.frint
16211784Sarthur.perais@inria.frLTAGE::lindex(Addr pc_in) const
16311784Sarthur.perais@inria.fr{
16413413Spau.cabre@metempsy.com    return (((pc_in >> instShiftAmt) &
16513413Spau.cabre@metempsy.com             ((ULL(1) << (logSizeLoopPred - 2)) - 1)) << 2);
16611784Sarthur.perais@inria.fr}
16711784Sarthur.perais@inria.fr
16811784Sarthur.perais@inria.frint
16911784Sarthur.perais@inria.frLTAGE::F(int A, int size, int bank) const
17011784Sarthur.perais@inria.fr{
17111784Sarthur.perais@inria.fr    int A1, A2;
17211784Sarthur.perais@inria.fr
17311784Sarthur.perais@inria.fr    A = A & ((ULL(1) << size) - 1);
17411784Sarthur.perais@inria.fr    A1 = (A & ((ULL(1) << tagTableSizes[bank]) - 1));
17511784Sarthur.perais@inria.fr    A2 = (A >> tagTableSizes[bank]);
17611784Sarthur.perais@inria.fr    A2 = ((A2 << bank) & ((ULL(1) << tagTableSizes[bank]) - 1))
17711784Sarthur.perais@inria.fr       + (A2 >> (tagTableSizes[bank] - bank));
17811784Sarthur.perais@inria.fr    A = A1 ^ A2;
17911784Sarthur.perais@inria.fr    A = ((A << bank) & ((ULL(1) << tagTableSizes[bank]) - 1))
18011784Sarthur.perais@inria.fr      + (A >> (tagTableSizes[bank] - bank));
18111784Sarthur.perais@inria.fr    return (A);
18211784Sarthur.perais@inria.fr}
18311784Sarthur.perais@inria.fr
18411784Sarthur.perais@inria.fr
18511784Sarthur.perais@inria.fr// gindex computes a full hash of pc, ghist and pathHist
18611784Sarthur.perais@inria.frint
18711784Sarthur.perais@inria.frLTAGE::gindex(ThreadID tid, Addr pc, int bank) const
18811784Sarthur.perais@inria.fr{
18911784Sarthur.perais@inria.fr    int index;
19011784Sarthur.perais@inria.fr    int hlen = (histLengths[bank] > 16) ? 16 : histLengths[bank];
19111784Sarthur.perais@inria.fr    index =
19213413Spau.cabre@metempsy.com        (pc >> instShiftAmt) ^
19313413Spau.cabre@metempsy.com        ((pc >> instShiftAmt) >> ((int) abs(tagTableSizes[bank] - bank) + 1)) ^
19411784Sarthur.perais@inria.fr        threadHistory[tid].computeIndices[bank].comp ^
19511784Sarthur.perais@inria.fr        F(threadHistory[tid].pathHist, hlen, bank);
19611784Sarthur.perais@inria.fr
19711784Sarthur.perais@inria.fr    return (index & ((ULL(1) << (tagTableSizes[bank])) - 1));
19811784Sarthur.perais@inria.fr}
19911784Sarthur.perais@inria.fr
20011784Sarthur.perais@inria.fr
20111784Sarthur.perais@inria.fr// Tag computation
20211784Sarthur.perais@inria.fruint16_t
20311784Sarthur.perais@inria.frLTAGE::gtag(ThreadID tid, Addr pc, int bank) const
20411784Sarthur.perais@inria.fr{
20513413Spau.cabre@metempsy.com    int tag = (pc >> instShiftAmt) ^
20613413Spau.cabre@metempsy.com              threadHistory[tid].computeTags[0][bank].comp ^
20713413Spau.cabre@metempsy.com              (threadHistory[tid].computeTags[1][bank].comp << 1);
20811784Sarthur.perais@inria.fr
20911784Sarthur.perais@inria.fr    return (tag & ((ULL(1) << tagWidths[bank]) - 1));
21011784Sarthur.perais@inria.fr}
21111784Sarthur.perais@inria.fr
21211784Sarthur.perais@inria.fr
21311784Sarthur.perais@inria.fr// Up-down saturating counter
21411784Sarthur.perais@inria.frvoid
21511784Sarthur.perais@inria.frLTAGE::ctrUpdate(int8_t & ctr, bool taken, int nbits)
21611784Sarthur.perais@inria.fr{
21711784Sarthur.perais@inria.fr    assert(nbits <= sizeof(int8_t) << 3);
21811784Sarthur.perais@inria.fr    if (taken) {
21911784Sarthur.perais@inria.fr        if (ctr < ((1 << (nbits - 1)) - 1))
22011784Sarthur.perais@inria.fr            ctr++;
22111784Sarthur.perais@inria.fr    } else {
22211784Sarthur.perais@inria.fr        if (ctr > -(1 << (nbits - 1)))
22311784Sarthur.perais@inria.fr            ctr--;
22411784Sarthur.perais@inria.fr    }
22511784Sarthur.perais@inria.fr}
22611784Sarthur.perais@inria.fr
22713442Spau.cabre@metempsy.com// Up-down unsigned saturating counter
22813442Spau.cabre@metempsy.comvoid
22913442Spau.cabre@metempsy.comLTAGE::unsignedCtrUpdate(uint8_t & ctr, bool up, unsigned nbits)
23013442Spau.cabre@metempsy.com{
23113442Spau.cabre@metempsy.com    assert(nbits <= sizeof(uint8_t) << 3);
23213442Spau.cabre@metempsy.com    if (up) {
23313442Spau.cabre@metempsy.com        if (ctr < ((1 << nbits) - 1))
23413442Spau.cabre@metempsy.com            ctr++;
23513442Spau.cabre@metempsy.com    } else {
23613442Spau.cabre@metempsy.com        if (ctr)
23713442Spau.cabre@metempsy.com            ctr--;
23813442Spau.cabre@metempsy.com    }
23913442Spau.cabre@metempsy.com}
24013442Spau.cabre@metempsy.com
24111784Sarthur.perais@inria.fr// Bimodal prediction
24211784Sarthur.perais@inria.frbool
24311784Sarthur.perais@inria.frLTAGE::getBimodePred(Addr pc, BranchInfo* bi) const
24411784Sarthur.perais@inria.fr{
24513420Spau.cabre@metempsy.com    return btablePrediction[bi->bimodalIndex];
24611784Sarthur.perais@inria.fr}
24711784Sarthur.perais@inria.fr
24811784Sarthur.perais@inria.fr
24913420Spau.cabre@metempsy.com// Update the bimodal predictor: a hysteresis bit is shared among N prediction
25013420Spau.cabre@metempsy.com// bits (N = 2 ^ logRatioBiModalHystEntries)
25111784Sarthur.perais@inria.frvoid
25211784Sarthur.perais@inria.frLTAGE::baseUpdate(Addr pc, bool taken, BranchInfo* bi)
25311784Sarthur.perais@inria.fr{
25413420Spau.cabre@metempsy.com    int inter = (btablePrediction[bi->bimodalIndex] << 1)
25513420Spau.cabre@metempsy.com        + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries];
25611784Sarthur.perais@inria.fr    if (taken) {
25711784Sarthur.perais@inria.fr        if (inter < 3)
25811784Sarthur.perais@inria.fr            inter++;
25911784Sarthur.perais@inria.fr    } else if (inter > 0) {
26011784Sarthur.perais@inria.fr        inter--;
26111784Sarthur.perais@inria.fr    }
26213420Spau.cabre@metempsy.com    const bool pred = inter >> 1;
26313420Spau.cabre@metempsy.com    const bool hyst = inter & 1;
26413420Spau.cabre@metempsy.com    btablePrediction[bi->bimodalIndex] = pred;
26513420Spau.cabre@metempsy.com    btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries] = hyst;
26613420Spau.cabre@metempsy.com    DPRINTF(LTage, "Updating branch %lx, pred:%d, hyst:%d\n", pc, pred, hyst);
26711784Sarthur.perais@inria.fr}
26811784Sarthur.perais@inria.fr
26911784Sarthur.perais@inria.fr
27011784Sarthur.perais@inria.fr//loop prediction: only used if high confidence
27111784Sarthur.perais@inria.frbool
27211784Sarthur.perais@inria.frLTAGE::getLoop(Addr pc, BranchInfo* bi) const
27311784Sarthur.perais@inria.fr{
27411784Sarthur.perais@inria.fr    bi->loopHit = -1;
27511784Sarthur.perais@inria.fr    bi->loopPredValid = false;
27611784Sarthur.perais@inria.fr    bi->loopIndex = lindex(pc);
27713442Spau.cabre@metempsy.com    bi->loopTag = ((pc) >> (instShiftAmt + logSizeLoopPred - 2)) & loopTagMask;
27811784Sarthur.perais@inria.fr
27911784Sarthur.perais@inria.fr    for (int i = 0; i < 4; i++) {
28011784Sarthur.perais@inria.fr        if (ltable[bi->loopIndex + i].tag == bi->loopTag) {
28111784Sarthur.perais@inria.fr            bi->loopHit = i;
28213442Spau.cabre@metempsy.com            bi->loopPredValid =
28313442Spau.cabre@metempsy.com                ltable[bi->loopIndex + i].confidence == confidenceThreshold;
28411784Sarthur.perais@inria.fr            bi->currentIter = ltable[bi->loopIndex + i].currentIterSpec;
28511784Sarthur.perais@inria.fr            if (ltable[bi->loopIndex + i].currentIterSpec + 1 ==
28611784Sarthur.perais@inria.fr                ltable[bi->loopIndex + i].numIter) {
28711784Sarthur.perais@inria.fr                return !(ltable[bi->loopIndex + i].dir);
28811784Sarthur.perais@inria.fr            }else {
28911784Sarthur.perais@inria.fr                return (ltable[bi->loopIndex + i].dir);
29011784Sarthur.perais@inria.fr            }
29111784Sarthur.perais@inria.fr        }
29211784Sarthur.perais@inria.fr    }
29311784Sarthur.perais@inria.fr    return false;
29411784Sarthur.perais@inria.fr}
29511784Sarthur.perais@inria.fr
29611784Sarthur.perais@inria.frvoid
29711784Sarthur.perais@inria.frLTAGE::specLoopUpdate(Addr pc, bool taken, BranchInfo* bi)
29811784Sarthur.perais@inria.fr{
29911784Sarthur.perais@inria.fr    if (bi->loopHit>=0) {
30011784Sarthur.perais@inria.fr        int index = lindex(pc);
30111784Sarthur.perais@inria.fr        if (taken != ltable[index].dir) {
30211784Sarthur.perais@inria.fr            ltable[index].currentIterSpec = 0;
30311784Sarthur.perais@inria.fr        } else {
30413442Spau.cabre@metempsy.com            ltable[index].currentIterSpec =
30513442Spau.cabre@metempsy.com                (ltable[index].currentIterSpec + 1) & loopNumIterMask;
30611784Sarthur.perais@inria.fr        }
30711784Sarthur.perais@inria.fr    }
30811784Sarthur.perais@inria.fr}
30911784Sarthur.perais@inria.fr
31011784Sarthur.perais@inria.frvoid
31111784Sarthur.perais@inria.frLTAGE::loopUpdate(Addr pc, bool taken, BranchInfo* bi)
31211784Sarthur.perais@inria.fr{
31311784Sarthur.perais@inria.fr    int idx = bi->loopIndex + bi->loopHit;
31411784Sarthur.perais@inria.fr    if (bi->loopHit >= 0) {
31511784Sarthur.perais@inria.fr        //already a hit
31611784Sarthur.perais@inria.fr        if (bi->loopPredValid) {
31711784Sarthur.perais@inria.fr            if (taken != bi->loopPred) {
31811784Sarthur.perais@inria.fr                // free the entry
31911784Sarthur.perais@inria.fr                ltable[idx].numIter = 0;
32011784Sarthur.perais@inria.fr                ltable[idx].age = 0;
32111784Sarthur.perais@inria.fr                ltable[idx].confidence = 0;
32211784Sarthur.perais@inria.fr                ltable[idx].currentIter = 0;
32311784Sarthur.perais@inria.fr                return;
32411784Sarthur.perais@inria.fr            } else if (bi->loopPred != bi->tagePred) {
32511784Sarthur.perais@inria.fr                DPRINTF(LTage, "Loop Prediction success:%lx\n",pc);
32613442Spau.cabre@metempsy.com                unsignedCtrUpdate(ltable[idx].age, true, loopTableAgeBits);
32711784Sarthur.perais@inria.fr            }
32811784Sarthur.perais@inria.fr        }
32911784Sarthur.perais@inria.fr
33013442Spau.cabre@metempsy.com        ltable[idx].currentIter =
33113442Spau.cabre@metempsy.com            (ltable[idx].currentIter + 1) & loopNumIterMask;
33211784Sarthur.perais@inria.fr        if (ltable[idx].currentIter > ltable[idx].numIter) {
33311784Sarthur.perais@inria.fr            ltable[idx].confidence = 0;
33411784Sarthur.perais@inria.fr            if (ltable[idx].numIter != 0) {
33511784Sarthur.perais@inria.fr                // free the entry
33611784Sarthur.perais@inria.fr                ltable[idx].numIter = 0;
33711784Sarthur.perais@inria.fr                ltable[idx].age = 0;
33811784Sarthur.perais@inria.fr                ltable[idx].confidence = 0;
33911784Sarthur.perais@inria.fr            }
34011784Sarthur.perais@inria.fr        }
34111784Sarthur.perais@inria.fr
34211784Sarthur.perais@inria.fr        if (taken != ltable[idx].dir) {
34311784Sarthur.perais@inria.fr            if (ltable[idx].currentIter == ltable[idx].numIter) {
34411784Sarthur.perais@inria.fr                DPRINTF(LTage, "Loop End predicted successfully:%lx\n", pc);
34511784Sarthur.perais@inria.fr
34613442Spau.cabre@metempsy.com                unsignedCtrUpdate(ltable[idx].confidence, true,
34713442Spau.cabre@metempsy.com                                  loopTableConfidenceBits);
34811784Sarthur.perais@inria.fr                //just do not predict when the loop count is 1 or 2
34911784Sarthur.perais@inria.fr                if (ltable[idx].numIter < 3) {
35011784Sarthur.perais@inria.fr                    // free the entry
35111784Sarthur.perais@inria.fr                    ltable[idx].dir = taken;
35211784Sarthur.perais@inria.fr                    ltable[idx].numIter = 0;
35311784Sarthur.perais@inria.fr                    ltable[idx].age = 0;
35411784Sarthur.perais@inria.fr                    ltable[idx].confidence = 0;
35511784Sarthur.perais@inria.fr                }
35611784Sarthur.perais@inria.fr            } else {
35711784Sarthur.perais@inria.fr                DPRINTF(LTage, "Loop End predicted incorrectly:%lx\n", pc);
35811784Sarthur.perais@inria.fr                if (ltable[idx].numIter == 0) {
35911784Sarthur.perais@inria.fr                    // first complete nest;
36011784Sarthur.perais@inria.fr                    ltable[idx].confidence = 0;
36111784Sarthur.perais@inria.fr                    ltable[idx].numIter = ltable[idx].currentIter;
36211784Sarthur.perais@inria.fr                } else {
36311784Sarthur.perais@inria.fr                    //not the same number of iterations as last time: free the
36411784Sarthur.perais@inria.fr                    //entry
36511784Sarthur.perais@inria.fr                    ltable[idx].numIter = 0;
36611784Sarthur.perais@inria.fr                    ltable[idx].age = 0;
36711784Sarthur.perais@inria.fr                    ltable[idx].confidence = 0;
36811784Sarthur.perais@inria.fr                }
36911784Sarthur.perais@inria.fr            }
37011784Sarthur.perais@inria.fr            ltable[idx].currentIter = 0;
37111784Sarthur.perais@inria.fr        }
37211784Sarthur.perais@inria.fr
37311784Sarthur.perais@inria.fr    } else if (taken) {
37411784Sarthur.perais@inria.fr        //try to allocate an entry on taken branch
37511784Sarthur.perais@inria.fr        int nrand = random_mt.random<int>();
37611784Sarthur.perais@inria.fr        for (int i = 0; i < 4; i++) {
37711784Sarthur.perais@inria.fr            int loop_hit = (nrand + i) & 3;
37811784Sarthur.perais@inria.fr            idx = bi->loopIndex + loop_hit;
37911784Sarthur.perais@inria.fr            if (ltable[idx].age == 0) {
38011784Sarthur.perais@inria.fr                DPRINTF(LTage, "Allocating loop pred entry for branch %lx\n",
38111784Sarthur.perais@inria.fr                        pc);
38211784Sarthur.perais@inria.fr                ltable[idx].dir = !taken;
38311784Sarthur.perais@inria.fr                ltable[idx].tag = bi->loopTag;
38411784Sarthur.perais@inria.fr                ltable[idx].numIter = 0;
38513442Spau.cabre@metempsy.com                ltable[idx].age = (1 << loopTableAgeBits) - 1;
38611784Sarthur.perais@inria.fr                ltable[idx].confidence = 0;
38711784Sarthur.perais@inria.fr                ltable[idx].currentIter = 1;
38811784Sarthur.perais@inria.fr                break;
38911784Sarthur.perais@inria.fr
39011784Sarthur.perais@inria.fr            }
39111784Sarthur.perais@inria.fr            else
39211784Sarthur.perais@inria.fr                ltable[idx].age--;
39311784Sarthur.perais@inria.fr        }
39411784Sarthur.perais@inria.fr    }
39511784Sarthur.perais@inria.fr
39611784Sarthur.perais@inria.fr}
39711784Sarthur.perais@inria.fr
39811784Sarthur.perais@inria.fr// shifting the global history:  we manage the history in a big table in order
39911784Sarthur.perais@inria.fr// to reduce simulation time
40011784Sarthur.perais@inria.frvoid
40111784Sarthur.perais@inria.frLTAGE::updateGHist(uint8_t * &h, bool dir, uint8_t * tab, int &pt)
40211784Sarthur.perais@inria.fr{
40311784Sarthur.perais@inria.fr    if (pt == 0) {
40411784Sarthur.perais@inria.fr        DPRINTF(LTage, "Rolling over the histories\n");
40511784Sarthur.perais@inria.fr         // Copy beginning of globalHistoryBuffer to end, such that
40611784Sarthur.perais@inria.fr         // the last maxHist outcomes are still reachable
40711784Sarthur.perais@inria.fr         // through pt[0 .. maxHist - 1].
40811784Sarthur.perais@inria.fr         for (int i = 0; i < maxHist; i++)
40911784Sarthur.perais@inria.fr             tab[histBufferSize - maxHist + i] = tab[i];
41011784Sarthur.perais@inria.fr         pt =  histBufferSize - maxHist;
41111784Sarthur.perais@inria.fr         h = &tab[pt];
41211784Sarthur.perais@inria.fr    }
41311784Sarthur.perais@inria.fr    pt--;
41411784Sarthur.perais@inria.fr    h--;
41511784Sarthur.perais@inria.fr    h[0] = (dir) ? 1 : 0;
41611784Sarthur.perais@inria.fr}
41711784Sarthur.perais@inria.fr
41811784Sarthur.perais@inria.fr// Get GHR for hashing indirect predictor
41911784Sarthur.perais@inria.fr// Build history backwards from pointer in
42011784Sarthur.perais@inria.fr// bp_history.
42111784Sarthur.perais@inria.frunsigned
42211784Sarthur.perais@inria.frLTAGE::getGHR(ThreadID tid, void *bp_history) const
42311784Sarthur.perais@inria.fr{
42411784Sarthur.perais@inria.fr    BranchInfo* bi = static_cast<BranchInfo*>(bp_history);
42511784Sarthur.perais@inria.fr    unsigned val = 0;
42611784Sarthur.perais@inria.fr    for (unsigned i = 0; i < 32; i++) {
42711784Sarthur.perais@inria.fr        // Make sure we don't go out of bounds
42811784Sarthur.perais@inria.fr        int gh_offset = bi->ptGhist + i;
42911784Sarthur.perais@inria.fr        assert(&(threadHistory[tid].globalHistory[gh_offset]) <
43011784Sarthur.perais@inria.fr               threadHistory[tid].globalHistory + histBufferSize);
43111784Sarthur.perais@inria.fr        val |= ((threadHistory[tid].globalHistory[gh_offset] & 0x1) << i);
43211784Sarthur.perais@inria.fr    }
43311784Sarthur.perais@inria.fr
43411784Sarthur.perais@inria.fr    return val;
43511784Sarthur.perais@inria.fr}
43611784Sarthur.perais@inria.fr
43711784Sarthur.perais@inria.fr//prediction
43811784Sarthur.perais@inria.frbool
43911784Sarthur.perais@inria.frLTAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b)
44011784Sarthur.perais@inria.fr{
44111784Sarthur.perais@inria.fr    BranchInfo *bi = new BranchInfo(nHistoryTables+1);
44211784Sarthur.perais@inria.fr    b = (void*)(bi);
44311784Sarthur.perais@inria.fr    Addr pc = branch_pc;
44411784Sarthur.perais@inria.fr    bool pred_taken = true;
44511784Sarthur.perais@inria.fr    bi->loopHit = -1;
44611784Sarthur.perais@inria.fr
44711784Sarthur.perais@inria.fr    if (cond_branch) {
44811784Sarthur.perais@inria.fr        // TAGE prediction
44911784Sarthur.perais@inria.fr
45011784Sarthur.perais@inria.fr        // computes the table addresses and the partial tags
45111784Sarthur.perais@inria.fr        for (int i = 1; i <= nHistoryTables; i++) {
45211784Sarthur.perais@inria.fr            tableIndices[i] = gindex(tid, pc, i);
45311784Sarthur.perais@inria.fr            bi->tableIndices[i] = tableIndices[i];
45411784Sarthur.perais@inria.fr            tableTags[i] = gtag(tid, pc, i);
45511784Sarthur.perais@inria.fr            bi->tableTags[i] = tableTags[i];
45611784Sarthur.perais@inria.fr        }
45711784Sarthur.perais@inria.fr
45811784Sarthur.perais@inria.fr        bi->bimodalIndex = bindex(pc);
45911784Sarthur.perais@inria.fr
46011784Sarthur.perais@inria.fr        bi->hitBank = 0;
46111784Sarthur.perais@inria.fr        bi->altBank = 0;
46211784Sarthur.perais@inria.fr        //Look for the bank with longest matching history
46311784Sarthur.perais@inria.fr        for (int i = nHistoryTables; i > 0; i--) {
46411784Sarthur.perais@inria.fr            if (gtable[i][tableIndices[i]].tag == tableTags[i]) {
46511784Sarthur.perais@inria.fr                bi->hitBank = i;
46611784Sarthur.perais@inria.fr                bi->hitBankIndex = tableIndices[bi->hitBank];
46711784Sarthur.perais@inria.fr                break;
46811784Sarthur.perais@inria.fr            }
46911784Sarthur.perais@inria.fr        }
47011784Sarthur.perais@inria.fr        //Look for the alternate bank
47111784Sarthur.perais@inria.fr        for (int i = bi->hitBank - 1; i > 0; i--) {
47211784Sarthur.perais@inria.fr            if (gtable[i][tableIndices[i]].tag == tableTags[i]) {
47311784Sarthur.perais@inria.fr                bi->altBank = i;
47411784Sarthur.perais@inria.fr                bi->altBankIndex = tableIndices[bi->altBank];
47511784Sarthur.perais@inria.fr                break;
47611784Sarthur.perais@inria.fr            }
47711784Sarthur.perais@inria.fr        }
47811784Sarthur.perais@inria.fr        //computes the prediction and the alternate prediction
47911784Sarthur.perais@inria.fr        if (bi->hitBank > 0) {
48011784Sarthur.perais@inria.fr            if (bi->altBank > 0) {
48111784Sarthur.perais@inria.fr                bi->altTaken =
48211784Sarthur.perais@inria.fr                    gtable[bi->altBank][tableIndices[bi->altBank]].ctr >= 0;
48311784Sarthur.perais@inria.fr            }else {
48411784Sarthur.perais@inria.fr                bi->altTaken = getBimodePred(pc, bi);
48511784Sarthur.perais@inria.fr            }
48611784Sarthur.perais@inria.fr
48711784Sarthur.perais@inria.fr            bi->longestMatchPred =
48811784Sarthur.perais@inria.fr                gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr >= 0;
48911784Sarthur.perais@inria.fr            bi->pseudoNewAlloc =
49011784Sarthur.perais@inria.fr                abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) <= 1;
49111784Sarthur.perais@inria.fr
49211784Sarthur.perais@inria.fr            //if the entry is recognized as a newly allocated entry and
49311784Sarthur.perais@inria.fr            //useAltPredForNewlyAllocated is positive use the alternate
49411784Sarthur.perais@inria.fr            //prediction
49511784Sarthur.perais@inria.fr            if ((useAltPredForNewlyAllocated < 0)
49611784Sarthur.perais@inria.fr                   || abs(2 *
49711784Sarthur.perais@inria.fr                   gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr + 1) > 1)
49811784Sarthur.perais@inria.fr                bi->tagePred = bi->longestMatchPred;
49911784Sarthur.perais@inria.fr            else
50011784Sarthur.perais@inria.fr                bi->tagePred = bi->altTaken;
50111784Sarthur.perais@inria.fr        } else {
50211784Sarthur.perais@inria.fr            bi->altTaken = getBimodePred(pc, bi);
50311784Sarthur.perais@inria.fr            bi->tagePred = bi->altTaken;
50411784Sarthur.perais@inria.fr            bi->longestMatchPred = bi->altTaken;
50511784Sarthur.perais@inria.fr        }
50611784Sarthur.perais@inria.fr        //end TAGE prediction
50711784Sarthur.perais@inria.fr
50811784Sarthur.perais@inria.fr        bi->loopPred = getLoop(pc, bi);	// loop prediction
50911784Sarthur.perais@inria.fr
51011784Sarthur.perais@inria.fr        pred_taken = (((loopUseCounter >= 0) && bi->loopPredValid)) ?
51111784Sarthur.perais@inria.fr                     (bi->loopPred): (bi->tagePred);
51211784Sarthur.perais@inria.fr        DPRINTF(LTage, "Predict for %lx: taken?:%d, loopTaken?:%d, "
51311784Sarthur.perais@inria.fr                "loopValid?:%d, loopUseCounter:%d, tagePred:%d, altPred:%d\n",
51411784Sarthur.perais@inria.fr                branch_pc, pred_taken, bi->loopPred, bi->loopPredValid,
51511784Sarthur.perais@inria.fr                loopUseCounter, bi->tagePred, bi->altTaken);
51611784Sarthur.perais@inria.fr    }
51711784Sarthur.perais@inria.fr    bi->branchPC = branch_pc;
51811784Sarthur.perais@inria.fr    bi->condBranch = cond_branch;
51911784Sarthur.perais@inria.fr    specLoopUpdate(branch_pc, pred_taken, bi);
52011784Sarthur.perais@inria.fr    return pred_taken;
52111784Sarthur.perais@inria.fr}
52211784Sarthur.perais@inria.fr
52311784Sarthur.perais@inria.fr// PREDICTOR UPDATE
52411784Sarthur.perais@inria.frvoid
52511784Sarthur.perais@inria.frLTAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history,
52611784Sarthur.perais@inria.fr              bool squashed)
52711784Sarthur.perais@inria.fr{
52811784Sarthur.perais@inria.fr    assert(bp_history);
52911784Sarthur.perais@inria.fr
53011784Sarthur.perais@inria.fr    BranchInfo *bi = static_cast<BranchInfo*>(bp_history);
53111784Sarthur.perais@inria.fr
53211784Sarthur.perais@inria.fr    if (squashed) {
53311784Sarthur.perais@inria.fr        // This restores the global history, then update it
53411784Sarthur.perais@inria.fr        // and recomputes the folded histories.
53511784Sarthur.perais@inria.fr        squash(tid, taken, bp_history);
53611784Sarthur.perais@inria.fr        return;
53711784Sarthur.perais@inria.fr    }
53811784Sarthur.perais@inria.fr
53911784Sarthur.perais@inria.fr    int nrand  = random_mt.random<int>(0,3);
54011784Sarthur.perais@inria.fr    Addr pc = branch_pc;
54111784Sarthur.perais@inria.fr    if (bi->condBranch) {
54211784Sarthur.perais@inria.fr        DPRINTF(LTage, "Updating tables for branch:%lx; taken?:%d\n",
54311784Sarthur.perais@inria.fr                branch_pc, taken);
54411784Sarthur.perais@inria.fr        // first update the loop predictor
54511784Sarthur.perais@inria.fr        loopUpdate(pc, taken, bi);
54611784Sarthur.perais@inria.fr
54711784Sarthur.perais@inria.fr        if (bi->loopPredValid) {
54811784Sarthur.perais@inria.fr            if (bi->tagePred != bi->loopPred) {
54911784Sarthur.perais@inria.fr                ctrUpdate(loopUseCounter, (bi->loopPred== taken), 7);
55011784Sarthur.perais@inria.fr            }
55111784Sarthur.perais@inria.fr        }
55211784Sarthur.perais@inria.fr
55311784Sarthur.perais@inria.fr        // TAGE UPDATE
55411784Sarthur.perais@inria.fr        // try to allocate a  new entries only if prediction was wrong
55511784Sarthur.perais@inria.fr        bool longest_match_pred = false;
55611784Sarthur.perais@inria.fr        bool alloc = (bi->tagePred != taken) && (bi->hitBank < nHistoryTables);
55711784Sarthur.perais@inria.fr        if (bi->hitBank > 0) {
55811784Sarthur.perais@inria.fr            // Manage the selection between longest matching and alternate
55911784Sarthur.perais@inria.fr            // matching for "pseudo"-newly allocated longest matching entry
56011784Sarthur.perais@inria.fr             longest_match_pred = bi->longestMatchPred;
56111784Sarthur.perais@inria.fr            bool PseudoNewAlloc = bi->pseudoNewAlloc;
56211784Sarthur.perais@inria.fr            // an entry is considered as newly allocated if its prediction
56311784Sarthur.perais@inria.fr            // counter is weak
56411784Sarthur.perais@inria.fr            if (PseudoNewAlloc) {
56511784Sarthur.perais@inria.fr                if (longest_match_pred == taken) {
56611784Sarthur.perais@inria.fr                    alloc = false;
56711784Sarthur.perais@inria.fr                }
56811784Sarthur.perais@inria.fr                // if it was delivering the correct prediction, no need to
56911784Sarthur.perais@inria.fr                // allocate new entry even if the overall prediction was false
57011784Sarthur.perais@inria.fr                if (longest_match_pred != bi->altTaken) {
57111784Sarthur.perais@inria.fr                    ctrUpdate(useAltPredForNewlyAllocated,
57211784Sarthur.perais@inria.fr                         bi->altTaken == taken, 4);
57311784Sarthur.perais@inria.fr                }
57411784Sarthur.perais@inria.fr            }
57511784Sarthur.perais@inria.fr        }
57611784Sarthur.perais@inria.fr
57711784Sarthur.perais@inria.fr        if (alloc) {
57811784Sarthur.perais@inria.fr            // is there some "unuseful" entry to allocate
57911784Sarthur.perais@inria.fr            int8_t min = 1;
58011784Sarthur.perais@inria.fr            for (int i = nHistoryTables; i > bi->hitBank; i--) {
58111784Sarthur.perais@inria.fr                if (gtable[i][bi->tableIndices[i]].u < min) {
58211784Sarthur.perais@inria.fr                    min = gtable[i][bi->tableIndices[i]].u;
58311784Sarthur.perais@inria.fr                }
58411784Sarthur.perais@inria.fr            }
58511784Sarthur.perais@inria.fr
58611784Sarthur.perais@inria.fr            // we allocate an entry with a longer history
58711784Sarthur.perais@inria.fr            // to  avoid ping-pong, we do not choose systematically the next
58811784Sarthur.perais@inria.fr            // entry, but among the 3 next entries
58911784Sarthur.perais@inria.fr            int Y = nrand &
59011784Sarthur.perais@inria.fr                ((ULL(1) << (nHistoryTables - bi->hitBank - 1)) - 1);
59111784Sarthur.perais@inria.fr            int X = bi->hitBank + 1;
59211784Sarthur.perais@inria.fr            if (Y & 1) {
59311784Sarthur.perais@inria.fr                X++;
59411784Sarthur.perais@inria.fr                if (Y & 2)
59511784Sarthur.perais@inria.fr                    X++;
59611784Sarthur.perais@inria.fr            }
59711784Sarthur.perais@inria.fr            // No entry available, forces one to be available
59811784Sarthur.perais@inria.fr            if (min > 0) {
59911784Sarthur.perais@inria.fr                gtable[X][bi->tableIndices[X]].u = 0;
60011784Sarthur.perais@inria.fr            }
60111784Sarthur.perais@inria.fr
60211784Sarthur.perais@inria.fr
60311784Sarthur.perais@inria.fr            //Allocate only  one entry
60411784Sarthur.perais@inria.fr            for (int i = X; i <= nHistoryTables; i++) {
60511784Sarthur.perais@inria.fr                if ((gtable[i][bi->tableIndices[i]].u == 0)) {
60611784Sarthur.perais@inria.fr                    gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i];
60711784Sarthur.perais@inria.fr                    gtable[i][bi->tableIndices[i]].ctr = (taken) ? 0 : -1;
60811784Sarthur.perais@inria.fr                    gtable[i][bi->tableIndices[i]].u = 0; //?
60913433Spau.cabre@metempsy.com                    break;
61011784Sarthur.perais@inria.fr                }
61111784Sarthur.perais@inria.fr            }
61211784Sarthur.perais@inria.fr        }
61311784Sarthur.perais@inria.fr        //periodic reset of u: reset is not complete but bit by bit
61411784Sarthur.perais@inria.fr        tCounter++;
61511784Sarthur.perais@inria.fr        if ((tCounter & ((ULL(1) << logTick) - 1)) == 0) {
61611784Sarthur.perais@inria.fr            // reset least significant bit
61711784Sarthur.perais@inria.fr            // most significant bit becomes least significant bit
61811784Sarthur.perais@inria.fr            for (int i = 1; i <= nHistoryTables; i++) {
61911784Sarthur.perais@inria.fr                for (int j = 0; j < (ULL(1) << tagTableSizes[i]); j++) {
62011784Sarthur.perais@inria.fr                    gtable[i][j].u = gtable[i][j].u >> 1;
62111784Sarthur.perais@inria.fr                }
62211784Sarthur.perais@inria.fr            }
62311784Sarthur.perais@inria.fr        }
62411784Sarthur.perais@inria.fr
62511784Sarthur.perais@inria.fr        if (bi->hitBank > 0) {
62611784Sarthur.perais@inria.fr            DPRINTF(LTage, "Updating tag table entry (%d,%d) for branch %lx\n",
62711784Sarthur.perais@inria.fr                    bi->hitBank, bi->hitBankIndex, branch_pc);
62811784Sarthur.perais@inria.fr            ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken,
62911784Sarthur.perais@inria.fr                      tagTableCounterBits);
63011784Sarthur.perais@inria.fr            // if the provider entry is not certified to be useful also update
63111784Sarthur.perais@inria.fr            // the alternate prediction
63211784Sarthur.perais@inria.fr            if (gtable[bi->hitBank][bi->hitBankIndex].u == 0) {
63311784Sarthur.perais@inria.fr                if (bi->altBank > 0) {
63411784Sarthur.perais@inria.fr                    ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken,
63511784Sarthur.perais@inria.fr                              tagTableCounterBits);
63611784Sarthur.perais@inria.fr                    DPRINTF(LTage, "Updating tag table entry (%d,%d) for"
63711784Sarthur.perais@inria.fr                            " branch %lx\n", bi->hitBank, bi->hitBankIndex,
63811784Sarthur.perais@inria.fr                            branch_pc);
63911784Sarthur.perais@inria.fr                }
64011784Sarthur.perais@inria.fr                if (bi->altBank == 0) {
64111784Sarthur.perais@inria.fr                    baseUpdate(pc, taken, bi);
64211784Sarthur.perais@inria.fr                }
64311784Sarthur.perais@inria.fr            }
64411784Sarthur.perais@inria.fr
64511784Sarthur.perais@inria.fr            // update the u counter
64611784Sarthur.perais@inria.fr            if (longest_match_pred != bi->altTaken) {
64711784Sarthur.perais@inria.fr                if (longest_match_pred == taken) {
64811784Sarthur.perais@inria.fr                    if (gtable[bi->hitBank][bi->hitBankIndex].u < 1) {
64911784Sarthur.perais@inria.fr                        gtable[bi->hitBank][bi->hitBankIndex].u++;
65011784Sarthur.perais@inria.fr                    }
65111784Sarthur.perais@inria.fr                }
65211784Sarthur.perais@inria.fr            }
65311784Sarthur.perais@inria.fr        } else {
65411784Sarthur.perais@inria.fr            baseUpdate(pc, taken, bi);
65511784Sarthur.perais@inria.fr        }
65611784Sarthur.perais@inria.fr
65711784Sarthur.perais@inria.fr        //END PREDICTOR UPDATE
65811784Sarthur.perais@inria.fr    }
65911784Sarthur.perais@inria.fr    if (!squashed) {
66011784Sarthur.perais@inria.fr        delete bi;
66111784Sarthur.perais@inria.fr    }
66211784Sarthur.perais@inria.fr}
66311784Sarthur.perais@inria.fr
66411784Sarthur.perais@inria.frvoid
66511784Sarthur.perais@inria.frLTAGE::updateHistories(ThreadID tid, Addr branch_pc, bool taken, void* b)
66611784Sarthur.perais@inria.fr{
66711784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*)(b);
66811784Sarthur.perais@inria.fr    ThreadHistory& tHist = threadHistory[tid];
66911784Sarthur.perais@inria.fr    //  UPDATE HISTORIES
67013413Spau.cabre@metempsy.com    bool pathbit = ((branch_pc >> instShiftAmt) & 1);
67111784Sarthur.perais@inria.fr    //on a squash, return pointers to this and recompute indices.
67211784Sarthur.perais@inria.fr    //update user history
67311784Sarthur.perais@inria.fr    updateGHist(tHist.gHist, taken, tHist.globalHistory, tHist.ptGhist);
67411784Sarthur.perais@inria.fr    tHist.pathHist = (tHist.pathHist << 1) + pathbit;
67511784Sarthur.perais@inria.fr    tHist.pathHist = (tHist.pathHist & ((ULL(1) << 16) - 1));
67611784Sarthur.perais@inria.fr
67711784Sarthur.perais@inria.fr    bi->ptGhist = tHist.ptGhist;
67811784Sarthur.perais@inria.fr    bi->pathHist = tHist.pathHist;
67911784Sarthur.perais@inria.fr    //prepare next index and tag computations for user branchs
68011784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++)
68111784Sarthur.perais@inria.fr    {
68211784Sarthur.perais@inria.fr        bi->ci[i]  = tHist.computeIndices[i].comp;
68311784Sarthur.perais@inria.fr        bi->ct0[i] = tHist.computeTags[0][i].comp;
68411784Sarthur.perais@inria.fr        bi->ct1[i] = tHist.computeTags[1][i].comp;
68511784Sarthur.perais@inria.fr        tHist.computeIndices[i].update(tHist.gHist);
68611784Sarthur.perais@inria.fr        tHist.computeTags[0][i].update(tHist.gHist);
68711784Sarthur.perais@inria.fr        tHist.computeTags[1][i].update(tHist.gHist);
68811784Sarthur.perais@inria.fr    }
68911784Sarthur.perais@inria.fr    DPRINTF(LTage, "Updating global histories with branch:%lx; taken?:%d, "
69011784Sarthur.perais@inria.fr            "path Hist: %x; pointer:%d\n", branch_pc, taken, tHist.pathHist,
69111784Sarthur.perais@inria.fr            tHist.ptGhist);
69211784Sarthur.perais@inria.fr}
69311784Sarthur.perais@inria.fr
69411784Sarthur.perais@inria.frvoid
69511784Sarthur.perais@inria.frLTAGE::squash(ThreadID tid, bool taken, void *bp_history)
69611784Sarthur.perais@inria.fr{
69711784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*)(bp_history);
69811784Sarthur.perais@inria.fr    ThreadHistory& tHist = threadHistory[tid];
69911784Sarthur.perais@inria.fr    DPRINTF(LTage, "Restoring branch info: %lx; taken? %d; PathHistory:%x, "
70011784Sarthur.perais@inria.fr            "pointer:%d\n", bi->branchPC,taken, bi->pathHist, bi->ptGhist);
70111784Sarthur.perais@inria.fr    tHist.pathHist = bi->pathHist;
70211784Sarthur.perais@inria.fr    tHist.ptGhist = bi->ptGhist;
70311784Sarthur.perais@inria.fr    tHist.gHist = &(tHist.globalHistory[tHist.ptGhist]);
70411784Sarthur.perais@inria.fr    tHist.gHist[0] = (taken ? 1 : 0);
70511784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++) {
70611784Sarthur.perais@inria.fr        tHist.computeIndices[i].comp = bi->ci[i];
70711784Sarthur.perais@inria.fr        tHist.computeTags[0][i].comp = bi->ct0[i];
70811784Sarthur.perais@inria.fr        tHist.computeTags[1][i].comp = bi->ct1[i];
70911784Sarthur.perais@inria.fr        tHist.computeIndices[i].update(tHist.gHist);
71011784Sarthur.perais@inria.fr        tHist.computeTags[0][i].update(tHist.gHist);
71111784Sarthur.perais@inria.fr        tHist.computeTags[1][i].update(tHist.gHist);
71211784Sarthur.perais@inria.fr    }
71311784Sarthur.perais@inria.fr
71411784Sarthur.perais@inria.fr    if (bi->condBranch) {
71511784Sarthur.perais@inria.fr        if (bi->loopHit >= 0) {
71611784Sarthur.perais@inria.fr            int idx = bi->loopIndex + bi->loopHit;
71711784Sarthur.perais@inria.fr            ltable[idx].currentIterSpec = bi->currentIter;
71811784Sarthur.perais@inria.fr        }
71911784Sarthur.perais@inria.fr    }
72011784Sarthur.perais@inria.fr
72111784Sarthur.perais@inria.fr}
72211784Sarthur.perais@inria.fr
72311784Sarthur.perais@inria.frvoid
72411784Sarthur.perais@inria.frLTAGE::squash(ThreadID tid, void *bp_history)
72511784Sarthur.perais@inria.fr{
72611784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*)(bp_history);
72711784Sarthur.perais@inria.fr    DPRINTF(LTage, "Deleting branch info: %lx\n", bi->branchPC);
72811784Sarthur.perais@inria.fr    if (bi->condBranch) {
72911784Sarthur.perais@inria.fr        if (bi->loopHit >= 0) {
73011784Sarthur.perais@inria.fr            int idx = bi->loopIndex + bi->loopHit;
73111784Sarthur.perais@inria.fr            ltable[idx].currentIterSpec = bi->currentIter;
73211784Sarthur.perais@inria.fr        }
73311784Sarthur.perais@inria.fr    }
73411784Sarthur.perais@inria.fr
73511784Sarthur.perais@inria.fr    delete bi;
73611784Sarthur.perais@inria.fr}
73711784Sarthur.perais@inria.fr
73811784Sarthur.perais@inria.frbool
73911784Sarthur.perais@inria.frLTAGE::lookup(ThreadID tid, Addr branch_pc, void* &bp_history)
74011784Sarthur.perais@inria.fr{
74111784Sarthur.perais@inria.fr    bool retval = predict(tid, branch_pc, true, bp_history);
74211784Sarthur.perais@inria.fr
74311784Sarthur.perais@inria.fr    DPRINTF(LTage, "Lookup branch: %lx; predict:%d\n", branch_pc, retval);
74411784Sarthur.perais@inria.fr    updateHistories(tid, branch_pc, retval, bp_history);
74511784Sarthur.perais@inria.fr    assert(threadHistory[tid].gHist ==
74611784Sarthur.perais@inria.fr           &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]);
74711784Sarthur.perais@inria.fr
74811784Sarthur.perais@inria.fr    return retval;
74911784Sarthur.perais@inria.fr}
75011784Sarthur.perais@inria.fr
75111784Sarthur.perais@inria.frvoid
75211784Sarthur.perais@inria.frLTAGE::btbUpdate(ThreadID tid, Addr branch_pc, void* &bp_history)
75311784Sarthur.perais@inria.fr{
75411784Sarthur.perais@inria.fr    BranchInfo* bi = (BranchInfo*) bp_history;
75511784Sarthur.perais@inria.fr    ThreadHistory& tHist = threadHistory[tid];
75611784Sarthur.perais@inria.fr    DPRINTF(LTage, "BTB miss resets prediction: %lx\n", branch_pc);
75711784Sarthur.perais@inria.fr    assert(tHist.gHist == &tHist.globalHistory[tHist.ptGhist]);
75811784Sarthur.perais@inria.fr    tHist.gHist[0] = 0;
75911784Sarthur.perais@inria.fr    for (int i = 1; i <= nHistoryTables; i++) {
76011784Sarthur.perais@inria.fr        tHist.computeIndices[i].comp = bi->ci[i];
76111784Sarthur.perais@inria.fr        tHist.computeTags[0][i].comp = bi->ct0[i];
76211784Sarthur.perais@inria.fr        tHist.computeTags[1][i].comp = bi->ct1[i];
76311784Sarthur.perais@inria.fr        tHist.computeIndices[i].update(tHist.gHist);
76411784Sarthur.perais@inria.fr        tHist.computeTags[0][i].update(tHist.gHist);
76511784Sarthur.perais@inria.fr        tHist.computeTags[1][i].update(tHist.gHist);
76611784Sarthur.perais@inria.fr    }
76711784Sarthur.perais@inria.fr}
76811784Sarthur.perais@inria.fr
76911784Sarthur.perais@inria.frvoid
77011784Sarthur.perais@inria.frLTAGE::uncondBranch(ThreadID tid, Addr br_pc, void* &bp_history)
77111784Sarthur.perais@inria.fr{
77211784Sarthur.perais@inria.fr    DPRINTF(LTage, "UnConditionalBranch: %lx\n", br_pc);
77311784Sarthur.perais@inria.fr    predict(tid, br_pc, false, bp_history);
77411784Sarthur.perais@inria.fr    updateHistories(tid, br_pc, true, bp_history);
77511784Sarthur.perais@inria.fr    assert(threadHistory[tid].gHist ==
77611784Sarthur.perais@inria.fr           &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]);
77711784Sarthur.perais@inria.fr}
77811784Sarthur.perais@inria.fr
77911784Sarthur.perais@inria.frLTAGE*
78011784Sarthur.perais@inria.frLTAGEParams::create()
78111784Sarthur.perais@inria.fr{
78211784Sarthur.perais@inria.fr    return new LTAGE(this);
78311784Sarthur.perais@inria.fr}
784