use super::defaults;
use serde::Deserialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub enum MemoryControllerKind {
#[default]
Simple,
#[serde(alias = "DRAM")]
Dram,
#[serde(alias = "DDR5")]
Ddr5,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MemoryConfig {
#[serde(default = "MemoryConfig::default_ram_size")]
pub ram_size: usize,
#[serde(default)]
pub controller: MemoryControllerKind,
#[serde(default)]
pub ddr5: crate::config::ddr5::Ddr5Params,
#[serde(default = "MemoryConfig::default_t_cas")]
pub t_cas: u64,
#[serde(default = "MemoryConfig::default_t_ras")]
pub t_ras: u64,
#[serde(default = "MemoryConfig::default_t_pre")]
pub t_pre: u64,
#[serde(default = "MemoryConfig::default_simple_latency")]
pub simple_latency: u64,
#[serde(default = "MemoryConfig::default_simple_bandwidth_gib_s")]
pub simple_bandwidth_gib_s: f64,
#[serde(default = "MemoryConfig::default_num_banks")]
pub num_banks: usize,
#[serde(default = "MemoryConfig::default_t_rrd")]
pub t_rrd: u64,
#[serde(default = "MemoryConfig::default_row_size")]
pub row_size_bytes: usize,
#[serde(default = "MemoryConfig::default_t_refi")]
pub t_refi: u64,
#[serde(default = "MemoryConfig::default_t_rfc")]
pub t_rfc: u64,
#[serde(default = "MemoryConfig::default_tlb_size")]
pub tlb_size: usize,
#[serde(default = "MemoryConfig::default_tlb_ways")]
pub tlb_ways: usize,
#[serde(default = "MemoryConfig::default_l2_tlb_size")]
pub l2_tlb_size: usize,
#[serde(default = "MemoryConfig::default_l2_tlb_ways")]
pub l2_tlb_ways: usize,
#[serde(default = "MemoryConfig::default_l2_tlb_latency")]
pub l2_tlb_latency: u64,
#[serde(default = "MemoryConfig::default_misaligned_access_trap")]
pub misaligned_access_trap: bool,
#[serde(
default = "MemoryConfig::default_paging_mode_max",
deserialize_with = "deserialize_paging_mode"
)]
pub paging_mode_max: crate::isa::privileged::PagingMode,
}
fn deserialize_paging_mode<'de, D>(
deserializer: D,
) -> Result<crate::isa::privileged::PagingMode, D::Error>
where
D: serde::Deserializer<'de>,
{
use crate::isa::privileged::PagingMode;
use serde::de::{Error, Unexpected};
let s = String::deserialize(deserializer)?;
match s.to_ascii_lowercase().as_str() {
"bare" => Ok(PagingMode::Bare),
"sv39" => Ok(PagingMode::Sv39),
"sv48" => Ok(PagingMode::Sv48),
"sv57" => Ok(PagingMode::Sv57),
_ => Err(D::Error::invalid_value(
Unexpected::Str(&s),
&"one of \"bare\", \"sv39\", \"sv48\", \"sv57\"",
)),
}
}
impl MemoryConfig {
#[must_use]
pub fn simple_bandwidth_bytes_per_second(&self) -> Option<std::num::NonZeroU64> {
let gib_s = self.simple_bandwidth_gib_s;
if !(gib_s.is_finite() && gib_s > 0.0) {
return None;
}
std::num::NonZeroU64::new((gib_s * f64::from(1u32 << 30)) as u64)
}
const fn default_ram_size() -> usize {
defaults::RAM_SIZE
}
const fn default_t_cas() -> u64 {
defaults::T_CAS
}
const fn default_t_ras() -> u64 {
defaults::T_RAS
}
const fn default_t_pre() -> u64 {
defaults::T_PRE
}
const fn default_simple_latency() -> u64 {
defaults::SIMPLE_LATENCY
}
const fn default_simple_bandwidth_gib_s() -> f64 {
defaults::SIMPLE_BANDWIDTH_GIB_S
}
const fn default_num_banks() -> usize {
defaults::NUM_BANKS
}
const fn default_t_rrd() -> u64 {
defaults::T_RRD
}
const fn default_row_size() -> usize {
defaults::ROW_SIZE_BYTES
}
const fn default_t_refi() -> u64 {
defaults::T_REFI
}
const fn default_t_rfc() -> u64 {
defaults::T_RFC
}
const fn default_tlb_size() -> usize {
defaults::TLB_SIZE
}
const fn default_tlb_ways() -> usize {
defaults::TLB_WAYS
}
const fn default_l2_tlb_size() -> usize {
defaults::L2_TLB_SIZE
}
const fn default_l2_tlb_ways() -> usize {
defaults::L2_TLB_WAYS
}
const fn default_l2_tlb_latency() -> u64 {
defaults::L2_TLB_LATENCY
}
const fn default_misaligned_access_trap() -> bool {
false
}
const fn default_paging_mode_max() -> crate::isa::privileged::PagingMode {
crate::isa::privileged::PagingMode::Sv57
}
}
impl Default for MemoryConfig {
fn default() -> Self {
Self {
ram_size: defaults::RAM_SIZE,
controller: MemoryControllerKind::default(),
ddr5: crate::config::ddr5::Ddr5Params::default(),
t_cas: defaults::T_CAS,
t_ras: defaults::T_RAS,
t_pre: defaults::T_PRE,
simple_latency: defaults::SIMPLE_LATENCY,
simple_bandwidth_gib_s: defaults::SIMPLE_BANDWIDTH_GIB_S,
num_banks: defaults::NUM_BANKS,
t_rrd: defaults::T_RRD,
row_size_bytes: defaults::ROW_SIZE_BYTES,
t_refi: defaults::T_REFI,
t_rfc: defaults::T_RFC,
tlb_size: defaults::TLB_SIZE,
tlb_ways: defaults::TLB_WAYS,
l2_tlb_size: defaults::L2_TLB_SIZE,
l2_tlb_ways: defaults::L2_TLB_WAYS,
l2_tlb_latency: defaults::L2_TLB_LATENCY,
misaligned_access_trap: false,
paging_mode_max: crate::isa::privileged::PagingMode::Sv57,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, serde::Deserialize)]
pub enum AddressMappingKind {
#[default]
RoRaBaChCo,
RoRaBaCoCh,
RoCoRaBaCh,
}