From 9c55fa3b2a4c04cd99e8b7b8044eca201b8e47db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Kr=C3=BCger?= Date: Wed, 2 Apr 2025 21:19:44 +0100 Subject: [PATCH] RISC-V: New state allocation and initialisation mechanism --- src/riscv/lib/src/array_utils.rs | 11 ++ src/riscv/lib/src/lib.rs | 1 + src/riscv/lib/src/machine_state.rs | 169 ++++++++++-------- .../address_translation/translation_cache.rs | 41 +++++ .../lib/src/machine_state/block_cache.rs | 50 +++++- .../src/machine_state/block_cache/bcall.rs | 32 +++- .../src/machine_state/block_cache/metrics.rs | 16 +- .../lib/src/machine_state/csregisters.rs | 12 ++ .../src/machine_state/csregisters/values.rs | 25 ++- .../csregisters/values/mstatus.rs | 31 ++++ src/riscv/lib/src/machine_state/hart_state.rs | 17 ++ src/riscv/lib/src/machine_state/memory.rs | 3 +- .../lib/src/machine_state/memory/buddy.rs | 83 +-------- .../src/machine_state/memory/buddy/branch.rs | 31 +++- .../memory/buddy/branch_combinations.rs | 14 ++ .../src/machine_state/memory/buddy/leaf.rs | 12 ++ .../lib/src/machine_state/memory/config.rs | 30 ++++ .../src/machine_state/memory/protection.rs | 14 ++ src/riscv/lib/src/machine_state/registers.rs | 22 +++ .../lib/src/machine_state/reservation_set.rs | 12 ++ src/riscv/lib/src/pvm/common.rs | 31 +++- src/riscv/lib/src/pvm/linux.rs | 17 ++ src/riscv/lib/src/pvm/node_pvm.rs | 15 +- src/riscv/lib/src/pvm/reveals.rs | 14 ++ src/riscv/lib/src/state.rs | 45 +++++ src/riscv/lib/src/state_backend/effects.rs | 17 +- src/riscv/lib/src/state_backend/region.rs | 79 +++++++- src/riscv/lib/src/stepper/test.rs | 8 +- src/riscv/lib/src/stepper/test/posix.rs | 25 +-- 29 files changed, 680 insertions(+), 197 deletions(-) create mode 100644 src/riscv/lib/src/state.rs diff --git a/src/riscv/lib/src/array_utils.rs b/src/riscv/lib/src/array_utils.rs index f9e0d93a31a7..863c40f5c17e 100644 --- a/src/riscv/lib/src/array_utils.rs +++ b/src/riscv/lib/src/array_utils.rs @@ -14,3 +14,14 @@ macro_rules! boxed_array { } pub(crate) use boxed_array; + +/// Create a boxed array from a function. +pub fn boxed_from_fn(mut f: impl FnMut() -> T) -> Box<[T; LEN]> { + let mut entries = Vec::with_capacity(LEN); + entries.resize_with(LEN, &mut f); + entries + .into_boxed_slice() + .try_into() + .map_err(|_| unreachable!("Converting vec into boxed slice of same length always succeeds")) + .unwrap() +} diff --git a/src/riscv/lib/src/lib.rs b/src/riscv/lib/src/lib.rs index 65d2e5f8c3e9..de117fa844a0 100644 --- a/src/riscv/lib/src/lib.rs +++ b/src/riscv/lib/src/lib.rs @@ -17,6 +17,7 @@ pub mod parser; pub mod program; pub mod pvm; pub mod range_utils; +pub mod state; pub mod state_backend; pub mod stepper; pub mod storage; diff --git a/src/riscv/lib/src/machine_state.rs b/src/riscv/lib/src/machine_state.rs index deb728a41b36..dfd1f3d26d7c 100644 --- a/src/riscv/lib/src/machine_state.rs +++ b/src/riscv/lib/src/machine_state.rs @@ -54,6 +54,7 @@ use crate::program::Program; use crate::range_utils::bound_saturating_sub; use crate::range_utils::less_than_bound; use crate::range_utils::unwrap_bound; +use crate::state::NewState; use crate::state_backend as backend; use crate::state_backend::ManagerReadWrite; use crate::traps::EnvironException; @@ -80,78 +81,6 @@ pub struct MachineCoreState { pub translation_cache: TranslationCache, } -impl Clone for MachineCoreState { - fn clone(&self) -> Self { - Self { - hart: self.hart.clone(), - main_memory: self.main_memory.clone(), - translation_cache: self.translation_cache.clone(), - } - } -} - -/// Layout for the machine state - everything required to fetch & run instructions. -pub type MachineStateLayout = ( - MachineCoreStateLayout, - ::BlockCacheLayout, -); - -/// The machine state contains everything required to fetch & run instructions. -pub struct MachineState< - MC: memory::MemoryConfig, - CL: CacheLayouts, - B: Block, - M: backend::ManagerBase, -> { - pub core: MachineCoreState, - pub block_cache: BlockCache, -} - -impl + Clone, M: backend::ManagerClone> - Clone for MachineState -{ - fn clone(&self) -> Self { - Self { - core: self.core.clone(), - block_cache: self.block_cache.clone(), - } - } -} - -/// How to modify the program counter -#[derive(Debug, PartialEq)] -pub enum ProgramCounterUpdate { - /// Jump to a fixed address - Set(AddressRepr), - /// Offset to the next instruction by current instruction width - Next(InstrWidth), -} - -/// Result type when running multiple steps at a time with [`MachineState::step_max`] -#[derive(Debug)] -pub struct StepManyResult { - pub steps: usize, - pub error: Option, -} - -/// Runs a syscall instruction (ecall, ebreak) -macro_rules! run_syscall_instr { - ($state: ident, $run_fn: ident) => {{ Err($state.hart.$run_fn()) }}; -} - -/// Runs a xret instruction (mret, sret, mnret) -macro_rules! run_xret_instr { - ($state: ident, $run_fn: ident) => {{ $state.hart.$run_fn().map(Set) }}; -} - -/// Runs a no-arguments instruction (wfi, fenceI) -macro_rules! run_no_args_instr { - ($state: ident, $instr: ident, $run_fn: ident) => {{ - $state.$run_fn(); - Ok(Next($instr.width())) - }}; -} - impl MachineCoreState { /// Handle an [`Exception`] if one was risen during execution /// of an instruction (also known as synchronous exception) by taking a trap. @@ -245,9 +174,105 @@ impl MachineCoreState } } +impl NewState for MachineCoreState { + fn new(manager: &mut M) -> Self + where + M: backend::ManagerAlloc, + { + Self { + hart: HartState::new(manager), + main_memory: NewState::new(manager), + translation_cache: TranslationCache::new(manager), + } + } +} + +impl Clone for MachineCoreState { + fn clone(&self) -> Self { + Self { + hart: self.hart.clone(), + main_memory: self.main_memory.clone(), + translation_cache: self.translation_cache.clone(), + } + } +} + +/// Layout for the machine state - everything required to fetch & run instructions. +pub type MachineStateLayout = ( + MachineCoreStateLayout, + ::BlockCacheLayout, +); + +/// The machine state contains everything required to fetch & run instructions. +pub struct MachineState< + MC: memory::MemoryConfig, + CL: CacheLayouts, + B: Block, + M: backend::ManagerBase, +> { + pub core: MachineCoreState, + pub block_cache: BlockCache, +} + +impl + Clone, M: backend::ManagerClone> + Clone for MachineState +{ + fn clone(&self) -> Self { + Self { + core: self.core.clone(), + block_cache: self.block_cache.clone(), + } + } +} + +/// How to modify the program counter +#[derive(Debug, PartialEq)] +pub enum ProgramCounterUpdate { + /// Jump to a fixed address + Set(AddressRepr), + /// Offset to the next instruction by current instruction width + Next(InstrWidth), +} + +/// Result type when running multiple steps at a time with [`MachineState::step_max`] +#[derive(Debug)] +pub struct StepManyResult { + pub steps: usize, + pub error: Option, +} + +/// Runs a syscall instruction (ecall, ebreak) +macro_rules! run_syscall_instr { + ($state: ident, $run_fn: ident) => {{ Err($state.hart.$run_fn()) }}; +} + +/// Runs a xret instruction (mret, sret, mnret) +macro_rules! run_xret_instr { + ($state: ident, $run_fn: ident) => {{ $state.hart.$run_fn().map(Set) }}; +} + +/// Runs a no-arguments instruction (wfi, fenceI) +macro_rules! run_no_args_instr { + ($state: ident, $instr: ident, $run_fn: ident) => {{ + $state.$run_fn(); + Ok(Next($instr.width())) + }}; +} + impl, M: backend::ManagerBase> MachineState { + /// Allocate a new machine state. + pub fn new(manager: &mut M, block_builder: B::BlockBuilder) -> Self + where + M: backend::ManagerAlloc, + { + Self { + core: MachineCoreState::new(manager), + block_cache: BlockCache::new(manager, block_builder), + } + } + /// Bind the block cache to the given allocated state and the given [block builder]. /// /// [block builder]: Block::BlockBuilder diff --git a/src/riscv/lib/src/machine_state/address_translation/translation_cache.rs b/src/riscv/lib/src/machine_state/address_translation/translation_cache.rs index 339f53f7b29e..8ff83fe32e15 100644 --- a/src/riscv/lib/src/machine_state/address_translation/translation_cache.rs +++ b/src/riscv/lib/src/machine_state/address_translation/translation_cache.rs @@ -37,15 +37,18 @@ use strum::EnumCount; use super::AccessType; use super::PAGE_OFFSET_WIDTH; +use crate::array_utils::boxed_from_fn; use crate::bits::ones; use crate::cache_utils::FenceCounter; use crate::machine_state::csregisters::CSRRepr; use crate::machine_state::memory::Address; use crate::machine_state::mode::Mode; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; use crate::state_backend::Cell; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerRead; @@ -182,6 +185,21 @@ impl Cached { } } +impl NewState for Cached { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + mode: Cell::new(manager), + satp: Cell::new(manager), + virt_page: Cell::new(manager), + phys_page: Cell::new(manager), + fence_counter: Cell::new(manager), + } + } +} + impl Clone for Cached { fn clone(&self) -> Self { Self { @@ -315,6 +333,18 @@ impl AccessCache { } } +impl NewState for AccessCache { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + fence_counter: Cell::new(manager), + entries: boxed_from_fn(|| Cached::new(manager)), + } + } +} + impl Clone for AccessCache { fn clone(&self) -> Self { Self { @@ -424,6 +454,17 @@ impl TranslationCache { } } +impl NewState for TranslationCache { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + entries: NewState::new(manager), + } + } +} + impl Clone for TranslationCache { fn clone(&self) -> Self { Self { diff --git a/src/riscv/lib/src/machine_state/block_cache.rs b/src/riscv/lib/src/machine_state/block_cache.rs index 506bb63342c9..6a1be661cebd 100644 --- a/src/riscv/lib/src/machine_state/block_cache.rs +++ b/src/riscv/lib/src/machine_state/block_cache.rs @@ -99,6 +99,7 @@ use crate::cache_utils::Sizes; use crate::machine_state::address_translation::PAGE_SIZE; use crate::machine_state::instruction::Args; use crate::parser::instruction::InstrWidth; +use crate::state::NewState; use crate::state_backend; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; @@ -106,6 +107,7 @@ use crate::state_backend::Cell; use crate::state_backend::EnrichedCell; use crate::state_backend::EnrichedValue; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerRead; @@ -181,7 +183,7 @@ pub struct AddressCellLayout; impl state_backend::Layout for AddressCellLayout { type Allocated = Cell; - fn allocate(backend: &mut M) -> Self::Allocated { + fn allocate(backend: &mut M) -> Self::Allocated { Cell::bind(backend.allocate_region([!0])) } } @@ -280,12 +282,26 @@ impl, M: ManagerBase> Cached { } } +impl, M: ManagerBase> NewState for Cached { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + address: Cell::new_with(manager, !0), + block: B::new(manager), + fence_counter: Cell::new(manager), + _pd: PhantomData, + } + } +} + impl + Clone, M: ManagerClone> Clone for Cached { fn clone(&self) -> Self { Self { address: self.address.clone(), - fence_counter: self.fence_counter.clone(), block: self.block.clone(), + fence_counter: self.fence_counter.clone(), _pd: PhantomData, } } @@ -358,10 +374,23 @@ impl PartialBlock { } } +impl NewState for PartialBlock { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + phys_addr: Cell::new(manager), + in_progress: Cell::new(manager), + progress: Cell::new(manager), + } + } +} + /// Trait for capturing the different possible layouts of the instruction cache (i.e. /// controlling the number of cache entries present). pub trait BlockCacheLayout: state_backend::CommitmentLayout + state_backend::ProofLayout { - type Entries, M: ManagerBase>; + type Entries, M: ManagerBase>: NewState; type Sizes; @@ -513,6 +542,21 @@ pub struct BlockCache, MC: MemoryConfig, impl, MC: MemoryConfig, M: ManagerBase> BlockCache { + /// Allocate a new block cache. + pub fn new(manager: &mut M, block_builder: B::BlockBuilder) -> Self + where + M: ManagerAlloc, + { + Self { + current_block_addr: Cell::new_with(manager, !0), + next_instr_addr: Cell::new_with(manager, !0), + fence_counter: Cell::new(manager), + partial_block: PartialBlock::new(manager), + entries: NewState::new(manager), + block_builder, + } + } + /// Bind the block cache to the given allocated state and the given [block builder]. /// /// [block builder]: Block::BlockBuilder diff --git a/src/riscv/lib/src/machine_state/block_cache/bcall.rs b/src/riscv/lib/src/machine_state/block_cache/bcall.rs index 4f842b2c4b59..b2c53a9729f2 100644 --- a/src/riscv/lib/src/machine_state/block_cache/bcall.rs +++ b/src/riscv/lib/src/machine_state/block_cache/bcall.rs @@ -20,11 +20,13 @@ use crate::machine_state::ProgramCounterUpdate; use crate::machine_state::instruction::Instruction; use crate::machine_state::memory::Address; use crate::machine_state::memory::MemoryConfig; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; use crate::state_backend::Cell; use crate::state_backend::EnrichedCell; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerRead; @@ -74,7 +76,7 @@ pub type BlockLayout = (Atom, [Atom; CACHE_INSTR]); /// /// A block is a sequence of at least one instruction, which may be executed sequentially. /// Blocks will never contain more than [`CACHE_INSTR`] instructions. -pub trait Block { +pub trait Block: NewState { /// Block construction may require additional state not kept in storage, /// this is then passed as a parameter to [`Block::callable`]. type BlockBuilder: Default; @@ -196,6 +198,18 @@ impl BCall for [EnrichedCell NewState for Interpreted { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + len_instr: Cell::new(manager), + instr: NewState::new(manager), + } + } +} + impl Block for Interpreted { type BlockBuilder = InterpretedBlockBuilder; @@ -306,6 +320,20 @@ pub struct InlineJit { block_hash: BlockHash, } +impl NewState for InlineJit { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + fallback: Interpreted::new(manager), + jit_fn: None, + compiled: false, + block_hash: BlockHash::Dirty, + } + } +} + impl Block for InlineJit { type BlockBuilder = (JIT, InterpretedBlockBuilder); @@ -530,7 +558,7 @@ mod test { // use block metrics, since interpreted has no hash let $block_name = - &mut BlockMetrics::new(create_state!(Interpreted, BlockLayout, $F, M4K)); + &mut BlockMetrics::wrap(create_state!(Interpreted, BlockLayout, $F, M4K)); let $bb_name = &mut > as Block>>::BlockBuilder::default(); { diff --git a/src/riscv/lib/src/machine_state/block_cache/metrics.rs b/src/riscv/lib/src/machine_state/block_cache/metrics.rs index 54a2d314e311..6feeb476e6e2 100644 --- a/src/riscv/lib/src/machine_state/block_cache/metrics.rs +++ b/src/riscv/lib/src/machine_state/block_cache/metrics.rs @@ -35,6 +35,8 @@ pub(crate) use block_metrics; use super::bcall::Block; use super::bcall::BlockHash; use crate::machine_state::memory::MemoryConfig; +use crate::state::NewState; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; #[cfg(feature = "metrics")] @@ -283,7 +285,7 @@ impl BlockMetrics { /// Since BlockMetrics doesn't take a `M: ManagerBase` as a type-parameter, /// we can't use it with `create_state!`. #[cfg(test)] - pub(super) fn new(block: B) -> Self { + pub(super) fn wrap(block: B) -> Self { Self { block, block_hash: BlockHash::Dirty, @@ -291,6 +293,18 @@ impl BlockMetrics { } } +impl, M: ManagerBase> NewState for BlockMetrics { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + block: B::new(manager), + block_hash: BlockHash::Dirty, + } + } +} + impl, MC: MemoryConfig, M: ManagerBase> Block for BlockMetrics { type BlockBuilder = B::BlockBuilder; diff --git a/src/riscv/lib/src/machine_state/csregisters.rs b/src/riscv/lib/src/machine_state/csregisters.rs index cca09ebbb021..eb35eecd12ef 100644 --- a/src/riscv/lib/src/machine_state/csregisters.rs +++ b/src/riscv/lib/src/machine_state/csregisters.rs @@ -32,6 +32,7 @@ use crate::bits::Bits64; use crate::bits::ones; use crate::bits::u64; use crate::machine_state::mode::Mode; +use crate::state::NewState; use crate::state_backend as backend; use crate::state_backend::ManagerRead; use crate::traps::Exception; @@ -1662,6 +1663,17 @@ impl CSRegisters { } } +impl NewState for CSRegisters { + fn new(manager: &mut M) -> Self + where + M: backend::ManagerAlloc, + { + Self { + registers: CSRValues::new(manager), + } + } +} + impl Clone for CSRegisters { fn clone(&self) -> Self { Self { diff --git a/src/riscv/lib/src/machine_state/csregisters/values.rs b/src/riscv/lib/src/machine_state/csregisters/values.rs index 61a2f2c6e62d..bfa78ab2ef70 100644 --- a/src/riscv/lib/src/machine_state/csregisters/values.rs +++ b/src/riscv/lib/src/machine_state/csregisters/values.rs @@ -16,6 +16,7 @@ use super::effects::NoEffect; use super::effects::handle_csr_effect; use super::root::RootCSRegister; use crate::bits::Bits64; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Cell; use crate::state_backend::CommitmentLayout; @@ -107,6 +108,20 @@ impl CSRValues { } } +impl NewState for CSRValues { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + let manager = std::cell::RefCell::new(manager); + CSRValuesF::new_with( + || MStatusValue::new(*manager.borrow_mut()), + || XipCell, + || RawValue::new(*manager.borrow_mut()), + ) + } +} + impl CSRegisters { /// Perform a general read of a CSR. #[inline(always)] @@ -165,7 +180,7 @@ impl Layout for CSRValuesLayout { fn allocate(backend: &mut M) -> Self::Allocated { let backend = std::cell::RefCell::new(backend); - Self::Allocated::new( + Self::Allocated::new_with( || MStatusLayout::allocate(*backend.borrow_mut()), || XipCellLayout::allocate(*backend.borrow_mut()), || EffectCellLayout::::allocate(*backend.borrow_mut()), @@ -187,7 +202,7 @@ impl ProofLayout for CSRValuesLayout { fn from_proof(proof: ProofTree) -> FromProofResult { fn make_absent() -> AllocatedOf { - CSRValuesF::new( + CSRValuesF::new_with( || mstatus::MStatusLayoutF { sie: Cell::absent(), mie: Cell::absent(), @@ -529,7 +544,7 @@ impl CSRValuesF { /// Create a new CSR values structure. The given functions are used to initialise each CSR /// value. #[inline] - fn new( + fn new_with( make_mstatus: impl FnOnce() -> MStatus, make_mip: impl FnOnce() -> MIP, mut make_raw: impl FnMut() -> Raw, @@ -2027,7 +2042,7 @@ mod tests { fn fold_ref_mut_consistent() { let counter = AtomicUsize::new(0); - let mut example = CSRValuesF::new( + let mut example = CSRValuesF::new_with( || counter.fetch_add(1, Ordering::SeqCst), || counter.fetch_add(1, Ordering::SeqCst), || counter.fetch_add(1, Ordering::SeqCst), @@ -2045,7 +2060,7 @@ mod tests { fn as_ref_consistent() { let counter = AtomicUsize::new(0); - let example = CSRValuesF::new( + let example = CSRValuesF::new_with( || counter.fetch_add(1, Ordering::SeqCst), || counter.fetch_add(1, Ordering::SeqCst), || counter.fetch_add(1, Ordering::SeqCst), diff --git a/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs index 77c3b8cff9d5..8752691fd110 100644 --- a/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs +++ b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs @@ -12,11 +12,13 @@ use crate::machine_state::csregisters::xstatus::MPPValue; use crate::machine_state::csregisters::xstatus::MStatus; use crate::machine_state::csregisters::xstatus::SPPValue; use crate::machine_state::csregisters::xstatus::XLenValue; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; use crate::state_backend::Cell; use crate::state_backend::EffectCell; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerRead; @@ -108,6 +110,35 @@ impl MStatusValue { } } +impl NewState for MStatusValue { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + MStatusValue { + sie: EffectCell::new(manager), + mie: EffectCell::new(manager), + spie: Cell::new(manager), + ube: Cell::new(manager), + mpie: Cell::new(manager), + spp: Cell::new(manager), + mpp: Cell::new(manager), + fs: Cell::new(manager), + xs: Cell::new(manager), + mprv: Cell::new(manager), + sum: Cell::new(manager), + mxr: Cell::new(manager), + tvm: Cell::new(manager), + tw: Cell::new(manager), + tsr: Cell::new(manager), + uxl: Cell::new(manager), + sxl: Cell::new(manager), + sbe: Cell::new(manager), + mbe: Cell::new(manager), + } + } +} + impl Clone for MStatusValue { fn clone(&self) -> Self { Self { diff --git a/src/riscv/lib/src/machine_state/hart_state.rs b/src/riscv/lib/src/machine_state/hart_state.rs index 0008208d3d0d..5adb95f9b175 100644 --- a/src/riscv/lib/src/machine_state/hart_state.rs +++ b/src/riscv/lib/src/machine_state/hart_state.rs @@ -15,6 +15,7 @@ use crate::machine_state::mode::TrapMode; use crate::machine_state::registers; use crate::machine_state::reservation_set; use crate::machine_state::reservation_set::ReservationSet; +use crate::state::NewState; use crate::state_backend as backend; use crate::state_backend::Atom; use crate::state_backend::Cell; @@ -192,6 +193,22 @@ impl HartState { } } +impl NewState for HartState { + fn new(manager: &mut M) -> Self + where + M: backend::ManagerAlloc, + { + Self { + xregisters: registers::XRegisters::new(manager), + fregisters: registers::FRegisters::new(manager), + csregisters: csregisters::CSRegisters::new(manager), + mode: Cell::new(manager), + pc: Cell::new(manager), + reservation_set: ReservationSet::new(manager), + } + } +} + impl Clone for HartState { fn clone(&self) -> Self { Self { diff --git a/src/riscv/lib/src/machine_state/memory.rs b/src/riscv/lib/src/machine_state/memory.rs index dea82031083b..daa9bcd8e687 100644 --- a/src/riscv/lib/src/machine_state/memory.rs +++ b/src/riscv/lib/src/machine_state/memory.rs @@ -14,6 +14,7 @@ use tezos_smart_rollup_constants::riscv::SbiError; use thiserror::Error; use super::registers::XValue; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::CommitmentLayout; use crate::state_backend::Elem; @@ -130,7 +131,7 @@ impl From for SbiError { } /// Instance of memory -pub trait Memory: Sized { +pub trait Memory: NewState + Sized { /// Read an element in the region. `address` is in bytes. fn read(&self, address: Address) -> Result where diff --git a/src/riscv/lib/src/machine_state/memory/buddy.rs b/src/riscv/lib/src/machine_state/memory/buddy.rs index d5dc0a118884..7ff48c0dcf9f 100644 --- a/src/riscv/lib/src/machine_state/memory/buddy.rs +++ b/src/riscv/lib/src/machine_state/memory/buddy.rs @@ -24,6 +24,7 @@ mod proxy; pub use proxy::BuddyLayoutProxy; +use crate::state::NewState; use crate::state_backend::CommitmentLayout; use crate::state_backend::FnManager; use crate::state_backend::ManagerBase; @@ -48,23 +49,8 @@ pub trait BuddyLayout: CommitmentLayout + ProofLayout { F: FnManager>; } -impl BuddyLayout for Box { - type Buddy = Box>; - - fn bind(space: Self::Allocated) -> Self::Buddy { - Box::new(B::bind(*space)) - } - - fn struct_ref<'a, F, M: ManagerBase>(space: &'a Self::Buddy) -> Self::Allocated - where - F: FnManager>, - { - Box::new(B::struct_ref::(space.as_ref())) - } -} - /// Buddy-style memory manager -pub trait Buddy { +pub trait Buddy: NewState { /// Number of pages being managed const PAGES: u64; @@ -111,71 +97,6 @@ pub trait Buddy { M: ManagerClone; } -impl Buddy for Box -where - B: Buddy, - M: ManagerBase, -{ - const PAGES: u64 = B::PAGES; - - fn allocate(&mut self, pages: u64) -> Option - where - M: ManagerReadWrite, - { - self.as_mut().allocate(pages) - } - - fn allocate_fixed(&mut self, idx: u64, pages: u64, replace: bool) -> Option<()> - where - M: ManagerReadWrite, - { - self.as_mut().allocate_fixed(idx, pages, replace) - } - - fn deallocate(&mut self, idx: u64, pages: u64) - where - M: ManagerReadWrite, - { - self.as_mut().deallocate(idx, pages) - } - - fn longest_free_sequence(&self) -> u64 - where - M: ManagerRead, - { - self.as_ref().longest_free_sequence() - } - - fn count_free_start(&self) -> u64 - where - M: ManagerRead, - { - self.as_ref().count_free_start() - } - - fn count_free_end(&self) -> u64 - where - M: ManagerRead, - { - self.as_ref().count_free_end() - } - - #[cfg(test)] - fn deep_refresh(&mut self) - where - M: ManagerReadWrite, - { - self.as_mut().deep_refresh() - } - - fn clone(&self) -> Self - where - M: ManagerClone, - { - Box::new(self.as_ref().clone()) - } -} - #[cfg(test)] mod tests { use rand::Rng; diff --git a/src/riscv/lib/src/machine_state/memory/buddy/branch.rs b/src/riscv/lib/src/machine_state/memory/buddy/branch.rs index c8eb1fa2f960..ac45123a391d 100644 --- a/src/riscv/lib/src/machine_state/memory/buddy/branch.rs +++ b/src/riscv/lib/src/machine_state/memory/buddy/branch.rs @@ -10,9 +10,11 @@ use serde::Serialize; use super::Buddy; use super::BuddyLayout; use crate::default::ConstDefault; +use crate::state::NewState; use crate::state_backend::Atom; use crate::state_backend::Cell; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerDeserialise; @@ -69,8 +71,8 @@ impl BuddyLayout for BuddyBranch2Layout { fn bind(space: Self::Allocated) -> Self::Buddy { BuddyBranch2 { free_info: space.free_info, - left: as BuddyLayout>::bind(space.left), - right: as BuddyLayout>::bind(space.right), + left: Box::new(B::bind(*space.left)), + right: Box::new(B::bind(*space.right)), } } @@ -80,8 +82,8 @@ impl BuddyLayout for BuddyBranch2Layout { { BuddyBranch2LayoutF { free_info: space.free_info.struct_ref::(), - left: as BuddyLayout>::struct_ref::(&space.left), - right: as BuddyLayout>::struct_ref::(&space.right), + left: Box::new(B::struct_ref::(&space.left)), + right: Box::new(B::struct_ref::(&space.right)), } } } @@ -109,6 +111,23 @@ impl, M: ManagerBase> BuddyBranch2 { } } +impl NewState for BuddyBranch2 +where + B: NewState, + M: ManagerBase, +{ + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + free_info: Cell::new(manager), + left: Box::new(B::new(manager)), + right: Box::new(B::new(manager)), + } + } +} + impl Buddy for BuddyBranch2 where B: Buddy, @@ -282,8 +301,8 @@ where { Self { free_info: self.free_info.clone(), - left: self.left.clone(), - right: self.right.clone(), + left: Box::new(self.left.clone()), + right: Box::new(self.right.clone()), } } } diff --git a/src/riscv/lib/src/machine_state/memory/buddy/branch_combinations.rs b/src/riscv/lib/src/machine_state/memory/buddy/branch_combinations.rs index 4273353d8fde..65eaa6ecd437 100644 --- a/src/riscv/lib/src/machine_state/memory/buddy/branch_combinations.rs +++ b/src/riscv/lib/src/machine_state/memory/buddy/branch_combinations.rs @@ -14,6 +14,7 @@ use super::Buddy; use super::BuddyLayout; use super::branch::BuddyBranch2; use super::branch::BuddyBranch2Layout; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::CommitmentLayout; use crate::state_backend::FnManager; @@ -177,6 +178,19 @@ macro_rules! combined_buddy_branch { } } + impl NewState for $name + where + B: NewState, + M: ManagerBase, + { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self(NewState::new(manager)) + } + } + impl Buddy for $name where B: Buddy, diff --git a/src/riscv/lib/src/machine_state/memory/buddy/leaf.rs b/src/riscv/lib/src/machine_state/memory/buddy/leaf.rs index 66344ad05c54..927f896ca950 100644 --- a/src/riscv/lib/src/machine_state/memory/buddy/leaf.rs +++ b/src/riscv/lib/src/machine_state/memory/buddy/leaf.rs @@ -10,6 +10,7 @@ use serde::Serialize; use super::Buddy; use super::BuddyLayout; use crate::bits::ones; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; use crate::state_backend::Cell; @@ -96,6 +97,17 @@ pub struct BuddyLeaf { set: Cell, } +impl NewState for BuddyLeaf { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + set: Cell::new(manager), + } + } +} + impl Buddy for BuddyLeaf { const PAGES: u64 = PAGES; diff --git a/src/riscv/lib/src/machine_state/memory/config.rs b/src/riscv/lib/src/machine_state/memory/config.rs index c4d608e15b14..a888715bba7b 100644 --- a/src/riscv/lib/src/machine_state/memory/config.rs +++ b/src/riscv/lib/src/machine_state/memory/config.rs @@ -9,15 +9,45 @@ use super::protection::PagePermissions; #[cfg(feature = "supervisor")] use super::protection::PagePermissionsLayout; use super::state::MemoryImpl; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::DynArray; +use crate::state_backend::DynCells; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::Ref; /// State layout for the memory component pub struct MemoryConfig; +impl NewState + for MemoryImpl +where + B: NewState, + M: ManagerBase, +{ + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + #[cfg(not(feature = "supervisor"))] + return MemoryImpl { + data: DynCells::new(manager), + _pd: std::marker::PhantomData, + }; + + #[cfg(feature = "supervisor")] + MemoryImpl { + data: DynCells::new(manager), + readable_pages: PagePermissions::new(manager), + writable_pages: PagePermissions::new(manager), + executable_pages: PagePermissions::new(manager), + allocated_pages: B::new(manager), + } + } +} + impl super::MemoryConfig for MemoryConfig where diff --git a/src/riscv/lib/src/machine_state/memory/protection.rs b/src/riscv/lib/src/machine_state/memory/protection.rs index e7bf903db45b..16e8f0be9b81 100644 --- a/src/riscv/lib/src/machine_state/memory/protection.rs +++ b/src/riscv/lib/src/machine_state/memory/protection.rs @@ -3,10 +3,13 @@ // SPDX-License-Identifier: MIT use super::Address; +use crate::array_utils::boxed_from_fn; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; use crate::state_backend::Cell; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerDeserialise; @@ -97,6 +100,17 @@ impl PagePermissions { } } +impl NewState for PagePermissions { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + PagePermissions { + pages: boxed_from_fn(|| Cell::new(manager)), + } + } +} + impl<'de, const PAGES: usize, M: ManagerDeserialise> serde::Deserialize<'de> for PagePermissions { diff --git a/src/riscv/lib/src/machine_state/registers.rs b/src/riscv/lib/src/machine_state/registers.rs index 76abd1af6c62..816ee0bc212a 100644 --- a/src/riscv/lib/src/machine_state/registers.rs +++ b/src/riscv/lib/src/machine_state/registers.rs @@ -12,6 +12,7 @@ use arbitrary_int::u5; use crate::default::ConstDefault; use crate::machine_state::backend; +use crate::state::NewState; /// Integer register index #[allow(non_camel_case_types)] // To make names consistent with specification @@ -264,6 +265,17 @@ impl XRegisters { } } +impl NewState for XRegisters { + fn new(manager: &mut M) -> Self + where + M: backend::ManagerAlloc, + { + XRegisters { + registers: backend::Cells::new(manager), + } + } +} + impl Clone for XRegisters { fn clone(&self) -> Self { Self { @@ -571,6 +583,16 @@ pub struct FRegisters { } impl FRegisters { + /// Allocate a new floating-point registers state. + pub fn new(manager: &mut M) -> Self + where + M: backend::ManagerAlloc, + { + Self { + registers: backend::Cells::new(manager), + } + } + /// Bind the floating-point register space to the allocated space. pub fn bind(space: backend::AllocatedOf) -> Self { FRegisters { registers: space } diff --git a/src/riscv/lib/src/machine_state/reservation_set.rs b/src/riscv/lib/src/machine_state/reservation_set.rs index 3ec278754132..37ef68f8171d 100644 --- a/src/riscv/lib/src/machine_state/reservation_set.rs +++ b/src/riscv/lib/src/machine_state/reservation_set.rs @@ -19,6 +19,7 @@ use crate::machine_state::backend; /// pair with the most recent LR, and LR with the next following SC, in program /// order." use crate::machine_state::backend::Cell; +use crate::state::NewState; pub struct ReservationSet { start_addr: Cell, @@ -107,6 +108,17 @@ impl ReservationSet { } } +impl NewState for ReservationSet { + fn new(manager: &mut M) -> Self + where + M: backend::ManagerAlloc, + { + ReservationSet { + start_addr: Cell::new(manager), + } + } +} + impl Clone for ReservationSet { fn clone(&self) -> Self { Self { diff --git a/src/riscv/lib/src/pvm/common.rs b/src/riscv/lib/src/pvm/common.rs index 8912804b5c10..dfdc0f43765d 100644 --- a/src/riscv/lib/src/pvm/common.rs +++ b/src/riscv/lib/src/pvm/common.rs @@ -26,6 +26,7 @@ use crate::machine_state::memory::MemoryConfig; use crate::machine_state::registers::a0; use crate::pvm::sbi; use crate::range_utils::less_than_bound; +use crate::state::NewState; use crate::state_backend; use crate::state_backend::Atom; use crate::state_backend::Cell; @@ -170,7 +171,32 @@ pub struct Pvm, M: Ma status: Cell, } -impl, M: ManagerBase> Pvm { +impl< + MC: MemoryConfig, + CL: machine_state::CacheLayouts, + B: bcall::Block, + M: state_backend::ManagerBase, +> Pvm +{ + /// Allocate a new PVM. + pub fn new(manager: &mut M, block_builder: B::BlockBuilder) -> Self + where + M: state_backend::ManagerAlloc, + { + Self { + machine_state: machine_state::MachineState::new(manager, block_builder), + reveal_request: RevealRequest::new(manager), + #[cfg(feature = "supervisor")] + system_state: linux::SupervisorState::new(manager), + version: Cell::new_with(manager, INITIAL_VERSION), + status: Cell::new(manager), + tick: Cell::new(manager), + message_counter: Cell::new(manager), + level: Cell::new(manager), + level_is_set: Cell::new(manager), + } + } + /// Bind the block cache to the given allocated state and the given [block builder]. /// /// [block builder]: bcall::Block::BlockBuilder @@ -432,8 +458,7 @@ impl, M: ManagerBase> impl> Pvm { pub(crate) fn empty(block_builder: B::BlockBuilder) -> Self { - let space = Owned::allocate::>(); - Self::bind(space, block_builder) + Self::new(&mut Owned, block_builder) } pub(crate) fn hash(&self) -> Result { diff --git a/src/riscv/lib/src/pvm/linux.rs b/src/riscv/lib/src/pvm/linux.rs index 82de7d0a00ac..4b57a325126c 100644 --- a/src/riscv/lib/src/pvm/linux.rs +++ b/src/riscv/lib/src/pvm/linux.rs @@ -33,10 +33,12 @@ use crate::machine_state::memory::Permissions; use crate::machine_state::mode::Mode; use crate::machine_state::registers; use crate::program::Program; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; use crate::state_backend::Cell; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerRead; @@ -427,6 +429,21 @@ pub struct SupervisorState { } impl SupervisorState { + /// Allocate a new supervisor state. + pub fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + SupervisorState { + tid_address: Cell::new(manager), + exited: Cell::new(manager), + exit_code: Cell::new(manager), + program: Cell::new(manager), + heap: Cell::new(manager), + stack_guard: Cell::new(manager), + } + } + /// Bind the given allocated regions to the supervisor state. pub fn bind(space: AllocatedOf) -> Self { SupervisorState { diff --git a/src/riscv/lib/src/pvm/node_pvm.rs b/src/riscv/lib/src/pvm/node_pvm.rs index d28a6505f6e9..132d8f699a9b 100644 --- a/src/riscv/lib/src/pvm/node_pvm.rs +++ b/src/riscv/lib/src/pvm/node_pvm.rs @@ -18,6 +18,7 @@ use crate::machine_state::mode::Mode; use crate::program::Program; use crate::pvm::common::PvmHooks; use crate::pvm::common::PvmStatus; +use crate::state::NewState; use crate::state_backend; use crate::state_backend::AllocatedOf; use crate::state_backend::owned_backend::Owned; @@ -183,8 +184,7 @@ impl NodePvm { impl NodePvm { /// Construct an empty PVM state. pub fn empty() -> Self { - let space = Owned::allocate::(); - Self::bind(space) + Self::new(&mut Owned) } /// Compute the root hash of the PVM state. @@ -230,6 +230,17 @@ impl PartialEq for NodePvm { impl Eq for NodePvm {} +impl NewState for NodePvm { + fn new(manager: &mut M) -> Self + where + M: state_backend::ManagerAlloc, + { + Self { + state: Box::new(NodePvmState::::new(manager, InterpretedBlockBuilder)), + } + } +} + #[derive(Error, Debug)] pub enum PvmStorageError { #[error("Storage error: {0}")] diff --git a/src/riscv/lib/src/pvm/reveals.rs b/src/riscv/lib/src/pvm/reveals.rs index 5e2791fba80b..df882a6efd20 100644 --- a/src/riscv/lib/src/pvm/reveals.rs +++ b/src/riscv/lib/src/pvm/reveals.rs @@ -4,12 +4,14 @@ use tezos_smart_rollup_constants::riscv::REVEAL_REQUEST_MAX_SIZE; +use crate::state::NewState; use crate::state_backend::AllocatedOf; use crate::state_backend::Atom; use crate::state_backend::Cell; use crate::state_backend::DynArray; use crate::state_backend::DynCells; use crate::state_backend::FnManager; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerClone; use crate::state_backend::ManagerRead; @@ -57,6 +59,18 @@ impl RevealRequest { } } +impl NewState for RevealRequest { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + bytes: DynCells::new(manager), + size: Cell::new(manager), + } + } +} + impl Clone for RevealRequest { fn clone(&self) -> Self { Self { diff --git a/src/riscv/lib/src/state.rs b/src/riscv/lib/src/state.rs new file mode 100644 index 000000000000..0548aca07278 --- /dev/null +++ b/src/riscv/lib/src/state.rs @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2025 TriliTech +// +// SPDX-License-Identifier: MIT + +use std::array; + +use crate::array_utils::boxed_from_fn; +use crate::state_backend::ManagerAlloc; +use crate::state_backend::ManagerBase; + +/// Methods for creating a new state without additional information +pub trait NewState { + /// Create a new state. + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc; +} + +impl, const LEN: usize, M: ManagerBase> NewState for [T; LEN] { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + array::from_fn(|_| T::new(manager)) + } +} + +// We cannot compose the implementations of `NewState` for `[T; LEN]` and `Box<_>`. Doing so would +// allocate potentially large arrays on the stack and only then move them to the heap using `Box`. +// This results in potential stack overflow for large arrays. +// +// To avoid this, we implement a combined version `Box<[T; LEN]>` that does not allocate on the +// stack. This makes usage of `NewState::new` safe everywhere as it doesn't sneakily compose +// implementations that would result in stack overflows. +// +// This comes with a small trade-off, we loose out on the `Box<_>` implementation of `NewState`. +// However, this is not a problem since we can always use `Box::new` independently. +impl, const LEN: usize, M: ManagerBase> NewState for Box<[T; LEN]> { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + boxed_from_fn(|| T::new(manager)) + } +} diff --git a/src/riscv/lib/src/state_backend/effects.rs b/src/riscv/lib/src/state_backend/effects.rs index d38b3dc07b38..db6ff96b9390 100644 --- a/src/riscv/lib/src/state_backend/effects.rs +++ b/src/riscv/lib/src/state_backend/effects.rs @@ -8,14 +8,15 @@ use super::AllocatedOf; use super::Atom; use super::Cell; use super::FnManager; +use super::ManagerAlloc; use super::ManagerBase; use super::ManagerClone; use super::ManagerRead; use super::ManagerReadWrite; use super::ManagerWrite; use super::Ref; -use super::StaticCopy; use crate::default::ConstDefault; +use crate::state::NewState; /// XXX: Workaround trait for not having enum variants as const-generics pub trait EffectGetter { @@ -33,7 +34,7 @@ pub struct EffectCell { _pd: PhantomData, } -impl EffectCell { +impl EffectCell { pub fn bind(space: AllocatedOf, M>) -> Self { Self { inner: space, @@ -79,6 +80,18 @@ impl EffectCell { } } +impl NewState for EffectCell { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self { + inner: Cell::new(manager), + _pd: PhantomData, + } + } +} + impl Clone for EffectCell { fn clone(&self) -> Self { Self { diff --git a/src/riscv/lib/src/state_backend/region.rs b/src/riscv/lib/src/state_backend/region.rs index 7b308036aedd..3b381daa65b4 100644 --- a/src/riscv/lib/src/state_backend/region.rs +++ b/src/riscv/lib/src/state_backend/region.rs @@ -9,6 +9,7 @@ use super::Elem; use super::EnrichedValue; use super::EnrichedValueLinked; use super::FnManager; +use super::ManagerAlloc; use super::ManagerBase; use super::ManagerClone; use super::ManagerDeserialise; @@ -19,6 +20,8 @@ use super::ManagerWrite; use super::Ref; use super::proof_backend::ProofGen; use super::proof_backend::merkle::AccessInfoAggregatable; +use crate::default::ConstDefault; +use crate::state::NewState; /// Link a stored value directly with a derived value - /// that would either be expensive to compute each time, or cannot @@ -30,6 +33,17 @@ pub struct EnrichedCell { } impl EnrichedCell { + /// Allocate a new enriched cell with the given value. + pub fn new_with(manager: &mut M, value: V::E) -> Self + where + M: ManagerAlloc, + V: EnrichedValueLinked, + { + let region = manager.allocate_region([value]); + let cell = M::enrich_cell(region); + Self { cell } + } + /// Bind this state to the enriched cell. pub fn bind(cell: Cell) -> Self where @@ -93,6 +107,19 @@ impl EnrichedCell { } } +impl NewState for EnrichedCell +where + V: EnrichedValueLinked, + V::E: ConstDefault, +{ + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self::new_with(manager, ::DEFAULT) + } +} + impl Clone for EnrichedCell where V::E: Clone, @@ -122,6 +149,17 @@ pub struct Cell { } impl Cell { + /// Allocate a new cell with the given value. + pub fn new_with(manager: &mut M, value: E) -> Self + where + M: ManagerAlloc, + { + let region = manager.allocate_region([value]); + Self { + region: Cells::bind(region), + } + } + /// Bind this state to the single element region. pub const fn bind(region: M::Region) -> Self { Self { @@ -141,9 +179,7 @@ impl Cell { pub fn into_region(self) -> M::Region { self.region.into_region() } -} -impl Cell { /// Read the value managed by the cell. #[inline(always)] pub fn read(&self) -> E @@ -174,6 +210,15 @@ impl Cell { } } +impl NewState for Cell { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self::new_with(manager, E::DEFAULT) + } +} + impl From> for Cell { fn from(region: Cells) -> Self { Self { region } @@ -333,6 +378,15 @@ pub struct Cells { } impl Cells { + /// Allocate new cells with the given values. + pub fn new_with(manager: &mut M, values: [E; LEN]) -> Self + where + M: ManagerAlloc, + { + let region = manager.allocate_region(values); + Self { region } + } + /// Bind this state to the given region. pub const fn bind(region: M::Region) -> Self { Self { region } @@ -355,9 +409,7 @@ impl Cells { pub fn into_region(self) -> M::Region { self.region } -} -impl Cells { /// Read an element in the region. #[inline] pub fn read(&self, index: usize) -> E @@ -408,6 +460,15 @@ impl Cells { } } +impl NewState for Cells { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + Self::new_with(manager, [E::DEFAULT; LEN]) + } +} + impl serde::Serialize for Cells { @@ -555,6 +616,16 @@ impl DynCells { } } +impl NewState for DynCells { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + let region = manager.allocate_dyn_region(); + Self { region } + } +} + impl serde::Serialize for DynCells { fn serialize(&self, serializer: S) -> Result where diff --git a/src/riscv/lib/src/stepper/test.rs b/src/riscv/lib/src/stepper/test.rs index f4a773d21a57..b1da5e93db88 100644 --- a/src/riscv/lib/src/stepper/test.rs +++ b/src/riscv/lib/src/stepper/test.rs @@ -29,6 +29,7 @@ use crate::machine_state::memory::M1G; use crate::machine_state::memory::MemoryConfig; use crate::machine_state::mode; use crate::program::Program; +use crate::state::NewState; use crate::state_backend::owned_backend::Owned; use crate::traps::EnvironException; @@ -127,12 +128,9 @@ impl> TestStepper mode: mode::Mode, block_builder: B::BlockBuilder, ) -> Result<(Self, BTreeMap), TestStepperError> { - let (posix_space, machine_state_space) = Owned::allocate::>(); - let posix_state = PosixState::bind(posix_space); - let machine_state = MachineState::bind(machine_state_space, block_builder); let mut stepper = Self { - posix_state, - machine_state, + posix_state: PosixState::new(&mut Owned), + machine_state: MachineState::new(&mut Owned, block_builder), }; // By default the Posix EE expects to exit in a specific privilege mode. diff --git a/src/riscv/lib/src/stepper/test/posix.rs b/src/riscv/lib/src/stepper/test/posix.rs index 83d810473619..4301acd59784 100644 --- a/src/riscv/lib/src/stepper/test/posix.rs +++ b/src/riscv/lib/src/stepper/test/posix.rs @@ -9,9 +9,10 @@ use crate::machine_state::memory::MemoryConfig; use crate::machine_state::mode::Mode; use crate::machine_state::registers::a0; use crate::machine_state::registers::a7; -use crate::state_backend::AllocatedOf; +use crate::state::NewState; use crate::state_backend::Atom; use crate::state_backend::Cell; +use crate::state_backend::ManagerAlloc; use crate::state_backend::ManagerBase; use crate::state_backend::ManagerRead; use crate::state_backend::ManagerReadWrite; @@ -29,15 +30,6 @@ pub struct PosixState { } impl PosixState { - /// Bind the posix state to the given allocated space. - pub fn bind(space: AllocatedOf) -> Self { - Self { - code: space.0, - exited: space.1, - exit_mode: space.2, - } - } - /// If an exit has been requested, return the exit code. #[allow(dead_code)] pub fn exit_code(&self) -> Option @@ -123,3 +115,16 @@ impl PosixState { } } } + +impl NewState for PosixState { + fn new(manager: &mut M) -> Self + where + M: ManagerAlloc, + { + PosixState { + code: Cell::new(manager), + exited: Cell::new(manager), + exit_mode: Cell::new(manager), + } + } +} -- GitLab