TournamentBP: Fix some bugs with table sizes and counters

globalHistoryBits, globalPredictorSize, and choicePredictorSize are decoupled.
globalHistoryBits controls how much history is kept, global and choice
predictor sizes control how much of that history is used when accessing
predictor tables. This way, global and choice predictors can actually be
different sizes, and it is no longer possible to walk off the predictor arrays
and cause a seg fault.

There are now individual thresholds for choice, global, and local saturating
counters, so that taken/not taken decisions are correct even when the
predictors' counters' sizes are different.

The interface for localPredictorSize has been removed from TournamentBP because
the value can be calculated from localHistoryBits.

Committed by: Nilay Vaish <nilay@cs.wisc.edu>
This commit is contained in:
Erik Tomusk 2012-12-06 09:31:06 -06:00
parent 150e9b8c68
commit 3dc7e4f496
5 changed files with 85 additions and 60 deletions

View file

@ -90,7 +90,6 @@ class O3_ARM_v7a_FUP(FUPool):
class O3_ARM_v7a_3(DerivO3CPU): class O3_ARM_v7a_3(DerivO3CPU):
predType = "tournament" predType = "tournament"
localPredictorSize = 64
localCtrBits = 2 localCtrBits = 2
localHistoryTableSize = 64 localHistoryTableSize = 64
localHistoryBits = 6 localHistoryBits = 6

View file

