use crate::arch::translation::TranslationResult;
use crate::common::{LineAddr, PhysAddr, VirtAddr};
use crate::sim::memory::write_log::WriteSeq;
use crate::sim::packet::MemRespData;
use crate::uarch::mmu::ptw::WalkState;
use crate::uarch::pipeline::latches::{ExMem1Entry, Fetch1Fetch2Entry, VecMemAccess, VecMemTarget};
#[derive(Clone, Debug)]
pub struct OutstandingFetch {
pub fetch_seq: u64,
pub line: Option<LineAddr>,
pub entries: Vec<Fetch1Fetch2Entry>,
}
#[derive(Clone, Debug)]
pub struct OutstandingLoad {
pub entry: ExMem1Entry,
pub paddr: PhysAddr,
pub vaddr: VirtAddr,
pub dirty_updates: crate::arch::translation::DirtyUpdates,
pub side_effecting: bool,
pub parts: LoadParts,
}
impl OutstandingLoad {
pub fn set_span_data(&mut self, bytes: Box<[u8]>) {
if let Some(VecMemAccess { target: VecMemTarget::Span(span), .. }) =
self.entry.vec_mem.as_mut()
{
span.data = Some(bytes);
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PartRead {
pub value: u64,
pub observed: Option<WriteSeq>,
}
impl PartRead {
#[must_use]
pub const fn of(data: &MemRespData) -> Self {
match data {
MemRespData::Performed { value, observed } => {
Self { value: *value, observed: *observed }
}
MemRespData::Small(value) => Self { value: *value, observed: None },
MemRespData::PerformedBytes { observed, .. } => Self { value: 0, observed: *observed },
MemRespData::Line(_) => Self { value: 0, observed: None },
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LoadParts {
Whole(Option<PartRead>),
Split {
low_bytes: u8,
low: Option<PartRead>,
high: Option<PartRead>,
},
}
impl LoadParts {
pub const fn record(&mut self, high: bool, read: PartRead) {
match self {
Self::Whole(whole) => *whole = Some(read),
Self::Split { low, .. } if !high => *low = Some(read),
Self::Split { high: slot, .. } => *slot = Some(read),
}
}
#[must_use]
pub fn assembled(&self) -> Option<PartRead> {
match *self {
Self::Whole(read) => read,
Self::Split { low_bytes, low: Some(low), high: Some(high) } => Some(PartRead {
value: low.value | (high.value << (8 * u32::from(low_bytes))),
observed: match (low.observed, high.observed) {
(Some(a), Some(b)) => Some(a.min(b)),
(a, b) => a.or(b),
},
}),
Self::Split { .. } => None,
}
}
}
#[derive(Clone, Debug)]
pub struct DelayedAccess {
pub ready_cycle: u64,
pub entry: ExMem1Entry,
pub translations: PageTranslations,
}
#[derive(Clone, Debug, Default)]
pub struct PageTranslations {
pub first: Option<TranslationResult>,
pub second: Option<TranslationResult>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StoreOwner {
StoreBuffer,
VecStoreBuffer,
WriteCombining,
Untracked,
}
#[derive(Clone, Debug)]
pub struct OutstandingStore {
pub owner: StoreOwner,
}
#[derive(Clone, Debug)]
pub struct OutstandingWalk {
pub state: WalkState,
pub continuation: WalkContinuation,
}
#[derive(Clone, Debug)]
pub enum WalkContinuation {
Fetch {
fetch_seq: u64,
entry: Fetch1Fetch2Entry,
},
LoadStore {
entry: ExMem1Entry,
translations: Box<PageTranslations>,
},
}
#[derive(Clone, Debug)]
pub struct ForwardedLoad {
pub ready_cycle: u64,
pub entry: crate::uarch::pipeline::latches::Mem1Mem2Entry,
}