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