1/*
2 * Copyright 2019 Texas A&M University
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 *    this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 *    this list of conditions and the following disclaimer in the documentation
12 *    and/or other materials provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its
15 *    contributors may be used to endorse or promote products derived from this
16 *    software without specific prior written permission.
17 *
18 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 *  Author: Daniel A. Jiménez
31 *  Adapted to gem5 by: Javier Bueno Hedo
32 *
33 */
34
35/*
36 * Multiperspective Perceptron Predictor with TAGE (by Daniel A. Jiménez)
37 */
38
39#include "cpu/pred/multiperspective_perceptron_tage.hh"
40
41#include "base/random.hh"
42
43void
44MPP_TAGE::calculateParameters()
45{
46   assert(tunedHistoryLengths.size() == (nHistoryTables+1));
47   for (int i = 0; i <= nHistoryTables; i += 1) {
48      histLengths[i] = tunedHistoryLengths[i];
49   }
50}
51
52void
53MPP_TAGE::handleTAGEUpdate(Addr branch_pc, bool taken,
54                           TAGEBase::BranchInfo* bi)
55{
56    if (bi->hitBank > 0) {
57        if (abs (2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) == 1) {
58            if (bi->longestMatchPred != taken) {
59                // acts as a protection
60                if (bi->altBank > 0) {
61                    ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken,
62                              tagTableCounterBits);
63                }
64                if (bi->altBank == 0){
65                    baseUpdate(branch_pc, taken, bi);
66                }
67            }
68        }
69
70        ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken,
71                  tagTableCounterBits);
72
73        //sign changes: no way it can have been useful
74        if (abs (2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) == 1) {
75            gtable[bi->hitBank][bi->hitBankIndex].u = 0;
76        }
77    } else {
78        baseUpdate(branch_pc, taken, bi);
79    }
80
81    if ((bi->longestMatchPred != bi->altTaken) &&
82        (bi->longestMatchPred == taken) &&
83        (gtable[bi->hitBank][bi->hitBankIndex].u < (1 << tagTableUBits) -1)) {
84            gtable[bi->hitBank][bi->hitBankIndex].u++;
85    }
86}
87
88void
89MPP_TAGE::handleAllocAndUReset(bool alloc, bool taken,
90                               TAGEBase::BranchInfo* bi, int nrand)
91{
92    if (!alloc) {
93        return;
94    }
95
96    int a = 1;
97
98    if ((random_mt.random<int>() & 127) < 32) {
99        a = 2;
100    }
101    int dep = bi->hitBank + a;
102
103    int penalty = 0;
104    int numAllocated = 0;
105    int T = 1;
106
107    for (int i = dep; i <= nHistoryTables; i += 1) {
108        if (noSkip[i]) {
109            if (gtable[i][bi->tableIndices[i]].u == 0) {
110                gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i];
111                gtable[i][bi->tableIndices[i]].ctr = taken ? 0 : -1;
112                numAllocated++;
113                if (T <= 0) {
114                    break;
115                }
116                i += 1;
117                T -= 1;
118            } else {
119                penalty++;
120            }
121        } else { assert(false); }
122    }
123
124    tCounter += (penalty - numAllocated);
125
126    handleUReset();
127}
128
129void
130MPP_TAGE::handleUReset()
131{
132    //just the best formula for the Championship:
133    //In practice when one out of two entries are useful
134    if (tCounter < 0) {
135        tCounter = 0;
136    }
137
138    if (tCounter >= ((ULL(1) << logUResetPeriod))) {
139        // Update the u bits for the short tags table
140        for (int i = 1; i <= nHistoryTables; i++) {
141            for (int j = 0; j < (ULL(1) << logTagTableSizes[i]); j++) {
142                resetUctr(gtable[i][j].u);
143            }
144        }
145
146        tCounter = 0;
147    }
148}
149
150void
151MPP_TAGE::resetUctr(uint8_t &u)
152{
153    // On real HW it should be u >>= 1 instead of if > 0 then u--
154    if (u > 0) {
155        u--;
156    }
157}
158
159
160int
161MPP_TAGE::bindex(Addr pc_in) const
162{
163    uint32_t pc = (uint32_t) pc_in;
164    return ((pc ^ (pc >> 4)) &
165            ((ULL(1) << (logTagTableSizes[0])) - 1));
166}
167
168unsigned
169MPP_TAGE::getUseAltIdx(TAGEBase::BranchInfo* bi, Addr branch_pc)
170{
171    uint32_t hpc = ((uint32_t) branch_pc);
172    hpc = (hpc ^(hpc >> 4));
173    return 2 * ((hpc & ((numUseAltOnNa/2)-1)) ^ bi->longestMatchPred) +
174           ((bi->hitBank > (nHistoryTables / 3)) ? 1 : 0);
175}
176
177void
178MPP_TAGE::adjustAlloc(bool & alloc, bool taken, bool pred_taken)
179{
180    // Do not allocate too often if the prediction is ok
181    if ((taken == pred_taken) && ((random_mt.random<int>() & 31) != 0)) {
182        alloc = false;
183    }
184}
185
186void
187MPP_TAGE::updateHistories(
188    ThreadID tid, Addr branch_pc, bool taken, TAGEBase::BranchInfo* b,
189    bool speculative, const StaticInstPtr &inst, Addr target)
190{
191    if (speculative != speculativeHistUpdate) {
192        return;
193    }
194    // speculation is not implemented
195    assert(! speculative);
196
197    ThreadHistory& tHist = threadHistory[tid];
198
199    int brtype = inst->isDirectCtrl() ? 0 : 2;
200    if (! inst->isUncondCtrl()) {
201        ++brtype;
202    }
203    updatePathAndGlobalHistory(tHist, brtype, taken, branch_pc, target);
204}
205
206void
207MPP_TAGE::updatePathAndGlobalHistory(
208    ThreadHistory& tHist, int brtype, bool taken, Addr branch_pc, Addr target)
209{
210    // TAGE update
211    int tmp = (branch_pc << 1) + taken;
212    int path = branch_pc;
213
214    int maxt = (brtype & 1) ? 1 : 4;
215
216    for (int t = 0; t < maxt; t++) {
217        bool dir = (tmp & 1);
218        tmp >>= 1;
219        int pathbit = (path & 127);
220        path >>= 1;
221        updateGHist(tHist.gHist, dir, tHist.globalHistory, tHist.ptGhist);
222        tHist.pathHist = (tHist.pathHist << 1) ^ pathbit;
223        for (int i = 1; i <= nHistoryTables; i++) {
224            tHist.computeIndices[i].update(tHist.gHist);
225            tHist.computeTags[0][i].update(tHist.gHist);
226            tHist.computeTags[1][i].update(tHist.gHist);
227        }
228    }
229}
230
231bool
232MPP_TAGE::isHighConfidence(TAGEBase::BranchInfo *bi) const
233{
234    if (bi->hitBank > 0) {
235        return (abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1)) >=
236               ((1 << tagTableCounterBits) - 1);
237    } else {
238        int bim = (btablePrediction[bi->bimodalIndex] << 1)
239            + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries];
240        return (bim == 0) || (bim == 3);
241    }
242
243}
244
245MPP_TAGE*
246MPP_TAGEParams::create()
247{
248    return new MPP_TAGE(this);
249}
250
251bool
252MPP_LoopPredictor::calcConf(int index) const
253{
254    return LoopPredictor::calcConf(index) ||
255           (ltable[index].confidence * ltable[index].numIter > 128);
256}
257
258bool
259MPP_LoopPredictor::optionalAgeInc() const
260{
261    return ((random_mt.random<int>() & 7) == 0);
262}
263
264MPP_LoopPredictor*
265MPP_LoopPredictorParams::create()
266{
267    return new MPP_LoopPredictor(this);
268}
269
270MPP_StatisticalCorrector::MPP_StatisticalCorrector(
271        const MPP_StatisticalCorrectorParams *p) : StatisticalCorrector(p),
272    thirdH(0), pnb(p->pnb), logPnb(p->logPnb), pm(p->pm), gnb(p->gnb),
273    logGnb(p->logGnb), gm(p->gm)
274{
275    initGEHLTable(pnb, pm, pgehl, logPnb, wp, -1);
276    initGEHLTable(gnb, gm, ggehl, logGnb, wg, -1);
277
278    for (int8_t &pos : wl) {
279        pos = -1;
280    }
281}
282
283void
284MPP_StatisticalCorrector::initBias()
285{
286    for (int j = 0; j < (1 << logBias); j++) {
287        if (j & 1) {
288            bias[j] = 15;
289            biasSK[j] = 15;
290        } else {
291            bias[j] = -16;
292            biasSK[j] = -16;
293        }
294    }
295}
296
297unsigned
298MPP_StatisticalCorrector::getIndBias(Addr branch_pc,
299        StatisticalCorrector::BranchInfo* bi, bool bias) const
300{
301    unsigned int truncated_pc = branch_pc;
302    return ((truncated_pc << 1) + bi->predBeforeSC) & ((1 << logBias) - 1);
303}
304
305unsigned
306MPP_StatisticalCorrector::getIndBiasSK(Addr branch_pc,
307        StatisticalCorrector::BranchInfo* bi) const
308{
309    return (((branch_pc ^ (branch_pc >> (logBias - 1))) << 1)
310            + bi->predBeforeSC) & ((1 << logBias) - 1);
311}
312
313unsigned
314MPP_StatisticalCorrector::getIndBiasBank(Addr branch_pc,
315        StatisticalCorrector::BranchInfo* bi, int hitBank, int altBank) const
316{
317    return 0;
318}
319
320int
321MPP_StatisticalCorrector::gIndexLogsSubstr(int nbr, int i)
322{
323    return (i >= (nbr - 2)) ? 1 : 0;
324}
325
326unsigned
327MPP_StatisticalCorrector::getIndUpd(Addr branch_pc) const
328{
329    return ((branch_pc ^ (branch_pc >> 4)) & ((1 << (logSizeUp)) - 1));
330}
331
332void
333MPP_StatisticalCorrector::gUpdate(Addr branch_pc, bool taken, int64_t hist,
334                   std::vector<int> & length, std::vector<int8_t> * tab,
335                   int nbr, int logs, std::vector<int8_t> & w,
336                   StatisticalCorrector::BranchInfo* bi)
337{
338    int percsum = 0;
339    for (int i = 0; i < nbr; i++) {
340        int64_t bhist = hist & ((int64_t) ((1 << length[i]) - 1));
341        int64_t index = gIndex(branch_pc, bhist, logs, nbr, i);
342        percsum += (2 * tab[i][index] + 1);
343        ctrUpdate(tab[i][index], taken, scCountersWidth - (i < (nbr - 1)));
344    }
345}
346
347bool
348MPP_StatisticalCorrector::scPredict(ThreadID tid, Addr branch_pc,
349        bool cond_branch, StatisticalCorrector::BranchInfo* bi,
350        bool prev_pred_taken, bool bias_bit, bool use_conf_ctr,
351        int8_t conf_ctr, unsigned conf_bits, int hitBank, int altBank,
352        int64_t phist, int init_lsum)
353{
354    bool pred_taken = prev_pred_taken;
355    if (cond_branch) {
356
357        bi->predBeforeSC = prev_pred_taken;
358
359        int lsum = init_lsum;
360
361        getBiasLSUM(branch_pc, bi, lsum);
362
363        int thres = gPredictions(tid, branch_pc, bi, lsum, phist);
364
365        // These will be needed at update time
366        bi->lsum = lsum;
367        bi->thres = thres;
368        bi->scPred = (lsum >= 0);
369
370        if (pred_taken != bi->scPred) {
371            pred_taken = bi->scPred;
372
373            if (bi->highConf /* comes from tage prediction */) {
374              if ((abs(lsum) < thres / 3))
375                pred_taken = (firstH < 0) ? bi->scPred : prev_pred_taken;
376              else if ((abs(lsum) < 2 * thres / 3))
377                pred_taken = (secondH < 0) ? bi->scPred : prev_pred_taken;
378              else if ((abs(lsum) < thres))
379                pred_taken = (thirdH < 0) ? bi->scPred : prev_pred_taken;
380            }
381        }
382    }
383
384    return pred_taken;
385}
386
387MultiperspectivePerceptronTAGE::MultiperspectivePerceptronTAGE(
388    const MultiperspectivePerceptronTAGEParams *p)
389  : MultiperspectivePerceptron(p), tage(p->tage),
390    loopPredictor(p->loop_predictor),
391    statisticalCorrector(p->statistical_corrector)
392{
393    fatal_if(tage->isSpeculativeUpdateEnabled(),
394        "Speculative updates support is not implemented");
395}
396
397void
398MultiperspectivePerceptronTAGE::init()
399{
400    tage->init();
401    int numBitsTage = tage->getSizeInBits();
402    int numBitsLoopPred = loopPredictor->getSizeInBits();
403    int numBitsStatisticalCorrector = statisticalCorrector->getSizeInBits();
404
405    setExtraBits(numBitsTage + numBitsLoopPred + numBitsStatisticalCorrector);
406    MultiperspectivePerceptron::init();
407}
408
409
410unsigned int
411MultiperspectivePerceptronTAGE::getIndex(ThreadID tid, MPPTAGEBranchInfo &bi,
412        const HistorySpec &spec, int index) const
413{
414    // get the hash for the feature
415    unsigned int g = spec.getHash(tid, bi.getPC(), bi.getPC() >> 2, index);
416    // shift it and xor it with the hashed PC
417    unsigned long long int h = g;
418    h <<= 20;
419    h ^= (bi.getPC() ^ (bi.getPC() >> 2));
420
421    // maybe xor in an IMLI counter
422    if ((1ull << index) & imli_mask1) {
423        h += threadData[tid]->imli_counter[0];
424    }
425    if ((1ull << index) & imli_mask4) {
426        h += threadData[tid]->imli_counter[3];
427    }
428
429    // return it modulo the table size
430    return h % table_sizes[index];
431}
432
433
434int
435MultiperspectivePerceptronTAGE::computePartialSum(ThreadID tid,
436                                                  MPPTAGEBranchInfo &bi) const
437{
438    int yout = 0;
439    for (int i = 0; i < specs.size(); i += 1) {
440        yout += specs[i]->coeff *
441            threadData[tid]->tables[i][getIndex(tid, bi, *specs[i], i)];
442    }
443    return yout;
444}
445
446void
447MultiperspectivePerceptronTAGE::updatePartial(ThreadID tid,
448                                              MPPTAGEBranchInfo &bi,
449                                              bool taken)
450{
451    // update tables
452    for (int i = 0; i < specs.size(); i += 1) {
453        unsigned int idx = getIndex(tid, bi, *specs[i], i);
454        short int *c =
455            &threadData[tid]->tables[i][idx];
456        short int max_weight = (1 << (specs[i]->width - 1)) - 1;
457        short int min_weight = -(1 << (specs[i]->width - 1));
458        if (taken) {
459            if (*c < max_weight) {
460                *c += 1;
461            }
462        } else {
463            if (*c > min_weight) {
464                *c -= 1;
465            }
466        }
467    }
468}
469
470void
471MultiperspectivePerceptronTAGE::updateHistories(ThreadID tid,
472                                                MPPTAGEBranchInfo &bi,
473                                                bool taken)
474{
475    unsigned int hpc = (bi.getPC() ^ (bi.getPC() >> 2));
476    unsigned int pc = bi.getPC();
477
478    // update recency stack
479    unsigned short recency_pc = pc >> 2;
480    threadData[tid]->insertRecency(recency_pc, assoc);
481
482    // update acyclic history
483    threadData[tid]->updateAcyclic(taken, hpc);
484
485    // update modpath histories
486    for (int ii = 0; ii < modpath_indices.size(); ii +=1) {
487        int i = modpath_indices[ii];
488        if (hpc % (i + 2) == 0) {
489            memmove(&threadData[tid]->modpath_histories[i][1],
490                    &threadData[tid]->modpath_histories[i][0],
491                    sizeof(unsigned short int) * (modpath_lengths[ii] - 1));
492            threadData[tid]->modpath_histories[i][0] = hpc;
493        }
494    }
495
496    // update modulo histories
497    for (int ii = 0; ii < modhist_indices.size(); ii += 1) {
498        int i = modhist_indices[ii];
499        if (hpc % (i + 2) == 0) {
500            for (int j = modhist_lengths[ii] - 1; j > 0; j -= 1) {
501                threadData[tid]->mod_histories[i][j] =
502                    threadData[tid]->mod_histories[i][j-1];
503            }
504            threadData[tid]->mod_histories[i][0] = taken;
505        }
506    }
507
508    // update blurry history
509    std::vector<std::vector<unsigned int>> &blurrypath_histories =
510        threadData[tid]->blurrypath_histories;
511    for (int i = 0; i < blurrypath_histories.size(); i += 1)
512    {
513        if (blurrypath_histories[i].size() > 0) {
514            unsigned int z = pc >> i;
515            if (blurrypath_histories[i][0] != z) {
516                memmove(&blurrypath_histories[i][1],
517                        &blurrypath_histories[i][0],
518                        sizeof(unsigned int) *
519                        (blurrypath_histories[i].size() - 1));
520                blurrypath_histories[i][0] = z;
521            }
522        }
523    }
524}
525
526bool
527MultiperspectivePerceptronTAGE::lookup(ThreadID tid, Addr instPC,
528                                   void * &bp_history)
529{
530    MPPTAGEBranchInfo *bi =
531        new MPPTAGEBranchInfo(instPC, pcshift, true, *tage, *loopPredictor,
532                              *statisticalCorrector);
533    bp_history = (void *)bi;
534    bool pred_taken = tage->tagePredict(tid, instPC, true, bi->tageBranchInfo);
535
536    pred_taken = loopPredictor->loopPredict(tid, instPC, true,
537            bi->lpBranchInfo, pred_taken, instShiftAmt);
538
539    bi->scBranchInfo->highConf = tage->isHighConfidence(bi->tageBranchInfo);
540
541    int init_lsum = 22;
542    if (!pred_taken) {
543        init_lsum = -init_lsum;
544    }
545    init_lsum += computePartialSum(tid, *bi);
546
547    pred_taken = statisticalCorrector->scPredict(tid, instPC, true,
548            bi->scBranchInfo, pred_taken, false /* bias_bit: unused */,
549            false /* use_tage_ctr: unused */, 0 /* conf_ctr: unused */,
550            0 /* conf_bits: unused */, 0 /* hitBank: unused */,
551            0 /* altBank: unused */, tage->getPathHist(tid), init_lsum);
552    bi->predictedTaken = pred_taken;
553    bi->lpBranchInfo->predTaken = pred_taken;
554    return pred_taken;
555}
556
557
558void
559MPP_StatisticalCorrector::condBranchUpdate(ThreadID tid, Addr branch_pc,
560        bool taken, StatisticalCorrector::BranchInfo *bi, Addr corrTarget,
561        bool bias_bit, int hitBank, int altBank, int64_t phist)
562{
563    bool scPred = (bi->lsum >= 0);
564
565    if (bi->predBeforeSC != scPred) {
566        if (abs(bi->lsum) < bi->thres) {
567            if (bi->highConf) {
568                if (abs(bi->lsum) < bi->thres / 3) {
569                    ctrUpdate(firstH, (bi->predBeforeSC == taken),
570                              chooserConfWidth);
571                } else if (abs(bi->lsum) < 2 * bi->thres / 3) {
572                    ctrUpdate(secondH, (bi->predBeforeSC == taken),
573                              chooserConfWidth);
574                } else if (abs(bi->lsum) < bi->thres) {
575                    ctrUpdate(thirdH, (bi->predBeforeSC == taken),
576                              chooserConfWidth);
577                }
578            }
579        }
580    }
581
582    if ((scPred != taken) || ((abs(bi->lsum) < bi->thres))) {
583
584        ctrUpdate(pUpdateThreshold[getIndUpd(branch_pc)], (scPred != taken),
585                  pUpdateThresholdWidth + 1); //+1 because the sign is ignored
586        if (pUpdateThreshold[getIndUpd(branch_pc)] < 0)
587            pUpdateThreshold[getIndUpd(branch_pc)] = 0;
588
589        unsigned indBias = getIndBias(branch_pc, bi, false);
590        unsigned indBiasSK = getIndBiasSK(branch_pc, bi);
591
592        ctrUpdate(bias[indBias], taken, scCountersWidth);
593        ctrUpdate(biasSK[indBiasSK], taken, scCountersWidth);
594
595        gUpdates(tid, branch_pc, taken, bi, phist);
596    }
597}
598
599void
600MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken,
601                                   void *bp_history, bool squashed,
602                                   const StaticInstPtr & inst,
603                                   Addr corrTarget)
604{
605    assert(bp_history);
606    MPPTAGEBranchInfo *bi = static_cast<MPPTAGEBranchInfo*>(bp_history);
607
608    assert(corrTarget != MaxAddr);
609
610    if (squashed) {
611        if (tage->isSpeculativeUpdateEnabled()) {
612            // This restores the global history, then update it
613            // and recomputes the folded histories.
614            tage->squash(tid, taken, bi->tageBranchInfo, corrTarget);
615            if (bi->tageBranchInfo->condBranch) {
616                loopPredictor->squashLoop(bi->lpBranchInfo);
617            }
618        }
619        return;
620    }
621
622    if (bi->isUnconditional()) {
623        statisticalCorrector->scHistoryUpdate(instPC, inst, taken,
624                bi->scBranchInfo, corrTarget);
625        tage->updateHistories(tid, instPC, taken, bi->tageBranchInfo, false,
626                inst, corrTarget);
627    } else {
628        tage->updateStats(taken, bi->tageBranchInfo);
629        loopPredictor->updateStats(taken, bi->lpBranchInfo);
630        statisticalCorrector->updateStats(taken, bi->scBranchInfo);
631
632        loopPredictor->condBranchUpdate(tid, instPC, taken,
633                bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt);
634
635        bool scPred = (bi->scBranchInfo->lsum >= 0);
636        if ((scPred != taken) ||
637            ((abs(bi->scBranchInfo->lsum) < bi->scBranchInfo->thres))) {
638            updatePartial(tid, *bi, taken);
639        }
640        statisticalCorrector->condBranchUpdate(tid, instPC, taken,
641                bi->scBranchInfo, corrTarget, false /* bias_bit: unused */,
642                0 /* hitBank: unused */, 0 /* altBank: unused*/,
643                tage->getPathHist(tid));
644
645        tage->condBranchUpdate(tid, instPC, taken, bi->tageBranchInfo,
646                               random_mt.random<int>(), corrTarget,
647                               bi->predictedTaken, true);
648
649        updateHistories(tid, *bi, taken);
650
651        if (!tage->isSpeculativeUpdateEnabled()) {
652            if (inst->isCondCtrl() && inst->isDirectCtrl()
653                && !inst->isCall() && !inst->isReturn()) {
654                uint32_t truncated_target = corrTarget;
655                uint32_t truncated_pc = instPC;
656                if (truncated_target < truncated_pc) {
657                    if (!taken) {
658                        threadData[tid]->imli_counter[0] = 0;
659                    } else {
660                        threadData[tid]->imli_counter[0] += 1;
661                    }
662                } else {
663                    if (taken) {
664                        threadData[tid]->imli_counter[3] = 0;
665                    } else {
666                        threadData[tid]->imli_counter[3] += 1;
667                    }
668                }
669            }
670
671            statisticalCorrector->scHistoryUpdate(instPC, inst, taken,
672                    bi->scBranchInfo, corrTarget);
673
674            tage->updateHistories(tid, instPC, taken, bi->tageBranchInfo,
675                                  false, inst, corrTarget);
676        }
677    }
678    delete bi;
679}
680
681void
682MultiperspectivePerceptronTAGE::uncondBranch(ThreadID tid, Addr pc,
683                                             void * &bp_history)
684{
685    MPPTAGEBranchInfo *bi =
686        new MPPTAGEBranchInfo(pc, pcshift, false, *tage, *loopPredictor,
687                              *statisticalCorrector);
688    bp_history = (void *) bi;
689}
690
691void
692MultiperspectivePerceptronTAGE::squash(ThreadID tid, void *bp_history)
693{
694    assert(bp_history);
695    MPPTAGEBranchInfo *bi = static_cast<MPPTAGEBranchInfo*>(bp_history);
696    delete bi;
697}
698