use crate::cglue::*;
use crate::dataview::{Pod, PodMethods};
use crate::error::Result;
use crate::types::{umem, Address, PhysicalAddress};
use super::mem_data::*;
use super::PhysicalMemoryMapping;
use std::prelude::v1::*;
use crate::mem::memory_view::*;
pub mod cache;
pub use cache::*;
#[cfg_attr(feature = "plugins", cglue_trait)]
#[int_result]
#[cglue_forward]
pub trait PhysicalMemory: Send {
fn phys_read_raw_iter(&mut self, data: PhysicalReadMemOps) -> Result<()>;
fn phys_write_raw_iter(&mut self, data: PhysicalWriteMemOps) -> Result<()>;
fn metadata(&self) -> PhysicalMemoryMetadata;
#[inline]
fn set_mem_map(&mut self, _mem_map: &[PhysicalMemoryMapping]) {}
#[skip_func]
fn phys_read_into<T: Pod + ?Sized>(&mut self, addr: PhysicalAddress, out: &mut T) -> Result<()>
where
Self: Sized,
{
MemOps::with(
std::iter::once((addr, CSliceMut::from(out.as_bytes_mut()))),
None,
Some(
&mut (&mut |CTup2(_, mut d): ReadData| {
d.iter_mut().for_each(|b| *b = 0);
true
})
.into(),
),
|data| self.phys_read_raw_iter(data),
)
}
#[skip_func]
fn phys_write<T: Pod + ?Sized>(&mut self, addr: PhysicalAddress, data: &T) -> Result<()>
where
Self: Sized,
{
MemOps::with(
std::iter::once((addr, CSliceRef::from(data.as_bytes()))),
None,
None,
|data| self.phys_write_raw_iter(data),
)
}
#[vtbl_only('static, wrap_with_obj(MemoryView))]
fn into_phys_view(self) -> PhysicalMemoryView<Self>
where
Self: Sized,
{
PhysicalMemoryView {
mem: self,
zero_fill_gaps: false,
}
}
#[vtbl_only('_, wrap_with_obj(MemoryView))]
fn phys_view(&mut self) -> PhysicalMemoryView<Fwd<&mut Self>>
where
Self: Sized,
{
self.forward_mut().into_phys_view()
}
}
#[repr(C)]
#[derive(Clone)]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct PhysicalMemoryView<T> {
mem: T,
zero_fill_gaps: bool,
}
impl<T> PhysicalMemoryView<T> {
pub fn zero_fill_gaps(mut self) -> Self {
self.zero_fill_gaps = true;
self
}
}
impl<T: PhysicalMemory> MemoryView for PhysicalMemoryView<T> {
fn read_raw_iter<'a>(
&mut self,
MemOps { inp, out, out_fail }: ReadRawMemOps<'a, '_, '_, '_>,
) -> Result<()> {
let inp = &mut inp.map(|CTup3(addr, meta_addr, data)| CTup3(addr.into(), meta_addr, data));
let inp = inp.into();
#[allow(clippy::unnecessary_unwrap)]
if self.zero_fill_gaps && out.is_some() && out_fail.is_some() {
let out = std::cell::RefCell::new(out.unwrap());
let ma = self.mem.metadata().max_address;
let out1 = &mut |data| out.borrow_mut().call(data);
let out = &mut |data| out.borrow_mut().call(data);
let out = &mut out.into();
let out = Some(out);
let out_fail = out_fail.unwrap();
let out_fail = &mut |mut data: ReadData<'a>| {
if data.0 < ma {
data.1.iter_mut().for_each(|b| *b = 0);
out1(data)
} else {
out_fail.call(data)
}
};
let out_fail = &mut out_fail.into();
let out_fail = Some(out_fail);
let data = MemOps { inp, out, out_fail };
self.mem.phys_read_raw_iter(data)
} else {
let data = MemOps { inp, out, out_fail };
self.mem.phys_read_raw_iter(data)
}
}
fn write_raw_iter(&mut self, MemOps { inp, out, out_fail }: WriteRawMemOps) -> Result<()> {
let inp = &mut inp.map(|CTup3(addr, meta_addr, data)| CTup3(addr.into(), meta_addr, data));
let inp = inp.into();
let data = MemOps { inp, out, out_fail };
self.mem.phys_write_raw_iter(data)
}
fn metadata(&self) -> MemoryViewMetadata {
let PhysicalMemoryMetadata {
max_address,
real_size,
readonly,
..
} = self.mem.metadata();
MemoryViewMetadata {
max_address,
real_size,
readonly,
#[cfg(target_pointer_width = "64")]
arch_bits: 64,
#[cfg(target_pointer_width = "32")]
arch_bits: 32,
#[cfg(target_endian = "little")]
little_endian: true,
#[cfg(target_endian = "big")]
little_endian: false,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct PhysicalMemoryMetadata {
pub max_address: Address,
pub real_size: umem,
pub readonly: bool,
pub ideal_batch_size: u32,
}