use crate::uarch::pipeline::rob::RobTag;
#[derive(Default, Debug, Clone)]
pub struct MdpStats {
pub predictions_bypass: u64,
pub predictions_wait_all: u64,
pub predictions_wait_for: u64,
pub violations: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MemPrediction {
NoDep,
DepOn(RobTag),
}
pub trait MemDepPredictor {
fn predict(&mut self, pc: u64, rob_tag: RobTag, is_store: bool) -> MemPrediction;
fn register_store(&mut self, store_pc: u64, rob_tag: RobTag);
fn train(&mut self, load_pc: u64, store_pc: u64);
fn rebuild_lfst_entry(&mut self, store_pc: u64, rob_tag: RobTag);
fn flush(&mut self);
fn flush_after(&mut self, keep_tag: RobTag);
fn note_mem_op(&mut self);
}
#[cfg(test)]
mod tests {
use super::*;
struct DummyPredictor;
impl MemDepPredictor for DummyPredictor {
fn predict(&mut self, _pc: u64, _rob_tag: RobTag, _is_store: bool) -> MemPrediction {
MemPrediction::NoDep
}
fn register_store(&mut self, _store_pc: u64, _rob_tag: RobTag) {}
fn train(&mut self, _load_pc: u64, _store_pc: u64) {}
fn rebuild_lfst_entry(&mut self, _store_pc: u64, _rob_tag: RobTag) {}
fn flush(&mut self) {}
fn flush_after(&mut self, _keep_tag: RobTag) {}
fn note_mem_op(&mut self) {}
}
#[test]
fn test_mem_dep_predictor_defaults() {
let mut predictor = DummyPredictor;
assert_eq!(predictor.predict(0x1000, RobTag(1), false), MemPrediction::NoDep);
predictor.train(0x1000, 0x2000);
predictor.register_store(0x2000, RobTag(1));
predictor.rebuild_lfst_entry(0x2000, RobTag(1));
predictor.flush();
predictor.flush_after(RobTag(5));
predictor.note_mem_op();
}
#[test]
fn test_prediction_eq() {
assert_eq!(MemPrediction::NoDep, MemPrediction::NoDep);
assert_eq!(MemPrediction::DepOn(RobTag(3)), MemPrediction::DepOn(RobTag(3)));
assert_ne!(MemPrediction::NoDep, MemPrediction::DepOn(RobTag(1)));
assert_ne!(MemPrediction::DepOn(RobTag(1)), MemPrediction::DepOn(RobTag(2)));
}
}