From: Pau Cabre Date: Thu, 22 Nov 2018 13:48:30 +0000 (+0100) Subject: cpu: Added new stats to TAGE and LTAGE branch predictors X-Git-Tag: v19.0.0.0~1364 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=86b23a175c9985ecbfae710ba2b0fd6f629650df;p=gem5.git cpu: Added new stats to TAGE and LTAGE branch predictors They are basically used to tell wich component of the predictor is providing the prediction and whether it is correct or wrong Change-Id: I7b3db66535f159091f1b37d70c2d942d50b20fb2 Signed-off-by: Pau Cabre Reviewed-on: https://gem5-review.googlesource.com/c/14535 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power --- diff --git a/src/cpu/pred/ltage.cc b/src/cpu/pred/ltage.cc index 3be01936e..73f477745 100644 --- a/src/cpu/pred/ltage.cc +++ b/src/cpu/pred/ltage.cc @@ -228,6 +228,7 @@ LTAGE::predict(ThreadID tid, Addr branch_pc, bool cond_branch, void* &b) if ((loopUseCounter >= 0) && bi->loopPredValid) { pred_taken = bi->loopPred; + bi->provider = LOOP; } DPRINTF(LTage, "Predict for %lx: taken?:%d, loopTaken?:%d, " "loopValid?:%d, loopUseCounter:%d, tagePred:%d, altPred:%d\n", @@ -288,6 +289,43 @@ LTAGE::squash(ThreadID tid, void *bp_history) TAGE::squash(tid, bp_history); } + +void +LTAGE::updateStats(bool taken, TageBranchInfo* bi) +{ + TAGE::updateStats(taken, bi); + + LTageBranchInfo * ltage_bi = static_cast(bi); + + if (ltage_bi->provider == LOOP) { + if (taken == ltage_bi->loopPred) { + loopPredictorCorrect++; + } else { + loopPredictorWrong++; + } + } +} + + + +void +LTAGE::regStats() +{ + TAGE::regStats(); + + loopPredictorCorrect + .name(name() + ".loopPredictorCorrect") + .desc("Number of times the loop predictor is the provider and " + "the prediction is correct"); + + loopPredictorWrong + .name(name() + ".loopPredictorWrong") + .desc("Number of times the loop predictor is the provier and " + "the prediction is wrong"); +} + + + LTAGE* LTAGEParams::create() { diff --git a/src/cpu/pred/ltage.hh b/src/cpu/pred/ltage.hh index d614026d2..e9e34b75d 100644 --- a/src/cpu/pred/ltage.hh +++ b/src/cpu/pred/ltage.hh @@ -67,6 +67,8 @@ class LTAGE: public TAGE // Base class methods. void squash(ThreadID tid, void *bp_history) override; + void regStats() override; + private: // Prediction Structures // Loop Predictor Entry @@ -84,6 +86,11 @@ class LTAGE: public TAGE confidence(0), tag(0), age(0), dir(0) { } }; + // more provider types + enum { + LOOP = LAST_TAGE_PROVIDER_TYPE + 1 + }; + // Primary branch history entry struct LTageBranchInfo : public TageBranchInfo { @@ -177,6 +184,14 @@ class LTAGE: public TAGE void squash( ThreadID tid, bool taken, void *bp_history) override; + /** + * Update the stats + * @param taken Actual branch outcome + * @param bi Pointer to information on the prediction + * recorded at prediction time. + */ + void updateStats(bool taken, TageBranchInfo* bi) override; + const unsigned logSizeLoopPred; const unsigned loopTableAgeBits; const unsigned loopTableConfidenceBits; @@ -191,6 +206,10 @@ class LTAGE: public TAGE int8_t loopUseCounter; unsigned withLoopBits; + + // stats + Stats::Scalar loopPredictorCorrect; + Stats::Scalar loopPredictorWrong; }; #endif // __CPU_PRED_LTAGE diff --git a/src/cpu/pred/tage.cc b/src/cpu/pred/tage.cc index c22e6b7a5..061f808e8 100644 --- a/src/cpu/pred/tage.cc +++ b/src/cpu/pred/tage.cc @@ -348,16 +348,19 @@ TAGE::tagePredict(ThreadID tid, Addr branch_pc, //if the entry is recognized as a newly allocated entry and //useAltPredForNewlyAllocated is positive use the alternate //prediction - if ((useAltPredForNewlyAllocated < 0) - || abs(2 * - gtable[bi->hitBank][tableIndices[bi->hitBank]].ctr + 1) > 1) + if ((useAltPredForNewlyAllocated < 0) || ! bi->pseudoNewAlloc) { bi->tagePred = bi->longestMatchPred; - else + bi->provider = TAGE_LONGEST_MATCH; + } else { bi->tagePred = bi->altTaken; + bi->provider = bi->altBank ? TAGE_ALT_MATCH + : BIMODAL_ALT_MATCH; + } } else { bi->altTaken = getBimodePred(pc, bi); bi->tagePred = bi->altTaken; bi->longestMatchPred = bi->altTaken; + bi->provider = BIMODAL_ONLY; } //end TAGE prediction @@ -390,6 +393,7 @@ TAGE::update(ThreadID tid, Addr branch_pc, bool taken, void* bp_history, if (bi->condBranch) { DPRINTF(Tage, "Updating tables for branch:%lx; taken?:%d\n", branch_pc, taken); + updateStats(taken, bi); condBranchUpdate(branch_pc, taken, bi, nrand); } if (!squashed) { @@ -602,6 +606,119 @@ TAGE::uncondBranch(ThreadID tid, Addr br_pc, void* &bp_history) &threadHistory[tid].globalHistory[threadHistory[tid].ptGhist]); } +void +TAGE::updateStats(bool taken, TageBranchInfo* bi) +{ + if (taken == bi->tagePred) { + // correct prediction + switch (bi->provider) { + case BIMODAL_ONLY: tageBimodalProviderCorrect++; break; + case TAGE_LONGEST_MATCH: tageLongestMatchProviderCorrect++; break; + case BIMODAL_ALT_MATCH: bimodalAltMatchProviderCorrect++; break; + case TAGE_ALT_MATCH: tageAltMatchProviderCorrect++; break; + } + } else { + // wrong prediction + switch (bi->provider) { + case BIMODAL_ONLY: tageBimodalProviderWrong++; break; + case TAGE_LONGEST_MATCH: + tageLongestMatchProviderWrong++; + if (bi->altTaken == taken) { + tageAltMatchProviderWouldHaveHit++; + } + break; + case BIMODAL_ALT_MATCH: + bimodalAltMatchProviderWrong++; + break; + case TAGE_ALT_MATCH: + tageAltMatchProviderWrong++; + break; + } + + switch (bi->provider) { + case BIMODAL_ALT_MATCH: + case TAGE_ALT_MATCH: + if (bi->longestMatchPred == taken) { + tageLongestMatchProviderWouldHaveHit++; + } + } + } + + switch (bi->provider) { + case TAGE_LONGEST_MATCH: + case TAGE_ALT_MATCH: + tageLongestMatchProvider[bi->hitBank]++; + tageAltMatchProvider[bi->altBank]++; + break; + } +} + +void +TAGE::regStats() +{ + BPredUnit::regStats(); + + tageLongestMatchProviderCorrect + .name(name() + ".tageLongestMatchProviderCorrect") + .desc("Number of times TAGE Longest Match is the provider and " + "the prediction is correct"); + + tageAltMatchProviderCorrect + .name(name() + ".tageAltMatchProviderCorrect") + .desc("Number of times TAGE Alt Match is the provider and " + "the prediction is correct"); + + bimodalAltMatchProviderCorrect + .name(name() + ".bimodalAltMatchProviderCorrect") + .desc("Number of times TAGE Alt Match is the bimodal and it is the " + "provider and the prediction is correct"); + + tageBimodalProviderCorrect + .name(name() + ".tageBimodalProviderCorrect") + .desc("Number of times there are no hits on the TAGE tables " + "and the bimodal prediction is correct"); + + tageLongestMatchProviderWrong + .name(name() + ".tageLongestMatchProviderWrong") + .desc("Number of times TAGE Longest Match is the provider and " + "the prediction is wrong"); + + tageAltMatchProviderWrong + .name(name() + ".tageAltMatchProviderWrong") + .desc("Number of times TAGE Alt Match is the provider and " + "the prediction is wrong"); + + bimodalAltMatchProviderWrong + .name(name() + ".bimodalAltMatchProviderWrong") + .desc("Number of times TAGE Alt Match is the bimodal and it is the " + "provider and the prediction is wrong"); + + tageBimodalProviderWrong + .name(name() + ".tageBimodalProviderWrong") + .desc("Number of times there are no hits on the TAGE tables " + "and the bimodal prediction is wrong"); + + tageAltMatchProviderWouldHaveHit + .name(name() + ".tageAltMatchProviderWouldHaveHit") + .desc("Number of times TAGE Longest Match is the provider, " + "the prediction is wrong and Alt Match prediction was correct"); + + tageLongestMatchProviderWouldHaveHit + .name(name() + ".tageLongestMatchProviderWouldHaveHit") + .desc("Number of times TAGE Alt Match is the provider, the " + "prediction is wrong and Longest Match prediction was correct"); + + tageLongestMatchProvider + .init(nHistoryTables + 1) + .name(name() + ".tageLongestMatchProvider") + .desc("TAGE provider for longest match"); + + tageAltMatchProvider + .init(nHistoryTables + 1) + .name(name() + ".tageAltMatchProvider") + .desc("TAGE provider for alt match"); +} + TAGE* TAGEParams::create() { diff --git a/src/cpu/pred/tage.hh b/src/cpu/pred/tage.hh index 9ba02414c..c66c28cb1 100644 --- a/src/cpu/pred/tage.hh +++ b/src/cpu/pred/tage.hh @@ -71,6 +71,8 @@ class TAGE: public BPredUnit virtual void squash(ThreadID tid, void *bp_history) override; unsigned getGHR(ThreadID tid, void *bp_history) const override; + virtual void regStats() override; + protected: // Prediction Structures @@ -110,6 +112,15 @@ class TAGE: public BPredUnit } }; + // provider type + enum { + BIMODAL_ONLY = 0, + TAGE_LONGEST_MATCH, + BIMODAL_ALT_MATCH, + TAGE_ALT_MATCH, + LAST_TAGE_PROVIDER_TYPE = TAGE_ALT_MATCH + }; + // Primary branch history entry struct TageBranchInfo { @@ -141,6 +152,9 @@ class TAGE: public BPredUnit int *ct0; int *ct1; + // for stats purposes + unsigned provider; + TageBranchInfo(int sz) : pathHist(0), ptGhist(0), hitBank(0), hitBankIndex(0), @@ -148,7 +162,8 @@ class TAGE: public BPredUnit bimodalIndex(0), tagePred(false), altTaken(false), condBranch(false), longestMatchPred(false), - pseudoNewAlloc(false), branchPC(0) + pseudoNewAlloc(false), branchPC(0), + provider(-1) { storage = new int [sz * 5]; tableIndices = storage; @@ -320,6 +335,14 @@ class TAGE: public BPredUnit bool tagePredict( ThreadID tid, Addr branch_pc, bool cond_branch, TageBranchInfo* bi); + /** + * Update the stats + * @param taken Actual branch outcome + * @param bi Pointer to information on the prediction + * recorded at prediction time. + */ + virtual void updateStats(bool taken, TageBranchInfo* bi); + const unsigned logRatioBiModalHystEntries; const unsigned nHistoryTables; const unsigned tagTableCounterBits; @@ -369,6 +392,21 @@ class TAGE: public BPredUnit uint64_t tCounter; uint64_t logUResetPeriod; unsigned useAltOnNaBits; + + // stats + Stats::Scalar tageLongestMatchProviderCorrect; + Stats::Scalar tageAltMatchProviderCorrect; + Stats::Scalar bimodalAltMatchProviderCorrect; + Stats::Scalar tageBimodalProviderCorrect; + Stats::Scalar tageLongestMatchProviderWrong; + Stats::Scalar tageAltMatchProviderWrong; + Stats::Scalar bimodalAltMatchProviderWrong; + Stats::Scalar tageBimodalProviderWrong; + Stats::Scalar tageAltMatchProviderWouldHaveHit; + Stats::Scalar tageLongestMatchProviderWouldHaveHit; + + Stats::Vector tageLongestMatchProvider; + Stats::Vector tageAltMatchProvider; }; #endif // __CPU_PRED_TAGE