pub use self::direction::DirectionPredictor;
pub use self::ghr::Ghr;
pub use self::unit::{BranchPredUnit, ControlInst};
pub mod btb;
pub mod components;
pub mod direction;
pub mod ghr;
pub mod predictors;
pub mod ras;
pub mod unit;
use self::predictors::{
gshare::GSharePredictor, perceptron::PerceptronPredictor, sc_l_tage::ScLTagePredictor,
static_bp::StaticPredictor, tage::TagePredictor, tournament::TournamentPredictor,
};
use crate::common::InstSeq;
use crate::config::{BranchPredictorKind, Config};
#[derive(Debug)]
pub enum BranchPredictor {
Static(BranchPredUnit<StaticPredictor>),
GShare(BranchPredUnit<GSharePredictor>),
Tournament(BranchPredUnit<TournamentPredictor>),
Tage(Box<BranchPredUnit<TagePredictor>>),
Perceptron(BranchPredUnit<PerceptronPredictor>),
ScLTage(Box<BranchPredUnit<ScLTagePredictor>>),
}
fn unit_for<P: DirectionPredictor>(config: &Config, direction: P) -> BranchPredUnit<P> {
let pipeline = &config.pipeline;
BranchPredUnit::new(direction, pipeline.btb_size, pipeline.btb_ways, pipeline.ras_size)
}
macro_rules! dispatch {
($wrapper:expr, $unit:ident => $call:expr) => {
match $wrapper {
BranchPredictor::Static($unit) => $call,
BranchPredictor::GShare($unit) => $call,
BranchPredictor::Tournament($unit) => $call,
BranchPredictor::Tage($unit) => $call,
BranchPredictor::Perceptron($unit) => $call,
BranchPredictor::ScLTage($unit) => $call,
}
};
}
impl BranchPredictor {
pub fn new(config: &Config) -> Self {
let pipeline = &config.pipeline;
match pipeline.branch_predictor {
BranchPredictorKind::Static => Self::Static(unit_for(config, StaticPredictor::new())),
BranchPredictorKind::GShare => Self::GShare(unit_for(config, GSharePredictor::new())),
BranchPredictorKind::Tournament => {
Self::Tournament(unit_for(config, TournamentPredictor::new(&pipeline.tournament)))
}
BranchPredictorKind::Tage => {
Self::Tage(Box::new(unit_for(config, TagePredictor::new(&pipeline.tage))))
}
BranchPredictorKind::Perceptron => {
Self::Perceptron(unit_for(config, PerceptronPredictor::new(&pipeline.perceptron)))
}
BranchPredictorKind::ScLTage => Self::ScLTage(Box::new(unit_for(
config,
ScLTagePredictor::new(
&pipeline.tage,
&pipeline.sc,
&pipeline.ittage,
&pipeline.loop_predictor,
),
))),
}
}
#[inline(always)]
pub fn predict(&mut self, seq: InstSeq, pc: u64, inst: ControlInst) -> Option<u64> {
dispatch!(self, unit => unit.predict(seq, pc, inst))
}
pub fn squash_after(&mut self, keep: InstSeq) {
dispatch!(self, unit => unit.squash_after(keep));
}
#[must_use]
pub fn btb_lookup(&self, pc: u64) -> Option<btb::BtbHit> {
dispatch!(self, unit => unit.btb_lookup(pc))
}
#[must_use]
pub fn is_predicted(&self, seq: InstSeq) -> bool {
dispatch!(self, unit => unit.is_predicted(seq))
}
pub fn discover(&mut self, seq: InstSeq, pc: u64, inst: ControlInst) -> (Option<u64>, bool) {
dispatch!(self, unit => unit.discover(seq, pc, inst))
}
pub fn correct_target(&mut self, seq: InstSeq, target: u64) {
dispatch!(self, unit => unit.correct_target(seq, target));
}
pub fn forget(&mut self, seq: InstSeq, pc: u64) {
dispatch!(self, unit => unit.forget(seq, pc));
}
pub fn squash_all(&mut self) {
dispatch!(self, unit => unit.squash_all());
}
pub fn mispredict(&mut self, seq: InstSeq, taken: bool, target: u64) {
dispatch!(self, unit => unit.mispredict(seq, taken, target));
}
pub fn commit(&mut self, done: InstSeq) {
dispatch!(self, unit => unit.commit(done));
}
}