use std::num::NonZeroUsize;
pub(crate) mod maxsim;
pub(crate) mod blocks;
mod bounds;
mod cache;
mod driver;
mod num;
mod ptr;
mod util;
pub(crate) use driver::Drive;
pub(crate) use num::DimK;
#[cfg(feature = "cache-diagnostics")]
pub use cache::{CacheLevel, HardwareCache};
#[derive(Debug, Clone, Copy)]
pub(crate) struct Cache {
l1: NonZeroUsize,
l2: NonZeroUsize,
}
impl Cache {
const FALLBACK: Self = Self::from_cache_sizes(48_000, 1_250_000);
const fn new(l1: NonZeroUsize, l2: NonZeroUsize) -> Self {
Self { l1, l2 }
}
fn l1(&self) -> NonZeroUsize {
self.l1
}
fn l2(&self) -> NonZeroUsize {
self.l2
}
pub(crate) fn detect() -> Self {
cache::HardwareCache::detect().map_or(Self::FALLBACK, |info| {
Self::from_cache_sizes(info.l1d.bytes.get(), info.l2.bytes.get())
})
}
const fn from_cache_sizes(l1d_bytes: usize, l2_bytes: usize) -> Self {
let l1 = num::value_or_one(l1d_bytes * 3 / 4);
let l2 = num::value_or_one(l2_bytes / 2);
Self::new(l1, l2)
}
}
#[cfg(test)]
mod test_util;
#[cfg(test)]
mod tests {
use super::Cache;
#[test]
fn cache_budgets_scale_detected_sizes() {
for (l1d_bytes, l2_bytes, l1_budget, l2_budget) in [
(32 * 1024, 256 * 1024, 24 * 1024, 128 * 1024),
(48_000, 1_250_000, 36_000, 625_000),
(128 * 1024, 4 * 1024 * 1024, 96 * 1024, 2 * 1024 * 1024),
(7, 7, 5, 3),
(0, 0, 1, 1),
(1, 1, 1, 1),
] {
let cache = Cache::from_cache_sizes(l1d_bytes, l2_bytes);
assert_eq!(cache.l1().get(), l1_budget);
assert_eq!(cache.l2().get(), l2_budget);
}
}
}