diff options
Diffstat (limited to 'src/cpu/pred')
-rw-r--r-- | src/cpu/pred/ltage.cc | 38 | ||||
-rw-r--r-- | src/cpu/pred/ltage.hh | 19 | ||||
-rw-r--r-- | src/cpu/pred/tage.cc | 125 | ||||
-rw-r--r-- | src/cpu/pred/tage.hh | 40 |
4 files changed, 217 insertions, 5 deletions
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<LTageBranchInfo *>(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 |