sim: WIP adding memory support
All checks were successful
/ deps (push) Successful in 16s
/ test (push) Successful in 5m28s
/ deps (pull_request) Successful in 14s
/ test (pull_request) Successful in 5m24s

This commit is contained in:
Jacob Lifshay 2024-12-05 21:35:23 -08:00
parent e504cfebfe
commit 3ed7827485
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
8 changed files with 335 additions and 38 deletions

View file

@ -16,6 +16,7 @@ use crate::{
}, },
int::BoolOrIntType, int::BoolOrIntType,
intern::{Intern, Interned, Memoize}, intern::{Intern, Interned, Memoize},
memory::PortKind,
module::{ module::{
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule, transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule,
ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration,
@ -28,9 +29,9 @@ use crate::{
Insn, InsnField, InsnFieldKind, InsnFieldType, Insns, InsnsBuilding, InsnsBuildingDone, Insn, InsnField, InsnFieldKind, InsnFieldType, Insns, InsnsBuilding, InsnsBuildingDone,
SlotDebugData, SmallUInt, State, StatePartArrayIndex, StatePartArrayIndexed, SlotDebugData, SmallUInt, State, StatePartArrayIndex, StatePartArrayIndexed,
StatePartIndex, StatePartIndexRange, StatePartKind, StatePartKindBigSlots, StatePartIndex, StatePartIndexRange, StatePartKind, StatePartKindBigSlots,
StatePartKindSmallSlots, StatePartLayout, StatePartLen, StatePartsValue, StatePartKindMemories, StatePartKindSmallSlots, StatePartLayout, StatePartLen,
TypeArrayIndex, TypeArrayIndexes, TypeIndex, TypeIndexRange, TypeLayout, TypeLen, StatePartsValue, TypeArrayIndex, TypeArrayIndexes, TypeIndex, TypeIndexRange,
TypeParts, TypeLayout, TypeLen, TypeParts,
}, },
time::{SimDuration, SimInstant}, time::{SimDuration, SimInstant},
}, },
@ -136,7 +137,7 @@ impl<T: Type> CompiledTypeLayout<T> {
name: Interned::default(), name: Interned::default(),
ty: *input, ty: *input,
}; };
layout.big_slots = StatePartLayout::scalar(debug_data); layout.big_slots = StatePartLayout::scalar(debug_data, ());
CompiledTypeLayout { CompiledTypeLayout {
ty: *input, ty: *input,
layout: layout.into(), layout: layout.into(),
@ -1163,14 +1164,20 @@ impl Assignment {
} }
( (
_, _,
InsnFieldType::SmallUInt(_) InsnFieldType::Memory(_)
| InsnFieldType::SmallUInt(_)
| InsnFieldType::SmallSInt(_) | InsnFieldType::SmallSInt(_)
| InsnFieldType::InternedBigInt(_) | InsnFieldType::InternedBigInt(_)
| InsnFieldType::U8(_) | InsnFieldType::U8(_)
| InsnFieldType::USize(_) | InsnFieldType::USize(_)
| InsnFieldType::Empty(_), | InsnFieldType::Empty(_),
) )
| (InsnFieldKind::Immediate | InsnFieldKind::BranchTarget, _) => {} | (
InsnFieldKind::Immediate
| InsnFieldKind::Memory
| InsnFieldKind::BranchTarget,
_,
) => {}
} }
} }
} }
@ -1207,6 +1214,20 @@ struct Register {
source_location: SourceLocation, source_location: SourceLocation,
} }
#[derive(Debug)]
enum MemoryPort {
ReadOnly {},
WriteOnly {},
ReadWrite {},
}
#[derive(Debug)]
struct Memory {
mem: Mem,
memory: StatePartIndex<StatePartKindMemories>,
ports: Vec<MemoryPort>,
}
#[derive(Debug)] #[derive(Debug)]
pub struct Compiler { pub struct Compiler {
insns: Insns<InsnsBuilding>, insns: Insns<InsnsBuilding>,
@ -1227,6 +1248,7 @@ pub struct Compiler {
enum_discriminants: HashMap<CompiledValue<Enum>, StatePartIndex<StatePartKindSmallSlots>>, enum_discriminants: HashMap<CompiledValue<Enum>, StatePartIndex<StatePartKindSmallSlots>>,
registers: Vec<Register>, registers: Vec<Register>,
traces: Vec<SimTrace<()>>, traces: Vec<SimTrace<()>>,
memories: Vec<Memory>,
} }
impl Compiler { impl Compiler {
@ -1251,6 +1273,7 @@ impl Compiler {
enum_discriminants: HashMap::new(), enum_discriminants: HashMap::new(),
registers: Vec::new(), registers: Vec::new(),
traces: Vec::new(), traces: Vec::new(),
memories: Vec::new(),
} }
} }
fn new_sim_trace(&mut self, kind: SimTraceKind) -> TraceScalarId { fn new_sim_trace(&mut self, kind: SimTraceKind) -> TraceScalarId {
@ -1809,7 +1832,7 @@ impl Compiler {
let dest = self let dest = self
.insns .insns
.allocate_variable(&TypeLayout { .allocate_variable(&TypeLayout {
small_slots: StatePartLayout::scalar(debug_data), small_slots: StatePartLayout::scalar(debug_data, ()),
big_slots: StatePartLayout::empty(), big_slots: StatePartLayout::empty(),
}) })
.small_slots .small_slots
@ -1851,7 +1874,7 @@ impl Compiler {
let dest = self let dest = self
.insns .insns
.allocate_variable(&TypeLayout { .allocate_variable(&TypeLayout {
small_slots: StatePartLayout::scalar(debug_data), small_slots: StatePartLayout::scalar(debug_data, ()),
big_slots: StatePartLayout::empty(), big_slots: StatePartLayout::empty(),
}) })
.small_slots .small_slots
@ -3038,10 +3061,13 @@ impl Compiler {
.state_layout .state_layout
.ty .ty
.small_slots .small_slots
.allocate(&StatePartLayout::scalar(SlotDebugData { .allocate(&StatePartLayout::scalar(
name: Interned::default(), SlotDebugData {
ty: Bool.canonical(), name: Interned::default(),
})) ty: Bool.canonical(),
},
(),
))
.start .start
}; };
let last_clk_was_low = alloc_small_slot("last_clk_was_low"); let last_clk_was_low = alloc_small_slot("last_clk_was_low");
@ -3098,10 +3124,13 @@ impl Compiler {
.state_layout .state_layout
.ty .ty
.small_slots .small_slots
.allocate(&StatePartLayout::scalar(SlotDebugData { .allocate(&StatePartLayout::scalar(
name: Interned::default(), SlotDebugData {
ty: retval_ty.canonical(), name: Interned::default(),
})) ty: retval_ty.canonical(),
},
(),
))
.start; .start;
let discriminant_bit_width = enum_value.layout.ty.discriminant_bit_width(); let discriminant_bit_width = enum_value.layout.ty.discriminant_bit_width();
let discriminant_mask = !(!0u64 << discriminant_bit_width); let discriminant_mask = !(!0u64 << discriminant_bit_width);
@ -3289,6 +3318,49 @@ impl Compiler {
} }
self.make_trace_decl(*parent_module, target_base) self.make_trace_decl(*parent_module, target_base)
} }
fn compile_memory(
&mut self,
mem: Mem,
instantiated_module: InstantiatedModule,
conditions: Interned<[Cond]>,
trace_decls: &mut Vec<TraceDecl>,
) {
let memory = self
.insns
.state_layout
.memories
.allocate(&StatePartLayout::scalar(
(),
mem.initial_value().unwrap_or_else(|| {
Intern::intern_owned(BitVec::repeat(
false,
mem.array_type().type_properties().bit_width,
))
}),
))
.start;
let ports = mem
.ports()
.iter()
.map(|&port| {
let target_base = TargetBase::MemPort(port);
let target = TargetInInstantiatedModule {
instantiated_module,
target: target_base.into(),
};
self.decl_conditions.insert(target, conditions);
trace_decls.push(self.make_trace_decl(instantiated_module, target_base));
todo!("handle read/write");
match port.port_kind() {
PortKind::ReadOnly => MemoryPort::ReadOnly {},
PortKind::WriteOnly => MemoryPort::WriteOnly {},
PortKind::ReadWrite => MemoryPort::ReadWrite {},
}
})
.collect();
self.memories.push(Memory { mem, memory, ports });
todo!("implement memory");
}
fn compile_block( fn compile_block(
&mut self, &mut self,
parent_module: Interned<InstantiatedModule>, parent_module: Interned<InstantiatedModule>,
@ -3298,7 +3370,7 @@ impl Compiler {
) { ) {
let Block { memories, stmts } = block; let Block { memories, stmts } = block;
for memory in memories { for memory in memories {
todo!("implement memory"); self.compile_memory(memory, *parent_module, conditions, trace_decls);
} }
for stmt in stmts { for stmt in stmts {
match stmt { match stmt {
@ -3613,11 +3685,17 @@ impl Compiler {
} }
} }
} }
fn process_memories(&mut self) {
for memory in mem::take(&mut self.memories) {
todo!();
}
}
pub fn compile(mut self) -> Compiled<Bundle> { pub fn compile(mut self) -> Compiled<Bundle> {
let base_module = let base_module =
*self.compile_module(InstantiatedModule::Base(self.base_module).intern_sized()); *self.compile_module(InstantiatedModule::Base(self.base_module).intern_sized());
self.process_assignments(); self.process_assignments();
self.process_registers(); self.process_registers();
self.process_memories();
let clocks_triggered = self.process_clocks(); let clocks_triggered = self.process_clocks();
self.insns self.insns
.push(Insn::Return, self.base_module.source_location()); .push(Insn::Return, self.base_module.source_location());

View file

@ -2,15 +2,18 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
int::{BoolOrIntType, SInt, UInt},
intern::{Intern, Interned, Memoize}, intern::{Intern, Interned, Memoize},
source_location::SourceLocation, source_location::SourceLocation,
ty::CanonicalType, ty::CanonicalType,
util::get_many_mut, util::get_many_mut,
}; };
use bitvec::{boxed::BitBox, slice::BitSlice};
use hashbrown::HashMap; use hashbrown::HashMap;
use num_bigint::BigInt; use num_bigint::BigInt;
use num_traits::{One, Signed, ToPrimitive, Zero}; use num_traits::{One, Signed, ToPrimitive, Zero};
use std::{ use std::{
any::TypeId,
borrow::BorrowMut, borrow::BorrowMut,
convert::Infallible, convert::Infallible,
fmt, fmt,
@ -28,6 +31,7 @@ pub(crate) const MIN_BITS_FOR_NEEDING_BIG: usize = SmallUInt::BITS as usize + 1;
pub(crate) enum InsnFieldKind { pub(crate) enum InsnFieldKind {
Input, Input,
Output, Output,
Memory,
Immediate, Immediate,
BranchTarget, BranchTarget,
} }
@ -108,6 +112,7 @@ macro_rules! insn_field_enum {
insn_field_enum! { insn_field_enum! {
pub(crate) enum InsnFieldType<Transform: InsnFieldTypeTransform> { pub(crate) enum InsnFieldType<Transform: InsnFieldTypeTransform> {
Memory(Transform::Type<StatePartIndex<StatePartKindMemories>>),
SmallSlot(Transform::Type<StatePartIndex<StatePartKindSmallSlots>>), SmallSlot(Transform::Type<StatePartIndex<StatePartKindSmallSlots>>),
BigSlot(Transform::Type<StatePartIndex<StatePartKindBigSlots>>), BigSlot(Transform::Type<StatePartIndex<StatePartKindBigSlots>>),
SmallSlotArrayIndexed(Transform::Type<StatePartArrayIndexed<StatePartKindSmallSlots>>), SmallSlotArrayIndexed(Transform::Type<StatePartArrayIndexed<StatePartKindSmallSlots>>),
@ -206,7 +211,8 @@ impl Insn {
continue; continue;
} }
} }
InsnFieldType::SmallSlot(_) InsnFieldType::Memory(_)
| InsnFieldType::SmallSlot(_)
| InsnFieldType::BigSlot(_) | InsnFieldType::BigSlot(_)
| InsnFieldType::SmallSlotArrayIndexed(_) | InsnFieldType::SmallSlotArrayIndexed(_)
| InsnFieldType::BigSlotArrayIndexed(_) | InsnFieldType::BigSlotArrayIndexed(_)
@ -216,9 +222,15 @@ impl Insn {
| InsnFieldType::U8(_) | InsnFieldType::U8(_)
| InsnFieldType::Empty(_) => {} | InsnFieldType::Empty(_) => {}
}, },
InsnFieldKind::Input | InsnFieldKind::Output | InsnFieldKind::Immediate => {} InsnFieldKind::Input
| InsnFieldKind::Memory
| InsnFieldKind::Output
| InsnFieldKind::Immediate => {}
} }
match field.ty { match field.ty {
InsnFieldType::Memory(v) => {
v.debug_fmt(f, ",", " // ", "", state_layout)?;
}
InsnFieldType::SmallSlot(v) => { InsnFieldType::SmallSlot(v) => {
v.debug_fmt(f, ",", " // ", "", state_layout)?; v.debug_fmt(f, ",", " // ", "", state_layout)?;
} }
@ -577,9 +589,10 @@ pub(crate) trait StatePartKind:
{ {
const NAME: &'static str; const NAME: &'static str;
type DebugData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy; type DebugData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy;
type LayoutData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy;
type State: fmt::Debug + 'static + Clone; type State: fmt::Debug + 'static + Clone;
type BorrowedState<'a>: 'a; type BorrowedState<'a>: 'a;
fn new_state(len: StatePartLen<Self>) -> Self::State; fn new_state(layout_data: &[Self::LayoutData]) -> Self::State;
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a>; fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a>;
fn part_debug_data<BK: InsnsBuildingKind>( fn part_debug_data<BK: InsnsBuildingKind>(
state_layout: &StateLayout<BK>, state_layout: &StateLayout<BK>,
@ -950,8 +963,8 @@ macro_rules! make_state_part_kinds {
Self { Self {
insns, insns,
pc: 0, pc: 0,
$($state_field: StatePart::new(insns.state_layout.$state_field.len()),)* $($state_field: StatePart::new(&insns.state_layout.$state_field.layout_data),)*
$($type_field: StatePart::new(insns.state_layout.ty.$type_field.len()),)* $($type_field: StatePart::new(&insns.state_layout.ty.$type_field.layout_data),)*
} }
} }
pub(crate) fn borrow(&mut self) -> BorrowedState<'_> { pub(crate) fn borrow(&mut self) -> BorrowedState<'_> {
@ -1150,10 +1163,11 @@ make_state_part_kinds! {
impl StatePartKind for StatePartKindSmallStack { impl StatePartKind for StatePartKindSmallStack {
const NAME: &'static str = "SmallStack"; const NAME: &'static str = "SmallStack";
type DebugData = (); type DebugData = ();
type LayoutData = ();
type State = Stack<SmallUInt>; type State = Stack<SmallUInt>;
type BorrowedState<'a> = BorrowedStack<'a, SmallUInt>; type BorrowedState<'a> = BorrowedStack<'a, SmallUInt>;
fn new_state(len: StatePartLen<Self>) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
Stack::new(len.value.try_into().expect("state is too big")) Stack::new(layout_data.len())
} }
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state.borrow() state.borrow()
@ -1169,10 +1183,11 @@ make_state_part_kinds! {
impl StatePartKind for StatePartKindBigStack { impl StatePartKind for StatePartKindBigStack {
const NAME: &'static str = "BigStack"; const NAME: &'static str = "BigStack";
type DebugData = (); type DebugData = ();
type LayoutData = ();
type State = Stack<BigInt>; type State = Stack<BigInt>;
type BorrowedState<'a> = BorrowedStack<'a, BigInt>; type BorrowedState<'a> = BorrowedStack<'a, BigInt>;
fn new_state(len: StatePartLen<Self>) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
Stack::new(len.value.try_into().expect("state is too big")) Stack::new(layout_data.len())
} }
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state.borrow() state.borrow()
@ -1184,14 +1199,35 @@ make_state_part_kinds! {
state_layout.big_stack.debug_data.get(part_index.as_usize()) state_layout.big_stack.debug_data.get(part_index.as_usize())
} }
}*/ }*/
#[state, field = memories]
impl StatePartKind for StatePartKindMemories {
const NAME: &'static str = "Memories";
type DebugData = ();
type LayoutData = Interned<BitSlice>;
type State = Box<[BitBox]>;
type BorrowedState<'a> = &'a mut [BitBox];
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
layout_data.iter().map(|initial_data| BitBox::from_bitslice(initial_data)).collect()
}
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state
}
fn part_debug_data<BK: InsnsBuildingKind>(
state_layout: &StateLayout<BK>,
part_index: StatePartIndex<Self>,
) -> Option<&Self::DebugData> {
state_layout.memories.debug_data.get(part_index.as_usize())
}
}
#[type, field = small_slots] #[type, field = small_slots]
impl StatePartKind for StatePartKindSmallSlots { impl StatePartKind for StatePartKindSmallSlots {
const NAME: &'static str = "SmallSlots"; const NAME: &'static str = "SmallSlots";
type DebugData = SlotDebugData; type DebugData = SlotDebugData;
type LayoutData = ();
type State = Box<[SmallUInt]>; type State = Box<[SmallUInt]>;
type BorrowedState<'a> = &'a mut [SmallUInt]; type BorrowedState<'a> = &'a mut [SmallUInt];
fn new_state(len: StatePartLen<Self>) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
vec![0; len.value.try_into().expect("state is too big")].into_boxed_slice() vec![0; layout_data.len()].into_boxed_slice()
} }
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state state
@ -1207,10 +1243,11 @@ make_state_part_kinds! {
impl StatePartKind for StatePartKindBigSlots { impl StatePartKind for StatePartKindBigSlots {
const NAME: &'static str = "BigSlots"; const NAME: &'static str = "BigSlots";
type DebugData = SlotDebugData; type DebugData = SlotDebugData;
type LayoutData = ();
type State = Box<[BigInt]>; type State = Box<[BigInt]>;
type BorrowedState<'a> = &'a mut [BigInt]; type BorrowedState<'a> = &'a mut [BigInt];
fn new_state(len: StatePartLen<Self>) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
std::iter::repeat_with(BigInt::default).take(len.value.try_into().expect("state is too big")).collect() layout_data.iter().map(|_| BigInt::default()).collect()
} }
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state state
@ -1348,6 +1385,7 @@ impl<K: StatePartKind<DebugData = SlotDebugData>, BK: InsnsBuildingKind> StatePa
.iter() .iter()
.map(|v| v.with_prefixed_debug_names(prefix)) .map(|v| v.with_prefixed_debug_names(prefix))
.collect(), .collect(),
layout_data: self.layout_data.clone(),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
@ -1358,6 +1396,7 @@ impl<K: StatePartKind<DebugData = SlotDebugData>, BK: InsnsBuildingKind> StatePa
.iter() .iter()
.map(|v| v.with_anonymized_debug_info()) .map(|v| v.with_anonymized_debug_info())
.collect(), .collect(),
layout_data: self.layout_data.clone(),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
@ -1552,6 +1591,7 @@ impl<K: StatePartKind> fmt::Debug for StatePartLen<K> {
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub(crate) struct StatePartLayout<K: StatePartKind, BK: InsnsBuildingKind> { pub(crate) struct StatePartLayout<K: StatePartKind, BK: InsnsBuildingKind> {
pub(crate) debug_data: BK::Vec<K::DebugData>, pub(crate) debug_data: BK::Vec<K::DebugData>,
pub(crate) layout_data: BK::Vec<K::LayoutData>,
pub(crate) _phantom: PhantomData<K>, pub(crate) _phantom: PhantomData<K>,
} }
@ -1572,6 +1612,7 @@ impl<K: StatePartKind, BK: InsnsBuildingKind> StatePartLayout<K, BK> {
pub(crate) fn empty() -> Self { pub(crate) fn empty() -> Self {
Self { Self {
debug_data: Default::default(), debug_data: Default::default(),
layout_data: Default::default(),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
@ -1583,15 +1624,17 @@ impl<K: StatePartKind> From<StatePartLayout<K, InsnsBuilding>>
fn from(value: StatePartLayout<K, InsnsBuilding>) -> Self { fn from(value: StatePartLayout<K, InsnsBuilding>) -> Self {
Self { Self {
debug_data: Intern::intern_owned(value.debug_data), debug_data: Intern::intern_owned(value.debug_data),
layout_data: Intern::intern_owned(value.layout_data),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
} }
impl<K: StatePartKind> StatePartLayout<K, InsnsBuilding> { impl<K: StatePartKind> StatePartLayout<K, InsnsBuilding> {
pub(crate) fn scalar(debug_data: K::DebugData) -> Self { pub(crate) fn scalar(debug_data: K::DebugData, layout_data: K::LayoutData) -> Self {
Self { Self {
debug_data: vec![debug_data], debug_data: vec![debug_data],
layout_data: vec![layout_data],
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
@ -1609,9 +1652,11 @@ impl<K: StatePartKind> StatePartLayout<K, InsnsBuilding> {
let len = layout.len(); let len = layout.len();
let Self { let Self {
debug_data, debug_data,
layout_data,
_phantom: _, _phantom: _,
} = self; } = self;
debug_data.extend_from_slice(&layout.debug_data); debug_data.extend_from_slice(&layout.debug_data);
layout_data.extend_from_slice(&layout.layout_data);
StatePartIndexRange { start, len } StatePartIndexRange { start, len }
} }
} }
@ -1620,13 +1665,18 @@ impl<K: StatePartKind, BK: InsnsBuildingKind> fmt::Debug for StatePartLayout<K,
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
debug_data, debug_data,
layout_data,
_phantom: _, _phantom: _,
} = self; } = self;
write!(f, "StatePartAllocationLayout<{}>", K::NAME)?; write!(f, "StatePartAllocationLayout<{}>", K::NAME)?;
f.debug_struct("") let mut debug_struct = f.debug_struct("");
debug_struct
.field("len", &debug_data.len()) .field("len", &debug_data.len())
.field("debug_data", debug_data) .field("debug_data", debug_data);
.finish_non_exhaustive() if TypeId::of::<K::LayoutData>() != TypeId::of::<()>() {
debug_struct.field("layout_data", layout_data);
}
debug_struct.finish_non_exhaustive()
} }
} }
@ -1723,9 +1773,9 @@ pub(crate) struct StatePart<K: StatePartKind> {
} }
impl<K: StatePartKind> StatePart<K> { impl<K: StatePartKind> StatePart<K> {
pub(crate) fn new(len: StatePartLen<K>) -> Self { pub(crate) fn new(layout_data: &[K::LayoutData]) -> Self {
Self { Self {
value: K::new_state(len), value: K::new_state(layout_data),
} }
} }
pub(crate) fn borrow<'a>(&'a mut self) -> BorrowedStatePart<'a, K> { pub(crate) fn borrow<'a>(&'a mut self) -> BorrowedStatePart<'a, K> {
@ -2020,7 +2070,8 @@ impl From<Insns<InsnsBuilding>> for Insns<InsnsBuildingDone> {
.address .address
.expect("label address not set"); .expect("label address not set");
} }
InsnFieldType::SmallSlot(_) InsnFieldType::Memory(_)
| InsnFieldType::SmallSlot(_)
| InsnFieldType::BigSlot(_) | InsnFieldType::BigSlot(_)
| InsnFieldType::SmallSlotArrayIndexed(_) | InsnFieldType::SmallSlotArrayIndexed(_)
| InsnFieldType::BigSlotArrayIndexed(_) | InsnFieldType::BigSlotArrayIndexed(_)
@ -2032,7 +2083,10 @@ impl From<Insns<InsnsBuilding>> for Insns<InsnsBuildingDone> {
unreachable!() unreachable!()
} }
}, },
InsnFieldKind::Input | InsnFieldKind::Output | InsnFieldKind::Immediate => {} InsnFieldKind::Input
| InsnFieldKind::Memory
| InsnFieldKind::Output
| InsnFieldKind::Immediate => {}
} }
} }
} }
@ -2050,6 +2104,7 @@ impl State {
let Self { let Self {
insns: _, insns: _,
pc, pc,
memories: _,
small_slots: _, small_slots: _,
big_slots: _, big_slots: _,
} = self; } = self;
@ -2161,6 +2216,44 @@ fn cast_bigint_to_uint(src: &BigInt, dest_width: usize) -> BigInt {
src & &*bigint_mask(dest_width) src & &*bigint_mask(dest_width)
} }
fn memory_get_mut(
memory: &mut BitSlice,
addr: SmallUInt,
stride: usize,
start: usize,
width: usize,
) -> Option<&mut BitSlice> {
let start = usize::try_from(addr)
.ok()?
.checked_mul(stride)?
.checked_add(start)?;
memory.get_mut(start..start.checked_add(width)?)
}
fn memory_read_big<T: BoolOrIntType>(
memory: &mut BitSlice,
addr: SmallUInt,
stride: usize,
start: usize,
width: usize,
) -> Option<BigInt> {
let bits = memory_get_mut(memory, addr, stride, start, width)?;
Some(T::bits_to_bigint(bits))
}
fn memory_write_big<T: BoolOrIntType>(
memory: &mut BitSlice,
addr: SmallUInt,
stride: usize,
start: usize,
width: usize,
value: &BigInt,
) -> Option<()> {
let bits = memory_get_mut(memory, addr, stride, start, width)?;
T::copy_bits_from_bigint_wrapping(value, bits);
Some(())
}
impl_insns! { impl_insns! {
#[insn = Insn, next_macro = next, branch_macro = branch] #[insn = Insn, next_macro = next, branch_macro = branch]
pub(crate) fn State::run(&mut self) -> () { pub(crate) fn State::run(&mut self) -> () {
@ -2702,6 +2795,78 @@ impl_insns! {
next!(); next!();
} }
} }
MemoryReadUInt {
#[kind = Output]
dest: StatePartIndex<StatePartKindBigSlots>,
#[kind = Memory]
memory: StatePartIndex<StatePartKindMemories>,
#[kind = Input]
addr: StatePartIndex<StatePartKindSmallSlots>,
#[kind = Immediate]
stride: usize,
#[kind = Immediate]
start: usize,
#[kind = Immediate]
width: usize,
} => {
let addr = state.small_slots[addr];
state.big_slots[dest] = memory_read_big::<UInt>(&mut state.memories[memory], addr, stride, start, width).unwrap_or_default();
next!();
}
MemoryReadSInt {
#[kind = Output]
dest: StatePartIndex<StatePartKindBigSlots>,
#[kind = Memory]
memory: StatePartIndex<StatePartKindMemories>,
#[kind = Input]
addr: StatePartIndex<StatePartKindSmallSlots>,
#[kind = Immediate]
stride: usize,
#[kind = Immediate]
start: usize,
#[kind = Immediate]
width: usize,
} => {
let addr = state.small_slots[addr];
state.big_slots[dest] = memory_read_big::<SInt>(&mut state.memories[memory], addr, stride, start, width).unwrap_or_default();
next!();
}
MemoryWriteUInt {
#[kind = Input]
value: StatePartIndex<StatePartKindBigSlots>,
#[kind = Memory]
memory: StatePartIndex<StatePartKindMemories>,
#[kind = Input]
addr: StatePartIndex<StatePartKindSmallSlots>,
#[kind = Immediate]
stride: usize,
#[kind = Immediate]
start: usize,
#[kind = Immediate]
width: usize,
} => {
let addr = state.small_slots[addr];
memory_write_big::<UInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
next!();
}
MemoryWriteSInt {
#[kind = Input]
value: StatePartIndex<StatePartKindBigSlots>,
#[kind = Memory]
memory: StatePartIndex<StatePartKindMemories>,
#[kind = Input]
addr: StatePartIndex<StatePartKindSmallSlots>,
#[kind = Immediate]
stride: usize,
#[kind = Immediate]
start: usize,
#[kind = Immediate]
width: usize,
} => {
let addr = state.small_slots[addr];
memory_write_big::<SInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
next!();
}
Return => { Return => {
break; break;
} }

View file

@ -23,6 +23,12 @@ Simulation {
.. ..
}, },
}, },
memories: StatePartAllocationLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
}, },
insns: [ insns: [
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
@ -41,6 +47,9 @@ Simulation {
.. ..
}, },
pc: 2, pc: 2,
memories: StatePart {
value: [],
},
small_slots: StatePart { small_slots: StatePart {
value: [], value: [],
}, },

View file

@ -35,6 +35,12 @@ Simulation {
.. ..
}, },
}, },
memories: StatePartAllocationLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
}, },
insns: [ insns: [
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
@ -67,6 +73,9 @@ Simulation {
.. ..
}, },
pc: 5, pc: 5,
memories: StatePart {
value: [],
},
small_slots: StatePart { small_slots: StatePart {
value: [], value: [],
}, },

View file

@ -72,6 +72,12 @@ Simulation {
.. ..
}, },
}, },
memories: StatePartAllocationLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
}, },
insns: [ insns: [
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
@ -162,6 +168,9 @@ Simulation {
.. ..
}, },
pc: 18, pc: 18,
memories: StatePart {
value: [],
},
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
18446744073709551614, 18446744073709551614,

View file

@ -68,6 +68,12 @@ Simulation {
.. ..
}, },
}, },
memories: StatePartAllocationLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
}, },
insns: [ insns: [
// at: module-XXXXXXXXXX.rs:6:1 // at: module-XXXXXXXXXX.rs:6:1
@ -144,6 +150,9 @@ Simulation {
.. ..
}, },
pc: 15, pc: 15,
memories: StatePart {
value: [],
},
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
18446744073709551614, 18446744073709551614,

View file

@ -83,6 +83,12 @@ Simulation {
.. ..
}, },
}, },
memories: StatePartAllocationLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
}, },
insns: [ insns: [
// at: module-XXXXXXXXXX.rs:4:1 // at: module-XXXXXXXXXX.rs:4:1
@ -174,6 +180,9 @@ Simulation {
.. ..
}, },
pc: 17, pc: 17,
memories: StatePart {
value: [],
},
small_slots: StatePart { small_slots: StatePart {
value: [], value: [],
}, },

View file

@ -84,6 +84,12 @@ Simulation {
.. ..
}, },
}, },
memories: StatePartAllocationLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
}, },
insns: [ insns: [
// at: module-XXXXXXXXXX.rs:13:1 // at: module-XXXXXXXXXX.rs:13:1
@ -221,6 +227,9 @@ Simulation {
.. ..
}, },
pc: 30, pc: 30,
memories: StatePart {
value: [],
},
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
18446744073709551614, 18446744073709551614,