-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
They are modeled after LocalBP and IndirectBP from gem5. One is N-bit local branch predictor and the other is a set-associative indirect branch predictor.
- Loading branch information
Showing
8 changed files
with
813 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#include <map> | ||
#include "CustomHWUnits/IndirectBPU.h" | ||
|
||
namespace llvm { | ||
namespace mcad { | ||
|
||
void IndirectBPU::recordTakenBranch(MDInstrAddr IA, MDInstrAddr destAddr) { | ||
// Look for the entry in the table. | ||
auto& set = indirectBranchTable[getSetIndex(IA)]; | ||
for (auto &way : set) { | ||
if (way.tag == IA) { | ||
way.target = destAddr; | ||
return; | ||
} | ||
} | ||
|
||
// If we didn't find an entry, we need to evict one. | ||
// We will choose a random entry to evict. | ||
auto &way = set[rand() % numWays]; | ||
way.tag = IA; | ||
way.target = destAddr; | ||
} | ||
|
||
MDInstrAddr IndirectBPU::predictBranch(MDInstrAddr IA) { | ||
// Look for the entry in the table. | ||
auto& set = indirectBranchTable[getSetIndex(IA)]; | ||
for (auto &way : set) { | ||
if (way.tag == IA) { | ||
return way.target; | ||
} | ||
} | ||
|
||
// If we didn't find an entry, we will predict the next byte. | ||
return MDInstrAddr { IA.addr + 1 }; | ||
} | ||
|
||
unsigned IndirectBPU::getSetIndex(MDInstrAddr IA) const { | ||
return IA.addr % numSets; | ||
} | ||
} // namespace mcad | ||
} // namespace llvm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#ifndef LLVM_MCAD_INDIRECT_BPU_H | ||
#define LLVM_MCAD_INDIRECT_BPU_H | ||
|
||
#include "CustomHWUnits/AbstractBranchPredictorUnit.h" | ||
|
||
#include <map> | ||
|
||
#include "lib/gem5/sat_counter.h" | ||
#include "lib/gem5/intmath.h" | ||
|
||
namespace llvm { | ||
namespace mcad { | ||
|
||
/// @brief A simple indirect branch predictor. | ||
/// | ||
/// This branch predictor is based off of the `IndirectBP` in gem5. | ||
/// It maintains a set-associative table of indirect branch targets. | ||
class IndirectBPU : public AbstractIndirectBranchPredictorUnit { | ||
private: | ||
const unsigned numSets; | ||
const unsigned numWays; | ||
|
||
struct IndirectBranchEntry { | ||
MDInstrAddr tag = {0}; | ||
MDInstrAddr target = {0}; | ||
}; | ||
|
||
std::vector<std::vector<IndirectBranchEntry>> indirectBranchTable; | ||
|
||
unsigned getSetIndex(MDInstrAddr IA) const; | ||
|
||
|
||
public: | ||
IndirectBPU(unsigned numSets = 256, unsigned numWays = 2) | ||
: numSets(numSets), numWays(numWays), indirectBranchTable(numSets, std::vector<IndirectBranchEntry>(numWays)) {} | ||
|
||
void recordTakenBranch(MDInstrAddr IA, MDInstrAddr destAddr) override; | ||
MDInstrAddr predictBranch(MDInstrAddr IA) override; | ||
}; | ||
|
||
} // namespace mcad | ||
} // namespace llvm | ||
|
||
#endif /* LLVM_MCAD_INDIRECT_BPU_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#include <map> | ||
#include "CustomHWUnits/LocalBPU.h" | ||
|
||
namespace llvm { | ||
namespace mcad { | ||
|
||
void LocalBPU::recordTakenBranch(MDInstrAddr IA, BranchDirection nextInstrDirection) { | ||
bool isTaken = nextInstrDirection == BranchDirection::TAKEN; | ||
unsigned idx = getPredictorIndex(IA); | ||
predictorTable[idx] += isTaken; | ||
} | ||
|
||
AbstractBranchPredictorUnit::BranchDirection LocalBPU::predictBranch(MDInstrAddr IA) { | ||
return getPrediction(IA) ? BranchDirection::TAKEN : BranchDirection::NOT_TAKEN; | ||
} | ||
|
||
unsigned LocalBPU::getPredictorIndex(MDInstrAddr IA) const { | ||
// TODO: this could probably be improved. gem5 shifts it by 2 then mask it. | ||
return IA.addr % numPredictorSets; | ||
} | ||
|
||
bool LocalBPU::getPrediction(MDInstrAddr IA) const { | ||
unsigned idx = getPredictorIndex(IA); | ||
// Return the MSB of the counter. | ||
return predictorTable[idx] >> (numCtrlBits - 1); | ||
} | ||
} // namespace mcad | ||
} // namespace llvm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#ifndef LLVM_MCAD_TWO_BIT_LOCAL_BPU_H | ||
#define LLVM_MCAD_TWO_BIT_LOCAL_BPU_H | ||
|
||
#include "CustomHWUnits/AbstractBranchPredictorUnit.h" | ||
|
||
#include <map> | ||
|
||
#include "lib/gem5/sat_counter.h" | ||
#include "lib/gem5/intmath.h" | ||
|
||
namespace llvm { | ||
namespace mcad { | ||
|
||
/// @brief A simple two-bit local branch predictor. | ||
/// | ||
/// This branch predictor is based off of the `LocalBP` in gem5. | ||
/// It uses a table of n-bit saturating counters to predict whether a branch | ||
/// will be taken or not. | ||
class LocalBPU : public AbstractBranchPredictorUnit { | ||
private: | ||
/// @brief The penalty for a misprediction. | ||
const unsigned mispredictionPenalty; | ||
/// @brief The number of control bits per entry in the predictor table. | ||
const unsigned numCtrlBits; | ||
/// @brief The size of the predictor table in bits. | ||
const unsigned predictorSize; | ||
/// @brief The number of entries in the predictor table. | ||
const unsigned numPredictorSets; | ||
/// @brief The branch predictor table with n-bit saturating counters as entries. | ||
std::vector<gem5::SatCounter8> predictorTable; | ||
|
||
public: | ||
LocalBPU(unsigned mispredictionPenalty = 20, unsigned numCtrlBits = 2, | ||
unsigned predictorSize = 2048) | ||
: mispredictionPenalty(mispredictionPenalty), | ||
numCtrlBits(numCtrlBits), predictorSize(predictorSize) | ||
,numPredictorSets(predictorSize / numCtrlBits) | ||
,predictorTable(numPredictorSets, gem5::SatCounter8(numCtrlBits)) | ||
{ | ||
assert(gem5::isPowerOf2(predictorSize)); | ||
assert(numCtrlBits > 0); | ||
}; | ||
|
||
void recordTakenBranch(MDInstrAddr IA, BranchDirection nextInstrDirection) override; | ||
BranchDirection predictBranch(MDInstrAddr IA) override; | ||
unsigned getMispredictionPenalty() override { return mispredictionPenalty; } | ||
|
||
private: | ||
/// @brief Get the index of the predictor table for the given instruction address. | ||
unsigned getPredictorIndex(MDInstrAddr IA) const; | ||
/// @brief Get the prediction for the given instruction address. | ||
bool getPrediction(MDInstrAddr IA) const; | ||
}; | ||
|
||
} // namespace mcad | ||
} // namespace llvm | ||
|
||
#endif /* LLVM_MCAD_TWO_BIT_LOCAL_BPU_H */ |
Oops, something went wrong.