@ -53,8 +53,7 @@ BPredUnit::BPredUnit(Resource *_res, ThePipeline::Params *params)
params->instShiftAmt); params->instShiftAmt);
predictor = Local; predictor = Local;
} else if (params->predType == "tournament") { } else if (params->predType == "tournament") {
tournamentBP = new TournamentBP(params->localPredictorSize, tournamentBP = new TournamentBP(params->localCtrBits,
params->localCtrBits,
params->localHistoryTableSize, params->localHistoryTableSize,
params->localHistoryBits, params->localHistoryBits,
params->globalPredictorSize, params->globalPredictorSize,

View file

@ -65,8 +65,7 @@ BPredUnit<Impl>::BPredUnit(DerivO3CPUParams *params)
params->instShiftAmt); params->instShiftAmt);
predictor = Local; predictor = Local;
} else if (params->predType == "tournament") { } else if (params->predType == "tournament") {
tournamentBP = new TournamentBP(params->localPredictorSize, tournamentBP = new TournamentBP(params->localCtrBits,
params->localCtrBits,
params->localHistoryTableSize, params->localHistoryTableSize,
params->localHistoryBits, params->localHistoryBits,
params->globalPredictorSize, params->globalPredictorSize,

View file

@ -40,11 +40,11 @@
* Authors: Kevin Lim * Authors: Kevin Lim
*/ */
#include "base/bitfield.hh"
#include "base/intmath.hh" #include "base/intmath.hh"
#include "cpu/pred/tournament.hh" #include "cpu/pred/tournament.hh"
TournamentBP::TournamentBP(unsigned _localPredictorSize, TournamentBP::TournamentBP(unsigned _localCtrBits,
unsigned _localCtrBits,
unsigned _localHistoryTableSize, unsigned _localHistoryTableSize,
unsigned _localHistoryBits, unsigned _localHistoryBits,
unsigned _globalPredictorSize, unsigned _globalPredictorSize,
@ -53,28 +53,25 @@ TournamentBP::TournamentBP(unsigned _localPredictorSize,
unsigned _choicePredictorSize, unsigned _choicePredictorSize,
unsigned _choiceCtrBits, unsigned _choiceCtrBits,
unsigned _instShiftAmt) unsigned _instShiftAmt)
: localPredictorSize(_localPredictorSize), : localCtrBits(_localCtrBits),
localCtrBits(_localCtrBits),
localHistoryTableSize(_localHistoryTableSize), localHistoryTableSize(_localHistoryTableSize),
localHistoryBits(_localHistoryBits), localHistoryBits(_localHistoryBits),
globalPredictorSize(_globalPredictorSize), globalPredictorSize(_globalPredictorSize),
globalCtrBits(_globalCtrBits), globalCtrBits(_globalCtrBits),
globalHistoryBits(_globalHistoryBits), globalHistoryBits(_globalHistoryBits),
choicePredictorSize(_globalPredictorSize), choicePredictorSize(_choicePredictorSize),
choiceCtrBits(_choiceCtrBits), choiceCtrBits(_choiceCtrBits),
instShiftAmt(_instShiftAmt) instShiftAmt(_instShiftAmt)
{ {
if (!isPowerOf2(localPredictorSize)) { localPredictorSize = ULL(1) << localHistoryBits;
fatal("Invalid local predictor size!\n");
}
//Setup the array of counters for the local predictor //Set up the array of counters for the local predictor
localCtrs.resize(localPredictorSize); localCtrs.resize(localPredictorSize);
for (int i = 0; i < localPredictorSize; ++i) for (int i = 0; i < localPredictorSize; ++i)
localCtrs[i].setBits(localCtrBits); localCtrs[i].setBits(localCtrBits);
localPredictorMask = floorPow2(localPredictorSize) - 1; localPredictorMask = mask(localHistoryBits);
if (!isPowerOf2(localHistoryTableSize)) { if (!isPowerOf2(localHistoryTableSize)) {
fatal("Invalid local history table size!\n"); fatal("Invalid local history table size!\n");
@ -86,9 +83,6 @@ TournamentBP::TournamentBP(unsigned _localPredictorSize,
for (int i = 0; i < localHistoryTableSize; ++i) for (int i = 0; i < localHistoryTableSize; ++i)
localHistoryTable[i] = 0; localHistoryTable[i] = 0;
// Setup the local history mask
localHistoryMask = (1 << localHistoryBits) - 1;
if (!isPowerOf2(globalPredictorSize)) { if (!isPowerOf2(globalPredictorSize)) {
fatal("Invalid global predictor size!\n"); fatal("Invalid global predictor size!\n");
} }
@ -101,21 +95,45 @@ TournamentBP::TournamentBP(unsigned _localPredictorSize,
//Clear the global history //Clear the global history
globalHistory = 0; globalHistory = 0;
// Setup the global history mask // Set up the global history mask
globalHistoryMask = (1 << globalHistoryBits) - 1; // this is equivalent to mask(log2(globalPredictorSize)
globalHistoryMask = globalPredictorSize - 1;
if (!isPowerOf2(choicePredictorSize)) { if (!isPowerOf2(choicePredictorSize)) {
fatal("Invalid choice predictor size!\n"); fatal("Invalid choice predictor size!\n");
} }
// Set up choiceHistoryMask
// this is equivalent to mask(log2(choicePredictorSize)
choiceHistoryMask = choicePredictorSize - 1;
//Setup the array of counters for the choice predictor //Setup the array of counters for the choice predictor
choiceCtrs.resize(choicePredictorSize); choiceCtrs.resize(choicePredictorSize);
for (int i = 0; i < choicePredictorSize; ++i) for (int i = 0; i < choicePredictorSize; ++i)
choiceCtrs[i].setBits(choiceCtrBits); choiceCtrs[i].setBits(choiceCtrBits);
// @todo: Allow for different thresholds between the predictors. //Set up historyRegisterMask
threshold = (1 << (localCtrBits - 1)) - 1; historyRegisterMask = mask(globalHistoryBits);
//Check that predictors don't use more bits than they have available
if (globalHistoryMask > historyRegisterMask) {
fatal("Global predictor too large for global history bits!\n");
}
if (choiceHistoryMask > historyRegisterMask) {
fatal("Choice predictor too large for global history bits!\n");
}
if (globalHistoryMask < historyRegisterMask &&
choiceHistoryMask < historyRegisterMask) {
inform("More global history bits than required by predictors\n");
}
// Set thresholds for the three predictors' counters
// This is equivalent to (2^(Ctr))/2 - 1
localThreshold = (ULL(1) << (localCtrBits - 1)) - 1;
globalThreshold = (ULL(1) << (globalCtrBits - 1)) - 1;
choiceThreshold = (ULL(1) << (choiceCtrBits - 1)) - 1;
} }
inline inline
@ -131,7 +149,7 @@ void
TournamentBP::updateGlobalHistTaken() TournamentBP::updateGlobalHistTaken()
{ {
globalHistory = (globalHistory << 1) | 1; globalHistory = (globalHistory << 1) | 1;
globalHistory = globalHistory & globalHistoryMask; globalHistory = globalHistory & historyRegisterMask;
} }
inline inline
@ -139,7 +157,7 @@ void
TournamentBP::updateGlobalHistNotTaken() TournamentBP::updateGlobalHistNotTaken()
{ {
globalHistory = (globalHistory << 1); globalHistory = (globalHistory << 1);
globalHistory = globalHistory & globalHistoryMask; globalHistory = globalHistory & historyRegisterMask;
} }
inline inline
@ -163,8 +181,8 @@ void
TournamentBP::BTBUpdate(Addr &branch_addr, void * &bp_history) TournamentBP::BTBUpdate(Addr &branch_addr, void * &bp_history)
{ {
unsigned local_history_idx = calcLocHistIdx(branch_addr); unsigned local_history_idx = calcLocHistIdx(branch_addr);
//Update Global History to Not Taken //Update Global History to Not Taken (clear LSB)
globalHistory = globalHistory & (globalHistoryMask - 1); globalHistory &= (historyRegisterMask & ~ULL(1));
//Update Local History to Not Taken //Update Local History to Not Taken
localHistoryTable[local_history_idx] = localHistoryTable[local_history_idx] =
localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1)); localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1));
@ -184,13 +202,15 @@ TournamentBP::lookup(Addr &branch_addr, void * &bp_history)
local_history_idx = calcLocHistIdx(branch_addr); local_history_idx = calcLocHistIdx(branch_addr);
local_predictor_idx = localHistoryTable[local_history_idx] local_predictor_idx = localHistoryTable[local_history_idx]
& localPredictorMask; & localPredictorMask;
local_prediction = localCtrs[local_predictor_idx].read() > threshold; local_prediction = localCtrs[local_predictor_idx].read() > localThreshold;
//Lookup in the global predictor to get its branch prediction //Lookup in the global predictor to get its branch prediction
global_prediction = globalCtrs[globalHistory].read() > threshold; global_prediction =
globalCtrs[globalHistory & globalHistoryMask].read() > globalThreshold;
//Lookup in the choice predictor to see which one to use //Lookup in the choice predictor to see which one to use
choice_prediction = choiceCtrs[globalHistory].read() > threshold; choice_prediction =
choiceCtrs[globalHistory & choiceHistoryMask].read() > choiceThreshold;
// Create BPHistory and pass it back to be recorded. // Create BPHistory and pass it back to be recorded.
BPHistory *history = new BPHistory; BPHistory *history = new BPHistory;
@ -201,9 +221,7 @@ TournamentBP::lookup(Addr &branch_addr, void * &bp_history)
history->localHistory = local_predictor_idx; history->localHistory = local_predictor_idx;
bp_history = (void *)history; bp_history = (void *)history;
assert(globalHistory < globalPredictorSize && assert(local_history_idx < localHistoryTableSize);
local_history_idx < localHistoryTableSize &&
local_predictor_idx < localPredictorSize);
// Commented code is for doing speculative update of counters and // Commented code is for doing speculative update of counters and
// all histories. // all histories.
@ -283,10 +301,12 @@ TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history,
// If the local prediction matches the actual outcome, // If the local prediction matches the actual outcome,
// decerement the counter. Otherwise increment the // decerement the counter. Otherwise increment the
// counter. // counter.
unsigned choice_predictor_idx =
history->globalHistory & choiceHistoryMask;
if (history->localPredTaken == taken) { if (history->localPredTaken == taken) {
choiceCtrs[history->globalHistory].decrement(); choiceCtrs[choice_predictor_idx].decrement();
} else if (history->globalPredTaken == taken) { } else if (history->globalPredTaken == taken) {
choiceCtrs[history->globalHistory].increment(); choiceCtrs[choice_predictor_idx].increment();
} }
} }
@ -295,13 +315,15 @@ TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history,
// resolution of the branch. Global history is updated // resolution of the branch. Global history is updated
// speculatively and restored upon squash() calls, so it does not // speculatively and restored upon squash() calls, so it does not
// need to be updated. // need to be updated.
unsigned global_predictor_idx =
history->globalHistory & globalHistoryMask;
if (taken) { if (taken) {
globalCtrs[history->globalHistory].increment(); globalCtrs[global_predictor_idx].increment();
if (old_local_pred_valid) { if (old_local_pred_valid) {
localCtrs[old_local_pred_index].increment(); localCtrs[old_local_pred_index].increment();
} }
} else { } else {
globalCtrs[history->globalHistory].decrement(); globalCtrs[global_predictor_idx].decrement();
if (old_local_pred_valid) { if (old_local_pred_valid) {
localCtrs[old_local_pred_index].decrement(); localCtrs[old_local_pred_index].decrement();
} }
@ -310,14 +332,14 @@ TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history,
if (squashed) { if (squashed) {
if (taken) { if (taken) {
globalHistory = (history->globalHistory << 1) | 1; globalHistory = (history->globalHistory << 1) | 1;
globalHistory = globalHistory & globalHistoryMask; globalHistory = globalHistory & historyRegisterMask;
if (old_local_pred_valid) { if (old_local_pred_valid) {
localHistoryTable[local_history_idx] = localHistoryTable[local_history_idx] =
(history->localHistory << 1) | 1; (history->localHistory << 1) | 1;
} }
} else { } else {
globalHistory = (history->globalHistory << 1); globalHistory = (history->globalHistory << 1);
globalHistory = globalHistory & globalHistoryMask; globalHistory = globalHistory & historyRegisterMask;
if (old_local_pred_valid) { if (old_local_pred_valid) {
localHistoryTable[local_history_idx] = localHistoryTable[local_history_idx] =
history->localHistory << 1; history->localHistory << 1;
@ -330,9 +352,7 @@ TournamentBP::update(Addr &branch_addr, bool taken, void *bp_history,
} }
assert(globalHistory < globalPredictorSize && assert(local_history_idx < localHistoryTableSize);
local_history_idx < localHistoryTableSize &&
local_predictor_idx < localPredictorSize);
} }

View file

@ -63,8 +63,7 @@ class TournamentBP
/** /**
* Default branch predictor constructor. * Default branch predictor constructor.
*/ */
TournamentBP(unsigned localPredictorSize, TournamentBP(unsigned localCtrBits,
unsigned localCtrBits,
unsigned localHistoryTableSize, unsigned localHistoryTableSize,
unsigned localHistoryBits, unsigned localHistoryBits,
unsigned globalPredictorSize, unsigned globalPredictorSize,
@ -181,10 +180,10 @@ class TournamentBP
/** Local counters. */ /** Local counters. */
std::vector<SatCounter> localCtrs; std::vector<SatCounter> localCtrs;
/** Size of the local predictor. */ /** Number of counters in the local predictor. */
unsigned localPredictorSize; unsigned localPredictorSize;
/** Mask to get the proper index bits into the predictor. */ /** Mask to truncate values stored in the local history table. */
unsigned localPredictorMask; unsigned localPredictorMask;
/** Number of bits of the local predictor's counters. */ /** Number of bits of the local predictor's counters. */
@ -193,42 +192,49 @@ class TournamentBP
/** Array of local history table entries. */ /** Array of local history table entries. */
std::vector<unsigned> localHistoryTable; std::vector<unsigned> localHistoryTable;
/** Size of the local history table. */ /** Number of entries in the local history table. */
unsigned localHistoryTableSize; unsigned localHistoryTableSize;
/** Number of bits for each entry of the local history table. /** Number of bits for each entry of the local history table. */
* @todo Doesn't this come from the size of the local predictor?
*/
unsigned localHistoryBits; unsigned localHistoryBits;
/** Mask to get the proper local history. */
unsigned localHistoryMask;
/** Array of counters that make up the global predictor. */ /** Array of counters that make up the global predictor. */
std::vector<SatCounter> globalCtrs; std::vector<SatCounter> globalCtrs;
/** Size of the global predictor. */ /** Number of entries in the global predictor. */
unsigned globalPredictorSize; unsigned globalPredictorSize;
/** Number of bits of the global predictor's counters. */ /** Number of bits of the global predictor's counters. */
unsigned globalCtrBits; unsigned globalCtrBits;
/** Global history register. */ /** Global history register. Contains as much history as specified by
* globalHistoryBits. Actual number of bits used is determined by
* globalHistoryMask and choiceHistoryMask. */
unsigned globalHistory; unsigned globalHistory;
/** Number of bits for the global history. */ /** Number of bits for the global history. Determines maximum number of
entries in global and choice predictor tables. */
unsigned globalHistoryBits; unsigned globalHistoryBits;
/** Mask to get the proper global history. */ /** Mask to apply to globalHistory to access global history table.
* Based on globalPredictorSize.*/
unsigned globalHistoryMask; unsigned globalHistoryMask;
/** Mask to apply to globalHistory to access choice history table.
* Based on choicePredictorSize.*/
unsigned choiceHistoryMask;
/** Mask to control how much history is stored. All of it might not be
* used. */
unsigned historyRegisterMask;
/** Array of counters that make up the choice predictor. */ /** Array of counters that make up the choice predictor. */
std::vector<SatCounter> choiceCtrs; std::vector<SatCounter> choiceCtrs;
/** Size of the choice predictor (identical to the global predictor). */ /** Number of entries in the choice predictor. */
unsigned choicePredictorSize; unsigned choicePredictorSize;
/** Number of bits of the choice predictor's counters. */ /** Number of bits in the choice predictor's counters. */
unsigned choiceCtrBits; unsigned choiceCtrBits;
/** Number of bits to shift the instruction over to get rid of the word /** Number of bits to shift the instruction over to get rid of the word
@ -236,10 +242,12 @@ class TournamentBP
*/ */
unsigned instShiftAmt; unsigned instShiftAmt;
/** Threshold for the counter value; above the threshold is taken, /** Thresholds for the counter value; above the threshold is taken,
* equal to or below the threshold is not taken. * equal to or below the threshold is not taken.
*/ */
unsigned threshold; unsigned localThreshold;
unsigned globalThreshold;
unsigned choiceThreshold;
}; };
#endif // __CPU_O3_TOURNAMENT_PRED_HH__ #endif // __CPU_O3_TOURNAMENT_PRED_HH__