| /* |
| * Copyright 2019 Texas A&M University |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3. Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * Author: Daniel A. Jiménez |
| * Adapted to gem5 by: Javier Bueno Hedo |
| * |
| */ |
| |
| /* |
| * Multiperspective Perceptron Predictor with TAGE (by Daniel A. Jiménez) |
| */ |
| |
| #include "cpu/pred/multiperspective_perceptron_tage.hh" |
| |
| #include "base/random.hh" |
| |
| namespace gem5 |
| { |
| |
| namespace branch_prediction |
| { |
| |
| void |
| MPP_TAGE::calculateParameters() |
| { |
| assert(tunedHistoryLengths.size() == (nHistoryTables+1)); |
| for (int i = 0; i <= nHistoryTables; i += 1) { |
| histLengths[i] = tunedHistoryLengths[i]; |
| } |
| } |
| |
| void |
| MPP_TAGE::handleTAGEUpdate(Addr branch_pc, bool taken, |
| TAGEBase::BranchInfo* bi) |
| { |
| if (bi->hitBank > 0) { |
| if (abs (2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) == 1) { |
| if (bi->longestMatchPred != taken) { |
| // acts as a protection |
| if (bi->altBank > 0) { |
| ctrUpdate(gtable[bi->altBank][bi->altBankIndex].ctr, taken, |
| tagTableCounterBits); |
| } |
| if (bi->altBank == 0){ |
| baseUpdate(branch_pc, taken, bi); |
| } |
| } |
| } |
| |
| ctrUpdate(gtable[bi->hitBank][bi->hitBankIndex].ctr, taken, |
| tagTableCounterBits); |
| |
| //sign changes: no way it can have been useful |
| if (abs (2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1) == 1) { |
| gtable[bi->hitBank][bi->hitBankIndex].u = 0; |
| } |
| } else { |
| baseUpdate(branch_pc, taken, bi); |
| } |
| |
| if ((bi->longestMatchPred != bi->altTaken) && |
| (bi->longestMatchPred == taken) && |
| (gtable[bi->hitBank][bi->hitBankIndex].u < (1 << tagTableUBits) -1)) { |
| gtable[bi->hitBank][bi->hitBankIndex].u++; |
| } |
| } |
| |
| void |
| MPP_TAGE::handleAllocAndUReset(bool alloc, bool taken, |
| TAGEBase::BranchInfo* bi, int nrand) |
| { |
| if (!alloc) { |
| return; |
| } |
| |
| int a = 1; |
| |
| if ((random_mt.random<int>() & 127) < 32) { |
| a = 2; |
| } |
| int dep = bi->hitBank + a; |
| |
| int penalty = 0; |
| int numAllocated = 0; |
| int T = 1; |
| |
| for (int i = dep; i <= nHistoryTables; i += 1) { |
| if (noSkip[i]) { |
| if (gtable[i][bi->tableIndices[i]].u == 0) { |
| gtable[i][bi->tableIndices[i]].tag = bi->tableTags[i]; |
| gtable[i][bi->tableIndices[i]].ctr = taken ? 0 : -1; |
| numAllocated++; |
| if (T <= 0) { |
| break; |
| } |
| i += 1; |
| T -= 1; |
| } else { |
| penalty++; |
| } |
| } else { assert(false); } |
| } |
| |
| tCounter += (penalty - numAllocated); |
| |
| handleUReset(); |
| } |
| |
| void |
| MPP_TAGE::handleUReset() |
| { |
| //just the best formula for the Championship: |
| //In practice when one out of two entries are useful |
| if (tCounter < 0) { |
| tCounter = 0; |
| } |
| |
| if (tCounter >= ((1ULL << logUResetPeriod))) { |
| // Update the u bits for the short tags table |
| for (int i = 1; i <= nHistoryTables; i++) { |
| for (int j = 0; j < (1ULL << logTagTableSizes[i]); j++) { |
| resetUctr(gtable[i][j].u); |
| } |
| } |
| |
| tCounter = 0; |
| } |
| } |
| |
| void |
| MPP_TAGE::resetUctr(uint8_t &u) |
| { |
| // On real HW it should be u >>= 1 instead of if > 0 then u-- |
| if (u > 0) { |
| u--; |
| } |
| } |
| |
| |
| int |
| MPP_TAGE::bindex(Addr pc_in) const |
| { |
| uint32_t pc = (uint32_t) pc_in; |
| return ((pc ^ (pc >> 4)) & ((1ULL << (logTagTableSizes[0])) - 1)); |
| } |
| |
| unsigned |
| MPP_TAGE::getUseAltIdx(TAGEBase::BranchInfo* bi, Addr branch_pc) |
| { |
| uint32_t hpc = ((uint32_t) branch_pc); |
| hpc = (hpc ^(hpc >> 4)); |
| return 2 * ((hpc & ((numUseAltOnNa/2)-1)) ^ bi->longestMatchPred) + |
| ((bi->hitBank > (nHistoryTables / 3)) ? 1 : 0); |
| } |
| |
| void |
| MPP_TAGE::adjustAlloc(bool & alloc, bool taken, bool pred_taken) |
| { |
| // Do not allocate too often if the prediction is ok |
| if ((taken == pred_taken) && ((random_mt.random<int>() & 31) != 0)) { |
| alloc = false; |
| } |
| } |
| |
| void |
| MPP_TAGE::updateHistories( |
| ThreadID tid, Addr branch_pc, bool taken, TAGEBase::BranchInfo* b, |
| bool speculative, const StaticInstPtr &inst, Addr target) |
| { |
| if (speculative != speculativeHistUpdate) { |
| return; |
| } |
| // speculation is not implemented |
| assert(! speculative); |
| |
| ThreadHistory& tHist = threadHistory[tid]; |
| |
| int brtype = inst->isDirectCtrl() ? 0 : 2; |
| if (! inst->isUncondCtrl()) { |
| ++brtype; |
| } |
| updatePathAndGlobalHistory(tHist, brtype, taken, branch_pc, target); |
| } |
| |
| void |
| MPP_TAGE::updatePathAndGlobalHistory( |
| ThreadHistory& tHist, int brtype, bool taken, Addr branch_pc, Addr target) |
| { |
| // TAGE update |
| int tmp = (branch_pc << 1) + taken; |
| int path = branch_pc; |
| |
| int maxt = (brtype & 1) ? 1 : 4; |
| |
| for (int t = 0; t < maxt; t++) { |
| bool dir = (tmp & 1); |
| tmp >>= 1; |
| int pathbit = (path & 127); |
| path >>= 1; |
| updateGHist(tHist.gHist, dir, tHist.globalHistory, tHist.ptGhist); |
| tHist.pathHist = (tHist.pathHist << 1) ^ pathbit; |
| for (int i = 1; i <= nHistoryTables; i++) { |
| tHist.computeIndices[i].update(tHist.gHist); |
| tHist.computeTags[0][i].update(tHist.gHist); |
| tHist.computeTags[1][i].update(tHist.gHist); |
| } |
| } |
| } |
| |
| bool |
| MPP_TAGE::isHighConfidence(TAGEBase::BranchInfo *bi) const |
| { |
| if (bi->hitBank > 0) { |
| return (abs(2 * gtable[bi->hitBank][bi->hitBankIndex].ctr + 1)) >= |
| ((1 << tagTableCounterBits) - 1); |
| } else { |
| int bim = (btablePrediction[bi->bimodalIndex] << 1) |
| + btableHysteresis[bi->bimodalIndex >> logRatioBiModalHystEntries]; |
| return (bim == 0) || (bim == 3); |
| } |
| |
| } |
| |
| bool |
| MPP_LoopPredictor::calcConf(int index) const |
| { |
| return LoopPredictor::calcConf(index) || |
| (ltable[index].confidence * ltable[index].numIter > 128); |
| } |
| |
| bool |
| MPP_LoopPredictor::optionalAgeInc() const |
| { |
| return ((random_mt.random<int>() & 7) == 0); |
| } |
| |
| MPP_StatisticalCorrector::MPP_StatisticalCorrector( |
| const MPP_StatisticalCorrectorParams &p) : StatisticalCorrector(p), |
| thirdH(0), pnb(p.pnb), logPnb(p.logPnb), pm(p.pm), gnb(p.gnb), |
| logGnb(p.logGnb), gm(p.gm) |
| { |
| initGEHLTable(pnb, pm, pgehl, logPnb, wp, -1); |
| initGEHLTable(gnb, gm, ggehl, logGnb, wg, -1); |
| |
| for (int8_t &pos : wl) { |
| pos = -1; |
| } |
| } |
| |
| void |
| MPP_StatisticalCorrector::initBias() |
| { |
| for (int j = 0; j < (1 << logBias); j++) { |
| if (j & 1) { |
| bias[j] = 15; |
| biasSK[j] = 15; |
| } else { |
| bias[j] = -16; |
| biasSK[j] = -16; |
| } |
| } |
| } |
| |
| unsigned |
| MPP_StatisticalCorrector::getIndBias(Addr branch_pc, |
| StatisticalCorrector::BranchInfo* bi, bool bias) const |
| { |
| unsigned int truncated_pc = branch_pc; |
| return ((truncated_pc << 1) + bi->predBeforeSC) & ((1 << logBias) - 1); |
| } |
| |
| unsigned |
| MPP_StatisticalCorrector::getIndBiasSK(Addr branch_pc, |
| StatisticalCorrector::BranchInfo* bi) const |
| { |
| return (((branch_pc ^ (branch_pc >> (logBias - 1))) << 1) |
| + bi->predBeforeSC) & ((1 << logBias) - 1); |
| } |
| |
| unsigned |
| MPP_StatisticalCorrector::getIndBiasBank(Addr branch_pc, |
| StatisticalCorrector::BranchInfo* bi, int hitBank, int altBank) const |
| { |
| return 0; |
| } |
| |
| int |
| MPP_StatisticalCorrector::gIndexLogsSubstr(int nbr, int i) |
| { |
| return (i >= (nbr - 2)) ? 1 : 0; |
| } |
| |
| unsigned |
| MPP_StatisticalCorrector::getIndUpd(Addr branch_pc) const |
| { |
| return ((branch_pc ^ (branch_pc >> 4)) & ((1 << (logSizeUp)) - 1)); |
| } |
| |
| void |
| MPP_StatisticalCorrector::gUpdate(Addr branch_pc, bool taken, int64_t hist, |
| std::vector<int> & length, std::vector<int8_t> * tab, |
| int nbr, int logs, std::vector<int8_t> & w, |
| StatisticalCorrector::BranchInfo* bi) |
| { |
| int percsum = 0; |
| for (int i = 0; i < nbr; i++) { |
| int64_t bhist = hist & ((int64_t) ((1 << length[i]) - 1)); |
| int64_t index = gIndex(branch_pc, bhist, logs, nbr, i); |
| percsum += (2 * tab[i][index] + 1); |
| ctrUpdate(tab[i][index], taken, scCountersWidth - (i < (nbr - 1))); |
| } |
| } |
| |
| bool |
| MPP_StatisticalCorrector::scPredict(ThreadID tid, Addr branch_pc, |
| bool cond_branch, StatisticalCorrector::BranchInfo* bi, |
| bool prev_pred_taken, bool bias_bit, bool use_conf_ctr, |
| int8_t conf_ctr, unsigned conf_bits, int hitBank, int altBank, |
| int64_t phist, int init_lsum) |
| { |
| bool pred_taken = prev_pred_taken; |
| if (cond_branch) { |
| |
| bi->predBeforeSC = prev_pred_taken; |
| |
| int lsum = init_lsum; |
| |
| getBiasLSUM(branch_pc, bi, lsum); |
| |
| int thres = gPredictions(tid, branch_pc, bi, lsum, phist); |
| |
| // These will be needed at update time |
| bi->lsum = lsum; |
| bi->thres = thres; |
| bi->scPred = (lsum >= 0); |
| |
| if (pred_taken != bi->scPred) { |
| pred_taken = bi->scPred; |
| |
| if (bi->highConf /* comes from tage prediction */) { |
| if ((abs(lsum) < thres / 3)) |
| pred_taken = (firstH < 0) ? bi->scPred : prev_pred_taken; |
| else if ((abs(lsum) < 2 * thres / 3)) |
| pred_taken = (secondH < 0) ? bi->scPred : prev_pred_taken; |
| else if ((abs(lsum) < thres)) |
| pred_taken = (thirdH < 0) ? bi->scPred : prev_pred_taken; |
| } |
| } |
| } |
| |
| return pred_taken; |
| } |
| |
| MultiperspectivePerceptronTAGE::MultiperspectivePerceptronTAGE( |
| const MultiperspectivePerceptronTAGEParams &p) |
| : MultiperspectivePerceptron(p), tage(p.tage), |
| loopPredictor(p.loop_predictor), |
| statisticalCorrector(p.statistical_corrector) |
| { |
| fatal_if(tage->isSpeculativeUpdateEnabled(), |
| "Speculative updates support is not implemented"); |
| } |
| |
| void |
| MultiperspectivePerceptronTAGE::init() |
| { |
| tage->init(); |
| int numBitsTage = tage->getSizeInBits(); |
| int numBitsLoopPred = loopPredictor->getSizeInBits(); |
| int numBitsStatisticalCorrector = statisticalCorrector->getSizeInBits(); |
| |
| setExtraBits(numBitsTage + numBitsLoopPred + numBitsStatisticalCorrector); |
| MultiperspectivePerceptron::init(); |
| } |
| |
| |
| unsigned int |
| MultiperspectivePerceptronTAGE::getIndex(ThreadID tid, MPPTAGEBranchInfo &bi, |
| const HistorySpec &spec, int index) const |
| { |
| // get the hash for the feature |
| unsigned int g = spec.getHash(tid, bi.getPC(), bi.getPC() >> 2, index); |
| // shift it and xor it with the hashed PC |
| unsigned long long int h = g; |
| h <<= 20; |
| h ^= (bi.getPC() ^ (bi.getPC() >> 2)); |
| |
| // maybe xor in an IMLI counter |
| if ((1ull << index) & imli_mask1) { |
| h += threadData[tid]->imli_counter[0]; |
| } |
| if ((1ull << index) & imli_mask4) { |
| h += threadData[tid]->imli_counter[3]; |
| } |
| |
| // return it modulo the table size |
| return h % table_sizes[index]; |
| } |
| |
| |
| int |
| MultiperspectivePerceptronTAGE::computePartialSum(ThreadID tid, |
| MPPTAGEBranchInfo &bi) const |
| { |
| int yout = 0; |
| for (int i = 0; i < specs.size(); i += 1) { |
| yout += specs[i]->coeff * |
| threadData[tid]->tables[i][getIndex(tid, bi, *specs[i], i)]; |
| } |
| return yout; |
| } |
| |
| void |
| MultiperspectivePerceptronTAGE::updatePartial(ThreadID tid, |
| MPPTAGEBranchInfo &bi, |
| bool taken) |
| { |
| // update tables |
| for (int i = 0; i < specs.size(); i += 1) { |
| unsigned int idx = getIndex(tid, bi, *specs[i], i); |
| short int *c = |
| &threadData[tid]->tables[i][idx]; |
| short int max_weight = (1 << (specs[i]->width - 1)) - 1; |
| short int min_weight = -(1 << (specs[i]->width - 1)); |
| if (taken) { |
| if (*c < max_weight) { |
| *c += 1; |
| } |
| } else { |
| if (*c > min_weight) { |
| *c -= 1; |
| } |
| } |
| } |
| } |
| |
| void |
| MultiperspectivePerceptronTAGE::updateHistories(ThreadID tid, |
| MPPTAGEBranchInfo &bi, |
| bool taken) |
| { |
| unsigned int hpc = (bi.getPC() ^ (bi.getPC() >> 2)); |
| unsigned int pc = bi.getPC(); |
| |
| // update recency stack |
| unsigned short recency_pc = pc >> 2; |
| threadData[tid]->insertRecency(recency_pc, assoc); |
| |
| // update acyclic history |
| threadData[tid]->updateAcyclic(taken, hpc); |
| |
| // update modpath histories |
| for (int ii = 0; ii < modpath_indices.size(); ii +=1) { |
| int i = modpath_indices[ii]; |
| if (hpc % (i + 2) == 0) { |
| memmove(&threadData[tid]->modpath_histories[i][1], |
| &threadData[tid]->modpath_histories[i][0], |
| sizeof(unsigned short int) * (modpath_lengths[ii] - 1)); |
| threadData[tid]->modpath_histories[i][0] = hpc; |
| } |
| } |
| |
| // update modulo histories |
| for (int ii = 0; ii < modhist_indices.size(); ii += 1) { |
| int i = modhist_indices[ii]; |
| if (hpc % (i + 2) == 0) { |
| for (int j = modhist_lengths[ii] - 1; j > 0; j -= 1) { |
| threadData[tid]->mod_histories[i][j] = |
| threadData[tid]->mod_histories[i][j-1]; |
| } |
| threadData[tid]->mod_histories[i][0] = taken; |
| } |
| } |
| |
| // update blurry history |
| std::vector<std::vector<unsigned int>> &blurrypath_histories = |
| threadData[tid]->blurrypath_histories; |
| for (int i = 0; i < blurrypath_histories.size(); i += 1) |
| { |
| if (blurrypath_histories[i].size() > 0) { |
| unsigned int z = pc >> i; |
| if (blurrypath_histories[i][0] != z) { |
| memmove(&blurrypath_histories[i][1], |
| &blurrypath_histories[i][0], |
| sizeof(unsigned int) * |
| (blurrypath_histories[i].size() - 1)); |
| blurrypath_histories[i][0] = z; |
| } |
| } |
| } |
| } |
| |
| bool |
| MultiperspectivePerceptronTAGE::lookup(ThreadID tid, Addr instPC, |
| void * &bp_history) |
| { |
| MPPTAGEBranchInfo *bi = |
| new MPPTAGEBranchInfo(instPC, pcshift, true, *tage, *loopPredictor, |
| *statisticalCorrector); |
| bp_history = (void *)bi; |
| bool pred_taken = tage->tagePredict(tid, instPC, true, bi->tageBranchInfo); |
| |
| pred_taken = loopPredictor->loopPredict(tid, instPC, true, |
| bi->lpBranchInfo, pred_taken, instShiftAmt); |
| |
| bi->scBranchInfo->highConf = tage->isHighConfidence(bi->tageBranchInfo); |
| |
| int init_lsum = 22; |
| if (!pred_taken) { |
| init_lsum = -init_lsum; |
| } |
| init_lsum += computePartialSum(tid, *bi); |
| |
| pred_taken = statisticalCorrector->scPredict(tid, instPC, true, |
| bi->scBranchInfo, pred_taken, false /* bias_bit: unused */, |
| false /* use_tage_ctr: unused */, 0 /* conf_ctr: unused */, |
| 0 /* conf_bits: unused */, 0 /* hitBank: unused */, |
| 0 /* altBank: unused */, tage->getPathHist(tid), init_lsum); |
| bi->predictedTaken = pred_taken; |
| bi->lpBranchInfo->predTaken = pred_taken; |
| return pred_taken; |
| } |
| |
| |
| void |
| MPP_StatisticalCorrector::condBranchUpdate(ThreadID tid, Addr branch_pc, |
| bool taken, StatisticalCorrector::BranchInfo *bi, Addr corrTarget, |
| bool bias_bit, int hitBank, int altBank, int64_t phist) |
| { |
| bool scPred = (bi->lsum >= 0); |
| |
| if (bi->predBeforeSC != scPred) { |
| if (abs(bi->lsum) < bi->thres) { |
| if (bi->highConf) { |
| if (abs(bi->lsum) < bi->thres / 3) { |
| ctrUpdate(firstH, (bi->predBeforeSC == taken), |
| chooserConfWidth); |
| } else if (abs(bi->lsum) < 2 * bi->thres / 3) { |
| ctrUpdate(secondH, (bi->predBeforeSC == taken), |
| chooserConfWidth); |
| } else if (abs(bi->lsum) < bi->thres) { |
| ctrUpdate(thirdH, (bi->predBeforeSC == taken), |
| chooserConfWidth); |
| } |
| } |
| } |
| } |
| |
| if ((scPred != taken) || ((abs(bi->lsum) < bi->thres))) { |
| |
| ctrUpdate(pUpdateThreshold[getIndUpd(branch_pc)], (scPred != taken), |
| pUpdateThresholdWidth + 1); //+1 because the sign is ignored |
| if (pUpdateThreshold[getIndUpd(branch_pc)] < 0) |
| pUpdateThreshold[getIndUpd(branch_pc)] = 0; |
| |
| unsigned indBias = getIndBias(branch_pc, bi, false); |
| unsigned indBiasSK = getIndBiasSK(branch_pc, bi); |
| |
| ctrUpdate(bias[indBias], taken, scCountersWidth); |
| ctrUpdate(biasSK[indBiasSK], taken, scCountersWidth); |
| |
| gUpdates(tid, branch_pc, taken, bi, phist); |
| } |
| } |
| |
| void |
| MultiperspectivePerceptronTAGE::update(ThreadID tid, Addr instPC, bool taken, |
| void *bp_history, bool squashed, |
| const StaticInstPtr & inst, |
| Addr corrTarget) |
| { |
| assert(bp_history); |
| MPPTAGEBranchInfo *bi = static_cast<MPPTAGEBranchInfo*>(bp_history); |
| |
| if (squashed) { |
| if (tage->isSpeculativeUpdateEnabled()) { |
| // This restores the global history, then update it |
| // and recomputes the folded histories. |
| tage->squash(tid, taken, bi->tageBranchInfo, corrTarget); |
| if (bi->tageBranchInfo->condBranch) { |
| loopPredictor->squashLoop(bi->lpBranchInfo); |
| } |
| } |
| return; |
| } |
| |
| if (bi->isUnconditional()) { |
| statisticalCorrector->scHistoryUpdate(instPC, inst, taken, |
| bi->scBranchInfo, corrTarget); |
| tage->updateHistories(tid, instPC, taken, bi->tageBranchInfo, false, |
| inst, corrTarget); |
| } else { |
| tage->updateStats(taken, bi->tageBranchInfo); |
| loopPredictor->updateStats(taken, bi->lpBranchInfo); |
| statisticalCorrector->updateStats(taken, bi->scBranchInfo); |
| |
| loopPredictor->condBranchUpdate(tid, instPC, taken, |
| bi->tageBranchInfo->tagePred, bi->lpBranchInfo, instShiftAmt); |
| |
| bool scPred = (bi->scBranchInfo->lsum >= 0); |
| if ((scPred != taken) || |
| ((abs(bi->scBranchInfo->lsum) < bi->scBranchInfo->thres))) { |
| updatePartial(tid, *bi, taken); |
| } |
| statisticalCorrector->condBranchUpdate(tid, instPC, taken, |
| bi->scBranchInfo, corrTarget, false /* bias_bit: unused */, |
| 0 /* hitBank: unused */, 0 /* altBank: unused*/, |
| tage->getPathHist(tid)); |
| |
| tage->condBranchUpdate(tid, instPC, taken, bi->tageBranchInfo, |
| random_mt.random<int>(), corrTarget, |
| bi->predictedTaken, true); |
| |
| updateHistories(tid, *bi, taken); |
| |
| if (!tage->isSpeculativeUpdateEnabled()) { |
| if (inst->isCondCtrl() && inst->isDirectCtrl() |
| && !inst->isCall() && !inst->isReturn()) { |
| uint32_t truncated_target = corrTarget; |
| uint32_t truncated_pc = instPC; |
| if (truncated_target < truncated_pc) { |
| if (!taken) { |
| threadData[tid]->imli_counter[0] = 0; |
| } else { |
| threadData[tid]->imli_counter[0] += 1; |
| } |
| } else { |
| if (taken) { |
| threadData[tid]->imli_counter[3] = 0; |
| } else { |
| threadData[tid]->imli_counter[3] += 1; |
| } |
| } |
| } |
| |
| statisticalCorrector->scHistoryUpdate(instPC, inst, taken, |
| bi->scBranchInfo, corrTarget); |
| |
| tage->updateHistories(tid, instPC, taken, bi->tageBranchInfo, |
| false, inst, corrTarget); |
| } |
| } |
| delete bi; |
| } |
| |
| void |
| MultiperspectivePerceptronTAGE::uncondBranch(ThreadID tid, Addr pc, |
| void * &bp_history) |
| { |
| MPPTAGEBranchInfo *bi = |
| new MPPTAGEBranchInfo(pc, pcshift, false, *tage, *loopPredictor, |
| *statisticalCorrector); |
| bp_history = (void *) bi; |
| } |
| |
| void |
| MultiperspectivePerceptronTAGE::squash(ThreadID tid, void *bp_history) |
| { |
| assert(bp_history); |
| MPPTAGEBranchInfo *bi = static_cast<MPPTAGEBranchInfo*>(bp_history); |
| delete bi; |
| } |
| |
| } // namespace branch_prediction |
| } // namespace gem5 |