use std::fmt::Debug;
use crate::config::ddr5::RefreshKind;
use crate::config::ddr5::timing::Ddr5Timing;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RankLayout {
pub bank_groups: u8,
pub banks_per_group: u8,
}
impl RankLayout {
#[must_use]
pub const fn bank_count(self) -> u32 {
self.bank_groups as u32 * self.banks_per_group as u32
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RefreshTarget {
pub bank_mask: u64,
pub duration: u64,
}
pub trait RefreshPolicy: Debug + Send + Sync {
fn interval(&self, timing: &Ddr5Timing, layout: RankLayout) -> u64;
fn target(&self, timing: &Ddr5Timing, layout: RankLayout, sequence: u64) -> RefreshTarget;
}
#[derive(Debug, Default)]
pub struct AllBank;
impl RefreshPolicy for AllBank {
fn interval(&self, timing: &Ddr5Timing, _layout: RankLayout) -> u64 {
timing.t_refi
}
fn target(&self, timing: &Ddr5Timing, layout: RankLayout, _sequence: u64) -> RefreshTarget {
RefreshTarget { bank_mask: bank_mask_all(layout), duration: timing.t_rfc1 }
}
}
#[derive(Debug, Default)]
pub struct SameBank;
impl RefreshPolicy for SameBank {
fn interval(&self, timing: &Ddr5Timing, layout: RankLayout) -> u64 {
timing.t_refi / u64::from(layout.banks_per_group.max(1))
}
fn target(&self, timing: &Ddr5Timing, layout: RankLayout, sequence: u64) -> RefreshTarget {
let set = sequence % u64::from(layout.banks_per_group.max(1));
RefreshTarget { bank_mask: bank_mask_set(layout, set), duration: timing.t_rfcsb }
}
}
impl RefreshKind {
#[must_use]
pub fn build(self) -> Box<dyn RefreshPolicy> {
match self {
Self::AllBank => Box::new(AllBank),
Self::SameBank => Box::new(SameBank),
}
}
}
#[must_use]
pub const fn bank_mask_all(layout: RankLayout) -> u64 {
let count = layout.bank_count();
if count >= 64 { u64::MAX } else { (1u64 << count) - 1 }
}
#[must_use]
pub const fn bank_mask_set(layout: RankLayout, set: u64) -> u64 {
let mut mask = 0u64;
let mut group = 0u64;
while group < layout.bank_groups as u64 {
let bank_index = group * layout.banks_per_group as u64 + set;
if bank_index < 64 {
mask |= 1u64 << bank_index;
}
group += 1;
}
mask
}