summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/pred/ltage.cc38
-rw-r--r--src/cpu/pred/ltage.hh19
-rw-r--r--src/cpu/pred/tage.cc125
-rw-r--r--src/cpu/pred/tage.hh40
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