From 402f457c68547ef5e0400926527bf0e3118af27f Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 30 Apr 2026 19:06:01 -0700 Subject: [PATCH 01/15] sim: Speed up updating traces by tracking which traces are written to --- crates/fayalite/src/sim.rs | 49 ++- crates/fayalite/src/sim/compiler.rs | 1 + crates/fayalite/src/sim/interpreter.rs | 53 +-- crates/fayalite/src/sim/interpreter/parts.rs | 263 ++++++++++++- .../fayalite/tests/sim/expected/array_rw.txt | 59 ++- .../expected/conditional_assignment_last.txt | 6 +- .../tests/sim/expected/connect_const.txt | 3 +- .../sim/expected/connect_const_reset.txt | 8 +- .../tests/sim/expected/counter_async.txt | 24 +- .../tests/sim/expected/counter_sync.txt | 22 +- .../tests/sim/expected/duplicate_names.txt | 6 +- crates/fayalite/tests/sim/expected/enums.txt | 217 ++++++----- .../tests/sim/expected/extern_module.txt | 2 + .../tests/sim/expected/extern_module2.txt | 5 +- .../tests/sim/expected/last_connect.txt | 62 +-- .../tests/sim/expected/many_memories.txt | 368 ++++++++++++------ .../fayalite/tests/sim/expected/memories.txt | 56 ++- .../fayalite/tests/sim/expected/memories2.txt | 78 ++-- .../fayalite/tests/sim/expected/memories3.txt | 184 ++++++--- crates/fayalite/tests/sim/expected/mod1.txt | 22 +- .../tests/sim/expected/phantom_const.txt | 26 +- .../sim/expected/queue_1_false_false.txt | 166 ++++---- .../tests/sim/expected/queue_1_false_true.txt | 162 ++++---- .../tests/sim/expected/queue_1_true_false.txt | 166 ++++---- .../tests/sim/expected/queue_1_true_true.txt | 162 ++++---- .../sim/expected/queue_2_false_false.txt | 170 ++++---- .../tests/sim/expected/queue_2_false_true.txt | 166 ++++---- .../tests/sim/expected/queue_2_true_false.txt | 170 ++++---- .../tests/sim/expected/queue_2_true_true.txt | 166 ++++---- .../sim/expected/queue_3_false_false.txt | 173 ++++---- .../tests/sim/expected/queue_3_false_true.txt | 169 ++++---- .../tests/sim/expected/queue_3_true_false.txt | 173 ++++---- .../tests/sim/expected/queue_3_true_true.txt | 169 ++++---- .../sim/expected/queue_4_false_false.txt | 170 ++++---- .../tests/sim/expected/queue_4_false_true.txt | 166 ++++---- .../tests/sim/expected/queue_4_true_false.txt | 170 ++++---- .../tests/sim/expected/queue_4_true_true.txt | 166 ++++---- .../tests/sim/expected/ripple_counter.txt | 127 +++--- .../tests/sim/expected/shift_register.txt | 26 +- .../tests/sim/expected/sim_fork_join.txt | 14 +- .../sim/expected/sim_fork_join_scope.txt | 14 +- .../tests/sim/expected/sim_only_connects.txt | 50 ++- .../tests/sim/expected/sim_read_past.txt | 122 +++--- .../expected/sim_resettable_counter_async.txt | 7 +- ...settable_counter_async_immediate_reset.txt | 7 +- .../expected/sim_resettable_counter_sync.txt | 5 +- ...esettable_counter_sync_immediate_reset.txt | 5 +- 47 files changed, 2888 insertions(+), 1687 deletions(-) diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index 45691ea..b3e4cd6 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -828,6 +828,7 @@ where #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) struct SimTrace { kind: K, + maybe_changed: bool, state: S, last_state: S, } @@ -848,12 +849,14 @@ impl SimTraceDebug for SimTrace { fn fmt(&self, id: TraceScalarId, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { kind, + maybe_changed, state, last_state, } = self; f.debug_struct("SimTrace") .field("id", &id) .field("kind", kind) + .field("maybe_changed", maybe_changed) .field("state", state) .field("last_state", last_state) .finish() @@ -864,12 +867,14 @@ impl SimTraceDebug for SimTrace fn fmt(&self, id: TraceScalarId, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { kind, + maybe_changed, state, last_state, } = self; f.debug_struct("SimTrace") .field("id", &id) .field("kind", kind) + .field("maybe_changed", maybe_changed) .field("state", state) .field("last_state", last_state) .finish() @@ -2078,10 +2083,12 @@ impl SimulationImpl { traces: SimTraces(Box::from_iter(compiled.traces.0.iter().map( |&SimTrace { kind, + maybe_changed: _, state: _, last_state: _, }| SimTrace { kind, + maybe_changed: true, state: kind.make_state(), last_state: kind.make_state(), }, @@ -2126,13 +2133,16 @@ impl SimulationImpl { id, &SimTrace { kind, + maybe_changed, ref state, ref last_state, }, ) in self.traces.0.iter().enumerate() { - if ONLY_IF_CHANGED && state == last_state { - continue; + if ONLY_IF_CHANGED { + if !(maybe_changed && state != last_state) { + continue; + } } let id = TraceScalarId(id); match kind { @@ -2193,10 +2203,45 @@ impl SimulationImpl { fn read_traces(&mut self) { for &mut SimTrace { kind, + ref mut maybe_changed, ref mut state, ref mut last_state, } in &mut self.traces.0 { + let new_maybe_changed = match kind { + SimTraceKind::BigUInt { index, ty: _ } + | SimTraceKind::BigSInt { index, ty: _ } + | SimTraceKind::BigBool { index } + | SimTraceKind::BigAsyncReset { index } + | SimTraceKind::BigSyncReset { index } + | SimTraceKind::BigClock { index } => self + .state + .big_slots + .state_index_fetch_and_clear_maybe_modified_flag(index), + SimTraceKind::SmallUInt { index, ty: _ } + | SimTraceKind::SmallSInt { index, ty: _ } + | SimTraceKind::SmallBool { index } + | SimTraceKind::SmallAsyncReset { index } + | SimTraceKind::SmallSyncReset { index } + | SimTraceKind::SmallClock { index } + | SimTraceKind::EnumDiscriminant { index, ty: _ } => self + .state + .small_slots + .state_index_fetch_and_clear_maybe_modified_flag(index), + SimTraceKind::SimOnly { index, ty: _ } => self + .state + .sim_only_slots + .state_index_fetch_and_clear_maybe_modified_flag(index), + SimTraceKind::PhantomConst { ty: _ } => IS_INITIAL_STEP, + }; + if !new_maybe_changed && !IS_INITIAL_STEP { + if *maybe_changed { + last_state.clone_from(state); + } + *maybe_changed = false; + continue; + } + *maybe_changed = new_maybe_changed; if !IS_INITIAL_STEP { mem::swap(state, last_state); } diff --git a/crates/fayalite/src/sim/compiler.rs b/crates/fayalite/src/sim/compiler.rs index e85ff0f..dbdbffb 100644 --- a/crates/fayalite/src/sim/compiler.rs +++ b/crates/fayalite/src/sim/compiler.rs @@ -2234,6 +2234,7 @@ impl Compiler { let id = TraceScalarId(self.traces.0.len()); self.traces.0.push(SimTrace { kind, + maybe_changed: true, state: (), last_state: (), }); diff --git a/crates/fayalite/src/sim/interpreter.rs b/crates/fayalite/src/sim/interpreter.rs index 2b121b5..0cf98d0 100644 --- a/crates/fayalite/src/sim/interpreter.rs +++ b/crates/fayalite/src/sim/interpreter.rs @@ -17,12 +17,11 @@ use bitvec::slice::BitSlice; use num_bigint::BigInt; use num_traits::{One, Signed, ToPrimitive, Zero}; use std::{ - borrow::BorrowMut, convert::Infallible, fmt::{self, Write}, hash::Hash, marker::PhantomData, - ops::{ControlFlow, Deref, DerefMut, Index, IndexMut}, + ops::{ControlFlow, Deref, Index, IndexMut}, }; use vec_map::VecMap; @@ -915,6 +914,12 @@ impl StatePart { value: K::borrow_state(&mut self.value), } } + pub(crate) fn state_index_fetch_and_clear_maybe_modified_flag( + &mut self, + part_index: StatePartIndex, + ) -> bool { + K::state_index_fetch_and_clear_maybe_modified_flag(&mut self.value, part_index) + } } #[derive(Clone, PartialEq, Eq, Hash, Debug)] @@ -922,56 +927,38 @@ pub(crate) struct BorrowedStatePart<'a, K: StatePartKind> { pub(crate) value: K::BorrowedState<'a>, } -impl< - 'a, - K: StatePartKind< - BorrowedState<'a>: DerefMut + BorrowMut<[T]>>, - >, - T, -> BorrowedStatePart<'a, K> -{ +impl BorrowedStatePart<'_, K> { pub(crate) fn get_disjoint_mut( &mut self, indexes: [StatePartIndex; N], - ) -> [&mut T; N] { - (*self.value) - .borrow_mut() - .get_disjoint_mut(indexes.map(|v| v.value as usize)) - .expect("indexes are disjoint") + ) -> [&mut K::StateElement; N] { + K::borrowed_state_get_disjoint_mut(&mut self.value, indexes) } } -impl>>, T> Index> - for StatePart -{ - type Output = T; +impl Index> for StatePart { + type Output = K::StateElement; fn index(&self, index: StatePartIndex) -> &Self::Output { - &self.value[index.value as usize] + K::state_index(&self.value, index) } } -impl>>, T> - IndexMut> for StatePart -{ +impl IndexMut> for StatePart { fn index_mut(&mut self, index: StatePartIndex) -> &mut Self::Output { - &mut self.value[index.value as usize] + K::state_index_mut(&mut self.value, index) } } -impl<'a, K: StatePartKind: Deref>>, T> - Index> for BorrowedStatePart<'a, K> -{ - type Output = T; +impl Index> for BorrowedStatePart<'_, K> { + type Output = K::StateElement; fn index(&self, index: StatePartIndex) -> &Self::Output { - &self.value[index.value as usize] + K::borrowed_state_index(&self.value, index) } } -impl<'a, K: StatePartKind: DerefMut>>, T> - IndexMut> for BorrowedStatePart<'a, K> -{ +impl IndexMut> for BorrowedStatePart<'_, K> { fn index_mut(&mut self, index: StatePartIndex) -> &mut Self::Output { - &mut self.value[index.value as usize] + K::borrowed_state_index_mut(&mut self.value, index) } } diff --git a/crates/fayalite/src/sim/interpreter/parts.rs b/crates/fayalite/src/sim/interpreter/parts.rs index 75427c9..d9e4214 100644 --- a/crates/fayalite/src/sim/interpreter/parts.rs +++ b/crates/fayalite/src/sim/interpreter/parts.rs @@ -236,6 +236,7 @@ pub(crate) trait StatePartKind: type LayoutData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy; type State: fmt::Debug + 'static + Clone; type BorrowedState<'a>: 'a; + type StateElement; fn new_state(layout_data: &[Self::LayoutData]) -> Self::State; fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a>; fn part_debug_data( @@ -247,6 +248,30 @@ pub(crate) trait StatePartKind: index: StatePartIndex, f: &mut impl fmt::Write, ) -> fmt::Result; + fn state_index<'a>( + state: &'a Self::State, + part_index: StatePartIndex, + ) -> &'a Self::StateElement; + fn state_index_mut<'a>( + state: &'a mut Self::State, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement; + fn state_index_fetch_and_clear_maybe_modified_flag( + state: &mut Self::State, + part_index: StatePartIndex, + ) -> bool; + fn borrowed_state_index<'a, 'b>( + state: &'a Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a Self::StateElement; + fn borrowed_state_index_mut<'a, 'b>( + state: &'a mut Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement; + fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>( + state: &'a mut Self::BorrowedState<'b>, + part_indexes: [StatePartIndex; N], + ) -> [&'a mut Self::StateElement; N]; } macro_rules! make_state_part_kinds { @@ -272,6 +297,7 @@ impl StatePartKind for StatePartKindMemories { type LayoutData = MemoryData>; type State = Box<[MemoryData]>; type BorrowedState<'a> = &'a mut [MemoryData]; + type StateElement = MemoryData; fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { layout_data .iter() @@ -297,19 +323,88 @@ impl StatePartKind for StatePartKindMemories { ) -> fmt::Result { write!(f, "{:#?}", &state.memories[index]) } + fn state_index<'a>( + state: &'a Self::State, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state[part_index.as_usize()] + } + fn state_index_mut<'a>( + state: &'a mut Self::State, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + &mut state[part_index.as_usize()] + } + fn state_index_fetch_and_clear_maybe_modified_flag( + _state: &mut Self::State, + _part_index: StatePartIndex, + ) -> bool { + true + } + fn borrowed_state_index<'a, 'b>( + state: &'a Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state[part_index.as_usize()] + } + fn borrowed_state_index_mut<'a, 'b>( + state: &'a mut Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + &mut state[part_index.as_usize()] + } + fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>( + state: &'a mut Self::BorrowedState<'b>, + part_indexes: [StatePartIndex; N], + ) -> [&'a mut Self::StateElement; N] { + state + .get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize)) + .expect("indexes are disjoint") + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)] +pub(crate) struct StateAndModified { + pub(crate) state: T, + pub(crate) modified: M, +} + +impl, M: Deref, E: fmt::Debug> fmt::Debug + for StateAndModified +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(self.state.iter().zip(self.modified.iter().copied()).map( + |(state, modified)| { + fmt::from_fn(move |f| { + state.fmt(f)?; + if modified { + f.write_str(" (modified)")?; + } + Ok(()) + }) + }, + )) + .finish() + } } impl StatePartKind for StatePartKindSmallSlots { const NAME: &'static str = "SmallSlots"; type DebugData = SlotDebugData; type LayoutData = (); - type State = Box<[SmallUInt]>; - type BorrowedState<'a> = &'a mut [SmallUInt]; + type State = StateAndModified, Box<[bool]>>; + type BorrowedState<'a> = StateAndModified<&'a mut [Self::StateElement], &'a mut [bool]>; + type StateElement = SmallUInt; fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { - vec![0; layout_data.len()].into_boxed_slice() + StateAndModified { + state: vec![0; layout_data.len()].into_boxed_slice(), + modified: vec![false; layout_data.len()].into_boxed_slice(), + } } fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { - state + let StateAndModified { state, modified } = state; + StateAndModified { state, modified } } fn part_debug_data( state_layout: &StateLayout, @@ -330,19 +425,69 @@ impl StatePartKind for StatePartKindSmallSlots { write!(f, "{value:#x} {}", value as SmallSInt)?; Ok(()) } + fn state_index<'a>( + state: &'a Self::State, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state.state[part_index.as_usize()] + } + fn state_index_mut<'a>( + state: &'a mut Self::State, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + state.modified[part_index.as_usize()] = true; + &mut state.state[part_index.as_usize()] + } + fn state_index_fetch_and_clear_maybe_modified_flag( + state: &mut Self::State, + part_index: StatePartIndex, + ) -> bool { + std::mem::replace(&mut state.modified[part_index.as_usize()], false) + } + fn borrowed_state_index<'a, 'b>( + state: &'a Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state.state[part_index.as_usize()] + } + fn borrowed_state_index_mut<'a, 'b>( + state: &'a mut Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + state.modified[part_index.as_usize()] = true; + &mut state.state[part_index.as_usize()] + } + fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>( + state: &'a mut Self::BorrowedState<'b>, + part_indexes: [StatePartIndex; N], + ) -> [&'a mut Self::StateElement; N] { + for part_index in part_indexes { + state.modified[part_index.as_usize()] = true; + } + state + .state + .get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize)) + .expect("indexes are disjoint") + } } impl StatePartKind for StatePartKindBigSlots { const NAME: &'static str = "BigSlots"; type DebugData = SlotDebugData; type LayoutData = (); - type State = Box<[BigInt]>; - type BorrowedState<'a> = &'a mut [BigInt]; + type State = StateAndModified, Box<[bool]>>; + type BorrowedState<'a> = StateAndModified<&'a mut [Self::StateElement], &'a mut [bool]>; + type StateElement = BigInt; fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { - layout_data.iter().map(|_| BigInt::default()).collect() + let state: Box<[_]> = layout_data.iter().map(|_| BigInt::default()).collect(); + StateAndModified { + modified: vec![false; state.len()].into_boxed_slice(), + state, + } } fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { - state + let StateAndModified { state, modified } = state; + StateAndModified { state, modified } } fn part_debug_data( state_layout: &StateLayout, @@ -361,19 +506,69 @@ impl StatePartKind for StatePartKindBigSlots { ) -> fmt::Result { write!(f, "{:#x}", state.big_slots[index]) } + fn state_index<'a>( + state: &'a Self::State, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state.state[part_index.as_usize()] + } + fn state_index_mut<'a>( + state: &'a mut Self::State, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + state.modified[part_index.as_usize()] = true; + &mut state.state[part_index.as_usize()] + } + fn state_index_fetch_and_clear_maybe_modified_flag( + state: &mut Self::State, + part_index: StatePartIndex, + ) -> bool { + std::mem::replace(&mut state.modified[part_index.as_usize()], false) + } + fn borrowed_state_index<'a, 'b>( + state: &'a Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state.state[part_index.as_usize()] + } + fn borrowed_state_index_mut<'a, 'b>( + state: &'a mut Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + state.modified[part_index.as_usize()] = true; + &mut state.state[part_index.as_usize()] + } + fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>( + state: &'a mut Self::BorrowedState<'b>, + part_indexes: [StatePartIndex; N], + ) -> [&'a mut Self::StateElement; N] { + for part_index in part_indexes { + state.modified[part_index.as_usize()] = true; + } + state + .state + .get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize)) + .expect("indexes are disjoint") + } } impl StatePartKind for StatePartKindSimOnlySlots { const NAME: &'static str = "SimOnlySlots"; type DebugData = SlotDebugData; type LayoutData = DynSimOnly; - type State = Box<[DynSimOnlyValue]>; - type BorrowedState<'a> = &'a mut [DynSimOnlyValue]; + type State = StateAndModified, Box<[bool]>>; + type BorrowedState<'a> = StateAndModified<&'a mut [Self::StateElement], &'a mut [bool]>; + type StateElement = DynSimOnlyValue; fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { - layout_data.iter().map(|ty| ty.default_value()).collect() + let state: Box<[_]> = layout_data.iter().map(|ty| ty.default_value()).collect(); + StateAndModified { + modified: vec![false; state.len()].into_boxed_slice(), + state, + } } fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { - state + let StateAndModified { state, modified } = state; + StateAndModified { state, modified } } fn part_debug_data( state_layout: &StateLayout, @@ -392,6 +587,50 @@ impl StatePartKind for StatePartKindSimOnlySlots { ) -> fmt::Result { write!(f, "{:?}", state.sim_only_slots[index]) } + fn state_index<'a>( + state: &'a Self::State, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state.state[part_index.as_usize()] + } + fn state_index_mut<'a>( + state: &'a mut Self::State, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + state.modified[part_index.as_usize()] = true; + &mut state.state[part_index.as_usize()] + } + fn state_index_fetch_and_clear_maybe_modified_flag( + state: &mut Self::State, + part_index: StatePartIndex, + ) -> bool { + std::mem::replace(&mut state.modified[part_index.as_usize()], false) + } + fn borrowed_state_index<'a, 'b>( + state: &'a Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a Self::StateElement { + &state.state[part_index.as_usize()] + } + fn borrowed_state_index_mut<'a, 'b>( + state: &'a mut Self::BorrowedState<'b>, + part_index: StatePartIndex, + ) -> &'a mut Self::StateElement { + state.modified[part_index.as_usize()] = true; + &mut state.state[part_index.as_usize()] + } + fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>( + state: &'a mut Self::BorrowedState<'b>, + part_indexes: [StatePartIndex; N], + ) -> [&'a mut Self::StateElement; N] { + for part_index in part_indexes { + state.modified[part_index.as_usize()] = true; + } + state + .state + .get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize)) + .expect("indexes are disjoint") + } } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/crates/fayalite/tests/sim/expected/array_rw.txt b/crates/fayalite/tests/sim/expected/array_rw.txt index 27b040d..2486eaa 100644 --- a/crates/fayalite/tests/sim/expected/array_rw.txt +++ b/crates/fayalite/tests/sim/expected/array_rw.txt @@ -424,8 +424,8 @@ Simulation { }, small_slots: StatePart { value: [ - 16, - 0, + 16 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -483,7 +483,7 @@ Simulation { 248, 252, 254, - 255, + 255 (modified), ], }, sim_only_slots: StatePart { @@ -1218,6 +1218,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<8>, }, + maybe_changed: true, state: 0xff, last_state: 0xff, }, @@ -1227,6 +1228,7 @@ Simulation { index: StatePartIndex(1), ty: UInt<8>, }, + maybe_changed: true, state: 0x7f, last_state: 0x7f, }, @@ -1236,6 +1238,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<8>, }, + maybe_changed: true, state: 0x3f, last_state: 0x3f, }, @@ -1245,6 +1248,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1254,6 +1258,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<8>, }, + maybe_changed: true, state: 0x0f, last_state: 0x0f, }, @@ -1263,6 +1268,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x07, last_state: 0x07, }, @@ -1272,6 +1278,7 @@ Simulation { index: StatePartIndex(6), ty: UInt<8>, }, + maybe_changed: true, state: 0x03, last_state: 0x03, }, @@ -1281,6 +1288,7 @@ Simulation { index: StatePartIndex(7), ty: UInt<8>, }, + maybe_changed: true, state: 0x01, last_state: 0x01, }, @@ -1290,6 +1298,7 @@ Simulation { index: StatePartIndex(8), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -1299,6 +1308,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x80, last_state: 0x80, }, @@ -1308,6 +1318,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<8>, }, + maybe_changed: true, state: 0xc0, last_state: 0xc0, }, @@ -1317,6 +1328,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<8>, }, + maybe_changed: true, state: 0xe0, last_state: 0xe0, }, @@ -1326,6 +1338,7 @@ Simulation { index: StatePartIndex(12), ty: UInt<8>, }, + maybe_changed: true, state: 0xf0, last_state: 0xf0, }, @@ -1335,6 +1348,7 @@ Simulation { index: StatePartIndex(13), ty: UInt<8>, }, + maybe_changed: true, state: 0xf8, last_state: 0xf8, }, @@ -1344,6 +1358,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0xfc, last_state: 0xfc, }, @@ -1353,6 +1368,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<8>, }, + maybe_changed: true, state: 0xfe, last_state: 0xfe, }, @@ -1362,6 +1378,7 @@ Simulation { index: StatePartIndex(16), ty: UInt<8>, }, + maybe_changed: true, state: 0xff, last_state: 0xff, }, @@ -1371,6 +1388,7 @@ Simulation { index: StatePartIndex(17), ty: UInt<8>, }, + maybe_changed: true, state: 0x7f, last_state: 0x7f, }, @@ -1380,6 +1398,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x3f, last_state: 0x3f, }, @@ -1389,6 +1408,7 @@ Simulation { index: StatePartIndex(19), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1398,6 +1418,7 @@ Simulation { index: StatePartIndex(20), ty: UInt<8>, }, + maybe_changed: true, state: 0x0f, last_state: 0x0f, }, @@ -1407,6 +1428,7 @@ Simulation { index: StatePartIndex(21), ty: UInt<8>, }, + maybe_changed: true, state: 0x07, last_state: 0x07, }, @@ -1416,6 +1438,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<8>, }, + maybe_changed: true, state: 0x03, last_state: 0x03, }, @@ -1425,6 +1448,7 @@ Simulation { index: StatePartIndex(23), ty: UInt<8>, }, + maybe_changed: true, state: 0x01, last_state: 0x01, }, @@ -1434,6 +1458,7 @@ Simulation { index: StatePartIndex(24), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -1443,6 +1468,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<8>, }, + maybe_changed: true, state: 0x80, last_state: 0x80, }, @@ -1452,6 +1478,7 @@ Simulation { index: StatePartIndex(26), ty: UInt<8>, }, + maybe_changed: true, state: 0xc0, last_state: 0xc0, }, @@ -1461,6 +1488,7 @@ Simulation { index: StatePartIndex(27), ty: UInt<8>, }, + maybe_changed: true, state: 0xe0, last_state: 0xe0, }, @@ -1470,6 +1498,7 @@ Simulation { index: StatePartIndex(28), ty: UInt<8>, }, + maybe_changed: true, state: 0xf0, last_state: 0xf0, }, @@ -1479,6 +1508,7 @@ Simulation { index: StatePartIndex(29), ty: UInt<8>, }, + maybe_changed: true, state: 0xf8, last_state: 0xf8, }, @@ -1488,6 +1518,7 @@ Simulation { index: StatePartIndex(30), ty: UInt<8>, }, + maybe_changed: true, state: 0xfc, last_state: 0xfc, }, @@ -1497,6 +1528,7 @@ Simulation { index: StatePartIndex(31), ty: UInt<8>, }, + maybe_changed: true, state: 0xfe, last_state: 0xe1, }, @@ -1506,6 +1538,7 @@ Simulation { index: StatePartIndex(32), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -1515,6 +1548,7 @@ Simulation { index: StatePartIndex(33), ty: UInt<8>, }, + maybe_changed: true, state: 0xff, last_state: 0xff, }, @@ -1524,6 +1558,7 @@ Simulation { index: StatePartIndex(34), ty: UInt<8>, }, + maybe_changed: true, state: 0x10, last_state: 0x0f, }, @@ -1533,6 +1568,7 @@ Simulation { index: StatePartIndex(35), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0xe1, }, @@ -1541,6 +1577,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1550,6 +1587,7 @@ Simulation { index: StatePartIndex(37), ty: UInt<8>, }, + maybe_changed: true, state: 0xff, last_state: 0xff, }, @@ -1559,6 +1597,7 @@ Simulation { index: StatePartIndex(38), ty: UInt<8>, }, + maybe_changed: true, state: 0x7f, last_state: 0x7f, }, @@ -1568,6 +1607,7 @@ Simulation { index: StatePartIndex(39), ty: UInt<8>, }, + maybe_changed: true, state: 0x3f, last_state: 0x3f, }, @@ -1577,6 +1617,7 @@ Simulation { index: StatePartIndex(40), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1586,6 +1627,7 @@ Simulation { index: StatePartIndex(41), ty: UInt<8>, }, + maybe_changed: true, state: 0x0f, last_state: 0x0f, }, @@ -1595,6 +1637,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x07, last_state: 0x07, }, @@ -1604,6 +1647,7 @@ Simulation { index: StatePartIndex(43), ty: UInt<8>, }, + maybe_changed: true, state: 0x03, last_state: 0x03, }, @@ -1613,6 +1657,7 @@ Simulation { index: StatePartIndex(44), ty: UInt<8>, }, + maybe_changed: true, state: 0x01, last_state: 0x01, }, @@ -1622,6 +1667,7 @@ Simulation { index: StatePartIndex(45), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -1631,6 +1677,7 @@ Simulation { index: StatePartIndex(46), ty: UInt<8>, }, + maybe_changed: true, state: 0x80, last_state: 0x80, }, @@ -1640,6 +1687,7 @@ Simulation { index: StatePartIndex(47), ty: UInt<8>, }, + maybe_changed: true, state: 0xc0, last_state: 0xc0, }, @@ -1649,6 +1697,7 @@ Simulation { index: StatePartIndex(48), ty: UInt<8>, }, + maybe_changed: true, state: 0xe0, last_state: 0xe0, }, @@ -1658,6 +1707,7 @@ Simulation { index: StatePartIndex(49), ty: UInt<8>, }, + maybe_changed: true, state: 0xf0, last_state: 0xf0, }, @@ -1667,6 +1717,7 @@ Simulation { index: StatePartIndex(50), ty: UInt<8>, }, + maybe_changed: true, state: 0xf8, last_state: 0xf8, }, @@ -1676,6 +1727,7 @@ Simulation { index: StatePartIndex(51), ty: UInt<8>, }, + maybe_changed: true, state: 0xfc, last_state: 0xfc, }, @@ -1685,6 +1737,7 @@ Simulation { index: StatePartIndex(52), ty: UInt<8>, }, + maybe_changed: true, state: 0xfe, last_state: 0xe1, }, diff --git a/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt index d470792..0df7f20 100644 --- a/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt +++ b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt @@ -86,8 +86,8 @@ Simulation { value: [ 1, 0, - 1, - 0, + 1 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -155,6 +155,7 @@ Simulation { kind: BigBool { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x1, last_state: 0x0, }, @@ -163,6 +164,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, diff --git a/crates/fayalite/tests/sim/expected/connect_const.txt b/crates/fayalite/tests/sim/expected/connect_const.txt index 56ea4ad..6cf4014 100644 --- a/crates/fayalite/tests/sim/expected/connect_const.txt +++ b/crates/fayalite/tests/sim/expected/connect_const.txt @@ -63,7 +63,7 @@ Simulation { big_slots: StatePart { value: [ 5, - 5, + 5 (modified), ], }, sim_only_slots: StatePart { @@ -124,6 +124,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<8>, }, + maybe_changed: true, state: 0x05, last_state: 0x05, }, diff --git a/crates/fayalite/tests/sim/expected/connect_const_reset.txt b/crates/fayalite/tests/sim/expected/connect_const_reset.txt index 6b5814a..a75ff8a 100644 --- a/crates/fayalite/tests/sim/expected/connect_const_reset.txt +++ b/crates/fayalite/tests/sim/expected/connect_const_reset.txt @@ -90,9 +90,9 @@ Simulation { value: [ 1, 1, - 1, - 1, - 1, + 1 (modified), + 1 (modified), + 1 (modified), ], }, sim_only_slots: StatePart { @@ -175,6 +175,7 @@ Simulation { kind: BigAsyncReset { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -183,6 +184,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, diff --git a/crates/fayalite/tests/sim/expected/counter_async.txt b/crates/fayalite/tests/sim/expected/counter_async.txt index 2bdd665..256e1b7 100644 --- a/crates/fayalite/tests/sim/expected/counter_async.txt +++ b/crates/fayalite/tests/sim/expected/counter_async.txt @@ -185,10 +185,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0, - 0, - 1, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -197,12 +197,12 @@ Simulation { 0, 3, 3, - 4, - 3, - 0, - 1, - 4, - 4, + 4 (modified), + 3 (modified), + 0 (modified), + 1 (modified), + 4 (modified), + 4 (modified), ], }, sim_only_slots: StatePart { @@ -332,6 +332,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x1, last_state: 0x0, }, @@ -340,6 +341,7 @@ Simulation { kind: BigAsyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -349,6 +351,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<4>, }, + maybe_changed: true, state: 0x3, last_state: 0x2, }, @@ -358,6 +361,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<4>, }, + maybe_changed: true, state: 0x3, last_state: 0x2, }, diff --git a/crates/fayalite/tests/sim/expected/counter_sync.txt b/crates/fayalite/tests/sim/expected/counter_sync.txt index 87c2098..1448f58 100644 --- a/crates/fayalite/tests/sim/expected/counter_sync.txt +++ b/crates/fayalite/tests/sim/expected/counter_sync.txt @@ -167,10 +167,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0, - 0, - 1, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -179,11 +179,11 @@ Simulation { 0, 3, 3, - 4, - 3, - 1, - 4, - 4, + 4 (modified), + 3 (modified), + 1 (modified), + 4 (modified), + 4 (modified), ], }, sim_only_slots: StatePart { @@ -313,6 +313,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x1, last_state: 0x0, }, @@ -321,6 +322,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -330,6 +332,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<4>, }, + maybe_changed: true, state: 0x3, last_state: 0x2, }, @@ -339,6 +342,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<4>, }, + maybe_changed: true, state: 0x3, last_state: 0x2, }, diff --git a/crates/fayalite/tests/sim/expected/duplicate_names.txt b/crates/fayalite/tests/sim/expected/duplicate_names.txt index 64bbbe6..394cfbb 100644 --- a/crates/fayalite/tests/sim/expected/duplicate_names.txt +++ b/crates/fayalite/tests/sim/expected/duplicate_names.txt @@ -81,9 +81,9 @@ Simulation { big_slots: StatePart { value: [ 5, - 5, - 6, + 5 (modified), 6, + 6 (modified), ], }, sim_only_slots: StatePart { @@ -137,6 +137,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<8>, }, + maybe_changed: true, state: 0x05, last_state: 0x05, }, @@ -146,6 +147,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<8>, }, + maybe_changed: true, state: 0x06, last_state: 0x06, }, diff --git a/crates/fayalite/tests/sim/expected/enums.txt b/crates/fayalite/tests/sim/expected/enums.txt index a3a52cb..2b00f05 100644 --- a/crates/fayalite/tests/sim/expected/enums.txt +++ b/crates/fayalite/tests/sim/expected/enums.txt @@ -1191,10 +1191,10 @@ Simulation { value: [ 0, 0, - 0, - 0, - 1, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), 2, ], }, @@ -1207,110 +1207,110 @@ Simulation { 15, 2, 15, + 0 (modified), 0, 0, + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), 0, 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 62, - 62, - 0, - 0, - 1, - 1, - 62, - 3, - 1, + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 62 (modified), + 62 (modified), + 0 (modified), + 0 (modified), 1, 1, + 62 (modified), + 3 (modified), + 1 (modified), + 1 (modified), + 1 (modified), 1, 1, -1, - 1, - 1, - 15, - 3, - 1, - 1, - 3, - -1, - 0, - 0, - 1, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 3, - 12, - 13, - 13, - 13, - 2, - 1, - 1, - -1, - 2, - 1, - 1, - -1, - 1, - 1, - 1, - 3, - -1, - 2, - 3, - 3, - 12, - 15, - 60, - 62, - 62, - 62, - 0, - 0, - 0, - 1, - 2, - 3, - 3, - 1, - 1, - 1, - 1, - 1, - 2, - 3, - 6, - 7, - 7, - 7, - 2, - 3, - 3, - 12, - 15, + 1 (modified), + 1 (modified), + 15 (modified), + 3 (modified), + 1 (modified), + 1 (modified), + 3 (modified), + -1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 2 (modified), + 3 (modified), + 12 (modified), + 13 (modified), + 13 (modified), + 13 (modified), + 2 (modified), + 1 (modified), + 1 (modified), + -1 (modified), + 2 (modified), + 1 (modified), + 1 (modified), + -1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 3 (modified), + -1 (modified), + 2 (modified), + 3 (modified), + 3 (modified), + 12 (modified), + 15 (modified), + 60 (modified), + 62 (modified), + 62 (modified), + 62 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 3 (modified), + 3 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 2 (modified), + 3 (modified), + 6 (modified), + 7 (modified), + 7 (modified), + 7 (modified), + 2 (modified), + 3 (modified), + 3 (modified), + 12 (modified), + 15 (modified), ], }, sim_only_slots: StatePart { @@ -1746,6 +1746,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x1, last_state: 0x0, }, @@ -1754,6 +1755,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1762,6 +1764,7 @@ Simulation { kind: BigBool { index: StatePartIndex(2), }, + maybe_changed: false, state: 0x1, last_state: 0x1, }, @@ -1771,6 +1774,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<2>, }, + maybe_changed: false, state: 0x2, last_state: 0x2, }, @@ -1780,6 +1784,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<4>, }, + maybe_changed: false, state: 0xf, last_state: 0xf, }, @@ -1789,6 +1794,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1798,6 +1804,7 @@ Simulation { index: StatePartIndex(6), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -1810,6 +1817,7 @@ Simulation { HdlSome(Bundle {0: UInt<1>, 1: Bool}), }, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1819,6 +1827,7 @@ Simulation { index: StatePartIndex(8), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1827,6 +1836,7 @@ Simulation { kind: BigBool { index: StatePartIndex(9), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1839,6 +1849,7 @@ Simulation { HdlSome(Bundle {0: UInt<1>, 1: Bool}), }, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1848,6 +1859,7 @@ Simulation { index: StatePartIndex(16), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1856,6 +1868,7 @@ Simulation { kind: BigBool { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1869,6 +1882,7 @@ Simulation { C(Bundle {a: Array, 2>, b: SInt<2>}), }, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1878,6 +1892,7 @@ Simulation { index: StatePartIndex(27), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1886,6 +1901,7 @@ Simulation { kind: BigBool { index: StatePartIndex(28), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1895,6 +1911,7 @@ Simulation { index: StatePartIndex(34), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1904,6 +1921,7 @@ Simulation { index: StatePartIndex(35), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1913,6 +1931,7 @@ Simulation { index: StatePartIndex(36), ty: SInt<2>, }, + maybe_changed: true, state: 0x3, last_state: 0x3, }, diff --git a/crates/fayalite/tests/sim/expected/extern_module.txt b/crates/fayalite/tests/sim/expected/extern_module.txt index f49106f..48a3af5 100644 --- a/crates/fayalite/tests/sim/expected/extern_module.txt +++ b/crates/fayalite/tests/sim/expected/extern_module.txt @@ -221,6 +221,7 @@ Simulation { kind: BigBool { index: StatePartIndex(0), }, + maybe_changed: false, state: 0x1, last_state: 0x1, }, @@ -229,6 +230,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x1, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/extern_module2.txt b/crates/fayalite/tests/sim/expected/extern_module2.txt index 365830f..d488666 100644 --- a/crates/fayalite/tests/sim/expected/extern_module2.txt +++ b/crates/fayalite/tests/sim/expected/extern_module2.txt @@ -57,7 +57,7 @@ Simulation { big_slots: StatePart { value: [ 0, - 1, + 1 (modified), 101, ], }, @@ -280,6 +280,7 @@ Simulation { kind: BigBool { index: StatePartIndex(0), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -288,6 +289,7 @@ Simulation { kind: BigClock { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -297,6 +299,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<8>, }, + maybe_changed: false, state: 0x65, last_state: 0x65, }, diff --git a/crates/fayalite/tests/sim/expected/last_connect.txt b/crates/fayalite/tests/sim/expected/last_connect.txt index 6a43497..297d395 100644 --- a/crates/fayalite/tests/sim/expected/last_connect.txt +++ b/crates/fayalite/tests/sim/expected/last_connect.txt @@ -418,39 +418,39 @@ Simulation { }, big_slots: StatePart { value: [ - 31, + 31 (modified), 1, 1, 1, 1, - 31, - 15, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 7, - 7, + 31 (modified), + 15 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 7 (modified), + 7 (modified), 3, - 0, - 0, - 3, - 1, - 3, - 1, - 6, - 7, - 7, - 7, - 4, - 0, - 1, - 2, + 0 (modified), + 0 (modified), 3, + 1 (modified), + 3 (modified), + 1 (modified), + 6 (modified), + 7 (modified), + 7 (modified), + 7 (modified), + 4 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 3 (modified), ], }, sim_only_slots: StatePart { @@ -614,6 +614,7 @@ Simulation { HdlSome(Array), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -622,6 +623,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -630,6 +632,7 @@ Simulation { kind: BigBool { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -638,6 +641,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -646,6 +650,7 @@ Simulation { kind: BigBool { index: StatePartIndex(4), }, + maybe_changed: true, state: 0x1, last_state: 0x0, }, @@ -658,6 +663,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -667,6 +673,7 @@ Simulation { index: StatePartIndex(17), ty: UInt<8>, }, + maybe_changed: true, state: 0x03, last_state: 0x02, }, @@ -676,6 +683,7 @@ Simulation { index: StatePartIndex(20), ty: UInt<8>, }, + maybe_changed: true, state: 0x03, last_state: 0x02, }, diff --git a/crates/fayalite/tests/sim/expected/many_memories.txt b/crates/fayalite/tests/sim/expected/many_memories.txt index c521d72..84d9162 100644 --- a/crates/fayalite/tests/sim/expected/many_memories.txt +++ b/crates/fayalite/tests/sim/expected/many_memories.txt @@ -2910,102 +2910,102 @@ Simulation { }, small_slots: StatePart { value: [ - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 1, - 15, - 1, - 0, - 0, - 0, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 15 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -3091,8 +3091,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), 15, 1, 0, @@ -3102,8 +3102,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), 15, 1, 0, @@ -3113,8 +3113,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), 15, 1, 0, @@ -3124,8 +3124,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), 15, 1, 0, @@ -3135,8 +3135,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), 15, 1, 0, @@ -3146,8 +3146,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), 15, 1, 0, @@ -3157,8 +3157,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), 15, 1, 0, @@ -3168,8 +3168,8 @@ Simulation { 0, 0, 1, - 0, - 1, + 0 (modified), + 1 (modified), ], }, sim_only_slots: StatePart { @@ -5545,6 +5545,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5553,6 +5554,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5561,6 +5563,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5569,6 +5572,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5578,6 +5582,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5586,6 +5591,7 @@ Simulation { kind: BigBool { index: StatePartIndex(5), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5594,6 +5600,7 @@ Simulation { kind: BigClock { index: StatePartIndex(6), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5602,6 +5609,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5611,6 +5619,7 @@ Simulation { index: StatePartIndex(8), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5619,6 +5628,7 @@ Simulation { kind: BigBool { index: StatePartIndex(9), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5627,6 +5637,7 @@ Simulation { kind: BigClock { index: StatePartIndex(10), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5635,6 +5646,7 @@ Simulation { kind: BigBool { index: StatePartIndex(11), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5644,6 +5656,7 @@ Simulation { index: StatePartIndex(12), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5652,6 +5665,7 @@ Simulation { kind: BigBool { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5660,6 +5674,7 @@ Simulation { kind: BigClock { index: StatePartIndex(14), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5668,6 +5683,7 @@ Simulation { kind: BigBool { index: StatePartIndex(15), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5677,6 +5693,7 @@ Simulation { index: StatePartIndex(16), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5685,6 +5702,7 @@ Simulation { kind: BigBool { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5693,6 +5711,7 @@ Simulation { kind: BigClock { index: StatePartIndex(18), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5701,6 +5720,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5710,6 +5730,7 @@ Simulation { index: StatePartIndex(20), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5718,6 +5739,7 @@ Simulation { kind: BigBool { index: StatePartIndex(21), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5726,6 +5748,7 @@ Simulation { kind: BigClock { index: StatePartIndex(22), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5734,6 +5757,7 @@ Simulation { kind: BigBool { index: StatePartIndex(23), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5743,6 +5767,7 @@ Simulation { index: StatePartIndex(24), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5751,6 +5776,7 @@ Simulation { kind: BigBool { index: StatePartIndex(25), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5759,6 +5785,7 @@ Simulation { kind: BigClock { index: StatePartIndex(26), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5767,6 +5794,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5776,6 +5804,7 @@ Simulation { index: StatePartIndex(28), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -5784,6 +5813,7 @@ Simulation { kind: BigBool { index: StatePartIndex(29), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5792,6 +5822,7 @@ Simulation { kind: BigClock { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5800,6 +5831,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5809,6 +5841,7 @@ Simulation { index: StatePartIndex(32), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5817,6 +5850,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5825,6 +5859,7 @@ Simulation { kind: BigClock { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5833,6 +5868,7 @@ Simulation { kind: BigBool { index: StatePartIndex(35), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5841,6 +5877,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5850,6 +5887,7 @@ Simulation { index: StatePartIndex(37), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5858,6 +5896,7 @@ Simulation { kind: BigBool { index: StatePartIndex(38), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5866,6 +5905,7 @@ Simulation { kind: BigClock { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5874,6 +5914,7 @@ Simulation { kind: BigBool { index: StatePartIndex(40), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5882,6 +5923,7 @@ Simulation { kind: BigBool { index: StatePartIndex(41), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5891,6 +5933,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5899,6 +5942,7 @@ Simulation { kind: BigBool { index: StatePartIndex(43), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5907,6 +5951,7 @@ Simulation { kind: BigClock { index: StatePartIndex(44), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5915,6 +5960,7 @@ Simulation { kind: BigBool { index: StatePartIndex(45), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5923,6 +5969,7 @@ Simulation { kind: BigBool { index: StatePartIndex(46), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5932,6 +5979,7 @@ Simulation { index: StatePartIndex(47), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5940,6 +5988,7 @@ Simulation { kind: BigBool { index: StatePartIndex(48), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5948,6 +5997,7 @@ Simulation { kind: BigClock { index: StatePartIndex(49), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5956,6 +6006,7 @@ Simulation { kind: BigBool { index: StatePartIndex(50), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5964,6 +6015,7 @@ Simulation { kind: BigBool { index: StatePartIndex(51), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -5973,6 +6025,7 @@ Simulation { index: StatePartIndex(52), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5981,6 +6034,7 @@ Simulation { kind: BigBool { index: StatePartIndex(53), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -5989,6 +6043,7 @@ Simulation { kind: BigClock { index: StatePartIndex(54), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -5997,6 +6052,7 @@ Simulation { kind: BigBool { index: StatePartIndex(55), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6005,6 +6061,7 @@ Simulation { kind: BigBool { index: StatePartIndex(56), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6014,6 +6071,7 @@ Simulation { index: StatePartIndex(57), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6022,6 +6080,7 @@ Simulation { kind: BigBool { index: StatePartIndex(58), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6030,6 +6089,7 @@ Simulation { kind: BigClock { index: StatePartIndex(59), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6038,6 +6098,7 @@ Simulation { kind: BigBool { index: StatePartIndex(60), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6046,6 +6107,7 @@ Simulation { kind: BigBool { index: StatePartIndex(61), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6055,6 +6117,7 @@ Simulation { index: StatePartIndex(62), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6063,6 +6126,7 @@ Simulation { kind: BigBool { index: StatePartIndex(63), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6071,6 +6135,7 @@ Simulation { kind: BigClock { index: StatePartIndex(64), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6079,6 +6144,7 @@ Simulation { kind: BigBool { index: StatePartIndex(65), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6087,6 +6153,7 @@ Simulation { kind: BigBool { index: StatePartIndex(66), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6096,6 +6163,7 @@ Simulation { index: StatePartIndex(67), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6104,6 +6172,7 @@ Simulation { kind: BigBool { index: StatePartIndex(68), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6112,6 +6181,7 @@ Simulation { kind: BigClock { index: StatePartIndex(69), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6120,6 +6190,7 @@ Simulation { kind: BigBool { index: StatePartIndex(70), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6128,6 +6199,7 @@ Simulation { kind: BigBool { index: StatePartIndex(71), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6137,6 +6209,7 @@ Simulation { index: StatePartIndex(72), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6145,6 +6218,7 @@ Simulation { kind: BigBool { index: StatePartIndex(73), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6153,6 +6227,7 @@ Simulation { kind: BigClock { index: StatePartIndex(74), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6161,6 +6236,7 @@ Simulation { kind: BigBool { index: StatePartIndex(75), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6170,6 +6246,7 @@ Simulation { index: StatePartIndex(76), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6178,6 +6255,7 @@ Simulation { kind: BigBool { index: StatePartIndex(77), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6186,6 +6264,7 @@ Simulation { kind: BigClock { index: StatePartIndex(78), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6194,6 +6273,7 @@ Simulation { kind: BigBool { index: StatePartIndex(79), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6202,6 +6282,7 @@ Simulation { kind: BigBool { index: StatePartIndex(80), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6211,6 +6292,7 @@ Simulation { index: StatePartIndex(83), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6219,6 +6301,7 @@ Simulation { kind: BigBool { index: StatePartIndex(84), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6227,6 +6310,7 @@ Simulation { kind: BigClock { index: StatePartIndex(85), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6235,6 +6319,7 @@ Simulation { kind: BigBool { index: StatePartIndex(86), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6244,6 +6329,7 @@ Simulation { index: StatePartIndex(87), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6252,6 +6338,7 @@ Simulation { kind: BigBool { index: StatePartIndex(88), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6260,6 +6347,7 @@ Simulation { kind: BigClock { index: StatePartIndex(89), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6268,6 +6356,7 @@ Simulation { kind: BigBool { index: StatePartIndex(90), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6276,6 +6365,7 @@ Simulation { kind: BigBool { index: StatePartIndex(91), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6285,6 +6375,7 @@ Simulation { index: StatePartIndex(94), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6293,6 +6384,7 @@ Simulation { kind: BigBool { index: StatePartIndex(95), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6301,6 +6393,7 @@ Simulation { kind: BigClock { index: StatePartIndex(96), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6309,6 +6402,7 @@ Simulation { kind: BigBool { index: StatePartIndex(97), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6318,6 +6412,7 @@ Simulation { index: StatePartIndex(98), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6326,6 +6421,7 @@ Simulation { kind: BigBool { index: StatePartIndex(99), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6334,6 +6430,7 @@ Simulation { kind: BigClock { index: StatePartIndex(100), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6342,6 +6439,7 @@ Simulation { kind: BigBool { index: StatePartIndex(101), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6350,6 +6448,7 @@ Simulation { kind: BigBool { index: StatePartIndex(102), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6359,6 +6458,7 @@ Simulation { index: StatePartIndex(105), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6367,6 +6467,7 @@ Simulation { kind: BigBool { index: StatePartIndex(106), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6375,6 +6476,7 @@ Simulation { kind: BigClock { index: StatePartIndex(107), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6383,6 +6485,7 @@ Simulation { kind: BigBool { index: StatePartIndex(108), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6392,6 +6495,7 @@ Simulation { index: StatePartIndex(109), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6400,6 +6504,7 @@ Simulation { kind: BigBool { index: StatePartIndex(110), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6408,6 +6513,7 @@ Simulation { kind: BigClock { index: StatePartIndex(111), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6416,6 +6522,7 @@ Simulation { kind: BigBool { index: StatePartIndex(112), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6424,6 +6531,7 @@ Simulation { kind: BigBool { index: StatePartIndex(113), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6433,6 +6541,7 @@ Simulation { index: StatePartIndex(116), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6441,6 +6550,7 @@ Simulation { kind: BigBool { index: StatePartIndex(117), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6449,6 +6559,7 @@ Simulation { kind: BigClock { index: StatePartIndex(118), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6457,6 +6568,7 @@ Simulation { kind: BigBool { index: StatePartIndex(119), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6466,6 +6578,7 @@ Simulation { index: StatePartIndex(120), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6474,6 +6587,7 @@ Simulation { kind: BigBool { index: StatePartIndex(121), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6482,6 +6596,7 @@ Simulation { kind: BigClock { index: StatePartIndex(122), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6490,6 +6605,7 @@ Simulation { kind: BigBool { index: StatePartIndex(123), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6498,6 +6614,7 @@ Simulation { kind: BigBool { index: StatePartIndex(124), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6507,6 +6624,7 @@ Simulation { index: StatePartIndex(127), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6515,6 +6633,7 @@ Simulation { kind: BigBool { index: StatePartIndex(128), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6523,6 +6642,7 @@ Simulation { kind: BigClock { index: StatePartIndex(129), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6531,6 +6651,7 @@ Simulation { kind: BigBool { index: StatePartIndex(130), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6540,6 +6661,7 @@ Simulation { index: StatePartIndex(131), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6548,6 +6670,7 @@ Simulation { kind: BigBool { index: StatePartIndex(132), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6556,6 +6679,7 @@ Simulation { kind: BigClock { index: StatePartIndex(133), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6564,6 +6688,7 @@ Simulation { kind: BigBool { index: StatePartIndex(134), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6572,6 +6697,7 @@ Simulation { kind: BigBool { index: StatePartIndex(135), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6581,6 +6707,7 @@ Simulation { index: StatePartIndex(138), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6589,6 +6716,7 @@ Simulation { kind: BigBool { index: StatePartIndex(139), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6597,6 +6725,7 @@ Simulation { kind: BigClock { index: StatePartIndex(140), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6605,6 +6734,7 @@ Simulation { kind: BigBool { index: StatePartIndex(141), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6614,6 +6744,7 @@ Simulation { index: StatePartIndex(142), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6622,6 +6753,7 @@ Simulation { kind: BigBool { index: StatePartIndex(143), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6630,6 +6762,7 @@ Simulation { kind: BigClock { index: StatePartIndex(144), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6638,6 +6771,7 @@ Simulation { kind: BigBool { index: StatePartIndex(145), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6646,6 +6780,7 @@ Simulation { kind: BigBool { index: StatePartIndex(146), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6655,6 +6790,7 @@ Simulation { index: StatePartIndex(149), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xf, }, @@ -6663,6 +6799,7 @@ Simulation { kind: BigBool { index: StatePartIndex(150), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -6671,6 +6808,7 @@ Simulation { kind: BigClock { index: StatePartIndex(151), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6679,6 +6817,7 @@ Simulation { kind: BigBool { index: StatePartIndex(152), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6688,6 +6827,7 @@ Simulation { index: StatePartIndex(153), ty: UInt<4>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6696,6 +6836,7 @@ Simulation { kind: BigBool { index: StatePartIndex(154), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6704,6 +6845,7 @@ Simulation { kind: BigClock { index: StatePartIndex(155), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -6712,6 +6854,7 @@ Simulation { kind: BigBool { index: StatePartIndex(156), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -6720,6 +6863,7 @@ Simulation { kind: BigBool { index: StatePartIndex(157), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, diff --git a/crates/fayalite/tests/sim/expected/memories.txt b/crates/fayalite/tests/sim/expected/memories.txt index 0358bb3..db5a2f3 100644 --- a/crates/fayalite/tests/sim/expected/memories.txt +++ b/crates/fayalite/tests/sim/expected/memories.txt @@ -522,18 +522,18 @@ Simulation { }, small_slots: StatePart { value: [ - 1, - 0, - 0, - 1, - 2, - 1, - 0, - 0, - 0, - 2, - 2, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -562,10 +562,10 @@ Simulation { -32, 1, 1, - 208, - -32, - 1, - 1, + 208 (modified), + -32 (modified), + 1 (modified), + 1 (modified), ], }, sim_only_slots: StatePart { @@ -1168,6 +1168,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<4>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1176,6 +1177,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1184,6 +1186,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1193,6 +1196,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<8>, }, + maybe_changed: true, state: 0xb0, last_state: 0xb0, }, @@ -1202,6 +1206,7 @@ Simulation { index: StatePartIndex(4), ty: SInt<8>, }, + maybe_changed: true, state: 0xc0, last_state: 0xc0, }, @@ -1211,6 +1216,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<4>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1219,6 +1225,7 @@ Simulation { kind: BigBool { index: StatePartIndex(6), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1227,6 +1234,7 @@ Simulation { kind: BigClock { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1236,6 +1244,7 @@ Simulation { index: StatePartIndex(8), ty: UInt<8>, }, + maybe_changed: true, state: 0xd0, last_state: 0xd0, }, @@ -1245,6 +1254,7 @@ Simulation { index: StatePartIndex(9), ty: SInt<8>, }, + maybe_changed: true, state: 0xe0, last_state: 0xe0, }, @@ -1253,6 +1263,7 @@ Simulation { kind: BigBool { index: StatePartIndex(10), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1261,6 +1272,7 @@ Simulation { kind: BigBool { index: StatePartIndex(11), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1270,6 +1282,7 @@ Simulation { index: StatePartIndex(12), ty: UInt<4>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1278,6 +1291,7 @@ Simulation { kind: BigBool { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1286,6 +1300,7 @@ Simulation { kind: BigClock { index: StatePartIndex(14), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1295,6 +1310,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<8>, }, + maybe_changed: true, state: 0xb0, last_state: 0xb0, }, @@ -1304,6 +1320,7 @@ Simulation { index: StatePartIndex(16), ty: SInt<8>, }, + maybe_changed: true, state: 0xc0, last_state: 0xc0, }, @@ -1313,6 +1330,7 @@ Simulation { index: StatePartIndex(17), ty: UInt<4>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1321,6 +1339,7 @@ Simulation { kind: BigBool { index: StatePartIndex(18), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1329,6 +1348,7 @@ Simulation { kind: BigClock { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1338,6 +1358,7 @@ Simulation { index: StatePartIndex(20), ty: UInt<8>, }, + maybe_changed: true, state: 0xd0, last_state: 0xd0, }, @@ -1347,6 +1368,7 @@ Simulation { index: StatePartIndex(21), ty: SInt<8>, }, + maybe_changed: true, state: 0xe0, last_state: 0xe0, }, @@ -1355,6 +1377,7 @@ Simulation { kind: BigBool { index: StatePartIndex(22), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1363,6 +1386,7 @@ Simulation { kind: BigBool { index: StatePartIndex(23), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, diff --git a/crates/fayalite/tests/sim/expected/memories2.txt b/crates/fayalite/tests/sim/expected/memories2.txt index b4041ba..5a82b91 100644 --- a/crates/fayalite/tests/sim/expected/memories2.txt +++ b/crates/fayalite/tests/sim/expected/memories2.txt @@ -545,15 +545,15 @@ Simulation { value: [ 0, 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -568,32 +568,32 @@ Simulation { 0, 0, 0, + 0 (modified), 0, + 0 (modified), 0, + 0 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 1, - 1, + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), ], }, sim_only_slots: StatePart { @@ -943,6 +943,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<3>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -951,6 +952,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -959,6 +961,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -968,6 +971,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -976,6 +980,7 @@ Simulation { kind: BigBool { index: StatePartIndex(4), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -985,6 +990,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<2>, }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -993,6 +999,7 @@ Simulation { kind: BigBool { index: StatePartIndex(6), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1002,6 +1009,7 @@ Simulation { index: StatePartIndex(7), ty: UInt<3>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1010,6 +1018,7 @@ Simulation { kind: BigBool { index: StatePartIndex(8), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1018,6 +1027,7 @@ Simulation { kind: BigClock { index: StatePartIndex(9), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1030,6 +1040,7 @@ Simulation { HdlSome(Bool), }, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1038,6 +1049,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1046,6 +1058,7 @@ Simulation { kind: BigBool { index: StatePartIndex(11), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1058,6 +1071,7 @@ Simulation { HdlSome(Bool), }, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1066,6 +1080,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1074,6 +1089,7 @@ Simulation { kind: BigBool { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/memories3.txt b/crates/fayalite/tests/sim/expected/memories3.txt index 2213912..7522430 100644 --- a/crates/fayalite/tests/sim/expected/memories3.txt +++ b/crates/fayalite/tests/sim/expected/memories3.txt @@ -1356,20 +1356,20 @@ Simulation { }, small_slots: StatePart { value: [ - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -1415,6 +1415,22 @@ Simulation { 0, 0, 0, + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), 0, 0, 0, @@ -1434,54 +1450,38 @@ Simulation { 0, 0, 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -2391,6 +2391,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<3>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2399,6 +2400,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2407,6 +2409,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -2416,6 +2419,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2425,6 +2429,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2434,6 +2439,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2443,6 +2449,7 @@ Simulation { index: StatePartIndex(6), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2452,6 +2459,7 @@ Simulation { index: StatePartIndex(7), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2461,6 +2469,7 @@ Simulation { index: StatePartIndex(8), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2470,6 +2479,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2479,6 +2489,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2488,6 +2499,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<3>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2496,6 +2508,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2504,6 +2517,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -2513,6 +2527,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2522,6 +2537,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2531,6 +2547,7 @@ Simulation { index: StatePartIndex(16), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2540,6 +2557,7 @@ Simulation { index: StatePartIndex(17), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2549,6 +2567,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2558,6 +2577,7 @@ Simulation { index: StatePartIndex(19), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2567,6 +2587,7 @@ Simulation { index: StatePartIndex(20), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2576,6 +2597,7 @@ Simulation { index: StatePartIndex(21), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2584,6 +2606,7 @@ Simulation { kind: BigBool { index: StatePartIndex(22), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2592,6 +2615,7 @@ Simulation { kind: BigBool { index: StatePartIndex(23), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2600,6 +2624,7 @@ Simulation { kind: BigBool { index: StatePartIndex(24), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2608,6 +2633,7 @@ Simulation { kind: BigBool { index: StatePartIndex(25), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2616,6 +2642,7 @@ Simulation { kind: BigBool { index: StatePartIndex(26), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2624,6 +2651,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2632,6 +2660,7 @@ Simulation { kind: BigBool { index: StatePartIndex(28), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2640,6 +2669,7 @@ Simulation { kind: BigBool { index: StatePartIndex(29), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2649,6 +2679,7 @@ Simulation { index: StatePartIndex(30), ty: UInt<3>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2657,6 +2688,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2665,6 +2697,7 @@ Simulation { kind: BigClock { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -2674,6 +2707,7 @@ Simulation { index: StatePartIndex(33), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2683,6 +2717,7 @@ Simulation { index: StatePartIndex(34), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2692,6 +2727,7 @@ Simulation { index: StatePartIndex(35), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2701,6 +2737,7 @@ Simulation { index: StatePartIndex(36), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2710,6 +2747,7 @@ Simulation { index: StatePartIndex(37), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2719,6 +2757,7 @@ Simulation { index: StatePartIndex(38), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2728,6 +2767,7 @@ Simulation { index: StatePartIndex(39), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2737,6 +2777,7 @@ Simulation { index: StatePartIndex(40), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2746,6 +2787,7 @@ Simulation { index: StatePartIndex(57), ty: UInt<3>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2754,6 +2796,7 @@ Simulation { kind: BigBool { index: StatePartIndex(58), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2762,6 +2805,7 @@ Simulation { kind: BigClock { index: StatePartIndex(59), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -2771,6 +2815,7 @@ Simulation { index: StatePartIndex(60), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2780,6 +2825,7 @@ Simulation { index: StatePartIndex(61), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2789,6 +2835,7 @@ Simulation { index: StatePartIndex(62), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2798,6 +2845,7 @@ Simulation { index: StatePartIndex(63), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2807,6 +2855,7 @@ Simulation { index: StatePartIndex(64), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2816,6 +2865,7 @@ Simulation { index: StatePartIndex(65), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2825,6 +2875,7 @@ Simulation { index: StatePartIndex(66), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2834,6 +2885,7 @@ Simulation { index: StatePartIndex(67), ty: UInt<8>, }, + maybe_changed: true, state: 0x00, last_state: 0x00, }, @@ -2842,6 +2894,7 @@ Simulation { kind: BigBool { index: StatePartIndex(68), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2850,6 +2903,7 @@ Simulation { kind: BigBool { index: StatePartIndex(69), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2858,6 +2912,7 @@ Simulation { kind: BigBool { index: StatePartIndex(70), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2866,6 +2921,7 @@ Simulation { kind: BigBool { index: StatePartIndex(71), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2874,6 +2930,7 @@ Simulation { kind: BigBool { index: StatePartIndex(72), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2882,6 +2939,7 @@ Simulation { kind: BigBool { index: StatePartIndex(73), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2890,6 +2948,7 @@ Simulation { kind: BigBool { index: StatePartIndex(74), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2898,6 +2957,7 @@ Simulation { kind: BigBool { index: StatePartIndex(75), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/mod1.txt b/crates/fayalite/tests/sim/expected/mod1.txt index 3f7a55e..7f89a66 100644 --- a/crates/fayalite/tests/sim/expected/mod1.txt +++ b/crates/fayalite/tests/sim/expected/mod1.txt @@ -207,11 +207,11 @@ Simulation { -2, -2, 15, - -2, - 14, - 5, - 1, - 15, + -2 (modified), + 14 (modified), + 5 (modified), + 1 (modified), + 15 (modified), ], }, sim_only_slots: StatePart { @@ -445,6 +445,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<4>, }, + maybe_changed: true, state: 0xa, last_state: 0x3, }, @@ -454,6 +455,7 @@ Simulation { index: StatePartIndex(1), ty: SInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x3, }, @@ -463,6 +465,7 @@ Simulation { index: StatePartIndex(2), ty: SInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -472,6 +475,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xe, }, @@ -481,6 +485,7 @@ Simulation { index: StatePartIndex(8), ty: UInt<4>, }, + maybe_changed: true, state: 0xa, last_state: 0x3, }, @@ -490,6 +495,7 @@ Simulation { index: StatePartIndex(9), ty: SInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x3, }, @@ -499,6 +505,7 @@ Simulation { index: StatePartIndex(10), ty: SInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -508,6 +515,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xe, }, @@ -517,6 +525,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<4>, }, + maybe_changed: true, state: 0xa, last_state: 0x3, }, @@ -526,6 +535,7 @@ Simulation { index: StatePartIndex(5), ty: SInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x3, }, @@ -535,6 +545,7 @@ Simulation { index: StatePartIndex(6), ty: SInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -544,6 +555,7 @@ Simulation { index: StatePartIndex(7), ty: UInt<4>, }, + maybe_changed: true, state: 0xf, last_state: 0xe, }, diff --git a/crates/fayalite/tests/sim/expected/phantom_const.txt b/crates/fayalite/tests/sim/expected/phantom_const.txt index 94072ac..864a4f7 100644 --- a/crates/fayalite/tests/sim/expected/phantom_const.txt +++ b/crates/fayalite/tests/sim/expected/phantom_const.txt @@ -185,11 +185,11 @@ Simulation { }, small_slots: StatePart { value: [ - 1, - 0, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -197,11 +197,11 @@ Simulation { 0, 0, 0, - 0, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -373,6 +373,7 @@ Simulation { ["a","b"], ), }, + maybe_changed: true, state: PhantomConst, last_state: PhantomConst, }, @@ -383,6 +384,7 @@ Simulation { ["a","b"], ), }, + maybe_changed: true, state: PhantomConst, last_state: PhantomConst, }, @@ -392,6 +394,7 @@ Simulation { index: StatePartIndex(0), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -400,6 +403,7 @@ Simulation { kind: BigBool { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -408,6 +412,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -418,6 +423,7 @@ Simulation { "mem_element", ), }, + maybe_changed: true, state: PhantomConst, last_state: PhantomConst, }, diff --git a/crates/fayalite/tests/sim/expected/queue_1_false_false.txt b/crates/fayalite/tests/sim/expected/queue_1_false_false.txt index 570c08d..1ac0403 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_false_false.txt @@ -1098,35 +1098,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 51, + 51 (modified), 0, - 51, + 51 (modified), 25, - 51, + 51 (modified), 0, - 51, + 51 (modified), 25, 1, 0, @@ -1138,56 +1138,56 @@ Simulation { 0, 25, 1, + 25 (modified), + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 25, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 25, - 0, - 0, - 1, - 1, - 25, - 1, - 50, - 51, - 51, - 51, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 25 (modified), + 1 (modified), + 50 (modified), + 51 (modified), + 51 (modified), + 51 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1722,6 +1722,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1730,6 +1731,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1742,6 +1744,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1751,6 +1754,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x19, last_state: 0x19, }, @@ -1759,6 +1763,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1771,6 +1776,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1780,6 +1786,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x19, last_state: 0x19, }, @@ -1788,6 +1795,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1797,6 +1805,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1806,6 +1815,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1814,6 +1824,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1822,6 +1833,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1831,6 +1843,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x19, last_state: 0x19, }, @@ -1840,6 +1853,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1848,6 +1862,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1856,6 +1871,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1865,6 +1881,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x19, last_state: 0x19, }, @@ -1873,6 +1890,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1882,6 +1900,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1891,6 +1910,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1899,6 +1919,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1907,6 +1928,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1915,6 +1937,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1923,6 +1946,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1931,6 +1955,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1939,6 +1964,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1947,6 +1973,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1955,6 +1982,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1964,6 +1992,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x19, last_state: 0x19, }, @@ -1973,6 +2002,7 @@ Simulation { index: StatePartIndex(66), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/queue_1_false_true.txt b/crates/fayalite/tests/sim/expected/queue_1_false_true.txt index 5bff275..5b56068 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_false_true.txt @@ -1079,35 +1079,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 63, + 63 (modified), 0, - 63, + 63 (modified), 31, - 63, + 63 (modified), 0, - 63, + 63 (modified), 31, 1, 0, @@ -1119,54 +1119,54 @@ Simulation { 0, 31, 1, + 31 (modified), + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 31, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 31, - 0, - 0, - 1, - 1, - 31, - 1, - 62, - 63, - 63, - 63, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 31 (modified), + 1 (modified), + 62 (modified), + 63 (modified), + 63 (modified), + 63 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1701,6 +1701,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1709,6 +1710,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1721,6 +1723,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1730,6 +1733,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1738,6 +1742,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1750,6 +1755,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1759,6 +1765,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1767,6 +1774,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1776,6 +1784,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1785,6 +1794,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1793,6 +1803,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1801,6 +1812,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1810,6 +1822,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1819,6 +1832,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1827,6 +1841,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1835,6 +1850,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1844,6 +1860,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1852,6 +1869,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1861,6 +1879,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1870,6 +1889,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1878,6 +1898,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1886,6 +1907,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1894,6 +1916,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1902,6 +1925,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1910,6 +1934,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1918,6 +1943,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1926,6 +1952,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1934,6 +1961,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1943,6 +1971,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1952,6 +1981,7 @@ Simulation { index: StatePartIndex(64), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/queue_1_true_false.txt b/crates/fayalite/tests/sim/expected/queue_1_true_false.txt index d9771dc..6076237 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_true_false.txt @@ -1108,35 +1108,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 63, + 63 (modified), 0, - 63, + 63 (modified), 31, - 63, + 63 (modified), 0, - 63, + 63 (modified), 31, 1, 0, @@ -1148,56 +1148,56 @@ Simulation { 0, 31, 1, + 31 (modified), + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 31, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 31, - 0, - 0, - 1, - 1, - 31, - 1, - 62, - 63, - 63, - 63, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 31 (modified), + 1 (modified), + 62 (modified), + 63 (modified), + 63 (modified), + 63 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1732,6 +1732,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1740,6 +1741,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1752,6 +1754,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1761,6 +1764,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1769,6 +1773,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1781,6 +1786,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1790,6 +1796,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1798,6 +1805,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1807,6 +1815,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1816,6 +1825,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1824,6 +1834,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1832,6 +1843,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1841,6 +1853,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1850,6 +1863,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1858,6 +1872,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1866,6 +1881,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1875,6 +1891,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1883,6 +1900,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1892,6 +1910,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1901,6 +1920,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1909,6 +1929,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1917,6 +1938,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1925,6 +1947,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1933,6 +1956,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1941,6 +1965,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1949,6 +1974,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1957,6 +1983,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1965,6 +1992,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1974,6 +2002,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x1f, last_state: 0x1f, }, @@ -1983,6 +2012,7 @@ Simulation { index: StatePartIndex(66), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/queue_1_true_true.txt b/crates/fayalite/tests/sim/expected/queue_1_true_true.txt index 0e16d2d..8fe32ad 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_true_true.txt @@ -1089,35 +1089,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 71, + 71 (modified), 0, - 71, + 71 (modified), 35, - 71, + 71 (modified), 0, - 71, + 71 (modified), 35, 1, 0, @@ -1129,54 +1129,54 @@ Simulation { 0, 35, 1, + 35 (modified), + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 35, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 35, - 0, - 0, - 1, - 1, - 35, - 1, - 70, - 71, - 71, - 71, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 35 (modified), + 1 (modified), + 70 (modified), + 71 (modified), + 71 (modified), + 71 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1711,6 +1711,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1719,6 +1720,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1731,6 +1733,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1740,6 +1743,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1748,6 +1752,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1760,6 +1765,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1769,6 +1775,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1777,6 +1784,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1786,6 +1794,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1795,6 +1804,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1803,6 +1813,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1811,6 +1822,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1820,6 +1832,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1829,6 +1842,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1837,6 +1851,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1845,6 +1860,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1854,6 +1870,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1862,6 +1879,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1871,6 +1889,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1880,6 +1899,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1888,6 +1908,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1896,6 +1917,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1904,6 +1926,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1912,6 +1935,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1920,6 +1944,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1928,6 +1953,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1936,6 +1962,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1944,6 +1971,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1953,6 +1981,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1962,6 +1991,7 @@ Simulation { index: StatePartIndex(64), ty: UInt<0>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/queue_2_false_false.txt b/crates/fayalite/tests/sim/expected/queue_2_false_false.txt index 23b0a7b..5a5c47d 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_false_false.txt @@ -1114,35 +1114,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 1, - 1, - 0, - 0, - 1, - 0, - 1, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 71, + 71 (modified), 1, - 71, + 71 (modified), 35, - 71, + 71 (modified), 0, - 71, + 71 (modified), 35, 1, 1, @@ -1154,58 +1154,58 @@ Simulation { 0, 35, 1, + 35 (modified), + 1 (modified), + 0, + 1 (modified), + 0 (modified), + 1, + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1, + 0, + 0, + 0, + 0 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1 (modified), 35, + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 35 (modified), + 1 (modified), + 70 (modified), + 71 (modified), + 71 (modified), + 71 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 2 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 0 (modified), 1, - 0, - 1, - 0, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 35, - 0, - 1, - 1, - 1, - 35, - 1, - 70, - 71, - 71, - 71, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 2, - 0, - 2, - 2, - 0, - 1, - 3, - 1, - 1, + 3 (modified), + 1 (modified), + 1 (modified), ], }, sim_only_slots: StatePart { @@ -1740,6 +1740,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1748,6 +1749,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1760,6 +1762,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1769,6 +1772,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1777,6 +1781,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1789,6 +1794,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1798,6 +1804,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1806,6 +1813,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1815,6 +1823,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1824,6 +1833,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1832,6 +1842,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1840,6 +1851,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1849,6 +1861,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1858,6 +1871,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1866,6 +1880,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1874,6 +1889,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1883,6 +1899,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1891,6 +1908,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1900,6 +1918,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1909,6 +1928,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1917,6 +1937,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1925,6 +1946,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1933,6 +1955,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1941,6 +1964,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1949,6 +1973,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1957,6 +1982,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1965,6 +1991,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1973,6 +2000,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1982,6 +2010,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x23, last_state: 0x23, }, @@ -1991,6 +2020,7 @@ Simulation { index: StatePartIndex(68), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, diff --git a/crates/fayalite/tests/sim/expected/queue_2_false_true.txt b/crates/fayalite/tests/sim/expected/queue_2_false_true.txt index a057fa7..2d9ea3f 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_false_true.txt @@ -1095,35 +1095,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 77, + 77 (modified), 1, - 77, + 77 (modified), 38, - 77, + 77 (modified), 0, - 77, + 77 (modified), 38, 1, 0, @@ -1135,56 +1135,56 @@ Simulation { 0, 38, 1, + 38 (modified), + 1 (modified), + 1, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1, + 0, + 0, + 0, + 0 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1 (modified), 38, + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 38 (modified), + 1 (modified), + 76 (modified), + 77 (modified), + 77 (modified), + 77 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 2 (modified), + 2 (modified), + 0 (modified), 1, - 1, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 38, - 0, - 1, - 1, - 1, - 38, - 1, - 76, - 77, - 77, - 77, - 1, - 1, - 1, - 0, - 0, - 2, - 0, - 0, - 1, - 1, - 2, - 2, - 0, - 1, - 1, - 1, - 1, + 1 (modified), + 1 (modified), + 1 (modified), ], }, sim_only_slots: StatePart { @@ -1719,6 +1719,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1727,6 +1728,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1739,6 +1741,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1748,6 +1751,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x26, last_state: 0x26, }, @@ -1756,6 +1760,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1768,6 +1773,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1777,6 +1783,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x26, last_state: 0x26, }, @@ -1785,6 +1792,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1794,6 +1802,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1803,6 +1812,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1811,6 +1821,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1819,6 +1830,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1828,6 +1840,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x26, last_state: 0x26, }, @@ -1837,6 +1850,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1845,6 +1859,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1853,6 +1868,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1862,6 +1878,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x26, last_state: 0x26, }, @@ -1870,6 +1887,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1879,6 +1897,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1888,6 +1907,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1896,6 +1916,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1904,6 +1925,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1912,6 +1934,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1920,6 +1943,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1928,6 +1952,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1936,6 +1961,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1944,6 +1970,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1952,6 +1979,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1961,6 +1989,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x26, last_state: 0x26, }, @@ -1970,6 +1999,7 @@ Simulation { index: StatePartIndex(66), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, diff --git a/crates/fayalite/tests/sim/expected/queue_2_true_false.txt b/crates/fayalite/tests/sim/expected/queue_2_true_false.txt index 1f6d8ec..3d16da2 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_true_false.txt @@ -1124,35 +1124,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 79, + 79 (modified), 0, - 79, + 79 (modified), 39, - 77, + 77 (modified), 0, - 77, + 77 (modified), 38, 2, 0, @@ -1164,58 +1164,58 @@ Simulation { 0, 39, 1, + 39 (modified), + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 39, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 39, - 0, - 0, - 1, - 1, - 38, - 1, - 76, - 77, - 77, - 77, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 2, - 2, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 38 (modified), + 1 (modified), + 76 (modified), + 77 (modified), + 77 (modified), + 77 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 2 (modified), + 2 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1750,6 +1750,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1758,6 +1759,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1770,6 +1772,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1779,6 +1782,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x27, last_state: 0x27, }, @@ -1787,6 +1791,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1799,6 +1804,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1808,6 +1814,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x26, last_state: 0x26, }, @@ -1816,6 +1823,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1825,6 +1833,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1834,6 +1843,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1842,6 +1852,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1850,6 +1861,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1859,6 +1871,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x26, last_state: 0x26, }, @@ -1868,6 +1881,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1876,6 +1890,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1884,6 +1899,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1893,6 +1909,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x27, last_state: 0x27, }, @@ -1901,6 +1918,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1910,6 +1928,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1919,6 +1938,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1927,6 +1947,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1935,6 +1956,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1943,6 +1965,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1951,6 +1974,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1959,6 +1983,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1967,6 +1992,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1975,6 +2001,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1983,6 +2010,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1992,6 +2020,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x27, last_state: 0x27, }, @@ -2001,6 +2030,7 @@ Simulation { index: StatePartIndex(68), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/queue_2_true_true.txt b/crates/fayalite/tests/sim/expected/queue_2_true_true.txt index 25b08a1..041e62d 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_true_true.txt @@ -1105,35 +1105,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 1, - 1, - 0, - 0, - 0, - 1, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 85, + 85 (modified), 0, - 85, + 85 (modified), 42, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 2, 1, @@ -1145,56 +1145,56 @@ Simulation { 0, 42, 1, + 42 (modified), + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 42, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 42, - 0, - 0, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 0, - 1, - 1, - 0, - 0, - 2, - 0, - 1, - 2, - 0, - 2, - 2, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1729,6 +1729,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1737,6 +1738,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1749,6 +1751,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1758,6 +1761,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2a, last_state: 0x2a, }, @@ -1766,6 +1770,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1778,6 +1783,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1787,6 +1793,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1795,6 +1802,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1804,6 +1812,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1813,6 +1822,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1821,6 +1831,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1829,6 +1840,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1838,6 +1850,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1847,6 +1860,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1855,6 +1869,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1863,6 +1878,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1872,6 +1888,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2a, last_state: 0x2a, }, @@ -1880,6 +1897,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1889,6 +1907,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1898,6 +1917,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<1>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1906,6 +1926,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1914,6 +1935,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1922,6 +1944,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1930,6 +1953,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1938,6 +1962,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1946,6 +1971,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1954,6 +1980,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1962,6 +1989,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1971,6 +1999,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2a, last_state: 0x2a, }, @@ -1980,6 +2009,7 @@ Simulation { index: StatePartIndex(66), ty: UInt<1>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/queue_3_false_false.txt b/crates/fayalite/tests/sim/expected/queue_3_false_false.txt index 6f65006..f9c68cc 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_false_false.txt @@ -1142,35 +1142,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 0, - 1, - 0, - 0, - 1, - 2, - 1, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 81, + 81 (modified), 1, - 81, + 81 (modified), 40, - 79, + 79 (modified), 0, - 79, + 79 (modified), 39, 2, 0, @@ -1182,59 +1182,59 @@ Simulation { 0, 40, 1, + 40 (modified), + 1 (modified), + 2, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1, + 0, + 0, + 0, + 0 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1 (modified), 40, - 1, - 2, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 40, - 0, - 1, - 1, - 1, - 39, - 1, - 78, - 79, - 79, - 79, - 0, - 0, - 1, - 2, - 1, - 0, - 0, - 3, - 3, - 0, - 1, - 1, - 3, - 3, - 0, - 5, - 5, - 1, - 2, - 2, + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 39 (modified), + 1 (modified), + 78 (modified), + 79 (modified), + 79 (modified), + 79 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 3 (modified), + 3 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 3 (modified), + 3 (modified), + 0 (modified), + 5 (modified), + 5 (modified), + 1 (modified), + 2 (modified), + 2 (modified), ], }, sim_only_slots: StatePart { @@ -1759,6 +1759,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1767,6 +1768,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1779,6 +1781,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1788,6 +1791,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x28, last_state: 0x28, }, @@ -1796,6 +1800,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1808,6 +1813,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1817,6 +1823,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x27, last_state: 0x27, }, @@ -1825,6 +1832,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1834,6 +1842,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1843,6 +1852,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1851,6 +1861,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1859,6 +1870,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1868,6 +1880,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x27, last_state: 0x27, }, @@ -1877,6 +1890,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1885,6 +1899,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1893,6 +1908,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1902,6 +1918,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x28, last_state: 0x28, }, @@ -1910,6 +1927,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1919,6 +1937,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1928,6 +1947,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1936,6 +1956,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1944,6 +1965,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1952,6 +1974,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1960,6 +1983,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1968,6 +1992,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1976,6 +2001,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1984,6 +2010,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1992,6 +2019,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2001,6 +2029,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x28, last_state: 0x28, }, diff --git a/crates/fayalite/tests/sim/expected/queue_3_false_true.txt b/crates/fayalite/tests/sim/expected/queue_3_false_true.txt index 4cffcd6..9b0a7ea 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_false_true.txt @@ -1123,35 +1123,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 2, - 1, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 85, + 85 (modified), 1, - 85, + 85 (modified), 42, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 2, 2, @@ -1163,57 +1163,57 @@ Simulation { 0, 42, 1, + 42 (modified), + 1 (modified), + 1, + 2 (modified), + 0 (modified), + 2, + 2 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1, + 0, + 0, + 0, + 0 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1 (modified), 42, - 1, - 1, - 2, - 0, - 2, - 2, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 42, - 0, - 1, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 1, - 2, - 0, - 0, - 0, - 2, - 2, - 1, - 3, - 3, - 3, - 3, - 1, - 4, - 2, - 2, - 7, - 3, + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 1 (modified), + 2 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 1 (modified), + 3 (modified), + 3 (modified), + 3 (modified), + 3 (modified), + 1 (modified), + 4 (modified), + 2 (modified), + 2 (modified), + 7 (modified), + 3 (modified), ], }, sim_only_slots: StatePart { @@ -1738,6 +1738,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1746,6 +1747,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1758,6 +1760,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1767,6 +1770,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2a, last_state: 0x2a, }, @@ -1775,6 +1779,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1787,6 +1792,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1796,6 +1802,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1804,6 +1811,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1813,6 +1821,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1822,6 +1831,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1830,6 +1840,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1838,6 +1849,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1847,6 +1859,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1856,6 +1869,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1864,6 +1878,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1872,6 +1887,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1881,6 +1897,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2a, last_state: 0x2a, }, @@ -1889,6 +1906,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1898,6 +1916,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1907,6 +1926,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1915,6 +1935,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1923,6 +1944,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1931,6 +1953,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1939,6 +1962,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1947,6 +1971,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1955,6 +1980,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1963,6 +1989,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1971,6 +1998,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1980,6 +2008,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2a, last_state: 0x2a, }, diff --git a/crates/fayalite/tests/sim/expected/queue_3_true_false.txt b/crates/fayalite/tests/sim/expected/queue_3_true_false.txt index 03d3aba..1b486d6 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_true_false.txt @@ -1152,35 +1152,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 2, - 1, - 0, - 0, - 0, - 2, - 1, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 87, + 87 (modified), 0, - 87, + 87 (modified), 43, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 3, 2, @@ -1192,59 +1192,59 @@ Simulation { 0, 43, 1, + 43 (modified), + 1 (modified), + 2, + 2 (modified), + 0 (modified), + 2, + 2 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 43, - 1, - 2, - 2, - 0, - 2, - 2, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 43, - 0, - 0, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 0, - 0, - 0, - 2, - 1, - 0, - 0, - 3, - 3, - 1, - 3, - 3, - 3, - 3, - 0, - 5, - 3, - 3, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 3 (modified), + 3 (modified), + 1 (modified), + 3 (modified), + 3 (modified), + 3 (modified), + 3 (modified), + 0 (modified), + 5 (modified), + 3 (modified), + 3 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1769,6 +1769,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1777,6 +1778,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1789,6 +1791,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1798,6 +1801,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1806,6 +1810,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1818,6 +1823,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1827,6 +1833,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1835,6 +1842,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1844,6 +1852,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x3, last_state: 0x3, }, @@ -1853,6 +1862,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1861,6 +1871,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1869,6 +1880,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1878,6 +1890,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1887,6 +1900,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1895,6 +1909,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1903,6 +1918,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1912,6 +1928,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1920,6 +1937,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1929,6 +1947,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1938,6 +1957,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1946,6 +1966,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1954,6 +1975,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1962,6 +1984,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1970,6 +1993,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1978,6 +2002,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1986,6 +2011,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1994,6 +2020,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -2002,6 +2029,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -2011,6 +2039,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, diff --git a/crates/fayalite/tests/sim/expected/queue_3_true_true.txt b/crates/fayalite/tests/sim/expected/queue_3_true_true.txt index a663e23..730e7e5 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_true_true.txt @@ -1133,35 +1133,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 2, - 1, - 0, - 0, - 0, - 2, - 1, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 2 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 87, + 87 (modified), 0, - 87, + 87 (modified), 43, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 3, 2, @@ -1173,57 +1173,57 @@ Simulation { 0, 43, 1, + 43 (modified), + 1 (modified), + 2, + 2 (modified), + 0 (modified), + 2, + 2 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 43, - 1, - 2, - 2, - 0, - 2, - 2, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 43, - 0, - 0, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 0, - 2, - 1, - 0, - 0, - 3, - 3, - 1, - 3, - 3, - 3, - 3, - 0, - 5, - 3, - 3, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 0 (modified), + 2 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 3 (modified), + 3 (modified), + 1 (modified), + 3 (modified), + 3 (modified), + 3 (modified), + 3 (modified), + 0 (modified), + 5 (modified), + 3 (modified), + 3 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1748,6 +1748,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1756,6 +1757,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1768,6 +1770,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1777,6 +1780,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1785,6 +1789,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1797,6 +1802,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1806,6 +1812,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1814,6 +1821,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1823,6 +1831,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<2>, }, + maybe_changed: true, state: 0x3, last_state: 0x3, }, @@ -1832,6 +1841,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1840,6 +1850,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1848,6 +1859,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1857,6 +1869,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1866,6 +1879,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1874,6 +1888,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1882,6 +1897,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1891,6 +1907,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1899,6 +1916,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1908,6 +1926,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1917,6 +1936,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x2, last_state: 0x2, }, @@ -1925,6 +1945,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1933,6 +1954,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1941,6 +1963,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1949,6 +1972,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1957,6 +1981,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1965,6 +1990,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1973,6 +1999,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1981,6 +2008,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1990,6 +2018,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, diff --git a/crates/fayalite/tests/sim/expected/queue_4_false_false.txt b/crates/fayalite/tests/sim/expected/queue_4_false_false.txt index 445d9d0..e549ced 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_false_false.txt @@ -1122,35 +1122,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 1, - 1, - 0, - 0, - 1, - 0, - 3, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 3 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 87, + 87 (modified), 1, - 87, + 87 (modified), 43, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 3, 1, @@ -1162,58 +1162,58 @@ Simulation { 0, 43, 1, + 43 (modified), + 1 (modified), + 0, + 1 (modified), + 0 (modified), + 1, + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1, + 0, + 0, + 0, + 0 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1 (modified), 43, - 1, - 0, - 1, - 0, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 43, - 0, - 1, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 0, - 0, - 1, - 3, - 0, - 0, - 0, - 1, - 1, - 0, - 2, - 2, - 4, - 4, - 0, - 3, - 7, - 3, + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 3 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 4 (modified), + 4 (modified), + 0 (modified), 3, + 7 (modified), + 3 (modified), + 3 (modified), ], }, sim_only_slots: StatePart { @@ -1748,6 +1748,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1756,6 +1757,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1768,6 +1770,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1777,6 +1780,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1785,6 +1789,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1797,6 +1802,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1806,6 +1812,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1814,6 +1821,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1823,6 +1831,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<3>, }, + maybe_changed: true, state: 0x3, last_state: 0x3, }, @@ -1832,6 +1841,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1840,6 +1850,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1848,6 +1859,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1857,6 +1869,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1866,6 +1879,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1874,6 +1888,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1882,6 +1897,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1891,6 +1907,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1899,6 +1916,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1908,6 +1926,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1917,6 +1936,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1925,6 +1945,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1933,6 +1954,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1941,6 +1963,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1949,6 +1972,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1957,6 +1981,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1965,6 +1990,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1973,6 +1999,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1981,6 +2008,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1990,6 +2018,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1999,6 +2028,7 @@ Simulation { index: StatePartIndex(68), ty: UInt<2>, }, + maybe_changed: true, state: 0x3, last_state: 0x3, }, diff --git a/crates/fayalite/tests/sim/expected/queue_4_false_true.txt b/crates/fayalite/tests/sim/expected/queue_4_false_true.txt index 5e7ada2..9f1d05b 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_false_true.txt @@ -1103,35 +1103,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 1, - 1, - 0, - 0, - 1, - 0, - 3, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 3 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 87, + 87 (modified), 1, - 87, + 87 (modified), 43, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 3, 1, @@ -1143,56 +1143,56 @@ Simulation { 0, 43, 1, + 43 (modified), + 1 (modified), + 0, + 1 (modified), + 0 (modified), + 1, + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1, + 0, + 0, + 0, + 0 (modified), + 0, + 0 (modified), + 0 (modified), + 0, + 0 (modified), + 1 (modified), 43, - 1, - 0, - 1, - 0, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 43, - 0, - 1, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 1, - 3, - 0, - 0, - 0, - 1, - 1, - 0, - 2, - 2, - 4, - 4, - 0, - 3, - 7, - 3, + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 1 (modified), + 3 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 4 (modified), + 4 (modified), + 0 (modified), 3, + 7 (modified), + 3 (modified), + 3 (modified), ], }, sim_only_slots: StatePart { @@ -1727,6 +1727,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1735,6 +1736,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1747,6 +1749,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1756,6 +1759,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1764,6 +1768,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1776,6 +1781,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1785,6 +1791,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1793,6 +1800,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1802,6 +1810,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<3>, }, + maybe_changed: true, state: 0x3, last_state: 0x3, }, @@ -1811,6 +1820,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1819,6 +1829,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1827,6 +1838,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1836,6 +1848,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1845,6 +1858,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1853,6 +1867,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1861,6 +1876,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1870,6 +1886,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1878,6 +1895,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1887,6 +1905,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1896,6 +1915,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1904,6 +1924,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1912,6 +1933,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1920,6 +1942,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1928,6 +1951,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1936,6 +1960,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1944,6 +1969,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1952,6 +1978,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1960,6 +1987,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1969,6 +1997,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2b, last_state: 0x2b, }, @@ -1978,6 +2007,7 @@ Simulation { index: StatePartIndex(66), ty: UInt<2>, }, + maybe_changed: true, state: 0x3, last_state: 0x3, }, diff --git a/crates/fayalite/tests/sim/expected/queue_4_true_false.txt b/crates/fayalite/tests/sim/expected/queue_4_true_false.txt index 2701c1d..b37a9cd 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_true_false.txt @@ -1132,35 +1132,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 1, - 1, - 0, - 0, - 0, - 1, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 89, + 89 (modified), 0, - 89, + 89 (modified), 44, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 4, 1, @@ -1172,58 +1172,58 @@ Simulation { 0, 44, 1, + 44 (modified), + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 44, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 44, - 0, - 0, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 2, - 2, - 0, - 2, - 2, - 4, - 4, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 3 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 4 (modified), + 4 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1758,6 +1758,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1766,6 +1767,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1778,6 +1780,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1787,6 +1790,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2c, last_state: 0x2c, }, @@ -1795,6 +1799,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1807,6 +1812,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1816,6 +1822,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1824,6 +1831,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1833,6 +1841,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<3>, }, + maybe_changed: true, state: 0x4, last_state: 0x4, }, @@ -1842,6 +1851,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1850,6 +1860,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1858,6 +1869,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1867,6 +1879,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1876,6 +1889,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1884,6 +1898,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1892,6 +1907,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1901,6 +1917,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2c, last_state: 0x2c, }, @@ -1909,6 +1926,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1918,6 +1936,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1927,6 +1946,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1935,6 +1955,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1943,6 +1964,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1951,6 +1973,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1959,6 +1982,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1967,6 +1991,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1975,6 +2000,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1983,6 +2009,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1991,6 +2018,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -2000,6 +2028,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2c, last_state: 0x2c, }, @@ -2009,6 +2038,7 @@ Simulation { index: StatePartIndex(68), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/queue_4_true_true.txt b/crates/fayalite/tests/sim/expected/queue_4_true_true.txt index a52069d..051b203 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_true_true.txt @@ -1113,35 +1113,35 @@ Simulation { value: [ 1, 1, - 1, - 0, - 0, - 1, - 1, - 1, - 0, - 0, - 0, - 1, - 0, - 1, - 1, - 0, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ 0, 0, - 89, + 89 (modified), 0, - 89, + 89 (modified), 44, - 83, + 83 (modified), 0, - 83, + 83 (modified), 41, 4, 1, @@ -1153,56 +1153,56 @@ Simulation { 0, 44, 1, + 44 (modified), + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 1, + 1 (modified), + 1, + 1 (modified), + 0 (modified), + 0, + 0, + 0, + 0, + 1, + 1 (modified), + 0, + 0 (modified), + 0 (modified), + 1, + 1 (modified), + 1 (modified), 44, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 44, - 0, - 0, - 1, - 1, - 41, - 1, - 82, - 83, - 83, - 83, - 0, - 3, - 0, - 0, - 0, - 2, - 2, - 0, - 2, - 2, - 4, - 4, - 0, - 0, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 41 (modified), + 1 (modified), + 82 (modified), + 83 (modified), + 83 (modified), + 83 (modified), + 0 (modified), + 3 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 0 (modified), + 2 (modified), + 2 (modified), + 4 (modified), + 4 (modified), + 0 (modified), 0, + 0 (modified), + 0 (modified), + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1737,6 +1737,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1745,6 +1746,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1757,6 +1759,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1766,6 +1769,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: true, state: 0x2c, last_state: 0x2c, }, @@ -1774,6 +1778,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1786,6 +1791,7 @@ Simulation { HdlSome(UInt<8>), }, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1795,6 +1801,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1803,6 +1810,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1812,6 +1820,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<3>, }, + maybe_changed: true, state: 0x4, last_state: 0x4, }, @@ -1821,6 +1830,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1829,6 +1839,7 @@ Simulation { kind: BigBool { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1837,6 +1848,7 @@ Simulation { kind: BigClock { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1846,6 +1858,7 @@ Simulation { index: StatePartIndex(14), ty: UInt<8>, }, + maybe_changed: true, state: 0x29, last_state: 0x29, }, @@ -1855,6 +1868,7 @@ Simulation { index: StatePartIndex(15), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1863,6 +1877,7 @@ Simulation { kind: BigBool { index: StatePartIndex(16), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1871,6 +1886,7 @@ Simulation { kind: BigClock { index: StatePartIndex(17), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -1880,6 +1896,7 @@ Simulation { index: StatePartIndex(18), ty: UInt<8>, }, + maybe_changed: true, state: 0x2c, last_state: 0x2c, }, @@ -1888,6 +1905,7 @@ Simulation { kind: BigBool { index: StatePartIndex(19), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1897,6 +1915,7 @@ Simulation { index: StatePartIndex(22), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1906,6 +1925,7 @@ Simulation { index: StatePartIndex(25), ty: UInt<2>, }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1914,6 +1934,7 @@ Simulation { kind: BigBool { index: StatePartIndex(27), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1922,6 +1943,7 @@ Simulation { kind: BigBool { index: StatePartIndex(30), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1930,6 +1952,7 @@ Simulation { kind: BigBool { index: StatePartIndex(31), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1938,6 +1961,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1946,6 +1970,7 @@ Simulation { kind: BigBool { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1954,6 +1979,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1962,6 +1988,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1970,6 +1997,7 @@ Simulation { kind: BigBool { index: StatePartIndex(39), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1979,6 +2007,7 @@ Simulation { index: StatePartIndex(42), ty: UInt<8>, }, + maybe_changed: true, state: 0x2c, last_state: 0x2c, }, @@ -1988,6 +2017,7 @@ Simulation { index: StatePartIndex(66), ty: UInt<2>, }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/ripple_counter.txt b/crates/fayalite/tests/sim/expected/ripple_counter.txt index 1fb5fee..91bbffd 100644 --- a/crates/fayalite/tests/sim/expected/ripple_counter.txt +++ b/crates/fayalite/tests/sim/expected/ripple_counter.txt @@ -641,15 +641,15 @@ Simulation { }, small_slots: StatePart { value: [ - 0, - 0, - 1, - 1, - 0, - 0, - 1, - 0, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -662,56 +662,56 @@ Simulation { 0, 0, 0, + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 0, + 1 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), 0, 0, + 0 (modified), + 0, + 0 (modified), + 0, + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), 0, 0, + 0 (modified), + 0, + 0 (modified), + 0, + 1 (modified), + 0 (modified), + 0 (modified), + 0 (modified), + 1 (modified), 0, 0, + 0 (modified), 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, + 0 (modified), ], }, sim_only_slots: StatePart { @@ -1284,6 +1284,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: false, state: 0x1, last_state: 0x1, }, @@ -1293,6 +1294,7 @@ Simulation { index: StatePartIndex(1), ty: UInt<6>, }, + maybe_changed: false, state: 0x00, last_state: 0x00, }, @@ -1301,6 +1303,7 @@ Simulation { kind: BigBool { index: StatePartIndex(2), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1309,6 +1312,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1317,6 +1321,7 @@ Simulation { kind: BigBool { index: StatePartIndex(4), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1325,6 +1330,7 @@ Simulation { kind: BigBool { index: StatePartIndex(5), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1333,6 +1339,7 @@ Simulation { kind: BigBool { index: StatePartIndex(6), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1341,6 +1348,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1349,6 +1357,7 @@ Simulation { kind: BigBool { index: StatePartIndex(24), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1357,6 +1366,7 @@ Simulation { kind: BigClock { index: StatePartIndex(33), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1365,6 +1375,7 @@ Simulation { kind: BigBool { index: StatePartIndex(34), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1373,6 +1384,7 @@ Simulation { kind: BigClock { index: StatePartIndex(31), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1381,6 +1393,7 @@ Simulation { kind: BigBool { index: StatePartIndex(32), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1389,6 +1402,7 @@ Simulation { kind: BigBool { index: StatePartIndex(36), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1397,6 +1411,7 @@ Simulation { kind: BigClock { index: StatePartIndex(44), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1405,6 +1420,7 @@ Simulation { kind: BigBool { index: StatePartIndex(45), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1413,6 +1429,7 @@ Simulation { kind: BigClock { index: StatePartIndex(42), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1421,6 +1438,7 @@ Simulation { kind: BigBool { index: StatePartIndex(43), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1429,6 +1447,7 @@ Simulation { kind: BigBool { index: StatePartIndex(47), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1437,6 +1456,7 @@ Simulation { kind: BigClock { index: StatePartIndex(55), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1445,6 +1465,7 @@ Simulation { kind: BigBool { index: StatePartIndex(56), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1453,6 +1474,7 @@ Simulation { kind: BigClock { index: StatePartIndex(53), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -1461,6 +1483,7 @@ Simulation { kind: BigBool { index: StatePartIndex(54), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/shift_register.txt b/crates/fayalite/tests/sim/expected/shift_register.txt index 2e1b176..cc9d95a 100644 --- a/crates/fayalite/tests/sim/expected/shift_register.txt +++ b/crates/fayalite/tests/sim/expected/shift_register.txt @@ -259,10 +259,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0, - 0, - 1, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -272,14 +272,14 @@ Simulation { 0, 0, 0, + 0 (modified), + 0 (modified), 0, + 0 (modified), 0, + 0 (modified), 0, - 0, - 0, - 0, - 0, - 0, + 0 (modified), ], }, sim_only_slots: StatePart { @@ -458,6 +458,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x1, last_state: 0x0, }, @@ -466,6 +467,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -474,6 +476,7 @@ Simulation { kind: BigBool { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -482,6 +485,7 @@ Simulation { kind: BigBool { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -490,6 +494,7 @@ Simulation { kind: BigBool { index: StatePartIndex(4), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -498,6 +503,7 @@ Simulation { kind: BigBool { index: StatePartIndex(7), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -506,6 +512,7 @@ Simulation { kind: BigBool { index: StatePartIndex(9), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -514,6 +521,7 @@ Simulation { kind: BigBool { index: StatePartIndex(11), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, diff --git a/crates/fayalite/tests/sim/expected/sim_fork_join.txt b/crates/fayalite/tests/sim/expected/sim_fork_join.txt index df9c092..c66e77e 100644 --- a/crates/fayalite/tests/sim/expected/sim_fork_join.txt +++ b/crates/fayalite/tests/sim/expected/sim_fork_join.txt @@ -68,12 +68,12 @@ Simulation { }, big_slots: StatePart { value: [ + 0 (modified), 0, 0, - 0, - 49, - 50, - 50, + 49 (modified), + 50 (modified), + 50 (modified), ], }, sim_only_slots: StatePart { @@ -356,6 +356,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -364,6 +365,7 @@ Simulation { kind: BigClock { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -372,6 +374,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -381,6 +384,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<8>, }, + maybe_changed: false, state: 0x31, last_state: 0x31, }, @@ -390,6 +394,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<8>, }, + maybe_changed: false, state: 0x32, last_state: 0x32, }, @@ -399,6 +404,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: false, state: 0x32, last_state: 0x32, }, diff --git a/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt b/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt index 917dd5d..ae88960 100644 --- a/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt +++ b/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt @@ -68,12 +68,12 @@ Simulation { }, big_slots: StatePart { value: [ + 0 (modified), 0, 0, - 0, - 49, - 50, - 50, + 49 (modified), + 50 (modified), + 50 (modified), ], }, sim_only_slots: StatePart { @@ -356,6 +356,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -364,6 +365,7 @@ Simulation { kind: BigClock { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -372,6 +374,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -381,6 +384,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<8>, }, + maybe_changed: false, state: 0x31, last_state: 0x31, }, @@ -390,6 +394,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<8>, }, + maybe_changed: false, state: 0x32, last_state: 0x32, }, @@ -399,6 +404,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: false, state: 0x32, last_state: 0x32, }, diff --git a/crates/fayalite/tests/sim/expected/sim_only_connects.txt b/crates/fayalite/tests/sim/expected/sim_only_connects.txt index 827f3cc..3b90ca8 100644 --- a/crates/fayalite/tests/sim/expected/sim_only_connects.txt +++ b/crates/fayalite/tests/sim/expected/sim_only_connects.txt @@ -380,10 +380,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0, - 0, - 1, - 0, + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), ], }, big_slots: StatePart { @@ -392,15 +392,15 @@ Simulation { 0, 1, 0, + 1 (modified), + 0, + 0, + 0 (modified), + 1 (modified), + 0 (modified), 1, 0, - 0, - 0, - 1, - 0, - 1, - 0, - 1, + 1 (modified), 0, ], }, @@ -443,8 +443,8 @@ Simulation { }, { "extra": "value", - }, - {}, + } (modified), + {} (modified), { "bar": "", "extra": "value", @@ -1252,6 +1252,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1260,6 +1261,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1269,6 +1271,7 @@ Simulation { index: StatePartIndex(0), ty: SimOnly>>, }, + maybe_changed: true, state: { "extra": "value", }, @@ -1282,6 +1285,7 @@ Simulation { index: StatePartIndex(1), ty: SimOnly>>, }, + maybe_changed: true, state: { "extra": "value", }, @@ -1295,6 +1299,7 @@ Simulation { index: StatePartIndex(2), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "", "extra": "value", @@ -1312,6 +1317,7 @@ Simulation { index: StatePartIndex(3), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "baz", "extra": "value", @@ -1328,6 +1334,7 @@ Simulation { kind: BigClock { index: StatePartIndex(4), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1336,6 +1343,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(5), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1345,6 +1353,7 @@ Simulation { index: StatePartIndex(6), ty: SimOnly>>, }, + maybe_changed: true, state: { "extra": "value", }, @@ -1358,6 +1367,7 @@ Simulation { index: StatePartIndex(7), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "", "extra": "value", @@ -1374,6 +1384,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1382,6 +1393,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(3), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1391,6 +1403,7 @@ Simulation { index: StatePartIndex(4), ty: SimOnly>>, }, + maybe_changed: true, state: { "extra": "value", }, @@ -1404,6 +1417,7 @@ Simulation { index: StatePartIndex(5), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "", "extra": "value", @@ -1421,6 +1435,7 @@ Simulation { index: StatePartIndex(8), ty: SimOnly>>, }, + maybe_changed: true, state: { "extra": "value", }, @@ -1433,6 +1448,7 @@ Simulation { kind: BigBool { index: StatePartIndex(6), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1441,6 +1457,7 @@ Simulation { kind: BigClock { index: StatePartIndex(12), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1449,6 +1466,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(13), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1458,6 +1476,7 @@ Simulation { index: StatePartIndex(13), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "", "extra": "value", @@ -1475,6 +1494,7 @@ Simulation { index: StatePartIndex(14), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "baz", "extra": "value", @@ -1491,6 +1511,7 @@ Simulation { kind: BigClock { index: StatePartIndex(10), }, + maybe_changed: true, state: 0x1, last_state: 0x1, }, @@ -1499,6 +1520,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(11), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -1508,6 +1530,7 @@ Simulation { index: StatePartIndex(11), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "", "extra": "value", @@ -1525,6 +1548,7 @@ Simulation { index: StatePartIndex(12), ty: SimOnly>>, }, + maybe_changed: true, state: { "bar": "baz", "extra": "value", diff --git a/crates/fayalite/tests/sim/expected/sim_read_past.txt b/crates/fayalite/tests/sim/expected/sim_read_past.txt index 6df4571..17156d0 100644 --- a/crates/fayalite/tests/sim/expected/sim_read_past.txt +++ b/crates/fayalite/tests/sim/expected/sim_read_past.txt @@ -517,67 +517,67 @@ Simulation { }, small_slots: StatePart { value: [ - 1, - 0, - 0, - 1, - 0, - 0, - 1, - 0, - 0, + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 0 (modified), ], }, big_slots: StatePart { value: [ + 0 (modified), 0, 0, - 0, - 49, - 50, - 50, - 0, - 1, - 0, - 49, - 49, - 50, - 1, - 0, - 0, - 48, - 49, - 49, - 0, - 0, - 1, - 48, - 49, - 48, - 0, - 1, - 0, - 49, - 49, - 50, - 0, - 0, - 1, - 49, - 49, - 49, - 0, - 0, - 1, - 49, - 50, - 50, - 0, - 1, - 0, - 49, - 49, - 50, + 49 (modified), + 50 (modified), + 50 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 49 (modified), + 49 (modified), + 50 (modified), + 1 (modified), + 0 (modified), + 0 (modified), + 48 (modified), + 49 (modified), + 49 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 48 (modified), + 49 (modified), + 48 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 49 (modified), + 49 (modified), + 50 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 49 (modified), + 49 (modified), + 49 (modified), + 0 (modified), + 0 (modified), + 1 (modified), + 49 (modified), + 50 (modified), + 50 (modified), + 0 (modified), + 1 (modified), + 0 (modified), + 49 (modified), + 49 (modified), + 50 (modified), ], }, sim_only_slots: StatePart { @@ -9500,6 +9500,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -9508,6 +9509,7 @@ Simulation { kind: BigClock { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -9516,6 +9518,7 @@ Simulation { kind: BigClock { index: StatePartIndex(2), }, + maybe_changed: true, state: 0x0, last_state: 0x1, }, @@ -9525,6 +9528,7 @@ Simulation { index: StatePartIndex(3), ty: UInt<8>, }, + maybe_changed: false, state: 0x31, last_state: 0x31, }, @@ -9534,6 +9538,7 @@ Simulation { index: StatePartIndex(4), ty: UInt<8>, }, + maybe_changed: false, state: 0x32, last_state: 0x32, }, @@ -9543,6 +9548,7 @@ Simulation { index: StatePartIndex(5), ty: UInt<8>, }, + maybe_changed: false, state: 0x32, last_state: 0x32, }, @@ -9551,6 +9557,7 @@ Simulation { kind: BigClock { index: StatePartIndex(6), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -9559,6 +9566,7 @@ Simulation { kind: BigClock { index: StatePartIndex(7), }, + maybe_changed: false, state: 0x1, last_state: 0x1, }, @@ -9567,6 +9575,7 @@ Simulation { kind: BigClock { index: StatePartIndex(8), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -9576,6 +9585,7 @@ Simulation { index: StatePartIndex(9), ty: UInt<8>, }, + maybe_changed: false, state: 0x31, last_state: 0x31, }, @@ -9585,6 +9595,7 @@ Simulation { index: StatePartIndex(10), ty: UInt<8>, }, + maybe_changed: false, state: 0x31, last_state: 0x31, }, @@ -9594,6 +9605,7 @@ Simulation { index: StatePartIndex(11), ty: UInt<8>, }, + maybe_changed: false, state: 0x32, last_state: 0x32, }, diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt index 3fea928..5584b73 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt @@ -56,8 +56,8 @@ Simulation { }, big_slots: StatePart { value: [ - 0, - 0, + 0 (modified), + 0 (modified), 3, ], }, @@ -310,6 +310,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -318,6 +319,7 @@ Simulation { kind: BigAsyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -327,6 +329,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<8>, }, + maybe_changed: false, state: 0x03, last_state: 0x03, }, diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt index 2283ce5..f03c25a 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt @@ -56,8 +56,8 @@ Simulation { }, big_slots: StatePart { value: [ - 0, - 0, + 0 (modified), + 0 (modified), 3, ], }, @@ -310,6 +310,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -318,6 +319,7 @@ Simulation { kind: BigAsyncReset { index: StatePartIndex(1), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -327,6 +329,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<8>, }, + maybe_changed: false, state: 0x03, last_state: 0x03, }, diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt index c77046f..c93d6c1 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt @@ -56,7 +56,7 @@ Simulation { }, big_slots: StatePart { value: [ - 0, + 0 (modified), 0, 3, ], @@ -310,6 +310,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -318,6 +319,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -327,6 +329,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<8>, }, + maybe_changed: false, state: 0x03, last_state: 0x03, }, diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt index e1c565a..f13af84 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt @@ -56,7 +56,7 @@ Simulation { }, big_slots: StatePart { value: [ - 0, + 0 (modified), 0, 3, ], @@ -310,6 +310,7 @@ Simulation { kind: BigClock { index: StatePartIndex(0), }, + maybe_changed: true, state: 0x0, last_state: 0x0, }, @@ -318,6 +319,7 @@ Simulation { kind: BigSyncReset { index: StatePartIndex(1), }, + maybe_changed: false, state: 0x0, last_state: 0x0, }, @@ -327,6 +329,7 @@ Simulation { index: StatePartIndex(2), ty: UInt<8>, }, + maybe_changed: false, state: 0x03, last_state: 0x03, }, From 8e4eeef72340f1205ed5d2277dab112cdf352b35 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 30 Apr 2026 23:10:49 -0700 Subject: [PATCH 02/15] add support for custom debug/display formatting of #[hdl] structs/enums also cleans up default debug formatting to use the struct/enum name (or MaskType) instead of the implementation detail type name. --- crates/fayalite-proc-macros-impl/src/fold.rs | 1 + .../src/hdl_bundle.rs | 128 ++++++++++--- .../fayalite-proc-macros-impl/src/hdl_enum.rs | 122 ++++++++++++- .../src/hdl_type_alias.rs | 28 ++- .../src/hdl_type_common.rs | 168 +++++++++++++++++- crates/fayalite-proc-macros-impl/src/lib.rs | 5 + crates/fayalite/src/array.rs | 17 +- crates/fayalite/src/bundle.rs | 30 +++- crates/fayalite/src/clock.rs | 14 +- crates/fayalite/src/enum_.rs | 13 +- crates/fayalite/src/int.rs | 31 +++- crates/fayalite/src/int/uint_in_range.rs | 20 ++- crates/fayalite/src/phantom_const.rs | 11 +- crates/fayalite/src/reset.rs | 14 +- crates/fayalite/src/sim/value.rs | 21 ++- crates/fayalite/src/ty.rs | 29 ++- crates/fayalite/tests/hdl_types_fmt.rs | 166 +++++++++++++++++ .../ui/simvalue_is_not_internable.stderr | 18 +- 18 files changed, 773 insertions(+), 63 deletions(-) create mode 100644 crates/fayalite/tests/hdl_types_fmt.rs diff --git a/crates/fayalite-proc-macros-impl/src/fold.rs b/crates/fayalite-proc-macros-impl/src/fold.rs index 22e7b82..50423b5 100644 --- a/crates/fayalite-proc-macros-impl/src/fold.rs +++ b/crates/fayalite-proc-macros-impl/src/fold.rs @@ -257,5 +257,6 @@ no_op_fold!(syn::Token![let]); no_op_fold!(syn::Token![mut]); no_op_fold!(syn::Token![static]); no_op_fold!(syn::Token![struct]); +no_op_fold!(syn::Token![type]); no_op_fold!(syn::Token![where]); no_op_fold!(usize); diff --git a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs index 97fa3ff..6847af9 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs @@ -3,8 +3,9 @@ use crate::{ Errors, HdlAttr, PairsIterExt, hdl_type_common::{ - ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedField, ParsedFieldsNamed, ParsedGenerics, - SplitForImpl, TypesParser, WrappedInConst, common_derives, get_target, + CustomDebugOptions, CustomDebugTrait, ItemOptions, MakeHdlTypeExpr, MaybeParsed, + ParsedField, ParsedFieldsNamed, ParsedGenerics, SplitForImpl, TypesParser, WrappedInConst, + common_derives, create_struct_debug_impl, get_target, }, kw, }; @@ -30,6 +31,7 @@ pub(crate) struct ParsedBundle { pub(crate) fields: MaybeParsed, pub(crate) field_flips: Vec>>, pub(crate) mask_type_ident: Ident, + pub(crate) mask_type_name: String, pub(crate) mask_type_match_variant_ident: Ident, pub(crate) mask_type_sim_value_ident: Ident, pub(crate) match_variant_ident: Ident, @@ -88,6 +90,8 @@ impl ParsedBundle { no_runtime_generics: _, cmp_eq: _, ref get, + custom_debug: _, + custom_sim_display: _, } = options.body; if let Some((get, ..)) = get { errors.error(get, "#[hdl(get(...))] is not allowed on structs"); @@ -131,6 +135,7 @@ impl ParsedBundle { fields, field_flips, mask_type_ident: format_ident!("__{}__MaskType", ident), + mask_type_name: format!("MaskType<{}>", ident), mask_type_match_variant_ident: format_ident!("__{}__MaskType__MatchVariant", ident), mask_type_sim_value_ident: format_ident!("__{}__MaskType__SimValue", ident), match_variant_ident: format_ident!("__{}__MatchVariant", ident), @@ -448,6 +453,7 @@ impl ToTokens for ParsedBundle { fields, field_flips, mask_type_ident, + mask_type_name, mask_type_match_variant_ident, mask_type_sim_value_ident, match_variant_ident, @@ -464,11 +470,20 @@ impl ToTokens for ParsedBundle { no_runtime_generics, cmp_eq, get: _, + custom_debug: _, + custom_sim_display, } = &options.body; + let CustomDebugOptions { + type_: custom_debug_type, + sim: custom_debug_sim, + mask_type: custom_debug_mask_type, + mask_sim: custom_debug_mask_sim, + } = options.body.custom_debug(); let target = get_target(target, ident); + let struct_name = ident.to_string(); let mut item_attrs = attrs.clone(); - item_attrs.push(common_derives(span)); - ItemStruct { + item_attrs.push(common_derives(span, false)); + let type_struct = ItemStruct { attrs: item_attrs, vis: vis.clone(), struct_token: *struct_token, @@ -476,8 +491,8 @@ impl ToTokens for ParsedBundle { generics: generics.into(), fields: Fields::Named(fields.clone().into()), semi_token: None, - } - .to_tokens(tokens); + }; + type_struct.to_tokens(tokens); let (impl_generics, type_generics, where_clause) = generics.split_for_impl(); if let (MaybeParsed::Parsed(generics), MaybeParsed::Parsed(fields), None) = (generics, fields, no_runtime_generics) @@ -503,6 +518,9 @@ impl ToTokens for ParsedBundle { } let mut wrapped_in_const = WrappedInConst::new(tokens, span); let tokens = wrapped_in_const.inner(); + if custom_debug_type.is_none() { + create_struct_debug_impl(&type_struct, &struct_name, None).to_tokens(tokens); + } let builder = Builder { vis: vis.clone(), struct_token: *struct_token, @@ -530,9 +548,9 @@ impl ToTokens for ParsedBundle { mask_type_builder.to_tokens(tokens); let unfilled_mask_type_builder_ty = mask_type_builder.builder_struct_ty(|_| BuilderFieldState::Unfilled); - ItemStruct { + let mask_type_struct = ItemStruct { attrs: vec![ - common_derives(span), + common_derives(span, false), parse_quote_spanned! {span=> #[allow(non_camel_case_types, dead_code)] }, @@ -543,17 +561,20 @@ impl ToTokens for ParsedBundle { generics: generics.into(), fields: Fields::Named(mask_type_fields.clone()), semi_token: None, + }; + mask_type_struct.to_tokens(tokens); + if custom_debug_mask_type.is_none() { + create_struct_debug_impl(&mask_type_struct, mask_type_name, None).to_tokens(tokens); } - .to_tokens(tokens); let mut mask_type_match_variant_fields = mask_type_fields.clone(); for Field { ty, .. } in &mut mask_type_match_variant_fields.named { *ty = parse_quote_spanned! {span=> ::fayalite::expr::Expr<#ty> }; } - ItemStruct { + let mask_type_match_variant_struct = ItemStruct { attrs: vec![ - common_derives(span), + common_derives(span, false), parse_quote_spanned! {span=> #[allow(non_camel_case_types, dead_code)] }, @@ -564,17 +585,19 @@ impl ToTokens for ParsedBundle { generics: generics.into(), fields: Fields::Named(mask_type_match_variant_fields), semi_token: None, - } - .to_tokens(tokens); + }; + mask_type_match_variant_struct.to_tokens(tokens); + create_struct_debug_impl(&mask_type_match_variant_struct, mask_type_name, None) + .to_tokens(tokens); let mut match_variant_fields = FieldsNamed::from(fields.clone()); for Field { ty, .. } in &mut match_variant_fields.named { *ty = parse_quote_spanned! {span=> ::fayalite::expr::Expr<#ty> }; } - ItemStruct { + let match_variant_struct = ItemStruct { attrs: vec![ - common_derives(span), + common_derives(span, false), parse_quote_spanned! {span=> #[allow(non_camel_case_types, dead_code)] }, @@ -585,19 +608,19 @@ impl ToTokens for ParsedBundle { generics: generics.into(), fields: Fields::Named(match_variant_fields), semi_token: None, - } - .to_tokens(tokens); + }; + match_variant_struct.to_tokens(tokens); + create_struct_debug_impl(&match_variant_struct, &struct_name, None).to_tokens(tokens); let mut mask_type_sim_value_fields = mask_type_fields; for Field { ty, .. } in &mut mask_type_sim_value_fields.named { *ty = parse_quote_spanned! {span=> ::fayalite::sim::value::SimValue<#ty> }; } - ItemStruct { + let mask_type_sim_value_struct = ItemStruct { attrs: vec![ parse_quote_spanned! {span=> #[::fayalite::__std::prelude::v1::derive( - ::fayalite::__std::fmt::Debug, ::fayalite::__std::clone::Clone, )] }, @@ -611,19 +634,34 @@ impl ToTokens for ParsedBundle { generics: generics.into(), fields: Fields::Named(mask_type_sim_value_fields), semi_token: None, + }; + mask_type_sim_value_struct.to_tokens(tokens); + if custom_debug_mask_sim.is_none() { + create_struct_debug_impl( + &mask_type_struct, + mask_type_name, + Some(CustomDebugTrait { + trait_path: &parse_quote_spanned! {span=> + ::fayalite::ty::SimValueDebug + }, + fn_name: &format_ident!("sim_value_debug", span = span), + this_arg: &parse_quote_spanned! {span=> + value: &::SimValue + }, + }), + ) + .to_tokens(tokens); } - .to_tokens(tokens); let mut sim_value_fields = FieldsNamed::from(fields.clone()); for Field { ty, .. } in &mut sim_value_fields.named { *ty = parse_quote_spanned! {span=> ::fayalite::sim::value::SimValue<#ty> }; } - ItemStruct { + let sim_value_struct = ItemStruct { attrs: vec![ parse_quote_spanned! {span=> #[::fayalite::__std::prelude::v1::derive( - ::fayalite::__std::fmt::Debug, ::fayalite::__std::clone::Clone, )] }, @@ -637,8 +675,36 @@ impl ToTokens for ParsedBundle { generics: generics.into(), fields: Fields::Named(sim_value_fields), semi_token: None, + }; + sim_value_struct.to_tokens(tokens); + if custom_debug_sim.is_none() { + create_struct_debug_impl( + &type_struct, + &struct_name, + Some(CustomDebugTrait { + trait_path: &parse_quote_spanned! {span=> + ::fayalite::ty::SimValueDebug + }, + fn_name: &format_ident!("sim_value_debug", span = span), + this_arg: &parse_quote_spanned! {span=> + value: &::SimValue + }, + }), + ) + .to_tokens(tokens); + } + if custom_sim_display.is_some() { + quote_spanned! {span=> + #[automatically_derived] + impl #impl_generics ::fayalite::__std::fmt::Display for #sim_value_ident #type_generics + #where_clause + { + fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + <#target #type_generics as ::fayalite::ty::SimValueDisplay>::sim_value_display(self, f) + } + } + }.to_tokens(tokens); } - .to_tokens(tokens); let this_token = Ident::new("__this", span); let fields_token = Ident::new("__fields", span); let self_token = Token![self](span); @@ -820,6 +886,14 @@ impl ToTokens for ParsedBundle { } } #[automatically_derived] + impl #impl_generics ::fayalite::__std::fmt::Debug for #mask_type_sim_value_ident #type_generics + #where_clause + { + fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + <#mask_type_ident #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f) + } + } + #[automatically_derived] impl #impl_generics ::fayalite::expr::ValueType for #mask_type_sim_value_ident #type_generics #where_clause { @@ -980,6 +1054,14 @@ impl ToTokens for ParsedBundle { } } #[automatically_derived] + impl #impl_generics ::fayalite::__std::fmt::Debug for #sim_value_ident #type_generics + #where_clause + { + fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + <#target #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f) + } + } + #[automatically_derived] impl #impl_generics ::fayalite::expr::ValueType for #sim_value_ident #type_generics #where_clause { diff --git a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs index ae0f8f4..e2410bc 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs @@ -3,8 +3,9 @@ use crate::{ Errors, HdlAttr, PairsIterExt, hdl_type_common::{ - ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, SplitForImpl, - TypesParser, WrappedInConst, common_derives, get_target, + CustomDebugOptions, ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, + SplitForImpl, TypesParser, WrappedInConst, common_derives, create_struct_debug_impl, + get_target, }, kw, }; @@ -160,6 +161,8 @@ impl ParsedEnum { no_runtime_generics: _, cmp_eq, ref get, + custom_debug: _, + custom_sim_display: _, } = options.body; if let Some((cmp_eq,)) = cmp_eq { errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for enums"); @@ -167,6 +170,24 @@ impl ParsedEnum { if let Some((get, ..)) = get { errors.error(get, "#[hdl(get(...))] is not allowed on enums"); } + let CustomDebugOptions { + type_: _, + sim: _, + mask_type, + mask_sim, + } = options.body.custom_debug(); + if let Some((mask_type,)) = mask_type { + errors.error( + mask_type, + "#[hdl(custom_debug(mask_type)] is not allowed on enums", + ); + } + if let Some((mask_sim,)) = mask_sim { + errors.error( + mask_sim, + "#[hdl(custom_debug(mask_sim)] is not allowed on enums", + ); + } attrs.retain(|attr| { if attr.path().is_ident("repr") { errors.error(attr, "#[repr] is not supported on #[hdl] enums"); @@ -230,10 +251,19 @@ impl ToTokens for ParsedEnum { no_runtime_generics, cmp_eq: _, // TODO: implement cmp_eq for enums get: _, + custom_debug: _, + custom_sim_display, } = &options.body; + let CustomDebugOptions { + type_: custom_debug_type, + sim: custom_debug_sim, + mask_type: _, + mask_sim: _, + } = options.body.custom_debug(); let target = get_target(target, ident); + let enum_name = ident.to_string(); let mut struct_attrs = attrs.clone(); - struct_attrs.push(common_derives(span)); + struct_attrs.push(common_derives(span, false)); struct_attrs.push(parse_quote_spanned! {span=> #[allow(non_snake_case)] }); @@ -273,7 +303,7 @@ impl ToTokens for ParsedEnum { } }, )); - ItemStruct { + let type_struct = ItemStruct { attrs: struct_attrs, vis: vis.clone(), struct_token: Token![struct](enum_token.span), @@ -288,8 +318,8 @@ impl ToTokens for ParsedEnum { }) }, semi_token: None, - } - .to_tokens(tokens); + }; + type_struct.to_tokens(tokens); let (impl_generics, type_generics, where_clause) = generics.split_for_impl(); if let (MaybeParsed::Parsed(generics), None) = (generics, no_runtime_generics) { generics.make_runtime_generics(tokens, vis, ident, &target, |context| { @@ -373,6 +403,9 @@ impl ToTokens for ParsedEnum { } .to_tokens(tokens); } + if custom_debug_type.is_none() { + create_struct_debug_impl(&type_struct, &enum_name, None).to_tokens(tokens); + } let mut enum_attrs = attrs.clone(); enum_attrs.push(parse_quote_spanned! {span=> #[allow(dead_code, non_camel_case_types)] @@ -453,7 +486,6 @@ impl ToTokens for ParsedEnum { let mut enum_attrs = attrs.clone(); enum_attrs.push(parse_quote_spanned! {span=> #[::fayalite::__std::prelude::v1::derive( - ::fayalite::__std::fmt::Debug, ::fayalite::__std::clone::Clone, )] }); @@ -838,6 +870,74 @@ impl ToTokens for ParsedEnum { }, )), ); + if custom_debug_sim.is_none() { + let debug_match_arms = Vec::from_iter( + variants + .iter() + .map( + |ParsedVariant { + attrs: _, + options: _, + ident, + field, + }| { + let variant_name = ident.to_string(); + if let Some(_) = field { + quote_spanned! {span=> + #sim_value_ident::#ident(field, _) => { + f.debug_tuple(#variant_name).field(field).finish() + } + } + } else { + quote_spanned! {span=> + #sim_value_ident::#ident(_) => { + f.write_str(#variant_name) + } + } + } + }, + ) + .chain(sim_value_unknown_variant_name.as_ref().map( + |sim_value_unknown_variant_name| { + let sim_value_unknown_variant_name_str = + sim_value_unknown_variant_name.to_string(); + quote_spanned! {span=> + #sim_value_ident::#sim_value_unknown_variant_name(_) => { + f.write_str(#sim_value_unknown_variant_name_str) + } + } + }, + )), + ); + quote_spanned! {span=> + #[automatically_derived] + impl #impl_generics ::fayalite::ty::SimValueDebug for #target #type_generics + #where_clause + { + fn sim_value_debug( + value: &::SimValue, + f: &mut ::fayalite::__std::fmt::Formatter<'_>, + ) -> ::fayalite::__std::fmt::Result { + match value { + #(#debug_match_arms)* + } + } + } + } + .to_tokens(tokens); + } + if custom_sim_display.is_some() { + quote_spanned! {span=> + #[automatically_derived] + impl #impl_generics ::fayalite::__std::fmt::Display for #sim_value_ident #type_generics + #where_clause + { + fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + <#target #type_generics as ::fayalite::ty::SimValueDisplay>::sim_value_display(self, f) + } + } + }.to_tokens(tokens); + } let variants_len = variants.len(); quote_spanned! {span=> #[automatically_derived] @@ -934,6 +1034,14 @@ impl ToTokens for ParsedEnum { } } #[automatically_derived] + impl #impl_generics ::fayalite::__std::fmt::Debug for #sim_value_ident #type_generics + #where_clause + { + fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + <#target #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f) + } + } + #[automatically_derived] impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#target #type_generics> for #sim_value_ident #type_generics #where_clause diff --git a/crates/fayalite-proc-macros-impl/src/hdl_type_alias.rs b/crates/fayalite-proc-macros-impl/src/hdl_type_alias.rs index 0fa2222..556c15b 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_type_alias.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_type_alias.rs @@ -215,6 +215,8 @@ impl ParsedTypeAlias { no_runtime_generics, cmp_eq, get: _, + ref custom_debug, + custom_sim_display, } = options.body; if let Some((no_static,)) = no_static { errors.error(no_static, "no_static is not valid on type aliases"); @@ -234,6 +236,15 @@ impl ParsedTypeAlias { if let Some((cmp_eq,)) = cmp_eq { errors.error(cmp_eq, "cmp_eq is not valid on type aliases"); } + if let Some((custom_debug, _, _)) = custom_debug { + errors.error(custom_debug, "custom_debug is not valid on type aliases"); + } + if let Some((custom_sim_display,)) = custom_sim_display { + errors.error( + custom_sim_display, + "custom_sim_display is not valid on type aliases", + ); + } if let Some((custom_bounds,)) = custom_bounds { errors.error( custom_bounds, @@ -287,6 +298,8 @@ impl ParsedTypeAlias { no_runtime_generics: _, cmp_eq, ref mut get, + ref custom_debug, + custom_sim_display, } = options.body; if let Some(get) = get.take() { return Self::parse_phantom_const_accessor( @@ -311,6 +324,15 @@ impl ParsedTypeAlias { if let Some((cmp_eq,)) = cmp_eq { errors.error(cmp_eq, "cmp_eq is not valid on type aliases"); } + if let Some((custom_debug, _, _)) = custom_debug { + errors.error(custom_debug, "custom_debug is not valid on type aliases"); + } + if let Some((custom_sim_display,)) = custom_sim_display { + errors.error( + custom_sim_display, + "custom_sim_display is not valid on type aliases", + ); + } let generics = if custom_bounds.is_some() { MaybeParsed::Unrecognized(generics) } else if let Some(generics) = errors.ok(ParsedGenerics::parse(&mut generics)) { @@ -356,6 +378,8 @@ impl ToTokens for ParsedTypeAlias { no_runtime_generics, cmp_eq: _, get: _, + custom_debug: _, + custom_sim_display: _, } = &options.body; let target = get_target(target, ident); let mut type_attrs = attrs.clone(); @@ -402,6 +426,8 @@ impl ToTokens for ParsedTypeAlias { no_runtime_generics: _, cmp_eq: _, get: _, + custom_debug: _, + custom_sim_display: _, } = &options.body; let span = ident.span(); let mut type_attrs = attrs.clone(); @@ -427,7 +453,7 @@ impl ToTokens for ParsedTypeAlias { format_ident!("__{}__GenericsAccumulation", ident); ItemStruct { attrs: vec![ - common_derives(span), + common_derives(span, true), parse_quote_spanned! {span=> #[allow(non_camel_case_types)] }, diff --git a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs index 3a0e5e9..18cffc6 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs @@ -7,10 +7,10 @@ use std::{collections::HashMap, fmt, mem}; use syn::{ AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup, ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed, - FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct, - Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound, Turbofish, - Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath, TypeTuple, - Visibility, WhereClause, WherePredicate, + FieldsUnnamed, FnArg, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, + ItemStruct, Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound, + Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath, + TypeTuple, Visibility, WhereClause, WherePredicate, parse::{Parse, ParseStream}, parse_quote, parse_quote_spanned, punctuated::{Pair, Punctuated}, @@ -18,6 +18,17 @@ use syn::{ token::{Brace, Bracket, Paren}, }; +crate::options! { + #[options = CustomDebugOptions] + #[no_ident_fragment] + pub(crate) enum CustomDebugOption { + Type(type_), + Sim(sim), + MaskType(mask_type), + MaskSim(mask_sim), + } +} + crate::options! { #[options = ItemOptions] pub(crate) enum ItemOption { @@ -28,6 +39,8 @@ crate::options! { NoRuntimeGenerics(no_runtime_generics), CmpEq(cmp_eq), Get(get, Expr), + CustomDebug(custom_debug, CustomDebugOptions), + CustomSimDisplay(custom_sim_display), } } @@ -41,8 +54,36 @@ impl ItemOptions { { self.no_static = Some((kw::no_static(custom_bounds.span),)); } + if let Some((kw, _, custom_debug)) = &mut self.custom_debug { + if let CustomDebugOptions { + type_: None, + sim: None, + mask_type: None, + mask_sim: None, + } = custom_debug + { + *custom_debug = CustomDebugOptions { + type_: Some((kw::type_(kw.span),)), + sim: Some((kw::sim(kw.span),)), + mask_type: None, + mask_sim: None, + }; + } + } Ok(()) } + pub(crate) fn custom_debug(&self) -> &CustomDebugOptions { + self.custom_debug.as_ref().map(|v| &v.2).unwrap_or( + const { + &CustomDebugOptions { + type_: None, + sim: None, + mask_type: None, + mask_sim: None, + } + }, + ) + } } pub(crate) struct WrappedInConst<'a> { @@ -84,10 +125,17 @@ pub(crate) fn get_target(target: &Option<(kw::target, Paren, Path)>, item_ident: } } -pub(crate) fn common_derives(span: Span) -> Attribute { +pub(crate) fn common_derives(span: Span, include_debug: bool) -> Attribute { + let debug = include_debug + .then(|| { + quote_spanned! {span=> + ::fayalite::__std::fmt::Debug + } + }) + .into_iter(); parse_quote_spanned! {span=> #[::fayalite::__std::prelude::v1::derive( - ::fayalite::__std::fmt::Debug, + #(#debug,)* ::fayalite::__std::cmp::Eq, ::fayalite::__std::cmp::PartialEq, ::fayalite::__std::hash::Hash, @@ -2975,7 +3023,7 @@ impl ParsedGenerics { let span = ident.span(); ItemStruct { attrs: vec![ - common_derives(span), + common_derives(span, true), parse_quote_spanned! {span=> #[allow(non_camel_case_types)] }, @@ -4733,3 +4781,109 @@ impl ParsedVisibility { .map(|ord| if ord.is_lt() { self } else { other }) } } + +pub(crate) struct CustomDebugTrait<'a> { + pub(crate) trait_path: &'a Path, + pub(crate) fn_name: &'a Ident, + pub(crate) this_arg: &'a FnArg, +} + +#[must_use] +pub(crate) fn create_struct_debug_impl( + item_struct: &ItemStruct, + debug_struct_name: &str, + custom_debug_trait: Option>, +) -> TokenStream { + let ident = &item_struct.ident; + let span = ident.span(); + let (impl_generics, type_generics, where_clause) = item_struct.generics.split_for_impl(); + let trait_path; + let fn_name; + let this_arg; + let CustomDebugTrait { + trait_path, + fn_name, + this_arg, + } = match custom_debug_trait { + Some(v) => v, + None => { + trait_path = parse_quote_spanned! {span=> + ::fayalite::__std::fmt::Debug + }; + fn_name = parse_quote_spanned! {span=> + fmt + }; + this_arg = parse_quote_spanned! {span=> + &self + }; + CustomDebugTrait { + trait_path: &trait_path, + fn_name: &fn_name, + this_arg: &this_arg, + } + } + }; + let this_arg_name = match this_arg { + FnArg::Receiver(this_arg) => this_arg.self_token.to_token_stream(), + FnArg::Typed(this_arg) => match &*this_arg.pat { + syn::Pat::Ident(pat_ident) => pat_ident.ident.to_token_stream(), + _ => unreachable!(), + }, + }; + match &item_struct.fields { + Fields::Named(fields) => { + let field_idents = fields + .named + .iter() + .map(|v| v.ident.as_ref().expect("known to have field name")); + let field_names = field_idents.clone().map(|v| v.to_string()); + quote_spanned! {span=> + #[automatically_derived] + impl #impl_generics #trait_path for #ident #type_generics + #where_clause + { + fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + let _ = #this_arg_name; + f.debug_struct(#debug_struct_name) + #(.field(#field_names, &#this_arg_name.#field_idents))* + .finish() + } + } + } + } + Fields::Unnamed(fields) => { + let field_members = fields + .unnamed + .iter() + .enumerate() + .map(|(index, _)| syn::Index { + index: index as _, + span, + }); + quote_spanned! {span=> + #[automatically_derived] + impl #impl_generics #trait_path for #ident #type_generics + #where_clause + { + fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + let _ = #this_arg_name; + f.debug_tuple(#debug_struct_name) + #(.field(&#this_arg_name.#field_members))* + .finish() + } + } + } + } + Fields::Unit => quote_spanned! {ident.span()=> + #[automatically_derived] + impl #impl_generics #trait_path for #ident #type_generics + #where_clause + { + fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result { + let _ = #this_arg_name; + f.write_str(#debug_struct_name) + } + } + }, + } +} diff --git a/crates/fayalite-proc-macros-impl/src/lib.rs b/crates/fayalite-proc-macros-impl/src/lib.rs index 152053c..905cb05 100644 --- a/crates/fayalite-proc-macros-impl/src/lib.rs +++ b/crates/fayalite-proc-macros-impl/src/lib.rs @@ -42,6 +42,7 @@ pub(crate) trait CustomToken: mod kw { pub(crate) use syn::token::Extern as extern_; + pub(crate) use syn::token::Type as type_; macro_rules! custom_keyword { ($kw:ident) => { @@ -75,6 +76,8 @@ mod kw { custom_keyword!(cmp_eq); custom_keyword!(connect_inexact); custom_keyword!(custom_bounds); + custom_keyword!(custom_debug); + custom_keyword!(custom_sim_display); custom_keyword!(flip); custom_keyword!(get); custom_keyword!(hdl); @@ -83,6 +86,8 @@ mod kw { custom_keyword!(input); custom_keyword!(instance); custom_keyword!(m); + custom_keyword!(mask_sim); + custom_keyword!(mask_type); custom_keyword!(memory); custom_keyword!(memory_array); custom_keyword!(memory_with_init); diff --git a/crates/fayalite/src/array.rs b/crates/fayalite/src/array.rs index 6ca6809..fa754fd 100644 --- a/crates/fayalite/src/array.rs +++ b/crates/fayalite/src/array.rs @@ -13,13 +13,13 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, MatchVariantWithoutScope, OpaqueSimValueSlice, OpaqueSimValueWriter, - OpaqueSimValueWritten, StaticType, Type, TypeProperties, TypeWithDeref, + OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties, TypeWithDeref, serde_impls::SerdeCanonicalType, }, util::ConstUsize, }; use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error}; -use std::{borrow::Cow, iter::FusedIterator, ops::Index}; +use std::{borrow::Cow, fmt, iter::FusedIterator, ops::Index}; #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct ArrayType { @@ -28,8 +28,8 @@ pub struct ArrayType { type_properties: TypeProperties, } -impl std::fmt::Debug for ArrayType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Debug for ArrayType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Array<{:?}, {}>", self.element, self.len()) } } @@ -182,6 +182,15 @@ impl, Len: Size, State: Visitor + ?Sized> Visit } } +impl SimValueDebug for ArrayType { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl Type for ArrayType { type BaseType = Array; type MaskType = ArrayType; diff --git a/crates/fayalite/src/bundle.rs b/crates/fayalite/src/bundle.rs index 1471f3a..5fad35c 100644 --- a/crates/fayalite/src/bundle.rs +++ b/crates/fayalite/src/bundle.rs @@ -14,8 +14,8 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, MatchVariantWithoutScope, OpaqueSimValue, OpaqueSimValueSize, - OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type, - TypeProperties, TypeWithDeref, impl_match_variant_as_self, + OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug, + StaticType, Type, TypeProperties, TypeWithDeref, impl_match_variant_as_self, }, util::HashMap, }; @@ -271,6 +271,15 @@ impl Type for Bundle { } } +impl SimValueDebug for Bundle { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + pub trait BundleType: Type { type Builder: Default; fn fields(&self) -> Interned<[BundleField]>; @@ -471,6 +480,14 @@ macro_rules! impl_tuples { #[var($var)] })*] } + impl<$($T: Type,)*> SimValueDebug for ($($T,)*) { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } + } impl<$($T: Type,)*> Type for ($($T,)*) { type BaseType = Bundle; type MaskType = ($($T::MaskType,)*); @@ -773,6 +790,15 @@ impl_tuples! { ] } +impl SimValueDebug for PhantomData { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl Type for PhantomData { type BaseType = Bundle; type MaskType = (); diff --git a/crates/fayalite/src/clock.rs b/crates/fayalite/src/clock.rs index 168142b..0e6d145 100644 --- a/crates/fayalite/src/clock.rs +++ b/crates/fayalite/src/clock.rs @@ -1,5 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information + use crate::{ expr::{Expr, ValueType}, hdl, @@ -9,10 +10,12 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter, - OpaqueSimValueWritten, StaticType, Type, TypeProperties, impl_match_variant_as_self, + OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties, + impl_match_variant_as_self, }, }; use bitvec::{bits, order::Lsb0}; +use std::fmt; #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)] pub struct Clock; @@ -69,6 +72,15 @@ impl Type for Clock { } } +impl SimValueDebug for Clock { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl Clock { pub fn type_properties(self) -> TypeProperties { Self::TYPE_PROPERTIES diff --git a/crates/fayalite/src/enum_.rs b/crates/fayalite/src/enum_.rs index a04f67a..d545f93 100644 --- a/crates/fayalite/src/enum_.rs +++ b/crates/fayalite/src/enum_.rs @@ -14,8 +14,8 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, OpaqueSimValueSize, - OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type, - TypeProperties, + OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug, + StaticType, Type, TypeProperties, }, util::HashMap, }; @@ -410,6 +410,15 @@ impl Type for Enum { } } +impl SimValueDebug for Enum { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + #[derive(Clone, PartialEq, Eq, Hash, Debug, Default)] pub struct EnumPaddingSimValue { bits: Option, diff --git a/crates/fayalite/src/int.rs b/crates/fayalite/src/int.rs index c461306..ff20933 100644 --- a/crates/fayalite/src/int.rs +++ b/crates/fayalite/src/int.rs @@ -15,8 +15,8 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, FillInDefaultedGenerics, OpaqueSimValueSize, OpaqueSimValueSlice, - OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type, TypeProperties, - impl_match_variant_as_self, + OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug, SimValueDisplay, StaticType, + Type, TypeProperties, impl_match_variant_as_self, }, util::{ConstBool, ConstUsize, GenericConstBool, GenericConstUsize, interned_bit, slice_range}, }; @@ -1019,6 +1019,24 @@ macro_rules! impl_int { } } + impl SimValueDebug for $name { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } + } + + impl SimValueDisplay for $name { + fn sim_value_display( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Display::fmt(value, f) + } + } + impl Default for $name { fn default() -> Self { Self::TYPE @@ -1899,6 +1917,15 @@ impl Type for Bool { } } +impl SimValueDebug for Bool { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl StaticType for Bool { const TYPE: Self = Bool; const MASK_TYPE: Self::MaskType = Bool; diff --git a/crates/fayalite/src/int/uint_in_range.rs b/crates/fayalite/src/int/uint_in_range.rs index acf2fec..edf2e25 100644 --- a/crates/fayalite/src/int/uint_in_range.rs +++ b/crates/fayalite/src/int/uint_in_range.rs @@ -14,7 +14,7 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, - StaticType, Type, TypeProperties, impl_match_variant_as_self, + SimValueDebug, StaticType, Type, TypeProperties, impl_match_variant_as_self, }, }; use bitvec::{order::Lsb0, view::BitView}; @@ -94,6 +94,15 @@ impl Type for UIntInRangeMaskType { } } +impl SimValueDebug for UIntInRangeMaskType { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl BundleType for UIntInRangeMaskType { type Builder = NoBuilder; @@ -339,6 +348,15 @@ macro_rules! define_uint_in_range_type { } } + impl SimValueDebug for $UIntInRangeType { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } + } + impl fmt::Debug for $UIntInRangeType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { value, range } = self; diff --git a/crates/fayalite/src/phantom_const.rs b/crates/fayalite/src/phantom_const.rs index fb7be6f..ba85817 100644 --- a/crates/fayalite/src/phantom_const.rs +++ b/crates/fayalite/src/phantom_const.rs @@ -9,7 +9,7 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, - StaticType, Type, TypeProperties, impl_match_variant_as_self, + SimValueDebug, StaticType, Type, TypeProperties, impl_match_variant_as_self, serde_impls::{SerdeCanonicalType, SerdePhantomConst}, }, }; @@ -327,6 +327,15 @@ impl Type for PhantomConst { } } +impl SimValueDebug for PhantomConst { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl Default for PhantomConst where Interned: Default, diff --git a/crates/fayalite/src/reset.rs b/crates/fayalite/src/reset.rs index 13273ac..ddc3651 100644 --- a/crates/fayalite/src/reset.rs +++ b/crates/fayalite/src/reset.rs @@ -1,5 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information + use crate::{ clock::Clock, expr::{CastToImpl, Expr, ValueType}, @@ -8,11 +9,13 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter, - OpaqueSimValueWritten, StaticType, Type, TypeProperties, impl_match_variant_as_self, + OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties, + impl_match_variant_as_self, }, util::ConstUsize, }; use bitvec::{bits, order::Lsb0}; +use std::fmt; mod sealed { pub trait ResetTypeSealed {} @@ -100,6 +103,15 @@ macro_rules! reset_type { } } + impl SimValueDebug for $name { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } + } + impl $name { pub fn type_properties(self) -> TypeProperties { Self::TYPE_PROPERTIES diff --git a/crates/fayalite/src/sim/value.rs b/crates/fayalite/src/sim/value.rs index b6a4e4b..a127878 100644 --- a/crates/fayalite/src/sim/value.rs +++ b/crates/fayalite/src/sim/value.rs @@ -15,7 +15,8 @@ use crate::{ source_location::SourceLocation, ty::{ CanonicalType, OpaqueSimValue, OpaqueSimValueSize, OpaqueSimValueSlice, - OpaqueSimValueWriter, StaticType, Type, TypeProperties, impl_match_variant_as_self, + OpaqueSimValueWriter, SimValueDebug, StaticType, Type, TypeProperties, + impl_match_variant_as_self, }, util::{ ConstUsize, HashMap, @@ -1394,6 +1395,15 @@ impl Type for DynSimOnly { } } +impl SimValueDebug for DynSimOnly { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl Type for SimOnly { type BaseType = DynSimOnly; type MaskType = Bool; @@ -1459,6 +1469,15 @@ impl Type for SimOnly { } } +impl SimValueDebug for SimOnly { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl StaticType for SimOnly { const TYPE: Self = Self::new(); diff --git a/crates/fayalite/src/ty.rs b/crates/fayalite/src/ty.rs index 76c0955..ed0ba03 100644 --- a/crates/fayalite/src/ty.rs +++ b/crates/fayalite/src/ty.rs @@ -367,7 +367,15 @@ impl TypeOrDefault for crate::__ { } pub trait Type: - Copy + Hash + Eq + fmt::Debug + Send + Sync + 'static + FillInDefaultedGenerics + Copy + + Hash + + Eq + + fmt::Debug + + Send + + Sync + + 'static + + FillInDefaultedGenerics + + SimValueDebug { type BaseType: BaseType; type MaskType: Type; @@ -402,6 +410,16 @@ pub trait Type: ) -> OpaqueSimValueWritten<'w>; } +pub trait SimValueDebug { + fn sim_value_debug(value: &::SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result + where + Self: Type; +} + +pub trait SimValueDisplay: Type { + fn sim_value_display(value: &Self::SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result; +} + pub trait BaseType: Type< BaseType = Self, @@ -490,6 +508,15 @@ impl Type for CanonicalType { } } +impl SimValueDebug for CanonicalType { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + #[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Default)] #[non_exhaustive] pub struct OpaqueSimValueSizeRange { diff --git a/crates/fayalite/tests/hdl_types_fmt.rs b/crates/fayalite/tests/hdl_types_fmt.rs new file mode 100644 index 0000000..382f64d --- /dev/null +++ b/crates/fayalite/tests/hdl_types_fmt.rs @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// See Notices.txt for copyright information +use fayalite::{prelude::*, ty::SimValueDebug}; +use std::fmt; + +#[hdl(outline_generated)] +struct MyStruct0 { + v: T, + a: ArrayType, S>, +} + +#[hdl] +#[test] +fn check_my_struct0() { + let ty = MyStruct0[UInt[8]][3]; + assert_eq!( + format!("{ty:?}"), + "MyStruct0 { v: UInt<8>, a: Array, 3> }", + ); + assert_eq!( + format!("{:?}", ty.mask_type()), + "MaskType { v: Bool, a: Array }", + ); + let v = #[hdl(sim)] + MyStruct0::<_, _> { + v: 0x23u8, + a: [1u8, 2, 3], + }; + assert_eq!( + format!("{v:?}"), + "MyStruct0 { v: 0x23_u8, a: [0x1_u8, 0x2_u8, 0x3_u8] }", + ); +} + +#[hdl(outline_generated, custom_debug())] +struct MyStruct1 { + v: T, + a: ArrayType, S>, +} + +impl fmt::Debug for MyStruct1 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { v, a } = self; + f.debug_struct("Custom") + .field("v", v) + .field("a", a) + .finish() + } +} + +impl SimValueDebug for MyStruct1 { + #[hdl] + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + #[hdl(sim)] + let Self { v, a } = value; + f.debug_struct("Custom") + .field("v", &v) + .field("a", &a) + .finish() + } +} + +#[hdl] +#[test] +fn check_my_struct1() { + let ty = MyStruct1[UInt[8]][3]; + assert_eq!( + format!("{ty:?}"), + "Custom { v: UInt<8>, a: Array, 3> }", + ); + assert_eq!( + format!("{:?}", ty.mask_type()), + "MaskType { v: Bool, a: Array }", + ); + let v = #[hdl(sim)] + MyStruct1::<_, _> { + v: 0x23u8, + a: [1u8, 2, 3], + }; + assert_eq!( + format!("{v:?}"), + "Custom { v: 0x23_u8, a: [0x1_u8, 0x2_u8, 0x3_u8] }", + ); +} + +#[hdl(outline_generated)] +enum MyEnum0 { + Unit, + V(T), + A(ArrayType, S>), +} + +#[hdl] +#[test] +fn check_my_enum0() { + let ty = MyEnum0[UInt[8]][3]; + assert_eq!( + format!("{ty:?}"), + "MyEnum0 { Unit: (), V: UInt<8>, A: Array, 3> }", + ); + let v = #[hdl(sim)] + ty.Unit(); + assert_eq!(format!("{v:?}"), "Unit"); + let v = #[hdl(sim)] + ty.V(0x23u8); + assert_eq!(format!("{v:?}"), "V(0x23_u8)"); + let v = #[hdl(sim)] + ty.A([1u8, 2, 3]); + assert_eq!(format!("{v:?}"), "A([0x1_u8, 0x2_u8, 0x3_u8])"); +} + +#[hdl(outline_generated, custom_debug())] +enum MyEnum1 { + Unit, + V(T), + A(ArrayType, S>), +} + +impl fmt::Debug for MyEnum1 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { Unit, V, A } = self; + f.debug_struct("Custom") + .field("Unit", Unit) + .field("V", V) + .field("A", A) + .finish() + } +} + +impl SimValueDebug for MyEnum1 { + #[hdl] + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + type SimValueT = ::SimValue; + match value { + SimValueT::::Unit(_) => f.write_str("MyEnum1::Unit"), + SimValueT::::V(v, _) => f.debug_tuple("MyEnum1::V").field(v).finish(), + SimValueT::::A(a, _) => f.debug_tuple("MyEnum1::A").field(a).finish(), + SimValueT::::Unknown(_) => f.write_str("MyEnum1::Unknown"), + } + } +} + +#[hdl] +#[test] +fn check_my_enum1() { + let ty = MyEnum1[UInt[8]][3]; + assert_eq!( + format!("{ty:?}"), + "Custom { Unit: (), V: UInt<8>, A: Array, 3> }", + ); + let v = #[hdl(sim)] + ty.Unit(); + assert_eq!(format!("{v:?}"), "MyEnum1::Unit"); + let v = #[hdl(sim)] + ty.V(0x23u8); + assert_eq!(format!("{v:?}"), "MyEnum1::V(0x23_u8)"); + let v = #[hdl(sim)] + ty.A([1u8, 2, 3]); + assert_eq!(format!("{v:?}"), "MyEnum1::A([0x1_u8, 0x2_u8, 0x3_u8])"); +} diff --git a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr index 6c78637..44aff3f 100644 --- a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr +++ b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr @@ -75,12 +75,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 734 | pub struct OpaqueSimValue { + 761 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 51 | struct SimValueInner { + 52 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -95,7 +95,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 160 | pub struct SimValue { + 161 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` --> src/intern.rs @@ -214,12 +214,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 734 | pub struct OpaqueSimValue { + 761 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 51 | struct SimValueInner { + 52 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -234,7 +234,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 160 | pub struct SimValue { + 161 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `intern_sized` --> src/intern.rs @@ -326,12 +326,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 734 | pub struct OpaqueSimValue { + 761 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 51 | struct SimValueInner { + 52 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -346,7 +346,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 160 | pub struct SimValue { + 161 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` --> src/intern.rs From 7516ec3c24405e07640db4da52ece6f40acb2bec Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 1 May 2026 18:34:49 -0700 Subject: [PATCH 03/15] implement #[hdl(cmp_eq)] for enums --- .../src/hdl_bundle.rs | 2 +- .../fayalite-proc-macros-impl/src/hdl_enum.rs | 173 ++++++++- crates/fayalite/tests/module.rs | 362 +++++++++++++++++- 3 files changed, 530 insertions(+), 7 deletions(-) diff --git a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs index 6847af9..f7ad68d 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs @@ -1223,7 +1223,7 @@ impl ToTokens for ParsedBundle { valueless_eq_body = quote_spanned! {span=> let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); let __rhs = ::fayalite::expr::ValueType::ty(&__rhs); - #(#fields_valueless_eq)|* + #(#fields_valueless_eq)&* }; valueless_ne_body = quote_spanned! {span=> let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); diff --git a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs index e2410bc..e9f013b 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs @@ -159,14 +159,11 @@ impl ParsedEnum { custom_bounds, no_static: _, no_runtime_generics: _, - cmp_eq, + cmp_eq: _, ref get, custom_debug: _, custom_sim_display: _, } = options.body; - if let Some((cmp_eq,)) = cmp_eq { - errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for enums"); - } if let Some((get, ..)) = get { errors.error(get, "#[hdl(get(...))] is not allowed on enums"); } @@ -249,7 +246,7 @@ impl ToTokens for ParsedEnum { custom_bounds: _, no_static, no_runtime_generics, - cmp_eq: _, // TODO: implement cmp_eq for enums + cmp_eq, get: _, custom_debug: _, custom_sim_display, @@ -938,6 +935,172 @@ impl ToTokens for ParsedEnum { } }.to_tokens(tokens); } + if let Some((cmp_eq,)) = cmp_eq { + let mut cmp_eq_where_clause = + Generics::from(generics) + .where_clause + .unwrap_or_else(|| syn::WhereClause { + where_token: Token![where](span), + predicates: Punctuated::new(), + }); + let mut variants_value_eq = vec![]; + let mut variants_expr_eq = vec![]; + let mut fields_valueless_eq = vec![]; + for ( + variant_index, + ParsedVariant { + attrs: _, + options: variant_options, + ident: variant_ident, + field, + }, + ) in variants.iter().enumerate() + { + let VariantOptions {} = variant_options.body; + if let Some(ParsedVariantField { + paren_token: _, + attrs: _, + options: field_options, + ty: field_ty, + comma_token: _, + }) = field + { + let FieldOptions {} = field_options.body; + cmp_eq_where_clause + .predicates + .push(parse_quote_spanned! {cmp_eq.span=> + #field_ty: ::fayalite::expr::HdlPartialEqImpl<#field_ty> + }); + variants_value_eq.push(quote_spanned! {span=> + (#sim_value_ident::#variant_ident(__lhs_field, _), #sim_value_ident::#variant_ident(__rhs_field, _)) => { + ::fayalite::expr::HdlPartialEqImpl::cmp_value_eq( + __lhs.#variant_ident, + ::fayalite::__std::borrow::Cow::Borrowed(__lhs_field), + __rhs.#variant_ident, + ::fayalite::__std::borrow::Cow::Borrowed(__rhs_field), + ) + } + }); + variants_expr_eq.push(quote_spanned! {span=> + { + let (#match_variant_ident::#variant_ident(__lhs), __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter) + .expect("known to have enough variants"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + let (#match_variant_ident::#variant_ident(__rhs), __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::nth( + &mut ::fayalite::module::match_(__rhs), + #variant_index, + ) + .expect("known to have variant"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + ::fayalite::module::connect(__retval, ::fayalite::expr::HdlPartialEqImpl::cmp_expr_eq(__lhs, __rhs)); + } + }); + fields_valueless_eq.push(quote_spanned! {span=> + ::fayalite::expr::HdlPartialEqImpl::cmp_valueless_eq( + ::fayalite::expr::Valueless::new(__lhs.#variant_ident), + ::fayalite::expr::Valueless::new(__rhs.#variant_ident), + ) + }); + } else { + variants_value_eq.push(quote_spanned! {span=> + (#sim_value_ident::#variant_ident(_), #sim_value_ident::#variant_ident(_)) => true, + }); + variants_expr_eq.push(quote_spanned! {span=> + { + let (#match_variant_ident::#variant_ident, __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter) + .expect("known to have enough variants"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + let (#match_variant_ident::#variant_ident, __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::nth( + &mut ::fayalite::module::match_(__rhs), + #variant_index, + ) + .expect("known to have variant"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + ::fayalite::module::connect(__retval, true); + } + }); + } + } + if let Some(sim_value_unknown_variant_name) = &sim_value_unknown_variant_name { + variants_value_eq.push(quote_spanned! {span=> + (#sim_value_ident::#sim_value_unknown_variant_name(__lhs_unknown), #sim_value_ident::#sim_value_unknown_variant_name(__rhs_unknown)) => { + __lhs_unknown == __rhs_unknown + } + }); + } + let valueless_eq_body = if fields_valueless_eq.is_empty() { + quote_spanned! {span=> + ::fayalite::expr::Valueless::new(::fayalite::int::Bool) + } + } else { + quote_spanned! {span=> + let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); + let __rhs = ::fayalite::expr::ValueType::ty(&__rhs); + #(#fields_valueless_eq)&* + } + }; + let cmp_expr_eq_wire_name = format!("{ident}_cmp_eq"); + quote_spanned! {span=> + #[automatically_derived] + impl #impl_generics ::fayalite::expr::HdlPartialEqImpl for #target #type_generics + #cmp_eq_where_clause + { + #[track_caller] + fn cmp_value_eq( + __lhs: Self, + __lhs_value: ::fayalite::__std::borrow::Cow<'_, ::SimValue>, + __rhs: Self, + __rhs_value: ::fayalite::__std::borrow::Cow<'_, ::SimValue>, + ) -> ::fayalite::__std::primitive::bool { + match (&*__lhs_value, &*__rhs_value) { + #(#variants_value_eq)* + _ => false, + } + } + + #[track_caller] + fn cmp_expr_eq( + __lhs: ::fayalite::expr::Expr, + __rhs: ::fayalite::expr::Expr, + ) -> ::fayalite::expr::Expr<::fayalite::int::Bool> { + let __retval = ::fayalite::module::wire(::fayalite::module::ImplicitName(#cmp_expr_eq_wire_name), ::fayalite::int::Bool); + ::fayalite::module::connect(__retval, false); + let mut __lhs_match_variant_iter = ::fayalite::module::match_(__lhs); + #(#variants_expr_eq)* + __retval + } + + #[track_caller] + fn cmp_valueless_eq( + __lhs: ::fayalite::expr::Valueless, + __rhs: ::fayalite::expr::Valueless, + ) -> ::fayalite::expr::Valueless<::fayalite::int::Bool> { + #valueless_eq_body + } + } + } + .to_tokens(tokens); + } let variants_len = variants.len(); quote_spanned! {span=> #[automatically_derived] diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index 2761cba..9dc0107 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -13,7 +13,7 @@ use fayalite::{ }; use serde_json::json; -#[hdl(outline_generated)] +#[hdl(outline_generated, cmp_eq)] pub enum TestEnum { A, B(UInt<8>), @@ -679,6 +679,366 @@ circuit check_enum_literals: }; } +#[hdl_module(outline_generated)] +pub fn check_enum_cmp_eq() { + #[hdl] + let lhs: TestEnum = m.input(); + #[hdl] + let rhs: TestEnum = m.input(); + #[hdl] + let eq: Bool = m.output(); + connect(eq, lhs.cmp_eq(rhs)); +} + +#[test] +fn test_enum_cmp_eq() { + let _n = SourceLocation::normalize_files_for_tests(); + let m = check_enum_cmp_eq(); + dbg!(m); + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: None, + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + type Ty0 = {|A, B: UInt<8>, C: UInt<1>[3]|} + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: Ty0 @[module-XXXXXXXXXX.rs 2:1] + input rhs: Ty0 @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + match lhs: @[module-XXXXXXXXXX.rs 5:1] + A: + match rhs: @[module-XXXXXXXXXX.rs 5:1] + A: + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + B(_match_arm_value): + skip + C(_match_arm_value_1): + skip + B(_match_arm_value_2): + match rhs: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B(_match_arm_value_3): + connect TestEnum_cmp_eq, eq(_match_arm_value_2, _match_arm_value_3) @[module-XXXXXXXXXX.rs 5:1] + C(_match_arm_value_4): + skip + C(_match_arm_value_5): + match rhs: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B(_match_arm_value_6): + skip + C(_match_arm_value_7): + wire _array_literal_expr: UInt<1>[3] + connect _array_literal_expr[0], eq(_match_arm_value_5[0], _match_arm_value_7[0]) + connect _array_literal_expr[1], eq(_match_arm_value_5[1], _match_arm_value_7[1]) + connect _array_literal_expr[2], eq(_match_arm_value_5[2], _match_arm_value_7[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: Some(SimplifyEnumsKind::SimplifyToEnumsWithNoBody), + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + type Ty0 = {|A, B, C|} + type Ty1 = {tag: Ty0, body: UInt<8>} + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: Ty1 @[module-XXXXXXXXXX.rs 2:1] + input rhs: Ty1 @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + match lhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + match rhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + B: + skip + C: + skip + B: + match rhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B: + connect TestEnum_cmp_eq, eq(bits(lhs.body, 7, 0), bits(rhs.body, 7, 0)) @[module-XXXXXXXXXX.rs 5:1] + C: + skip + C: + match rhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B: + skip + C: + wire _array_literal_expr: UInt<1>[3] + wire _cast_bits_to_array_expr: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0] + connect _cast_bits_to_array_expr_flattened[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1] + connect _cast_bits_to_array_expr_flattened[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2] + wire _cast_bits_to_array_expr_1: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0] + connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1] + connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] + connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) + wire _cast_bits_to_array_expr_2: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] + connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] + connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] + wire _cast_bits_to_array_expr_3: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] + connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] + connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) + wire _cast_bits_to_array_expr_4: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] + connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] + connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] + wire _cast_bits_to_array_expr_5: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] + connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] + connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts), + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + type Ty0 = {tag: UInt<2>, body: UInt<8>} + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: Ty0 @[module-XXXXXXXXXX.rs 2:1] + input rhs: Ty0 @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + when eq(lhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(lhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, eq(bits(lhs.body, 7, 0), bits(rhs.body, 7, 0)) @[module-XXXXXXXXXX.rs 5:1] + else when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else: + wire _array_literal_expr: UInt<1>[3] + wire _cast_bits_to_array_expr: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0] + connect _cast_bits_to_array_expr_flattened[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1] + connect _cast_bits_to_array_expr_flattened[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2] + wire _cast_bits_to_array_expr_1: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0] + connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1] + connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] + connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) + wire _cast_bits_to_array_expr_2: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] + connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] + connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] + wire _cast_bits_to_array_expr_3: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] + connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] + connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) + wire _cast_bits_to_array_expr_4: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] + connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] + connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] + wire _cast_bits_to_array_expr_5: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] + connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] + connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: Some(SimplifyEnumsKind::ReplaceWithUInt), + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: UInt<10> @[module-XXXXXXXXXX.rs 2:1] + input rhs: UInt<10> @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + when eq(bits(lhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(bits(lhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, eq(bits(bits(lhs, 9, 2), 7, 0), bits(bits(rhs, 9, 2), 7, 0)) @[module-XXXXXXXXXX.rs 5:1] + else when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else: + wire _array_literal_expr: UInt<1>[3] + wire _cast_bits_to_array_expr: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0] + connect _cast_bits_to_array_expr_flattened[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1] + connect _cast_bits_to_array_expr_flattened[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2] + wire _cast_bits_to_array_expr_1: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0] + connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1] + connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] + connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) + wire _cast_bits_to_array_expr_2: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] + connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] + connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] + wire _cast_bits_to_array_expr_3: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] + connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] + connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) + wire _cast_bits_to_array_expr_4: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] + connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] + connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] + wire _cast_bits_to_array_expr_5: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] + connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] + connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; +} + #[hdl_module(outline_generated)] pub fn check_struct_enum_match() { #[hdl] From 7e9d7739fba743927392ac9f5466af25ee09515f Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 1 May 2026 18:35:21 -0700 Subject: [PATCH 04/15] use #[hdl(cmp_eq)] for HdlOption and implement conversion <-> Option --- crates/fayalite/src/enum_.rs | 208 ++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 87 deletions(-) diff --git a/crates/fayalite/src/enum_.rs b/crates/fayalite/src/enum_.rs index d545f93..f6af578 100644 --- a/crates/fayalite/src/enum_.rs +++ b/crates/fayalite/src/enum_.rs @@ -2,7 +2,7 @@ // See Notices.txt for copyright information use crate::{ - expr::{Expr, HdlPartialEq, HdlPartialEqImpl, ToExpr, ValueType, ops::VariantAccess}, + expr::{Expr, ToExpr, ValueType, ops::VariantAccess}, hdl, int::{Bool, UIntValue}, intern::{Intern, Interned}, @@ -10,7 +10,7 @@ use crate::{ EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope, connect, enum_match_variants_helper, incomplete_wire, wire, }, - sim::value::SimValue, + sim::value::{SimValue, ToSimValue, ToSimValueWithType}, source_location::SourceLocation, ty::{ CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, OpaqueSimValueSize, @@ -21,7 +21,7 @@ use crate::{ }; use bitvec::{order::Lsb0, slice::BitSlice, view::BitView}; use serde::{Deserialize, Serialize}; -use std::{borrow::Cow, convert::Infallible, fmt, iter::FusedIterator, sync::Arc}; +use std::{convert::Infallible, fmt, iter::FusedIterator, sync::Arc}; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] pub struct EnumVariant { @@ -732,95 +732,12 @@ pub fn enum_type_to_sim_builder(v: T) -> T::SimBuilder { v.into() } -#[hdl] +#[hdl(cmp_eq)] pub enum HdlOption { HdlNone, HdlSome(T), } -impl, Rhs: Type> HdlPartialEqImpl> - for HdlOption -{ - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: HdlOption, - rhs_value: Cow<'_, as Type>::SimValue>, - ) -> bool { - type SimValueMatch = ::SimValue; - match (&*lhs_value, &*rhs_value) { - (SimValueMatch::::HdlNone(_), SimValueMatch::>::HdlNone(_)) => { - true - } - (SimValueMatch::::HdlSome(..), SimValueMatch::>::HdlNone(_)) - | (SimValueMatch::::HdlNone(_), SimValueMatch::>::HdlSome(..)) => { - false - } - ( - SimValueMatch::::HdlSome(l, _), - SimValueMatch::>::HdlSome(r, _), - ) => HdlPartialEqImpl::cmp_value_eq( - lhs.HdlSome, - Cow::Borrowed(&**l), - rhs.HdlSome, - Cow::Borrowed(&**r), - ), - } - } - - #[hdl] - fn cmp_expr_eq(lhs: Expr, rhs: Expr>) -> Expr { - #[hdl] - let cmp_eq = wire(); - #[hdl] - match lhs { - HdlSome(lhs) => - { - #[hdl] - match rhs { - HdlSome(rhs) => connect(cmp_eq, lhs.cmp_eq(rhs)), - HdlNone => connect(cmp_eq, false), - } - } - HdlNone => - { - #[hdl] - match rhs { - HdlSome(_) => connect(cmp_eq, false), - HdlNone => connect(cmp_eq, true), - } - } - } - cmp_eq - } - - #[hdl] - fn cmp_expr_ne(lhs: Expr, rhs: Expr>) -> Expr { - #[hdl] - let cmp_ne = wire(); - #[hdl] - match lhs { - HdlSome(lhs) => - { - #[hdl] - match rhs { - HdlSome(rhs) => connect(cmp_ne, lhs.cmp_ne(rhs)), - HdlNone => connect(cmp_ne, true), - } - } - HdlNone => - { - #[hdl] - match rhs { - HdlSome(_) => connect(cmp_ne, true), - HdlNone => connect(cmp_ne, false), - } - } - } - cmp_ne - } -} - #[allow(non_snake_case)] pub fn HdlNone() -> Expr> { HdlOption[T::TYPE].HdlNone() @@ -832,6 +749,123 @@ pub fn HdlSome(value: impl ToExpr) -> Expr> { HdlOption[value.ty()].HdlSome(value) } +impl From>> for Option> { + #[hdl] + fn from(value: SimValue>) -> Self { + #[hdl(sim)] + match value { + HdlSome(v) => Some(v), + HdlNone => None, + } + } +} + +impl<'a, T: Type> From<&'a SimValue>> for Option<&'a SimValue> { + #[hdl] + fn from(value: &'a SimValue>) -> Self { + #[hdl(sim)] + match value { + HdlSome(v) => Some(v), + HdlNone => None, + } + } +} + +impl<'a, T: Type> From<&'a mut SimValue>> for Option<&'a mut SimValue> { + #[hdl] + fn from(value: &'a mut SimValue>) -> Self { + #[hdl(sim)] + match value { + HdlSome(v) => Some(v), + HdlNone => None, + } + } +} + +impl>> ValueType for Option { + type Type = HdlOption; + type ValueCategory = T::ValueCategory; + + fn ty(&self) -> Self::Type { + StaticType::TYPE + } +} + +impl> ToSimValueWithType> for Option { + #[hdl] + fn to_sim_value_with_type(&self, ty: HdlOption) -> SimValue> { + match self { + Some(v) => + { + #[hdl(sim)] + ty.HdlSome(v) + } + None => + { + #[hdl(sim)] + ty.HdlNone() + } + } + } + #[hdl] + fn into_sim_value_with_type(self, ty: HdlOption) -> SimValue> { + match self { + Some(v) => + { + #[hdl(sim)] + ty.HdlSome(v) + } + None => + { + #[hdl(sim)] + ty.HdlNone() + } + } + } +} + +impl>> ToSimValue for Option { + #[hdl] + fn to_sim_value(&self) -> SimValue { + match self { + Some(v) => + { + #[hdl(sim)] + HdlSome(v) + } + None => + { + #[hdl(sim)] + HdlNone() + } + } + } + #[hdl] + fn into_sim_value(self) -> SimValue { + match self { + Some(v) => + { + #[hdl(sim)] + HdlSome(v) + } + None => + { + #[hdl(sim)] + HdlNone() + } + } + } +} + +impl>> ToExpr for Option { + fn to_expr(&self) -> Expr { + match self { + Some(v) => HdlSome(v), + None => HdlNone(), + } + } +} + impl HdlOption { #[track_caller] pub fn try_map( From 226631594458f4137739baf98d2a9cd2c257242e Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 3 May 2026 22:35:30 -0700 Subject: [PATCH 05/15] redo #[hdl(sim)] match/let destructuring to support matching values of type Type::SimValue --- .../src/module/transform_body/expand_match.rs | 16 +- .../hdl_let_statements/destructuring.rs | 41 +++- .../module_bodies/hdl_match_statements.rs | 42 +++- crates/fayalite/src/sim/value.rs | 200 +++++++++--------- 4 files changed, 183 insertions(+), 116 deletions(-) diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs index ca06c0b..605f662 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs @@ -1096,11 +1096,9 @@ impl Visitor<'_> { let (#(#bindings,)*) = { type __MatchTy = ::SimValue; let __match_value = #expr; - let __match_value = { - use ::fayalite::sim::value::match_sim_value::*; - // use method syntax to deduce the correct trait to call - ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value).__fayalite_match_sim_value() - }; + // use method syntax to deduce what type to convert to + let __match_value = ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value) + .__fayalite_match_sim_value(); #let_token #pat #eq_token __match_value #semi_token (#(#bindings_idents,)*) }; @@ -1172,11 +1170,9 @@ impl Visitor<'_> { { type __MatchTy = ::SimValue; let __match_value = #expr; - let __match_value = { - use ::fayalite::sim::value::match_sim_value::*; - // use method syntax to deduce the correct trait to call - ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value).__fayalite_match_sim_value() - }; + // use method syntax to deduce what type to convert to + let __match_value = ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value) + .__fayalite_match_sim_value(); #match_token __match_value { #(#arms)* } diff --git a/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs b/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs index 8d70d21..065e5de 100644 --- a/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs +++ b/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs @@ -95,7 +95,23 @@ //! } //! //! #[hdl] -//! fn destructure_to_sim_value<'a, T: Type>(v: impl ToSimValue>) { +//! fn destructure_inner(v: as Type>::SimValue) { +//! #[hdl(sim)] +//! let MyStruct:: { +//! a, +//! mut b, +//! c, +//! } = v; +//! +//! // that gives these types: +//! let _: SimValue> = a; +//! let _: SimValue = b; +//! let _: SimValue = c; +//! *b = false; // can modify b since mut was used +//! } +//! +//! #[hdl] +//! fn destructure_inner_ref<'a, T: Type>(v: &'a as Type>::SimValue) { //! #[hdl(sim)] //! let MyStruct:: { //! a, @@ -104,8 +120,25 @@ //! } = v; //! //! // that gives these types: -//! let _: SimValue> = a; -//! let _: SimValue = b; -//! let _: SimValue = c; +//! let _: &'a SimValue> = a; +//! let _: &'a SimValue = b; +//! let _: &'a SimValue = c; +//! } +//! +//! #[hdl] +//! fn destructure_inner_mut<'a, T: Type>(v: &'a mut as Type>::SimValue) { +//! #[hdl(sim)] +//! let MyStruct:: { +//! a, +//! b, +//! c, +//! } = v; +//! +//! **b = true; // you can modify v by modifying b which borrows from it +//! +//! // that gives these types: +//! let _: &'a mut SimValue> = a; +//! let _: &'a mut SimValue = b; +//! let _: &'a mut SimValue = c; //! } //! ``` diff --git a/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs b/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs index accd3d7..9e2d41d 100644 --- a/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs +++ b/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs @@ -72,15 +72,47 @@ //! } //! //! #[hdl] -//! fn match_to_sim_value<'a, T: Type>(v: impl ToSimValue>) { +//! fn match_inner_move(v: as Type>::SimValue) -> String { //! #[hdl(sim)] //! match v { -//! MyEnum::::A => println!("got A"), -//! MyEnum::::B(b) => { +//! MyEnum::::A => String::from("got A"), +//! MyEnum::::B(mut b) => { //! let _: SimValue = b; // b has this type -//! println!("got B({b})"); +//! let text = format!("got B({b})"); +//! *b = true; // can modify b since mut was used +//! text //! } -//! _ => println!("something else"), +//! _ => String::from("something else"), +//! } +//! } +//! +//! #[hdl] +//! fn match_inner_ref<'a, T: Type>(v: &'a as Type>::SimValue) -> u32 { +//! #[hdl(sim)] +//! match v { +//! MyEnum::::A => 1, +//! MyEnum::::B(b) => { +//! let _: &'a SimValue = b; // b has this type +//! println!("got B({b})"); +//! 5 +//! } +//! _ => 42, +//! } +//! } +//! +//! #[hdl] +//! fn match_inner_mut<'a, T: Type>(v: &'a mut as Type>::SimValue) -> Option<&'a mut SimValue> { +//! #[hdl(sim)] +//! match v { +//! MyEnum::::A => None, +//! MyEnum::::B(b) => { +//! println!("got B({b})"); +//! **b = true; // you can modify v by modifying b which borrows from it +//! let _: &'a mut SimValue = b; // b has this type +//! None +//! } +//! MyEnum::::C(v) => Some(v), // you can return matched values +//! _ => None, // HDL enums can have invalid discriminants, so we need this extra match arm //! } //! } //! ``` diff --git a/crates/fayalite/src/sim/value.rs b/crates/fayalite/src/sim/value.rs index a127878..eaa3f8d 100644 --- a/crates/fayalite/src/sim/value.rs +++ b/crates/fayalite/src/sim/value.rs @@ -552,113 +552,119 @@ impl_sim_value_cmp_as_bool!(AsyncReset); #[doc(hidden)] pub mod match_sim_value { - use crate::{ - sim::value::{SimValue, ToSimValue}, - ty::Type, - }; + use crate::{sim::value::SimValue, ty::Type}; + use std::ops::{Deref, DerefMut}; + + macro_rules! wrapper { + ( + $(pub struct $wrapper:ident<$T:ident>($inner:ty);)* + ) => { + $(#[doc(hidden)] + pub struct $wrapper<$T>($inner); + + impl<$T> $wrapper<$T> { + #[inline(always)] + pub fn new(value: $T) -> Self { + Self(<$inner>::new(value)) + } + } + + impl<$T> Deref for $wrapper<$T> { + type Target = $inner; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl<$T> DerefMut for $wrapper<$T> { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + })* + }; + } + + wrapper! { + pub struct MatchSimValueHelperCheckSimValue(MatchSimValueHelperCheckMutSimValue); + pub struct MatchSimValueHelperCheckMutSimValue(MatchSimValueHelperCheckRefSimValue); + pub struct MatchSimValueHelperCheckRefSimValue(MatchSimValueHelperCheckRefRefSimValue); + pub struct MatchSimValueHelperCheckRefRefSimValue(MatchSimValueHelperCheckRefMutSimValue); + pub struct MatchSimValueHelperCheckRefMutSimValue(MatchSimValueHelperCheckMutRefSimValue); + pub struct MatchSimValueHelperCheckMutRefSimValue(MatchSimValueHelperCheckMutMutSimValue); + pub struct MatchSimValueHelperCheckMutMutSimValue(MatchSimValueHelperIdentity); + } + + impl MatchSimValueHelperCheckSimValue> { + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> T::SimValue { + SimValue::into_value(self.take()) + } + } + + impl<'a, T: Type> MatchSimValueHelperCheckMutSimValue<&'a mut SimValue> { + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> &'a mut T::SimValue { + self.take() + } + } + + impl<'a, T: Type> MatchSimValueHelperCheckRefSimValue<&'a SimValue> { + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> &'a T::SimValue { + self.take() + } + } + + impl<'a, 'b, T: Type> MatchSimValueHelperCheckRefRefSimValue<&'a &'b SimValue> { + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> &'b T::SimValue { + self.take() + } + } + + impl<'a, 'b, T: Type> MatchSimValueHelperCheckRefMutSimValue<&'a &'b mut SimValue> { + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> &'a T::SimValue { + self.take() + } + } + + impl<'a, 'b, T: Type> MatchSimValueHelperCheckMutRefSimValue<&'a mut &'b SimValue> { + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> &'b T::SimValue { + self.take() + } + } + + impl<'a, 'b, T: Type> MatchSimValueHelperCheckMutMutSimValue<&'a mut &'b mut SimValue> { + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> &'a mut T::SimValue { + self.take() + } + } #[doc(hidden)] - pub struct MatchSimValueHelper(Option); + pub struct MatchSimValueHelperIdentity(Option); - impl MatchSimValueHelper { - pub fn new(v: T) -> Self { + impl MatchSimValueHelperIdentity { + fn new(v: T) -> Self { Self(Some(v)) } - } - - #[doc(hidden)] - pub trait MatchSimValue { - type MatchValue; - - /// use `self` so it comes first in the method resolution order - fn __fayalite_match_sim_value(self) -> Self::MatchValue - where - Self: Sized; - } - - impl MatchSimValue for MatchSimValueHelper> { - type MatchValue = T::SimValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - SimValue::into_value(self.0.expect("should be Some")) + #[inline(always)] + fn take(&mut self) -> T { + self.0.take().expect("known to be Some") } - } - - impl<'a, T: Type> MatchSimValue for MatchSimValueHelper<&'a SimValue> { - type MatchValue = &'a T::SimValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - SimValue::value(self.0.expect("should be Some")) - } - } - - impl<'a, T: Type> MatchSimValue for MatchSimValueHelper<&'a mut SimValue> { - type MatchValue = &'a mut T::SimValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - SimValue::value_mut(self.0.expect("should be Some")) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'_ &'a T> - where - MatchSimValueHelper<&'a T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| *v))) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'_ mut &'a T> - where - MatchSimValueHelper<&'a T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| *v))) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'a &'_ mut T> - where - MatchSimValueHelper<&'a T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| &**v))) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'a mut &'_ mut T> - where - MatchSimValueHelper<&'a mut T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| &mut **v))) + #[inline(always)] + pub fn __fayalite_match_sim_value(&mut self) -> T { + self.take() } } #[doc(hidden)] - pub trait MatchSimValueFallback { - type MatchValue; - - /// use `&mut self` so it comes later in the method resolution order than MatchSimValue - fn __fayalite_match_sim_value(&mut self) -> Self::MatchValue; - } - - impl MatchSimValueFallback for MatchSimValueHelper { - type MatchValue = ::SimValue; - - fn __fayalite_match_sim_value(&mut self) -> Self::MatchValue { - SimValue::into_value(self.0.take().expect("should be Some").into_sim_value()) - } - } + pub type MatchSimValueHelper = MatchSimValueHelperCheckSimValue; } pub trait ToSimValue: ToSimValueWithType<::Type> + ValueType { From 26224abe1c145d1744da89e08b7f9c64ee2ee2ce Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 5 May 2026 21:12:00 -0700 Subject: [PATCH 06/15] sim: properly update all VCD wires when they share simulation state --- crates/fayalite/src/sim.rs | 7 +- crates/fayalite/src/sim/interpreter.rs | 13 +- crates/fayalite/src/sim/interpreter/parts.rs | 37 +- crates/fayalite/tests/sim.rs | 144 ++++ .../fayalite/tests/sim/expected/array_rw.txt | 6 +- .../expected/conditional_assignment_last.txt | 4 +- .../tests/sim/expected/connect_const.txt | 2 +- .../sim/expected/connect_const_reset.txt | 6 +- .../tests/sim/expected/counter_async.txt | 20 +- .../tests/sim/expected/counter_sync.txt | 18 +- .../tests/sim/expected/duplicate_names.txt | 4 +- .../sim/expected/enum_with_simple_body.txt | 749 ++++++++++++++++++ .../sim/expected/enum_with_simple_body.vcd | 133 ++++ crates/fayalite/tests/sim/expected/enums.txt | 198 ++--- .../tests/sim/expected/last_connect.txt | 52 +- .../tests/sim/expected/many_memories.txt | 224 +++--- .../fayalite/tests/sim/expected/memories.txt | 32 +- .../fayalite/tests/sim/expected/memories2.txt | 62 +- .../fayalite/tests/sim/expected/memories3.txt | 124 +-- crates/fayalite/tests/sim/expected/mod1.txt | 10 +- .../tests/sim/expected/phantom_const.txt | 20 +- .../sim/expected/queue_1_false_false.txt | 136 ++-- .../tests/sim/expected/queue_1_false_true.txt | 132 +-- .../tests/sim/expected/queue_1_true_false.txt | 136 ++-- .../tests/sim/expected/queue_1_true_true.txt | 132 +-- .../sim/expected/queue_2_false_false.txt | 140 ++-- .../tests/sim/expected/queue_2_false_true.txt | 136 ++-- .../tests/sim/expected/queue_2_true_false.txt | 140 ++-- .../tests/sim/expected/queue_2_true_true.txt | 136 ++-- .../sim/expected/queue_3_false_false.txt | 144 ++-- .../tests/sim/expected/queue_3_false_true.txt | 140 ++-- .../tests/sim/expected/queue_3_true_false.txt | 144 ++-- .../tests/sim/expected/queue_3_true_true.txt | 140 ++-- .../sim/expected/queue_4_false_false.txt | 140 ++-- .../tests/sim/expected/queue_4_false_true.txt | 136 ++-- .../tests/sim/expected/queue_4_true_false.txt | 140 ++-- .../tests/sim/expected/queue_4_true_true.txt | 136 ++-- .../tests/sim/expected/ripple_counter.txt | 88 +- .../tests/sim/expected/shift_register.txt | 18 +- .../tests/sim/expected/sim_only_connects.txt | 18 +- .../tests/sim/expected/sim_read_past.txt | 90 +-- 41 files changed, 2666 insertions(+), 1621 deletions(-) create mode 100644 crates/fayalite/tests/sim/expected/enum_with_simple_body.txt create mode 100644 crates/fayalite/tests/sim/expected/enum_with_simple_body.vcd diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index b3e4cd6..4a7721b 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -2217,7 +2217,7 @@ impl SimulationImpl { | SimTraceKind::BigClock { index } => self .state .big_slots - .state_index_fetch_and_clear_maybe_modified_flag(index), + .state_index_fetch_maybe_modified_flag(index), SimTraceKind::SmallUInt { index, ty: _ } | SimTraceKind::SmallSInt { index, ty: _ } | SimTraceKind::SmallBool { index } @@ -2227,11 +2227,11 @@ impl SimulationImpl { | SimTraceKind::EnumDiscriminant { index, ty: _ } => self .state .small_slots - .state_index_fetch_and_clear_maybe_modified_flag(index), + .state_index_fetch_maybe_modified_flag(index), SimTraceKind::SimOnly { index, ty: _ } => self .state .sim_only_slots - .state_index_fetch_and_clear_maybe_modified_flag(index), + .state_index_fetch_maybe_modified_flag(index), SimTraceKind::PhantomConst { ty: _ } => IS_INITIAL_STEP, }; if !new_maybe_changed && !IS_INITIAL_STEP { @@ -2291,6 +2291,7 @@ impl SimulationImpl { last_state.clone_from(state); } } + self.state.clear_all_maybe_modified_flags(); } #[track_caller] fn advance_time(this_ref: &Rc>, duration: SimDuration) { diff --git a/crates/fayalite/src/sim/interpreter.rs b/crates/fayalite/src/sim/interpreter.rs index 0cf98d0..e16519b 100644 --- a/crates/fayalite/src/sim/interpreter.rs +++ b/crates/fayalite/src/sim/interpreter.rs @@ -914,11 +914,14 @@ impl StatePart { value: K::borrow_state(&mut self.value), } } - pub(crate) fn state_index_fetch_and_clear_maybe_modified_flag( - &mut self, + pub(crate) fn state_index_fetch_maybe_modified_flag( + &self, part_index: StatePartIndex, ) -> bool { - K::state_index_fetch_and_clear_maybe_modified_flag(&mut self.value, part_index) + K::state_index_fetch_maybe_modified_flag(&self.value, part_index) + } + pub(crate) fn clear_all_maybe_modified_flags(&mut self) { + K::clear_all_maybe_modified_flags(&mut self.value) } } @@ -1015,6 +1018,10 @@ macro_rules! make_state { $($type_plural_field: self.$type_plural_field.borrow(),)* } } + pub(crate) fn clear_all_maybe_modified_flags(&mut self) { + $(self.$state_plural_field.clear_all_maybe_modified_flags();)* + $(self.$type_plural_field.clear_all_maybe_modified_flags();)* + } } #[derive(Debug)] diff --git a/crates/fayalite/src/sim/interpreter/parts.rs b/crates/fayalite/src/sim/interpreter/parts.rs index d9e4214..308ac44 100644 --- a/crates/fayalite/src/sim/interpreter/parts.rs +++ b/crates/fayalite/src/sim/interpreter/parts.rs @@ -256,10 +256,11 @@ pub(crate) trait StatePartKind: state: &'a mut Self::State, part_index: StatePartIndex, ) -> &'a mut Self::StateElement; - fn state_index_fetch_and_clear_maybe_modified_flag( - state: &mut Self::State, + fn state_index_fetch_maybe_modified_flag( + state: &Self::State, part_index: StatePartIndex, ) -> bool; + fn clear_all_maybe_modified_flags(state: &mut Self::State); fn borrowed_state_index<'a, 'b>( state: &'a Self::BorrowedState<'b>, part_index: StatePartIndex, @@ -335,12 +336,13 @@ impl StatePartKind for StatePartKindMemories { ) -> &'a mut Self::StateElement { &mut state[part_index.as_usize()] } - fn state_index_fetch_and_clear_maybe_modified_flag( - _state: &mut Self::State, + fn state_index_fetch_maybe_modified_flag( + _state: &Self::State, _part_index: StatePartIndex, ) -> bool { true } + fn clear_all_maybe_modified_flags(_state: &mut Self::State) {} fn borrowed_state_index<'a, 'b>( state: &'a Self::BorrowedState<'b>, part_index: StatePartIndex, @@ -438,11 +440,14 @@ impl StatePartKind for StatePartKindSmallSlots { state.modified[part_index.as_usize()] = true; &mut state.state[part_index.as_usize()] } - fn state_index_fetch_and_clear_maybe_modified_flag( - state: &mut Self::State, + fn state_index_fetch_maybe_modified_flag( + state: &Self::State, part_index: StatePartIndex, ) -> bool { - std::mem::replace(&mut state.modified[part_index.as_usize()], false) + state.modified[part_index.as_usize()] + } + fn clear_all_maybe_modified_flags(state: &mut Self::State) { + state.modified.fill(false); } fn borrowed_state_index<'a, 'b>( state: &'a Self::BorrowedState<'b>, @@ -519,11 +524,14 @@ impl StatePartKind for StatePartKindBigSlots { state.modified[part_index.as_usize()] = true; &mut state.state[part_index.as_usize()] } - fn state_index_fetch_and_clear_maybe_modified_flag( - state: &mut Self::State, + fn state_index_fetch_maybe_modified_flag( + state: &Self::State, part_index: StatePartIndex, ) -> bool { - std::mem::replace(&mut state.modified[part_index.as_usize()], false) + state.modified[part_index.as_usize()] + } + fn clear_all_maybe_modified_flags(state: &mut Self::State) { + state.modified.fill(false); } fn borrowed_state_index<'a, 'b>( state: &'a Self::BorrowedState<'b>, @@ -600,11 +608,14 @@ impl StatePartKind for StatePartKindSimOnlySlots { state.modified[part_index.as_usize()] = true; &mut state.state[part_index.as_usize()] } - fn state_index_fetch_and_clear_maybe_modified_flag( - state: &mut Self::State, + fn state_index_fetch_maybe_modified_flag( + state: &Self::State, part_index: StatePartIndex, ) -> bool { - std::mem::replace(&mut state.modified[part_index.as_usize()], false) + state.modified[part_index.as_usize()] + } + fn clear_all_maybe_modified_flags(state: &mut Self::State) { + state.modified.fill(false); } fn borrowed_state_index<'a, 'b>( state: &'a Self::BorrowedState<'b>, diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index e57c064..53f7d9d 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -550,6 +550,150 @@ fn test_enums() { } } +#[hdl] +pub enum EnumWithSimpleBody { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), +} + +#[hdl_module(outline_generated)] +pub fn enum_with_simple_body() { + #[hdl] + let which_in: UInt<8> = m.input(); + #[hdl] + let data_in: UInt<8> = m.input(); + #[hdl] + let which_out: UInt<8> = m.output(); + #[hdl] + let data_out: UInt<8> = m.output(); + #[hdl] + let enum_out: EnumWithSimpleBody = m.output(); + + #[hdl] + if which_in.cmp_eq(0u8) { + connect(enum_out, EnumWithSimpleBody.A(data_in)); + } else if which_in.cmp_eq(1u8) { + connect(enum_out, EnumWithSimpleBody.B(data_in)); + } else { + connect(enum_out, EnumWithSimpleBody.C(data_in)); + } + + #[hdl] + match enum_out { + EnumWithSimpleBody::A(v) => { + connect(which_out, 0u8); + connect(data_out, v); + } + EnumWithSimpleBody::B(v) => { + connect(which_out, 1u8); + connect(data_out, v); + } + EnumWithSimpleBody::C(v) => { + connect(which_out, 2u8); + connect(data_out, v); + } + } +} + +#[hdl] +#[test] +fn test_enum_with_simple_body() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(enum_with_simple_body()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + for which in 0u8..=2 { + for data in (0..u8::MAX).step_by(45) { + sim.write(sim.io().which_in, which); + sim.write(sim.io().data_in, data); + sim.advance_time(SimDuration::from_micros(1)); + assert_eq!(sim.read(sim.io().which_out).as_int(), which); + assert_eq!(sim.read(sim.io().data_out).as_int(), data); + } + } + sim.flush_traces().unwrap(); + let vcd = String::from_utf8(writer.take()).unwrap(); + println!("####### VCD:\n{vcd}\n#######"); + #[derive(Debug)] + struct WireState<'a> { + name: &'a str, + space_then_id: Option<&'a str>, + value: Option<&'a str>, + } + impl<'a> WireState<'a> { + fn new(name: &'a str) -> Self { + Self { + name, + space_then_id: None, + value: None, + } + } + } + let mut variant_wires = [ + WireState::new("A"), + WireState::new("B"), + WireState::new("C"), + ]; + // check that output .vcd has the proper values for all variants' wires + for (is_last, line) in vcd.lines().map(|line| (false, line)).chain([(true, "")]) { + if let Some(line) = line.strip_prefix("$var wire 8") + && let Some(line) = line.strip_suffix(" $end") + && let Some((space_then_id, state)) = variant_wires + .iter_mut() + .find_map(|state| Some((line.strip_suffix(state.name)?.strip_suffix(" ")?, state))) + { + assert_eq!(space_then_id.chars().next(), Some(' ')); + assert!( + space_then_id + .chars() + .skip(1) + .all(|ch| matches!(ch, '!'..='~')) + ); + assert_eq!(state.space_then_id.replace(space_then_id), None); + } else if line.starts_with("#") || is_last { + let Some(expected_value) = variant_wires[0].value else { + panic!( + "variant {} hasn't been initialized before a timestamp or EOF: {variant_wires:#?}\n\ + line={line:?}", + variant_wires[0].name, + ); + }; + for state in &variant_wires { + assert_eq!( + state.value, + Some(expected_value), + "at a timestamp or EOF: variant value for {} doesn't match expected value.\n\ + {variant_wires:#?}\nline={line:?}", + state.name, + ); + } + } else if line.starts_with("b") { + for state in &mut variant_wires { + let Some(space_then_id) = state.space_then_id else { + let name = state.name; + panic!( + "variant {name} hasn't had an id assigned yet: {variant_wires:#?}\n\ + line={line:?}", + ); + }; + if let Some(value) = line.strip_suffix(space_then_id) { + state.value = Some(value); + break; + } + } + } + } + if vcd != include_str!("sim/expected/enum_with_simple_body.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/enum_with_simple_body.txt") { + panic!(); + } +} + #[hdl_module(outline_generated)] pub fn memories() { #[hdl] diff --git a/crates/fayalite/tests/sim/expected/array_rw.txt b/crates/fayalite/tests/sim/expected/array_rw.txt index 2486eaa..271ec3c 100644 --- a/crates/fayalite/tests/sim/expected/array_rw.txt +++ b/crates/fayalite/tests/sim/expected/array_rw.txt @@ -424,8 +424,8 @@ Simulation { }, small_slots: StatePart { value: [ - 16 (modified), - 0 (modified), + 16, + 0, ], }, big_slots: StatePart { @@ -483,7 +483,7 @@ Simulation { 248, 252, 254, - 255 (modified), + 255, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt index 0df7f20..74c03a4 100644 --- a/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt +++ b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt @@ -86,8 +86,8 @@ Simulation { value: [ 1, 0, - 1 (modified), - 0 (modified), + 1, + 0, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/connect_const.txt b/crates/fayalite/tests/sim/expected/connect_const.txt index 6cf4014..8193fc5 100644 --- a/crates/fayalite/tests/sim/expected/connect_const.txt +++ b/crates/fayalite/tests/sim/expected/connect_const.txt @@ -63,7 +63,7 @@ Simulation { big_slots: StatePart { value: [ 5, - 5 (modified), + 5, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/connect_const_reset.txt b/crates/fayalite/tests/sim/expected/connect_const_reset.txt index a75ff8a..5a64923 100644 --- a/crates/fayalite/tests/sim/expected/connect_const_reset.txt +++ b/crates/fayalite/tests/sim/expected/connect_const_reset.txt @@ -90,9 +90,9 @@ Simulation { value: [ 1, 1, - 1 (modified), - 1 (modified), - 1 (modified), + 1, + 1, + 1, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/counter_async.txt b/crates/fayalite/tests/sim/expected/counter_async.txt index 256e1b7..20d27ac 100644 --- a/crates/fayalite/tests/sim/expected/counter_async.txt +++ b/crates/fayalite/tests/sim/expected/counter_async.txt @@ -185,10 +185,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), + 0, + 0, + 1, + 0, ], }, big_slots: StatePart { @@ -197,12 +197,12 @@ Simulation { 0, 3, 3, - 4 (modified), - 3 (modified), - 0 (modified), - 1 (modified), - 4 (modified), - 4 (modified), + 4, + 3, + 0, + 1, + 4, + 4, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/counter_sync.txt b/crates/fayalite/tests/sim/expected/counter_sync.txt index 1448f58..baa08e7 100644 --- a/crates/fayalite/tests/sim/expected/counter_sync.txt +++ b/crates/fayalite/tests/sim/expected/counter_sync.txt @@ -167,10 +167,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), + 0, + 0, + 1, + 0, ], }, big_slots: StatePart { @@ -179,11 +179,11 @@ Simulation { 0, 3, 3, - 4 (modified), - 3 (modified), - 1 (modified), - 4 (modified), - 4 (modified), + 4, + 3, + 1, + 4, + 4, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/duplicate_names.txt b/crates/fayalite/tests/sim/expected/duplicate_names.txt index 394cfbb..76338e8 100644 --- a/crates/fayalite/tests/sim/expected/duplicate_names.txt +++ b/crates/fayalite/tests/sim/expected/duplicate_names.txt @@ -81,9 +81,9 @@ Simulation { big_slots: StatePart { value: [ 5, - 5 (modified), + 5, + 6, 6, - 6 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/enum_with_simple_body.txt b/crates/fayalite/tests/sim/expected/enum_with_simple_body.txt new file mode 100644 index 0000000..6b5af1c --- /dev/null +++ b/crates/fayalite/tests/sim/expected/enum_with_simple_body.txt @@ -0,0 +1,749 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + ty: Enum { + A, + B, + C, + }, + }, + ], + .. + }, + big_slots: StatePartLayout { + len: 33, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_in", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: ".0", + ty: UInt<2>, + }, + SlotDebugData { + name: ".1", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: ".0", + ty: UInt<2>, + }, + SlotDebugData { + name: ".1", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + }, + SlotDebugData { + name: ".0", + ty: UInt<2>, + }, + SlotDebugData { + name: ".1", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: UInt<10>, + }, + SlotDebugData { + name: "", + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + memories: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + insns: [ + // at: module-XXXXXXXXXX.rs:1:1 + 0: Const { + dest: StatePartIndex(32), // (0x2) SlotDebugData { name: "", ty: UInt<8> }, + value: 0x2, + }, + 1: Const { + dest: StatePartIndex(27), // (0x2) SlotDebugData { name: "", ty: UInt<2> }, + value: 0x2, + }, + 2: Copy { + dest: StatePartIndex(25), // (0x2) SlotDebugData { name: ".0", ty: UInt<2> }, + src: StatePartIndex(27), // (0x2) SlotDebugData { name: "", ty: UInt<2> }, + }, + 3: Copy { + dest: StatePartIndex(26), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> }, + src: StatePartIndex(1), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in", ty: UInt<8> }, + }, + 4: Shl { + dest: StatePartIndex(28), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + lhs: StatePartIndex(26), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> }, + rhs: 2, + }, + 5: Or { + dest: StatePartIndex(29), // (0x386) SlotDebugData { name: "", ty: UInt<10> }, + lhs: StatePartIndex(25), // (0x2) SlotDebugData { name: ".0", ty: UInt<2> }, + rhs: StatePartIndex(28), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + }, + 6: CastToUInt { + dest: StatePartIndex(30), // (0x386) SlotDebugData { name: "", ty: UInt<10> }, + src: StatePartIndex(29), // (0x386) SlotDebugData { name: "", ty: UInt<10> }, + dest_width: 10, + }, + 7: Copy { + dest: StatePartIndex(31), // (0x386) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + src: StatePartIndex(30), // (0x386) SlotDebugData { name: "", ty: UInt<10> }, + }, + 8: Const { + dest: StatePartIndex(20), // (0x1) SlotDebugData { name: "", ty: UInt<2> }, + value: 0x1, + }, + 9: Copy { + dest: StatePartIndex(18), // (0x1) SlotDebugData { name: ".0", ty: UInt<2> }, + src: StatePartIndex(20), // (0x1) SlotDebugData { name: "", ty: UInt<2> }, + }, + 10: Copy { + dest: StatePartIndex(19), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> }, + src: StatePartIndex(1), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in", ty: UInt<8> }, + }, + 11: Shl { + dest: StatePartIndex(21), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + lhs: StatePartIndex(19), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> }, + rhs: 2, + }, + 12: Or { + dest: StatePartIndex(22), // (0x385) SlotDebugData { name: "", ty: UInt<10> }, + lhs: StatePartIndex(18), // (0x1) SlotDebugData { name: ".0", ty: UInt<2> }, + rhs: StatePartIndex(21), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + }, + 13: CastToUInt { + dest: StatePartIndex(23), // (0x385) SlotDebugData { name: "", ty: UInt<10> }, + src: StatePartIndex(22), // (0x385) SlotDebugData { name: "", ty: UInt<10> }, + dest_width: 10, + }, + 14: Copy { + dest: StatePartIndex(24), // (0x385) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + src: StatePartIndex(23), // (0x385) SlotDebugData { name: "", ty: UInt<10> }, + }, + 15: Const { + dest: StatePartIndex(16), // (0x1) SlotDebugData { name: "", ty: UInt<8> }, + value: 0x1, + }, + 16: CmpEq { + dest: StatePartIndex(17), // (0x0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(0), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_in", ty: UInt<8> }, + rhs: StatePartIndex(16), // (0x1) SlotDebugData { name: "", ty: UInt<8> }, + }, + 17: Const { + dest: StatePartIndex(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, + value: 0x0, + }, + 18: Copy { + dest: StatePartIndex(9), // (0x0) SlotDebugData { name: ".0", ty: UInt<2> }, + src: StatePartIndex(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, + }, + 19: Copy { + dest: StatePartIndex(10), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> }, + src: StatePartIndex(1), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in", ty: UInt<8> }, + }, + 20: Shl { + dest: StatePartIndex(12), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + lhs: StatePartIndex(10), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> }, + rhs: 2, + }, + 21: Or { + dest: StatePartIndex(13), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + lhs: StatePartIndex(9), // (0x0) SlotDebugData { name: ".0", ty: UInt<2> }, + rhs: StatePartIndex(12), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + }, + 22: CastToUInt { + dest: StatePartIndex(14), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + src: StatePartIndex(13), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + dest_width: 10, + }, + 23: Copy { + dest: StatePartIndex(15), // (0x384) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + src: StatePartIndex(14), // (0x384) SlotDebugData { name: "", ty: UInt<10> }, + }, + 24: Const { + dest: StatePartIndex(7), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + value: 0x0, + }, + 25: CmpEq { + dest: StatePartIndex(8), // (0x0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(0), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_in", ty: UInt<8> }, + rhs: StatePartIndex(7), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:7:1 + 26: BranchIfZero { + target: 28, + value: StatePartIndex(8), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:8:1 + 27: Copy { + dest: StatePartIndex(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + src: StatePartIndex(15), // (0x384) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + }, + // at: module-XXXXXXXXXX.rs:7:1 + 28: BranchIfNonZero { + target: 33, + value: StatePartIndex(8), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:9:1 + 29: BranchIfZero { + target: 31, + value: StatePartIndex(17), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:10:1 + 30: Copy { + dest: StatePartIndex(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + src: StatePartIndex(24), // (0x385) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + }, + // at: module-XXXXXXXXXX.rs:9:1 + 31: BranchIfNonZero { + target: 33, + value: StatePartIndex(17), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:11:1 + 32: Copy { + dest: StatePartIndex(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + src: StatePartIndex(31), // (0x386) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 33: Copy { + dest: StatePartIndex(5), // (0x386) SlotDebugData { name: "", ty: UInt<10> }, + src: StatePartIndex(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + }, + 34: SliceInt { + dest: StatePartIndex(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> }, + src: StatePartIndex(5), // (0x386) SlotDebugData { name: "", ty: UInt<10> }, + start: 2, + len: 8, + }, + // at: module-XXXXXXXXXX.rs:6:1 + 35: AndBigWithSmallImmediate { + dest: StatePartIndex(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} }, + lhs: StatePartIndex(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} }, + rhs: 0x3, + }, + // at: module-XXXXXXXXXX.rs:12:1 + 36: BranchIfSmallNeImmediate { + target: 39, + lhs: StatePartIndex(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} }, + rhs: 0x0, + }, + // at: module-XXXXXXXXXX.rs:13:1 + 37: Copy { + dest: StatePartIndex(2), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out", ty: UInt<8> }, + src: StatePartIndex(7), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:14:1 + 38: Copy { + dest: StatePartIndex(3), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out", ty: UInt<8> }, + src: StatePartIndex(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:12:1 + 39: BranchIfSmallNeImmediate { + target: 42, + lhs: StatePartIndex(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} }, + rhs: 0x1, + }, + // at: module-XXXXXXXXXX.rs:15:1 + 40: Copy { + dest: StatePartIndex(2), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out", ty: UInt<8> }, + src: StatePartIndex(16), // (0x1) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:16:1 + 41: Copy { + dest: StatePartIndex(3), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out", ty: UInt<8> }, + src: StatePartIndex(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:12:1 + 42: BranchIfSmallNeImmediate { + target: 45, + lhs: StatePartIndex(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} }, + rhs: 0x2, + }, + // at: module-XXXXXXXXXX.rs:17:1 + 43: Copy { + dest: StatePartIndex(2), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out", ty: UInt<8> }, + src: StatePartIndex(32), // (0x2) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:18:1 + 44: Copy { + dest: StatePartIndex(3), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out", ty: UInt<8> }, + src: StatePartIndex(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 45: Return, + ], + .. + }, + pc: 45, + memory_write_log: [], + memories: StatePart { + value: [], + }, + small_slots: StatePart { + value: [ + 2, + ], + }, + big_slots: StatePart { + value: [ + 2, + 225, + 2 (modified), + 225 (modified), + 902, + 902, + 225, + 0, + 0, + 0, + 225, + 0, + 900, + 900, + 900, + 900, + 1, + 0, + 1, + 225, + 1, + 900, + 901, + 901, + 901, + 2, + 225, + 2, + 900, + 902, + 902, + 902, + 2, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }, + main_module: SimulationModuleState { + base_targets: [ + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.which_in, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.data_in, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.which_out, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.data_out, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.enum_out, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.data_in, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.data_out, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.enum_out, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.which_in, + Instance { + name: ::enum_with_simple_body, + instantiated: Module { + name: enum_with_simple_body, + .. + }, + }.which_out, + }, + did_initial_settle: true, + clocks_for_past: {}, + }, + extern_modules: [], + trace_decls: TraceModule { + name: "enum_with_simple_body", + children: [ + TraceModuleIO { + name: "which_in", + child: TraceUInt { + location: TraceScalarId(0), + name: "which_in", + ty: UInt<8>, + flow: Source, + }, + ty: UInt<8>, + flow: Source, + }, + TraceModuleIO { + name: "data_in", + child: TraceUInt { + location: TraceScalarId(1), + name: "data_in", + ty: UInt<8>, + flow: Source, + }, + ty: UInt<8>, + flow: Source, + }, + TraceModuleIO { + name: "which_out", + child: TraceUInt { + location: TraceScalarId(2), + name: "which_out", + ty: UInt<8>, + flow: Sink, + }, + ty: UInt<8>, + flow: Sink, + }, + TraceModuleIO { + name: "data_out", + child: TraceUInt { + location: TraceScalarId(3), + name: "data_out", + ty: UInt<8>, + flow: Sink, + }, + ty: UInt<8>, + flow: Sink, + }, + TraceModuleIO { + name: "enum_out", + child: TraceEnumWithFields { + name: "enum_out", + discriminant: TraceEnumDiscriminant { + location: TraceScalarId(4), + name: "$tag", + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + flow: Sink, + }, + non_empty_fields: [ + TraceUInt { + location: TraceScalarId(5), + name: "A", + ty: UInt<8>, + flow: Source, + }, + TraceUInt { + location: TraceScalarId(6), + name: "B", + ty: UInt<8>, + flow: Source, + }, + TraceUInt { + location: TraceScalarId(7), + name: "C", + ty: UInt<8>, + flow: Source, + }, + ], + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + flow: Sink, + }, + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + flow: Sink, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigUInt { + index: StatePartIndex(0), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0x02, + last_state: 0x02, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigUInt { + index: StatePartIndex(1), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0xe1, + last_state: 0xb4, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigUInt { + index: StatePartIndex(2), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0x02, + last_state: 0x02, + }, + SimTrace { + id: TraceScalarId(3), + kind: BigUInt { + index: StatePartIndex(3), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0xe1, + last_state: 0xb4, + }, + SimTrace { + id: TraceScalarId(4), + kind: EnumDiscriminant { + index: StatePartIndex(0), + ty: Enum { + A(UInt<8>), + B(UInt<8>), + C(UInt<8>), + }, + }, + maybe_changed: true, + state: 0x2, + last_state: 0x2, + }, + SimTrace { + id: TraceScalarId(5), + kind: BigUInt { + index: StatePartIndex(6), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0xe1, + last_state: 0xb4, + }, + SimTrace { + id: TraceScalarId(6), + kind: BigUInt { + index: StatePartIndex(6), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0xe1, + last_state: 0xb4, + }, + SimTrace { + id: TraceScalarId(7), + kind: BigUInt { + index: StatePartIndex(6), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0xe1, + last_state: 0xb4, + }, + ], + trace_memories: {}, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [], + event_queue: EventQueue(EventQueueData { + instant: 18 μs, + events: {}, + }), + waiting_sensitivity_sets_by_address: {}, + waiting_sensitivity_sets_by_compiled_value: {}, + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/enum_with_simple_body.vcd b/crates/fayalite/tests/sim/expected/enum_with_simple_body.vcd new file mode 100644 index 0000000..dfe0dc1 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/enum_with_simple_body.vcd @@ -0,0 +1,133 @@ +$timescale 1 ps $end +$scope module enum_with_simple_body $end +$var wire 8 J&-ne which_in $end +$var wire 8 \7mo/ data_in $end +$var wire 8 ,`>ir which_out $end +$var wire 8 0_gMP data_out $end +$scope struct enum_out $end +$var string 1 kFH/w \$tag $end +$var wire 8 |EI_= A $end +$var wire 8 !pRd4 B $end +$var wire 8 &RAbd C $end +$upscope $end +$upscope $end +$enddefinitions $end +$dumpvars +b0 J&-ne +b0 \7mo/ +b0 ,`>ir +b0 0_gMP +sA\x20(0) kFH/w +b0 |EI_= +b0 !pRd4 +b0 &RAbd +$end +#1000000 +b101101 \7mo/ +b101101 0_gMP +b101101 |EI_= +b101101 !pRd4 +b101101 &RAbd +#2000000 +b1011010 \7mo/ +b1011010 0_gMP +b1011010 |EI_= +b1011010 !pRd4 +b1011010 &RAbd +#3000000 +b10000111 \7mo/ +b10000111 0_gMP +b10000111 |EI_= +b10000111 !pRd4 +b10000111 &RAbd +#4000000 +b10110100 \7mo/ +b10110100 0_gMP +b10110100 |EI_= +b10110100 !pRd4 +b10110100 &RAbd +#5000000 +b11100001 \7mo/ +b11100001 0_gMP +b11100001 |EI_= +b11100001 !pRd4 +b11100001 &RAbd +#6000000 +b1 J&-ne +b0 \7mo/ +b1 ,`>ir +b0 0_gMP +sB\x20(1) kFH/w +b0 |EI_= +b0 !pRd4 +b0 &RAbd +#7000000 +b101101 \7mo/ +b101101 0_gMP +b101101 |EI_= +b101101 !pRd4 +b101101 &RAbd +#8000000 +b1011010 \7mo/ +b1011010 0_gMP +b1011010 |EI_= +b1011010 !pRd4 +b1011010 &RAbd +#9000000 +b10000111 \7mo/ +b10000111 0_gMP +b10000111 |EI_= +b10000111 !pRd4 +b10000111 &RAbd +#10000000 +b10110100 \7mo/ +b10110100 0_gMP +b10110100 |EI_= +b10110100 !pRd4 +b10110100 &RAbd +#11000000 +b11100001 \7mo/ +b11100001 0_gMP +b11100001 |EI_= +b11100001 !pRd4 +b11100001 &RAbd +#12000000 +b10 J&-ne +b0 \7mo/ +b10 ,`>ir +b0 0_gMP +sC\x20(2) kFH/w +b0 |EI_= +b0 !pRd4 +b0 &RAbd +#13000000 +b101101 \7mo/ +b101101 0_gMP +b101101 |EI_= +b101101 !pRd4 +b101101 &RAbd +#14000000 +b1011010 \7mo/ +b1011010 0_gMP +b1011010 |EI_= +b1011010 !pRd4 +b1011010 &RAbd +#15000000 +b10000111 \7mo/ +b10000111 0_gMP +b10000111 |EI_= +b10000111 !pRd4 +b10000111 &RAbd +#16000000 +b10110100 \7mo/ +b10110100 0_gMP +b10110100 |EI_= +b10110100 !pRd4 +b10110100 &RAbd +#17000000 +b11100001 \7mo/ +b11100001 0_gMP +b11100001 |EI_= +b11100001 !pRd4 +b11100001 &RAbd +#18000000 diff --git a/crates/fayalite/tests/sim/expected/enums.txt b/crates/fayalite/tests/sim/expected/enums.txt index 2b00f05..d2da2d9 100644 --- a/crates/fayalite/tests/sim/expected/enums.txt +++ b/crates/fayalite/tests/sim/expected/enums.txt @@ -1191,10 +1191,10 @@ Simulation { value: [ 0, 0, - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), + 0, + 0, + 1, + 0, 2, ], }, @@ -1207,110 +1207,110 @@ Simulation { 15, 2, 15, - 0 (modified), 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 62 (modified), - 62 (modified), - 0 (modified), - 0 (modified), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 62, + 62, + 0, + 0, + 1, + 1, + 62, + 3, + 1, 1, 1, - 62 (modified), - 3 (modified), - 1 (modified), - 1 (modified), - 1 (modified), 1, 1, -1, - 1 (modified), - 1 (modified), - 15 (modified), - 3 (modified), - 1 (modified), - 1 (modified), - 3 (modified), - -1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 2 (modified), - 3 (modified), - 12 (modified), - 13 (modified), - 13 (modified), - 13 (modified), - 2 (modified), - 1 (modified), - 1 (modified), - -1 (modified), - 2 (modified), - 1 (modified), - 1 (modified), - -1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 3 (modified), - -1 (modified), - 2 (modified), - 3 (modified), - 3 (modified), - 12 (modified), - 15 (modified), - 60 (modified), - 62 (modified), - 62 (modified), - 62 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 3 (modified), - 3 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 2 (modified), - 3 (modified), - 6 (modified), - 7 (modified), - 7 (modified), - 7 (modified), - 2 (modified), - 3 (modified), - 3 (modified), - 12 (modified), - 15 (modified), + 1, + 1, + 15, + 3, + 1, + 1, + 3, + -1, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 3, + 12, + 13, + 13, + 13, + 2, + 1, + 1, + -1, + 2, + 1, + 1, + -1, + 1, + 1, + 1, + 3, + -1, + 2, + 3, + 3, + 12, + 15, + 60, + 62, + 62, + 62, + 0, + 0, + 0, + 1, + 2, + 3, + 3, + 1, + 1, + 1, + 1, + 1, + 2, + 3, + 6, + 7, + 7, + 7, + 2, + 3, + 3, + 12, + 15, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/last_connect.txt b/crates/fayalite/tests/sim/expected/last_connect.txt index 297d395..c5d1341 100644 --- a/crates/fayalite/tests/sim/expected/last_connect.txt +++ b/crates/fayalite/tests/sim/expected/last_connect.txt @@ -418,39 +418,39 @@ Simulation { }, big_slots: StatePart { value: [ - 31 (modified), + 31, + 1, + 1, + 1, + 1, + 31, + 15, + 1, + 1, + 1, + 1, 1, 1, 1, 1, - 31 (modified), - 15 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 7 (modified), 7 (modified), + 7, 3, - 0 (modified), - 0 (modified), + 0, + 0, + 3, + 1, + 3, + 1, + 6, + 7, + 7, + 7, + 4, + 0, + 1, + 2, 3, - 1 (modified), - 3 (modified), - 1 (modified), - 6 (modified), - 7 (modified), - 7 (modified), - 7 (modified), - 4 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 3 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/many_memories.txt b/crates/fayalite/tests/sim/expected/many_memories.txt index 84d9162..0d1a6db 100644 --- a/crates/fayalite/tests/sim/expected/many_memories.txt +++ b/crates/fayalite/tests/sim/expected/many_memories.txt @@ -2910,102 +2910,102 @@ Simulation { }, small_slots: StatePart { value: [ - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 15 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 15, + 1, + 0, + 0, + 0, + 0, + 0, + 0, ], }, big_slots: StatePart { @@ -3091,8 +3091,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, 15, 1, 0, @@ -3102,8 +3102,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, 15, 1, 0, @@ -3113,8 +3113,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, 15, 1, 0, @@ -3124,8 +3124,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, 15, 1, 0, @@ -3135,8 +3135,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, 15, 1, 0, @@ -3146,8 +3146,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, 15, 1, 0, @@ -3157,8 +3157,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, 15, 1, 0, @@ -3168,8 +3168,8 @@ Simulation { 0, 0, 1, - 0 (modified), - 1 (modified), + 0, + 1, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/memories.txt b/crates/fayalite/tests/sim/expected/memories.txt index db5a2f3..c96da4f 100644 --- a/crates/fayalite/tests/sim/expected/memories.txt +++ b/crates/fayalite/tests/sim/expected/memories.txt @@ -522,18 +522,18 @@ Simulation { }, small_slots: StatePart { value: [ - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 2, + 1, + 0, + 0, + 0, + 2, + 2, + 0, ], }, big_slots: StatePart { @@ -562,10 +562,10 @@ Simulation { -32, 1, 1, - 208 (modified), - -32 (modified), - 1 (modified), - 1 (modified), + 208, + -32, + 1, + 1, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/memories2.txt b/crates/fayalite/tests/sim/expected/memories2.txt index 5a82b91..1f78fcf 100644 --- a/crates/fayalite/tests/sim/expected/memories2.txt +++ b/crates/fayalite/tests/sim/expected/memories2.txt @@ -545,15 +545,15 @@ Simulation { value: [ 0, 0, - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, ], }, big_slots: StatePart { @@ -568,32 +568,32 @@ Simulation { 0, 0, 0, - 0 (modified), 0, - 0 (modified), 0, - 0 (modified), - 0 (modified), 0, - 0 (modified), - 0 (modified), 0, - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/memories3.txt b/crates/fayalite/tests/sim/expected/memories3.txt index 7522430..75720a8 100644 --- a/crates/fayalite/tests/sim/expected/memories3.txt +++ b/crates/fayalite/tests/sim/expected/memories3.txt @@ -1356,20 +1356,20 @@ Simulation { }, small_slots: StatePart { value: [ - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, ], }, big_slots: StatePart { @@ -1415,22 +1415,6 @@ Simulation { 0, 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), 0, 0, 0, @@ -1450,38 +1434,54 @@ Simulation { 0, 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/mod1.txt b/crates/fayalite/tests/sim/expected/mod1.txt index 7f89a66..a1de89a 100644 --- a/crates/fayalite/tests/sim/expected/mod1.txt +++ b/crates/fayalite/tests/sim/expected/mod1.txt @@ -207,11 +207,11 @@ Simulation { -2, -2, 15, - -2 (modified), - 14 (modified), - 5 (modified), - 1 (modified), - 15 (modified), + -2, + 14, + 5, + 1, + 15, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/phantom_const.txt b/crates/fayalite/tests/sim/expected/phantom_const.txt index 864a4f7..c9adae4 100644 --- a/crates/fayalite/tests/sim/expected/phantom_const.txt +++ b/crates/fayalite/tests/sim/expected/phantom_const.txt @@ -185,11 +185,11 @@ Simulation { }, small_slots: StatePart { value: [ - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, ], }, big_slots: StatePart { @@ -197,11 +197,11 @@ Simulation { 0, 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 0, + 0, + 0, + 0, + 0, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_1_false_false.txt b/crates/fayalite/tests/sim/expected/queue_1_false_false.txt index 1ac0403..e349bbd 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_false_false.txt @@ -1098,35 +1098,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 51 (modified), + 51, 0, - 51 (modified), + 51, 25, - 51 (modified), + 51, 0, - 51 (modified), + 51, 25, 1, 0, @@ -1138,56 +1138,56 @@ Simulation { 0, 25, 1, - 25 (modified), - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 25, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 25 (modified), - 1 (modified), - 50 (modified), - 51 (modified), - 51 (modified), - 51 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 25, + 0, + 0, + 1, + 1, + 25, + 1, + 50, + 51, + 51, + 51, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_1_false_true.txt b/crates/fayalite/tests/sim/expected/queue_1_false_true.txt index 5b56068..3a31636 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_false_true.txt @@ -1079,35 +1079,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 63 (modified), + 63, 0, - 63 (modified), + 63, 31, - 63 (modified), + 63, 0, - 63 (modified), + 63, 31, 1, 0, @@ -1119,54 +1119,54 @@ Simulation { 0, 31, 1, - 31 (modified), - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 31, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 31 (modified), - 1 (modified), - 62 (modified), - 63 (modified), - 63 (modified), - 63 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 31, + 0, + 0, + 1, + 1, + 31, + 1, + 62, + 63, + 63, + 63, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_1_true_false.txt b/crates/fayalite/tests/sim/expected/queue_1_true_false.txt index 6076237..9dd3851 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_true_false.txt @@ -1108,35 +1108,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 63 (modified), + 63, 0, - 63 (modified), + 63, 31, - 63 (modified), + 63, 0, - 63 (modified), + 63, 31, 1, 0, @@ -1148,56 +1148,56 @@ Simulation { 0, 31, 1, - 31 (modified), - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 31, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 31 (modified), - 1 (modified), - 62 (modified), - 63 (modified), - 63 (modified), - 63 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 31, + 0, + 0, + 1, + 1, + 31, + 1, + 62, + 63, + 63, + 63, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_1_true_true.txt b/crates/fayalite/tests/sim/expected/queue_1_true_true.txt index 8fe32ad..5762f24 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_true_true.txt @@ -1089,35 +1089,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 71 (modified), + 71, 0, - 71 (modified), + 71, 35, - 71 (modified), + 71, 0, - 71 (modified), + 71, 35, 1, 0, @@ -1129,54 +1129,54 @@ Simulation { 0, 35, 1, - 35 (modified), - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 35, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 35 (modified), - 1 (modified), - 70 (modified), - 71 (modified), - 71 (modified), - 71 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 35, + 0, + 0, + 1, + 1, + 35, + 1, + 70, + 71, + 71, + 71, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_2_false_false.txt b/crates/fayalite/tests/sim/expected/queue_2_false_false.txt index 5a5c47d..c2cb51a 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_false_false.txt @@ -1114,35 +1114,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 71 (modified), + 71, 1, - 71 (modified), + 71, 35, - 71 (modified), + 71, 0, - 71 (modified), + 71, 35, 1, 1, @@ -1154,58 +1154,58 @@ Simulation { 0, 35, 1, - 35 (modified), - 1 (modified), - 0, - 1 (modified), - 0 (modified), - 1, - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1, - 0, - 0, - 0, - 0 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1 (modified), 35, - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 35 (modified), - 1 (modified), - 70 (modified), - 71 (modified), - 71 (modified), - 71 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 2 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 0 (modified), 1, - 3 (modified), - 1 (modified), - 1 (modified), + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 35, + 0, + 1, + 1, + 1, + 35, + 1, + 70, + 71, + 71, + 71, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 2, + 0, + 2, + 2, + 0, + 1, + 3, + 1, + 1, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_2_false_true.txt b/crates/fayalite/tests/sim/expected/queue_2_false_true.txt index 2d9ea3f..f229451 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_false_true.txt @@ -1095,35 +1095,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 77 (modified), + 77, 1, - 77 (modified), + 77, 38, - 77 (modified), + 77, 0, - 77 (modified), + 77, 38, 1, 0, @@ -1135,56 +1135,56 @@ Simulation { 0, 38, 1, - 38 (modified), - 1 (modified), - 1, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1, - 0, - 0, - 0, - 0 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1 (modified), 38, - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 38 (modified), - 1 (modified), - 76 (modified), - 77 (modified), - 77 (modified), - 77 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 2 (modified), - 2 (modified), - 0 (modified), 1, - 1 (modified), - 1 (modified), - 1 (modified), + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 38, + 0, + 1, + 1, + 1, + 38, + 1, + 76, + 77, + 77, + 77, + 1, + 1, + 1, + 0, + 0, + 2, + 0, + 0, + 1, + 1, + 2, + 2, + 0, + 1, + 1, + 1, + 1, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_2_true_false.txt b/crates/fayalite/tests/sim/expected/queue_2_true_false.txt index 3d16da2..e137316 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_true_false.txt @@ -1124,35 +1124,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 79 (modified), + 79, 0, - 79 (modified), + 79, 39, - 77 (modified), + 77, 0, - 77 (modified), + 77, 38, 2, 0, @@ -1164,58 +1164,58 @@ Simulation { 0, 39, 1, - 39 (modified), - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 39, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 38 (modified), - 1 (modified), - 76 (modified), - 77 (modified), - 77 (modified), - 77 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 2 (modified), - 2 (modified), - 0 (modified), + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 39, + 0, + 0, + 1, + 1, + 38, + 1, + 76, + 77, + 77, + 77, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 2, + 2, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_2_true_true.txt b/crates/fayalite/tests/sim/expected/queue_2_true_true.txt index 041e62d..5203027 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_true_true.txt @@ -1105,35 +1105,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 85 (modified), + 85, 0, - 85 (modified), + 85, 42, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 2, 1, @@ -1145,56 +1145,56 @@ Simulation { 0, 42, 1, - 42 (modified), - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 42, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 0 (modified), + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 42, + 0, + 0, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 0, + 1, + 1, + 0, + 0, + 2, + 0, + 1, + 2, + 0, + 2, + 2, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_3_false_false.txt b/crates/fayalite/tests/sim/expected/queue_3_false_false.txt index f9c68cc..f5641ce 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_false_false.txt @@ -1142,35 +1142,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 1, + 2, + 1, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 81 (modified), + 81, 1, - 81 (modified), + 81, 40, - 79 (modified), + 79, 0, - 79 (modified), + 79, 39, 2, 0, @@ -1182,59 +1182,59 @@ Simulation { 0, 40, 1, - 40 (modified), - 1 (modified), - 2, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1, - 0, - 0, - 0, - 0 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1 (modified), 40, - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 39 (modified), - 1 (modified), - 78 (modified), - 79 (modified), - 79 (modified), - 79 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 3 (modified), - 3 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 3 (modified), - 3 (modified), - 0 (modified), - 5 (modified), - 5 (modified), - 1 (modified), - 2 (modified), - 2 (modified), + 1, + 2, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 40, + 0, + 1, + 1, + 1, + 39, + 1, + 78, + 79, + 79, + 79, + 0, + 0, + 1, + 2, + 1, + 0, + 0, + 3, + 3, + 0, + 1, + 1, + 3, + 3, + 0, + 5, + 5, + 1, + 2, + 2, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_3_false_true.txt b/crates/fayalite/tests/sim/expected/queue_3_false_true.txt index 9b0a7ea..cde5489 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_false_true.txt @@ -1123,35 +1123,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 2, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 85 (modified), + 85, 1, - 85 (modified), + 85, 42, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 2, 2, @@ -1163,57 +1163,57 @@ Simulation { 0, 42, 1, - 42 (modified), - 1 (modified), - 1, - 2 (modified), - 0 (modified), - 2, - 2 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1, - 0, - 0, - 0, - 0 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1 (modified), 42, - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 1 (modified), - 2 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 1 (modified), - 3 (modified), - 3 (modified), - 3 (modified), - 3 (modified), - 1 (modified), - 4 (modified), - 2 (modified), - 2 (modified), - 7 (modified), - 3 (modified), + 1, + 1, + 2, + 0, + 2, + 2, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 42, + 0, + 1, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 1, + 2, + 0, + 0, + 0, + 2, + 2, + 1, + 3, + 3, + 3, + 3, + 1, + 4, + 2, + 2, + 7, + 3, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_3_true_false.txt b/crates/fayalite/tests/sim/expected/queue_3_true_false.txt index 1b486d6..d943150 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_true_false.txt @@ -1152,35 +1152,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 2, + 1, + 0, + 0, + 0, + 2, + 1, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 87 (modified), + 87, 0, - 87 (modified), + 87, 43, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 3, 2, @@ -1192,59 +1192,59 @@ Simulation { 0, 43, 1, - 43 (modified), - 1 (modified), - 2, - 2 (modified), - 0 (modified), - 2, - 2 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 43, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 3 (modified), - 3 (modified), - 1 (modified), - 3 (modified), - 3 (modified), - 3 (modified), - 3 (modified), - 0 (modified), - 5 (modified), - 3 (modified), - 3 (modified), - 0 (modified), - 0 (modified), + 1, + 2, + 2, + 0, + 2, + 2, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 43, + 0, + 0, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 0, + 0, + 0, + 2, + 1, + 0, + 0, + 3, + 3, + 1, + 3, + 3, + 3, + 3, + 0, + 5, + 3, + 3, + 0, + 0, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_3_true_true.txt b/crates/fayalite/tests/sim/expected/queue_3_true_true.txt index 730e7e5..4a0f664 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_true_true.txt @@ -1133,35 +1133,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 2 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 2, + 1, + 0, + 0, + 0, + 2, + 1, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 87 (modified), + 87, 0, - 87 (modified), + 87, 43, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 3, 2, @@ -1173,57 +1173,57 @@ Simulation { 0, 43, 1, - 43 (modified), - 1 (modified), - 2, - 2 (modified), - 0 (modified), - 2, - 2 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 43, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 0 (modified), - 2 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 3 (modified), - 3 (modified), - 1 (modified), - 3 (modified), - 3 (modified), - 3 (modified), - 3 (modified), - 0 (modified), - 5 (modified), - 3 (modified), - 3 (modified), - 0 (modified), - 0 (modified), + 1, + 2, + 2, + 0, + 2, + 2, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 43, + 0, + 0, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 0, + 2, + 1, + 0, + 0, + 3, + 3, + 1, + 3, + 3, + 3, + 3, + 0, + 5, + 3, + 3, + 0, + 0, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_4_false_false.txt b/crates/fayalite/tests/sim/expected/queue_4_false_false.txt index e549ced..4e0a067 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_false_false.txt @@ -1122,35 +1122,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 3 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 3, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 87 (modified), + 87, 1, - 87 (modified), + 87, 43, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 3, 1, @@ -1162,58 +1162,58 @@ Simulation { 0, 43, 1, - 43 (modified), - 1 (modified), - 0, - 1 (modified), - 0 (modified), - 1, - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1, - 0, - 0, - 0, - 0 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1 (modified), 43, - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 3 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 4 (modified), - 4 (modified), - 0 (modified), + 1, + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 43, + 0, + 1, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 0, + 0, + 1, + 3, + 0, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + 4, + 4, + 0, + 3, + 7, + 3, 3, - 7 (modified), - 3 (modified), - 3 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_4_false_true.txt b/crates/fayalite/tests/sim/expected/queue_4_false_true.txt index 9f1d05b..a374f44 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_false_true.txt @@ -1103,35 +1103,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 3 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 3, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 87 (modified), + 87, 1, - 87 (modified), + 87, 43, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 3, 1, @@ -1143,56 +1143,56 @@ Simulation { 0, 43, 1, - 43 (modified), - 1 (modified), - 0, - 1 (modified), - 0 (modified), - 1, - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1, - 0, - 0, - 0, - 0 (modified), - 0, - 0 (modified), - 0 (modified), - 0, - 0 (modified), - 1 (modified), 43, - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 1 (modified), - 3 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 4 (modified), - 4 (modified), - 0 (modified), + 1, + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 43, + 0, + 1, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 1, + 3, + 0, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + 4, + 4, + 0, + 3, + 7, + 3, 3, - 7 (modified), - 3 (modified), - 3 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_4_true_false.txt b/crates/fayalite/tests/sim/expected/queue_4_true_false.txt index b37a9cd..7d20f26 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_true_false.txt @@ -1132,35 +1132,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 89 (modified), + 89, 0, - 89 (modified), + 89, 44, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 4, 1, @@ -1172,58 +1172,58 @@ Simulation { 0, 44, 1, - 44 (modified), - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 44, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 3 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 4 (modified), - 4 (modified), - 0 (modified), + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 44, + 0, + 0, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 2, + 2, + 0, + 2, + 2, + 4, + 4, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/queue_4_true_true.txt b/crates/fayalite/tests/sim/expected/queue_4_true_true.txt index 051b203..a0ee509 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_true_true.txt @@ -1113,35 +1113,35 @@ Simulation { value: [ 1, 1, - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 0, + 0, ], }, big_slots: StatePart { value: [ 0, 0, - 89 (modified), + 89, 0, - 89 (modified), + 89, 44, - 83 (modified), + 83, 0, - 83 (modified), + 83, 41, 4, 1, @@ -1153,56 +1153,56 @@ Simulation { 0, 44, 1, - 44 (modified), - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 1, - 1 (modified), - 1, - 1 (modified), - 0 (modified), - 0, - 0, - 0, - 0, - 1, - 1 (modified), - 0, - 0 (modified), - 0 (modified), - 1, - 1 (modified), - 1 (modified), 44, - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 41 (modified), - 1 (modified), - 82 (modified), - 83 (modified), - 83 (modified), - 83 (modified), - 0 (modified), - 3 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 0 (modified), - 2 (modified), - 2 (modified), - 4 (modified), - 4 (modified), - 0 (modified), + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 44, + 0, + 0, + 1, + 1, + 41, + 1, + 82, + 83, + 83, + 83, + 0, + 3, + 0, + 0, + 0, + 2, + 2, + 0, + 2, + 2, + 4, + 4, + 0, + 0, + 0, + 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/ripple_counter.txt b/crates/fayalite/tests/sim/expected/ripple_counter.txt index 91bbffd..6562d4d 100644 --- a/crates/fayalite/tests/sim/expected/ripple_counter.txt +++ b/crates/fayalite/tests/sim/expected/ripple_counter.txt @@ -641,15 +641,15 @@ Simulation { }, small_slots: StatePart { value: [ - 0 (modified), - 0 (modified), - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), + 0, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 0, ], }, big_slots: StatePart { @@ -662,56 +662,56 @@ Simulation { 0, 0, 0, - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 0 (modified), 0, - 1 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, 0, 0, 0 (modified), 0, - 0 (modified), 0, - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), + 0, + 1, + 0, + 0, + 0, + 1, 0, 0, 0 (modified), 0, - 0 (modified), 0, - 1 (modified), - 0 (modified), - 0 (modified), - 0 (modified), - 1 (modified), + 0, + 1, + 0, + 0, + 0, + 1, 0, 0, 0 (modified), 0, - 0 (modified), + 0, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/shift_register.txt b/crates/fayalite/tests/sim/expected/shift_register.txt index cc9d95a..1eaa378 100644 --- a/crates/fayalite/tests/sim/expected/shift_register.txt +++ b/crates/fayalite/tests/sim/expected/shift_register.txt @@ -259,10 +259,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), + 0, + 0, + 1, + 0, ], }, big_slots: StatePart { @@ -272,14 +272,14 @@ Simulation { 0, 0, 0, - 0 (modified), - 0 (modified), 0, - 0 (modified), 0, - 0 (modified), 0, - 0 (modified), + 0, + 0, + 0, + 0, + 0, ], }, sim_only_slots: StatePart { diff --git a/crates/fayalite/tests/sim/expected/sim_only_connects.txt b/crates/fayalite/tests/sim/expected/sim_only_connects.txt index 3b90ca8..2ae2fbe 100644 --- a/crates/fayalite/tests/sim/expected/sim_only_connects.txt +++ b/crates/fayalite/tests/sim/expected/sim_only_connects.txt @@ -380,10 +380,10 @@ Simulation { }, small_slots: StatePart { value: [ - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), + 0, + 0, + 1, + 0, ], }, big_slots: StatePart { @@ -395,9 +395,9 @@ Simulation { 1 (modified), 0, 0, - 0 (modified), - 1 (modified), - 0 (modified), + 0, + 1, + 0, 1, 0, 1 (modified), @@ -443,8 +443,8 @@ Simulation { }, { "extra": "value", - } (modified), - {} (modified), + }, + {}, { "bar": "", "extra": "value", diff --git a/crates/fayalite/tests/sim/expected/sim_read_past.txt b/crates/fayalite/tests/sim/expected/sim_read_past.txt index 17156d0..f771434 100644 --- a/crates/fayalite/tests/sim/expected/sim_read_past.txt +++ b/crates/fayalite/tests/sim/expected/sim_read_past.txt @@ -517,15 +517,15 @@ Simulation { }, small_slots: StatePart { value: [ - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 0 (modified), + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, ], }, big_slots: StatePart { @@ -542,42 +542,42 @@ Simulation { 49 (modified), 49 (modified), 50 (modified), - 1 (modified), - 0 (modified), - 0 (modified), - 48 (modified), - 49 (modified), - 49 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 48 (modified), - 49 (modified), - 48 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 49 (modified), - 49 (modified), - 50 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 49 (modified), - 49 (modified), - 49 (modified), - 0 (modified), - 0 (modified), - 1 (modified), - 49 (modified), - 50 (modified), - 50 (modified), - 0 (modified), - 1 (modified), - 0 (modified), - 49 (modified), - 49 (modified), - 50 (modified), + 1, + 0, + 0, + 48, + 49, + 49, + 0, + 0, + 1, + 48, + 49, + 48, + 0, + 1, + 0, + 49, + 49, + 50, + 0, + 0, + 1, + 49, + 49, + 49, + 0, + 0, + 1, + 49, + 50, + 50, + 0, + 1, + 0, + 49, + 49, + 50, ], }, sim_only_slots: StatePart { From ea183eac8722a8ed1156420f9028364428c792ff Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 11 May 2026 22:44:54 -0700 Subject: [PATCH 07/15] add TraceAsString -- sim traces it as a string rather than all its internal fields --- crates/fayalite/src/expr.rs | 33 +- crates/fayalite/src/expr/ops.rs | 189 +- crates/fayalite/src/expr/target.rs | 58 +- crates/fayalite/src/firrtl.rs | 27 +- crates/fayalite/src/int.rs | 3 + crates/fayalite/src/memory.rs | 1 + crates/fayalite/src/module.rs | 97 +- .../src/module/transform/deduce_resets.rs | 177 +- .../src/module/transform/simplify_enums.rs | 43 +- .../src/module/transform/simplify_memories.rs | 39 +- crates/fayalite/src/module/transform/visit.rs | 7 +- crates/fayalite/src/sim.rs | 157 +- crates/fayalite/src/sim/compiler.rs | 217 +- crates/fayalite/src/sim/interpreter.rs | 17 +- crates/fayalite/src/sim/interpreter/parts.rs | 34 + crates/fayalite/src/sim/value.rs | 3 +- crates/fayalite/src/sim/vcd.rs | 63 +- crates/fayalite/src/ty.rs | 584 ++++- crates/fayalite/src/ty/serde_impls.rs | 24 +- crates/fayalite/src/util.rs | 1 + crates/fayalite/src/util/serde_by_id.rs | 234 ++ .../vendor/xilinx/yosys_nextpnr_prjxray.rs | 5 +- crates/fayalite/tests/sim.rs | 629 ++++- .../sim/expected/sim_trace_as_string.txt | 2254 +++++++++++++++++ .../sim/expected/sim_trace_as_string.vcd | 221 ++ .../ui/simvalue_is_not_internable.stderr | 6 +- crates/fayalite/visit_types.json | 47 +- 27 files changed, 5002 insertions(+), 168 deletions(-) create mode 100644 crates/fayalite/src/util/serde_by_id.rs create mode 100644 crates/fayalite/tests/sim/expected/sim_trace_as_string.txt create mode 100644 crates/fayalite/tests/sim/expected/sim_trace_as_string.vcd diff --git a/crates/fayalite/src/expr.rs b/crates/fayalite/src/expr.rs index 00a0cee..3309fb1 100644 --- a/crates/fayalite/src/expr.rs +++ b/crates/fayalite/src/expr.rs @@ -17,7 +17,7 @@ use crate::{ reg::Reg, reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset}, sim::value::{SimValue, ToSimValue, ToSimValueWithType}, - ty::{CanonicalType, OpaqueSimValue, StaticType, Type, TypeWithDeref}, + ty::{CanonicalType, OpaqueSimValue, StaticType, TraceAsString, Type, TypeWithDeref}, util::{ConstBool, ConstUsize}, wire::Wire, }; @@ -218,6 +218,8 @@ expr_enum! { SliceSInt(ops::SliceSInt), CastToBits(ops::CastToBits), CastBitsTo(ops::CastBitsTo), + AsTraceAsString(ops::AsTraceAsString), + TraceAsStringAsInner(ops::TraceAsStringAsInner), ModuleIO(ModuleIO), Instance(Instance), Wire(Wire), @@ -389,6 +391,35 @@ impl Expr { __flow: this.__flow, } } + #[track_caller] + pub fn as_trace_as_string(this: Self, ty: TraceAsString) -> Expr> { + assert_eq!(this.ty(), ty.inner_ty()); + ops::AsTraceAsString::new(Expr::canonical(this), ty).to_expr() + } +} + +impl Expr { + pub fn unwrap_transparent_types(mut this: Self) -> Expr { + loop { + match this.ty() { + CanonicalType::UInt(_) + | CanonicalType::SInt(_) + | CanonicalType::Bool(_) + | CanonicalType::Array(_) + | CanonicalType::Enum(_) + | CanonicalType::Bundle(_) + | CanonicalType::AsyncReset(_) + | CanonicalType::SyncReset(_) + | CanonicalType::Reset(_) + | CanonicalType::Clock(_) + | CanonicalType::PhantomConst(_) + | CanonicalType::DynSimOnly(_) => return this, + CanonicalType::TraceAsString(_) => { + this = *Expr::::from_canonical(this); + } + } + } + } } impl ToLiteralBits for Expr { diff --git a/crates/fayalite/src/expr/ops.rs b/crates/fayalite/src/expr/ops.rs index f4cfebd..22a0d99 100644 --- a/crates/fayalite/src/expr/ops.rs +++ b/crates/fayalite/src/expr/ops.rs @@ -11,8 +11,9 @@ use crate::{ HdlPartialEqImpl, HdlPartialOrd, HdlPartialOrdImpl, NotALiteralExpr, ReduceBitsImpl, ToExpr, ToLiteralBits, ToSimValueInner, ToValueless, ValueType, Valueless, target::{ - GetTarget, Target, TargetPathArrayElement, TargetPathBundleField, - TargetPathDynArrayElement, TargetPathElement, + GetTarget, Target, TargetPathArrayElement, TargetPathAsTraceAsString, + TargetPathBundleField, TargetPathDynArrayElement, TargetPathElement, + TargetPathTraceAsStringInner, }, value_category::ValueCategoryExpr, }, @@ -27,7 +28,7 @@ use crate::{ ToSyncReset, }, sim::value::{SimValue, ToSimValue}, - ty::{CanonicalType, StaticType, Type}, + ty::{CanonicalType, StaticType, TraceAsString, Type}, util::ConstUsize, }; use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView}; @@ -4694,3 +4695,185 @@ impl, A> FromIterator for Expr { This::expr_from_iter(iter) } } + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct AsTraceAsString { + inner: Expr, + ty: TraceAsString, + literal_bits: Result, NotALiteralExpr>, + target: Option>, +} + +impl fmt::Debug for AsTraceAsString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + inner, + ty: _, + literal_bits: _, + target: _, + } = self; + f.debug_struct("AsTraceAsString") + .field("inner", inner) + .finish_non_exhaustive() + } +} + +impl AsTraceAsString { + pub fn new(inner: Expr, ty: TraceAsString) -> Self { + assert_eq!(inner.ty(), ty.inner_ty().canonical()); + let literal_bits = inner.to_literal_bits(); + let target = inner.target().map(|base| { + Intern::intern_sized( + base.join(TargetPathElement::intern_sized( + TargetPathAsTraceAsString { + ty: ty.canonical_trace_as_string(), + } + .into(), + )), + ) + }); + Self { + inner, + ty, + literal_bits, + target, + } + } + pub fn inner(self) -> Expr { + self.inner + } +} + +impl GetTarget for AsTraceAsString { + fn target(&self) -> Option> { + self.target + } +} + +impl ToLiteralBits for AsTraceAsString { + fn to_literal_bits(&self) -> Result, NotALiteralExpr> { + self.literal_bits + } +} + +impl ValueType for AsTraceAsString { + type Type = TraceAsString; + type ValueCategory = ValueCategoryExpr; + + fn ty(&self) -> Self::Type { + self.ty + } +} + +impl ToExpr for AsTraceAsString { + fn to_expr(&self) -> Expr { + Expr { + __enum: ExprEnum::AsTraceAsString(AsTraceAsString { + inner: self.inner, + ty: self.ty.canonical_trace_as_string(), + literal_bits: self.literal_bits, + target: self.target, + }) + .intern(), + __ty: self.ty, + __flow: Expr::flow(self.inner), + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct TraceAsStringAsInner { + arg: Expr>, + ty: T, + literal_bits: Result, NotALiteralExpr>, + target: Option>, +} + +impl fmt::Debug for TraceAsStringAsInner { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + arg, + ty: _, + literal_bits: _, + target: _, + } = self; + f.debug_struct("TraceAsStringAsInner") + .field("arg", arg) + .finish_non_exhaustive() + } +} + +impl TraceAsStringAsInner { + pub fn from_arg_and_ty(arg: Expr>, ty: T) -> Self { + assert_eq!(arg.ty().inner_ty(), ty.canonical()); + let literal_bits = arg.to_literal_bits(); + let target = arg.target().map(|base| { + Intern::intern_sized(base.join(TargetPathElement::intern_sized( + TargetPathTraceAsStringInner {}.into(), + ))) + }); + Self { + arg, + ty, + literal_bits, + target, + } + } + pub fn new(arg: Expr>) -> Self { + Self::from_arg_and_ty( + Expr { + __enum: arg.__enum, + __ty: arg.__ty.canonical_trace_as_string(), + __flow: arg.__flow, + }, + arg.ty().inner_ty(), + ) + } + pub fn arg(self) -> Expr> { + self.arg + } + pub fn arg_typed(self) -> Expr> { + Expr { + __enum: self.arg.__enum, + __ty: TraceAsString::from_canonical_trace_as_string(self.arg.__ty), + __flow: self.arg.__flow, + } + } +} + +impl GetTarget for TraceAsStringAsInner { + fn target(&self) -> Option> { + self.target + } +} + +impl ToLiteralBits for TraceAsStringAsInner { + fn to_literal_bits(&self) -> Result, NotALiteralExpr> { + self.literal_bits + } +} + +impl ValueType for TraceAsStringAsInner { + type Type = T; + type ValueCategory = ValueCategoryExpr; + + fn ty(&self) -> Self::Type { + self.ty + } +} + +impl ToExpr for TraceAsStringAsInner { + fn to_expr(&self) -> Expr { + Expr { + __enum: ExprEnum::TraceAsStringAsInner(TraceAsStringAsInner { + arg: self.arg, + ty: self.ty.canonical(), + literal_bits: self.literal_bits, + target: self.target, + }) + .intern(), + __ty: self.ty, + __flow: Expr::flow(self.arg), + } + } +} diff --git a/crates/fayalite/src/expr/target.rs b/crates/fayalite/src/expr/target.rs index 95d8e0f..5140719 100644 --- a/crates/fayalite/src/expr/target.rs +++ b/crates/fayalite/src/expr/target.rs @@ -10,7 +10,7 @@ use crate::{ reg::Reg, reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset}, source_location::SourceLocation, - ty::{CanonicalType, Type}, + ty::{CanonicalType, TraceAsString, Type}, wire::Wire, }; use std::fmt; @@ -46,11 +46,33 @@ impl fmt::Display for TargetPathDynArrayElement { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct TargetPathTraceAsStringInner {} + +impl fmt::Display for TargetPathTraceAsStringInner { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, ".") + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct TargetPathAsTraceAsString { + pub ty: TraceAsString, +} + +impl fmt::Display for TargetPathAsTraceAsString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, ".as_trace_as_string(...)") + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TargetPathElement { BundleField(TargetPathBundleField), ArrayElement(TargetPathArrayElement), DynArrayElement(TargetPathDynArrayElement), + TraceAsStringInner(TargetPathTraceAsStringInner), + AsTraceAsString(TargetPathAsTraceAsString), } impl From for TargetPathElement { @@ -71,12 +93,26 @@ impl From for TargetPathElement { } } +impl From for TargetPathElement { + fn from(value: TargetPathTraceAsStringInner) -> Self { + Self::TraceAsStringInner(value) + } +} + +impl From for TargetPathElement { + fn from(value: TargetPathAsTraceAsString) -> Self { + Self::AsTraceAsString(value) + } +} + impl fmt::Display for TargetPathElement { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::BundleField(v) => v.fmt(f), Self::ArrayElement(v) => v.fmt(f), Self::DynArrayElement(v) => v.fmt(f), + Self::TraceAsStringInner(v) => v.fmt(f), + Self::AsTraceAsString(v) => v.fmt(f), } } } @@ -100,6 +136,15 @@ impl TargetPathElement { let parent_ty = Array::::from_canonical(parent.canonical_ty()); parent_ty.element() } + Self::TraceAsStringInner(_) => { + let parent_ty = + TraceAsString::::from_canonical(parent.canonical_ty()); + parent_ty.inner_ty() + } + &Self::AsTraceAsString(TargetPathAsTraceAsString { ty }) => { + assert_eq!(parent.canonical_ty(), ty.inner_ty()); + ty.canonical() + } } } pub fn flow(&self, parent: Interned) -> Flow { @@ -111,13 +156,18 @@ impl TargetPathElement { .expect("field name is known to be a valid field of parent type"); parent.flow().flip_if(field.flipped) } - Self::ArrayElement(_) => parent.flow(), - Self::DynArrayElement(_) => parent.flow(), + Self::ArrayElement(_) + | Self::DynArrayElement(_) + | Self::TraceAsStringInner(_) + | Self::AsTraceAsString(_) => parent.flow(), } } pub fn is_static(&self) -> bool { match self { - Self::BundleField(_) | Self::ArrayElement(_) => true, + Self::BundleField(_) + | Self::ArrayElement(_) + | Self::TraceAsStringInner(_) + | Self::AsTraceAsString(_) => true, Self::DynArrayElement(_) => false, } } diff --git a/crates/fayalite/src/firrtl.rs b/crates/fayalite/src/firrtl.rs index 383bd95..23aeb2e 100644 --- a/crates/fayalite/src/firrtl.rs +++ b/crates/fayalite/src/firrtl.rs @@ -16,6 +16,7 @@ use crate::{ ops::{self, VariantAccess}, target::{ Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement, + TargetPathTraceAsStringInner, }, }, formal::FormalKind, @@ -471,7 +472,7 @@ impl TypeState { Ok(self.enum_def(ty)?.1.variants.borrow_mut().get(name)) } fn ty(&self, ty: T) -> Result { - Ok(match ty.canonical() { + Ok(match ty.canonical().unwrap_transparent_types() { CanonicalType::Bundle(ty) => self.bundle_ty(ty)?.to_string(), CanonicalType::Enum(ty) => self.enum_ty(ty)?.to_string(), CanonicalType::Array(ty) => { @@ -490,6 +491,7 @@ impl TypeState { CanonicalType::DynSimOnly(_) => { return Err(FirrtlError::SimOnlyValuesAreNotPermitted); } + CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"), }) } } @@ -1191,7 +1193,7 @@ impl<'a> Exporter<'a> { definitions: &RcDefinitions, extra_indent: Indent<'_>, ) -> Result { - match ty { + match ty.unwrap_transparent_types() { CanonicalType::Bundle(ty) => { self.expr_cast_bundle_to_bits(value_str, ty, definitions, extra_indent) } @@ -1210,6 +1212,7 @@ impl<'a> Exporter<'a> { | CanonicalType::Reset(_) => Ok(format!("asUInt({value_str})")), CanonicalType::PhantomConst(_) => Ok("UInt<0>(0)".into()), CanonicalType::DynSimOnly(_) => Err(FirrtlError::SimOnlyValuesAreNotPermitted.into()), + CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"), } } fn expr_cast_bits_to_bundle( @@ -1407,7 +1410,7 @@ impl<'a> Exporter<'a> { definitions: &RcDefinitions, extra_indent: Indent<'_>, ) -> Result { - match ty { + match ty.unwrap_transparent_types() { CanonicalType::Bundle(ty) => { self.expr_cast_bits_to_bundle(value_str, ty, definitions, extra_indent) } @@ -1431,6 +1434,7 @@ impl<'a> Exporter<'a> { return Ok(retval.to_string()); } CanonicalType::DynSimOnly(_) => Err(FirrtlError::SimOnlyValuesAreNotPermitted.into()), + CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"), } } fn expr_unary( @@ -1798,6 +1802,10 @@ impl<'a> Exporter<'a> { write!(out, "[{index}]").unwrap(); Ok(out) } + ExprEnum::AsTraceAsString(expr) => self.expr(expr.inner(), definitions, const_ty), + ExprEnum::TraceAsStringAsInner(expr) => { + self.expr(Expr::canonical(expr.arg()), definitions, const_ty) + } ExprEnum::ModuleIO(expr) => Ok(self.module.ns.get(expr.name_id()).to_string()), ExprEnum::Instance(expr) => { assert!(!const_ty, "not a constant"); @@ -1957,6 +1965,10 @@ impl<'a> Exporter<'a> { .segments .push(AnnotationTargetRefSegment::Index { index }), TargetPathElement::DynArrayElement(_) => unreachable!(), + TargetPathElement::AsTraceAsString(_) + | TargetPathElement::TraceAsStringInner(_) => { + // ignored + } } Ok(retval) } @@ -3211,6 +3223,8 @@ impl ScalarizeTreeNode { TargetPathElement::DynArrayElement(_) => { unreachable!("annotations are only on static targets"); } + TargetPathElement::AsTraceAsString(_) + | TargetPathElement::TraceAsStringInner(_) => parent, } } } @@ -3337,6 +3351,13 @@ impl ScalarizeTreeBuilder { CanonicalType::DynSimOnly(_) => { return Err(ScalarizedModuleABIError::SimOnlyValuesAreNotPermitted); } + CanonicalType::TraceAsString(_) => self.build( + target + .join(TargetPathElement::intern_sized( + TargetPathTraceAsStringInner {}.into(), + )) + .intern_sized(), + )?, }) } } diff --git a/crates/fayalite/src/int.rs b/crates/fayalite/src/int.rs index ff20933..15f8ed1 100644 --- a/crates/fayalite/src/int.rs +++ b/crates/fayalite/src/int.rs @@ -1277,6 +1277,9 @@ macro_rules! impl_int { pub fn bitvec_mut(&mut self) -> &mut BitVec { Arc::make_mut(&mut self.bits) } + pub fn arc_bitvec_mut(&mut self) -> &mut Arc { + &mut self.bits + } } }; } diff --git a/crates/fayalite/src/memory.rs b/crates/fayalite/src/memory.rs index 83e7437..b3af13c 100644 --- a/crates/fayalite/src/memory.rs +++ b/crates/fayalite/src/memory.rs @@ -1093,6 +1093,7 @@ pub fn splat_mask(ty: T, value: Expr) -> Expr> { .to_expr(), )), CanonicalType::PhantomConst(_) => Expr::from_canonical(Expr::canonical(().to_expr())), + CanonicalType::TraceAsString(ty) => Expr::from_canonical(splat_mask(ty.inner_ty(), value)), } } diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index d959182..f39f800 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -12,7 +12,7 @@ use crate::{ ops::VariantAccess, target::{ GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, - TargetPathElement, + TargetPathElement, TargetPathTraceAsStringInner, }, value_category::ValueCategoryExpr, }, @@ -1111,7 +1111,10 @@ fn validate_clock_for_past( let mut target = clock_for_past; while let Target::Child(child) = target { match *child.path_element() { - TargetPathElement::BundleField(_) | TargetPathElement::ArrayElement(_) => {} + TargetPathElement::BundleField(_) + | TargetPathElement::ArrayElement(_) + | TargetPathElement::AsTraceAsString(_) + | TargetPathElement::TraceAsStringInner(_) => {} TargetPathElement::DynArrayElement(_) => { panic!( "clock_for_past: clock must be a static target (you can't use `Expr` array indexes):\n{clock_for_past:?}" @@ -1586,6 +1589,14 @@ impl TargetState { declared_in_block, written_in_blocks: RefCell::default(), }, + CanonicalType::TraceAsString(_) => { + return Self::new( + target + .join(Intern::intern_sized(TargetPathTraceAsStringInner {}.into())) + .intern_sized(), + declared_in_block, + ); + } }, } } @@ -1605,44 +1616,58 @@ impl AssertValidityState { } fn get_target_states<'a>( &'a self, - target: &Target, + mut target: &Target, process_target_state: &dyn Fn(&'a TargetState, bool), ) -> Result<(), ()> { - match target { - Target::Base(target_base) => { - let target_state = self.get_base_state(*target_base)?; - process_target_state(target_state, false); - Ok(()) - } - Target::Child(target_child) => self.get_target_states( - &target_child.parent(), - &|target_state, exact_target_unknown| { - let TargetStateInner::Decomposed { subtargets } = &target_state.inner else { - unreachable!( - "TargetState::new makes TargetState tree match the Target type" - ); - }; - match *target_child.path_element() { - TargetPathElement::BundleField(_) => process_target_state( - subtargets - .get(&target_child.path_element()) - .expect("bundle fields filled in by TargetState::new"), - exact_target_unknown, - ), - TargetPathElement::ArrayElement(_) => process_target_state( - subtargets - .get(&target_child.path_element()) - .expect("array elements filled in by TargetState::new"), - exact_target_unknown, - ), - TargetPathElement::DynArrayElement(_) => { - for target_state in subtargets.values() { - process_target_state(target_state, true); + loop { + break match target { + Target::Base(target_base) => { + let target_state = self.get_base_state(*target_base)?; + process_target_state(target_state, false); + Ok(()) + } + Target::Child(target_child) => match *target_child.path_element() { + TargetPathElement::BundleField(_) + | TargetPathElement::ArrayElement(_) + | TargetPathElement::DynArrayElement(_) => self.get_target_states( + &target_child.parent(), + &|target_state, exact_target_unknown| { + let TargetStateInner::Decomposed { subtargets } = &target_state.inner + else { + unreachable!( + "TargetState::new makes TargetState tree match the Target type" + ); + }; + match *target_child.path_element() { + TargetPathElement::BundleField(_) => process_target_state( + subtargets + .get(&target_child.path_element()) + .expect("bundle fields filled in by TargetState::new"), + exact_target_unknown, + ), + TargetPathElement::ArrayElement(_) => process_target_state( + subtargets + .get(&target_child.path_element()) + .expect("array elements filled in by TargetState::new"), + exact_target_unknown, + ), + TargetPathElement::DynArrayElement(_) => { + for target_state in subtargets.values() { + process_target_state(target_state, true); + } + } + TargetPathElement::TraceAsStringInner(_) + | TargetPathElement::AsTraceAsString(_) => unreachable!(), } - } + }, + ), + TargetPathElement::TraceAsStringInner(_) + | TargetPathElement::AsTraceAsString(_) => { + target = Interned::into_inner(target_child.parent()); + continue; } }, - ), + }; } } fn get_base_state(&self, target_base: Interned) -> Result<&TargetState, ()> { @@ -1716,6 +1741,8 @@ impl AssertValidityState { TargetPathElement::DynArrayElement { .. } => { Self::set_connect_target_written(sub_target_state, is_lhs, block, true); } + TargetPathElement::TraceAsStringInner(_) + | TargetPathElement::AsTraceAsString(_) => unreachable!("never added"), } } } diff --git a/crates/fayalite/src/module/transform/deduce_resets.rs b/crates/fayalite/src/module/transform/deduce_resets.rs index 61167fd..ef95c1c 100644 --- a/crates/fayalite/src/module/transform/deduce_resets.rs +++ b/crates/fayalite/src/module/transform/deduce_resets.rs @@ -9,8 +9,9 @@ use crate::{ ExprEnum, ValueType, ops::{self, ArrayLiteral}, target::{ - Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField, - TargetPathDynArrayElement, TargetPathElement, + Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathAsTraceAsString, + TargetPathBundleField, TargetPathDynArrayElement, TargetPathElement, + TargetPathTraceAsStringInner, }, }, formal::FormalKind, @@ -26,6 +27,7 @@ use crate::{ prelude::*, reset::{ResetType, ResetTypeDispatch}, sim::ExternModuleSimulation, + ty::TraceAsString, util::{HashMap, HashSet}, }; use hashbrown::hash_map::Entry; @@ -103,6 +105,10 @@ enum ResetsLayout { element: Interned, reset_count: usize, }, + Transparent { + inner: Interned, + reset_count: usize, + }, } impl ResetsLayout { @@ -112,7 +118,8 @@ impl ResetsLayout { ResetsLayout::Reset | ResetsLayout::SyncReset | ResetsLayout::AsyncReset => 1, ResetsLayout::Bundle { reset_count, .. } | ResetsLayout::Enum { reset_count, .. } - | ResetsLayout::Array { reset_count, .. } => reset_count, + | ResetsLayout::Array { reset_count, .. } + | ResetsLayout::Transparent { reset_count, .. } => reset_count, } } fn new(ty: CanonicalType) -> Self { @@ -166,6 +173,13 @@ impl ResetsLayout { CanonicalType::Clock(_) => ResetsLayout::NoResets, CanonicalType::PhantomConst(_) => ResetsLayout::NoResets, CanonicalType::DynSimOnly(_) => ResetsLayout::NoResets, + CanonicalType::TraceAsString(ty) => { + let inner = ResetsLayout::new(ty.inner_ty()).intern_sized(); + ResetsLayout::Transparent { + inner, + reset_count: inner.reset_count(), + } + } } } } @@ -315,6 +329,12 @@ impl ResetGraph { } => { self.append_new_nodes_for_layout(*element, node_indexes, source_location); } + ResetsLayout::Transparent { + inner, + reset_count: _, + } => { + self.append_new_nodes_for_layout(*inner, node_indexes, source_location); + } } } } @@ -357,6 +377,21 @@ impl Resets { node_indexes: self.node_indexes, } } + fn trace_as_string_inner(self) -> Self { + let trace_as_string = TraceAsString::from_canonical(self.ty); + let ResetsLayout::Transparent { + inner, + reset_count: _, + } = self.layout + else { + unreachable!(); + }; + Self { + ty: trace_as_string.inner_ty(), + layout: *inner, + node_indexes: self.node_indexes, + } + } fn bundle_fields(self) -> impl Iterator { let bundle = Bundle::from_canonical(self.ty); let ResetsLayout::Bundle { @@ -480,6 +515,17 @@ impl Resets { CanonicalType::SyncReset(SyncReset) }, ), + CanonicalType::TraceAsString(ty) => Ok(CanonicalType::TraceAsString( + ty.with_new_inner_ty( + self.array_elements() + .substituted_type( + reset_graph, + fallback_to_sync_reset, + fallback_error_source_location, + )? + .intern_sized(), + ), + )), } } } @@ -1013,7 +1059,8 @@ fn cast_bit_op( | CanonicalType::Bundle(_) | CanonicalType::Reset(_) | CanonicalType::PhantomConst(_) - | CanonicalType::DynSimOnly(_) => unreachable!(), + | CanonicalType::DynSimOnly(_) + | CanonicalType::TraceAsString(_) => unreachable!(), $(CanonicalType::$Variant(ty) => Expr::expr_enum($arg.cast_to(ty)),)* } }; @@ -1024,7 +1071,8 @@ fn cast_bit_op( CanonicalType::Array(_) | CanonicalType::Enum(_) | CanonicalType::Bundle(_) - | CanonicalType::Reset(_) => unreachable!(), + | CanonicalType::Reset(_) + | CanonicalType::TraceAsString(_) => unreachable!(), CanonicalType::PhantomConst(_) | CanonicalType::DynSimOnly(_) => Expr::expr_enum(arg), $(CanonicalType::$Variant(_) => { @@ -1156,6 +1204,10 @@ impl RunPass

for ExprEnum { ExprEnum::SliceSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::CastToBits(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::CastBitsTo(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), + ExprEnum::TraceAsStringAsInner(expr) => { + Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)) + } + ExprEnum::AsTraceAsString(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::ModuleIO(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::Instance(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::Wire(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), @@ -1536,6 +1588,67 @@ impl RunPassExpr for ops::CastBitsTo { } } +impl RunPassExpr for ops::TraceAsStringAsInner { + type Args<'a> = [Expr; 1]; + + fn args<'a>(&'a self) -> Self::Args<'a> { + [Expr::canonical(self.arg())] + } + + fn source_location(&self) -> Option { + None + } + + fn union_parts( + &self, + resets: Resets, + args_resets: Vec, + mut pass_args: PassArgs<'_, BuildResetGraph>, + ) -> Result<(), DeduceResetsError> { + pass_args.union(resets, args_resets[0].trace_as_string_inner(), None) + } + + fn new( + &self, + _ty: CanonicalType, + new_args: Vec>, + ) -> Result { + Ok(Self::new(Expr::from_canonical(new_args[0]))) + } +} + +impl RunPassExpr for ops::AsTraceAsString { + type Args<'a> = [Expr; 1]; + + fn args<'a>(&'a self) -> Self::Args<'a> { + [Expr::canonical(self.inner())] + } + + fn source_location(&self) -> Option { + None + } + + fn union_parts( + &self, + resets: Resets, + args_resets: Vec, + mut pass_args: PassArgs<'_, BuildResetGraph>, + ) -> Result<(), DeduceResetsError> { + pass_args.union(resets.trace_as_string_inner(), args_resets[0], None) + } + + fn new( + &self, + _ty: CanonicalType, + new_args: Vec>, + ) -> Result { + Ok(Self::new( + new_args[0], + self.ty().with_new_inner_ty(new_args[0].ty().intern_sized()), + )) + } +} + impl RunPassExpr for ModuleIO { type Args<'a> = [Expr; 0]; @@ -1691,7 +1804,8 @@ impl RunPassDispatch for AnyReg { | CanonicalType::Reset(_) | CanonicalType::Clock(_) | CanonicalType::PhantomConst(_) - | CanonicalType::DynSimOnly(_) => unreachable!(), + | CanonicalType::DynSimOnly(_) + | CanonicalType::TraceAsString(_) => unreachable!(), } }) } @@ -2173,30 +2287,6 @@ impl RunPass

for StmtDeclaration { } } -impl_run_pass_for_struct! { - impl[] RunPass for TargetPathBundleField { - name: _, - } -} - -impl_run_pass_for_struct! { - impl[] RunPass for TargetPathArrayElement { - index: _, - } -} - -impl_run_pass_for_struct! { - impl[] RunPass for TargetPathDynArrayElement {} -} - -impl_run_pass_for_enum! { - impl[] RunPass for TargetPathElement { - BundleField(v), - ArrayElement(v), - DynArrayElement(v), - } -} - impl_run_pass_for_enum! { impl[] RunPass for Target { Base(v), @@ -2204,11 +2294,28 @@ impl_run_pass_for_enum! { } } -impl_run_pass_for_struct! { - #[constructor = TargetChild::new(parent, path_element)] - impl[] RunPass for TargetChild { - parent(): _, - path_element(): _, +impl RunPass

for TargetChild { + fn run_pass( + &self, + mut pass_args: PassArgs<'_, P>, + ) -> Result, DeduceResetsError> { + Ok(self.parent().run_pass(pass_args.as_mut())?.map(|parent| { + let path_element = match *self.path_element() { + TargetPathElement::BundleField(TargetPathBundleField { name: _ }) + | TargetPathElement::ArrayElement(TargetPathArrayElement { index: _ }) + | TargetPathElement::DynArrayElement(TargetPathDynArrayElement {}) + | TargetPathElement::TraceAsStringInner(TargetPathTraceAsStringInner {}) => { + self.path_element() + } + TargetPathElement::AsTraceAsString(TargetPathAsTraceAsString { ty }) => { + TargetPathElement::from(TargetPathAsTraceAsString { + ty: ty.with_new_inner_ty(parent.canonical_ty().intern_sized()), + }) + .intern_sized() + } + }; + TargetChild::new(parent, path_element) + })) } } diff --git a/crates/fayalite/src/module/transform/simplify_enums.rs b/crates/fayalite/src/module/transform/simplify_enums.rs index 8902921..02b4dda 100644 --- a/crates/fayalite/src/module/transform/simplify_enums.rs +++ b/crates/fayalite/src/module/transform/simplify_enums.rs @@ -17,7 +17,7 @@ use crate::{ transform::visit::{Fold, Folder}, }, source_location::SourceLocation, - ty::{CanonicalType, Type}, + ty::{CanonicalType, TraceAsString, Type}, util::HashMap, wire::Wire, }; @@ -64,6 +64,7 @@ fn contains_any_enum_types(ty: CanonicalType) -> bool { .fields() .iter() .any(|field| contains_any_enum_types(field.ty)), + CanonicalType::TraceAsString(ty) => contains_any_enum_types(ty.inner_ty()), CanonicalType::UInt(_) | CanonicalType::SInt(_) | CanonicalType::Bool(_) @@ -313,6 +314,24 @@ impl State { } Ok(()) } + fn handle_stmt_connect_trace_as_string( + &mut self, + unfolded_lhs_ty: TraceAsString, + unfolded_rhs_ty: TraceAsString, + folded_lhs: Expr, + folded_rhs: Expr, + source_location: SourceLocation, + output_stmts: &mut Vec, + ) -> Result<(), SimplifyEnumsError> { + self.handle_stmt_connect( + unfolded_lhs_ty.inner_ty(), + unfolded_rhs_ty.inner_ty(), + ops::TraceAsStringAsInner::new(folded_lhs).to_expr(), + ops::TraceAsStringAsInner::new(folded_rhs).to_expr(), + source_location, + output_stmts, + ) + } fn handle_stmt_connect_bundle( &mut self, unfolded_lhs_ty: Bundle, @@ -509,6 +528,15 @@ impl State { source_location, output_stmts, ), + CanonicalType::TraceAsString(unfolded_lhs_ty) => self + .handle_stmt_connect_trace_as_string( + unfolded_lhs_ty, + TraceAsString::from_canonical(unfolded_rhs_ty), + Expr::from_canonical(folded_lhs), + Expr::from_canonical(folded_rhs), + source_location, + output_stmts, + ), CanonicalType::UInt(_) | CanonicalType::SInt(_) | CanonicalType::Bool(_) @@ -528,6 +556,8 @@ fn connect_port( rhs: Expr, source_location: SourceLocation, ) { + let lhs = Expr::unwrap_transparent_types(lhs); + let rhs = Expr::unwrap_transparent_types(rhs); if lhs.ty() == rhs.ty() { stmts.push( StmtConnect { @@ -573,6 +603,9 @@ fn connect_port( connect_port(stmts, lhs[index], rhs[index], source_location); } } + (CanonicalType::TraceAsString(_), CanonicalType::TraceAsString(_)) => { + unreachable!("handled by unwrap_transparent_types") + } (CanonicalType::Bundle(_), _) | (CanonicalType::Enum(_), _) | (CanonicalType::Array(_), _) @@ -584,7 +617,8 @@ fn connect_port( | (CanonicalType::SyncReset(_), _) | (CanonicalType::Reset(_), _) | (CanonicalType::PhantomConst(_), _) - | (CanonicalType::DynSimOnly(_), _) => unreachable!( + | (CanonicalType::DynSimOnly(_), _) + | (CanonicalType::TraceAsString(_), _) => unreachable!( "trying to connect memory ports:\n{:?}\n{:?}", lhs.ty(), rhs.ty(), @@ -772,6 +806,8 @@ impl Folder for State { | ExprEnum::SliceSInt(_) | ExprEnum::CastToBits(_) | ExprEnum::CastBitsTo(_) + | ExprEnum::TraceAsStringAsInner(_) + | ExprEnum::AsTraceAsString(_) | ExprEnum::ModuleIO(_) | ExprEnum::Instance(_) | ExprEnum::Wire(_) @@ -936,7 +972,8 @@ impl Folder for State { | CanonicalType::SyncReset(_) | CanonicalType::Reset(_) | CanonicalType::PhantomConst(_) - | CanonicalType::DynSimOnly(_) => canonical_type.default_fold(self), + | CanonicalType::DynSimOnly(_) + | CanonicalType::TraceAsString(_) => canonical_type.default_fold(self), } } diff --git a/crates/fayalite/src/module/transform/simplify_memories.rs b/crates/fayalite/src/module/transform/simplify_memories.rs index d741836..4a97353 100644 --- a/crates/fayalite/src/module/transform/simplify_memories.rs +++ b/crates/fayalite/src/module/transform/simplify_memories.rs @@ -90,7 +90,7 @@ impl MemSplit { } } fn new(element_type: CanonicalType) -> Self { - match element_type { + match element_type.unwrap_transparent_types() { CanonicalType::Bundle(bundle_ty) => MemSplit::Bundle { fields: bundle_ty .fields() @@ -195,6 +195,7 @@ impl MemSplit { | CanonicalType::SyncReset(_) | CanonicalType::Reset(_) => unreachable!("memory element type is a storable type"), CanonicalType::DynSimOnly(_) => todo!("memory containing sim-only values"), + CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"), } } } @@ -306,7 +307,9 @@ impl SplitMemState<'_, '_> { let outer_mem_name_path_len = self.mem_name_path.len(); match self.split { MemSplit::Bundle { fields } => { - let CanonicalType::Bundle(bundle_type) = self.element_type else { + let CanonicalType::Bundle(bundle_type) = + self.element_type.unwrap_transparent_types() + else { unreachable!(); }; for ((field, field_offset), split) in bundle_type @@ -321,7 +324,10 @@ impl SplitMemState<'_, '_> { let field_ty_bit_width = field.ty.bit_width(); self.split_state_stack.push_map( |e: Expr| { - Expr::field(Expr::::from_canonical(e), &field.name) + Expr::field( + Expr::::from_canonical(Expr::unwrap_transparent_types(e)), + &field.name, + ) }, |initial_value_element| { let Some(field_offset) = field_offset.only_bit_width() else { @@ -377,8 +383,8 @@ impl SplitMemState<'_, '_> { }; self.output_stmts.push( StmtConnect { - lhs: Expr::field(port_expr, name), - rhs: Expr::field(wire_expr, name), + lhs: Expr::unwrap_transparent_types(Expr::field(port_expr, name)), + rhs: Expr::unwrap_transparent_types(Expr::field(wire_expr, name)), source_location: port.source_location(), } .into(), @@ -389,7 +395,8 @@ impl SplitMemState<'_, '_> { self.output_mems.push(new_mem); } MemSplit::Array { elements } => { - let CanonicalType::Array(array_type) = self.element_type else { + let CanonicalType::Array(array_type) = self.element_type.unwrap_transparent_types() + else { unreachable!(); }; let element_type = array_type.element(); @@ -398,7 +405,7 @@ impl SplitMemState<'_, '_> { self.mem_name_path.truncate(outer_mem_name_path_len); write!(self.mem_name_path, "_{index}").unwrap(); self.split_state_stack.push_map( - |e| Expr::::from_canonical(e)[index], + |e| Expr::::from_canonical(Expr::unwrap_transparent_types(e))[index], |initial_value_element| { &initial_value_element[index * element_bit_width..][..element_bit_width] }, @@ -464,7 +471,7 @@ impl ModuleState { assert_eq!(memory_element_array_range_len % input_array_type.len(), 0); let chunk_size = memory_element_array_range_len / input_array_type.len(); for index in 0..input_array_type.len() { - let map = |e| Expr::::from_canonical(e)[index]; + let map = |e| Expr::::from_canonical(Expr::unwrap_transparent_types(e))[index]; let wire_rdata = wire_rdata.map(map); let wire_wdata = wire_wdata.map(map); let wire_wmask = wire_wmask.map(map); @@ -505,8 +512,8 @@ impl ModuleState { port_read: Expr| { output_stmts.push( StmtConnect { - lhs: wire_read, - rhs: port_read, + lhs: Expr::unwrap_transparent_types(wire_read), + rhs: Expr::unwrap_transparent_types(port_read), source_location, } .into(), @@ -517,8 +524,8 @@ impl ModuleState { port_write: Expr| { output_stmts.push( StmtConnect { - lhs: port_write, - rhs: wire_write, + lhs: Expr::unwrap_transparent_types(port_write), + rhs: Expr::unwrap_transparent_types(wire_write), source_location, } .into(), @@ -530,7 +537,8 @@ impl ModuleState { connect_read( output_stmts, wire_read, - Expr::::from_canonical(port_read).cast_bits_to(wire_read.ty()), + Expr::::from_canonical(Expr::unwrap_transparent_types(port_read)) + .cast_bits_to(wire_read.ty()), ); }; let connect_write_enum = @@ -544,7 +552,7 @@ impl ModuleState { ); }; loop { - match input_element_type { + match input_element_type.unwrap_transparent_types() { CanonicalType::Bundle(_) => { unreachable!("bundle types are always split") } @@ -625,6 +633,9 @@ impl ModuleState { | CanonicalType::SyncReset(_) | CanonicalType::Reset(_) => unreachable!("memory element type is a storable type"), CanonicalType::DynSimOnly(_) => todo!("memory containing sim-only values"), + CanonicalType::TraceAsString(_) => { + unreachable!("handled by unwrap_transparent_types") + } } break; } diff --git a/crates/fayalite/src/module/transform/visit.rs b/crates/fayalite/src/module/transform/visit.rs index 2869a49..134d9a8 100644 --- a/crates/fayalite/src/module/transform/visit.rs +++ b/crates/fayalite/src/module/transform/visit.rs @@ -13,8 +13,9 @@ use crate::{ expr::{ Expr, ExprEnum, ValueType, ops, target::{ - Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField, - TargetPathDynArrayElement, TargetPathElement, + Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathAsTraceAsString, + TargetPathBundleField, TargetPathDynArrayElement, TargetPathElement, + TargetPathTraceAsStringInner, }, }, formal::FormalKind, @@ -32,7 +33,7 @@ use crate::{ reset::{AsyncReset, Reset, ResetType, SyncReset}, sim::{ExternModuleSimulation, value::DynSimOnly}, source_location::SourceLocation, - ty::{CanonicalType, Type}, + ty::{CanonicalType, TraceAsString, Type}, vendor::xilinx::{ XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, XilinxAnnotation, }, diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index 4a7721b..658ae10 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -9,6 +9,7 @@ use crate::{ Flow, target::{ GetTarget, Target, TargetPathArrayElement, TargetPathBundleField, TargetPathElement, + TargetPathTraceAsStringInner, }, }, int::BoolOrIntType, @@ -38,7 +39,7 @@ use crate::{ }, ty::{ OpaqueSimValue, OpaqueSimValueSize, OpaqueSimValueSizeRange, OpaqueSimValueSlice, - OpaqueSimValueWriter, + OpaqueSimValueWriter, TraceAsString, }, util::{BitSliceWriteWithBase, DebugAsDisplay, HashMap, HashSet, copy_le_bytes_to_bitslice}, }; @@ -432,6 +433,15 @@ impl_trace_decl! { ty: DynSimOnly, flow: Flow, }), + TraceAsString(TraceTraceAsString { + fn location(self) -> _ { + self.location + } + location: TraceLocation, + name: Interned, + ty: TraceAsString, + flow: Flow, + }), }), } @@ -543,6 +553,7 @@ pub trait TraceWriter: fmt::Debug + 'static { id: TraceScalarId, value: &DynSimOnlyValue, ) -> Result<(), Self::Error>; + fn set_signal_string(&mut self, id: TraceScalarId, value: &str) -> Result<(), Self::Error>; } pub struct DynTraceWriterDecls(Box); @@ -607,6 +618,7 @@ trait TraceWriterDynTrait: fmt::Debug + 'static { id: TraceScalarId, value: &DynSimOnlyValue, ) -> std::io::Result<()>; + fn set_signal_string_dyn(&mut self, id: TraceScalarId, value: &str) -> std::io::Result<()>; } impl TraceWriterDynTrait for T { @@ -680,6 +692,9 @@ impl TraceWriterDynTrait for T { ) -> std::io::Result<()> { Ok(TraceWriter::set_signal_sim_only_value(self, id, value).map_err(err_into_io)?) } + fn set_signal_string_dyn(&mut self, id: TraceScalarId, value: &str) -> std::io::Result<()> { + Ok(TraceWriter::set_signal_string(self, id, value).map_err(err_into_io)?) + } } pub struct DynTraceWriter(Box); @@ -758,6 +773,9 @@ impl TraceWriter for DynTraceWriter { ) -> Result<(), Self::Error> { self.0.set_signal_sim_only_value_dyn(id, value) } + fn set_signal_string(&mut self, id: TraceScalarId, value: &str) -> Result<(), Self::Error> { + self.0.set_signal_string_dyn(id, value) + } } #[derive(Debug)] @@ -934,6 +952,10 @@ pub(crate) enum SimTraceKind { PhantomConst { ty: PhantomConst, }, + TraceAsString { + layout: compiler::CompiledTypeLayout, + range: TypeIndexRange, + }, } #[derive(PartialEq, Eq)] @@ -941,6 +963,7 @@ pub(crate) enum SimTraceState { Bits(BitVec), SimOnly(DynSimOnlyValue), PhantomConst, + OpaqueSimValue(OpaqueSimValue), } impl Clone for SimTraceState { @@ -949,6 +972,7 @@ impl Clone for SimTraceState { Self::Bits(v) => Self::Bits(v.clone()), Self::SimOnly(v) => Self::SimOnly(v.clone()), Self::PhantomConst => Self::PhantomConst, + Self::OpaqueSimValue(v) => Self::OpaqueSimValue(v.clone()), } } fn clone_from(&mut self, source: &Self) { @@ -956,6 +980,9 @@ impl Clone for SimTraceState { (SimTraceState::Bits(dest), SimTraceState::Bits(source)) => { dest.clone_from_bitslice(source); } + (SimTraceState::OpaqueSimValue(dest), SimTraceState::OpaqueSimValue(source)) => { + dest.clone_from(source); + } _ => *self = source.clone(), } } @@ -990,6 +1017,20 @@ impl SimTraceState { unreachable!() } } + fn unwrap_opaque_sim_value_ref(&self) -> &OpaqueSimValue { + if let SimTraceState::OpaqueSimValue(v) = self { + v + } else { + unreachable!() + } + } + fn unwrap_opaque_sim_value_mut(&mut self) -> &mut OpaqueSimValue { + if let SimTraceState::OpaqueSimValue(v) = self { + v + } else { + unreachable!() + } + } } impl fmt::Debug for SimTraceState { @@ -998,6 +1039,7 @@ impl fmt::Debug for SimTraceState { SimTraceState::Bits(v) => BitSliceWriteWithBase(v).fmt(f), SimTraceState::SimOnly(v) => v.fmt(f), SimTraceState::PhantomConst => f.debug_tuple("PhantomConst").finish(), + SimTraceState::OpaqueSimValue(v) => v.fmt(f), } } } @@ -1026,6 +1068,13 @@ impl SimTraceKind { } SimTraceKind::PhantomConst { .. } => SimTraceState::PhantomConst, SimTraceKind::SimOnly { index: _, ty } => SimTraceState::SimOnly(ty.default_value()), + SimTraceKind::TraceAsString { layout, range: _ } => { + let type_properties = layout.ty.type_properties(); + SimTraceState::OpaqueSimValue(OpaqueSimValue::from_bits_and_sim_only_values( + UIntValue::new_dyn(Arc::new(BitVec::repeat(false, type_properties.bit_width))), + Vec::with_capacity(type_properties.sim_only_values_len), + )) + } } } } @@ -1180,6 +1229,31 @@ impl SimulationModuleState { true } } + CompiledTypeLayoutBody::Transparent { .. } => { + let value = value.map_ty(|ty| match ty { + CanonicalType::UInt(_) + | CanonicalType::SInt(_) + | CanonicalType::Bool(_) + | CanonicalType::Array(_) + | CanonicalType::Enum(_) + | CanonicalType::Bundle(_) + | CanonicalType::AsyncReset(_) + | CanonicalType::SyncReset(_) + | CanonicalType::Reset(_) + | CanonicalType::Clock(_) + | CanonicalType::PhantomConst(_) + | CanonicalType::DynSimOnly(_) => unreachable!(), + CanonicalType::TraceAsString(ty) => ty, + }); + let sub_target = target + .join(TargetPathElement::from(TargetPathTraceAsStringInner {}).intern_sized()); + if self.parse_io(sub_target, value.inner()) { + self.uninitialized_ios.insert(target, vec![sub_target]); + true + } else { + false + } + } } } fn mark_target_as_initialized(&mut self, mut target: Target) { @@ -1230,7 +1304,10 @@ impl SimulationModuleState { Target::Base(_) => break, Target::Child(child) => { match *child.path_element() { - TargetPathElement::BundleField(_) | TargetPathElement::ArrayElement(_) => {} + TargetPathElement::BundleField(_) + | TargetPathElement::ArrayElement(_) + | TargetPathElement::TraceAsStringInner(_) + | TargetPathElement::AsTraceAsString(_) => {} TargetPathElement::DynArrayElement(_) => panic!( "simulator read/write expression must not have dynamic array indexes" ), @@ -1273,7 +1350,8 @@ impl SimulationModuleState { | CanonicalType::Reset(_) | CanonicalType::Clock(_) | CanonicalType::PhantomConst(_) - | CanonicalType::DynSimOnly(_) => unreachable!(), + | CanonicalType::DynSimOnly(_) + | CanonicalType::TraceAsString(_) => unreachable!(), CanonicalType::AsyncReset(_) => true, CanonicalType::SyncReset(_) => false, } @@ -1438,6 +1516,26 @@ impl SimulationExternModuleClockForPast { ); } } + CompiledTypeLayoutBody::Transparent { .. } => { + let map_ty_fn = |ty| match ty { + CanonicalType::UInt(_) + | CanonicalType::SInt(_) + | CanonicalType::Bool(_) + | CanonicalType::Array(_) + | CanonicalType::Enum(_) + | CanonicalType::Bundle(_) + | CanonicalType::AsyncReset(_) + | CanonicalType::SyncReset(_) + | CanonicalType::Reset(_) + | CanonicalType::Clock(_) + | CanonicalType::PhantomConst(_) + | CanonicalType::DynSimOnly(_) => unreachable!(), + CanonicalType::TraceAsString(ty) => ty, + }; + let current = current.map_ty(map_ty_fn); + let past = past.map_ty(map_ty_fn); + self.add_current_to_past_mapping(current.inner(), past.inner()); + } } } } @@ -1906,6 +2004,7 @@ struct SimulationImpl { ), >, waiting_sensitivity_sets_by_address: HashMap<*const SensitivitySet, Rc>, + trace_as_string_buf: String, } impl fmt::Debug for SimulationImpl { @@ -1995,6 +2094,7 @@ impl SimulationImpl { next_sensitivity_set_debug_id: _, waiting_sensitivity_sets_by_compiled_value, waiting_sensitivity_sets_by_address, + trace_as_string_buf: _, } = self; f.debug_struct("Simulation") .field("state", state) @@ -2101,6 +2201,7 @@ impl SimulationImpl { next_sensitivity_set_debug_id: 0, waiting_sensitivity_sets_by_compiled_value: HashMap::default(), waiting_sensitivity_sets_by_address: HashMap::default(), + trace_as_string_buf: String::with_capacity(256), } } fn write_traces( @@ -2181,6 +2282,15 @@ impl SimulationImpl { SimTraceKind::SimOnly { .. } => { trace_writer.set_signal_sim_only_value(id, state.unwrap_sim_only_ref())? } + SimTraceKind::TraceAsString { layout, .. } => { + self.trace_as_string_buf.clear(); + layout.ty.trace_fmt_append_to_string( + &mut self.trace_as_string_buf, + state.unwrap_opaque_sim_value_ref().as_slice(), + ); + trace_writer.set_signal_string(id, &self.trace_as_string_buf)?; + self.trace_as_string_buf.clear(); + } } } Ok(trace_writer) @@ -2233,6 +2343,9 @@ impl SimulationImpl { .sim_only_slots .state_index_fetch_maybe_modified_flag(index), SimTraceKind::PhantomConst { ty: _ } => IS_INITIAL_STEP, + SimTraceKind::TraceAsString { layout: _, range } => self + .state + .type_index_range_fetch_maybe_modified_flags(range), }; if !new_maybe_changed && !IS_INITIAL_STEP { if *maybe_changed { @@ -2286,6 +2399,20 @@ impl SimulationImpl { .unwrap_sim_only_mut() .clone_from(&self.state.sim_only_slots[index]); } + SimTraceKind::TraceAsString { layout, range } => { + let CompiledTypeLayoutBody::Transparent { inner } = layout.body else { + unreachable!() + }; + Self::read_opaque_no_settle( + &mut self.state, + CompiledValue { + layout: *inner, + range, + write: None, + }, + state.unwrap_opaque_sim_value_mut(), + ); + } } if IS_INITIAL_STEP { last_state.clone_from(state); @@ -2818,6 +2945,7 @@ impl SimulationImpl { + Copy, read_write_sim_only_scalar: impl Fn(usize, &mut Opaque, &mut DynSimOnlyValue) + Copy, ) { + let compiled_value = compiled_value.unwrap_transparent_types(); match compiled_value.layout.body { CompiledTypeLayoutBody::Scalar => { let signed = match compiled_value.layout.ty { @@ -2833,6 +2961,7 @@ impl SimulationImpl { CanonicalType::Clock(_) => false, CanonicalType::PhantomConst(_) => unreachable!(), CanonicalType::DynSimOnly(_) => false, + CanonicalType::TraceAsString(_) => unreachable!(), }; let indexes = OpaqueSimValueSizeRange::from( start_index..start_index + compiled_value.layout.ty.size(), @@ -2909,14 +3038,17 @@ impl SimulationImpl { ); } } + CompiledTypeLayoutBody::Transparent { .. } => { + unreachable!("handled by unwrap_transparent_types") + } } } #[track_caller] - fn read_no_settle_helper( + fn read_opaque_no_settle( state: &mut interpreter::State, - io: Expr, compiled_value: CompiledValue, - ) -> SimValue { + opaque: &mut OpaqueSimValue, + ) { #[track_caller] fn read_write_sim_only_scalar( index: usize, @@ -2937,8 +3069,7 @@ impl SimulationImpl { }, ); } - let size = io.ty().size(); - let mut opaque = OpaqueSimValue::with_capacity(size); + let size = compiled_value.layout.ty.size(); opaque.rewrite_with(size, |mut writer| { SimulationImpl::read_write_sim_value_helper( state, @@ -2970,6 +3101,16 @@ impl SimulationImpl { ); writer.fill_cloned_from_slice(OpaqueSimValueSlice::empty()) }); + } + #[track_caller] + fn read_no_settle_helper( + state: &mut interpreter::State, + io: Expr, + compiled_value: CompiledValue, + ) -> SimValue { + let size = io.ty().size(); + let mut opaque = OpaqueSimValue::with_capacity(size); + Self::read_opaque_no_settle(state, compiled_value, &mut opaque); SimValue::from_opaque(io.ty(), opaque) } /// doesn't modify `opaque` diff --git a/crates/fayalite/src/sim/compiler.rs b/crates/fayalite/src/sim/compiler.rs index dbdbffb..4f5c571 100644 --- a/crates/fayalite/src/sim/compiler.rs +++ b/crates/fayalite/src/sim/compiler.rs @@ -9,8 +9,8 @@ use crate::{ expr::{ ExprEnum, Flow, ValueType, ops, target::{ - GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, - TargetPathElement, + GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathAsTraceAsString, + TargetPathBundleField, TargetPathElement, TargetPathTraceAsStringInner, }, }, int::BoolOrIntType, @@ -29,7 +29,8 @@ use crate::{ TraceBool, TraceBundle, TraceClock, TraceDecl, TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, - TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire, + TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceTraceAsString, TraceUInt, + TraceWire, interpreter::{ self, Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding, InsnsBuildingDone, InsnsBuildingKind, Label, PrefixLinesWrapper, SmallUInt, @@ -42,7 +43,7 @@ use crate::{ }, }, }, - ty::{OpaqueSimValueSize, StaticType}, + ty::{OpaqueSimValueSize, StaticType, TraceAsString}, util::{HashMap, chain}, }; use bitvec::vec::BitVec; @@ -110,6 +111,9 @@ pub(crate) enum CompiledTypeLayoutBody { Bundle { fields: Interned<[CompiledBundleField]>, }, + Transparent { + inner: Interned>, + }, } impl CompiledTypeLayoutBody { @@ -128,6 +132,9 @@ impl CompiledTypeLayoutBody { .map(|field| field.with_prefixed_debug_names(prefix)) .collect(), }, + CompiledTypeLayoutBody::Transparent { inner } => CompiledTypeLayoutBody::Transparent { + inner: inner.with_prefixed_debug_names(prefix).intern_sized(), + }, } } fn with_anonymized_debug_info(self) -> Self { @@ -145,6 +152,9 @@ impl CompiledTypeLayoutBody { .map(|field| field.with_anonymized_debug_info()) .collect(), }, + CompiledTypeLayoutBody::Transparent { inner } => CompiledTypeLayoutBody::Transparent { + inner: inner.with_anonymized_debug_info().intern_sized(), + }, } } } @@ -179,7 +189,7 @@ impl CompiledTypeLayout { impl Memoize for MyMemoize { type Input = CanonicalType; type InputOwned = CanonicalType; - type Output = CompiledTypeLayout; + type Output = (TypeLayout, CompiledTypeLayoutBody); fn inner(self, input: &Self::Input) -> Self::Output { match input { @@ -197,11 +207,7 @@ impl CompiledTypeLayout { ty: *input, }; layout.big_slots = StatePartLayout::scalar(debug_data, ()); - CompiledTypeLayout { - ty: *input, - layout: layout.into(), - body: CompiledTypeLayoutBody::Scalar, - } + (layout.into(), CompiledTypeLayoutBody::Scalar) } CanonicalType::Array(array) => { let mut layout = TypeLayout::empty(); @@ -215,19 +221,16 @@ impl CompiledTypeLayout { if array.is_empty() { elements_non_empty.push(element.with_prefixed_debug_names("[]")); } - CompiledTypeLayout { - ty: *input, - layout: layout.into(), - body: CompiledTypeLayoutBody::Array { + ( + layout.into(), + CompiledTypeLayoutBody::Array { elements_non_empty: elements_non_empty.intern_deref(), }, - } + ) + } + CanonicalType::PhantomConst(_) => { + (TypeLayout::empty(), CompiledTypeLayoutBody::PhantomConst) } - CanonicalType::PhantomConst(_) => CompiledTypeLayout { - ty: *input, - layout: TypeLayout::empty(), - body: CompiledTypeLayoutBody::PhantomConst, - }, CanonicalType::Bundle(bundle) => { let mut layout = TypeLayout::empty(); let fields = bundle @@ -246,11 +249,7 @@ impl CompiledTypeLayout { }, ) .collect(); - CompiledTypeLayout { - ty: *input, - layout: layout.into(), - body: CompiledTypeLayoutBody::Bundle { fields }, - } + (layout.into(), CompiledTypeLayoutBody::Bundle { fields }) } CanonicalType::DynSimOnly(ty) => { let mut layout = TypeLayout::empty(); @@ -259,24 +258,30 @@ impl CompiledTypeLayout { ty: *input, }; layout.sim_only_slots = StatePartLayout::scalar(debug_data, *ty); - CompiledTypeLayout { - ty: *input, - layout: layout.into(), - body: CompiledTypeLayoutBody::Scalar, - } + (layout.into(), CompiledTypeLayoutBody::Scalar) + } + CanonicalType::TraceAsString(ty) => { + let inner = CompiledTypeLayout::get(ty.inner_ty()).intern_sized(); + (inner.layout, CompiledTypeLayoutBody::Transparent { inner }) } } } } - let CompiledTypeLayout { - ty: _, - layout, - body, - } = MyMemoize.get_owned(ty.canonical()); + let (layout, body) = MyMemoize.get_owned(ty.canonical()); Self { ty, layout, body } } } +impl CompiledTypeLayout { + #[must_use] + fn unwrap_transparent_types(mut self) -> Self { + while let CompiledTypeLayoutBody::Transparent { inner } = self.body { + self = *inner; + } + self + } +} + #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] pub(crate) struct CompiledValue { pub(crate) layout: CompiledTypeLayout, @@ -324,6 +329,29 @@ impl CompiledValue { } } +impl CompiledValue { + #[must_use] + pub(crate) fn unwrap_transparent_types(self) -> Self { + let Self { + layout, + range, + write, + } = self; + Self { + layout: layout.unwrap_transparent_types(), + range, + write: write.map(|(layout, range)| (layout.unwrap_transparent_types(), range)), + } + } + #[must_use] + pub(crate) fn wrap_in_trace_as_string(self, ty: TraceAsString) -> CompiledValue { + self.map(|layout, range| { + assert_eq!(layout.ty, ty.inner_ty()); + (CompiledTypeLayout::get(ty), range) + }) + } +} + pub(crate) struct DebugCompiledValueStateAsMap<'a> { pub(crate) compiled_value: CompiledValue, pub(crate) state_layout: &'a interpreter::parts::StateLayout, @@ -402,6 +430,17 @@ impl CompiledValue { } } +impl CompiledValue { + pub(crate) fn inner(self) -> CompiledValue { + self.map(|layout, range| { + let CompiledTypeLayoutBody::Transparent { inner } = layout.body else { + unreachable!(); + }; + (*inner, range) + }) + } +} + macro_rules! make_type_array_indexes { ( type_plural_fields = [$($type_plural_field:ident,)*]; @@ -618,6 +657,16 @@ impl CompiledExpr { } } +impl CompiledExpr { + #[must_use] + pub(crate) fn wrap_in_trace_as_string(self, ty: TraceAsString) -> CompiledExpr { + CompiledExpr { + static_part: self.static_part.wrap_in_trace_as_string(ty), + indexes: self.indexes, + } + } +} + impl CompiledExpr { fn field_by_index(self, field_index: usize) -> CompiledExpr { CompiledExpr { @@ -666,6 +715,15 @@ impl CompiledExpr { } } +impl CompiledExpr { + pub(crate) fn inner(self) -> CompiledExpr { + CompiledExpr { + static_part: self.static_part.inner(), + indexes: self.indexes, + } + } +} + macro_rules! make_assignment_graph { ( type_plural_fields = [$($type_plural_field:ident,)*]; @@ -1977,6 +2035,39 @@ macro_rules! impl_compiler { flow, } .into(), + CanonicalType::TraceAsString(ty) => { + let location = match target { + MakeTraceDeclTarget::Expr(target) => { + let compiled_value = self.compile_expr(instantiated_module, target); + let CompiledValue { layout, range, write: _ } = + self.compiled_expr_to_value(compiled_value, source_location).map_ty(Type::from_canonical); + TraceLocation::Scalar(self.new_sim_trace(SimTraceKind::TraceAsString { + layout, + range, + })) + } + MakeTraceDeclTarget::Memory { + id, + depth, + stride, + start, + ty: _, + } => TraceLocation::Memory(TraceMemoryLocation { + id, + depth, + stride, + start, + len: ty.type_properties().bit_width, + }), + }; + TraceTraceAsString { + location, + name, + ty, + flow, + } + .into() + } } } fn compiled_expr_to_value( @@ -2421,7 +2512,8 @@ impl Compiler { | CanonicalType::Reset(_) | CanonicalType::Clock(_) | CanonicalType::DynSimOnly(_) - | CanonicalType::PhantomConst(_) => { + | CanonicalType::PhantomConst(_) + | CanonicalType::TraceAsString(_) => { self.make_trace_scalar(instantiated_module, target, name, source_location) } } @@ -2591,6 +2683,12 @@ impl Compiler { parent.map_ty(Array::from_canonical).element(index) } TargetPathElement::DynArrayElement(_) => unreachable!(), + TargetPathElement::TraceAsStringInner(TargetPathTraceAsStringInner {}) => { + parent.map_ty(TraceAsString::from_canonical).inner() + } + TargetPathElement::AsTraceAsString(TargetPathAsTraceAsString { ty }) => parent + .wrap_in_trace_as_string(ty) + .map_ty(|ty| ty.canonical()), } } }; @@ -2823,6 +2921,12 @@ impl Compiler { CanonicalType::PhantomConst(_) | CanonicalType::DynSimOnly(_) => { self.compile_cast_aggregate_to_bits(instantiated_module, []) } + CanonicalType::TraceAsString(_) => self.compile_cast_to_bits( + instantiated_module, + ops::CastToBits::new( + ops::TraceAsStringAsInner::new(Expr::from_canonical(expr.arg())).to_expr(), + ), + ), } } fn compile_cast_bits_to_or_uninit( @@ -2912,6 +3016,16 @@ impl Compiler { vec![] }); } + CanonicalType::TraceAsString(ty) => Expr::canonical( + ops::AsTraceAsString::new( + match arg { + Some(arg) => arg.cast_bits_to(ty.inner_ty()), + None => ty.inner_ty().uninit(), + }, + ty, + ) + .to_expr(), + ), }; let retval = self.compile_expr(instantiated_module, Expr::canonical(retval)); self.compiled_expr_to_value(retval, instantiated_module.leaf_module().source_location()) @@ -2963,6 +3077,7 @@ impl Compiler { CanonicalType::Clock(_) => false, CanonicalType::PhantomConst(_) => unreachable!(), CanonicalType::DynSimOnly(_) => unreachable!(), + CanonicalType::TraceAsString(_) => unreachable!(), }; let dest_signed = match expr.ty() { CanonicalType::UInt(_) => false, @@ -2977,6 +3092,7 @@ impl Compiler { CanonicalType::Clock(_) => false, CanonicalType::PhantomConst(_) => unreachable!(), CanonicalType::DynSimOnly(_) => unreachable!(), + CanonicalType::TraceAsString(_) => unreachable!(), }; self.simple_nary_big_expr(instantiated_module, expr.ty(), [arg], |dest, [src]| match ( src_signed, @@ -3722,6 +3838,14 @@ impl Compiler { ExprEnum::CastBitsTo(expr) => self .compile_cast_bits_to_or_uninit(instantiated_module, Some(expr.arg()), expr.ty()) .into(), + ExprEnum::AsTraceAsString(expr) => self + .compile_expr(instantiated_module, expr.inner()) + .wrap_in_trace_as_string(expr.ty()) + .map_ty(|ty| ty.canonical()), + ExprEnum::TraceAsStringAsInner(expr) => self + .compile_expr(instantiated_module, Expr::canonical(expr.arg())) + .map_ty(TraceAsString::from_canonical) + .inner(), ExprEnum::ModuleIO(expr) => self .compile_value(TargetInInstantiatedModule { instantiated_module, @@ -3869,6 +3993,21 @@ impl Compiler { CanonicalType::DynSimOnly(_) => { unreachable!("DynSimOnly mismatch"); } + CanonicalType::TraceAsString(_) => { + let lhs = Expr::::from_canonical(lhs); + let rhs = Expr::::from_canonical(rhs); + let lhs_expr = ops::TraceAsStringAsInner::new(lhs).to_expr(); + let rhs_expr = ops::TraceAsStringAsInner::new(rhs).to_expr(); + return self.compile_connect( + lhs_instantiated_module, + lhs_conditions, + lhs_expr, + rhs_instantiated_module, + rhs_conditions, + rhs_expr, + source_location, + ); + } } } let Some(target) = lhs.target() else { @@ -4244,6 +4383,8 @@ impl Compiler { mut read: Option>, mut write: Option>, ) { + let data_layout = data_layout.unwrap_transparent_types(); + let mask_layout = mask_layout.unwrap_transparent_types(); match data_layout.body { CompiledTypeLayoutBody::Scalar => { let CompiledTypeLayoutBody::Scalar = mask_layout.body else { @@ -4262,6 +4403,7 @@ impl Compiler { CanonicalType::Clock(_) => false, CanonicalType::PhantomConst(_) => unreachable!(), CanonicalType::DynSimOnly(_) => false, + CanonicalType::TraceAsString(_) => unreachable!(), }; let width = data_layout.ty.bit_width(); if let Some(MemoryPortReadInsns { @@ -4484,6 +4626,9 @@ impl Compiler { start = start + field.ty.ty.bit_width(); } } + CompiledTypeLayoutBody::Transparent { .. } => { + unreachable!("handled by unwrap_transparent_types") + } } } fn compile_memory_port_rw( diff --git a/crates/fayalite/src/sim/interpreter.rs b/crates/fayalite/src/sim/interpreter.rs index e16519b..6b3eced 100644 --- a/crates/fayalite/src/sim/interpreter.rs +++ b/crates/fayalite/src/sim/interpreter.rs @@ -6,9 +6,9 @@ use crate::{ int::{BoolOrIntType, SInt, UInt}, intern::{Intern, Interned, Memoize}, sim::interpreter::parts::{ - StateLayout, StatePartIndex, StatePartKind, StatePartKindBigSlots, StatePartKindMemories, - StatePartKindSimOnlySlots, StatePartKindSmallSlots, StatePartLen, TypeIndexRange, - TypeLayout, get_state_part_kinds, + StateLayout, StatePartIndex, StatePartIndexRange, StatePartKind, StatePartKindBigSlots, + StatePartKindMemories, StatePartKindSimOnlySlots, StatePartKindSmallSlots, StatePartLen, + TypeIndexRange, TypeLayout, get_state_part_kinds, }, source_location::SourceLocation, util::{HashMap, HashSet}, @@ -920,6 +920,12 @@ impl StatePart { ) -> bool { K::state_index_fetch_maybe_modified_flag(&self.value, part_index) } + pub(crate) fn state_index_range_fetch_maybe_modified_flags( + &self, + part_index_range: StatePartIndexRange, + ) -> bool { + K::state_index_range_fetch_maybe_modified_flags(&self.value, part_index_range) + } pub(crate) fn clear_all_maybe_modified_flags(&mut self) { K::clear_all_maybe_modified_flags(&mut self.value) } @@ -1018,6 +1024,11 @@ macro_rules! make_state { $($type_plural_field: self.$type_plural_field.borrow(),)* } } + pub(crate) fn type_index_range_fetch_maybe_modified_flags(&self, range: TypeIndexRange) -> bool { + $(self.$type_plural_field.state_index_range_fetch_maybe_modified_flags( + range.$type_plural_field, + ))||* + } pub(crate) fn clear_all_maybe_modified_flags(&mut self) { $(self.$state_plural_field.clear_all_maybe_modified_flags();)* $(self.$type_plural_field.clear_all_maybe_modified_flags();)* diff --git a/crates/fayalite/src/sim/interpreter/parts.rs b/crates/fayalite/src/sim/interpreter/parts.rs index 308ac44..0d98c06 100644 --- a/crates/fayalite/src/sim/interpreter/parts.rs +++ b/crates/fayalite/src/sim/interpreter/parts.rs @@ -260,6 +260,10 @@ pub(crate) trait StatePartKind: state: &Self::State, part_index: StatePartIndex, ) -> bool; + fn state_index_range_fetch_maybe_modified_flags( + state: &Self::State, + part_index_range: StatePartIndexRange, + ) -> bool; fn clear_all_maybe_modified_flags(state: &mut Self::State); fn borrowed_state_index<'a, 'b>( state: &'a Self::BorrowedState<'b>, @@ -342,6 +346,12 @@ impl StatePartKind for StatePartKindMemories { ) -> bool { true } + fn state_index_range_fetch_maybe_modified_flags( + _state: &Self::State, + part_index_range: StatePartIndexRange, + ) -> bool { + part_index_range.len.value > 0 + } fn clear_all_maybe_modified_flags(_state: &mut Self::State) {} fn borrowed_state_index<'a, 'b>( state: &'a Self::BorrowedState<'b>, @@ -446,6 +456,14 @@ impl StatePartKind for StatePartKindSmallSlots { ) -> bool { state.modified[part_index.as_usize()] } + fn state_index_range_fetch_maybe_modified_flags( + state: &Self::State, + part_index_range: StatePartIndexRange, + ) -> bool { + state.modified[part_index_range.start.as_usize()..] + [..part_index_range.len.as_index().as_usize()] + .contains(&true) + } fn clear_all_maybe_modified_flags(state: &mut Self::State) { state.modified.fill(false); } @@ -530,6 +548,14 @@ impl StatePartKind for StatePartKindBigSlots { ) -> bool { state.modified[part_index.as_usize()] } + fn state_index_range_fetch_maybe_modified_flags( + state: &Self::State, + part_index_range: StatePartIndexRange, + ) -> bool { + state.modified[part_index_range.start.as_usize()..] + [..part_index_range.len.as_index().as_usize()] + .contains(&true) + } fn clear_all_maybe_modified_flags(state: &mut Self::State) { state.modified.fill(false); } @@ -614,6 +640,14 @@ impl StatePartKind for StatePartKindSimOnlySlots { ) -> bool { state.modified[part_index.as_usize()] } + fn state_index_range_fetch_maybe_modified_flags( + state: &Self::State, + part_index_range: StatePartIndexRange, + ) -> bool { + state.modified[part_index_range.start.as_usize()..] + [..part_index_range.len.as_index().as_usize()] + .contains(&true) + } fn clear_all_maybe_modified_flags(state: &mut Self::State) { state.modified.fill(false); } diff --git a/crates/fayalite/src/sim/value.rs b/crates/fayalite/src/sim/value.rs index eaa3f8d..79515ac 100644 --- a/crates/fayalite/src/sim/value.rs +++ b/crates/fayalite/src/sim/value.rs @@ -1098,7 +1098,8 @@ impl ToSimValueWithType for bool { | CanonicalType::Enum(_) | CanonicalType::Bundle(_) | CanonicalType::PhantomConst(_) - | CanonicalType::DynSimOnly(_) => { + | CanonicalType::DynSimOnly(_) + | CanonicalType::TraceAsString(_) => { panic!("can't create SimValue from bool: expected value of type: {ty:?}"); } CanonicalType::Bool(_) diff --git a/crates/fayalite/src/sim/vcd.rs b/crates/fayalite/src/sim/vcd.rs index ad3e974..09e7d66 100644 --- a/crates/fayalite/src/sim/vcd.rs +++ b/crates/fayalite/src/sim/vcd.rs @@ -12,11 +12,12 @@ use crate::{ TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, TraceScalar, TraceScalarId, - TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire, TraceWriter, - TraceWriterDecls, + TraceScope, TraceSimOnly, TraceSyncReset, TraceTraceAsString, TraceUInt, TraceWire, + TraceWriter, TraceWriterDecls, time::{SimDuration, SimInstant}, value::DynSimOnlyValue, }, + ty::{OpaqueSimValueSlice, TraceAsString}, util::HashMap, }; use bitvec::{order::Lsb0, slice::BitSlice}; @@ -331,6 +332,7 @@ impl WriteTrace for TraceScalar { Self::AsyncReset(v) => v.write_trace(writer, arg), Self::PhantomConst(v) => v.write_trace(writer, arg), Self::SimOnly(v) => v.write_trace(writer, arg), + Self::TraceAsString(v) => v.write_trace(writer, arg), } } } @@ -726,6 +728,34 @@ impl WriteTrace for TraceSimOnly { } } +impl WriteTrace for TraceTraceAsString { + fn write_trace(self, writer: &mut W, mut arg: A) -> io::Result<()> { + let ArgInType { + source_var_type: _, + sink_var_type: _, + duplex_var_type: _, + properties, + scope, + } = arg.in_type(); + let Self { + location, + name, + ty, + flow: _, + } = self; + write_vcd_var( + properties, + scope, + MemoryElementPartBody::TraceAsString { ty }, + writer, + "string", + 1, + location, + name, + ) + } +} + impl WriteTrace for TraceScope { fn write_trace(self, writer: &mut W, arg: A) -> io::Result<()> { match self { @@ -1093,6 +1123,7 @@ impl TraceWriterDecls for VcdWriterDecls { finished_init: false, timescale, properties, + trace_as_string_buf: String::with_capacity(256), }) } } @@ -1100,6 +1131,7 @@ impl TraceWriterDecls for VcdWriterDecls { enum MemoryElementPartBody { Scalar, EnumDiscriminant { ty: Enum }, + TraceAsString { ty: TraceAsString }, } struct MemoryElementPart { @@ -1217,6 +1249,7 @@ pub struct VcdWriter { finished_init: bool, timescale: SimDuration, properties: VcdWriterProperties, + trace_as_string_buf: String, } impl VcdWriter { @@ -1326,6 +1359,21 @@ impl TraceWriter for VcdWriter { .built_scalar_id_to_vcd_id(first_id + element_index), )? } + MemoryElementPartBody::TraceAsString { ty } => { + self.trace_as_string_buf.clear(); + ty.trace_fmt_append_to_string( + &mut self.trace_as_string_buf, + OpaqueSimValueSlice::from_bitslice(&element_data[start..start + len]), + ); + write_string_value_change( + &mut self.writer, + &self.trace_as_string_buf, + self.properties + .scalar_id_to_vcd_id_map + .built_scalar_id_to_vcd_id(first_id + element_index), + )?; + self.trace_as_string_buf.clear(); + } } } Ok(()) @@ -1419,6 +1467,16 @@ impl TraceWriter for VcdWriter { .built_scalar_id_to_vcd_id(id.as_usize()), ) } + + fn set_signal_string(&mut self, id: TraceScalarId, value: &str) -> Result<(), Self::Error> { + write_string_value_change( + &mut self.writer, + value, + self.properties + .scalar_id_to_vcd_id_map + .built_scalar_id_to_vcd_id(id.as_usize()), + ) + } } impl fmt::Debug for VcdWriter { @@ -1428,6 +1486,7 @@ impl fmt::Debug for VcdWriter { finished_init, timescale, properties: _, + trace_as_string_buf: _, } = self; f.debug_struct("VcdWriter") .field("finished_init", finished_init) diff --git a/crates/fayalite/src/ty.rs b/crates/fayalite/src/ty.rs index ed0ba03..2988a7d 100644 --- a/crates/fayalite/src/ty.rs +++ b/crates/fayalite/src/ty.rs @@ -3,22 +3,27 @@ use crate::{ array::Array, - bundle::Bundle, + bundle::{Bundle, BundleField, BundleType}, clock::Clock, - enum_::Enum, - expr::Expr, + enum_::{Enum, EnumType, EnumVariant}, + expr::{Expr, ToExpr, ValueType, ops}, int::{Bool, SInt, UInt, UIntValue}, - intern::{Intern, Interned}, + intern::{Intern, Interned, LazyInterned, Memoize, SupportsPtrEqWithTypeId}, + module::transform::visit::{Fold, Folder, Visit, Visitor}, phantom_const::PhantomConst, reset::{AsyncReset, Reset, SyncReset}, - sim::value::{DynSimOnly, DynSimOnlyValue, SimValue, ToSimValueWithType}, + sim::value::{DynSimOnly, DynSimOnlyValue, SimValue, ToSimValue, ToSimValueWithType}, source_location::SourceLocation, - util::{ConstUsize, slice_range, try_slice_range}, + util::{ + ConstUsize, iter_eq_by, + serde_by_id::{SerdeByIdProperties, SerdeByIdTable, SerdeByIdTrait}, + slice_range, try_slice_range, + }, }; use bitvec::{slice::BitSlice, vec::BitVec}; use serde::{Deserialize, Deserializer, Serialize, Serializer, de::DeserializeOwned}; use std::{ - fmt, + fmt::{self, Write}, hash::Hash, iter::{FusedIterator, Sum}, marker::PhantomData, @@ -69,6 +74,7 @@ pub enum CanonicalType { Clock(Clock), PhantomConst(PhantomConst), DynSimOnly(DynSimOnly), + TraceAsString(TraceAsString), } impl fmt::Debug for CanonicalType { @@ -86,6 +92,7 @@ impl fmt::Debug for CanonicalType { Self::Clock(v) => v.fmt(f), Self::PhantomConst(v) => v.fmt(f), Self::DynSimOnly(v) => v.fmt(f), + Self::TraceAsString(v) => v.fmt(f), } } } @@ -123,6 +130,7 @@ impl CanonicalType { CanonicalType::Clock(v) => v.type_properties(), CanonicalType::PhantomConst(v) => v.type_properties(), CanonicalType::DynSimOnly(v) => v.type_properties(), + CanonicalType::TraceAsString(v) => v.type_properties(), } } pub fn is_passive(self) -> bool { @@ -217,11 +225,134 @@ impl CanonicalType { }; lhs.can_connect(rhs) } + CanonicalType::TraceAsString(lhs) => { + let CanonicalType::TraceAsString(rhs) = rhs else { + return false; + }; + lhs.can_connect(rhs) + } } } pub(crate) fn as_serde_unexpected_str(self) -> &'static str { serde_impls::SerdeCanonicalType::from(self).as_serde_unexpected_str() } + /// Unwrap transparent types until reaching a non-transparent type. Currently [`TraceAsString`] is the only transparent type. + /// + /// [`TraceAsString`]: struct@TraceAsString + pub fn unwrap_transparent_types(mut self) -> Self { + loop { + self = match self { + Self::UInt(_) + | Self::SInt(_) + | Self::Bool(_) + | Self::Array(_) + | Self::Enum(_) + | Self::Bundle(_) + | Self::AsyncReset(_) + | Self::SyncReset(_) + | Self::Reset(_) + | Self::Clock(_) + | Self::PhantomConst(_) + | Self::DynSimOnly(_) => return self, + Self::TraceAsString(ty) => ty.inner_ty(), + }; + } + } + pub fn is_layout_equivalent(self, other: Self) -> bool { + fn is_bit(ty: CanonicalType) -> bool { + match ty { + CanonicalType::UInt(ty) => ty.width() == 1, + CanonicalType::SInt(_) => false, // SInt<1> doesn't count since it would be -1/0 instead of 1/0 + CanonicalType::Bool(_) + | CanonicalType::AsyncReset(_) + | CanonicalType::SyncReset(_) + | CanonicalType::Reset(_) + | CanonicalType::Clock(_) => true, + CanonicalType::Array(_) + | CanonicalType::Enum(_) + | CanonicalType::Bundle(_) + | CanonicalType::PhantomConst(_) + | CanonicalType::DynSimOnly(_) => false, + CanonicalType::TraceAsString(_) => { + unreachable!("handled by unwrap_transparent_types") + } + } + } + #[derive(Copy, Clone, PartialEq, Eq, Hash)] + struct MyMemoize; + impl Memoize for MyMemoize { + type Input = (CanonicalType, CanonicalType); + type InputOwned = (CanonicalType, CanonicalType); + type Output = bool; + + fn inner(self, input: &Self::Input) -> Self::Output { + let (this, other) = *input; + let this = this.unwrap_transparent_types(); + let other = other.unwrap_transparent_types(); + let this_is_bit = is_bit(this); + let other_is_bit = is_bit(other); + if this_is_bit || other_is_bit { + return this_is_bit && other_is_bit; + } + let this_is_empty = this.size().is_empty(); + let other_is_empty = other.size().is_empty(); + if this_is_empty || other_is_empty { + return this_is_empty && other_is_empty; + } + match this { + CanonicalType::UInt(_) + | CanonicalType::SInt(_) + | CanonicalType::DynSimOnly(_) => this == other, + CanonicalType::Array(this) => { + let CanonicalType::Array(other) = other else { + return false; + }; + this.len() == other.len() + && this.element().is_layout_equivalent(other.element()) + } + CanonicalType::Enum(this) => { + let CanonicalType::Enum(other) = other else { + return false; + }; + iter_eq_by( + this.variants(), + other.variants(), + |EnumVariant { name, ty }, other_variant| { + name == other_variant.name + && ty.unwrap_or_else(|| ().canonical()).is_layout_equivalent( + other_variant.ty.unwrap_or_else(|| ().canonical()), + ) + }, + ) + } + CanonicalType::Bundle(this) => { + let CanonicalType::Bundle(other) = other else { + return false; + }; + iter_eq_by( + this.fields().iter().filter(|f| !f.ty.size().is_empty()), + other.fields().iter().filter(|f| !f.ty.size().is_empty()), + |&BundleField { name, flipped, ty }, other_field| { + name == other_field.name + && flipped == other_field.flipped + && ty.is_layout_equivalent(other_field.ty) + }, + ) + } + CanonicalType::Bool(_) + | CanonicalType::AsyncReset(_) + | CanonicalType::SyncReset(_) + | CanonicalType::Reset(_) + | CanonicalType::Clock(_) => unreachable!("handled by is_bit"), + CanonicalType::PhantomConst(_) => unreachable!("handled by is_empty"), + CanonicalType::TraceAsString(_) => { + unreachable!("handled by unwrap_transparent_types") + } + } + } + } + MyMemoize.get_owned((self, other)) + } } pub trait MatchVariantAndInactiveScope: Sized { @@ -328,6 +459,7 @@ impl_base_type!(Reset); impl_base_type!(Clock); impl_base_type!(PhantomConst); impl_base_type!(DynSimOnly); +impl_base_type!(TraceAsString); impl_base_type_serde!(Bool, "a Bool"); impl_base_type_serde!(Enum, "an Enum"); @@ -336,6 +468,7 @@ impl_base_type_serde!(AsyncReset, "an AsyncReset"); impl_base_type_serde!(SyncReset, "a SyncReset"); impl_base_type_serde!(Reset, "a Reset"); impl_base_type_serde!(Clock, "a Clock"); +impl_base_type_serde!(TraceAsString, "a TraceAsString"); impl sealed::BaseTypeSealed for CanonicalType {} @@ -473,6 +606,7 @@ impl Type for CanonicalType { CanonicalType::Clock(v) => v.mask_type().canonical(), CanonicalType::PhantomConst(v) => v.mask_type().canonical(), CanonicalType::DynSimOnly(v) => v.mask_type().canonical(), + CanonicalType::TraceAsString(v) => v.mask_type().canonical(), } } fn canonical(&self) -> CanonicalType { @@ -757,13 +891,34 @@ impl Sum for OpaqueSimValueSize { } } -#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] +#[derive(PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] pub struct OpaqueSimValue { bits: UIntValue, #[serde(skip_serializing_if = "Vec::is_empty", default)] sim_only_values: Vec, } +impl Clone for OpaqueSimValue { + fn clone(&self) -> Self { + Self { + bits: self.bits.clone(), + sim_only_values: self.sim_only_values.clone(), + } + } + fn clone_from(&mut self, source: &Self) { + let Self { + bits, + sim_only_values, + } = self; + if let Some(bits) = Arc::get_mut(bits.arc_bitvec_mut()) { + bits.clone_from(source.bits.bits()); + } else { + *bits = source.bits.clone(); + } + sim_only_values.clone_from(&source.sim_only_values); + } +} + impl OpaqueSimValue { pub fn empty() -> Self { Self { @@ -842,6 +997,9 @@ impl OpaqueSimValue { pub fn sim_only_values(&self) -> &[DynSimOnlyValue] { &self.sim_only_values } + pub(crate) fn sim_only_values_vec(&self) -> &Vec { + &self.sim_only_values + } pub fn sim_only_values_mut(&mut self) -> &mut Vec { &mut self.sim_only_values } @@ -1143,3 +1301,413 @@ impl Index for AsMaskWithoutGenerics { Interned::into_inner(Intern::intern_sized(ty.mask_type())) } } + +trait TraceAsStringTrait: fmt::Debug + 'static + Send + Sync + SupportsPtrEqWithTypeId { + fn trace_fmt(&self, opaque: OpaqueSimValueSlice<'_>, f: &mut fmt::Formatter<'_>) + -> fmt::Result; + fn serde_by_id_properties(&self) -> SerdeByIdProperties> { + SerdeByIdProperties::of::() + } + fn can_substitute_type(&self, new_type: CanonicalType) -> bool; +} + +impl TraceAsStringTrait for T { + fn trace_fmt( + &self, + opaque: OpaqueSimValueSlice<'_>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(&Type::sim_value_from_opaque(self, opaque), f) + } + fn can_substitute_type(&self, new_type: CanonicalType) -> bool { + self.canonical().is_layout_equivalent(new_type) + } +} + +impl crate::intern::InternedCompare for dyn TraceAsStringTrait { + type InternedCompareKey = crate::intern::PtrEqWithTypeId; + + fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey { + this.get_ptr_eq_with_type_id() + } +} + +impl SerdeByIdTrait for Interned { + fn serde_by_id_properties(&self) -> SerdeByIdProperties { + TraceAsStringTrait::serde_by_id_properties(&**self) + } + + fn static_table() -> &'static SerdeByIdTable { + static TABLE: SerdeByIdTable> = SerdeByIdTable::new(); + &TABLE + } + + const NAME: &'static str = "dyn TraceAsStringTrait"; +} + +/// When running the fayalite simulator, outputs a single string signal containing a formatted version of the inner value (uses [`fmt::Debug`] by default). +/// This is a transparent type, meaning [`CanonicalType::unwrap_transparent_types`] will unwrap this type. +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct TraceAsString { + inner_ty: LazyInterned, + trace_as_string: LazyInterned, +} + +#[expect(non_upper_case_globals)] +pub const TraceAsString: TraceAsStringWithoutGenerics = TraceAsStringWithoutGenerics; + +impl fmt::Debug for TraceAsString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + inner_ty, + trace_as_string: _, + } = self; + f.debug_struct("TraceAsString") + .field("inner_ty", &inner_ty.interned()) + .finish_non_exhaustive() + } +} + +impl TraceAsString { + pub fn new(inner_ty: T) -> Self { + Self::new_interned(inner_ty.intern_sized()) + } + pub fn new_interned(inner_ty: Interned) -> Self { + Self { + inner_ty: LazyInterned::Interned(inner_ty), + trace_as_string: LazyInterned::Interned(Interned::cast_unchecked( + inner_ty, + |v| -> &dyn TraceAsStringTrait { v }, + )), + } + } + pub fn interned_inner_ty(self) -> Interned { + self.inner_ty.interned() + } + pub fn inner_ty(self) -> T { + *self.interned_inner_ty() + } + /// create a new `TraceAsString` but try to keep the old formatting method + pub fn with_new_inner_ty(self, inner_ty: Interned) -> TraceAsString { + if self + .trace_as_string + .can_substitute_type(inner_ty.canonical()) + { + TraceAsString { + inner_ty: LazyInterned::Interned(inner_ty), + trace_as_string: self.trace_as_string, + } + } else { + TraceAsString::new_interned(inner_ty) + } + } + pub fn canonical_trace_as_string(self) -> TraceAsString { + let Self { + inner_ty, + trace_as_string, + } = self; + TraceAsString { + inner_ty: LazyInterned::Interned(inner_ty.interned().canonical().intern_sized()), + trace_as_string, + } + } + pub fn from_canonical_trace_as_string(canonical: TraceAsString) -> Self { + let TraceAsString { + inner_ty, + trace_as_string, + } = canonical; + Self { + inner_ty: LazyInterned::Interned( + T::from_canonical(*inner_ty.interned()).intern_sized(), + ), + trace_as_string, + } + } + pub fn type_properties(self) -> TypeProperties { + self.interned_inner_ty().canonical().type_properties() + } + pub fn can_connect(self, rhs: TraceAsString) -> bool { + self.interned_inner_ty() + .canonical() + .can_connect(rhs.interned_inner_ty().canonical()) + } + pub fn trace_fmt( + self, + opaque: OpaqueSimValueSlice<'_>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + self.trace_as_string.interned().trace_fmt(opaque, f) + } + pub fn trace_fmt_append_to_string(self, output: &mut String, opaque: OpaqueSimValueSlice<'_>) { + fn impl_fn( + trace_as_string: Interned, + output: &mut String, + opaque: OpaqueSimValueSlice<'_>, + ) { + let initial_len = output.len(); + if let Err(fmt::Error {}) = write!( + output, + "{}", + fmt::from_fn(|f| trace_as_string.trace_fmt(opaque, f)) + ) { + output.truncate(initial_len); + output.push_str(""); + } + } + impl_fn(self.trace_as_string.interned(), output, opaque) + } +} + +impl SimValueDebug for TraceAsString { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + T::sim_value_debug(value, f) + } +} + +impl Type for TraceAsString { + type BaseType = TraceAsString; + type MaskType = T::MaskType; + type SimValue = TraceAsStringSimValue; + type MatchVariant = Expr; + type MatchActiveScope = (); + type MatchVariantAndInactiveScope = MatchVariantWithoutScope; + type MatchVariantsIter = std::iter::Once; + + fn match_variants( + this: Expr, + source_location: SourceLocation, + ) -> Self::MatchVariantsIter { + let _ = source_location; + std::iter::once(MatchVariantWithoutScope( + ops::TraceAsStringAsInner::new(this).to_expr(), + )) + } + + fn mask_type(&self) -> Self::MaskType { + self.inner_ty.mask_type() + } + + fn canonical(&self) -> CanonicalType { + CanonicalType::TraceAsString(self.canonical_trace_as_string()) + } + + fn from_canonical(canonical_type: CanonicalType) -> Self { + let CanonicalType::TraceAsString(canonical) = canonical_type else { + panic!("expected TraceAsString"); + }; + Self::from_canonical_trace_as_string(canonical) + } + + fn source_location() -> SourceLocation { + SourceLocation::builtin() + } + + fn sim_value_from_opaque(&self, opaque: OpaqueSimValueSlice<'_>) -> Self::SimValue { + TraceAsStringSimValue { + inner: self.inner_ty.sim_value_from_opaque(opaque), + } + } + + fn sim_value_clone_from_opaque( + &self, + value: &mut Self::SimValue, + opaque: OpaqueSimValueSlice<'_>, + ) { + self.inner_ty + .sim_value_clone_from_opaque(&mut value.inner, opaque); + } + + fn sim_value_to_opaque<'w>( + &self, + value: &Self::SimValue, + writer: OpaqueSimValueWriter<'w>, + ) -> OpaqueSimValueWritten<'w> { + self.inner_ty.sim_value_to_opaque(&value.inner, writer) + } +} + +impl TypeWithDeref for TraceAsString { + fn expr_deref(this: &Expr) -> &Self::MatchVariant { + Interned::into_inner( + ops::TraceAsStringAsInner::new(*this) + .to_expr() + .intern_sized(), + ) + } +} + +struct TraceAsStringStaticTypeHelper(PhantomData); + +impl Default for TraceAsStringStaticTypeHelper { + fn default() -> Self { + Self(PhantomData) + } +} + +impl From> for Interned { + fn from(_value: TraceAsStringStaticTypeHelper) -> Self { + Interned::cast_unchecked(T::TYPE.intern_sized(), |v| -> &dyn TraceAsStringTrait { v }) + } +} + +impl Default for TraceAsString { + fn default() -> Self { + Self::TYPE + } +} + +struct MakeType(Interned); + +impl From> for Interned { + fn from(value: MakeType) -> Self { + value.0 + } +} + +impl Default for MakeType { + fn default() -> Self { + Self(T::TYPE.intern_sized()) + } +} + +impl StaticType for TraceAsString { + const TYPE: Self = Self { + inner_ty: LazyInterned::new_const::>(), + trace_as_string: LazyInterned::new_const::>(), + }; + const MASK_TYPE: Self::MaskType = T::MASK_TYPE; + const TYPE_PROPERTIES: TypeProperties = T::TYPE_PROPERTIES; + const MASK_TYPE_PROPERTIES: TypeProperties = T::MASK_TYPE_PROPERTIES; +} + +#[doc(hidden)] +pub struct TraceAsStringWithoutGenerics; + +impl Index for TraceAsStringWithoutGenerics { + type Output = TraceAsString; + + fn index(&self, inner_ty: T) -> &Self::Output { + Interned::into_inner(TraceAsString::new(inner_ty).intern_sized()) + } +} + +#[derive(Copy, Clone, Eq, Ord, Hash, Default, Serialize, Deserialize)] +pub struct TraceAsStringSimValue { + inner: T, +} + +impl TraceAsStringSimValue { + pub const fn new(inner: T) -> Self { + Self { inner } + } + pub fn into_inner(this: Self) -> T { + let Self { inner } = this; + inner + } +} + +impl ValueType for TraceAsStringSimValue { + type Type = TraceAsString; + type ValueCategory = T::ValueCategory; + + fn ty(&self) -> Self::Type { + TraceAsString::new(self.inner.ty()) + } +} + +impl ToExpr for TraceAsStringSimValue { + fn to_expr(&self) -> Expr { + let inner = self.inner.to_expr(); + ops::AsTraceAsString::new(Expr::canonical(inner), TraceAsString::new(inner.ty())).to_expr() + } +} + +impl, Ty: Type> ToSimValueWithType> + for TraceAsStringSimValue +{ + fn to_sim_value_with_type(&self, ty: TraceAsString) -> SimValue> { + let inner = self.inner.to_sim_value_with_type(ty.inner_ty()); + let inner = SimValue::into_value(inner); + SimValue::from_value(ty, TraceAsStringSimValue { inner }) + } + fn into_sim_value_with_type(self, ty: TraceAsString) -> SimValue> { + let inner = self.inner.into_sim_value_with_type(ty.inner_ty()); + let inner = SimValue::into_value(inner); + SimValue::from_value(ty, TraceAsStringSimValue { inner }) + } +} + +impl ToSimValue for TraceAsStringSimValue { + fn to_sim_value(&self) -> SimValue { + self.to_sim_value_with_type(self.ty()) + } + fn into_sim_value(self) -> SimValue { + let ty = self.ty(); + self.into_sim_value_with_type(ty) + } +} + +impl std::ops::Deref for TraceAsStringSimValue { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl std::ops::DerefMut for TraceAsStringSimValue { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl fmt::Debug for TraceAsStringSimValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { inner } = self; + fmt::Debug::fmt(inner, f) + } +} + +impl fmt::Display for TraceAsStringSimValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { inner } = self; + fmt::Display::fmt(inner, f) + } +} + +impl, U> PartialOrd> for TraceAsStringSimValue { + fn partial_cmp(&self, other: &TraceAsStringSimValue) -> Option { + let Self { inner } = self; + inner.partial_cmp(&other.inner) + } +} + +impl, U> PartialEq> for TraceAsStringSimValue { + fn eq(&self, other: &TraceAsStringSimValue) -> bool { + let Self { inner } = self; + *inner == other.inner + } +} + +impl, State: ?Sized + Folder> Fold for TraceAsString { + fn fold(self, state: &mut State) -> Result { + state.fold_trace_as_string(self) + } + + fn default_fold(self, state: &mut State) -> Result { + Ok(self.with_new_inner_ty(self.interned_inner_ty().fold(state)?)) + } +} + +impl, State: ?Sized + Visitor> Visit for TraceAsString { + fn visit(&self, state: &mut State) -> Result<(), ::Error> { + state.visit_trace_as_string(self) + } + + fn default_visit(&self, state: &mut State) -> Result<(), ::Error> { + self.interned_inner_ty().visit(state) + } +} diff --git a/crates/fayalite/src/ty/serde_impls.rs b/crates/fayalite/src/ty/serde_impls.rs index af324f9..126c4b0 100644 --- a/crates/fayalite/src/ty/serde_impls.rs +++ b/crates/fayalite/src/ty/serde_impls.rs @@ -12,7 +12,8 @@ use crate::{ prelude::PhantomConst, reset::{AsyncReset, Reset, SyncReset}, sim::value::DynSimOnly, - ty::{BaseType, CanonicalType}, + ty::{BaseType, CanonicalType, TraceAsString, TraceAsStringTrait}, + util::serde_by_id::SerdeById, }; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -65,6 +66,10 @@ pub(crate) enum SerdeCanonicalType< Clock, PhantomConst(ThePhantomConst), DynSimOnly(DynSimOnly), + TraceAsString { + inner_ty: Interned, + trace_as_string: SerdeById>, + }, } impl SerdeCanonicalType { @@ -82,6 +87,7 @@ impl SerdeCanonicalType "a Clock", Self::PhantomConst(_) => "a PhantomConst", Self::DynSimOnly(_) => "a SimOnlyValue", + Self::TraceAsString { .. } => "a TraceAsString", } } } @@ -109,6 +115,15 @@ impl From for SerdeCanonicalType { CanonicalType::Clock(Clock {}) => Self::Clock, CanonicalType::PhantomConst(ty) => Self::PhantomConst(SerdePhantomConst(ty.get())), CanonicalType::DynSimOnly(ty) => Self::DynSimOnly(ty), + CanonicalType::TraceAsString(TraceAsString { + inner_ty, + trace_as_string, + }) => Self::TraceAsString { + inner_ty: inner_ty.interned(), + trace_as_string: SerdeById { + inner: trace_as_string.interned(), + }, + }, } } } @@ -130,6 +145,13 @@ impl From for CanonicalType { Self::PhantomConst(PhantomConst::new_interned(value.0)) } SerdeCanonicalType::DynSimOnly(value) => Self::DynSimOnly(value), + SerdeCanonicalType::TraceAsString { + inner_ty, + trace_as_string, + } => Self::TraceAsString(TraceAsString { + inner_ty: crate::intern::LazyInterned::Interned(inner_ty), + trace_as_string: crate::intern::LazyInterned::Interned(trace_as_string.inner), + }), } } } diff --git a/crates/fayalite/src/util.rs b/crates/fayalite/src/util.rs index f1457de..6845d3c 100644 --- a/crates/fayalite/src/util.rs +++ b/crates/fayalite/src/util.rs @@ -46,3 +46,4 @@ pub(crate) use misc::{InternedStrCompareAsStr, chain, copy_le_bytes_to_bitslice} pub mod job_server; pub mod prefix_sum; pub mod ready_valid; +pub(crate) mod serde_by_id; diff --git a/crates/fayalite/src/util/serde_by_id.rs b/crates/fayalite/src/util/serde_by_id.rs new file mode 100644 index 0000000..3db4ab6 --- /dev/null +++ b/crates/fayalite/src/util/serde_by_id.rs @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// See Notices.txt for copyright information + +use crate::util::HashMap; +use hashbrown::hash_map::Entry; +use serde::{Deserialize, Serialize, de::Error}; +use std::{ + any::TypeId, + borrow::Cow, + fmt::Write, + hash::{BuildHasher, Hash, Hasher}, + marker::PhantomData, + sync::Mutex, +}; + +pub(crate) struct SerdeByIdProperties { + type_id: TypeId, + type_name: &'static str, + _phantom: PhantomData T>, +} + +impl Clone for SerdeByIdProperties { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for SerdeByIdProperties {} + +impl SerdeByIdProperties { + pub fn of() -> Self { + Self { + type_id: TypeId::of::(), + type_name: std::any::type_name::(), + _phantom: PhantomData, + } + } +} + +pub(crate) trait SerdeByIdTrait: Hash + Eq + Clone + 'static + Send { + fn serde_by_id_properties(&self) -> SerdeByIdProperties; + fn static_table() -> &'static SerdeByIdTable; + const NAME: &'static str; +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] +#[serde(transparent)] +struct SerdeRandomId([u32; 4]); + +#[derive(Serialize, Deserialize)] +pub(crate) struct SerdeId<'a, T: SerdeByIdTrait> { + random_id: SerdeRandomId, + #[serde(borrow)] + type_name: Cow<'a, str>, + #[serde(skip)] + _phantom: PhantomData T>, +} + +impl<'a, T: SerdeByIdTrait> Clone for SerdeId<'a, T> { + fn clone(&self) -> Self { + Self { + random_id: self.random_id, + type_name: self.type_name.clone(), + _phantom: PhantomData, + } + } +} + +impl<'a, T: SerdeByIdTrait> Eq for SerdeId<'a, T> {} + +impl<'a, 'b, T: SerdeByIdTrait> PartialEq> for SerdeId<'a, T> { + fn eq(&self, other: &SerdeId<'b, T>) -> bool { + let Self { + random_id, + type_name, + _phantom: _, + } = self; + *random_id == other.random_id && *type_name == other.type_name + } +} + +impl<'a, T: SerdeByIdTrait> Hash for SerdeId<'a, T> { + fn hash(&self, state: &mut H) { + let Self { + random_id, + type_name: _, + _phantom: _, + } = self; + random_id.hash(state); + } +} + +struct SerdeByIdTableRest { + from_serde: HashMap, T>, + serde_id_random_state: std::hash::RandomState, + buffer: String, +} + +impl Default for SerdeByIdTableRest { + fn default() -> Self { + Self { + from_serde: Default::default(), + serde_id_random_state: Default::default(), + buffer: Default::default(), + } + } +} + +impl SerdeByIdTableRest { + fn add_new(&mut self, value: T) -> SerdeId<'static, T> { + let properties = value.serde_by_id_properties(); + let mut try_number = 0u64; + let mut hasher = self.serde_id_random_state.build_hasher(); + // extract more bits of randomness from TypeId -- its Hash impl only hashes 64-bits + write!(self.buffer, "{:?}", properties.type_id).expect("shouldn't ever fail"); + self.buffer.hash(&mut hasher); + loop { + let mut hasher = hasher.clone(); + try_number.hash(&mut hasher); + try_number += 1; + let key = SerdeId { + random_id: SerdeRandomId(std::array::from_fn(|i| { + let mut hasher = hasher.clone(); + i.hash(&mut hasher); + hasher.finish() as u32 + })), + type_name: Cow::Borrowed(properties.type_name), + _phantom: PhantomData, + }; + match self.from_serde.entry(key) { + Entry::Occupied(_) => continue, + Entry::Vacant(e) => { + let key = e.key().clone(); + e.insert(value); + return key; + } + } + } + } +} + +pub(crate) struct SerdeByIdTableMut { + to_serde: HashMap>, + rest: SerdeByIdTableRest, +} + +impl Default for SerdeByIdTableMut { + fn default() -> Self { + Self { + to_serde: Default::default(), + rest: Default::default(), + } + } +} + +impl SerdeByIdTableMut { + pub(crate) fn to_serde(&mut self, value: &T) -> SerdeId<'static, T> { + if let Some(retval) = self.to_serde.get(value) { + return retval.clone(); + } + self.to_serde_insert(value) + } + #[cold] + fn to_serde_insert(&mut self, value: &T) -> SerdeId<'static, T> { + let value = value.clone(); + let retval = self.rest.add_new(value.clone()); + self.to_serde.insert(value, retval.clone()); + retval + } + pub(crate) fn from_serde(&self, id: &SerdeId<'_, T>) -> Option { + self.rest.from_serde.get(id).cloned() + } +} + +pub(crate) struct SerdeByIdTable(Mutex>>); + +impl SerdeByIdTable { + pub(crate) const fn new() -> Self { + Self(Mutex::new(None)) + } + pub(crate) fn to_serde(&self, value: &T) -> SerdeId<'static, T> { + self.0 + .lock() + .expect("shouldn't be poison") + .get_or_insert_with( + #[cold] + || Default::default(), + ) + .to_serde(value) + } + pub(crate) fn from_serde(&self, id: &SerdeId<'_, T>) -> Option { + self.0 + .lock() + .expect("shouldn't be poison") + .get_or_insert_with( + #[cold] + || Default::default(), + ) + .from_serde(id) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, Ord, PartialOrd)] +pub(crate) struct SerdeById { + pub(crate) inner: T, +} + +impl<'de, T: SerdeByIdTrait> Deserialize<'de> for SerdeById { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let id = SerdeId::deserialize(deserializer)?; + let inner = T::static_table().from_serde(&id).ok_or_else(|| { + D::Error::custom(format_args!( + "doesn't match any {} that was serialized this time this program was run: type_name={:?}", + T::NAME, + id.type_name, + )) + })?; + Ok(Self { inner }) + } +} + +impl Serialize for SerdeById { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + T::static_table() + .to_serde(&self.inner) + .serialize(serializer) + } +} diff --git a/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs b/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs index 3e1ac0c..2d498e7 100644 --- a/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs +++ b/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs @@ -546,7 +546,7 @@ impl Visitor for XdcFileWriter { base.source_location(), )? {}, } - match base.canonical_ty() { + match base.canonical_ty().unwrap_transparent_types() { CanonicalType::UInt(_) | CanonicalType::SInt(_) | CanonicalType::Bool(_) @@ -563,6 +563,9 @@ impl Visitor for XdcFileWriter { v, base.source_location(), )? {}, + CanonicalType::TraceAsString(_) => { + unreachable!("handled by unwrap_transparent_types") + } } self.required_dont_touch_targets.insert(target); match v { diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index 53f7d9d..238259c 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -1,12 +1,19 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information +use bitvec::{order::Lsb0, view::BitView}; use fayalite::{ - memory::{ReadStruct, ReadWriteStruct, WriteStruct}, - module::{instance_with_loc, memory_with_init_and_loc, reg_builder_with_loc}, + assert_export_firrtl, + firrtl::ExportOptions, + memory::{ReadStruct, ReadWriteStruct, WriteStruct, splat_mask}, + module::{ + instance_with_loc, memory_with_init_and_loc, reg_builder_with_loc, + transform::simplify_enums::SimplifyEnumsKind, + }, prelude::*, reset::ResetType, sim::vcd::VcdWriterDecls, + ty::{SimValueDebug, StaticType, TraceAsString, TraceAsStringSimValue}, util::{RcWriter, ready_valid::queue}, }; use std::{collections::BTreeMap, num::NonZeroUsize, rc::Rc}; @@ -2985,3 +2992,621 @@ fn test_queue_4_true_true() { include_str!("sim/expected/queue_4_true_true.txt"), ); } + +#[hdl(outline_generated, custom_debug(sim), cmp_eq)] +pub enum HasCustomDebug { + Text(UInt<512>), + FmtError, +} + +impl HasCustomDebug { + #[hdl] + pub fn new_sim(text: Result<&str, std::fmt::Error>) -> SimValue { + match text { + Ok(text) => { + let mut retval = HasCustomDebug.Text.zero(); + let src = text.as_bytes().view_bits::(); + let dest = retval.bits_mut(); + let len = src.len().min(dest.len()); + dest[..len].clone_from_bitslice(&src[..len]); + #[hdl(sim)] + HasCustomDebug.Text(retval) + } + Err(std::fmt::Error) => + { + #[hdl(sim)] + HasCustomDebug.FmtError() + } + } + } +} + +impl SimValueDebug for HasCustomDebug { + #[hdl] + fn sim_value_debug( + value: &::SimValue, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + if f.alternate() { + return #[hdl(sim)] + match value { + Self::FmtError => f.write_str("FmtError"), + Self::Text(text) => f.debug_tuple("Text").field(text).finish(), + }; + } + #[hdl(sim)] + match value { + Self::FmtError => Err(std::fmt::Error), + Self::Text(text) => { + assert_eq!(text.ty().width() % u8::BITS as usize, 0); + let mut bytes = vec![0u8; text.ty().width() / u8::BITS as usize]; + bytes + .view_bits_mut::() + .clone_from_bitslice(text.bits()); + if let Some(len) = bytes.iter().position(|b| *b == 0) { + bytes.truncate(len); + } + f.write_str(&String::from_utf8_lossy(&bytes)) + } + } + } +} + +#[hdl_module(outline_generated)] +pub fn sim_trace_as_string() { + #[hdl] + let clk: Clock = m.input(); + #[hdl] + let read: ReadStruct>, ConstUsize<8>> = m.input(); + #[hdl] + let write: WriteStruct, 2>, ConstUsize<8>> = m.input(); + #[hdl] + let mut mem = memory_with_init( + [[Expr::as_trace_as_string(HasCustomDebug::new_sim(Ok("")).to_expr(), StaticType::TYPE); 2]; + 4], + ); + let read_port = mem.new_read_port(); + connect(read_port.clk, clk); + connect_any(read_port.addr, read.addr); + connect(read_port.en, read.en); + for (l, r) in read.data.iter().zip(read_port.data.iter()) { + connect(l, &**r); + } + let write_port = mem.new_write_port(); + connect(write_port.clk, clk); + connect_any(write_port.addr, write.addr); + connect(write_port.data, write.data); + connect(write_port.en, write.en); + connect(write_port.mask, write.mask); +} + +#[hdl] +#[test] +fn test_sim_trace_as_string() { + let _n = SourceLocation::normalize_files_for_tests(); + let m = sim_trace_as_string(); + let mut sim = Simulation::new(m); + // sim.set_breakpoints_unstable(Default::default(), true); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + sim.write(sim.io().clk, false); + sim.write(sim.io().read.clk, false); + sim.write(sim.io().write.clk, false); + #[derive(Debug)] + struct TestCase { + read: Option<(u8, [Result<&'static str, std::fmt::Error>; 2])>, + write_addr: Option, + write_data: [Result<&'static str, std::fmt::Error>; 2], + write_mask: [bool; 2], + } + const TEST_CASES: &[TestCase] = &[ + TestCase { + read: None, + write_addr: None, + write_data: [Ok(""); 2], + write_mask: [false; 2], + }, + TestCase { + read: None, + write_addr: Some(0), + write_data: [Ok("mem[0][0]"), Ok("mem[0][1]")], + write_mask: [true; 2], + }, + TestCase { + read: None, + write_addr: Some(1), + write_data: [Ok("mem[1][0]"), Ok("mem[1][1]")], + write_mask: [true; 2], + }, + TestCase { + read: None, + write_addr: Some(2), + write_data: [Ok("mem[2][0]"), Ok("mem[2][1]")], + write_mask: [true; 2], + }, + TestCase { + read: None, + write_addr: Some(3), + write_data: [Ok("mem[3][0]"), Ok("mem[3][1]")], + write_mask: [true; 2], + }, + TestCase { + read: Some((1, [Ok("mem[1][0]"), Ok("mem[1][1]")])), + write_addr: None, + write_data: [Err(std::fmt::Error), Err(std::fmt::Error)], + write_mask: [true; 2], + }, + TestCase { + read: Some((1, [Err(std::fmt::Error), Err(std::fmt::Error)])), + write_addr: Some(1), + write_data: [Err(std::fmt::Error), Err(std::fmt::Error)], + write_mask: [true; 2], + }, + ]; + for test_case in TEST_CASES { + let TestCase { + read, + write_addr, + write_data, + write_mask, + } = test_case; + sim.write(sim.io().read.addr, read.map(|v| v.0).unwrap_or(0)); + sim.write(sim.io().read.en, read.is_some()); + sim.write(sim.io().write.addr, write_addr.unwrap_or(0)); + sim.write(sim.io().write.en, write_addr.is_some()); + sim.write( + sim.io().write.data, + write_data.map(|v| TraceAsStringSimValue::new(HasCustomDebug::new_sim(v))), + ); + sim.write( + sim.io().write.mask, + write_mask.map(|v| splat_mask(TraceAsString[HasCustomDebug], v.to_expr())), + ); + sim.write(sim.io().clk, false); + sim.advance_time(SimDuration::from_nanos(500)); + sim.write(sim.io().clk, true); + sim.advance_time(SimDuration::from_nanos(500)); + if let Some((_, expected_read_data)) = read { + let read_data = sim.read(sim.io().read.data); + let expected_read_data = expected_read_data + .map(HasCustomDebug::new_sim) + .into_sim_value(); + assert!( + **read_data == *expected_read_data, + "{read_data:#?}\n!= {expected_read_data:#?}", + ); + } + } + sim.flush_traces().unwrap(); + let vcd = String::from_utf8(writer.take()).unwrap(); + println!("####### VCD:\n{vcd}\n#######"); + if vcd != include_str!("sim/expected/sim_trace_as_string.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/sim_trace_as_string.txt") { + panic!(); + } +} + +#[test] +fn test_firrtl_trace_as_string() { + let _n = SourceLocation::normalize_files_for_tests(); + let m = sim_trace_as_string(); + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_memories: false, + simplify_enums: None, + ..ExportOptions::default() + }, + "/test/sim_trace_as_string.fir": r#"FIRRTL version 3.2.0 +circuit sim_trace_as_string: %[[ + { + "class": "firrtl.annotations.MemoryFileInlineAnnotation", + "filename": "/test/sim_trace_as_string/mem.mem", + "hexOrBinary": "b", + "target": "~sim_trace_as_string|sim_trace_as_string>mem" + } +]] + type Ty0 = {|Text: UInt<512>, FmtError|} + type Ty1 = {addr: UInt<8>, en: UInt<1>, clk: Clock, flip data: Ty0[2]} + type Ty2 = {addr: UInt<8>, en: UInt<1>, clk: Clock, data: Ty0[2], mask: UInt<1>[2]} + type Ty3 = {addr: UInt<2>, en: UInt<1>, clk: Clock, flip data: Ty0[2]} + type Ty4 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: Ty0[2], mask: UInt<1>[2]} + module sim_trace_as_string: @[module-XXXXXXXXXX.rs 1:1] + input clk: Clock @[module-XXXXXXXXXX.rs 2:1] + input `read`: Ty1 @[module-XXXXXXXXXX.rs 3:1] + input `write`: Ty2 @[module-XXXXXXXXXX.rs 4:1] + mem `mem`: @[module-XXXXXXXXXX.rs 5:1] + data-type => Ty0[2] + depth => 4 + read-latency => 0 + write-latency => 1 + read-under-write => old + reader => r0 + writer => w1 + connect `mem`.r0.clk, clk @[module-XXXXXXXXXX.rs 7:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect `mem`.r0.addr, `read`.addr @[module-XXXXXXXXXX.rs 8:1] + connect `mem`.r0.en, `read`.en @[module-XXXXXXXXXX.rs 9:1] + connect `read`.data[0], `mem`.r0.data[0] @[module-XXXXXXXXXX.rs 10:1] + connect `read`.data[1], `mem`.r0.data[1] @[module-XXXXXXXXXX.rs 10:1] + connect `mem`.w1.clk, clk @[module-XXXXXXXXXX.rs 12:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect `mem`.w1.addr, `write`.addr @[module-XXXXXXXXXX.rs 13:1] + connect `mem`.w1.data, `write`.data @[module-XXXXXXXXXX.rs 14:1] + connect `mem`.w1.en, `write`.en @[module-XXXXXXXXXX.rs 15:1] + connect `mem`.w1.mask, `write`.mask @[module-XXXXXXXXXX.rs 16:1] +"#, + "/test/sim_trace_as_string/mem.mem": r"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_memories: true, + simplify_enums: None, + ..ExportOptions::default() + }, + "/test/sim_trace_as_string.fir": r#"FIRRTL version 3.2.0 +circuit sim_trace_as_string: %[[ + { + "class": "firrtl.annotations.MemoryFileInlineAnnotation", + "filename": "/test/sim_trace_as_string/mem.mem", + "hexOrBinary": "b", + "target": "~sim_trace_as_string|sim_trace_as_string>mem" + } +]] + type Ty0 = {|Text: UInt<512>, FmtError|} + type Ty1 = {addr: UInt<8>, en: UInt<1>, clk: Clock, flip data: Ty0[2]} + type Ty2 = {addr: UInt<8>, en: UInt<1>, clk: Clock, data: Ty0[2], mask: UInt<1>[2]} + type Ty3 = {addr: UInt<2>, en: UInt<1>, clk: Clock, flip data: Ty0[2]} + type Ty4 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: Ty0[2], mask: UInt<1>[2]} + type Ty5 = {addr: UInt<2>, en: UInt<1>, clk: Clock, flip data: UInt<513>[2]} + type Ty6 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: UInt<513>[2], mask: UInt<1>[2]} + module sim_trace_as_string: @[module-XXXXXXXXXX.rs 1:1] + input clk: Clock @[module-XXXXXXXXXX.rs 2:1] + input `read`: Ty1 @[module-XXXXXXXXXX.rs 3:1] + input `write`: Ty2 @[module-XXXXXXXXXX.rs 4:1] + mem `mem`: @[module-XXXXXXXXXX.rs 5:1] + data-type => UInt<513>[2] + depth => 4 + read-latency => 0 + write-latency => 1 + read-under-write => old + reader => r0 + writer => w1 + wire mem_r0: Ty3 @[module-XXXXXXXXXX.rs 6:1] + wire mem_w1: Ty4 @[module-XXXXXXXXXX.rs 11:1] + wire _cast_bits_to_enum_expr: Ty0 + wire _cast_bits_to_enum_expr_body: UInt<512> + connect _cast_bits_to_enum_expr_body, head(`mem`.r0.data[0], 512) + when eq(UInt<1>(0), tail(`mem`.r0.data[0], 512)): + connect _cast_bits_to_enum_expr, {|Text: UInt<512>, FmtError|}(Text, _cast_bits_to_enum_expr_body) + else: + connect _cast_bits_to_enum_expr, {|Text: UInt<512>, FmtError|}(FmtError) + connect mem_r0.data[0], _cast_bits_to_enum_expr @[module-XXXXXXXXXX.rs 6:1] + wire _cast_bits_to_enum_expr_1: Ty0 + wire _cast_bits_to_enum_expr_body_1: UInt<512> + connect _cast_bits_to_enum_expr_body_1, head(`mem`.r0.data[1], 512) + when eq(UInt<1>(0), tail(`mem`.r0.data[1], 512)): + connect _cast_bits_to_enum_expr_1, {|Text: UInt<512>, FmtError|}(Text, _cast_bits_to_enum_expr_body_1) + else: + connect _cast_bits_to_enum_expr_1, {|Text: UInt<512>, FmtError|}(FmtError) + connect mem_r0.data[1], _cast_bits_to_enum_expr_1 @[module-XXXXXXXXXX.rs 6:1] + wire _cast_enum_to_bits_expr: UInt<513> + match mem_w1.data[0]: + Text(_cast_enum_to_bits_expr_Text): + connect _cast_enum_to_bits_expr, pad(cat(_cast_enum_to_bits_expr_Text, UInt<1>(0)), 513) + FmtError: + connect _cast_enum_to_bits_expr, UInt<513>(1) + connect `mem`.w1.data[0], _cast_enum_to_bits_expr @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.mask[0], mem_w1.mask[0] @[module-XXXXXXXXXX.rs 11:1] + wire _cast_enum_to_bits_expr_1: UInt<513> + match mem_w1.data[1]: + Text(_cast_enum_to_bits_expr_Text_1): + connect _cast_enum_to_bits_expr_1, pad(cat(_cast_enum_to_bits_expr_Text_1, UInt<1>(0)), 513) + FmtError: + connect _cast_enum_to_bits_expr_1, UInt<513>(1) + connect `mem`.w1.data[1], _cast_enum_to_bits_expr_1 @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.mask[1], mem_w1.mask[1] @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.r0.addr, mem_r0.addr @[module-XXXXXXXXXX.rs 6:1] + connect `mem`.r0.clk, mem_r0.clk @[module-XXXXXXXXXX.rs 6:1] + connect `mem`.r0.en, mem_r0.en @[module-XXXXXXXXXX.rs 6:1] + connect `mem`.w1.addr, mem_w1.addr @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.clk, mem_w1.clk @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.en, mem_w1.en @[module-XXXXXXXXXX.rs 11:1] + connect mem_r0.clk, clk @[module-XXXXXXXXXX.rs 7:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect mem_r0.addr, `read`.addr @[module-XXXXXXXXXX.rs 8:1] + connect mem_r0.en, `read`.en @[module-XXXXXXXXXX.rs 9:1] + connect `read`.data[0], mem_r0.data[0] @[module-XXXXXXXXXX.rs 10:1] + connect `read`.data[1], mem_r0.data[1] @[module-XXXXXXXXXX.rs 10:1] + connect mem_w1.clk, clk @[module-XXXXXXXXXX.rs 12:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect mem_w1.addr, `write`.addr @[module-XXXXXXXXXX.rs 13:1] + connect mem_w1.data, `write`.data @[module-XXXXXXXXXX.rs 14:1] + connect mem_w1.en, `write`.en @[module-XXXXXXXXXX.rs 15:1] + connect mem_w1.mask, `write`.mask @[module-XXXXXXXXXX.rs 16:1] +"#, + "/test/sim_trace_as_string/mem.mem": r"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_memories: false, + simplify_enums: Some(SimplifyEnumsKind::SimplifyToEnumsWithNoBody), + ..ExportOptions::default() + }, + "/test/sim_trace_as_string.fir": r#"FIRRTL version 3.2.0 +circuit sim_trace_as_string: %[[ + { + "class": "firrtl.annotations.MemoryFileInlineAnnotation", + "filename": "/test/sim_trace_as_string/mem.mem", + "hexOrBinary": "b", + "target": "~sim_trace_as_string|sim_trace_as_string>mem" + } +]] + type Ty0 = {|Text, FmtError|} + type Ty1 = {tag: Ty0, body: UInt<512>} + type Ty2 = {addr: UInt<8>, en: UInt<1>, clk: Clock, flip data: Ty1[2]} + type Ty3 = {addr: UInt<8>, en: UInt<1>, clk: Clock, data: Ty1[2], mask: UInt<1>[2]} + type Ty4 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: Ty1[2], mask: UInt<1>[2]} + type Ty5 = {tag: UInt<1>, body: UInt<1>} + type Ty6 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: Ty1[2], mask: Ty5[2]} + type Ty7 = {addr: UInt<2>, en: UInt<1>, clk: Clock, flip data: Ty1[2]} + module sim_trace_as_string: @[module-XXXXXXXXXX.rs 1:1] + input clk: Clock @[module-XXXXXXXXXX.rs 2:1] + input `read`: Ty2 @[module-XXXXXXXXXX.rs 3:1] + input `write`: Ty3 @[module-XXXXXXXXXX.rs 4:1] + mem `mem`: @[module-XXXXXXXXXX.rs 5:1] + data-type => Ty1[2] + depth => 4 + read-latency => 0 + write-latency => 1 + read-under-write => old + reader => r0 + writer => w1 + wire mem_w1: Ty4 @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.addr, mem_w1.addr @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.en, mem_w1.en @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.clk, mem_w1.clk @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.data, mem_w1.data @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.mask[0].tag, mem_w1.mask[0] @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.mask[0].body, mem_w1.mask[0] @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.mask[1].tag, mem_w1.mask[1] @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.w1.mask[1].body, mem_w1.mask[1] @[module-XXXXXXXXXX.rs 11:1] + connect `mem`.r0.clk, clk @[module-XXXXXXXXXX.rs 7:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect `mem`.r0.addr, `read`.addr @[module-XXXXXXXXXX.rs 8:1] + connect `mem`.r0.en, `read`.en @[module-XXXXXXXXXX.rs 9:1] + connect `read`.data[0], `mem`.r0.data[0] @[module-XXXXXXXXXX.rs 10:1] + connect `read`.data[1], `mem`.r0.data[1] @[module-XXXXXXXXXX.rs 10:1] + connect mem_w1.clk, clk @[module-XXXXXXXXXX.rs 12:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect mem_w1.addr, `write`.addr @[module-XXXXXXXXXX.rs 13:1] + connect mem_w1.data, `write`.data @[module-XXXXXXXXXX.rs 14:1] + connect mem_w1.en, `write`.en @[module-XXXXXXXXXX.rs 15:1] + connect mem_w1.mask, `write`.mask @[module-XXXXXXXXXX.rs 16:1] +"#, + "/test/sim_trace_as_string/mem.mem": r"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_memories: true, + simplify_enums: Some(SimplifyEnumsKind::SimplifyToEnumsWithNoBody), + ..ExportOptions::default() + }, + "/test/sim_trace_as_string.fir": r#"FIRRTL version 3.2.0 +circuit sim_trace_as_string: %[[ + { + "class": "firrtl.annotations.MemoryFileInlineAnnotation", + "filename": "/test/sim_trace_as_string/mem_0_tag.mem", + "hexOrBinary": "b", + "target": "~sim_trace_as_string|sim_trace_as_string>mem_0_tag" + }, + { + "class": "firrtl.annotations.MemoryFileInlineAnnotation", + "filename": "/test/sim_trace_as_string/mem_0_body.mem", + "hexOrBinary": "h", + "target": "~sim_trace_as_string|sim_trace_as_string>mem_0_body" + }, + { + "class": "firrtl.annotations.MemoryFileInlineAnnotation", + "filename": "/test/sim_trace_as_string/mem_1_tag.mem", + "hexOrBinary": "b", + "target": "~sim_trace_as_string|sim_trace_as_string>mem_1_tag" + }, + { + "class": "firrtl.annotations.MemoryFileInlineAnnotation", + "filename": "/test/sim_trace_as_string/mem_1_body.mem", + "hexOrBinary": "h", + "target": "~sim_trace_as_string|sim_trace_as_string>mem_1_body" + } +]] + type Ty0 = {|Text, FmtError|} + type Ty1 = {tag: Ty0, body: UInt<512>} + type Ty2 = {addr: UInt<8>, en: UInt<1>, clk: Clock, flip data: Ty1[2]} + type Ty3 = {addr: UInt<8>, en: UInt<1>, clk: Clock, data: Ty1[2], mask: UInt<1>[2]} + type Ty4 = {addr: UInt<2>, en: UInt<1>, clk: Clock, flip data: Ty1[2]} + type Ty5 = {tag: UInt<1>, body: UInt<1>} + type Ty6 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: Ty1[2], mask: Ty5[2]} + type Ty7 = {addr: UInt<2>, en: UInt<1>, clk: Clock, flip data: UInt<1>} + type Ty8 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: UInt<1>, mask: UInt<1>} + type Ty9 = {addr: UInt<2>, en: UInt<1>, clk: Clock, flip data: UInt<512>} + type Ty10 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: UInt<512>, mask: UInt<1>} + type Ty11 = {addr: UInt<2>, en: UInt<1>, clk: Clock, data: Ty1[2], mask: UInt<1>[2]} + module sim_trace_as_string: @[module-XXXXXXXXXX.rs 1:1] + input clk: Clock @[module-XXXXXXXXXX.rs 2:1] + input `read`: Ty2 @[module-XXXXXXXXXX.rs 3:1] + input `write`: Ty3 @[module-XXXXXXXXXX.rs 4:1] + mem mem_0_tag: @[module-XXXXXXXXXX.rs 5:1] + data-type => UInt<1> + depth => 4 + read-latency => 0 + write-latency => 1 + read-under-write => old + reader => r0 + writer => w1 + mem mem_0_body: @[module-XXXXXXXXXX.rs 5:1] + data-type => UInt<512> + depth => 4 + read-latency => 0 + write-latency => 1 + read-under-write => old + reader => r0 + writer => w1 + mem mem_1_tag: @[module-XXXXXXXXXX.rs 5:1] + data-type => UInt<1> + depth => 4 + read-latency => 0 + write-latency => 1 + read-under-write => old + reader => r0 + writer => w1 + mem mem_1_body: @[module-XXXXXXXXXX.rs 5:1] + data-type => UInt<512> + depth => 4 + read-latency => 0 + write-latency => 1 + read-under-write => old + reader => r0 + writer => w1 + wire mem_r0: Ty4 @[module-XXXXXXXXXX.rs 6:1] + wire mem_w1: Ty6 @[module-XXXXXXXXXX.rs 11:1] + wire _cast_bits_to_enum_expr: Ty0 + when eq(UInt<1>(0), tail(mem_0_tag.r0.data, 0)): + connect _cast_bits_to_enum_expr, {|Text, FmtError|}(Text) + else: + connect _cast_bits_to_enum_expr, {|Text, FmtError|}(FmtError) + connect mem_r0.data[0].tag, _cast_bits_to_enum_expr @[module-XXXXXXXXXX.rs 6:1] + wire _cast_enum_to_bits_expr: UInt<1> + match mem_w1.data[0].tag: + Text: + connect _cast_enum_to_bits_expr, UInt<1>(0) + FmtError: + connect _cast_enum_to_bits_expr, UInt<1>(1) + connect mem_0_tag.w1.data, _cast_enum_to_bits_expr @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_tag.w1.mask, mem_w1.mask[0].tag @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_tag.r0.addr, mem_r0.addr @[module-XXXXXXXXXX.rs 6:1] + connect mem_0_tag.r0.clk, mem_r0.clk @[module-XXXXXXXXXX.rs 6:1] + connect mem_0_tag.r0.en, mem_r0.en @[module-XXXXXXXXXX.rs 6:1] + connect mem_0_tag.w1.addr, mem_w1.addr @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_tag.w1.clk, mem_w1.clk @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_tag.w1.en, mem_w1.en @[module-XXXXXXXXXX.rs 11:1] + connect mem_r0.data[0].body, mem_0_body.r0.data @[module-XXXXXXXXXX.rs 6:1] + connect mem_0_body.w1.data, mem_w1.data[0].body @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_body.w1.mask, mem_w1.mask[0].body @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_body.r0.addr, mem_r0.addr @[module-XXXXXXXXXX.rs 6:1] + connect mem_0_body.r0.clk, mem_r0.clk @[module-XXXXXXXXXX.rs 6:1] + connect mem_0_body.r0.en, mem_r0.en @[module-XXXXXXXXXX.rs 6:1] + connect mem_0_body.w1.addr, mem_w1.addr @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_body.w1.clk, mem_w1.clk @[module-XXXXXXXXXX.rs 11:1] + connect mem_0_body.w1.en, mem_w1.en @[module-XXXXXXXXXX.rs 11:1] + wire _cast_bits_to_enum_expr_1: Ty0 + when eq(UInt<1>(0), tail(mem_1_tag.r0.data, 0)): + connect _cast_bits_to_enum_expr_1, {|Text, FmtError|}(Text) + else: + connect _cast_bits_to_enum_expr_1, {|Text, FmtError|}(FmtError) + connect mem_r0.data[1].tag, _cast_bits_to_enum_expr_1 @[module-XXXXXXXXXX.rs 6:1] + wire _cast_enum_to_bits_expr_1: UInt<1> + match mem_w1.data[1].tag: + Text: + connect _cast_enum_to_bits_expr_1, UInt<1>(0) + FmtError: + connect _cast_enum_to_bits_expr_1, UInt<1>(1) + connect mem_1_tag.w1.data, _cast_enum_to_bits_expr_1 @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_tag.w1.mask, mem_w1.mask[1].tag @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_tag.r0.addr, mem_r0.addr @[module-XXXXXXXXXX.rs 6:1] + connect mem_1_tag.r0.clk, mem_r0.clk @[module-XXXXXXXXXX.rs 6:1] + connect mem_1_tag.r0.en, mem_r0.en @[module-XXXXXXXXXX.rs 6:1] + connect mem_1_tag.w1.addr, mem_w1.addr @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_tag.w1.clk, mem_w1.clk @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_tag.w1.en, mem_w1.en @[module-XXXXXXXXXX.rs 11:1] + connect mem_r0.data[1].body, mem_1_body.r0.data @[module-XXXXXXXXXX.rs 6:1] + connect mem_1_body.w1.data, mem_w1.data[1].body @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_body.w1.mask, mem_w1.mask[1].body @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_body.r0.addr, mem_r0.addr @[module-XXXXXXXXXX.rs 6:1] + connect mem_1_body.r0.clk, mem_r0.clk @[module-XXXXXXXXXX.rs 6:1] + connect mem_1_body.r0.en, mem_r0.en @[module-XXXXXXXXXX.rs 6:1] + connect mem_1_body.w1.addr, mem_w1.addr @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_body.w1.clk, mem_w1.clk @[module-XXXXXXXXXX.rs 11:1] + connect mem_1_body.w1.en, mem_w1.en @[module-XXXXXXXXXX.rs 11:1] + wire mem_w1_1: Ty11 @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.addr, mem_w1_1.addr @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.en, mem_w1_1.en @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.clk, mem_w1_1.clk @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.data, mem_w1_1.data @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.mask[0].tag, mem_w1_1.mask[0] @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.mask[0].body, mem_w1_1.mask[0] @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.mask[1].tag, mem_w1_1.mask[1] @[module-XXXXXXXXXX.rs 11:1] + connect mem_w1.mask[1].body, mem_w1_1.mask[1] @[module-XXXXXXXXXX.rs 11:1] + connect mem_r0.clk, clk @[module-XXXXXXXXXX.rs 7:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect mem_r0.addr, `read`.addr @[module-XXXXXXXXXX.rs 8:1] + connect mem_r0.en, `read`.en @[module-XXXXXXXXXX.rs 9:1] + connect `read`.data[0], mem_r0.data[0] @[module-XXXXXXXXXX.rs 10:1] + connect `read`.data[1], mem_r0.data[1] @[module-XXXXXXXXXX.rs 10:1] + connect mem_w1_1.clk, clk @[module-XXXXXXXXXX.rs 12:1] + ; connect different types: + ; lhs: UInt<2> + ; rhs: UInt<8> + connect mem_w1_1.addr, `write`.addr @[module-XXXXXXXXXX.rs 13:1] + connect mem_w1_1.data, `write`.data @[module-XXXXXXXXXX.rs 14:1] + connect mem_w1_1.en, `write`.en @[module-XXXXXXXXXX.rs 15:1] + connect mem_w1_1.mask, `write`.mask @[module-XXXXXXXXXX.rs 16:1] +"#, + "/test/sim_trace_as_string/mem_0_body.mem": r"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +", + "/test/sim_trace_as_string/mem_0_tag.mem": r"0 +0 +0 +0 +", + "/test/sim_trace_as_string/mem_1_body.mem": r"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +", + "/test/sim_trace_as_string/mem_1_tag.mem": r"0 +0 +0 +0 +", + }; +} diff --git a/crates/fayalite/tests/sim/expected/sim_trace_as_string.txt b/crates/fayalite/tests/sim/expected/sim_trace_as_string.txt new file mode 100644 index 0000000..0dd374c --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_trace_as_string.txt @@ -0,0 +1,2254 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 12, + debug_data: [ + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + ], + .. + }, + big_slots: StatePartLayout { + len: 31, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.addr", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.en", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.addr", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.en", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.mask[0]", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.mask[1]", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.addr", + ty: UInt<2>, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.en", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.addr", + ty: UInt<2>, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.en", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.mask[0]", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.mask[1]", + ty: Bool, + }, + SlotDebugData { + name: "[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "[0]", + ty: Bool, + }, + SlotDebugData { + name: "[1]", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + SlotDebugData { + name: "", + ty: UInt<2>, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + memories: StatePartLayout { + len: 1, + debug_data: [ + (), + ], + layout_data: [ + MemoryData { + array_type: Array), FmtError}, .. }, 2>, 4>, + data: [ + // len = 0x4 + [0x0]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + [0x1]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + [0x2]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + [0x3]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, + ], + }, + ], + .. + }, + }, + insns: [ + // at: module-XXXXXXXXXX.rs:16:1 + 0: Copy { + dest: StatePartIndex(23), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.mask[0]", ty: Bool }, + src: StatePartIndex(11), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.mask[0]", ty: Bool }, + }, + 1: Copy { + dest: StatePartIndex(24), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.mask[1]", ty: Bool }, + src: StatePartIndex(12), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.mask[1]", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:15:1 + 2: Copy { + dest: StatePartIndex(19), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.en", ty: Bool }, + src: StatePartIndex(7), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.en", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:14:1 + 3: Copy { + dest: StatePartIndex(21), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[0]", ty: Enum {Text(UInt<512>), FmtError} }, + src: StatePartIndex(9), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[0]", ty: Enum {Text(UInt<512>), FmtError} }, + }, + 4: Copy { + dest: StatePartIndex(22), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[1]", ty: Enum {Text(UInt<512>), FmtError} }, + src: StatePartIndex(10), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[1]", ty: Enum {Text(UInt<512>), FmtError} }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 5: CastToUInt { + dest: StatePartIndex(30), // (0x1) SlotDebugData { name: "", ty: UInt<2> }, + src: StatePartIndex(6), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.addr", ty: UInt<8> }, + dest_width: 2, + }, + // at: module-XXXXXXXXXX.rs:13:1 + 6: Copy { + dest: StatePartIndex(18), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.addr", ty: UInt<2> }, + src: StatePartIndex(30), // (0x1) SlotDebugData { name: "", ty: UInt<2> }, + }, + // at: module-XXXXXXXXXX.rs:12:1 + 7: Copy { + dest: StatePartIndex(20), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.clk", ty: Clock }, + src: StatePartIndex(0), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::clk", ty: Clock }, + }, + // at: module-XXXXXXXXXX.rs:9:1 + 8: Copy { + dest: StatePartIndex(14), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.en", ty: Bool }, + src: StatePartIndex(2), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.en", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 9: CastToUInt { + dest: StatePartIndex(29), // (0x1) SlotDebugData { name: "", ty: UInt<2> }, + src: StatePartIndex(1), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.addr", ty: UInt<8> }, + dest_width: 2, + }, + // at: module-XXXXXXXXXX.rs:8:1 + 10: Copy { + dest: StatePartIndex(13), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.addr", ty: UInt<2> }, + src: StatePartIndex(29), // (0x1) SlotDebugData { name: "", ty: UInt<2> }, + }, + // at: module-XXXXXXXXXX.rs:7:1 + 11: Copy { + dest: StatePartIndex(15), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.clk", ty: Clock }, + src: StatePartIndex(0), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::clk", ty: Clock }, + }, + // at: module-XXXXXXXXXX.rs:5:1 + 12: CastBigToArrayIndex { + dest: StatePartIndex(9), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + src: StatePartIndex(18), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.addr", ty: UInt<2> }, + }, + 13: IsNonZeroDestIsSmall { + dest: StatePartIndex(8), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(19), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.en", ty: Bool }, + }, + 14: IsNonZeroDestIsSmall { + dest: StatePartIndex(7), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(20), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.clk", ty: Clock }, + }, + 15: AndSmall { + dest: StatePartIndex(6), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(7), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + rhs: StatePartIndex(5), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 16: CastBigToArrayIndex { + dest: StatePartIndex(4), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + src: StatePartIndex(13), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.addr", ty: UInt<2> }, + }, + 17: IsNonZeroDestIsSmall { + dest: StatePartIndex(3), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(14), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.en", ty: Bool }, + }, + 18: BranchIfSmallZero { + target: 22, + value: StatePartIndex(3), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + }, + 19: MemoryReadUInt { + dest: StatePartIndex(16), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[0]", ty: Enum {Text(UInt<512>), FmtError} }, + memory: StatePartIndex(0), // (MemoryData { + // array_type: Array), FmtError}, .. }, 2>, 4>, + // data: [ + // // len = 0x4 + // [0x0]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c16db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba60b6dacada, + // [0x1]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, + // [0x2]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c96db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba64b6dacada, + // [0x3]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74cd6db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba66b6dacada, + // ], + // }) (), + addr: StatePartIndex(4), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + stride: 1026, + start: 0, + width: 513, + }, + 20: MemoryReadUInt { + dest: StatePartIndex(17), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[1]", ty: Enum {Text(UInt<512>), FmtError} }, + memory: StatePartIndex(0), // (MemoryData { + // array_type: Array), FmtError}, .. }, 2>, 4>, + // data: [ + // // len = 0x4 + // [0x0]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c16db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba60b6dacada, + // [0x1]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, + // [0x2]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c96db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba64b6dacada, + // [0x3]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74cd6db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba66b6dacada, + // ], + // }) (), + addr: StatePartIndex(4), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + stride: 1026, + start: 513, + width: 513, + }, + 21: Branch { + target: 24, + }, + 22: Const { + dest: StatePartIndex(16), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[0]", ty: Enum {Text(UInt<512>), FmtError} }, + value: 0x0, + }, + 23: Const { + dest: StatePartIndex(17), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[1]", ty: Enum {Text(UInt<512>), FmtError} }, + value: 0x0, + }, + // at: module-XXXXXXXXXX.rs:10:1 + 24: Copy { + dest: StatePartIndex(4), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[0]", ty: Enum {Text(UInt<512>), FmtError} }, + src: StatePartIndex(16), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[0]", ty: Enum {Text(UInt<512>), FmtError} }, + }, + 25: Copy { + dest: StatePartIndex(5), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[1]", ty: Enum {Text(UInt<512>), FmtError} }, + src: StatePartIndex(17), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[1]", ty: Enum {Text(UInt<512>), FmtError} }, + }, + // at: module-XXXXXXXXXX.rs:5:1 + 26: IsNonZeroDestIsSmall { + dest: StatePartIndex(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(15), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.clk", ty: Clock }, + }, + 27: AndSmall { + dest: StatePartIndex(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + rhs: StatePartIndex(0), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 28: BranchIfSmallZero { + target: 29, + value: StatePartIndex(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 29: BranchIfSmallZero { + target: 41, + value: StatePartIndex(6), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 30: CopySmall { + dest: StatePartIndex(10), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + src: StatePartIndex(9), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + }, + 31: CopySmall { + dest: StatePartIndex(11), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(8), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + }, + 32: Copy { + dest: StatePartIndex(25), // (0x1) SlotDebugData { name: "[0]", ty: Enum {Text(UInt<512>), FmtError} }, + src: StatePartIndex(21), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[0]", ty: Enum {Text(UInt<512>), FmtError} }, + }, + 33: Copy { + dest: StatePartIndex(26), // (0x1) SlotDebugData { name: "[1]", ty: Enum {Text(UInt<512>), FmtError} }, + src: StatePartIndex(22), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[1]", ty: Enum {Text(UInt<512>), FmtError} }, + }, + 34: Copy { + dest: StatePartIndex(27), // (0x1) SlotDebugData { name: "[0]", ty: Bool }, + src: StatePartIndex(23), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.mask[0]", ty: Bool }, + }, + 35: Copy { + dest: StatePartIndex(28), // (0x1) SlotDebugData { name: "[1]", ty: Bool }, + src: StatePartIndex(24), // (0x1) SlotDebugData { name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.mask[1]", ty: Bool }, + }, + 36: BranchIfSmallZero { + target: 41, + value: StatePartIndex(11), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + }, + 37: BranchIfZero { + target: 39, + value: StatePartIndex(27), // (0x1) SlotDebugData { name: "[0]", ty: Bool }, + }, + 38: MemoryWriteUInt { + value: StatePartIndex(25), // (0x1) SlotDebugData { name: "[0]", ty: Enum {Text(UInt<512>), FmtError} }, + memory: StatePartIndex(0), // (MemoryData { + // array_type: Array), FmtError}, .. }, 2>, 4>, + // data: [ + // // len = 0x4 + // [0x0]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c16db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba60b6dacada, + // [0x1]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, + // [0x2]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c96db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba64b6dacada, + // [0x3]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74cd6db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba66b6dacada, + // ], + // }) (), + addr: StatePartIndex(10), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + stride: 1026, + start: 0, + width: 513, + }, + 39: BranchIfZero { + target: 41, + value: StatePartIndex(28), // (0x1) SlotDebugData { name: "[1]", ty: Bool }, + }, + 40: MemoryWriteUInt { + value: StatePartIndex(26), // (0x1) SlotDebugData { name: "[1]", ty: Enum {Text(UInt<512>), FmtError} }, + memory: StatePartIndex(0), // (MemoryData { + // array_type: Array), FmtError}, .. }, 2>, 4>, + // data: [ + // // len = 0x4 + // [0x0]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c16db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba60b6dacada, + // [0x1]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, + // [0x2]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c96db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba64b6dacada, + // [0x3]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74cd6db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba66b6dacada, + // ], + // }) (), + addr: StatePartIndex(10), // (0x1 1) SlotDebugData { name: "", ty: UInt<2> }, + stride: 1026, + start: 513, + width: 513, + }, + 41: XorSmallImmediate { + dest: StatePartIndex(0), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + rhs: 0x1, + }, + 42: XorSmallImmediate { + dest: StatePartIndex(5), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(7), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + rhs: 0x1, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 43: Return, + ], + .. + }, + pc: 43, + memory_write_log: [], + memories: StatePart { + value: [ + MemoryData { + array_type: Array), FmtError}, .. }, 2>, 4>, + data: [ + // len = 0x4 + [0x0]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c16db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba60b6dacada, + [0x1]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, + [0x2]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74c96db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba64b6dacada, + [0x3]: 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174c56d74cd6db595b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ba60b6ba66b6dacada, + ], + }, + ], + }, + small_slots: StatePart { + value: [ + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + ], + }, + big_slots: StatePart { + value: [ + 1, + 1, + 1, + 0, + 1 (modified), + 1 (modified), + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }, + main_module: SimulationModuleState { + base_targets: [ + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.clk, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.clk, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read.addr, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read.clk, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read.data, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read.data., + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read.data.[0], + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read.data.[1], + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.read.en, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.addr, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.clk, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.data, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.data[0], + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.data[0]., + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.data[1], + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.data[1]., + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.en, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.mask, + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.mask[0], + Instance { + name: ::sim_trace_as_string, + instantiated: Module { + name: sim_trace_as_string, + .. + }, + }.write.mask[1], + }, + did_initial_settle: true, + clocks_for_past: {}, + }, + extern_modules: [], + trace_decls: TraceModule { + name: "sim_trace_as_string", + children: [ + TraceModuleIO { + name: "clk", + child: TraceClock { + location: TraceScalarId(0), + name: "clk", + flow: Source, + }, + ty: Clock, + flow: Source, + }, + TraceModuleIO { + name: "read", + child: TraceBundle { + name: "read", + fields: [ + TraceUInt { + location: TraceScalarId(1), + name: "addr", + ty: UInt<8>, + flow: Source, + }, + TraceBool { + location: TraceScalarId(2), + name: "en", + flow: Source, + }, + TraceClock { + location: TraceScalarId(3), + name: "clk", + flow: Source, + }, + TraceTraceAsString { + location: TraceScalarId(4), + name: "data", + ty: TraceAsString { + inner_ty: Array), FmtError}, 2>, + .. + }, + flow: Sink, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<8>, + /* offset = 8 */ + en: Bool, + /* offset = 9 */ + clk: Clock, + #[hdl(flip)] /* offset = 10 */ + data: TraceAsString { + inner_ty: Array), FmtError}, 2>, + .. + }, + }, + flow: Source, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<8>, + /* offset = 8 */ + en: Bool, + /* offset = 9 */ + clk: Clock, + #[hdl(flip)] /* offset = 10 */ + data: TraceAsString { + inner_ty: Array), FmtError}, 2>, + .. + }, + }, + flow: Source, + }, + TraceModuleIO { + name: "write", + child: TraceBundle { + name: "write", + fields: [ + TraceUInt { + location: TraceScalarId(5), + name: "addr", + ty: UInt<8>, + flow: Source, + }, + TraceBool { + location: TraceScalarId(6), + name: "en", + flow: Source, + }, + TraceClock { + location: TraceScalarId(7), + name: "clk", + flow: Source, + }, + TraceArray { + name: "data", + elements: [ + TraceTraceAsString { + location: TraceScalarId(8), + name: "[0]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Source, + }, + TraceTraceAsString { + location: TraceScalarId(9), + name: "[1]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Source, + }, + ], + ty: Array), FmtError}, .. }, 2>, + flow: Source, + }, + TraceArray { + name: "mask", + elements: [ + TraceBool { + location: TraceScalarId(10), + name: "[0]", + flow: Source, + }, + TraceBool { + location: TraceScalarId(11), + name: "[1]", + flow: Source, + }, + ], + ty: Array, + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<8>, + /* offset = 8 */ + en: Bool, + /* offset = 9 */ + clk: Clock, + /* offset = 10 */ + data: Array), FmtError}, .. }, 2>, + /* offset = 1036 */ + mask: Array, + }, + flow: Source, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<8>, + /* offset = 8 */ + en: Bool, + /* offset = 9 */ + clk: Clock, + /* offset = 10 */ + data: Array), FmtError}, .. }, 2>, + /* offset = 1036 */ + mask: Array, + }, + flow: Source, + }, + TraceMem { + id: TraceMemoryId(0), + name: "mem", + stride: 1026, + element_type: TraceArray { + name: "mem", + elements: [ + TraceTraceAsString { + location: TraceMemoryLocation { + id: TraceMemoryId(0), + depth: 4, + stride: 1026, + start: 0, + len: 513, + }, + name: "[0]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Duplex, + }, + TraceTraceAsString { + location: TraceMemoryLocation { + id: TraceMemoryId(0), + depth: 4, + stride: 1026, + start: 513, + len: 513, + }, + name: "[1]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Duplex, + }, + ], + ty: Array), FmtError}, .. }, 2>, + flow: Duplex, + }, + ports: [ + TraceMemPort { + name: "r0", + bundle: TraceBundle { + name: "r0", + fields: [ + TraceUInt { + location: TraceScalarId(12), + name: "addr", + ty: UInt<2>, + flow: Sink, + }, + TraceBool { + location: TraceScalarId(13), + name: "en", + flow: Sink, + }, + TraceClock { + location: TraceScalarId(14), + name: "clk", + flow: Sink, + }, + TraceArray { + name: "data", + elements: [ + TraceTraceAsString { + location: TraceScalarId(15), + name: "[0]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Source, + }, + TraceTraceAsString { + location: TraceScalarId(16), + name: "[1]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Source, + }, + ], + ty: Array), FmtError}, .. }, 2>, + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + #[hdl(flip)] /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + }, + flow: Sink, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + #[hdl(flip)] /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + }, + }, + TraceMemPort { + name: "w1", + bundle: TraceBundle { + name: "w1", + fields: [ + TraceUInt { + location: TraceScalarId(17), + name: "addr", + ty: UInt<2>, + flow: Sink, + }, + TraceBool { + location: TraceScalarId(18), + name: "en", + flow: Sink, + }, + TraceClock { + location: TraceScalarId(19), + name: "clk", + flow: Sink, + }, + TraceArray { + name: "data", + elements: [ + TraceTraceAsString { + location: TraceScalarId(20), + name: "[0]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Sink, + }, + TraceTraceAsString { + location: TraceScalarId(21), + name: "[1]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Sink, + }, + ], + ty: Array), FmtError}, .. }, 2>, + flow: Sink, + }, + TraceArray { + name: "mask", + elements: [ + TraceBool { + location: TraceScalarId(22), + name: "[0]", + flow: Sink, + }, + TraceBool { + location: TraceScalarId(23), + name: "[1]", + flow: Sink, + }, + ], + ty: Array, + flow: Sink, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + /* offset = 1030 */ + mask: Array, + }, + flow: Sink, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + /* offset = 1030 */ + mask: Array, + }, + }, + ], + array_type: Array), FmtError}, .. }, 2>, 4>, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigClock { + index: StatePartIndex(0), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigUInt { + index: StatePartIndex(1), + ty: UInt<8>, + }, + maybe_changed: false, + state: 0x01, + last_state: 0x01, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigBool { + index: StatePartIndex(2), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(3), + kind: BigClock { + index: StatePartIndex(3), + }, + maybe_changed: false, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(4), + kind: TraceAsString { + layout: CompiledTypeLayout { + ty: TraceAsString { + inner_ty: Array), FmtError}, 2>, + .. + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 2, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Transparent { + inner: CompiledTypeLayout { + ty: Array), FmtError}, 2>, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 2, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Array { + elements_non_empty: [ + CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::read.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + ], + }, + }, + }, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 4, len: 2 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + }, + maybe_changed: true, + state: OpaqueSimValue { + bits: 0x200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001_u1026, + sim_only_values: [], + }, + last_state: OpaqueSimValue { + bits: 0x174C56D74C56DB595B400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BA60B6BA62B6DACADA_u1026, + sim_only_values: [], + }, + }, + SimTrace { + id: TraceScalarId(5), + kind: BigUInt { + index: StatePartIndex(6), + ty: UInt<8>, + }, + maybe_changed: false, + state: 0x01, + last_state: 0x01, + }, + SimTrace { + id: TraceScalarId(6), + kind: BigBool { + index: StatePartIndex(7), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(7), + kind: BigClock { + index: StatePartIndex(8), + }, + maybe_changed: false, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(8), + kind: TraceAsString { + layout: CompiledTypeLayout { + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Transparent { + inner: CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + }, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 9, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + }, + maybe_changed: true, + state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + last_state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + }, + SimTrace { + id: TraceScalarId(9), + kind: TraceAsString { + layout: CompiledTypeLayout { + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Transparent { + inner: CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::write.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + }, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 10, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + }, + maybe_changed: true, + state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + last_state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + }, + SimTrace { + id: TraceScalarId(10), + kind: BigBool { + index: StatePartIndex(11), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(11), + kind: BigBool { + index: StatePartIndex(12), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(12), + kind: BigUInt { + index: StatePartIndex(13), + ty: UInt<2>, + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(13), + kind: BigBool { + index: StatePartIndex(14), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(14), + kind: BigClock { + index: StatePartIndex(15), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(15), + kind: TraceAsString { + layout: CompiledTypeLayout { + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Transparent { + inner: CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + }, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 16, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + }, + maybe_changed: true, + state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + last_state: OpaqueSimValue { + bits: 0xBA60B6BA62B6DACADA_u513, + sim_only_values: [], + }, + }, + SimTrace { + id: TraceScalarId(16), + kind: TraceAsString { + layout: CompiledTypeLayout { + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Transparent { + inner: CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::r0.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + }, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 17, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + }, + maybe_changed: true, + state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + last_state: OpaqueSimValue { + bits: 0xBA62B6BA62B6DACADA_u513, + sim_only_values: [], + }, + }, + SimTrace { + id: TraceScalarId(17), + kind: BigUInt { + index: StatePartIndex(18), + ty: UInt<2>, + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(18), + kind: BigBool { + index: StatePartIndex(19), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(19), + kind: BigClock { + index: StatePartIndex(20), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(20), + kind: TraceAsString { + layout: CompiledTypeLayout { + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Transparent { + inner: CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[0]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + }, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 5, len: 0 }, + big_slots: StatePartIndexRange { start: 21, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + }, + maybe_changed: true, + state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + last_state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + }, + SimTrace { + id: TraceScalarId(21), + kind: TraceAsString { + layout: CompiledTypeLayout { + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Transparent { + inner: CompiledTypeLayout { + ty: Enum { + Text(UInt<512>), + FmtError, + }, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_trace_as_string: sim_trace_as_string).sim_trace_as_string::mem::w1.data[1]", + ty: Enum { + Text(UInt<512>), + FmtError, + }, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + }, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 5, len: 0 }, + big_slots: StatePartIndexRange { start: 22, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + }, + maybe_changed: true, + state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + last_state: OpaqueSimValue { + bits: 0x1_u513, + sim_only_values: [], + }, + }, + SimTrace { + id: TraceScalarId(22), + kind: BigBool { + index: StatePartIndex(23), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(23), + kind: BigBool { + index: StatePartIndex(24), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x1, + }, + ], + trace_memories: { + StatePartIndex(0): TraceMem { + id: TraceMemoryId(0), + name: "mem", + stride: 1026, + element_type: TraceArray { + name: "mem", + elements: [ + TraceTraceAsString { + location: TraceMemoryLocation { + id: TraceMemoryId(0), + depth: 4, + stride: 1026, + start: 0, + len: 513, + }, + name: "[0]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Duplex, + }, + TraceTraceAsString { + location: TraceMemoryLocation { + id: TraceMemoryId(0), + depth: 4, + stride: 1026, + start: 513, + len: 513, + }, + name: "[1]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Duplex, + }, + ], + ty: Array), FmtError}, .. }, 2>, + flow: Duplex, + }, + ports: [ + TraceMemPort { + name: "r0", + bundle: TraceBundle { + name: "r0", + fields: [ + TraceUInt { + location: TraceScalarId(12), + name: "addr", + ty: UInt<2>, + flow: Sink, + }, + TraceBool { + location: TraceScalarId(13), + name: "en", + flow: Sink, + }, + TraceClock { + location: TraceScalarId(14), + name: "clk", + flow: Sink, + }, + TraceArray { + name: "data", + elements: [ + TraceTraceAsString { + location: TraceScalarId(15), + name: "[0]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Source, + }, + TraceTraceAsString { + location: TraceScalarId(16), + name: "[1]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Source, + }, + ], + ty: Array), FmtError}, .. }, 2>, + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + #[hdl(flip)] /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + }, + flow: Sink, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + #[hdl(flip)] /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + }, + }, + TraceMemPort { + name: "w1", + bundle: TraceBundle { + name: "w1", + fields: [ + TraceUInt { + location: TraceScalarId(17), + name: "addr", + ty: UInt<2>, + flow: Sink, + }, + TraceBool { + location: TraceScalarId(18), + name: "en", + flow: Sink, + }, + TraceClock { + location: TraceScalarId(19), + name: "clk", + flow: Sink, + }, + TraceArray { + name: "data", + elements: [ + TraceTraceAsString { + location: TraceScalarId(20), + name: "[0]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Sink, + }, + TraceTraceAsString { + location: TraceScalarId(21), + name: "[1]", + ty: TraceAsString { + inner_ty: Enum { + Text(UInt<512>), + FmtError, + }, + .. + }, + flow: Sink, + }, + ], + ty: Array), FmtError}, .. }, 2>, + flow: Sink, + }, + TraceArray { + name: "mask", + elements: [ + TraceBool { + location: TraceScalarId(22), + name: "[0]", + flow: Sink, + }, + TraceBool { + location: TraceScalarId(23), + name: "[1]", + flow: Sink, + }, + ], + ty: Array, + flow: Sink, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + /* offset = 1030 */ + mask: Array, + }, + flow: Sink, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<2>, + /* offset = 2 */ + en: Bool, + /* offset = 3 */ + clk: Clock, + /* offset = 4 */ + data: Array), FmtError}, .. }, 2>, + /* offset = 1030 */ + mask: Array, + }, + }, + ], + array_type: Array), FmtError}, .. }, 2>, 4>, + }, + }, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [ + StatePartIndex(1), + StatePartIndex(6), + ], + event_queue: EventQueue(EventQueueData { + instant: 7 μs, + events: {}, + }), + waiting_sensitivity_sets_by_address: {}, + waiting_sensitivity_sets_by_compiled_value: {}, + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_trace_as_string.vcd b/crates/fayalite/tests/sim/expected/sim_trace_as_string.vcd new file mode 100644 index 0000000..3338905 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_trace_as_string.vcd @@ -0,0 +1,221 @@ +$timescale 1 ps $end +$scope module sim_trace_as_string $end +$var wire 1 J(7*b clk $end +$scope struct read $end +$var wire 8 @t0}\ addr $end +$var wire 1 78"T5 en $end +$var wire 1 G7v@m clk $end +$var string 1 F&^FN data $end +$upscope $end +$scope struct write $end +$var wire 8 "fUdW addr $end +$var wire 1 r1OK) en $end +$var wire 1 ,ADvU clk $end +$scope struct data $end +$var string 1 pD.mP \[0] $end +$var string 1 !V!em \[1] $end +$upscope $end +$scope struct mask $end +$var wire 1 l8dgD \[0] $end +$var wire 1 1/sDs \[1] $end +$upscope $end +$upscope $end +$scope struct mem $end +$scope struct contents $end +$scope struct \[0] $end +$scope struct mem $end +$var string 1 sz>#| \[0] $end +$var string 1 G._83 \[1] $end +$upscope $end +$upscope $end +$scope struct \[1] $end +$scope struct mem $end +$var string 1 2r3#W \[0] $end +$var string 1 AbGF% \[1] $end +$upscope $end +$upscope $end +$scope struct \[2] $end +$scope struct mem $end +$var string 1 .^<$p \[0] $end +$var string 1 ?s@Dc \[1] $end +$upscope $end +$upscope $end +$scope struct \[3] $end +$scope struct mem $end +$var string 1 {*||o \[0] $end +$var string 1 Bg,vB \[1] $end +$upscope $end +$upscope $end +$upscope $end +$scope struct r0 $end +$var wire 2 .0()- addr $end +$var wire 1 GEbRA en $end +$var wire 1 ;`9BK clk $end +$scope struct data $end +$var string 1 _Xe"P \[0] $end +$var string 1 jXrsx \[1] $end +$upscope $end +$upscope $end +$scope struct w1 $end +$var wire 2 '8u?z addr $end +$var wire 1 ~o=`& en $end +$var wire 1 *q>M1 clk $end +$scope struct data $end +$var string 1 N\zBe \[0] $end +$var string 1 c3h8{ \[1] $end +$upscope $end +$scope struct mask $end +$var wire 1 .SYGD \[0] $end +$var wire 1 />wYd \[1] $end +$upscope $end +$upscope $end +$upscope $end +$upscope $end +$enddefinitions $end +$dumpvars +s sz>#| +s G._83 +s 2r3#W +s AbGF% +s .^<$p +s ?s@Dc +s {*||o +s Bg,vB +0J(7*b +b0 @t0}\ +078"T5 +0G7v@m +s[,\x20] F&^FN +b0 "fUdW +0r1OK) +0,ADvU +s pD.mP +s !V!em +0l8dgD +01/sDs +b0 .0()- +0GEbRA +0;`9BK +s _Xe"P +s jXrsx +b0 '8u?z +0~o=`& +0*q>M1 +s N\zBe +s c3h8{ +0.SYGD +0/>wYd +$end +#500000 +1J(7*b +1;`9BK +1*q>M1 +#1000000 +0J(7*b +1r1OK) +smem[0][0] pD.mP +smem[0][1] !V!em +1l8dgD +11/sDs +0;`9BK +1~o=`& +0*q>M1 +smem[0][0] N\zBe +smem[0][1] c3h8{ +1.SYGD +1/>wYd +#1500000 +smem[0][0] sz>#| +smem[0][1] G._83 +1J(7*b +1;`9BK +1*q>M1 +#2000000 +0J(7*b +b1 "fUdW +smem[1][0] pD.mP +smem[1][1] !V!em +0;`9BK +b1 '8u?z +0*q>M1 +smem[1][0] N\zBe +smem[1][1] c3h8{ +#2500000 +smem[1][0] 2r3#W +smem[1][1] AbGF% +1J(7*b +1;`9BK +1*q>M1 +#3000000 +0J(7*b +b10 "fUdW +smem[2][0] pD.mP +smem[2][1] !V!em +0;`9BK +b10 '8u?z +0*q>M1 +smem[2][0] N\zBe +smem[2][1] c3h8{ +#3500000 +smem[2][0] .^<$p +smem[2][1] ?s@Dc +1J(7*b +1;`9BK +1*q>M1 +#4000000 +0J(7*b +b11 "fUdW +smem[3][0] pD.mP +smem[3][1] !V!em +0;`9BK +b11 '8u?z +0*q>M1 +smem[3][0] N\zBe +smem[3][1] c3h8{ +#4500000 +smem[3][0] {*||o +smem[3][1] Bg,vB +1J(7*b +1;`9BK +1*q>M1 +#5000000 +0J(7*b +b1 @t0}\ +178"T5 +s[mem[1][0],\x20mem[1][1]] F&^FN +b0 "fUdW +0r1OK) +s pD.mP +s !V!em +b1 .0()- +1GEbRA +0;`9BK +smem[1][0] _Xe"P +smem[1][1] jXrsx +b0 '8u?z +0~o=`& +0*q>M1 +s N\zBe +s c3h8{ +#5500000 +1J(7*b +1;`9BK +1*q>M1 +#6000000 +0J(7*b +b1 "fUdW +1r1OK) +0;`9BK +b1 '8u?z +1~o=`& +0*q>M1 +#6500000 +s 2r3#W +s AbGF% +1J(7*b +s F&^FN +1;`9BK +s _Xe"P +s jXrsx +1*q>M1 +#7000000 diff --git a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr index 44aff3f..dbdf937 100644 --- a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr +++ b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr @@ -75,7 +75,7 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 761 | pub struct OpaqueSimValue { + 895 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs @@ -214,7 +214,7 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 761 | pub struct OpaqueSimValue { + 895 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs @@ -326,7 +326,7 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 761 | pub struct OpaqueSimValue { + 895 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs diff --git a/crates/fayalite/visit_types.json b/crates/fayalite/visit_types.json index a74cef9..f5d666c 100644 --- a/crates/fayalite/visit_types.json +++ b/crates/fayalite/visit_types.json @@ -51,7 +51,8 @@ "Reset": "Visible", "Clock": "Visible", "PhantomConst": "Visible", - "DynSimOnly": "Visible" + "DynSimOnly": "Visible", + "TraceAsString": "Visible" } }, "Bundle": { @@ -1021,6 +1022,27 @@ "fold_where": "T: Fold", "visit_where": "T: Visit" }, + "ops::AsTraceAsString": { + "data": { + "$kind": "Struct", + "$constructor": "ops::AsTraceAsString::new", + "inner()": "Visible", + "ty()": "Visible" + }, + "generics": "", + "fold_where": "T: Fold", + "visit_where": "T: Visit" + }, + "ops::TraceAsStringAsInner": { + "data": { + "$kind": "Struct", + "$constructor": "ops::TraceAsStringAsInner::new", + "arg_typed()": "Visible" + }, + "generics": "", + "fold_where": "T: Fold", + "visit_where": "T: Visit" + }, "BlockId": { "data": { "$kind": "Opaque" @@ -1283,12 +1305,25 @@ "$kind": "Struct" } }, + "TargetPathTraceAsStringInner": { + "data": { + "$kind": "Struct" + } + }, + "TargetPathAsTraceAsString": { + "data": { + "$kind": "Struct", + "ty": "Visible" + } + }, "TargetPathElement": { "data": { "$kind": "Enum", "BundleField": "Visible", "ArrayElement": "Visible", - "DynArrayElement": "Visible" + "DynArrayElement": "Visible", + "TraceAsStringInner": "Visible", + "AsTraceAsString": "Visible" } }, "PhantomConst": { @@ -1306,6 +1341,14 @@ "data": { "$kind": "ManualImpl" } + }, + "TraceAsString": { + "data": { + "$kind": "ManualImpl" + }, + "generics": "", + "fold_where": "T: Fold", + "visit_where": "T: Visit" } } } \ No newline at end of file From cf3e6cfc6bc33eebf2d2862c7a1948b9cf40ecac Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 13 May 2026 23:32:33 -0700 Subject: [PATCH 08/15] Add .to_trace_as_string() and clean up code --- crates/fayalite/src/expr.rs | 189 ++++++- crates/fayalite/src/expr/ops.rs | 42 +- crates/fayalite/src/expr/target.rs | 171 +++++- crates/fayalite/src/firrtl.rs | 6 +- crates/fayalite/src/module.rs | 30 +- .../src/module/transform/deduce_resets.rs | 12 +- .../src/module/transform/simplify_enums.rs | 2 +- crates/fayalite/src/module/transform/visit.rs | 4 +- crates/fayalite/src/prelude.rs | 4 +- crates/fayalite/src/sim.rs | 2 +- crates/fayalite/src/sim/compiler.rs | 10 +- crates/fayalite/src/sim/value.rs | 103 +--- .../src/sim/value/sim_only_value_unsafe.rs | 12 +- crates/fayalite/src/ty.rs | 515 +++++++++++++++--- crates/fayalite/src/ty/serde_impls.rs | 1 + crates/fayalite/tests/sim.rs | 14 +- .../ui/simvalue_is_not_internable.stderr | 24 +- crates/fayalite/visit_types.json | 8 +- 18 files changed, 894 insertions(+), 255 deletions(-) diff --git a/crates/fayalite/src/expr.rs b/crates/fayalite/src/expr.rs index 3309fb1..e235cd7 100644 --- a/crates/fayalite/src/expr.rs +++ b/crates/fayalite/src/expr.rs @@ -218,7 +218,7 @@ expr_enum! { SliceSInt(ops::SliceSInt), CastToBits(ops::CastToBits), CastBitsTo(ops::CastBitsTo), - AsTraceAsString(ops::AsTraceAsString), + ToTraceAsString(ops::ToTraceAsString), TraceAsStringAsInner(ops::TraceAsStringAsInner), ModuleIO(ModuleIO), Instance(Instance), @@ -394,7 +394,7 @@ impl Expr { #[track_caller] pub fn as_trace_as_string(this: Self, ty: TraceAsString) -> Expr> { assert_eq!(this.ty(), ty.inner_ty()); - ops::AsTraceAsString::new(Expr::canonical(this), ty).to_expr() + ops::ToTraceAsString::new(Expr::canonical(this), ty).to_expr() } } @@ -1723,3 +1723,188 @@ impl<'a, T: Type> ToSimValueInner<'a> for &'a SimValue { Cow::Borrowed(&**this) } } + +pub trait ToTraceAsString: ValueType { + type Output: ValueType, ValueCategory = Self::ValueCategory>; + fn to_trace_as_string_with_ty(&self, ty: TraceAsString) -> Self::Output; + fn into_trace_as_string_with_ty(self, ty: TraceAsString) -> Self::Output + where + Self: Sized; + fn to_trace_as_string(&self) -> Self::Output; + fn into_trace_as_string(self) -> Self::Output + where + Self: Sized; +} + +impl< + T: ?Sized + + ValueType + + ToTraceAsStringImpl<::Type, ::ValueCategory>, +> ToTraceAsString for T +{ + type Output = T::ImplOutput; + fn to_trace_as_string_with_ty(&self, ty: TraceAsString) -> Self::Output { + Self::to_trace_as_string_with_ty_impl(self, ty) + } + fn into_trace_as_string_with_ty(self, ty: TraceAsString) -> Self::Output + where + Self: Sized, + { + Self::into_trace_as_string_with_ty_impl(self, ty) + } + fn to_trace_as_string(&self) -> Self::Output { + Self::to_trace_as_string_impl(self) + } + fn into_trace_as_string(self) -> Self::Output + where + Self: Sized, + { + Self::into_trace_as_string_impl(self) + } +} + +pub trait ToTraceAsStringImpl { + type ImplOutput: ValueType, ValueCategory = C>; + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput; + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized; + fn to_trace_as_string_with_ty_impl(this: &Self, ty: TraceAsString) -> Self::ImplOutput; + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized; +} + +impl + ToTraceAsStringImpl for T +{ + type ImplOutput = crate::ty::TraceAsStringSimValue; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new(this) + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new(this) + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty) + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty) + } +} + +impl + ToTraceAsStringImpl for T +{ + type ImplOutput = SimValue>; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new(this).into_sim_value() + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new(this).into_sim_value() + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty).into_sim_value() + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty).into_sim_value() + } +} + +impl ToTraceAsStringImpl for T { + type ImplOutput = Expr>; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + let this = this.to_expr(); + ops::ToTraceAsString::new(Expr::canonical(this), TraceAsString::new(this.ty())).to_expr() + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + let this = this.to_expr(); + ops::ToTraceAsString::new(Expr::canonical(this), TraceAsString::new(this.ty())).to_expr() + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + let this = this.to_expr(); + ops::ToTraceAsString::new( + Expr::canonical(this), + ty.with_new_inner_ty(this.ty().intern_sized()), + ) + .to_expr() + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + let this = this.to_expr(); + ops::ToTraceAsString::new( + Expr::canonical(this), + ty.with_new_inner_ty(this.ty().intern_sized()), + ) + .to_expr() + } +} + +impl ToTraceAsStringImpl + for T +{ + type ImplOutput = Valueless>; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + Valueless::new(TraceAsString::new(this.ty())) + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + Valueless::new(TraceAsString::new(this.ty())) + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + Valueless::new(ty.with_new_inner_ty(this.ty().intern_sized())) + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + Valueless::new(ty.with_new_inner_ty(this.ty().intern_sized())) + } +} diff --git a/crates/fayalite/src/expr/ops.rs b/crates/fayalite/src/expr/ops.rs index 22a0d99..b2e20ad 100644 --- a/crates/fayalite/src/expr/ops.rs +++ b/crates/fayalite/src/expr/ops.rs @@ -11,8 +11,8 @@ use crate::{ HdlPartialEqImpl, HdlPartialOrd, HdlPartialOrdImpl, NotALiteralExpr, ReduceBitsImpl, ToExpr, ToLiteralBits, ToSimValueInner, ToValueless, ValueType, Valueless, target::{ - GetTarget, Target, TargetPathArrayElement, TargetPathAsTraceAsString, - TargetPathBundleField, TargetPathDynArrayElement, TargetPathElement, + GetTarget, Target, TargetPathArrayElement, TargetPathBundleField, + TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString, TargetPathTraceAsStringInner, }, value_category::ValueCategoryExpr, @@ -45,6 +45,9 @@ use std::{ }, }; +#[cfg(test)] +mod test_ops_impls; + macro_rules! make_impls { ( $([$($args:tt)*])? @@ -584,9 +587,6 @@ macro_rules! make_impls { #[cfg(test)] pub(crate) use make_impls; -#[cfg(test)] -mod test_ops_impls; - macro_rules! impl_simple_binary_op_trait { ( [$($LLifetimes:tt)*][$($LBounds:tt)*] ($($L:tt)*), @@ -4697,14 +4697,14 @@ impl, A> FromIterator for Expr { } #[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct AsTraceAsString { +pub struct ToTraceAsString { inner: Expr, ty: TraceAsString, literal_bits: Result, NotALiteralExpr>, target: Option>, } -impl fmt::Debug for AsTraceAsString { +impl fmt::Debug for ToTraceAsString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { inner, @@ -4712,24 +4712,25 @@ impl fmt::Debug for AsTraceAsString { literal_bits: _, target: _, } = self; - f.debug_struct("AsTraceAsString") + f.debug_struct("ToTraceAsString") .field("inner", inner) .finish_non_exhaustive() } } -impl AsTraceAsString { +impl ToTraceAsString { pub fn new(inner: Expr, ty: TraceAsString) -> Self { assert_eq!(inner.ty(), ty.inner_ty().canonical()); let literal_bits = inner.to_literal_bits(); let target = inner.target().map(|base| { Intern::intern_sized( base.join(TargetPathElement::intern_sized( - TargetPathAsTraceAsString { + TargetPathToTraceAsString { ty: ty.canonical_trace_as_string(), } .into(), - )), + )) + .canonicalized(), ) }); Self { @@ -4744,19 +4745,19 @@ impl AsTraceAsString { } } -impl GetTarget for AsTraceAsString { +impl GetTarget for ToTraceAsString { fn target(&self) -> Option> { self.target } } -impl ToLiteralBits for AsTraceAsString { +impl ToLiteralBits for ToTraceAsString { fn to_literal_bits(&self) -> Result, NotALiteralExpr> { self.literal_bits } } -impl ValueType for AsTraceAsString { +impl ValueType for ToTraceAsString { type Type = TraceAsString; type ValueCategory = ValueCategoryExpr; @@ -4765,10 +4766,10 @@ impl ValueType for AsTraceAsString { } } -impl ToExpr for AsTraceAsString { +impl ToExpr for ToTraceAsString { fn to_expr(&self) -> Expr { Expr { - __enum: ExprEnum::AsTraceAsString(AsTraceAsString { + __enum: ExprEnum::ToTraceAsString(ToTraceAsString { inner: self.inner, ty: self.ty.canonical_trace_as_string(), literal_bits: self.literal_bits, @@ -4808,9 +4809,12 @@ impl TraceAsStringAsInner { assert_eq!(arg.ty().inner_ty(), ty.canonical()); let literal_bits = arg.to_literal_bits(); let target = arg.target().map(|base| { - Intern::intern_sized(base.join(TargetPathElement::intern_sized( - TargetPathTraceAsStringInner {}.into(), - ))) + Intern::intern_sized( + base.join(TargetPathElement::intern_sized( + TargetPathTraceAsStringInner {}.into(), + )) + .canonicalized(), + ) }); Self { arg, diff --git a/crates/fayalite/src/expr/target.rs b/crates/fayalite/src/expr/target.rs index 5140719..9016111 100644 --- a/crates/fayalite/src/expr/target.rs +++ b/crates/fayalite/src/expr/target.rs @@ -56,13 +56,13 @@ impl fmt::Display for TargetPathTraceAsStringInner { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct TargetPathAsTraceAsString { +pub struct TargetPathToTraceAsString { pub ty: TraceAsString, } -impl fmt::Display for TargetPathAsTraceAsString { +impl fmt::Display for TargetPathToTraceAsString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, ".as_trace_as_string(...)") + write!(f, ".to_trace_as_string(...)") } } @@ -72,7 +72,7 @@ pub enum TargetPathElement { ArrayElement(TargetPathArrayElement), DynArrayElement(TargetPathDynArrayElement), TraceAsStringInner(TargetPathTraceAsStringInner), - AsTraceAsString(TargetPathAsTraceAsString), + ToTraceAsString(TargetPathToTraceAsString), } impl From for TargetPathElement { @@ -99,9 +99,9 @@ impl From for TargetPathElement { } } -impl From for TargetPathElement { - fn from(value: TargetPathAsTraceAsString) -> Self { - Self::AsTraceAsString(value) +impl From for TargetPathElement { + fn from(value: TargetPathToTraceAsString) -> Self { + Self::ToTraceAsString(value) } } @@ -112,7 +112,7 @@ impl fmt::Display for TargetPathElement { Self::ArrayElement(v) => v.fmt(f), Self::DynArrayElement(v) => v.fmt(f), Self::TraceAsStringInner(v) => v.fmt(f), - Self::AsTraceAsString(v) => v.fmt(f), + Self::ToTraceAsString(v) => v.fmt(f), } } } @@ -141,7 +141,7 @@ impl TargetPathElement { TraceAsString::::from_canonical(parent.canonical_ty()); parent_ty.inner_ty() } - &Self::AsTraceAsString(TargetPathAsTraceAsString { ty }) => { + &Self::ToTraceAsString(TargetPathToTraceAsString { ty }) => { assert_eq!(parent.canonical_ty(), ty.inner_ty()); ty.canonical() } @@ -159,7 +159,7 @@ impl TargetPathElement { Self::ArrayElement(_) | Self::DynArrayElement(_) | Self::TraceAsStringInner(_) - | Self::AsTraceAsString(_) => parent.flow(), + | Self::ToTraceAsString(_) => parent.flow(), } } pub fn is_static(&self) -> bool { @@ -167,7 +167,7 @@ impl TargetPathElement { Self::BundleField(_) | Self::ArrayElement(_) | Self::TraceAsStringInner(_) - | Self::AsTraceAsString(_) => true, + | Self::ToTraceAsString(_) => true, Self::DynArrayElement(_) => false, } } @@ -364,6 +364,7 @@ pub struct TargetChild { path_element: Interned, canonical_ty: CanonicalType, flow: Flow, + canonicalized_if_different: Option>, } impl fmt::Debug for TargetChild { @@ -373,6 +374,7 @@ impl fmt::Debug for TargetChild { path_element, canonical_ty: _, flow: _, + canonicalized_if_different: _, } = self; parent.fmt(f)?; fmt::Display::fmt(path_element, f) @@ -386,6 +388,7 @@ impl fmt::Display for TargetChild { path_element, canonical_ty: _, flow: _, + canonicalized_if_different: _, } = self; parent.fmt(f)?; path_element.fmt(f) @@ -393,14 +396,69 @@ impl fmt::Display for TargetChild { } impl TargetChild { - pub fn new(parent: Interned, path_element: Interned) -> Self { + fn new_helper( + parent: Interned, + path_element: Interned, + canonicalized_if_different: Option>, + ) -> Self { Self { parent, path_element, canonical_ty: path_element.canonical_ty(parent), flow: path_element.flow(parent), + canonicalized_if_different, } } + fn make_canonicalized_if_different( + parent: Interned, + path_element: Interned, + ) -> Option> { + use TargetPathElement::*; + match *path_element { + BundleField(_) => {} + ArrayElement(_) => {} + DynArrayElement(_) => {} + TraceAsStringInner(_) => { + if let Some(child) = parent.canonicalized().child() { + match *child.path_element() { + BundleField(_) + | ArrayElement(_) + | DynArrayElement(_) + | TraceAsStringInner(_) => {} + ToTraceAsString(_) => return Some(child.parent()), + } + } + } + ToTraceAsString(TargetPathToTraceAsString { ty }) => { + if let Some(child) = parent.canonicalized().child() { + match *child.path_element() { + BundleField(_) | ArrayElement(_) | DynArrayElement(_) + | ToTraceAsString(_) => {} + TraceAsStringInner(_) => { + if ty.canonical() == child.parent().canonical_ty() { + return Some(child.parent()); + } + } + } + } + } + } + Some( + Target::Child(Self::new_helper( + parent.canonicalized_if_different()?, + path_element, + None, + )) + .intern_sized(), + ) + } + pub fn new(parent: Interned, path_element: Interned) -> Self { + Self::new_helper( + parent, + path_element, + Self::make_canonicalized_if_different(parent, path_element), + ) + } pub fn parent(self) -> Interned { self.parent } @@ -413,6 +471,19 @@ impl TargetChild { pub fn flow(self) -> Flow { self.flow } + pub fn is_canonicalized(self) -> bool { + self.canonicalized_if_different.is_none() + } + pub fn canonicalized_if_different(self) -> Option> { + self.canonicalized_if_different + } + #[must_use] + pub fn canonicalized(self) -> Target { + match self.canonicalized_if_different { + Some(v) => *v, + None => Target::Child(self), + } + } pub fn bundle_field(self) -> Option { if let TargetPathElement::BundleField(TargetPathBundleField { name }) = *self.path_element { let parent_ty = Bundle::from_canonical(self.parent.canonical_ty()); @@ -493,6 +564,82 @@ impl Target { Target::Child(v) => v.canonical_ty(), } } + pub fn is_canonicalized(self) -> bool { + match self { + Self::Base(_) => true, + Self::Child(child) => child.is_canonicalized(), + } + } + pub fn canonicalized_if_different(self) -> Option> { + match self { + Self::Base(_) => None, + Self::Child(child) => child.canonicalized_if_different(), + } + } + #[must_use] + pub fn canonicalized(self) -> Target { + match self.canonicalized_if_different() { + Some(v) => *v, + None => self, + } + } + #[must_use] + pub fn canonicalized_interned(this: Interned) -> Interned { + this.canonicalized_if_different().unwrap_or(this) + } + #[must_use] + pub fn unwrap_transparent_types(mut self) -> Target { + loop { + self = self.canonicalized(); + match self.canonical_ty() { + CanonicalType::UInt(_) + | CanonicalType::SInt(_) + | CanonicalType::Bool(_) + | CanonicalType::Array(_) + | CanonicalType::Enum(_) + | CanonicalType::Bundle(_) + | CanonicalType::AsyncReset(_) + | CanonicalType::SyncReset(_) + | CanonicalType::Reset(_) + | CanonicalType::Clock(_) + | CanonicalType::PhantomConst(_) + | CanonicalType::DynSimOnly(_) => return self, + CanonicalType::TraceAsString(_) => { + if let Self::Child(child) = self + && let TargetPathElement::ToTraceAsString(_) = *child.path_element() + { + self = *child.parent(); + } else { + self = self.join(TargetPathElement::intern_sized( + TargetPathTraceAsStringInner {}.into(), + )); + } + } + } + } + } + #[must_use] + pub fn unwrap_transparent_types_interned(this: Interned) -> Interned { + let retval = this.unwrap_transparent_types(); + if retval != *this { + retval.intern_sized() + } else { + this + } + } + #[must_use] + pub fn without_trailing_transparent_path_elements(mut self) -> Target { + use TargetPathElement::*; + loop { + match self { + Self::Base(_) => return self, + Self::Child(child) => match *child.path_element() { + BundleField(_) | ArrayElement(_) | DynArrayElement(_) => return self, + TraceAsStringInner(_) | ToTraceAsString(_) => self = *child.parent(), + }, + } + } + } } impl fmt::Display for Target { diff --git a/crates/fayalite/src/firrtl.rs b/crates/fayalite/src/firrtl.rs index 23aeb2e..51aa040 100644 --- a/crates/fayalite/src/firrtl.rs +++ b/crates/fayalite/src/firrtl.rs @@ -1802,7 +1802,7 @@ impl<'a> Exporter<'a> { write!(out, "[{index}]").unwrap(); Ok(out) } - ExprEnum::AsTraceAsString(expr) => self.expr(expr.inner(), definitions, const_ty), + ExprEnum::ToTraceAsString(expr) => self.expr(expr.inner(), definitions, const_ty), ExprEnum::TraceAsStringAsInner(expr) => { self.expr(Expr::canonical(expr.arg()), definitions, const_ty) } @@ -1965,7 +1965,7 @@ impl<'a> Exporter<'a> { .segments .push(AnnotationTargetRefSegment::Index { index }), TargetPathElement::DynArrayElement(_) => unreachable!(), - TargetPathElement::AsTraceAsString(_) + TargetPathElement::ToTraceAsString(_) | TargetPathElement::TraceAsStringInner(_) => { // ignored } @@ -3223,7 +3223,7 @@ impl ScalarizeTreeNode { TargetPathElement::DynArrayElement(_) => { unreachable!("annotations are only on static targets"); } - TargetPathElement::AsTraceAsString(_) + TargetPathElement::ToTraceAsString(_) | TargetPathElement::TraceAsStringInner(_) => parent, } } diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index f39f800..816a286 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -12,7 +12,7 @@ use crate::{ ops::VariantAccess, target::{ GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, - TargetPathElement, TargetPathTraceAsStringInner, + TargetPathElement, }, value_category::ValueCategoryExpr, }, @@ -1113,7 +1113,7 @@ fn validate_clock_for_past( match *child.path_element() { TargetPathElement::BundleField(_) | TargetPathElement::ArrayElement(_) - | TargetPathElement::AsTraceAsString(_) + | TargetPathElement::ToTraceAsString(_) | TargetPathElement::TraceAsStringInner(_) => {} TargetPathElement::DynArrayElement(_) => { panic!( @@ -1538,6 +1538,7 @@ impl TargetState { } } fn new(target: Interned, declared_in_block: usize) -> Self { + let target = Target::unwrap_transparent_types_interned(target); Self { target, inner: match target.canonical_ty() { @@ -1590,12 +1591,7 @@ impl TargetState { written_in_blocks: RefCell::default(), }, CanonicalType::TraceAsString(_) => { - return Self::new( - target - .join(Intern::intern_sized(TargetPathTraceAsStringInner {}.into())) - .intern_sized(), - declared_in_block, - ); + unreachable!("handled by Target::unwrap_transparent_types_interned") } }, } @@ -1616,13 +1612,14 @@ impl AssertValidityState { } fn get_target_states<'a>( &'a self, - mut target: &Target, + target: Target, process_target_state: &dyn Fn(&'a TargetState, bool), ) -> Result<(), ()> { + let mut target = target.unwrap_transparent_types(); loop { break match target { Target::Base(target_base) => { - let target_state = self.get_base_state(*target_base)?; + let target_state = self.get_base_state(target_base)?; process_target_state(target_state, false); Ok(()) } @@ -1630,7 +1627,7 @@ impl AssertValidityState { TargetPathElement::BundleField(_) | TargetPathElement::ArrayElement(_) | TargetPathElement::DynArrayElement(_) => self.get_target_states( - &target_child.parent(), + *target_child.parent(), &|target_state, exact_target_unknown| { let TargetStateInner::Decomposed { subtargets } = &target_state.inner else { @@ -1657,13 +1654,13 @@ impl AssertValidityState { } } TargetPathElement::TraceAsStringInner(_) - | TargetPathElement::AsTraceAsString(_) => unreachable!(), + | TargetPathElement::ToTraceAsString(_) => unreachable!(), } }, ), TargetPathElement::TraceAsStringInner(_) - | TargetPathElement::AsTraceAsString(_) => { - target = Interned::into_inner(target_child.parent()); + | TargetPathElement::ToTraceAsString(_) => { + target = *target_child.parent(); continue; } }, @@ -1718,6 +1715,7 @@ impl AssertValidityState { &TargetPathElement::BundleField(_) => { let field = sub_target_state .target + .without_trailing_transparent_path_elements() .child() .expect("known to be a child") .bundle_field() @@ -1742,7 +1740,7 @@ impl AssertValidityState { Self::set_connect_target_written(sub_target_state, is_lhs, block, true); } TargetPathElement::TraceAsStringInner(_) - | TargetPathElement::AsTraceAsString(_) => unreachable!("never added"), + | TargetPathElement::ToTraceAsString(_) => unreachable!("never added"), } } } @@ -1760,7 +1758,7 @@ impl AssertValidityState { debug_assert!(!is_lhs, "the ModuleBuilder asserts lhs.target().is_some()"); return; }; - let result = self.get_target_states(&target, &|target_state, exact_target_unknown| { + let result = self.get_target_states(*target, &|target_state, exact_target_unknown| { Self::set_connect_target_written(target_state, is_lhs, block, exact_target_unknown); }); if result.is_err() { diff --git a/crates/fayalite/src/module/transform/deduce_resets.rs b/crates/fayalite/src/module/transform/deduce_resets.rs index ef95c1c..4595e84 100644 --- a/crates/fayalite/src/module/transform/deduce_resets.rs +++ b/crates/fayalite/src/module/transform/deduce_resets.rs @@ -9,8 +9,8 @@ use crate::{ ExprEnum, ValueType, ops::{self, ArrayLiteral}, target::{ - Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathAsTraceAsString, - TargetPathBundleField, TargetPathDynArrayElement, TargetPathElement, + Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField, + TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString, TargetPathTraceAsStringInner, }, }, @@ -1207,7 +1207,7 @@ impl RunPass

for ExprEnum { ExprEnum::TraceAsStringAsInner(expr) => { Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)) } - ExprEnum::AsTraceAsString(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), + ExprEnum::ToTraceAsString(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::ModuleIO(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::Instance(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), ExprEnum::Wire(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), @@ -1617,7 +1617,7 @@ impl RunPassExpr for ops::TraceAsStringAsInner { } } -impl RunPassExpr for ops::AsTraceAsString { +impl RunPassExpr for ops::ToTraceAsString { type Args<'a> = [Expr; 1]; fn args<'a>(&'a self) -> Self::Args<'a> { @@ -2307,8 +2307,8 @@ impl RunPass

for TargetChild { | TargetPathElement::TraceAsStringInner(TargetPathTraceAsStringInner {}) => { self.path_element() } - TargetPathElement::AsTraceAsString(TargetPathAsTraceAsString { ty }) => { - TargetPathElement::from(TargetPathAsTraceAsString { + TargetPathElement::ToTraceAsString(TargetPathToTraceAsString { ty }) => { + TargetPathElement::from(TargetPathToTraceAsString { ty: ty.with_new_inner_ty(parent.canonical_ty().intern_sized()), }) .intern_sized() diff --git a/crates/fayalite/src/module/transform/simplify_enums.rs b/crates/fayalite/src/module/transform/simplify_enums.rs index 02b4dda..5f136f2 100644 --- a/crates/fayalite/src/module/transform/simplify_enums.rs +++ b/crates/fayalite/src/module/transform/simplify_enums.rs @@ -807,7 +807,7 @@ impl Folder for State { | ExprEnum::CastToBits(_) | ExprEnum::CastBitsTo(_) | ExprEnum::TraceAsStringAsInner(_) - | ExprEnum::AsTraceAsString(_) + | ExprEnum::ToTraceAsString(_) | ExprEnum::ModuleIO(_) | ExprEnum::Instance(_) | ExprEnum::Wire(_) diff --git a/crates/fayalite/src/module/transform/visit.rs b/crates/fayalite/src/module/transform/visit.rs index 134d9a8..7b4cd2a 100644 --- a/crates/fayalite/src/module/transform/visit.rs +++ b/crates/fayalite/src/module/transform/visit.rs @@ -13,8 +13,8 @@ use crate::{ expr::{ Expr, ExprEnum, ValueType, ops, target::{ - Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathAsTraceAsString, - TargetPathBundleField, TargetPathDynArrayElement, TargetPathElement, + Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField, + TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString, TargetPathTraceAsStringInner, }, }, diff --git a/crates/fayalite/src/prelude.rs b/crates/fayalite/src/prelude.rs index 4c5bfdf..42038ca 100644 --- a/crates/fayalite/src/prelude.rs +++ b/crates/fayalite/src/prelude.rs @@ -13,7 +13,7 @@ pub use crate::{ enum_::{Enum, HdlNone, HdlOption, HdlSome}, expr::{ CastBitsTo, CastTo, CastToBits, Expr, HdlPartialEq, HdlPartialOrd, MakeUninitExpr, - ReduceBits, ToExpr, ValueType, repeat, + ReduceBits, ToExpr, ToTraceAsString, ValueType, repeat, }, formal::{ MakeFormalExpr, all_const, all_seq, any_const, any_seq, formal_global_clock, formal_reset, @@ -38,7 +38,7 @@ pub use crate::{ }, source_location::SourceLocation, testing::{FormalMode, assert_formal}, - ty::{AsMask, CanonicalType, Type}, + ty::{AsMask, CanonicalType, TraceAsString, Type}, util::{ConstUsize, GenericConstUsize}, wire::Wire, }; diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index 658ae10..1247fd8 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -1307,7 +1307,7 @@ impl SimulationModuleState { TargetPathElement::BundleField(_) | TargetPathElement::ArrayElement(_) | TargetPathElement::TraceAsStringInner(_) - | TargetPathElement::AsTraceAsString(_) => {} + | TargetPathElement::ToTraceAsString(_) => {} TargetPathElement::DynArrayElement(_) => panic!( "simulator read/write expression must not have dynamic array indexes" ), diff --git a/crates/fayalite/src/sim/compiler.rs b/crates/fayalite/src/sim/compiler.rs index 4f5c571..4d6d9bc 100644 --- a/crates/fayalite/src/sim/compiler.rs +++ b/crates/fayalite/src/sim/compiler.rs @@ -9,8 +9,8 @@ use crate::{ expr::{ ExprEnum, Flow, ValueType, ops, target::{ - GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathAsTraceAsString, - TargetPathBundleField, TargetPathElement, TargetPathTraceAsStringInner, + GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, + TargetPathElement, TargetPathToTraceAsString, TargetPathTraceAsStringInner, }, }, int::BoolOrIntType, @@ -2686,7 +2686,7 @@ impl Compiler { TargetPathElement::TraceAsStringInner(TargetPathTraceAsStringInner {}) => { parent.map_ty(TraceAsString::from_canonical).inner() } - TargetPathElement::AsTraceAsString(TargetPathAsTraceAsString { ty }) => parent + TargetPathElement::ToTraceAsString(TargetPathToTraceAsString { ty }) => parent .wrap_in_trace_as_string(ty) .map_ty(|ty| ty.canonical()), } @@ -3017,7 +3017,7 @@ impl Compiler { }); } CanonicalType::TraceAsString(ty) => Expr::canonical( - ops::AsTraceAsString::new( + ops::ToTraceAsString::new( match arg { Some(arg) => arg.cast_bits_to(ty.inner_ty()), None => ty.inner_ty().uninit(), @@ -3838,7 +3838,7 @@ impl Compiler { ExprEnum::CastBitsTo(expr) => self .compile_cast_bits_to_or_uninit(instantiated_module, Some(expr.arg()), expr.ty()) .into(), - ExprEnum::AsTraceAsString(expr) => self + ExprEnum::ToTraceAsString(expr) => self .compile_expr(instantiated_module, expr.inner()) .wrap_in_trace_as_string(expr.ty()) .map_ty(|ty| ty.canonical()), diff --git a/crates/fayalite/src/sim/value.rs b/crates/fayalite/src/sim/value.rs index 79515ac..24bc1ef 100644 --- a/crates/fayalite/src/sim/value.rs +++ b/crates/fayalite/src/sim/value.rs @@ -19,20 +19,19 @@ use crate::{ impl_match_variant_as_self, }, util::{ - ConstUsize, HashMap, + ConstUsize, alternating_cell::{AlternatingCell, AlternatingCellMethods}, + serde_by_id::{SerdeById, SerdeByIdProperties, SerdeByIdTable, SerdeByIdTrait}, }, }; use bitvec::{slice::BitSlice, vec::BitVec}; -use hashbrown::hash_map::Entry; use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _, ser::Error as _}; use std::{ borrow::{Borrow, BorrowMut, Cow}, - fmt::{self, Write}, - hash::{BuildHasher, Hash, Hasher, RandomState}, + fmt, num::NonZero, ops::{Deref, DerefMut, Index, IndexMut}, - sync::{Arc, Mutex}, + sync::Arc, }; pub(crate) mod sim_only_value_unsafe; @@ -1228,80 +1227,17 @@ macro_rules! impl_to_sim_value_for_int_value { impl_to_sim_value_for_int_value!(UIntValue, UInt, UIntType); impl_to_sim_value_for_int_value!(SIntValue, SInt, SIntType); -#[derive(Default)] -struct DynSimOnlySerdeTableRest { - from_serde: HashMap, - serde_id_random_state: RandomState, - buffer: String, -} - -impl DynSimOnlySerdeTableRest { - #[cold] - fn add_new(&mut self, ty: DynSimOnly) -> DynSimOnlySerdeId { - let mut try_number = 0u64; - let mut hasher = self.serde_id_random_state.build_hasher(); - // extract more bits of randomness from TypeId -- its Hash impl only hashes 64-bits - write!(self.buffer, "{:?}", ty.type_id()).expect("shouldn't ever fail"); - self.buffer.hash(&mut hasher); - loop { - let mut hasher = hasher.clone(); - try_number.hash(&mut hasher); - try_number += 1; - let retval = DynSimOnlySerdeId(std::array::from_fn(|i| { - let mut hasher = hasher.clone(); - i.hash(&mut hasher); - hasher.finish() as u32 - })); - match self.from_serde.entry(retval) { - Entry::Occupied(_) => continue, - Entry::Vacant(e) => { - e.insert(ty); - return retval; - } - } - } +impl SerdeByIdTrait for DynSimOnly { + fn serde_by_id_properties(&self) -> SerdeByIdProperties { + self.serde_by_id_properties_inner() } -} -#[derive(Default)] -struct DynSimOnlySerdeTable { - to_serde: HashMap, - rest: DynSimOnlySerdeTableRest, -} - -static DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE: Mutex> = Mutex::new(None); - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] -#[serde(transparent)] -struct DynSimOnlySerdeId([u32; 4]); - -impl From for DynSimOnlySerdeId { - fn from(ty: DynSimOnly) -> Self { - let mut locked = DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE - .lock() - .expect("shouldn't be poison"); - let DynSimOnlySerdeTable { to_serde, rest } = locked.get_or_insert_default(); - match to_serde.entry(ty) { - Entry::Occupied(occupied_entry) => *occupied_entry.get(), - Entry::Vacant(vacant_entry) => *vacant_entry.insert(rest.add_new(ty)), - } + fn static_table() -> &'static SerdeByIdTable { + static TABLE: SerdeByIdTable = SerdeByIdTable::new(); + &TABLE } -} -impl DynSimOnlySerdeId { - fn ty(self) -> Option { - let locked = DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE - .lock() - .expect("shouldn't be poison"); - Some(*locked.as_ref()?.rest.from_serde.get(&self)?) - } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] -struct DynSimOnlySerde<'a> { - random_id: DynSimOnlySerdeId, - #[serde(borrow)] - type_name: Cow<'a, str>, + const NAME: &'static str = "DynSimOnly"; } impl Serialize for DynSimOnly { @@ -1309,11 +1245,7 @@ impl Serialize for DynSimOnly { where S: Serializer, { - DynSimOnlySerde { - random_id: (*self).into(), - type_name: Cow::Borrowed(self.type_name()), - } - .serialize(serializer) + SerdeById { inner: *self }.serialize(serializer) } } @@ -1322,16 +1254,7 @@ impl<'de> Deserialize<'de> for DynSimOnly { where D: Deserializer<'de>, { - let deserialized = DynSimOnlySerde::deserialize(deserializer)?; - let retval = deserialized - .random_id - .ty() - .filter(|ty| ty.type_name() == deserialized.type_name); - retval.ok_or_else(|| { - D::Error::custom( - "doesn't match any DynSimOnly that was serialized this time this program was run", - ) - }) + Ok(SerdeById::deserialize(deserializer)?.inner) } } diff --git a/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs b/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs index 2424c03..bcbcdc6 100644 --- a/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs +++ b/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs @@ -3,7 +3,10 @@ //! `unsafe` parts of [`DynSimOnlyValue`] -use crate::expr::{ValueType, value_category::ValueCategoryValue}; +use crate::{ + expr::{ValueType, value_category::ValueCategoryValue}, + util::serde_by_id::SerdeByIdProperties, +}; use serde::{Serialize, de::DeserializeOwned}; use std::{ any::{self, TypeId}, @@ -33,6 +36,7 @@ unsafe trait DynSimOnlyTrait: 'static + Send + Sync { &self, json_str: &str, ) -> serde_json::Result>; + fn serde_by_id_properties_inner(&self) -> SerdeByIdProperties; } /// Safety: `type_id_dyn` is implemented correctly @@ -55,6 +59,9 @@ unsafe impl DynSimOnlyTrait for SimOnly { ) -> serde_json::Result> { Ok(Rc::::new(serde_json::from_str(json_str)?)) } + fn serde_by_id_properties_inner(&self) -> SerdeByIdProperties { + SerdeByIdProperties::of::() + } } /// Safety: @@ -151,6 +158,9 @@ impl DynSimOnly { pub fn default_value(self) -> DynSimOnlyValue { DynSimOnlyValue(self.ty.default_value()) } + pub(super) fn serde_by_id_properties_inner(self) -> SerdeByIdProperties { + self.ty.serde_by_id_properties_inner() + } } impl PartialEq for DynSimOnly { diff --git a/crates/fayalite/src/ty.rs b/crates/fayalite/src/ty.rs index 2988a7d..ab69532 100644 --- a/crates/fayalite/src/ty.rs +++ b/crates/fayalite/src/ty.rs @@ -6,7 +6,7 @@ use crate::{ bundle::{Bundle, BundleField, BundleType}, clock::Clock, enum_::{Enum, EnumType, EnumVariant}, - expr::{Expr, ToExpr, ValueType, ops}, + expr::{Expr, HdlPartialEqImpl, HdlPartialOrdImpl, ToExpr, ValueType, Valueless, ops}, int::{Bool, SInt, UInt, UIntValue}, intern::{Intern, Interned, LazyInterned, Memoize, SupportsPtrEqWithTypeId}, module::transform::visit::{Fold, Folder, Visit, Visitor}, @@ -23,6 +23,7 @@ use crate::{ use bitvec::{slice::BitSlice, vec::BitVec}; use serde::{Deserialize, Deserializer, Serialize, Serializer, de::DeserializeOwned}; use std::{ + borrow::Cow, fmt::{self, Write}, hash::Hash, iter::{FusedIterator, Sum}, @@ -997,9 +998,6 @@ impl OpaqueSimValue { pub fn sim_only_values(&self) -> &[DynSimOnlyValue] { &self.sim_only_values } - pub(crate) fn sim_only_values_vec(&self) -> &Vec { - &self.sim_only_values - } pub fn sim_only_values_mut(&mut self) -> &mut Vec { &mut self.sim_only_values } @@ -1463,14 +1461,14 @@ impl SimValueDebug for TraceAsString { value: &::SimValue, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { - T::sim_value_debug(value, f) + T::sim_value_debug(value.inner(), f) } } impl Type for TraceAsString { type BaseType = TraceAsString; type MaskType = T::MaskType; - type SimValue = TraceAsStringSimValue; + type SimValue = TraceAsStringSimValue; type MatchVariant = Expr; type MatchActiveScope = (); type MatchVariantAndInactiveScope = MatchVariantWithoutScope; @@ -1507,7 +1505,8 @@ impl Type for TraceAsString { fn sim_value_from_opaque(&self, opaque: OpaqueSimValueSlice<'_>) -> Self::SimValue { TraceAsStringSimValue { - inner: self.inner_ty.sim_value_from_opaque(opaque), + inner: SimValue::from_opaque(self.inner_ty(), opaque.to_owned()), + trace_as_string: self.trace_as_string.interned(), } } @@ -1594,101 +1593,217 @@ impl Index for TraceAsStringWithoutGenerics { } } -#[derive(Copy, Clone, Eq, Ord, Hash, Default, Serialize, Deserialize)] -pub struct TraceAsStringSimValue { +#[derive(Clone)] +pub struct TraceAsStringSimValue { + inner: SimValue, + trace_as_string: Interned, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename = "TraceAsStringSimValue")] +struct TraceAsStringSimValueSerde { inner: T, + trace_as_string: crate::util::serde_by_id::SerdeById>, } -impl TraceAsStringSimValue { - pub const fn new(inner: T) -> Self { - Self { inner } - } - pub fn into_inner(this: Self) -> T { - let Self { inner } = this; - inner +impl + Serialize> Serialize for TraceAsStringSimValue { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let Self { + inner, + trace_as_string, + } = self; + TraceAsStringSimValueSerde { + inner, + trace_as_string: crate::util::serde_by_id::SerdeById { + inner: *trace_as_string, + }, + } + .serialize(serializer) } } -impl ValueType for TraceAsStringSimValue { - type Type = TraceAsString; - type ValueCategory = T::ValueCategory; - - fn ty(&self) -> Self::Type { - TraceAsString::new(self.inner.ty()) - } -} - -impl ToExpr for TraceAsStringSimValue { - fn to_expr(&self) -> Expr { - let inner = self.inner.to_expr(); - ops::AsTraceAsString::new(Expr::canonical(inner), TraceAsString::new(inner.ty())).to_expr() - } -} - -impl, Ty: Type> ToSimValueWithType> +impl<'de, T: Type> + Deserialize<'de>> Deserialize<'de> for TraceAsStringSimValue { - fn to_sim_value_with_type(&self, ty: TraceAsString) -> SimValue> { - let inner = self.inner.to_sim_value_with_type(ty.inner_ty()); - let inner = SimValue::into_value(inner); - SimValue::from_value(ty, TraceAsStringSimValue { inner }) - } - fn into_sim_value_with_type(self, ty: TraceAsString) -> SimValue> { - let inner = self.inner.into_sim_value_with_type(ty.inner_ty()); - let inner = SimValue::into_value(inner); - SimValue::from_value(ty, TraceAsStringSimValue { inner }) + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let TraceAsStringSimValueSerde { + inner, + trace_as_string: + crate::util::serde_by_id::SerdeById { + inner: trace_as_string, + }, + } = Deserialize::deserialize(deserializer)?; + Ok(Self { + inner, + trace_as_string, + }) } } -impl ToSimValue for TraceAsStringSimValue { - fn to_sim_value(&self) -> SimValue { - self.to_sim_value_with_type(self.ty()) +impl TraceAsStringSimValue { + pub fn new_with_ty(inner: impl ToSimValueWithType, ty: TraceAsString) -> Self { + Self { + inner: inner.into_sim_value_with_type(ty.inner_ty()), + trace_as_string: ty.trace_as_string.interned(), + } } - fn into_sim_value(self) -> SimValue { - let ty = self.ty(); - self.into_sim_value_with_type(ty) + pub fn new(inner: impl ToSimValue) -> Self { + let inner = inner.into_sim_value(); + Self { + trace_as_string: TraceAsString::new(inner.ty()).trace_as_string.interned(), + inner, + } } -} - -impl std::ops::Deref for TraceAsStringSimValue { - type Target = T; - - fn deref(&self) -> &Self::Target { + pub fn into_inner(self) -> SimValue { + self.inner + } + pub fn inner(&self) -> &SimValue { &self.inner } -} - -impl std::ops::DerefMut for TraceAsStringSimValue { - fn deref_mut(&mut self) -> &mut Self::Target { + pub fn inner_mut(&mut self) -> &mut SimValue { &mut self.inner } } -impl fmt::Debug for TraceAsStringSimValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { inner } = self; - fmt::Debug::fmt(inner, f) +impl ValueType for TraceAsStringSimValue { + type Type = TraceAsString; + type ValueCategory = crate::expr::value_category::ValueCategoryValue; + + fn ty(&self) -> Self::Type { + let inner_ty = self.inner.ty().intern_sized(); + if self + .trace_as_string + .can_substitute_type(inner_ty.canonical()) + { + TraceAsString { + inner_ty: LazyInterned::Interned(inner_ty), + trace_as_string: LazyInterned::Interned(self.trace_as_string), + } + } else { + TraceAsString::new_interned(inner_ty) + } } } -impl fmt::Display for TraceAsStringSimValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { inner } = self; - fmt::Display::fmt(inner, f) +impl ToExpr for TraceAsStringSimValue { + #[track_caller] + fn to_expr(&self) -> Expr { + let inner = self.inner.to_expr(); + let inner_canonical = Expr::canonical(inner); + let inner_ty = inner.ty().intern_sized(); + let ty = if self + .trace_as_string + .can_substitute_type(inner_canonical.ty()) + { + TraceAsString { + inner_ty: LazyInterned::Interned(inner_ty), + trace_as_string: LazyInterned::Interned(self.trace_as_string), + } + } else { + TraceAsString::new_interned(inner_ty) + }; + ops::ToTraceAsString::new(inner_canonical, ty).to_expr() } } -impl, U> PartialOrd> for TraceAsStringSimValue { +impl ToSimValueWithType> for TraceAsStringSimValue { + fn to_sim_value_with_type(&self, ty: TraceAsString) -> SimValue> { + let inner = self.inner.to_sim_value_with_type(ty.inner_ty()); + SimValue::from_value( + ty, + TraceAsStringSimValue { + inner, + trace_as_string: ty.trace_as_string.interned(), + }, + ) + } + fn into_sim_value_with_type(self, ty: TraceAsString) -> SimValue> { + let inner = self.inner.into_sim_value_with_type(ty.inner_ty()); + SimValue::from_value( + ty, + TraceAsStringSimValue { + inner, + trace_as_string: ty.trace_as_string.interned(), + }, + ) + } +} + +impl ToSimValue for TraceAsStringSimValue { + fn to_sim_value(&self) -> SimValue { + SimValue::from_value(self.ty(), self.clone()) + } + fn into_sim_value(self) -> SimValue { + SimValue::from_value(self.ty(), self) + } +} + +impl fmt::Debug for TraceAsStringSimValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.inner, f) + } +} + +impl> fmt::Display for TraceAsStringSimValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.inner, f) + } +} + +impl Ord for TraceAsStringSimValue +where + SimValue: Ord, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.inner.cmp(&other.inner) + } +} + +impl PartialOrd> for TraceAsStringSimValue +where + SimValue: PartialOrd>, +{ fn partial_cmp(&self, other: &TraceAsStringSimValue) -> Option { - let Self { inner } = self; - inner.partial_cmp(&other.inner) + self.inner.partial_cmp(&other.inner) } } -impl, U> PartialEq> for TraceAsStringSimValue { +impl Eq for TraceAsStringSimValue where SimValue: Eq {} + +impl Hash for TraceAsStringSimValue +where + SimValue: Hash, +{ + fn hash(&self, state: &mut H) { + self.inner.hash(state); + } +} + +impl Default for TraceAsStringSimValue +where + SimValue: Default, +{ + fn default() -> Self { + let inner = SimValue::default(); + Self { + trace_as_string: TraceAsString::new(inner.ty()).trace_as_string.interned(), + inner, + } + } +} + +impl PartialEq> for TraceAsStringSimValue +where + SimValue: PartialEq>, +{ fn eq(&self, other: &TraceAsStringSimValue) -> bool { - let Self { inner } = self; - *inner == other.inner + self.inner == other.inner } } @@ -1711,3 +1826,259 @@ impl, State: ?Sized + Visitor> Visit for TraceAsSt self.interned_inner_ty().visit(state) } } + +fn trace_as_string_cow_into_inner( + this: Cow<'_, SimValue>>, +) -> Cow<'_, SimValue> { + match this { + Cow::Borrowed(v) => Cow::Borrowed(&v.inner), + Cow::Owned(v) => Cow::Owned(SimValue::into_value(v).inner), + } +} + +fn trace_as_string_cow_into_inner_value( + this: Cow<'_, TraceAsStringSimValue>, +) -> Cow<'_, T::SimValue> { + match this { + Cow::Borrowed(v) => Cow::Borrowed(&v.inner), + Cow::Owned(v) => Cow::Owned(SimValue::into_value(v.inner)), + } +} + +impl, U: Type> HdlPartialEqImpl> for TraceAsString { + #[track_caller] + fn cmp_value_eq( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialEqImpl::cmp_value_eq( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_ne( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialEqImpl::cmp_value_ne( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_sim_value_eq( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialEqImpl::cmp_sim_value_eq( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_ne( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialEqImpl::cmp_sim_value_ne( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_expr_eq(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialEqImpl::cmp_expr_eq(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_ne(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialEqImpl::cmp_expr_ne(*lhs, *rhs) + } + + #[track_caller] + fn cmp_valueless_eq(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialEqImpl::cmp_valueless_eq( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_ne(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialEqImpl::cmp_valueless_ne( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } +} + +impl, U: Type> HdlPartialOrdImpl> for TraceAsString { + #[track_caller] + fn cmp_value_lt( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_lt( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_le( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_le( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_gt( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_gt( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_ge( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_ge( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_sim_value_lt( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_lt( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_le( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_le( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_gt( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_gt( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_ge( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_ge( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_expr_lt(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_lt(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_le(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_le(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_gt(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_gt(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_ge(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_ge(*lhs, *rhs) + } + + #[track_caller] + fn cmp_valueless_lt(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_lt( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_le(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_le( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_gt(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_gt( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_ge(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_ge( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } +} diff --git a/crates/fayalite/src/ty/serde_impls.rs b/crates/fayalite/src/ty/serde_impls.rs index 126c4b0..d5b5551 100644 --- a/crates/fayalite/src/ty/serde_impls.rs +++ b/crates/fayalite/src/ty/serde_impls.rs @@ -39,6 +39,7 @@ impl<'de, T: ?Sized + PhantomConstValue> Deserialize<'de> for SerdePhantomConst< #[derive(Serialize, Deserialize)] #[serde(rename = "CanonicalType")] +#[expect(private_interfaces)] pub(crate) enum SerdeCanonicalType< ArrayElement = CanonicalType, ThePhantomConst = SerdePhantomConst>, diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index 238259c..80ae4c2 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -13,7 +13,7 @@ use fayalite::{ prelude::*, reset::ResetType, sim::vcd::VcdWriterDecls, - ty::{SimValueDebug, StaticType, TraceAsString, TraceAsStringSimValue}, + ty::SimValueDebug, util::{RcWriter, ready_valid::queue}, }; use std::{collections::BTreeMap, num::NonZeroUsize, rc::Rc}; @@ -3019,6 +3019,9 @@ impl HasCustomDebug { } } } + pub fn new(text: Result<&str, std::fmt::Error>) -> Expr { + Self::new_sim(text).to_expr() + } } impl SimValueDebug for HasCustomDebug { @@ -3061,10 +3064,7 @@ pub fn sim_trace_as_string() { #[hdl] let write: WriteStruct, 2>, ConstUsize<8>> = m.input(); #[hdl] - let mut mem = memory_with_init( - [[Expr::as_trace_as_string(HasCustomDebug::new_sim(Ok("")).to_expr(), StaticType::TYPE); 2]; - 4], - ); + let mut mem = memory_with_init([[HasCustomDebug::new(Ok("")).to_trace_as_string(); 2]; 4]); let read_port = mem.new_read_port(); connect(read_port.clk, clk); connect_any(read_port.addr, read.addr); @@ -3156,7 +3156,7 @@ fn test_sim_trace_as_string() { sim.write(sim.io().write.en, write_addr.is_some()); sim.write( sim.io().write.data, - write_data.map(|v| TraceAsStringSimValue::new(HasCustomDebug::new_sim(v))), + write_data.map(|v| HasCustomDebug::new_sim(v).to_trace_as_string()), ); sim.write( sim.io().write.mask, @@ -3172,7 +3172,7 @@ fn test_sim_trace_as_string() { .map(HasCustomDebug::new_sim) .into_sim_value(); assert!( - **read_data == *expected_read_data, + *read_data.inner() == expected_read_data, "{read_data:#?}\n!= {expected_read_data:#?}", ); } diff --git a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr index dbdf937..8eff725 100644 --- a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr +++ b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr @@ -55,7 +55,7 @@ error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'sta note: required because it appears within the type `DynSimOnlyValue` --> src/sim/value/sim_only_value_unsafe.rs | - 271 | pub struct DynSimOnlyValue(Rc); + 281 | pub struct DynSimOnlyValue(Rc); | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` --> $RUST/core/src/marker.rs @@ -75,12 +75,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 895 | pub struct OpaqueSimValue { + 896 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 52 | struct SimValueInner { + 51 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -95,7 +95,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 161 | pub struct SimValue { + 160 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` --> src/intern.rs @@ -194,7 +194,7 @@ error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'sta note: required because it appears within the type `DynSimOnlyValue` --> src/sim/value/sim_only_value_unsafe.rs | - 271 | pub struct DynSimOnlyValue(Rc); + 281 | pub struct DynSimOnlyValue(Rc); | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` --> $RUST/core/src/marker.rs @@ -214,12 +214,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 895 | pub struct OpaqueSimValue { + 896 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 52 | struct SimValueInner { + 51 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -234,7 +234,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 161 | pub struct SimValue { + 160 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `intern_sized` --> src/intern.rs @@ -306,7 +306,7 @@ error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'sta note: required because it appears within the type `DynSimOnlyValue` --> src/sim/value/sim_only_value_unsafe.rs | - 271 | pub struct DynSimOnlyValue(Rc); + 281 | pub struct DynSimOnlyValue(Rc); | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` --> $RUST/core/src/marker.rs @@ -326,12 +326,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 895 | pub struct OpaqueSimValue { + 896 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 52 | struct SimValueInner { + 51 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -346,7 +346,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 161 | pub struct SimValue { + 160 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` --> src/intern.rs diff --git a/crates/fayalite/visit_types.json b/crates/fayalite/visit_types.json index f5d666c..f3af962 100644 --- a/crates/fayalite/visit_types.json +++ b/crates/fayalite/visit_types.json @@ -1022,10 +1022,10 @@ "fold_where": "T: Fold", "visit_where": "T: Visit" }, - "ops::AsTraceAsString": { + "ops::ToTraceAsString": { "data": { "$kind": "Struct", - "$constructor": "ops::AsTraceAsString::new", + "$constructor": "ops::ToTraceAsString::new", "inner()": "Visible", "ty()": "Visible" }, @@ -1310,7 +1310,7 @@ "$kind": "Struct" } }, - "TargetPathAsTraceAsString": { + "TargetPathToTraceAsString": { "data": { "$kind": "Struct", "ty": "Visible" @@ -1323,7 +1323,7 @@ "ArrayElement": "Visible", "DynArrayElement": "Visible", "TraceAsStringInner": "Visible", - "AsTraceAsString": "Visible" + "ToTraceAsString": "Visible" } }, "PhantomConst": { From 1880ed682fa1f10d9883c85e38d99a6975b5e7cb Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 1 Jun 2026 20:41:14 -0700 Subject: [PATCH 09/15] speed up TraceAsString by caching the canonical type for can_substitute_type --- crates/fayalite/src/ty.rs | 46 ++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/crates/fayalite/src/ty.rs b/crates/fayalite/src/ty.rs index ab69532..843aedb 100644 --- a/crates/fayalite/src/ty.rs +++ b/crates/fayalite/src/ty.rs @@ -1309,16 +1309,49 @@ trait TraceAsStringTrait: fmt::Debug + 'static + Send + Sync + SupportsPtrEqWith fn can_substitute_type(&self, new_type: CanonicalType) -> bool; } -impl TraceAsStringTrait for T { +#[derive(Clone, PartialEq, Eq, Hash)] +struct TraceAsStringState { + ty: Interned, + canonical_ty: CanonicalType, +} + +impl TraceAsStringState { + fn new(ty: Interned) -> Interned { + #[derive(Copy, Clone, PartialEq, Eq, Hash)] + struct MyMemoize(PhantomData); + impl Memoize for MyMemoize { + type Input = Interned; + type InputOwned = Interned; + type Output = Interned>; + + fn inner(self, input: &Self::Input) -> Self::Output { + TraceAsStringState { + ty: *input, + canonical_ty: input.canonical(), + } + .intern_sized() + } + } + MyMemoize(PhantomData).get_owned(ty) + } +} + +impl fmt::Debug for TraceAsStringState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.ty.fmt(f) + } +} + +impl TraceAsStringTrait for TraceAsStringState { fn trace_fmt( &self, opaque: OpaqueSimValueSlice<'_>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { - fmt::Debug::fmt(&Type::sim_value_from_opaque(self, opaque), f) + fmt::Debug::fmt(&Type::sim_value_from_opaque(&*self.ty, opaque), f) } fn can_substitute_type(&self, new_type: CanonicalType) -> bool { - self.canonical().is_layout_equivalent(new_type) + self.canonical_ty.is_layout_equivalent(new_type) } } @@ -1374,7 +1407,7 @@ impl TraceAsString { Self { inner_ty: LazyInterned::Interned(inner_ty), trace_as_string: LazyInterned::Interned(Interned::cast_unchecked( - inner_ty, + TraceAsStringState::new(inner_ty), |v| -> &dyn TraceAsStringTrait { v }, )), } @@ -1548,7 +1581,10 @@ impl Default for TraceAsStringStaticTypeHelper { impl From> for Interned { fn from(_value: TraceAsStringStaticTypeHelper) -> Self { - Interned::cast_unchecked(T::TYPE.intern_sized(), |v| -> &dyn TraceAsStringTrait { v }) + Interned::cast_unchecked( + TraceAsStringState::new(T::TYPE.intern_sized()), + |v| -> &dyn TraceAsStringTrait { v }, + ) } } From 6902aea3a6b5e5af63d335544a30a108e82adb4c Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 1 Jun 2026 20:53:22 -0700 Subject: [PATCH 10/15] firrtl: don't generate as many duplicate wires when compiling expressions --- crates/fayalite/src/firrtl.rs | 995 +++++++++++++++++++------------- crates/fayalite/tests/module.rs | 258 ++------- 2 files changed, 652 insertions(+), 601 deletions(-) diff --git a/crates/fayalite/src/firrtl.rs b/crates/fayalite/src/firrtl.rs index 51aa040..e2f33ae 100644 --- a/crates/fayalite/src/firrtl.rs +++ b/crates/fayalite/src/firrtl.rs @@ -2,17 +2,12 @@ // See Notices.txt for copyright information #![allow(clippy::type_complexity)] use crate::{ - annotations::{ - Annotation, BlackBoxInlineAnnotation, BlackBoxPathAnnotation, CustomFirrtlAnnotation, - DocStringAnnotation, DontTouchAnnotation, SVAttributeAnnotation, TargetedAnnotation, - }, - array::Array, + annotations::{Annotation, TargetedAnnotation}, build::{ToArgs, WriteArgs}, - bundle::{Bundle, BundleField, BundleType}, - clock::Clock, - enum_::{Enum, EnumType, EnumVariant}, + bundle::{BundleField, BundleType}, + enum_::{EnumType, EnumVariant}, expr::{ - CastBitsTo, Expr, ExprEnum, ToExpr, ValueType, + ExprEnum, ops::{self, VariantAccess}, target::{ Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement, @@ -20,29 +15,28 @@ use crate::{ }, }, formal::FormalKind, - int::{Bool, DynSize, IntType, SIntValue, UInt, UIntValue}, + int::IntType, intern::{Intern, Interned}, - memory::{Mem, PortKind, PortName, ReadUnderWrite}, + memory::{PortKind, PortName}, module::{ AnnotatedModuleIO, Block, ExternModuleBody, ExternModuleParameter, - ExternModuleParameterValue, Module, ModuleBody, ModuleIO, NameId, NameOptId, - NormalModuleBody, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, - StmtMatch, StmtReg, StmtWire, + ExternModuleParameterValue, ModuleBody, ModuleIO, NameId, NameOptId, NormalModuleBody, + Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, + StmtWire, transform::{ simplify_enums::{SimplifyEnumsError, SimplifyEnumsKind, simplify_enums}, simplify_memories::simplify_memories, }, }, - reset::{AsyncReset, Reset, ResetType, SyncReset}, - source_location::SourceLocation, - ty::{CanonicalType, OpaqueSimValueSize, Type}, + prelude::*, + reset::ResetType, + ty::OpaqueSimValueSize, util::{ BitSliceWriteWithBase, DebugAsRawString, GenericConstBool, HashMap, HashSet, const_str_array_is_strictly_ascending, }, vendor::xilinx::XilinxAnnotation, }; -use bitvec::slice::BitSlice; use clap::value_parser; use num_traits::Signed; use serde::{Deserialize, Serialize}; @@ -378,6 +372,107 @@ impl DefinitionsMap { } } +#[derive(Default)] +struct BlockDefinitionsCache { + array_literal_exprs: + RefCell, bool), String>>, + bundle_literal_exprs: RefCell>, + uninit_exprs: RefCell>, + cast_bundle_to_bits_exprs: RefCell>, + cast_enum_to_bits_exprs: RefCell>, + cast_array_to_bits_exprs: RefCell>, + cast_bits_to_bundle_exprs: RefCell>, + cast_bits_to_enum_exprs: RefCell>, + cast_bits_to_array_exprs: RefCell>, + cast_bits_to_phantom_const_exprs: RefCell>, +} + +struct BlockDefinitionsState<'a> { + rc_definitions: RcDefinitions, + parent: &'a BlockDefinitions<'a>, + cache: BlockDefinitionsCache, +} + +struct BlockDefinitions<'a> { + state: Option>, +} + +impl<'a> BlockDefinitions<'a> { + fn new(parent: &'a BlockDefinitions<'a>) -> Self { + Self { + state: Some(BlockDefinitionsState { + rc_definitions: RcDefinitions::default(), + parent, + cache: Default::default(), + }), + } + } + fn none() -> Self { + Self { state: None } + } + fn get_or_write_definition( + &mut self, + key: K, + field: impl Fn(&BlockDefinitionsCache) -> &RefCell>, + write_definition: impl FnOnce(BlockDefinitionsWriter<'_, '_>, &K) -> Result, + ) -> Result { + let state = self.state.as_ref().expect("should be some"); + let mut cur_state = state; + loop { + let field = field(&cur_state.cache).borrow(); + if let Some(retval) = field.get(&key) { + return Ok(retval.clone()); + } + let Some(parent_state) = &cur_state.parent.state else { + break; + }; + cur_state = parent_state; + } + let retval = write_definition(BlockDefinitionsWriter { definitions: self }, &key)?; + Ok(field(&self.state.as_ref().expect("should be some").cache) + .borrow_mut() + .entry(key) + .or_insert(retval) + .clone()) + } + fn write_out(&mut self, indent: Indent<'_>, out: &mut String) { + self.state + .as_ref() + .expect("should be some") + .rc_definitions + .write_and_clear(indent, out); + } +} + +struct BlockDefinitionsWriter<'a, 'b> { + definitions: &'b mut BlockDefinitions<'a>, +} + +impl BlockDefinitionsWriter<'_, '_> { + fn add_definition_line(&mut self, v: impl fmt::Display) { + self.definitions + .state + .as_ref() + .expect("should be some") + .rc_definitions + .add_definition_line(v); + } +} + +impl<'a> std::ops::Deref for BlockDefinitionsWriter<'a, '_> { + type Target = BlockDefinitions<'a>; + + fn deref(&self) -> &Self::Target { + &self.definitions + } +} + +impl std::ops::DerefMut for BlockDefinitionsWriter<'_, '_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.definitions + } +} + struct EnumDef { variants: RefCell, body: String, @@ -498,16 +593,13 @@ impl TypeState { struct ModuleState { ns: Namespace, - definitions: RcDefinitions, match_arm_values: HashMap, Ident>, } impl Default for ModuleState { fn default() -> Self { - let definitions = RcDefinitions::default(); Self { ns: Default::default(), - definitions, match_arm_values: Default::default(), } } @@ -876,7 +968,7 @@ impl<'a> Exporter<'a> { &mut self, value: Expr, to_ty: ToTy, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { let from_ty = value.ty(); @@ -911,7 +1003,7 @@ impl<'a> Exporter<'a> { &mut self, firrtl_cast_fn: Option<&str>, value: Expr, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { let value = self.expr(Expr::canonical(value), definitions, const_ty)?; @@ -925,7 +1017,7 @@ impl<'a> Exporter<'a> { &mut self, base: Expr, range: Range, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { let base_width = base.ty().width(); @@ -943,73 +1035,96 @@ impl<'a> Exporter<'a> { fn array_literal_expr( &mut self, expr: ops::ArrayLiteral, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { - let ident = self.module.ns.make_new("_array_literal_expr"); - let ty_str = self.type_state.ty(expr.ty())?; - let const_ = if const_ty { "const " } else { "" }; - definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_str}")); - for (index, element) in expr.element_values().into_iter().enumerate() { - let element = self.expr(Expr::canonical(element), definitions, const_ty)?; - definitions.add_definition_line(format_args!("connect {ident}[{index}], {element}")); - } - if expr.element_values().is_empty() { - definitions.add_definition_line(format_args!("invalidate {ident}")); - } - Ok(ident.to_string()) + definitions.get_or_write_definition( + (expr, const_ty), + |c| &c.array_literal_exprs, + |mut definitions, &(expr, const_ty)| { + let ident = self.module.ns.make_new("_array_literal_expr"); + let ty_str = self.type_state.ty(expr.ty())?; + let const_ = if const_ty { "const " } else { "" }; + definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_str}")); + for (index, element) in expr.element_values().into_iter().enumerate() { + let element = + self.expr(Expr::canonical(element), &mut definitions, const_ty)?; + definitions + .add_definition_line(format_args!("connect {ident}[{index}], {element}")); + } + if expr.element_values().is_empty() { + definitions.add_definition_line(format_args!("invalidate {ident}")); + } + Ok(ident.to_string()) + }, + ) } fn bundle_literal_expr( &mut self, expr: ops::BundleLiteral, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { - let ident = self.module.ns.make_new("_bundle_literal_expr"); - let ty = expr.ty(); - let (ty_ident, bundle_ns) = self.type_state.bundle_def(ty)?; - let const_ = if const_ty { "const " } else { "" }; - definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_ident}")); - for ( - field_value, - BundleField { - name, - flipped, - ty: _, + definitions.get_or_write_definition( + (expr, const_ty), + |c| &c.bundle_literal_exprs, + |mut definitions, &(expr, const_ty)| { + let ident = self.module.ns.make_new("_bundle_literal_expr"); + let ty = expr.ty(); + let (ty_ident, bundle_ns) = self.type_state.bundle_def(ty)?; + let const_ = if const_ty { "const " } else { "" }; + definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_ident}")); + for ( + field_value, + BundleField { + name, + flipped, + ty: _, + }, + ) in expr.field_values().into_iter().zip(ty.fields()) + { + debug_assert!( + !flipped, + "can't have bundle literal with flipped field -- \ + this should have been caught in BundleLiteral::new_unchecked" + ); + let name = bundle_ns.borrow_mut().get(name); + let field_value = + self.expr(Expr::canonical(field_value), &mut definitions, const_ty)?; + definitions + .add_definition_line(format_args!("connect {ident}.{name}, {field_value}")); + } + if ty.fields().is_empty() { + definitions.add_definition_line(format_args!("invalidate {ident}")); + } + Ok(ident.to_string()) }, - ) in expr.field_values().into_iter().zip(ty.fields()) - { - debug_assert!( - !flipped, - "can't have bundle literal with flipped field -- this should have been caught in BundleLiteral::new_unchecked" - ); - let name = bundle_ns.borrow_mut().get(name); - let field_value = self.expr(Expr::canonical(field_value), definitions, const_ty)?; - definitions.add_definition_line(format_args!("connect {ident}.{name}, {field_value}")); - } - if ty.fields().is_empty() { - definitions.add_definition_line(format_args!("invalidate {ident}")); - } - Ok(ident.to_string()) + ) } fn uninit_expr( &mut self, expr: ops::Uninit, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { - let ident = self.module.ns.make_new("_uninit_expr"); - let ty = expr.ty(); - let ty_ident = self.type_state.ty(ty)?; - let const_ = if const_ty { "const " } else { "" }; - definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_ident}")); - definitions.add_definition_line(format_args!("invalidate {ident}")); - Ok(ident.to_string()) + definitions.get_or_write_definition( + (expr, const_ty), + |c| &c.uninit_exprs, + |mut definitions, &(expr, const_ty)| { + let ident = self.module.ns.make_new("_uninit_expr"); + let ty = expr.ty(); + let ty_ident = self.type_state.ty(ty)?; + let const_ = if const_ty { "const " } else { "" }; + definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_ident}")); + definitions.add_definition_line(format_args!("invalidate {ident}")); + Ok(ident.to_string()) + }, + ) } fn enum_literal_expr( &mut self, expr: ops::EnumLiteral, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { let variant_expr = expr @@ -1022,175 +1137,198 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Bundle, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { - if ty.fields().is_empty() { - return Ok("UInt<0>(0)".into()); - } - if let [field] = *ty.fields() { - let field_ident = self.type_state.get_bundle_field(ty, field.name)?; - return self.expr_cast_to_bits( - format!("{value_str}.{field_ident}"), - field.ty, - definitions, - extra_indent, - ); - } - let flattened_bundle_ty = Bundle::new(Interned::from_iter(ty.fields().iter().map( - |&BundleField { - name, - flipped: _, - ty: field_ty, - }| BundleField { - name, - flipped: false, - ty: UInt[field_ty.bit_width()].canonical(), + definitions.get_or_write_definition( + (value_str, ty), + |c| &c.cast_bundle_to_bits_exprs, + |mut definitions, &(ref value_str, ty)| { + if ty.fields().is_empty() { + return Ok("UInt<0>(0)".into()); + } + if let [field] = *ty.fields() { + let field_ident = self.type_state.get_bundle_field(ty, field.name)?; + return self.expr_cast_to_bits( + format!("{value_str}.{field_ident}"), + field.ty, + &mut definitions, + extra_indent, + ); + } + let flattened_bundle_ty = Bundle::new(Interned::from_iter(ty.fields().iter().map( + |&BundleField { + name, + flipped: _, + ty: field_ty, + }| BundleField { + name, + flipped: false, + ty: UInt[field_ty.bit_width()].canonical(), + }, + ))); + let (flattened_ty_ident, _) = self.type_state.bundle_def(flattened_bundle_ty)?; + let ident = self.module.ns.make_new("_cast_bundle_to_bits_expr"); + definitions.add_definition_line(format_args!( + "{extra_indent}wire {ident}: {flattened_ty_ident}" + )); + let mut cat_expr = None; + for field in ty.fields() { + let field_ident = self.type_state.get_bundle_field(ty, field.name)?; + let flattened_field_ident = self + .type_state + .get_bundle_field(flattened_bundle_ty, field.name)?; + let field_bits = self.expr_cast_to_bits( + format!("{value_str}.{field_ident}"), + field.ty, + &mut definitions, + extra_indent, + )?; + definitions.add_definition_line(format_args!( + "{extra_indent}connect {ident}.{flattened_field_ident}, {field_bits}" + )); + cat_expr = Some(if let Some(cat_expr) = cat_expr { + format!("cat({ident}.{flattened_field_ident}, {cat_expr})") + } else { + format!("{ident}.{flattened_field_ident}") + }); + } + let retval = self.module.ns.make_new("_cast_to_bits_expr"); + definitions.add_definition_line(format_args!( + "{extra_indent}wire {retval}: UInt<{}>", + ty.type_properties().bit_width + )); + let cat_expr = cat_expr.expect("bundle already checked to have fields"); + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, {cat_expr}" + )); + Ok(retval.to_string()) }, - ))); - let (flattened_ty_ident, _) = self.type_state.bundle_def(flattened_bundle_ty)?; - let ident = self.module.ns.make_new("_cast_bundle_to_bits_expr"); - definitions.add_definition_line(format_args!( - "{extra_indent}wire {ident}: {flattened_ty_ident}" - )); - let mut cat_expr = None; - for field in ty.fields() { - let field_ident = self.type_state.get_bundle_field(ty, field.name)?; - let flattened_field_ident = self - .type_state - .get_bundle_field(flattened_bundle_ty, field.name)?; - let field_bits = self.expr_cast_to_bits( - format!("{value_str}.{field_ident}"), - field.ty, - definitions, - extra_indent, - )?; - definitions.add_definition_line(format_args!( - "{extra_indent}connect {ident}.{flattened_field_ident}, {field_bits}" - )); - cat_expr = Some(if let Some(cat_expr) = cat_expr { - format!("cat({ident}.{flattened_field_ident}, {cat_expr})") - } else { - format!("{ident}.{flattened_field_ident}") - }); - } - let retval = self.module.ns.make_new("_cast_to_bits_expr"); - definitions.add_definition_line(format_args!( - "{extra_indent}wire {retval}: UInt<{}>", - ty.type_properties().bit_width - )); - let cat_expr = cat_expr.expect("bundle already checked to have fields"); - definitions.add_definition_line(format_args!("{extra_indent}connect {retval}, {cat_expr}")); - Ok(retval.to_string()) + ) } fn expr_cast_enum_to_bits( &mut self, value_str: String, ty: Enum, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { - if ty.variants().is_empty() { - return Ok("UInt<0>(0)".into()); - } - let retval = self.module.ns.make_new("_cast_enum_to_bits_expr"); - definitions.add_definition_line(format_args!( - "{extra_indent}wire {retval}: UInt<{}>", - ty.type_properties().bit_width - )); - definitions.add_definition_line(format_args!("{extra_indent}match {value_str}:")); - let _match_arms_indent = extra_indent.push(); - for (variant_index, variant) in ty.variants().into_iter().enumerate() { - if let Some(variant_ty) = variant.ty { - let variant_value = self - .module - .ns - .make_new(&format!("_cast_enum_to_bits_expr_{}", variant.name)); + definitions.get_or_write_definition( + (value_str, ty), + |c| &c.cast_enum_to_bits_exprs, + |mut definitions, &(ref value_str, ty)| { + if ty.variants().is_empty() { + return Ok("UInt<0>(0)".into()); + } + let retval = self.module.ns.make_new("_cast_enum_to_bits_expr"); definitions.add_definition_line(format_args!( - "{extra_indent}{}({variant_value}):", - self.type_state.get_enum_variant(ty, variant.name)?, + "{extra_indent}wire {retval}: UInt<{}>", + ty.type_properties().bit_width )); - let _match_arm_indent = extra_indent.push(); - let variant_bits = self.expr_cast_to_bits( - variant_value.to_string(), - variant_ty, - definitions, - extra_indent, - )?; - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}, pad(cat({variant_bits}, UInt<{}>({variant_index})), {})", - ty.discriminant_bit_width(), - ty.type_properties().bit_width, - )); - } else { - definitions.add_definition_line(format_args!( - "{extra_indent}{}:", - self.type_state.get_enum_variant(ty, variant.name)?, - )); - let _match_arm_indent = extra_indent.push(); - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}, UInt<{}>({variant_index})", - ty.type_properties().bit_width, - )); - } - } - Ok(retval.to_string()) + definitions.add_definition_line(format_args!("{extra_indent}match {value_str}:")); + let _match_arms_indent = extra_indent.push(); + for (variant_index, variant) in ty.variants().into_iter().enumerate() { + if let Some(variant_ty) = variant.ty { + let variant_value = self + .module + .ns + .make_new(&format!("_cast_enum_to_bits_expr_{}", variant.name)); + definitions.add_definition_line(format_args!( + "{extra_indent}{}({variant_value}):", + self.type_state.get_enum_variant(ty, variant.name)?, + )); + let _match_arm_indent = extra_indent.push(); + let variant_bits = self.expr_cast_to_bits( + variant_value.to_string(), + variant_ty, + &mut definitions, + extra_indent, + )?; + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, \ + pad(cat({variant_bits}, UInt<{}>({variant_index})), {})", + ty.discriminant_bit_width(), + ty.type_properties().bit_width, + )); + } else { + definitions.add_definition_line(format_args!( + "{extra_indent}{}:", + self.type_state.get_enum_variant(ty, variant.name)?, + )); + let _match_arm_indent = extra_indent.push(); + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, UInt<{}>({variant_index})", + ty.type_properties().bit_width, + )); + } + } + Ok(retval.to_string()) + }, + ) } fn expr_cast_array_to_bits( &mut self, value_str: String, ty: Array, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { - if ty.is_empty() { - return Ok("UInt<0>(0)".into()); - } - if ty.len() == 1 { - return self.expr_cast_to_bits( - value_str + "[0]", - ty.element(), - definitions, - extra_indent, - ); - } - let element_width = ty.element().bit_width(); - let ident = self.module.ns.make_new("_cast_array_to_bits_expr"); - definitions.add_definition_line(format_args!( - "{extra_indent}wire {ident}: UInt<{element_width}>[{}]", - ty.len(), - )); - let mut cat_expr = None; - for index in 0..ty.len() { - let element_bits = self.expr_cast_to_bits( - format!("{value_str}[{index}]"), - ty.element(), - definitions, - extra_indent, - )?; - definitions.add_definition_line(format_args!( - "{extra_indent}connect {ident}[{index}], {element_bits}" - )); - cat_expr = Some(if let Some(cat_expr) = cat_expr { - format!("cat({ident}[{index}], {cat_expr})") - } else { - format!("{ident}[{index}]") - }); - } - let retval = self.module.ns.make_new("_cast_to_bits_expr"); - definitions.add_definition_line(format_args!( - "{extra_indent}wire {retval}: UInt<{}>", - ty.type_properties().bit_width - )); - let cat_expr = cat_expr.expect("array already checked to have elements"); - definitions.add_definition_line(format_args!("{extra_indent}connect {retval}, {cat_expr}")); - Ok(retval.to_string()) + definitions.get_or_write_definition( + (value_str, ty), + |c| &c.cast_array_to_bits_exprs, + |mut definitions, &(ref value_str, ty)| { + if ty.is_empty() { + return Ok("UInt<0>(0)".into()); + } + if ty.len() == 1 { + return self.expr_cast_to_bits( + value_str.clone() + "[0]", + ty.element(), + &mut definitions, + extra_indent, + ); + } + let element_width = ty.element().bit_width(); + let ident = self.module.ns.make_new("_cast_array_to_bits_expr"); + definitions.add_definition_line(format_args!( + "{extra_indent}wire {ident}: UInt<{element_width}>[{}]", + ty.len(), + )); + let mut cat_expr = None; + for index in 0..ty.len() { + let element_bits = self.expr_cast_to_bits( + format!("{value_str}[{index}]"), + ty.element(), + &mut definitions, + extra_indent, + )?; + definitions.add_definition_line(format_args!( + "{extra_indent}connect {ident}[{index}], {element_bits}" + )); + cat_expr = Some(if let Some(cat_expr) = cat_expr { + format!("cat({ident}[{index}], {cat_expr})") + } else { + format!("{ident}[{index}]") + }); + } + let retval = self.module.ns.make_new("_cast_to_bits_expr"); + definitions.add_definition_line(format_args!( + "{extra_indent}wire {retval}: UInt<{}>", + ty.type_properties().bit_width + )); + let cat_expr = cat_expr.expect("array already checked to have elements"); + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, {cat_expr}" + )); + Ok(retval.to_string()) + }, + ) } fn expr_cast_to_bits( &mut self, value_str: String, ty: CanonicalType, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { match ty.unwrap_transparent_types() { @@ -1219,195 +1357,230 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Bundle, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { - let (ty_ident, _) = self.type_state.bundle_def(ty)?; - let retval = self.module.ns.make_new("_cast_bits_to_bundle_expr"); - definitions.add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}")); - if ty.fields().is_empty() { - definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}")); - return Ok(retval.to_string()); - } - let flattened_bundle_ty = Bundle::new(Interned::from_iter(ty.fields().iter().map( - |&BundleField { - name, - flipped: _, - ty: field_ty, - }| BundleField { - name, - flipped: false, - ty: UInt[field_ty.bit_width()].canonical(), - }, - ))); - let (flattened_ty_ident, _) = self.type_state.bundle_def(flattened_bundle_ty)?; - let flattened_ident = self - .module - .ns - .make_new("_cast_bits_to_bundle_expr_flattened"); - definitions.add_definition_line(format_args!( - "{extra_indent}wire {flattened_ident}: {flattened_ty_ident}" - )); - for ( - field, - OpaqueSimValueSize { - bit_width: field_offset, - sim_only_values_len: _, - }, - ) in ty.fields().into_iter().zip(ty.field_offsets()) - { - let flattened_field_ident = self - .type_state - .get_bundle_field(flattened_bundle_ty, field.name)?; - let field_ident = self.type_state.get_bundle_field(ty, field.name)?; - if let Some(field_bit_width_minus_one) = field.ty.bit_width().checked_sub(1usize) { + definitions.get_or_write_definition( + (value_str, ty), + |c| &c.cast_bits_to_bundle_exprs, + |mut definitions, &(ref value_str, ty)| { + let (ty_ident, _) = self.type_state.bundle_def(ty)?; + let retval = self.module.ns.make_new("_cast_bits_to_bundle_expr"); + definitions + .add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}")); + if ty.fields().is_empty() { + definitions + .add_definition_line(format_args!("{extra_indent}invalidate {retval}")); + return Ok(retval.to_string()); + } + let flattened_bundle_ty = Bundle::new(Interned::from_iter(ty.fields().iter().map( + |&BundleField { + name, + flipped: _, + ty: field_ty, + }| BundleField { + name, + flipped: false, + ty: UInt[field_ty.bit_width()].canonical(), + }, + ))); + let (flattened_ty_ident, _) = self.type_state.bundle_def(flattened_bundle_ty)?; + let flattened_ident = self + .module + .ns + .make_new("_cast_bits_to_bundle_expr_flattened"); definitions.add_definition_line(format_args!( - "{extra_indent}connect {flattened_ident}.{flattened_field_ident}, bits({value_str}, {}, {field_offset})", - field_offset + field_bit_width_minus_one + "{extra_indent}wire {flattened_ident}: {flattened_ty_ident}" )); - } else { - definitions.add_definition_line(format_args!( + for ( + field, + OpaqueSimValueSize { + bit_width: field_offset, + sim_only_values_len: _, + }, + ) in ty.fields().into_iter().zip(ty.field_offsets()) + { + let flattened_field_ident = self + .type_state + .get_bundle_field(flattened_bundle_ty, field.name)?; + let field_ident = self.type_state.get_bundle_field(ty, field.name)?; + if let Some(field_bit_width_minus_one) = + field.ty.bit_width().checked_sub(1usize) + { + definitions.add_definition_line(format_args!( + "{extra_indent}connect {flattened_ident}.{flattened_field_ident}, \ + bits({value_str}, {}, {field_offset})", + field_offset + field_bit_width_minus_one + )); + } else { + definitions.add_definition_line(format_args!( "{extra_indent}connect {flattened_ident}.{flattened_field_ident}, UInt<0>(0)" )); - } - let field_value = self.expr_cast_bits_to( - format!("{flattened_ident}.{flattened_field_ident}"), - field.ty, - definitions, - extra_indent, - )?; - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}.{field_ident}, {field_value}" - )); - } - Ok(retval.to_string()) + } + let field_value = self.expr_cast_bits_to( + format!("{flattened_ident}.{flattened_field_ident}"), + field.ty, + &mut definitions, + extra_indent, + )?; + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}.{field_ident}, {field_value}" + )); + } + Ok(retval.to_string()) + }, + ) } fn expr_cast_bits_to_enum( &mut self, value_str: String, ty: Enum, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { - let (ty_ident, enum_def) = self.type_state.enum_def(ty)?; - let retval = self.module.ns.make_new("_cast_bits_to_enum_expr"); - definitions.add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}")); - if ty.variants().is_empty() { - definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}")); - return Ok(retval.to_string()); - } - if let [variant] = *ty.variants() { - let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?; - if let Some(variant_ty) = variant.ty { - let variant_value = - self.expr_cast_bits_to(value_str, variant_ty, definitions, extra_indent)?; - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}, {}({enum_variant}, {variant_value})", - enum_def.body - )); - } else { - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}, {}({enum_variant})", - enum_def.body - )); - } - return Ok(retval.to_string()); - } - let discriminant_bit_width = ty.discriminant_bit_width(); - let body_bit_width = ty.type_properties().bit_width - discriminant_bit_width; - let body_ident = self.module.ns.make_new("_cast_bits_to_enum_expr_body"); - let body_value = if body_bit_width != 0 { - definitions.add_definition_line(format_args!( - "{extra_indent}wire {body_ident}: UInt<{body_bit_width}>" - )); - definitions.add_definition_line(format_args!( - "{extra_indent}connect {body_ident}, head({value_str}, {body_bit_width})" - )); - body_ident.to_string() - } else { - "UInt<0>(0)".into() - }; - for (variant_index, variant) in ty.variants().into_iter().enumerate() { - let when_cond = format!( - "eq(UInt<{discriminant_bit_width}>({variant_index}), tail({value_str}, {body_bit_width}))" - ); - if variant_index == ty.variants().len() - 1 { - definitions.add_definition_line(format_args!("{extra_indent}else:")); - } else if variant_index == 0 { - definitions.add_definition_line(format_args!("{extra_indent}when {when_cond}:")); - } else { + definitions.get_or_write_definition( + (value_str, ty), + |c| &c.cast_bits_to_enum_exprs, + |mut definitions, &(ref value_str, ty)| { + let (ty_ident, enum_def) = self.type_state.enum_def(ty)?; + let retval = self.module.ns.make_new("_cast_bits_to_enum_expr"); definitions - .add_definition_line(format_args!("{extra_indent}else when {when_cond}:")); - } - let when_pushed_indent = extra_indent.push(); - let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?; - if let Some(variant_ty) = variant.ty { - let variant_value = self.expr_cast_bits_to( - body_value.clone(), - variant_ty, - definitions, - extra_indent, - )?; - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}, {}({enum_variant}, {variant_value})", - enum_def.body - )); - } else { - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}, {}({enum_variant})", - enum_def.body - )); - } - drop(when_pushed_indent); - } - Ok(retval.to_string()) + .add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}")); + if ty.variants().is_empty() { + definitions + .add_definition_line(format_args!("{extra_indent}invalidate {retval}")); + return Ok(retval.to_string()); + } + if let [variant] = *ty.variants() { + let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?; + if let Some(variant_ty) = variant.ty { + let variant_value = self.expr_cast_bits_to( + value_str.clone(), + variant_ty, + &mut definitions, + extra_indent, + )?; + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, {}({enum_variant}, {variant_value})", + enum_def.body + )); + } else { + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, {}({enum_variant})", + enum_def.body + )); + } + return Ok(retval.to_string()); + } + let discriminant_bit_width = ty.discriminant_bit_width(); + let body_bit_width = ty.type_properties().bit_width - discriminant_bit_width; + let body_ident = self.module.ns.make_new("_cast_bits_to_enum_expr_body"); + let body_value = if body_bit_width != 0 { + definitions.add_definition_line(format_args!( + "{extra_indent}wire {body_ident}: UInt<{body_bit_width}>" + )); + definitions.add_definition_line(format_args!( + "{extra_indent}connect {body_ident}, head({value_str}, {body_bit_width})" + )); + body_ident.to_string() + } else { + "UInt<0>(0)".into() + }; + for (variant_index, variant) in ty.variants().into_iter().enumerate() { + let when_cond = format!( + "eq(UInt<{discriminant_bit_width}>({variant_index}), \ + tail({value_str}, {body_bit_width}))" + ); + if variant_index == ty.variants().len() - 1 { + definitions.add_definition_line(format_args!("{extra_indent}else:")); + } else if variant_index == 0 { + definitions + .add_definition_line(format_args!("{extra_indent}when {when_cond}:")); + } else { + definitions.add_definition_line(format_args!( + "{extra_indent}else when {when_cond}:" + )); + } + let when_pushed_indent = extra_indent.push(); + let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?; + if let Some(variant_ty) = variant.ty { + let variant_value = self.expr_cast_bits_to( + body_value.clone(), + variant_ty, + &mut definitions, + extra_indent, + )?; + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, {}({enum_variant}, {variant_value})", + enum_def.body + )); + } else { + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}, {}({enum_variant})", + enum_def.body + )); + } + drop(when_pushed_indent); + } + Ok(retval.to_string()) + }, + ) } fn expr_cast_bits_to_array( &mut self, value_str: String, ty: Array, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { - let retval = self.module.ns.make_new("_cast_bits_to_array_expr"); - let array_ty = self.type_state.ty(ty)?; - definitions.add_definition_line(format_args!("{extra_indent}wire {retval}: {array_ty}")); - let element_bit_width = ty.element().bit_width(); - if ty.is_empty() || element_bit_width == 0 { - definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}")); - return Ok(retval.to_string()); - } - let flattened_ident = self - .module - .ns - .make_new("_cast_bits_to_array_expr_flattened"); - definitions.add_definition_line(format_args!( - "{extra_indent}wire {flattened_ident}: UInt<{element_bit_width}>[{}]", - ty.len(), - )); - for index in 0..ty.len() { - definitions.add_definition_line(format_args!( - "{extra_indent}connect {flattened_ident}[{index}], bits({value_str}, {}, {})", - element_bit_width * index + element_bit_width - 1, - element_bit_width * index, - )); - let element_value = self.expr_cast_bits_to( - format!("{flattened_ident}[{index}]"), - ty.element(), - definitions, - extra_indent, - )?; - definitions.add_definition_line(format_args!( - "{extra_indent}connect {retval}[{index}], {element_value}" - )); - } - Ok(retval.to_string()) + definitions.get_or_write_definition( + (value_str, ty), + |c| &c.cast_bits_to_array_exprs, + |mut definitions, &(ref value_str, ty)| { + let retval = self.module.ns.make_new("_cast_bits_to_array_expr"); + let array_ty = self.type_state.ty(ty)?; + definitions + .add_definition_line(format_args!("{extra_indent}wire {retval}: {array_ty}")); + let element_bit_width = ty.element().bit_width(); + if ty.is_empty() || element_bit_width == 0 { + definitions + .add_definition_line(format_args!("{extra_indent}invalidate {retval}")); + return Ok(retval.to_string()); + } + let flattened_ident = self + .module + .ns + .make_new("_cast_bits_to_array_expr_flattened"); + definitions.add_definition_line(format_args!( + "{extra_indent}wire {flattened_ident}: UInt<{element_bit_width}>[{}]", + ty.len(), + )); + for index in 0..ty.len() { + definitions.add_definition_line(format_args!( + "{extra_indent}connect {flattened_ident}[{index}], \ + bits({value_str}, {}, {})", + element_bit_width * index + element_bit_width - 1, + element_bit_width * index, + )); + let element_value = self.expr_cast_bits_to( + format!("{flattened_ident}[{index}]"), + ty.element(), + &mut definitions, + extra_indent, + )?; + definitions.add_definition_line(format_args!( + "{extra_indent}connect {retval}[{index}], {element_value}" + )); + } + Ok(retval.to_string()) + }, + ) } fn expr_cast_bits_to( &mut self, value_str: String, ty: CanonicalType, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { match ty.unwrap_transparent_types() { @@ -1427,12 +1600,18 @@ impl<'a> Exporter<'a> { CanonicalType::AsyncReset(_) => Ok(format!("asAsyncReset({value_str})")), CanonicalType::SyncReset(_) => Ok(value_str), CanonicalType::Reset(_) => unreachable!("Reset is not bit castable to"), - CanonicalType::PhantomConst(_) => { - let retval = self.module.ns.make_new("_cast_bits_to_phantom_const_expr"); - definitions.add_definition_line(format_args!("{extra_indent}wire {retval}: {{}}")); - definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}")); - return Ok(retval.to_string()); - } + CanonicalType::PhantomConst(ty) => definitions.get_or_write_definition( + (value_str, ty), + |c| &c.cast_bits_to_phantom_const_exprs, + |mut definitions, &(ref _value_str, _ty)| { + let retval = self.module.ns.make_new("_cast_bits_to_phantom_const_expr"); + definitions + .add_definition_line(format_args!("{extra_indent}wire {retval}: {{}}")); + definitions + .add_definition_line(format_args!("{extra_indent}invalidate {retval}")); + Ok(retval.to_string()) + }, + ), CanonicalType::DynSimOnly(_) => Err(FirrtlError::SimOnlyValuesAreNotPermitted.into()), CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"), } @@ -1441,7 +1620,7 @@ impl<'a> Exporter<'a> { &mut self, func: &str, arg: Expr, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { Ok(format!( @@ -1454,7 +1633,7 @@ impl<'a> Exporter<'a> { func: &str, lhs: Expr, rhs: Expr, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { Ok(format!( @@ -1466,7 +1645,7 @@ impl<'a> Exporter<'a> { fn expr( &mut self, expr: Expr, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, const_ty: bool, ) -> Result { match *Expr::expr_enum(expr) { @@ -2062,7 +2241,7 @@ impl<'a> Exporter<'a> { &mut self, stmt_reg: StmtReg, module_name: Ident, - definitions: &RcDefinitions, + definitions: &mut BlockDefinitions<'_>, body: &mut String, ) -> Result<()> { let StmtReg { annotations, reg } = stmt_reg; @@ -2095,10 +2274,10 @@ impl<'a> Exporter<'a> { module: Interned>, block: Block, _block_indent: &PushIndent<'_>, - definitions: Option, + parent_definitions: &BlockDefinitions, ) -> Result { let indent = self.indent; - let definitions = definitions.unwrap_or_default(); + let mut definitions = BlockDefinitions::new(parent_definitions); let mut body = String::new(); let mut out = String::new(); let Block { memories, stmts } = block; @@ -2122,8 +2301,8 @@ impl<'a> Exporter<'a> { ) .unwrap(); } - let lhs = self.expr(lhs, &definitions, false)?; - let rhs = self.expr(rhs, &definitions, false)?; + let lhs = self.expr(lhs, &mut definitions, false)?; + let rhs = self.expr(rhs, &mut definitions, false)?; writeln!( body, "{indent}connect {lhs}, {rhs}{}", @@ -2139,9 +2318,9 @@ impl<'a> Exporter<'a> { text, source_location, }) => { - let clk = self.expr(Expr::canonical(clk), &definitions, false)?; - let pred = self.expr(Expr::canonical(pred), &definitions, false)?; - let en = self.expr(Expr::canonical(en), &definitions, false)?; + let clk = self.expr(Expr::canonical(clk), &mut definitions, false)?; + let pred = self.expr(Expr::canonical(pred), &mut definitions, false)?; + let en = self.expr(Expr::canonical(en), &mut definitions, false)?; let kind = match kind { FormalKind::Assert => "assert", FormalKind::Assume => "assume", @@ -2166,7 +2345,7 @@ impl<'a> Exporter<'a> { let mut when = "when"; let mut pushed_indent; loop { - let cond_str = self.expr(Expr::canonical(cond), &definitions, false)?; + let cond_str = self.expr(Expr::canonical(cond), &mut definitions, false)?; writeln!( body, "{indent}{when} {cond_str}:{}", @@ -2175,7 +2354,7 @@ impl<'a> Exporter<'a> { .unwrap(); pushed_indent = indent.push(); let then_block_str = - self.block(module, then_block, &pushed_indent, None)?; + self.block(module, then_block, &pushed_indent, &definitions)?; if !then_block_str.is_empty() { body.push_str(&then_block_str); } else { @@ -2193,7 +2372,8 @@ impl<'a> Exporter<'a> { break; } } - let else_block = self.block(module, else_block, &pushed_indent, None)?; + let else_block = + self.block(module, else_block, &pushed_indent, &definitions)?; drop(pushed_indent); if !else_block.is_empty() { writeln!(body, "{indent}else:").unwrap(); @@ -2208,7 +2388,7 @@ impl<'a> Exporter<'a> { writeln!( body, "{indent}match {}:{}", - self.expr(Expr::canonical(expr), &definitions, false)?, + self.expr(Expr::canonical(expr), &mut definitions, false)?, FileInfo::new(source_location), ) .unwrap(); @@ -2236,7 +2416,8 @@ impl<'a> Exporter<'a> { }; body.push_str(":\n"); let match_arm_indent = indent.push(); - let block = self.block(module, match_arm_block, &match_arm_indent, None)?; + let block = + self.block(module, match_arm_block, &match_arm_indent, &definitions)?; if !block.is_empty() { body.push_str(&block); } else { @@ -2261,13 +2442,13 @@ impl<'a> Exporter<'a> { .unwrap(); } Stmt::Declaration(StmtDeclaration::Reg(stmt_reg)) => { - self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?; + self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?; } Stmt::Declaration(StmtDeclaration::RegSync(stmt_reg)) => { - self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?; + self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?; } Stmt::Declaration(StmtDeclaration::RegAsync(stmt_reg)) => { - self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?; + self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?; } Stmt::Declaration(StmtDeclaration::Instance(StmtInstance { annotations, @@ -2286,7 +2467,7 @@ impl<'a> Exporter<'a> { .unwrap(); } } - definitions.write_and_clear(indent, &mut out); + definitions.write_out(indent, &mut out); out.push_str(&body); body.clear(); } @@ -2366,7 +2547,7 @@ impl<'a> Exporter<'a> { module, top_block, &module_indent, - Some(self.module.definitions.clone()), + &BlockDefinitions::none(), )?); "module" } diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index 9dc0107..5c62933 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -808,40 +808,8 @@ circuit check_enum_cmp_eq: connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2) connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) - wire _cast_bits_to_array_expr_2: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] - connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] - connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] - wire _cast_bits_to_array_expr_3: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] - connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] - connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] - connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) - wire _cast_bits_to_array_expr_4: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] - connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] - connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] - wire _cast_bits_to_array_expr_5: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] - connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] - connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] - connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1]) + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[2]) wire _cast_array_to_bits_expr: UInt<1>[3] connect _cast_array_to_bits_expr[0], _array_literal_expr[0] connect _cast_array_to_bits_expr[1], _array_literal_expr[1] @@ -901,40 +869,8 @@ circuit check_enum_cmp_eq: connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2) connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) - wire _cast_bits_to_array_expr_2: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] - connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] - connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] - wire _cast_bits_to_array_expr_3: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] - connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] - connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] - connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) - wire _cast_bits_to_array_expr_4: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] - connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] - connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] - wire _cast_bits_to_array_expr_5: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0) - connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] - connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1) - connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] - connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2) - connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] - connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1]) + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[2]) wire _cast_array_to_bits_expr: UInt<1>[3] connect _cast_array_to_bits_expr[0], _array_literal_expr[0] connect _cast_array_to_bits_expr[1], _array_literal_expr[1] @@ -993,40 +929,8 @@ circuit check_enum_cmp_eq: connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) - wire _cast_bits_to_array_expr_2: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) - connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] - connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) - connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] - connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) - connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] - wire _cast_bits_to_array_expr_3: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) - connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] - connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) - connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] - connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) - connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] - connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) - wire _cast_bits_to_array_expr_4: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) - connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] - connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) - connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] - connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) - connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] - wire _cast_bits_to_array_expr_5: UInt<1>[3] - wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] - connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) - connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] - connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) - connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] - connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) - connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] - connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1]) + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[2]) wire _cast_array_to_bits_expr: UInt<1>[3] connect _cast_array_to_bits_expr[0], _array_literal_expr[0] connect _cast_array_to_bits_expr[1], _array_literal_expr[1] @@ -3925,21 +3829,10 @@ circuit check_enum_connect_any: connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1] HdlSome: wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1] - wire _cast_bits_to_bundle_expr_1: Ty5 - wire _cast_bits_to_bundle_expr_flattened_1: Ty6 - connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 2, 0), 0, 0) - wire _cast_bits_to_enum_expr_1: Ty3 - when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_1.tag, 0)): - connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlNone) - else: - connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlSome) - connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_enum_expr_1 - connect _cast_bits_to_bundle_expr_flattened_1.body, bits(bits(i2.body, 2, 0), 2, 1) - connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body ; connect different types: ; lhs: SInt<1> ; rhs: SInt<2> - connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr_1.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1] + connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1] wire _bundle_literal_expr_2: Ty4 connect _bundle_literal_expr_2.tag, {|HdlNone, HdlSome|}(HdlSome) connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2) @@ -3961,18 +3854,18 @@ circuit check_enum_connect_any: connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1] C: wire __connect_variant_body_3: Ty8 @[module-XXXXXXXXXX.rs 8:1] - wire _cast_bits_to_bundle_expr_2: Ty8 - wire _cast_bits_to_bundle_expr_flattened_2: Ty9 - connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i2.body, 0, 0), 0, 0) - wire _cast_bits_to_enum_expr_2: Ty3 - when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_2.tag, 0)): - connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlNone) + wire _cast_bits_to_bundle_expr_1: Ty8 + wire _cast_bits_to_bundle_expr_flattened_1: Ty9 + connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 0, 0), 0, 0) + wire _cast_bits_to_enum_expr_1: Ty3 + when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_1.tag, 0)): + connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlNone) else: - connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlSome) - connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_enum_expr_2 - connect _cast_bits_to_bundle_expr_flattened_2.body, UInt<0>(0) - connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body - connect __connect_variant_body_3, _cast_bits_to_bundle_expr_2 @[module-XXXXXXXXXX.rs 8:1] + connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlSome) + connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_enum_expr_1 + connect _cast_bits_to_bundle_expr_flattened_1.body, UInt<0>(0) + connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body + connect __connect_variant_body_3, _cast_bits_to_bundle_expr_1 @[module-XXXXXXXXXX.rs 8:1] wire _bundle_literal_expr_4: Ty1 connect _bundle_literal_expr_4.tag, {|A, B, C|}(C) wire _cast_bundle_to_bits_expr_1: Ty9 @@ -4001,18 +3894,18 @@ circuit check_enum_connect_any: connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1] B: wire __connect_variant_body_5: Ty5 @[module-XXXXXXXXXX.rs 9:1] - wire _cast_bits_to_bundle_expr_3: Ty4 - wire _cast_bits_to_bundle_expr_flattened_3: Ty7 - connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 1, 0), 0, 0) - wire _cast_bits_to_enum_expr_3: Ty3 - when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_3.tag, 0)): - connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlNone) + wire _cast_bits_to_bundle_expr_2: Ty4 + wire _cast_bits_to_bundle_expr_flattened_2: Ty7 + connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i1.body, 1, 0), 0, 0) + wire _cast_bits_to_enum_expr_2: Ty3 + when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_2.tag, 0)): + connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlNone) else: - connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlSome) - connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_enum_expr_3 - connect _cast_bits_to_bundle_expr_flattened_3.body, bits(bits(i1.body, 1, 0), 1, 1) - connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body - match _cast_bits_to_bundle_expr_3.tag: @[module-XXXXXXXXXX.rs 9:1] + connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlSome) + connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_enum_expr_2 + connect _cast_bits_to_bundle_expr_flattened_2.body, bits(bits(i1.body, 1, 0), 1, 1) + connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body + match _cast_bits_to_bundle_expr_2.tag: @[module-XXXXXXXXXX.rs 9:1] HdlNone: wire _bundle_literal_expr_6: Ty5 connect _bundle_literal_expr_6.tag, {|HdlNone, HdlSome|}(HdlNone) @@ -4020,21 +3913,10 @@ circuit check_enum_connect_any: connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1] HdlSome: wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1] - wire _cast_bits_to_bundle_expr_4: Ty4 - wire _cast_bits_to_bundle_expr_flattened_4: Ty7 - connect _cast_bits_to_bundle_expr_flattened_4.tag, bits(bits(i1.body, 1, 0), 0, 0) - wire _cast_bits_to_enum_expr_4: Ty3 - when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_4.tag, 0)): - connect _cast_bits_to_enum_expr_4, {|HdlNone, HdlSome|}(HdlNone) - else: - connect _cast_bits_to_enum_expr_4, {|HdlNone, HdlSome|}(HdlSome) - connect _cast_bits_to_bundle_expr_4.tag, _cast_bits_to_enum_expr_4 - connect _cast_bits_to_bundle_expr_flattened_4.body, bits(bits(i1.body, 1, 0), 1, 1) - connect _cast_bits_to_bundle_expr_4.body, _cast_bits_to_bundle_expr_flattened_4.body ; connect different types: ; lhs: SInt<2> ; rhs: SInt<1> - connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_4.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1] + connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_2.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1] wire _bundle_literal_expr_7: Ty5 connect _bundle_literal_expr_7.tag, {|HdlNone, HdlSome|}(HdlSome) connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6) @@ -4056,18 +3938,18 @@ circuit check_enum_connect_any: connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1] C: wire __connect_variant_body_7: Ty8 @[module-XXXXXXXXXX.rs 9:1] - wire _cast_bits_to_bundle_expr_5: Ty8 - wire _cast_bits_to_bundle_expr_flattened_5: Ty9 - connect _cast_bits_to_bundle_expr_flattened_5.tag, bits(bits(i1.body, 0, 0), 0, 0) - wire _cast_bits_to_enum_expr_5: Ty3 - when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_5.tag, 0)): - connect _cast_bits_to_enum_expr_5, {|HdlNone, HdlSome|}(HdlNone) + wire _cast_bits_to_bundle_expr_3: Ty8 + wire _cast_bits_to_bundle_expr_flattened_3: Ty9 + connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 0, 0), 0, 0) + wire _cast_bits_to_enum_expr_3: Ty3 + when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_3.tag, 0)): + connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlNone) else: - connect _cast_bits_to_enum_expr_5, {|HdlNone, HdlSome|}(HdlSome) - connect _cast_bits_to_bundle_expr_5.tag, _cast_bits_to_enum_expr_5 - connect _cast_bits_to_bundle_expr_flattened_5.body, UInt<0>(0) - connect _cast_bits_to_bundle_expr_5.body, _cast_bits_to_bundle_expr_flattened_5.body - connect __connect_variant_body_7, _cast_bits_to_bundle_expr_5 @[module-XXXXXXXXXX.rs 9:1] + connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlSome) + connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_enum_expr_3 + connect _cast_bits_to_bundle_expr_flattened_3.body, UInt<0>(0) + connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body + connect __connect_variant_body_7, _cast_bits_to_bundle_expr_3 @[module-XXXXXXXXXX.rs 9:1] wire _bundle_literal_expr_9: Ty2 connect _bundle_literal_expr_9.tag, {|A, B, C|}(C) wire _cast_bundle_to_bits_expr_3: Ty9 @@ -4134,16 +4016,10 @@ circuit check_enum_connect_any: connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1] else: wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1] - wire _cast_bits_to_bundle_expr_1: Ty3 - wire _cast_bits_to_bundle_expr_flattened_1: Ty3 - connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 2, 0), 0, 0) - connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_bundle_expr_flattened_1.tag - connect _cast_bits_to_bundle_expr_flattened_1.body, bits(bits(i2.body, 2, 0), 2, 1) - connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body ; connect different types: ; lhs: SInt<1> ; rhs: SInt<2> - connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr_1.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1] + connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1] wire _bundle_literal_expr_2: Ty2 connect _bundle_literal_expr_2.tag, UInt<1>(0h1) connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2) @@ -4159,13 +4035,13 @@ circuit check_enum_connect_any: connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1] else: wire __connect_variant_body_3: Ty4 @[module-XXXXXXXXXX.rs 8:1] - wire _cast_bits_to_bundle_expr_2: Ty4 - wire _cast_bits_to_bundle_expr_flattened_2: Ty4 - connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i2.body, 0, 0), 0, 0) - connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_bundle_expr_flattened_2.tag - connect _cast_bits_to_bundle_expr_flattened_2.body, UInt<0>(0) - connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body - connect __connect_variant_body_3, _cast_bits_to_bundle_expr_2 @[module-XXXXXXXXXX.rs 8:1] + wire _cast_bits_to_bundle_expr_1: Ty4 + wire _cast_bits_to_bundle_expr_flattened_1: Ty4 + connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 0, 0), 0, 0) + connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_bundle_expr_flattened_1.tag + connect _cast_bits_to_bundle_expr_flattened_1.body, UInt<0>(0) + connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body + connect __connect_variant_body_3, _cast_bits_to_bundle_expr_1 @[module-XXXXXXXXXX.rs 8:1] wire _bundle_literal_expr_4: Ty0 connect _bundle_literal_expr_4.tag, UInt<2>(0h2) wire _cast_bundle_to_bits_expr_1: Ty4 @@ -4187,29 +4063,23 @@ circuit check_enum_connect_any: connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1] else when eq(i1.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 9:1] wire __connect_variant_body_5: Ty3 @[module-XXXXXXXXXX.rs 9:1] - wire _cast_bits_to_bundle_expr_3: Ty2 - wire _cast_bits_to_bundle_expr_flattened_3: Ty2 - connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 1, 0), 0, 0) - connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_bundle_expr_flattened_3.tag - connect _cast_bits_to_bundle_expr_flattened_3.body, bits(bits(i1.body, 1, 0), 1, 1) - connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body - when eq(_cast_bits_to_bundle_expr_3.tag, UInt<1>(0h0)): @[module-XXXXXXXXXX.rs 9:1] + wire _cast_bits_to_bundle_expr_2: Ty2 + wire _cast_bits_to_bundle_expr_flattened_2: Ty2 + connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i1.body, 1, 0), 0, 0) + connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_bundle_expr_flattened_2.tag + connect _cast_bits_to_bundle_expr_flattened_2.body, bits(bits(i1.body, 1, 0), 1, 1) + connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body + when eq(_cast_bits_to_bundle_expr_2.tag, UInt<1>(0h0)): @[module-XXXXXXXXXX.rs 9:1] wire _bundle_literal_expr_6: Ty3 connect _bundle_literal_expr_6.tag, UInt<1>(0h0) connect _bundle_literal_expr_6.body, UInt<2>(0h0) connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1] else: wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1] - wire _cast_bits_to_bundle_expr_4: Ty2 - wire _cast_bits_to_bundle_expr_flattened_4: Ty2 - connect _cast_bits_to_bundle_expr_flattened_4.tag, bits(bits(i1.body, 1, 0), 0, 0) - connect _cast_bits_to_bundle_expr_4.tag, _cast_bits_to_bundle_expr_flattened_4.tag - connect _cast_bits_to_bundle_expr_flattened_4.body, bits(bits(i1.body, 1, 0), 1, 1) - connect _cast_bits_to_bundle_expr_4.body, _cast_bits_to_bundle_expr_flattened_4.body ; connect different types: ; lhs: SInt<2> ; rhs: SInt<1> - connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_4.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1] + connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_2.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1] wire _bundle_literal_expr_7: Ty3 connect _bundle_literal_expr_7.tag, UInt<1>(0h1) connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6) @@ -4225,13 +4095,13 @@ circuit check_enum_connect_any: connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1] else: wire __connect_variant_body_7: Ty4 @[module-XXXXXXXXXX.rs 9:1] - wire _cast_bits_to_bundle_expr_5: Ty4 - wire _cast_bits_to_bundle_expr_flattened_5: Ty4 - connect _cast_bits_to_bundle_expr_flattened_5.tag, bits(bits(i1.body, 0, 0), 0, 0) - connect _cast_bits_to_bundle_expr_5.tag, _cast_bits_to_bundle_expr_flattened_5.tag - connect _cast_bits_to_bundle_expr_flattened_5.body, UInt<0>(0) - connect _cast_bits_to_bundle_expr_5.body, _cast_bits_to_bundle_expr_flattened_5.body - connect __connect_variant_body_7, _cast_bits_to_bundle_expr_5 @[module-XXXXXXXXXX.rs 9:1] + wire _cast_bits_to_bundle_expr_3: Ty4 + wire _cast_bits_to_bundle_expr_flattened_3: Ty4 + connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 0, 0), 0, 0) + connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_bundle_expr_flattened_3.tag + connect _cast_bits_to_bundle_expr_flattened_3.body, UInt<0>(0) + connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body + connect __connect_variant_body_7, _cast_bits_to_bundle_expr_3 @[module-XXXXXXXXXX.rs 9:1] wire _bundle_literal_expr_9: Ty1 connect _bundle_literal_expr_9.tag, UInt<2>(0h2) wire _cast_bundle_to_bits_expr_3: Ty4 From b1116c4a1a88f68f3a5612f80c38fbfb7ba6f558 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 1 Jun 2026 21:39:26 -0700 Subject: [PATCH 11/15] simplify_enums: cache folded expressions --- .../src/module/transform/simplify_enums.rs | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/crates/fayalite/src/module/transform/simplify_enums.rs b/crates/fayalite/src/module/transform/simplify_enums.rs index 5f136f2..c52939c 100644 --- a/crates/fayalite/src/module/transform/simplify_enums.rs +++ b/crates/fayalite/src/module/transform/simplify_enums.rs @@ -96,6 +96,7 @@ enum EnumTypeState { struct ModuleState { module_name: NameId, + expr_cache: HashMap, } impl ModuleState { @@ -675,6 +676,7 @@ impl Folder for State { fn fold_module(&mut self, v: Module) -> Result, Self::Error> { self.module_state_stack.push(ModuleState { module_name: v.name_id(), + expr_cache: HashMap::default(), }); let retval = Fold::default_fold(v, self); self.module_state_stack.pop(); @@ -682,30 +684,39 @@ impl Folder for State { } fn fold_expr_enum(&mut self, op: ExprEnum) -> Result { - match op { + if let Some(folded_op) = self + .module_state_stack + .last() + .expect("known to be in module") + .expr_cache + .get(&op) + { + return Ok(*folded_op); + } + let folded_op = match op { ExprEnum::EnumLiteral(op) => { let folded_variant_value = op.variant_value().map(|v| v.fold(self)).transpose()?; - Ok(*Expr::expr_enum(self.handle_enum_literal( + *Expr::expr_enum(self.handle_enum_literal( op.ty(), op.variant_index(), folded_variant_value, - )?)) + )?) } ExprEnum::VariantAccess(op) => { let folded_base_expr = Expr::canonical(op.base()).fold(self)?; - Ok(*Expr::expr_enum(self.handle_variant_access( + *Expr::expr_enum(self.handle_variant_access( op.base().ty(), folded_base_expr, op.variant_index(), - )?)) + )?) } - ExprEnum::MemPort(mem_port) => Ok( + ExprEnum::MemPort(mem_port) => { if let Some(&wire) = self.replacement_mem_ports.get(&mem_port) { ExprEnum::Wire(wire) } else { ExprEnum::MemPort(mem_port.fold(self)?) - }, - ), + } + } ExprEnum::UIntLiteral(_) | ExprEnum::SIntLiteral(_) | ExprEnum::BoolLiteral(_) @@ -813,8 +824,14 @@ impl Folder for State { | ExprEnum::Wire(_) | ExprEnum::Reg(_) | ExprEnum::RegSync(_) - | ExprEnum::RegAsync(_) => op.default_fold(self), - } + | ExprEnum::RegAsync(_) => op.default_fold(self)?, + }; + self.module_state_stack + .last_mut() + .expect("known to be in module") + .expr_cache + .insert(op, folded_op); + Ok(folded_op) } fn fold_block(&mut self, block: Block) -> Result { From 31353862ceba3d255fd6712813a457688b269358 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 1 Jun 2026 23:10:43 -0700 Subject: [PATCH 12/15] fayalite/src/module: check that expressions are visible where they are used, e.g. erroring when a wire is inside an `if` but used outside. --- crates/fayalite/src/module.rs | 287 ++++++++++++++++++++++++++++++++-- 1 file changed, 276 insertions(+), 11 deletions(-) diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index 816a286..86fdd40 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -8,7 +8,7 @@ use crate::{ clock::{Clock, ClockDomain}, enum_::{Enum, EnumMatchVariantsIter, EnumType}, expr::{ - Expr, Flow, ToExpr, ValueType, + Expr, ExprEnum, Flow, ToExpr, ValueType, ops::VariantAccess, target::{ GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, @@ -20,6 +20,7 @@ use crate::{ int::{Bool, DynSize, Size}, intern::{Intern, Interned}, memory::{Mem, MemBuilder, MemBuilderTarget, PortName}, + module::transform::visit::{Visit, Visitor}, platform::PlatformIOBuilder, reg::Reg, reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset}, @@ -1598,9 +1599,54 @@ impl TargetState { } } +struct VisibleExprsStack { + buf: Vec>, + len: usize, +} + +impl VisibleExprsStack { + fn top(&mut self) -> &mut HashSet { + &mut self.buf[self.len - 1] + } + fn slice(&self) -> &[HashSet] { + &self.buf[..self.len] + } + fn contains(&self, v: &ExprEnum) -> bool { + self.slice().iter().any(|i| i.contains(v)) + } + fn push_empty(&mut self) { + #[cold] + fn push_empty_cold(stack: &mut VisibleExprsStack) { + stack.buf.push(HashSet::default()); + assert_eq!(stack.buf.len(), stack.len) + } + self.len += 1; + if self.len > self.buf.len() { + push_empty_cold(self) + } + } + fn pop(&mut self) { + let Some(new_len) = self.len.checked_sub(1) else { + unreachable!("visible exprs stack underflow"); + }; + self.buf[new_len].clear(); + self.len = new_len; + } +} + +impl Default for VisibleExprsStack { + fn default() -> Self { + Self { + buf: Vec::new(), + len: 0, + } + } +} + struct AssertValidityState { module: Module, blocks: Vec, + visible_exprs: VisibleExprsStack, target_states: HashMap, TargetState>, } @@ -1771,6 +1817,7 @@ impl AssertValidityState { } } } + #[track_caller] fn process_conditional_sub_blocks( &mut self, parent_block: usize, @@ -1784,17 +1831,40 @@ impl AssertValidityState { } } #[track_caller] + fn assert_expr_validity(&mut self, expr: Expr, source_location: SourceLocation) { + let mut visitor = AssertExprValidity { state: self }; + match visitor.visit_expr(&expr) { + Ok(()) => {} + Err(e) => match e { + InvalidExpr::ExprIsNotVisible(expr) => { + if let Some(target) = expr.target() { + panic!( + "at {source_location}: expression isn't visible here, it's defined:\n\ + at {}: {expr:?}", + target.base().source_location(), + ); + } else { + panic!("at {source_location}: expression isn't visible here: {expr:?}"); + } + } + }, + } + } + #[track_caller] fn assert_subtree_validity(&mut self, block: usize) { + self.visible_exprs.push_empty(); let module = self.module; if block == 0 { for module_io in &*module.module_io { self.insert_new_base(TargetBase::intern_sized(module_io.module_io.into()), block); + self.visible_exprs.top().insert(module_io.module_io.into()); } } let Block { memories, stmts } = self.blocks[block]; for m in memories { for port in m.ports() { self.insert_new_base(TargetBase::intern_sized(port.into()), block); + self.visible_exprs.top().insert(port.into()); } } for stmt in stmts { @@ -1808,44 +1878,104 @@ impl AssertValidityState { } = connect; self.set_connect_side_written(lhs, source_location, true, block); self.set_connect_side_written(rhs, source_location, false, block); + self.assert_expr_validity(lhs, source_location); + self.assert_expr_validity(rhs, source_location); + } + Stmt::Formal(formal) => { + let StmtFormal { + kind: _, + clk, + pred, + en, + text: _, + source_location, + } = formal; + self.assert_expr_validity(clk, source_location); + self.assert_expr_validity(pred, source_location); + self.assert_expr_validity(en, source_location); } - Stmt::Formal(_) => {} Stmt::If(if_stmt) => { - let sub_blocks = if_stmt.blocks.map(|block| self.make_block_index(block)); + let StmtIf { + cond, + source_location, + blocks: sub_blocks, + } = if_stmt; + self.assert_expr_validity(cond, source_location); + let sub_blocks = sub_blocks.map(|block| self.make_block_index(block)); self.process_conditional_sub_blocks(block, sub_blocks) } Stmt::Match(match_stmt) => { match_stmt.assert_validity(); + let StmtMatch { + expr, + source_location, + blocks: sub_blocks, + } = match_stmt; + self.assert_expr_validity(expr, source_location); let sub_blocks = Vec::from_iter( - match_stmt - .blocks + sub_blocks .into_iter() .map(|block| self.make_block_index(block)), ); - self.process_conditional_sub_blocks(block, sub_blocks.iter().copied()) + self.visible_exprs.push_empty(); + let visible_exprs_top = self.visible_exprs.top(); + for variant_index in 0..expr.ty().variants().len() { + visible_exprs_top + .insert(::new_by_index(expr, variant_index).into()); + } + self.process_conditional_sub_blocks(block, sub_blocks.iter().copied()); + self.visible_exprs.pop(); } Stmt::Declaration(StmtDeclaration::Wire(StmtWire { annotations: _, wire, - })) => self.insert_new_base(TargetBase::intern_sized(wire.into()), block), + })) => { + self.insert_new_base(TargetBase::intern_sized(wire.into()), block); + self.visible_exprs.top().insert(wire.into()); + } Stmt::Declaration(StmtDeclaration::Reg(StmtReg { annotations: _, reg, - })) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block), + })) => { + self.assert_expr_validity(reg.clock_domain(), reg.source_location()); + if let Some(init) = reg.init() { + self.assert_expr_validity(init, reg.source_location()); + } + self.insert_new_base(TargetBase::intern_sized(reg.into()), block); + self.visible_exprs.top().insert(reg.into()); + } Stmt::Declaration(StmtDeclaration::RegSync(StmtReg { annotations: _, reg, - })) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block), + })) => { + self.assert_expr_validity(reg.clock_domain(), reg.source_location()); + if let Some(init) = reg.init() { + self.assert_expr_validity(init, reg.source_location()); + } + self.insert_new_base(TargetBase::intern_sized(reg.into()), block); + self.visible_exprs.top().insert(reg.into()); + } Stmt::Declaration(StmtDeclaration::RegAsync(StmtReg { annotations: _, reg, - })) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block), + })) => { + self.assert_expr_validity(reg.clock_domain(), reg.source_location()); + if let Some(init) = reg.init() { + self.assert_expr_validity(init, reg.source_location()); + } + self.insert_new_base(TargetBase::intern_sized(reg.into()), block); + self.visible_exprs.top().insert(reg.into()); + } Stmt::Declaration(StmtDeclaration::Instance(StmtInstance { annotations: _, instance, - })) => self.insert_new_base(TargetBase::intern_sized(instance.into()), block), + })) => { + self.insert_new_base(TargetBase::intern_sized(instance.into()), block); + self.visible_exprs.top().insert(instance.into()); + } } } + self.visible_exprs.pop(); } #[track_caller] fn assert_validity(&mut self) { @@ -1874,6 +2004,140 @@ impl AssertValidityState { } } +struct AssertExprValidity<'a> { + state: &'a mut AssertValidityState, +} + +enum InvalidExpr { + ExprIsNotVisible(Expr), +} + +impl transform::visit::Visitor for AssertExprValidity<'_> { + type Error = InvalidExpr; + fn visit_expr_enum(&mut self, v: &ExprEnum) -> Result<(), Self::Error> { + match v { + ExprEnum::UIntLiteral(_) + | ExprEnum::SIntLiteral(_) + | ExprEnum::BoolLiteral(_) + | ExprEnum::PhantomConst(_) + | ExprEnum::BundleLiteral(_) + | ExprEnum::ArrayLiteral(_) + | ExprEnum::EnumLiteral(_) + | ExprEnum::Uninit(_) + | ExprEnum::NotU(_) + | ExprEnum::NotS(_) + | ExprEnum::NotB(_) + | ExprEnum::Neg(_) + | ExprEnum::BitAndU(_) + | ExprEnum::BitAndS(_) + | ExprEnum::BitAndB(_) + | ExprEnum::BitOrU(_) + | ExprEnum::BitOrS(_) + | ExprEnum::BitOrB(_) + | ExprEnum::BitXorU(_) + | ExprEnum::BitXorS(_) + | ExprEnum::BitXorB(_) + | ExprEnum::AddU(_) + | ExprEnum::AddS(_) + | ExprEnum::SubU(_) + | ExprEnum::SubS(_) + | ExprEnum::MulU(_) + | ExprEnum::MulS(_) + | ExprEnum::DivU(_) + | ExprEnum::DivS(_) + | ExprEnum::RemU(_) + | ExprEnum::RemS(_) + | ExprEnum::DynShlU(_) + | ExprEnum::DynShlS(_) + | ExprEnum::DynShrU(_) + | ExprEnum::DynShrS(_) + | ExprEnum::FixedShlU(_) + | ExprEnum::FixedShlS(_) + | ExprEnum::FixedShrU(_) + | ExprEnum::FixedShrS(_) + | ExprEnum::CmpLtB(_) + | ExprEnum::CmpLeB(_) + | ExprEnum::CmpGtB(_) + | ExprEnum::CmpGeB(_) + | ExprEnum::CmpEqB(_) + | ExprEnum::CmpNeB(_) + | ExprEnum::CmpLtU(_) + | ExprEnum::CmpLeU(_) + | ExprEnum::CmpGtU(_) + | ExprEnum::CmpGeU(_) + | ExprEnum::CmpEqU(_) + | ExprEnum::CmpNeU(_) + | ExprEnum::CmpLtS(_) + | ExprEnum::CmpLeS(_) + | ExprEnum::CmpGtS(_) + | ExprEnum::CmpGeS(_) + | ExprEnum::CmpEqS(_) + | ExprEnum::CmpNeS(_) + | ExprEnum::CastUIntToUInt(_) + | ExprEnum::CastUIntToSInt(_) + | ExprEnum::CastSIntToUInt(_) + | ExprEnum::CastSIntToSInt(_) + | ExprEnum::CastBoolToUInt(_) + | ExprEnum::CastBoolToSInt(_) + | ExprEnum::CastUIntToBool(_) + | ExprEnum::CastSIntToBool(_) + | ExprEnum::CastBoolToSyncReset(_) + | ExprEnum::CastUIntToSyncReset(_) + | ExprEnum::CastSIntToSyncReset(_) + | ExprEnum::CastBoolToAsyncReset(_) + | ExprEnum::CastUIntToAsyncReset(_) + | ExprEnum::CastSIntToAsyncReset(_) + | ExprEnum::CastSyncResetToBool(_) + | ExprEnum::CastSyncResetToUInt(_) + | ExprEnum::CastSyncResetToSInt(_) + | ExprEnum::CastSyncResetToReset(_) + | ExprEnum::CastAsyncResetToBool(_) + | ExprEnum::CastAsyncResetToUInt(_) + | ExprEnum::CastAsyncResetToSInt(_) + | ExprEnum::CastAsyncResetToReset(_) + | ExprEnum::CastResetToBool(_) + | ExprEnum::CastResetToUInt(_) + | ExprEnum::CastResetToSInt(_) + | ExprEnum::CastBoolToClock(_) + | ExprEnum::CastUIntToClock(_) + | ExprEnum::CastSIntToClock(_) + | ExprEnum::CastClockToBool(_) + | ExprEnum::CastClockToUInt(_) + | ExprEnum::CastClockToSInt(_) + | ExprEnum::FieldAccess(_) + | ExprEnum::ArrayIndex(_) + | ExprEnum::DynArrayIndex(_) + | ExprEnum::ReduceBitAndU(_) + | ExprEnum::ReduceBitAndS(_) + | ExprEnum::ReduceBitOrU(_) + | ExprEnum::ReduceBitOrS(_) + | ExprEnum::ReduceBitXorU(_) + | ExprEnum::ReduceBitXorS(_) + | ExprEnum::SliceUInt(_) + | ExprEnum::SliceSInt(_) + | ExprEnum::CastToBits(_) + | ExprEnum::CastBitsTo(_) + | ExprEnum::ToTraceAsString(_) + | ExprEnum::TraceAsStringAsInner(_) => v.default_visit(self), + ExprEnum::VariantAccess(_) + | ExprEnum::ModuleIO(_) + | ExprEnum::Instance(_) + | ExprEnum::Wire(_) + | ExprEnum::Reg(_) + | ExprEnum::RegSync(_) + | ExprEnum::RegAsync(_) + | ExprEnum::MemPort(_) => { + if self.state.visible_exprs.contains(v) { + // no need to visit inner expressions, we already checked them before adding them to visible_exprs + Ok(()) + } else { + Err(InvalidExpr::ExprIsNotVisible(v.to_expr())) + } + } + } + } +} + impl Module { /// you generally should use the [`#[hdl_module]`][`crate::hdl_module`] proc-macro and [`ModuleBuilder`] instead #[track_caller] @@ -1999,6 +2263,7 @@ impl Module { AssertValidityState { module: self.canonical(), blocks: vec![], + visible_exprs: VisibleExprsStack::default(), target_states: HashMap::with_capacity_and_hasher(64, Default::default()), } .assert_validity(); From 5d68885eaf7de221d0bed7ac6cdb767c3c0a743d Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 5 Jun 2026 00:35:19 -0700 Subject: [PATCH 13/15] fayalite::testing: add checked_vcd_output!() --- crates/fayalite/src/prelude.rs | 2 +- crates/fayalite/src/testing.rs | 191 ++++++++++++++++++++- crates/fayalite/tests/expected/my_test.md | 6 + crates/fayalite/tests/expected/my_test.vcd | 13 ++ scripts/check-copyright.sh | 2 +- 5 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 crates/fayalite/tests/expected/my_test.md create mode 100644 crates/fayalite/tests/expected/my_test.vcd diff --git a/crates/fayalite/src/prelude.rs b/crates/fayalite/src/prelude.rs index 42038ca..cebbddd 100644 --- a/crates/fayalite/src/prelude.rs +++ b/crates/fayalite/src/prelude.rs @@ -37,7 +37,7 @@ pub use crate::{ value::{SimOnly, SimOnlyValue, SimValue, ToSimValue, ToSimValueWithType}, }, source_location::SourceLocation, - testing::{FormalMode, assert_formal}, + testing::{FormalMode, assert_formal, checked_vcd_output}, ty::{AsMask, CanonicalType, TraceAsString, Type}, util::{ConstUsize, GenericConstUsize}, wire::Wire, diff --git a/crates/fayalite/src/testing.rs b/crates/fayalite/src/testing.rs index bc7a0b1..cb9db9c 100644 --- a/crates/fayalite/src/testing.rs +++ b/crates/fayalite/src/testing.rs @@ -12,11 +12,13 @@ use crate::{ bundle::BundleType, firrtl::ExportOptions, module::Module, - util::HashMap, + sim::{Simulation, vcd::VcdWriterDecls}, + util::{HashMap, RcWriter}, }; use serde::{Deserialize, Serialize}; use std::{ fmt::{self, Write}, + panic::Location, path::{Path, PathBuf}, process::Command, sync::{Mutex, OnceLock}, @@ -222,3 +224,190 @@ pub fn assert_formal>, T: BundleType>( ) .expect("testing::assert_formal() failed"); } + +pub struct CheckedVcdOutput { + writer: Option, + expected_path: PathBuf, + expected_contents: Result, std::io::Error)>, + location: &'static Location<'static>, +} + +impl CheckedVcdOutput { + #[must_use] + #[track_caller] + pub fn new(sim: &mut Simulation, expected_path: PathBuf) -> Self { + let writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + Self { + writer: Some(writer), + expected_contents: std::fs::read_to_string(&expected_path).map_err(|e| { + eprintln!( + "error: failed to read expected VCD from: {}", + expected_path.display(), + ); + (std::env::current_dir().ok(), e) + }), + expected_path, + location: Location::caller(), + } + } + #[must_use] + #[track_caller] + #[doc(hidden)] + pub fn __checked_vcd_output_macro_helper( + sim: &mut Simulation, + cargo_manifest_dir: &'static str, + path: &'static str, + ) -> Self { + Self::new(sim, Path::new(cargo_manifest_dir).join(path)) + } + pub fn with_vcd_output(&self, f: impl FnOnce(&str) -> R) -> R { + let Some(writer) = &self.writer else { + unreachable!(); + }; + writer.clone().borrow(|output| { + let Ok(output) = str::from_utf8(output) else { + unreachable!("VcdWriter writes valid UTF-8"); + }; + f(output) + }) + } + #[track_caller] + pub fn finish(mut self) { + let Ok(()) = self.finish_impl(|msg| panic!("{msg}")); + } + fn finish_impl( + &mut self, + error: impl FnOnce(std::fmt::Arguments<'_>) -> E, + ) -> Result<(), E> { + let Self { + writer: Some(writer), + expected_path, + expected_contents, + location, + } = self + else { + // already finished + return Ok(()); + }; + let Ok(vcd) = String::from_utf8(writer.take()) else { + unreachable!("VcdWriter writes valid UTF-8"); + }; + let expected_path_d = expected_path.display(); + if expected_contents + .as_ref() + .is_ok_and(|expected_contents| *expected_contents == vcd) + { + // avoid written output from being split from threads interleaving writes to stdout + let _stdout = std::io::stderr().lock(); + // use println to get output captured by tests + println!("\n{location}: generated VCD matches the expected VCD in {expected_path_d}"); + return Ok(()); + } + // avoid written output from being split from threads interleaving writes to stderr + let _stderr = std::io::stderr().lock(); + let error = |msg: std::fmt::Arguments<'_>| { + // print msg at both beginning and end so it's easier to find when the vcd is huge + Err(error(format_args!( + "\n{msg}####### VCD:\n{vcd}\n#######\n{msg}" + ))) + }; + let error = |msg: std::fmt::Arguments<'_>| match &*expected_contents { + Ok(_) => error(format_args!( + "{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\ + {msg}", + )), + Err((Some(current_dir), e)) => error(format_args!( + "{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\ + error: failed to read: {e}\n\ + current dir: {current_dir}\n\ + {msg}", + current_dir = current_dir.display(), + )), + Err((None, e)) => error(format_args!( + "{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\ + error: failed to read: {e}\n\ + {msg}", + )), + }; + const OVERWRITE_VAR_NAME: &str = "OVERWRITE_EXPECTED_VCD"; + const OVERWRITE_VAR_VALUE: &str = "overwrite"; + match std::env::var_os(OVERWRITE_VAR_NAME) { + Some(v) if v == OVERWRITE_VAR_VALUE => match std::fs::write(&expected_path, &vcd) { + Ok(()) => error(format_args!( + "warning: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- writing the generated VCD to {expected_path_d}\n" + )), + Err(e) => error(format_args!( + "error: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- tried to write the generated VCD to {expected_path_d}\n\ + error: failed to write: {e}" + )), + }, + _ => error(format_args!( + "note: rerun the test with the environment variable `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}`\n\ + to update the expected output to match the generated output.\n" + )), + } + } +} + +impl Drop for CheckedVcdOutput { + #[track_caller] + fn drop(&mut self) { + let _ = self.finish_impl(|msg| { + if std::thread::panicking() { + eprintln!("{msg}"); // use eprintln to get output captured by tests + } else { + panic!("{msg}"); + } + }); + } +} + +#[macro_export] +/// Use in tests to check that [`Simulation`] generates the expected VCD traces, by comparing to a `.vcd` file containing the expected traces. +/// +/// Use like so: +/// ``` +/// # use fayalite::prelude::*; +/// # +/// # #[hdl_module] +/// # fn my_module() { +/// # #[hdl] +/// # let a: UInt<8> = m.input(); +/// # #[hdl] +/// # let b: UInt<8> = m.output(); +/// # connect(b, 0u8); +/// # #[hdl] +/// # if a.cmp_eq(100u8) { +/// # connect(b, 42u8); +/// # } +/// # } +/// // inside your #[test] fn my_test(): +/// +/// // get the module to simulate: +/// let m = my_module(); +/// // create a simulation of the module: +/// let mut sim = Simulation::new(m); +/// // set up the expected VCD traces, the given .vcd path is relative to env!("CARGO_MANIFEST_DIR") +/// let _checked_vcd_output = checked_vcd_output!( +/// &mut sim, +/// "tests/expected/my_test.vcd", +/// ); +/// // now run the simulation like normal: +/// sim.write(sim.io().a, 0u8); +/// assert_eq!(sim.read(sim.io().b).as_int(), 0); +/// sim.advance_time(SimDuration::from_micros(1)); +/// sim.write(sim.io().a, 100u8); +/// assert_eq!(sim.read(sim.io().b).as_int(), 42); +/// ``` +macro_rules! checked_vcd_output { + ($sim:expr, $path_relative_to_manifest_dir:expr $(,)?) => { + $crate::testing::CheckedVcdOutput::__checked_vcd_output_macro_helper( + $sim, + $crate::__std::env!("CARGO_MANIFEST_DIR"), + $crate::__std::concat!($path_relative_to_manifest_dir), + ) + }; +} + +pub use checked_vcd_output; diff --git a/crates/fayalite/tests/expected/my_test.md b/crates/fayalite/tests/expected/my_test.md new file mode 100644 index 0000000..a3b52ae --- /dev/null +++ b/crates/fayalite/tests/expected/my_test.md @@ -0,0 +1,6 @@ + + +`my_test.vcd` is used in the doctest of `fayalite::testing::checked_vcd_output` diff --git a/crates/fayalite/tests/expected/my_test.vcd b/crates/fayalite/tests/expected/my_test.vcd new file mode 100644 index 0000000..3df1caf --- /dev/null +++ b/crates/fayalite/tests/expected/my_test.vcd @@ -0,0 +1,13 @@ +$timescale 1 ps $end +$scope module my_module $end +$var wire 8 gAF7X a $end +$var wire 8 QS=a/ b $end +$upscope $end +$enddefinitions $end +$dumpvars +b0 gAF7X +b0 QS=a/ +$end +#1000000 +b1100100 gAF7X +b101010 QS=a/ diff --git a/scripts/check-copyright.sh b/scripts/check-copyright.sh index 99205bb..779bcbf 100755 --- a/scripts/check-copyright.sh +++ b/scripts/check-copyright.sh @@ -47,7 +47,7 @@ function main() */LICENSE.md|*/Notices.txt) # copyright file ;; - /crates/fayalite/tests/ui/*.stderr|/crates/fayalite/tests/sim/expected/*.vcd|/crates/fayalite/tests/sim/expected/*.txt) + /crates/fayalite/tests/ui/*.stderr|/crates/fayalite/tests/expected/*.vcd|/crates/fayalite/tests/sim/expected/*.vcd|/crates/fayalite/tests/sim/expected/*.txt) # file that can't contain copyright header ;; /.forgejo/workflows/*.yml|*/.gitignore|*.toml|*/Makefile|*/_CoqProject) From d4d97067986267883d00ab788c195b17e593755f Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 5 Jun 2026 00:37:32 -0700 Subject: [PATCH 14/15] reimplement fayalite::formal and add support to the simulator Add support to the simulator for running hdl asserts/assumes and being able to write to the formal global clock/reset and all any/all_const/seq that are used. This allows you to use the exact same HDL code for running a simulation and for running a formal proof. --- crates/fayalite/src/annotations.rs | 5 +- crates/fayalite/src/expr.rs | 19 + crates/fayalite/src/expr/ops.rs | 67 ++ crates/fayalite/src/expr/target.rs | 48 + crates/fayalite/src/firrtl.rs | 412 ++++++--- crates/fayalite/src/formal.rs | 332 +++++-- crates/fayalite/src/intern.rs | 52 +- crates/fayalite/src/module.rs | 226 ++++- .../src/module/transform/deduce_resets.rs | 11 + .../src/module/transform/simplify_enums.rs | 6 +- crates/fayalite/src/module/transform/visit.rs | 30 +- crates/fayalite/src/prelude.rs | 4 +- crates/fayalite/src/reg.rs | 3 +- crates/fayalite/src/sim.rs | 651 ++++++++++--- crates/fayalite/src/sim/compiler.rs | 738 +++++++++------ crates/fayalite/src/sim/interpreter.rs | 24 + crates/fayalite/src/sim/vcd.rs | 32 +- .../vendor/xilinx/yosys_nextpnr_prjxray.rs | 3 + crates/fayalite/src/wire.rs | 4 +- crates/fayalite/tests/module.rs | 182 +++- crates/fayalite/tests/sim.rs | 141 ++- .../fayalite/tests/sim/expected/array_rw.txt | 3 + .../expected/conditional_assignment_last.txt | 3 + .../tests/sim/expected/connect_const.txt | 3 + .../sim/expected/connect_const_reset.txt | 3 + .../tests/sim/expected/counter_async.txt | 3 + .../tests/sim/expected/counter_sync.txt | 3 + .../tests/sim/expected/duplicate_names.txt | 3 + .../sim/expected/enum_with_simple_body.txt | 3 + crates/fayalite/tests/sim/expected/enums.txt | 3 + .../tests/sim/expected/extern_module.txt | 3 + .../tests/sim/expected/extern_module2.txt | 3 + .../tests/sim/expected/last_connect.txt | 3 + .../tests/sim/expected/many_memories.txt | 3 + .../fayalite/tests/sim/expected/memories.txt | 3 + .../fayalite/tests/sim/expected/memories2.txt | 3 + .../fayalite/tests/sim/expected/memories3.txt | 3 + crates/fayalite/tests/sim/expected/mod1.txt | 3 + .../tests/sim/expected/phantom_const.txt | 3 + .../sim/expected/queue_1_false_false.txt | 3 + .../tests/sim/expected/queue_1_false_true.txt | 3 + .../tests/sim/expected/queue_1_true_false.txt | 3 + .../tests/sim/expected/queue_1_true_true.txt | 3 + .../sim/expected/queue_2_false_false.txt | 3 + .../tests/sim/expected/queue_2_false_true.txt | 3 + .../tests/sim/expected/queue_2_true_false.txt | 3 + .../tests/sim/expected/queue_2_true_true.txt | 3 + .../sim/expected/queue_3_false_false.txt | 3 + .../tests/sim/expected/queue_3_false_true.txt | 3 + .../tests/sim/expected/queue_3_true_false.txt | 3 + .../tests/sim/expected/queue_3_true_true.txt | 3 + .../sim/expected/queue_4_false_false.txt | 3 + .../tests/sim/expected/queue_4_false_true.txt | 3 + .../tests/sim/expected/queue_4_true_false.txt | 3 + .../tests/sim/expected/queue_4_true_true.txt | 3 + .../tests/sim/expected/ripple_counter.txt | 3 + .../tests/sim/expected/shift_register.txt | 3 + .../tests/sim/expected/sim_fork_join.txt | 3 + .../sim/expected/sim_fork_join_scope.txt | 3 + .../tests/sim/expected/sim_only_connects.txt | 3 + .../tests/sim/expected/sim_read_past.txt | 3 + .../expected/sim_resettable_counter_async.txt | 3 + ...settable_counter_async_immediate_reset.txt | 3 + .../expected/sim_resettable_counter_sync.txt | 3 + ...esettable_counter_sync_immediate_reset.txt | 3 + .../sim/expected/sim_trace_as_string.txt | 3 + .../sim/expected/test_formal_counter.txt | 855 ++++++++++++++++++ .../sim/expected/test_formal_counter.vcd | 290 ++++++ .../expected/test_formal_counter_assert.vcd | 194 ++++ crates/fayalite/visit_types.json | 31 +- 70 files changed, 3836 insertions(+), 659 deletions(-) create mode 100644 crates/fayalite/tests/sim/expected/test_formal_counter.txt create mode 100644 crates/fayalite/tests/sim/expected/test_formal_counter.vcd create mode 100644 crates/fayalite/tests/sim/expected/test_formal_counter_assert.vcd diff --git a/crates/fayalite/src/annotations.rs b/crates/fayalite/src/annotations.rs index 4ca84dd..252a0ce 100644 --- a/crates/fayalite/src/annotations.rs +++ b/crates/fayalite/src/annotations.rs @@ -238,7 +238,10 @@ impl TargetedAnnotation { } #[track_caller] pub fn assert_valid_target(target: Interned) { - assert!(target.is_static(), "can't annotate non-static targets"); + assert!( + target.is_valid_annotation_target(), + "not a valid annotation target: {target:?}", + ); } pub fn target(&self) -> Interned { self.target diff --git a/crates/fayalite/src/expr.rs b/crates/fayalite/src/expr.rs index e235cd7..eb4bf0f 100644 --- a/crates/fayalite/src/expr.rs +++ b/crates/fayalite/src/expr.rs @@ -6,6 +6,7 @@ use crate::{ bundle::{Bundle, BundleType}, enum_::{Enum, EnumType}, expr::target::{GetTarget, Target}, + formal::FormalInput, int::{Bool, DynSize, IntType, SIntValue, Size, SizeType, UInt, UIntType, UIntValue}, intern::{Intern, Interned}, memory::{DynPortType, MemPort, PortType}, @@ -227,6 +228,8 @@ expr_enum! { RegSync(Reg), RegAsync(Reg), MemPort(MemPort), + FormalInput(FormalInput), + SimIoForGlobal(ops::SimIoForGlobal), } } @@ -1908,3 +1911,19 @@ impl ToTraceAsStringImpl Result, NotALiteralExpr> { + Err(NotALiteralExpr) + } +} + +impl ToExpr for FormalInput { + fn to_expr(&self) -> Expr { + Expr { + __enum: ExprEnum::FormalInput(*self).intern_sized(), + __ty: self.ty(), + __flow: self.flow(), + } + } +} diff --git a/crates/fayalite/src/expr/ops.rs b/crates/fayalite/src/expr/ops.rs index b2e20ad..5d335a5 100644 --- a/crates/fayalite/src/expr/ops.rs +++ b/crates/fayalite/src/expr/ops.rs @@ -17,6 +17,7 @@ use crate::{ }, value_category::ValueCategoryExpr, }, + formal::FormalInput, int::{ Bool, BoolOrIntType, DynSize, IntType, KnownSize, SInt, SIntType, SIntValue, Size, UInt, UIntType, UIntValue, @@ -4881,3 +4882,69 @@ impl ToExpr for TraceAsStringAsInner { } } } + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +/// The [`Simulation::io()`] equivalent for a global signal, this is a flipped version of a global signal +/// that allows you to e.g. use [`Simulation::write()`] to write to [`formal_global_clock()`]. +/// +/// [`Simulation::io()`]: crate::sim::Simulation::io +/// [`Simulation::write()`]: crate::sim::Simulation::write +/// [`formal_global_clock()`]: crate::formal::formal_global_clock +pub struct SimIoForGlobal { + global: FormalInput, +} + +impl fmt::Debug for SimIoForGlobal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SimIoForGlobal").field(&self.global).finish() + } +} + +impl SimIoForGlobal { + pub fn new(global: FormalInput) -> Self { + Self { global } + } + pub fn global(self) -> FormalInput { + self.global + } + pub(crate) fn must_connect_to(self) -> bool { + true + } + pub fn flow(self) -> Flow { + self.global.flow().flip() + } + pub(crate) fn source_location(self) -> crate::source_location::SourceLocation { + self.global.source_location() + } +} + +impl GetTarget for SimIoForGlobal { + fn target(&self) -> Option> { + Some(Target::from(*self).intern_sized()) + } +} + +impl ToLiteralBits for SimIoForGlobal { + fn to_literal_bits(&self) -> Result, NotALiteralExpr> { + Err(NotALiteralExpr) + } +} + +impl ValueType for SimIoForGlobal { + type Type = CanonicalType; + type ValueCategory = ValueCategoryExpr; + + fn ty(&self) -> Self::Type { + self.global.ty() + } +} + +impl ToExpr for SimIoForGlobal { + fn to_expr(&self) -> Expr { + Expr { + __enum: ExprEnum::SimIoForGlobal(*self).intern(), + __ty: self.ty(), + __flow: self.flow(), + } + } +} diff --git a/crates/fayalite/src/expr/target.rs b/crates/fayalite/src/expr/target.rs index 9016111..d7775ec 100644 --- a/crates/fayalite/src/expr/target.rs +++ b/crates/fayalite/src/expr/target.rs @@ -4,6 +4,7 @@ use crate::{ array::Array, bundle::{Bundle, BundleField}, expr::{Expr, Flow, ToExpr, ValueType, value_category::ValueCategoryExpr}, + formal::FormalInput, intern::{Intern, Interned}, memory::{DynPortType, MemPort}, module::{Instance, ModuleIO, TargetName}, @@ -295,6 +296,14 @@ impl_target_base! { #[is = is_instance] #[to = instance] Instance(Instance), + #[from = from] + #[is = is_formal_input] + #[to = formal_input] + FormalInput(FormalInput), + #[from = from] + #[is = is_sim_io_for_global] + #[to = sim_io_for_global] + SimIoForGlobal(crate::expr::ops::SimIoForGlobal), } } @@ -343,6 +352,8 @@ impl TargetBase { TargetBase::RegAsync(v) => TargetName(v.scoped_name(), None), TargetBase::Wire(v) => TargetName(v.scoped_name(), None), TargetBase::Instance(v) => TargetName(v.scoped_name(), None), + TargetBase::FormalInput(v) => TargetName(v.scoped_name(), None), + TargetBase::SimIoForGlobal(v) => TargetName(v.global().scoped_name(), None), } } pub fn canonical_ty(&self) -> CanonicalType { @@ -354,6 +365,21 @@ impl TargetBase { TargetBase::RegAsync(v) => v.ty(), TargetBase::Wire(v) => v.ty(), TargetBase::Instance(v) => v.ty().canonical(), + TargetBase::FormalInput(v) => v.ty(), + TargetBase::SimIoForGlobal(v) => v.ty(), + } + } + pub fn is_valid_annotation_target(&self) -> bool { + match self { + Self::ModuleIO(_) => true, + Self::MemPort(_) => true, + Self::Reg(_) => true, + Self::RegSync(_) => true, + Self::RegAsync(_) => true, + Self::Wire(_) => true, + Self::Instance(_) => true, + Self::FormalInput(_) => false, + Self::SimIoForGlobal(_) => false, } } } @@ -548,6 +574,16 @@ impl Target { } } } + pub fn is_valid_annotation_target(&self) -> bool { + let mut target = self; + loop { + match target { + Self::Base(target_base) => return target_base.is_valid_annotation_target(), + Self::Child(v) if !v.path_element().is_static() => return false, + Self::Child(v) => target = &v.parent, + } + } + } #[must_use] pub fn join(&self, path_element: Interned) -> Self { TargetChild::new(self.intern(), path_element).into() @@ -664,6 +700,18 @@ pub trait GetTarget { fn target(&self) -> Option>; } +impl GetTarget for Target { + fn target(&self) -> Option> { + Some(self.intern()) + } +} + +impl GetTarget for TargetBase { + fn target(&self) -> Option> { + Some(Target::Base(self.intern()).intern_sized()) + } +} + impl GetTarget for bool { fn target(&self) -> Option> { None diff --git a/crates/fayalite/src/firrtl.rs b/crates/fayalite/src/firrtl.rs index e2f33ae..60cc0d1 100644 --- a/crates/fayalite/src/firrtl.rs +++ b/crates/fayalite/src/firrtl.rs @@ -2,7 +2,7 @@ // See Notices.txt for copyright information #![allow(clippy::type_complexity)] use crate::{ - annotations::{Annotation, TargetedAnnotation}, + annotations::{Annotation, IntoAnnotations, TargetedAnnotation}, build::{ToArgs, WriteArgs}, bundle::{BundleField, BundleType}, enum_::{EnumType, EnumVariant}, @@ -14,18 +14,19 @@ use crate::{ TargetPathTraceAsStringInner, }, }, - formal::FormalKind, + formal::{FormalInput, FormalInputKind, FormalKind}, int::IntType, intern::{Intern, Interned}, memory::{PortKind, PortName}, module::{ AnnotatedModuleIO, Block, ExternModuleBody, ExternModuleParameter, ExternModuleParameterValue, ModuleBody, ModuleIO, NameId, NameOptId, NormalModuleBody, - Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, - StmtWire, + ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, + StmtMatch, StmtReg, StmtWire, transform::{ simplify_enums::{SimplifyEnumsError, SimplifyEnumsKind, simplify_enums}, simplify_memories::simplify_memories, + visit::Folder, }, }, prelude::*, @@ -44,6 +45,7 @@ use std::{ cell::{Cell, RefCell}, cmp::Ordering, collections::{BTreeMap, VecDeque}, + convert::Infallible, error::Error, ffi::OsString, fmt::{self, Write}, @@ -53,6 +55,7 @@ use std::{ ops::{ControlFlow, Range}, path::{Path, PathBuf}, rc::Rc, + sync::OnceLock, }; #[derive(Clone, Debug)] @@ -385,77 +388,66 @@ struct BlockDefinitionsCache { cast_bits_to_enum_exprs: RefCell>, cast_bits_to_array_exprs: RefCell>, cast_bits_to_phantom_const_exprs: RefCell>, -} - -struct BlockDefinitionsState<'a> { - rc_definitions: RcDefinitions, - parent: &'a BlockDefinitions<'a>, - cache: BlockDefinitionsCache, + per_module_formal_inputs: RefCell>, } struct BlockDefinitions<'a> { - state: Option>, + rc_definitions: RcDefinitions, + parent: Option<&'a BlockDefinitions<'a>>, + cache: BlockDefinitionsCache, } impl<'a> BlockDefinitions<'a> { fn new(parent: &'a BlockDefinitions<'a>) -> Self { Self { - state: Some(BlockDefinitionsState { - rc_definitions: RcDefinitions::default(), - parent, - cache: Default::default(), - }), + rc_definitions: RcDefinitions::default(), + parent: Some(parent), + cache: Default::default(), } } - fn none() -> Self { - Self { state: None } + fn module() -> Self { + Self { + rc_definitions: RcDefinitions::default(), + parent: None, + cache: Default::default(), + } } fn get_or_write_definition( - &mut self, + &self, key: K, field: impl Fn(&BlockDefinitionsCache) -> &RefCell>, write_definition: impl FnOnce(BlockDefinitionsWriter<'_, '_>, &K) -> Result, ) -> Result { - let state = self.state.as_ref().expect("should be some"); - let mut cur_state = state; + let mut current = self; loop { - let field = field(&cur_state.cache).borrow(); + let field = field(¤t.cache).borrow(); if let Some(retval) = field.get(&key) { return Ok(retval.clone()); } - let Some(parent_state) = &cur_state.parent.state else { + let Some(parent) = current.parent else { break; }; - cur_state = parent_state; + current = parent; } let retval = write_definition(BlockDefinitionsWriter { definitions: self }, &key)?; - Ok(field(&self.state.as_ref().expect("should be some").cache) + Ok(field(&self.cache) .borrow_mut() .entry(key) .or_insert(retval) .clone()) } - fn write_out(&mut self, indent: Indent<'_>, out: &mut String) { - self.state - .as_ref() - .expect("should be some") - .rc_definitions - .write_and_clear(indent, out); + fn write_out(&self, indent: Indent<'_>, out: &mut String) { + self.rc_definitions.write_and_clear(indent, out); } } struct BlockDefinitionsWriter<'a, 'b> { - definitions: &'b mut BlockDefinitions<'a>, + definitions: &'b BlockDefinitions<'a>, } impl BlockDefinitionsWriter<'_, '_> { - fn add_definition_line(&mut self, v: impl fmt::Display) { - self.definitions - .state - .as_ref() - .expect("should be some") - .rc_definitions - .add_definition_line(v); + fn add_definition_line(&self, v: impl fmt::Display) { + self.definitions.rc_definitions.add_definition_line(v); } } @@ -467,12 +459,6 @@ impl<'a> std::ops::Deref for BlockDefinitionsWriter<'a, '_> { } } -impl std::ops::DerefMut for BlockDefinitionsWriter<'_, '_> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.definitions - } -} - struct EnumDef { variants: RefCell, body: String, @@ -592,15 +578,19 @@ impl TypeState { } struct ModuleState { + module: Interned>, ns: Namespace, match_arm_values: HashMap, Ident>, + block_definitions: Rc>, } -impl Default for ModuleState { - fn default() -> Self { +impl ModuleState { + fn new(module: Interned>) -> Self { Self { + module, ns: Default::default(), match_arm_values: Default::default(), + block_definitions: Rc::new(BlockDefinitions::module()), } } } @@ -836,6 +826,15 @@ struct FirrtlAnnotation { target: AnnotationTarget, } +struct ResetSourceLocation; + +impl Folder for ResetSourceLocation { + type Error = Infallible; + fn fold_source_location(&mut self, _v: SourceLocation) -> Result { + Ok(SourceLocation::builtin()) + } +} + struct Exporter<'a> { file_backend: &'a mut dyn WrappedFileBackendTrait, indent: Indent<'a>, @@ -968,7 +967,7 @@ impl<'a> Exporter<'a> { &mut self, value: Expr, to_ty: ToTy, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { let from_ty = value.ty(); @@ -1003,7 +1002,7 @@ impl<'a> Exporter<'a> { &mut self, firrtl_cast_fn: Option<&str>, value: Expr, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { let value = self.expr(Expr::canonical(value), definitions, const_ty)?; @@ -1017,7 +1016,7 @@ impl<'a> Exporter<'a> { &mut self, base: Expr, range: Range, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { let base_width = base.ty().width(); @@ -1035,20 +1034,19 @@ impl<'a> Exporter<'a> { fn array_literal_expr( &mut self, expr: ops::ArrayLiteral, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { definitions.get_or_write_definition( (expr, const_ty), |c| &c.array_literal_exprs, - |mut definitions, &(expr, const_ty)| { + |definitions, &(expr, const_ty)| { let ident = self.module.ns.make_new("_array_literal_expr"); let ty_str = self.type_state.ty(expr.ty())?; let const_ = if const_ty { "const " } else { "" }; definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_str}")); for (index, element) in expr.element_values().into_iter().enumerate() { - let element = - self.expr(Expr::canonical(element), &mut definitions, const_ty)?; + let element = self.expr(Expr::canonical(element), &definitions, const_ty)?; definitions .add_definition_line(format_args!("connect {ident}[{index}], {element}")); } @@ -1062,13 +1060,13 @@ impl<'a> Exporter<'a> { fn bundle_literal_expr( &mut self, expr: ops::BundleLiteral, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { definitions.get_or_write_definition( (expr, const_ty), |c| &c.bundle_literal_exprs, - |mut definitions, &(expr, const_ty)| { + |definitions, &(expr, const_ty)| { let ident = self.module.ns.make_new("_bundle_literal_expr"); let ty = expr.ty(); let (ty_ident, bundle_ns) = self.type_state.bundle_def(ty)?; @@ -1090,7 +1088,7 @@ impl<'a> Exporter<'a> { ); let name = bundle_ns.borrow_mut().get(name); let field_value = - self.expr(Expr::canonical(field_value), &mut definitions, const_ty)?; + self.expr(Expr::canonical(field_value), &definitions, const_ty)?; definitions .add_definition_line(format_args!("connect {ident}.{name}, {field_value}")); } @@ -1104,13 +1102,13 @@ impl<'a> Exporter<'a> { fn uninit_expr( &mut self, expr: ops::Uninit, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { definitions.get_or_write_definition( (expr, const_ty), |c| &c.uninit_exprs, - |mut definitions, &(expr, const_ty)| { + |definitions, &(expr, const_ty)| { let ident = self.module.ns.make_new("_uninit_expr"); let ty = expr.ty(); let ty_ident = self.type_state.ty(ty)?; @@ -1124,7 +1122,7 @@ impl<'a> Exporter<'a> { fn enum_literal_expr( &mut self, expr: ops::EnumLiteral, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { let variant_expr = expr @@ -1137,13 +1135,13 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Bundle, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { definitions.get_or_write_definition( (value_str, ty), |c| &c.cast_bundle_to_bits_exprs, - |mut definitions, &(ref value_str, ty)| { + |definitions, &(ref value_str, ty)| { if ty.fields().is_empty() { return Ok("UInt<0>(0)".into()); } @@ -1152,7 +1150,7 @@ impl<'a> Exporter<'a> { return self.expr_cast_to_bits( format!("{value_str}.{field_ident}"), field.ty, - &mut definitions, + &definitions, extra_indent, ); } @@ -1181,7 +1179,7 @@ impl<'a> Exporter<'a> { let field_bits = self.expr_cast_to_bits( format!("{value_str}.{field_ident}"), field.ty, - &mut definitions, + &definitions, extra_indent, )?; definitions.add_definition_line(format_args!( @@ -1210,13 +1208,13 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Enum, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { definitions.get_or_write_definition( (value_str, ty), |c| &c.cast_enum_to_bits_exprs, - |mut definitions, &(ref value_str, ty)| { + |definitions, &(ref value_str, ty)| { if ty.variants().is_empty() { return Ok("UInt<0>(0)".into()); } @@ -1241,7 +1239,7 @@ impl<'a> Exporter<'a> { let variant_bits = self.expr_cast_to_bits( variant_value.to_string(), variant_ty, - &mut definitions, + &definitions, extra_indent, )?; definitions.add_definition_line(format_args!( @@ -1270,13 +1268,13 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Array, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { definitions.get_or_write_definition( (value_str, ty), |c| &c.cast_array_to_bits_exprs, - |mut definitions, &(ref value_str, ty)| { + |definitions, &(ref value_str, ty)| { if ty.is_empty() { return Ok("UInt<0>(0)".into()); } @@ -1284,7 +1282,7 @@ impl<'a> Exporter<'a> { return self.expr_cast_to_bits( value_str.clone() + "[0]", ty.element(), - &mut definitions, + &definitions, extra_indent, ); } @@ -1299,7 +1297,7 @@ impl<'a> Exporter<'a> { let element_bits = self.expr_cast_to_bits( format!("{value_str}[{index}]"), ty.element(), - &mut definitions, + &definitions, extra_indent, )?; definitions.add_definition_line(format_args!( @@ -1328,7 +1326,7 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: CanonicalType, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { match ty.unwrap_transparent_types() { @@ -1357,13 +1355,13 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Bundle, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { definitions.get_or_write_definition( (value_str, ty), |c| &c.cast_bits_to_bundle_exprs, - |mut definitions, &(ref value_str, ty)| { + |definitions, &(ref value_str, ty)| { let (ty_ident, _) = self.type_state.bundle_def(ty)?; let retval = self.module.ns.make_new("_cast_bits_to_bundle_expr"); definitions @@ -1420,7 +1418,7 @@ impl<'a> Exporter<'a> { let field_value = self.expr_cast_bits_to( format!("{flattened_ident}.{flattened_field_ident}"), field.ty, - &mut definitions, + &definitions, extra_indent, )?; definitions.add_definition_line(format_args!( @@ -1435,13 +1433,13 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Enum, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { definitions.get_or_write_definition( (value_str, ty), |c| &c.cast_bits_to_enum_exprs, - |mut definitions, &(ref value_str, ty)| { + |definitions, &(ref value_str, ty)| { let (ty_ident, enum_def) = self.type_state.enum_def(ty)?; let retval = self.module.ns.make_new("_cast_bits_to_enum_expr"); definitions @@ -1457,7 +1455,7 @@ impl<'a> Exporter<'a> { let variant_value = self.expr_cast_bits_to( value_str.clone(), variant_ty, - &mut definitions, + &definitions, extra_indent, )?; definitions.add_definition_line(format_args!( @@ -1507,7 +1505,7 @@ impl<'a> Exporter<'a> { let variant_value = self.expr_cast_bits_to( body_value.clone(), variant_ty, - &mut definitions, + &definitions, extra_indent, )?; definitions.add_definition_line(format_args!( @@ -1530,13 +1528,13 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: Array, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { definitions.get_or_write_definition( (value_str, ty), |c| &c.cast_bits_to_array_exprs, - |mut definitions, &(ref value_str, ty)| { + |definitions, &(ref value_str, ty)| { let retval = self.module.ns.make_new("_cast_bits_to_array_expr"); let array_ty = self.type_state.ty(ty)?; definitions @@ -1565,7 +1563,7 @@ impl<'a> Exporter<'a> { let element_value = self.expr_cast_bits_to( format!("{flattened_ident}[{index}]"), ty.element(), - &mut definitions, + &definitions, extra_indent, )?; definitions.add_definition_line(format_args!( @@ -1580,7 +1578,7 @@ impl<'a> Exporter<'a> { &mut self, value_str: String, ty: CanonicalType, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, extra_indent: Indent<'_>, ) -> Result { match ty.unwrap_transparent_types() { @@ -1603,7 +1601,7 @@ impl<'a> Exporter<'a> { CanonicalType::PhantomConst(ty) => definitions.get_or_write_definition( (value_str, ty), |c| &c.cast_bits_to_phantom_const_exprs, - |mut definitions, &(ref _value_str, _ty)| { + |definitions, &(ref _value_str, _ty)| { let retval = self.module.ns.make_new("_cast_bits_to_phantom_const_expr"); definitions .add_definition_line(format_args!("{extra_indent}wire {retval}: {{}}")); @@ -1620,7 +1618,7 @@ impl<'a> Exporter<'a> { &mut self, func: &str, arg: Expr, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { Ok(format!( @@ -1633,7 +1631,7 @@ impl<'a> Exporter<'a> { func: &str, lhs: Expr, rhs: Expr, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { Ok(format!( @@ -1642,10 +1640,144 @@ impl<'a> Exporter<'a> { rhs = self.expr(Expr::canonical(rhs), definitions, const_ty)?, )) } + #[hdl] + fn expr_formal_input(&mut self, formal_input: FormalInput, const_ty: bool) -> Result { + let definitions = self.module.block_definitions.clone(); + definitions.get_or_write_definition( + (formal_input, const_ty), + |c| &c.per_module_formal_inputs, + |definitions, &(formal_input, const_ty)| match formal_input.kind() { + FormalInputKind::FormalGlobalClock => { + let reg = Reg::new_unchecked( + ScopedNameId(self.module.module.name_id().into(), formal_input.name_id()), + formal_input.source_location(), + Bool, + #[hdl] + ClockDomain { + clk: false.to_clock(), + rst: false.to_sync_reset(), + }, + None, + ); + let module_name = self.global_ns.get(self.module.module.name_id()); + self.targeted_annotations( + module_name, + vec![], + &Vec::from_iter( + [ + SVAttributeAnnotation { + text: "gclk".intern(), + } + .into_annotations(), + DontTouchAnnotation.into_annotations(), + ] + .into_annotations() + .map(|a| { + TargetedAnnotation::new( + Target::from(reg.canonical()).intern_sized(), + a, + ) + }), + ), + )?; + definitions.add_definition_line(self.reg(reg.canonical(), &definitions)?); + self.expr( + Expr::canonical(reg.to_expr().to_clock()), + &definitions, + const_ty, + ) + } + FormalInputKind::FormalReset => { + #[hdl_module(extern)] + fn formal_reset() { + #[hdl] + let rst: SyncReset = m.output(); + m.annotate_module(BlackBoxInlineAnnotation { + path: "fayalite_formal_reset.v".intern(), + text: r"module __fayalite_formal_reset(output rst); + assign rst = $initstate; +endmodule +" + .intern(), + }); + m.verilog_name("__fayalite_formal_reset"); + } + static MOD: OnceLock>> = OnceLock::new(); + let formal_reset = Instance::new_unchecked( + ScopedNameId(self.module.module.name_id().into(), formal_input.name_id()), + *MOD.get_or_init(|| { + let module = formal_reset(); + let Ok(module) = ResetSourceLocation.fold_module(*module); + module.intern_sized() + }), + formal_input.source_location(), + ); + definitions.add_definition_line(self.instance(formal_reset.canonical())?); + self.expr( + Expr::canonical(formal_reset.to_expr().rst), + &definitions, + const_ty, + ) + } + FormalInputKind::AnyConst + | FormalInputKind::AnySeq + | FormalInputKind::AllConst + | FormalInputKind::AllSeq => { + match formal_input.ty() { + CanonicalType::UInt(_) + | CanonicalType::SInt(_) + | CanonicalType::Bool(_) => {} + _ => panic!( + "{}() -- unsupported type: {formal_input:#?}", + formal_input.name() + ), + } + if formal_input.ty().size().is_empty() { + return self.expr(formal_input.ty().uninit(), &definitions, const_ty); + } + let reg = Reg::new_unchecked( + ScopedNameId(self.module.module.name_id().into(), formal_input.name_id()), + formal_input.source_location(), + formal_input.ty(), + #[hdl] + ClockDomain { + clk: false.to_clock(), + rst: false.to_sync_reset(), + }, + None, + ); + let module_name = self.global_ns.get(self.module.module.name_id()); + self.targeted_annotations( + module_name, + vec![], + &Vec::from_iter( + [ + SVAttributeAnnotation { + text: match formal_input.kind() { + FormalInputKind::AnyConst => "anyconst".intern(), + FormalInputKind::AnySeq => "anyseq".intern(), + FormalInputKind::AllConst => "allconst".intern(), + FormalInputKind::AllSeq => "allseq".intern(), + _ => unreachable!(), + }, + } + .into_annotations(), + DontTouchAnnotation.into_annotations(), + ] + .into_annotations() + .map(|a| TargetedAnnotation::new(Target::from(reg).intern_sized(), a)), + ), + )?; + definitions.add_definition_line(self.reg(reg, &definitions)?); + self.expr(Expr::canonical(reg.to_expr()), &definitions, const_ty) + } + }, + ) + } fn expr( &mut self, expr: Expr, - definitions: &mut BlockDefinitions<'_>, + definitions: &BlockDefinitions<'_>, const_ty: bool, ) -> Result { match *Expr::expr_enum(expr) { @@ -2012,6 +2144,10 @@ impl<'a> Exporter<'a> { let port_name = Ident::from(expr.port_name()); Ok(format!("{mem_name}.{port_name}")) } + ExprEnum::FormalInput(expr) => self.expr_formal_input(expr, const_ty), + ExprEnum::SimIoForGlobal(_) => { + unreachable!("Module is known to not contain SimIoForGlobal from validation") + } } } fn write_mem_init( @@ -2126,6 +2262,9 @@ impl<'a> Exporter<'a> { TargetBase::RegAsync(v) => self.module.ns.get(v.name_id()), TargetBase::Wire(v) => self.module.ns.get(v.name_id()), TargetBase::Instance(v) => self.module.ns.get(v.name_id()), + TargetBase::FormalInput(_) | TargetBase::SimIoForGlobal(_) => { + unreachable!("base.is_valid_annotation_target() is known to be false") + } }; Ok(AnnotationTargetRef { base, segments }) } @@ -2237,38 +2376,51 @@ impl<'a> Exporter<'a> { drop(memory_indent); Ok(body) } - fn stmt_reg( + fn reg( &mut self, - stmt_reg: StmtReg, - module_name: Ident, - definitions: &mut BlockDefinitions<'_>, - body: &mut String, - ) -> Result<()> { - let StmtReg { annotations, reg } = stmt_reg; - let indent = self.indent; - self.targeted_annotations(module_name, vec![], &annotations)?; + reg: Reg, + definitions: &BlockDefinitions<'_>, + ) -> Result { let name = self.module.ns.get(reg.name_id()); let ty = self.type_state.ty(reg.ty())?; let clk = self.expr(Expr::canonical(reg.clock_domain().clk), definitions, false)?; if let Some(init) = reg.init() { let rst = self.expr(Expr::canonical(reg.clock_domain().rst), definitions, false)?; let init = self.expr(init, definitions, false)?; - writeln!( - body, - "{indent}regreset {name}: {ty}, {clk}, {rst}, {init}{}", + Ok(format!( + "regreset {name}: {ty}, {clk}, {rst}, {init}{}", FileInfo::new(reg.source_location()), - ) - .unwrap(); + )) } else { - writeln!( - body, - "{indent}reg {name}: {ty}, {clk}{}", + Ok(format!( + "reg {name}: {ty}, {clk}{}", FileInfo::new(reg.source_location()), - ) - .unwrap(); + )) } + } + fn stmt_reg( + &mut self, + stmt_reg: StmtReg, + module_name: Ident, + definitions: &BlockDefinitions<'_>, + body: &mut String, + ) -> Result<()> { + let StmtReg { annotations, reg } = stmt_reg; + let indent = self.indent; + self.targeted_annotations(module_name, vec![], &annotations)?; + writeln!(body, "{indent}{}", self.reg(reg, definitions)?).unwrap(); Ok(()) } + fn instance(&mut self, instance: Instance) -> Result { + let name = self.module.ns.get(instance.name_id()); + let instantiated = instance.instantiated(); + self.add_module(instantiated); + let module_name = self.global_ns.get(instantiated.name_id()); + Ok(format!( + "inst {name} of {module_name}{}", + FileInfo::new(instance.source_location()), + )) + } fn block( &mut self, module: Interned>, @@ -2277,7 +2429,7 @@ impl<'a> Exporter<'a> { parent_definitions: &BlockDefinitions, ) -> Result { let indent = self.indent; - let mut definitions = BlockDefinitions::new(parent_definitions); + let definitions = BlockDefinitions::new(parent_definitions); let mut body = String::new(); let mut out = String::new(); let Block { memories, stmts } = block; @@ -2301,8 +2453,8 @@ impl<'a> Exporter<'a> { ) .unwrap(); } - let lhs = self.expr(lhs, &mut definitions, false)?; - let rhs = self.expr(rhs, &mut definitions, false)?; + let lhs = self.expr(lhs, &definitions, false)?; + let rhs = self.expr(rhs, &definitions, false)?; writeln!( body, "{indent}connect {lhs}, {rhs}{}", @@ -2318,9 +2470,9 @@ impl<'a> Exporter<'a> { text, source_location, }) => { - let clk = self.expr(Expr::canonical(clk), &mut definitions, false)?; - let pred = self.expr(Expr::canonical(pred), &mut definitions, false)?; - let en = self.expr(Expr::canonical(en), &mut definitions, false)?; + let clk = self.expr(Expr::canonical(clk), &definitions, false)?; + let pred = self.expr(Expr::canonical(pred), &definitions, false)?; + let en = self.expr(Expr::canonical(en), &definitions, false)?; let kind = match kind { FormalKind::Assert => "assert", FormalKind::Assume => "assume", @@ -2345,7 +2497,7 @@ impl<'a> Exporter<'a> { let mut when = "when"; let mut pushed_indent; loop { - let cond_str = self.expr(Expr::canonical(cond), &mut definitions, false)?; + let cond_str = self.expr(Expr::canonical(cond), &definitions, false)?; writeln!( body, "{indent}{when} {cond_str}:{}", @@ -2388,7 +2540,7 @@ impl<'a> Exporter<'a> { writeln!( body, "{indent}match {}:{}", - self.expr(Expr::canonical(expr), &mut definitions, false)?, + self.expr(Expr::canonical(expr), &definitions, false)?, FileInfo::new(source_location), ) .unwrap(); @@ -2442,29 +2594,20 @@ impl<'a> Exporter<'a> { .unwrap(); } Stmt::Declaration(StmtDeclaration::Reg(stmt_reg)) => { - self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?; + self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?; } Stmt::Declaration(StmtDeclaration::RegSync(stmt_reg)) => { - self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?; + self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?; } Stmt::Declaration(StmtDeclaration::RegAsync(stmt_reg)) => { - self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?; + self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?; } Stmt::Declaration(StmtDeclaration::Instance(StmtInstance { annotations, instance, })) => { self.targeted_annotations(module_name, vec![], &annotations)?; - let name = self.module.ns.get(instance.name_id()); - let instantiated = instance.instantiated(); - self.add_module(instantiated); - let module_name = self.global_ns.get(instantiated.name_id()); - writeln!( - body, - "{indent}inst {name} of {module_name}{}", - FileInfo::new(instance.source_location()), - ) - .unwrap(); + writeln!(body, "{indent}{}", self.instance(instance)?).unwrap(); } } definitions.write_out(indent, &mut out); @@ -2474,7 +2617,8 @@ impl<'a> Exporter<'a> { Ok(out) } fn module(&mut self, module: Interned>) -> Result { - self.module = ModuleState::default(); + self.module = ModuleState::new(module); + let module_definitions = self.module.block_definitions.clone(); let indent = self.indent; let module_name = self.global_ns.get(module.name_id()); let mut body = String::new(); @@ -2543,12 +2687,10 @@ impl<'a> Exporter<'a> { "extmodule" } ModuleBody::Normal(NormalModuleBody { body: top_block }) => { - body.push_str(&self.block( - module, - top_block, - &module_indent, - &BlockDefinitions::none(), - )?); + let body_str = + self.block(module, top_block, &module_indent, &module_definitions)?; + module_definitions.write_out(indent, &mut body); + body.push_str(&body_str); "module" } }; @@ -2895,7 +3037,7 @@ fn export_impl( seen_modules: HashSet::default(), unwritten_modules: VecDeque::new(), global_ns, - module: ModuleState::default(), + module: ModuleState::new(top_module), type_state: TypeState::default(), circuit_name, annotations: vec![], diff --git a/crates/fayalite/src/formal.rs b/crates/fayalite/src/formal.rs index 17d3122..77ef808 100644 --- a/crates/fayalite/src/formal.rs +++ b/crates/fayalite/src/formal.rs @@ -1,11 +1,189 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information use crate::{ + expr::target::{GetTarget, Target}, int::BoolOrIntType, - intern::{Intern, Interned, Memoize}, + intern::{Intern, Interned}, + module::{NameId, NameIdOrGlobal, ScopedNameId}, prelude::*, }; -use std::sync::OnceLock; +use std::{fmt, sync::OnceLock}; + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub enum FormalInputKind { + FormalGlobalClock, + FormalReset, + AnyConst, + AnySeq, + AllConst, + AllSeq, +} + +impl FormalInputKind { + pub fn fixed_ty(self) -> Option { + match self { + Self::FormalGlobalClock => Some(Clock.into()), + Self::FormalReset => Some(SyncReset.into()), + Self::AnyConst => None, + Self::AnySeq => None, + Self::AllConst => None, + Self::AllSeq => None, + } + } + pub fn fixed_id(self) -> Option { + struct Cache { + formal_global_clock: crate::module::Id, + formal_reset: crate::module::Id, + } + static CACHE: OnceLock = OnceLock::new(); + let cache = || { + CACHE.get_or_init( + #[cold] + || Cache { + formal_global_clock: crate::module::Id::new(), + formal_reset: crate::module::Id::new(), + }, + ) + }; + match self { + Self::FormalGlobalClock => Some(cache().formal_global_clock), + Self::FormalReset => Some(cache().formal_reset), + Self::AnyConst => None, + Self::AnySeq => None, + Self::AllConst => None, + Self::AllSeq => None, + } + } + pub fn fixed_source_location(self) -> Option { + match self { + Self::FormalGlobalClock | Self::FormalReset => Some(SourceLocation::builtin()), + Self::AnyConst | Self::AnySeq | Self::AllConst | Self::AllSeq => None, + } + } + pub fn name(self) -> &'static str { + match self { + Self::FormalGlobalClock => "formal_global_clock", + Self::FormalReset => "formal_reset", + Self::AnyConst => "any_const", + Self::AnySeq => "any_seq", + Self::AllConst => "all_const", + Self::AllSeq => "all_seq", + } + } + pub fn interned_name(self) -> Interned { + macro_rules! impl_interned_name { + ($($variant:ident,)*) => { + match self { + $(Self::$variant => { + static CACHE: OnceLock> = OnceLock::new(); + *CACHE.get_or_init(|| Self::$variant.name().intern()) + })* + } + }; + } + impl_interned_name! { + FormalGlobalClock, + FormalReset, + AnyConst, + AnySeq, + AllConst, + AllSeq, + } + } +} + +#[derive(Clone, PartialEq, Eq, Hash)] +struct FormalInputData { + kind: FormalInputKind, + name_id: NameId, + ty: CanonicalType, + source_location: SourceLocation, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct FormalInput(Interned); + +impl fmt::Debug for FormalInput { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.kind().fixed_ty().is_some() { + f.write_str(&self.name()) + } else { + f.debug_tuple(&self.name()).field(&self.0.ty).finish() + } + } +} + +impl FormalInput { + #[track_caller] + pub fn new( + kind: FormalInputKind, + name_id: NameId, + ty: CanonicalType, + source_location: SourceLocation, + ) -> Self { + let NameId(name, id) = name_id; + assert_eq!(kind.interned_name(), name); + if let Some(fixed_ty) = kind.fixed_ty() { + assert_eq!(ty, fixed_ty); + } else { + assert!( + ty.is_castable_from_bits(), + "{name} type must be castable from bits. got:\n{ty:#?}", + ); + } + if let Some(fixed_source_location) = kind.fixed_source_location() { + assert_eq!(source_location, fixed_source_location); + } + if let Some(fixed_id) = kind.fixed_id() { + assert_eq!(id, fixed_id); + } + Self( + FormalInputData { + kind, + name_id, + ty, + source_location, + } + .intern_sized(), + ) + } + pub fn kind(self) -> FormalInputKind { + self.0.kind + } + pub fn name(self) -> Interned { + self.0.name_id.0 + } + pub fn name_id(self) -> NameId { + self.0.name_id + } + pub fn scoped_name(self) -> ScopedNameId { + ScopedNameId(NameIdOrGlobal::Global, self.name_id()) + } + pub fn source_location(self) -> SourceLocation { + self.0.source_location + } + pub(crate) fn must_connect_to(self) -> bool { + false + } + pub(crate) fn flow(self) -> crate::expr::Flow { + crate::expr::Flow::Source + } +} + +impl ValueType for FormalInput { + type Type = CanonicalType; + type ValueCategory = crate::expr::value_category::ValueCategoryExpr; + + fn ty(&self) -> Self::Type { + self.0.ty + } +} + +impl GetTarget for FormalInput { + fn target(&self) -> Option> { + Some(Target::from(*self).intern_sized()) + } +} #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum FormalKind { @@ -138,110 +316,76 @@ make_formal!( hdl_cover ); -pub trait MakeFormalExpr: Type {} - -impl MakeFormalExpr for T {} - #[hdl] pub fn formal_global_clock() -> Expr { - #[hdl_module(extern)] - fn formal_global_clock() { - #[hdl] - let clk: Clock = m.output(); - m.annotate_module(BlackBoxInlineAnnotation { - path: "fayalite_formal_global_clock.v".intern(), - text: r"module __fayalite_formal_global_clock(output clk); - (* gclk *) - reg clk; -endmodule -" - .intern(), - }); - m.verilog_name("__fayalite_formal_global_clock"); - } - #[hdl] - let formal_global_clock = instance(formal_global_clock()); - formal_global_clock.clk + static CACHE: OnceLock> = OnceLock::new(); + *CACHE.get_or_init(|| { + let kind = FormalInputKind::FormalGlobalClock; + Expr::from_canonical( + FormalInput::new( + kind, + NameId( + kind.interned_name(), + kind.fixed_id().expect("known to have a fixed Id"), + ), + Clock.into(), + kind.fixed_source_location() + .expect("known to have a fixed SourceLocation"), + ) + .to_expr(), + ) + }) } #[hdl] pub fn formal_reset() -> Expr { - #[hdl_module(extern)] - fn formal_reset() { - #[hdl] - let rst: SyncReset = m.output(); - m.annotate_module(BlackBoxInlineAnnotation { - path: "fayalite_formal_reset.v".intern(), - text: r"module __fayalite_formal_reset(output rst); - assign rst = $initstate; -endmodule -" - .intern(), - }); - m.verilog_name("__fayalite_formal_reset"); - } - static MOD: OnceLock>> = OnceLock::new(); - #[hdl] - let formal_reset = instance(*MOD.get_or_init(formal_reset)); - formal_reset.rst + static CACHE: OnceLock> = OnceLock::new(); + *CACHE.get_or_init(|| { + let kind = FormalInputKind::FormalReset; + Expr::from_canonical( + FormalInput::new( + kind, + NameId( + kind.interned_name(), + kind.fixed_id().expect("known to have a fixed Id"), + ), + SyncReset.into(), + kind.fixed_source_location() + .expect("known to have a fixed SourceLocation"), + ) + .to_expr(), + ) + }) } macro_rules! make_any_const_fn { - ($ident:ident, $verilog_attribute:literal) => { + ($ident:ident, $ident_with_loc:ident, $verilog_attribute:literal, $kind:ident) => { + #[track_caller] #[hdl] pub fn $ident(ty: T) -> Expr { - #[hdl_module(extern)] - pub(super) fn $ident(ty: T) { - #[hdl] - let out: T = m.output(ty); - let width = ty.width(); - let verilog_bitslice = if width == 1 { - String::new() - } else { - format!(" [{}:0]", width - 1) - }; - m.annotate_module(BlackBoxInlineAnnotation { - path: Intern::intern_owned(format!( - "fayalite_{}_{width}.v", - stringify!($ident), - )), - text: Intern::intern_owned(format!( - r"module __fayalite_{}_{width}(output{verilog_bitslice} out); - (* {} *) - reg{verilog_bitslice} out; -endmodule -", - stringify!($ident), - $verilog_attribute, - )), - }); - m.verilog_name(format!("__fayalite_{}_{width}", stringify!($ident))); - } - #[derive(Copy, Clone, PartialEq, Eq, Hash)] - struct TheMemoize(T); - impl Memoize for TheMemoize { - type Input = (); - type InputOwned = (); - type Output = Option>>>; - fn inner(self, _input: &Self::Input) -> Self::Output { - if self.0.width() == 0 { - None - } else { - Some($ident(self.0)) - } - } - } - let Some(module) = TheMemoize(ty).get_owned(()) else { - return 0_hdl_u0.cast_bits_to(ty); - }; - #[hdl] - let $ident = instance(module); - $ident.out + $ident_with_loc(ty, SourceLocation::caller()) + } + #[track_caller] + #[hdl] + pub fn $ident_with_loc( + ty: T, + source_location: SourceLocation, + ) -> Expr { + let kind = FormalInputKind::$kind; + Expr::from_canonical( + FormalInput::new( + kind, + NameId(kind.interned_name(), crate::module::Id::new()), + ty.canonical(), + source_location, + ) + .to_expr(), + ) } }; } -make_any_const_fn!(any_const, "anyconst"); -make_any_const_fn!(any_seq, "anyseq"); -make_any_const_fn!(all_const, "allconst"); -make_any_const_fn!(all_seq, "allseq"); +make_any_const_fn!(any_const, any_const_with_loc, "anyconst", AnyConst); +make_any_const_fn!(any_seq, any_seq_with_loc, "anyseq", AnySeq); +make_any_const_fn!(all_const, all_const_with_loc, "allconst", AllConst); +make_any_const_fn!(all_seq, all_seq_with_loc, "allseq", AllSeq); diff --git a/crates/fayalite/src/intern.rs b/crates/fayalite/src/intern.rs index b78aa59..89cc53d 100644 --- a/crates/fayalite/src/intern.rs +++ b/crates/fayalite/src/intern.rs @@ -682,27 +682,62 @@ impl, U: ?Sized> AsRef for Inter #[derive(Clone, Debug)] pub struct InternedSliceIter { - slice: Interned<[T]>, - index: std::ops::Range, + iter: std::iter::Cloned>, +} + +impl Default for InternedSliceIter { + fn default() -> Self { + Self { + iter: [].iter().cloned(), + } + } } impl Iterator for InternedSliceIter { type Item = T; fn next(&mut self) -> Option { - self.index.next().map(|index| self.slice[index].clone()) + self.iter.next() } fn size_hint(&self) -> (usize, Option) { - self.index.size_hint() + self.iter.size_hint() + } + + fn count(self) -> usize { + self.iter.count() + } + + fn last(mut self) -> Option { + self.next_back() + } + + fn nth(&mut self, n: usize) -> Option { + self.iter.nth(n) + } + + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.iter.fold(init, f) } } impl DoubleEndedIterator for InternedSliceIter { fn next_back(&mut self) -> Option { - self.index - .next_back() - .map(|index| self.slice[index].clone()) + self.iter.next_back() + } + + fn nth_back(&mut self, n: usize) -> Option { + self.iter.nth_back(n) + } + + fn rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.iter.rfold(init, f) } } @@ -716,8 +751,7 @@ impl IntoIterator for Interned<[T]> { fn into_iter(self) -> Self::IntoIter { InternedSliceIter { - index: 0..self.len(), - slice: self, + iter: Interned::into_inner(self).iter().cloned(), } } } diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index 86fdd40..2535694 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -727,7 +727,57 @@ impl fmt::Display for NameId { } #[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct ScopedNameId(pub NameId, pub NameId); +pub enum NameIdOrGlobal { + Global, + NameId(NameId), +} + +impl NameIdOrGlobal { + pub fn name_id(self) -> Option { + match self { + Self::Global => None, + Self::NameId(v) => Some(v), + } + } + #[track_caller] + pub fn assert_is_name_id(self) { + match self { + Self::Global => panic!("expected a NameId, got NameIdOrGlobal::Global"), + Self::NameId(_) => {} + } + } + #[track_caller] + pub fn unwrap_name_id(self) -> NameId { + match self { + Self::Global => panic!("expected a NameId, got NameIdOrGlobal::Global"), + Self::NameId(v) => v, + } + } +} + +impl fmt::Debug for NameIdOrGlobal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Display for NameIdOrGlobal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Global => f.write_str("<>"), + Self::NameId(name_id) => fmt::Display::fmt(name_id, f), + } + } +} + +impl From for NameIdOrGlobal { + fn from(value: NameId) -> Self { + Self::NameId(value) + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct ScopedNameId(pub NameIdOrGlobal, pub NameId); impl fmt::Debug for ScopedNameId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -805,7 +855,7 @@ impl Instance { self.containing_module_name_id().0 } pub fn containing_module_name_id(self) -> NameId { - self.scoped_name.0 + self.scoped_name.0.unwrap_name_id() } pub fn name(self) -> Interned { self.name_id().0 @@ -822,11 +872,13 @@ impl Instance { pub fn source_location(self) -> SourceLocation { self.source_location } + #[track_caller] pub fn new_unchecked( scoped_name: ScopedNameId, instantiated: Interned>, source_location: SourceLocation, ) -> Self { + scoped_name.0.assert_is_name_id(); Self { scoped_name, instantiated, @@ -1650,6 +1702,12 @@ struct AssertValidityState { target_states: HashMap, TargetState>, } +enum GetTargetStatesError { + NotFound, + IsGlobal, + FoundSimIoForGlobal(crate::expr::ops::SimIoForGlobal), +} + impl AssertValidityState { fn make_block_index(&mut self, block: Block) -> usize { let retval = self.blocks.len(); @@ -1660,7 +1718,7 @@ impl AssertValidityState { &'a self, target: Target, process_target_state: &dyn Fn(&'a TargetState, bool), - ) -> Result<(), ()> { + ) -> Result<(), GetTargetStatesError> { let mut target = target.unwrap_transparent_types(); loop { break match target { @@ -1713,8 +1771,24 @@ impl AssertValidityState { }; } } - fn get_base_state(&self, target_base: Interned) -> Result<&TargetState, ()> { - self.target_states.get(&target_base).ok_or(()) + fn get_base_state( + &self, + target_base: Interned, + ) -> Result<&TargetState, GetTargetStatesError> { + match *target_base { + TargetBase::ModuleIO(_) + | TargetBase::MemPort(_) + | TargetBase::Reg(_) + | TargetBase::RegSync(_) + | TargetBase::RegAsync(_) + | TargetBase::Wire(_) + | TargetBase::Instance(_) => self + .target_states + .get(&target_base) + .ok_or(GetTargetStatesError::NotFound), + TargetBase::FormalInput(_) => Err(GetTargetStatesError::IsGlobal), + TargetBase::SimIoForGlobal(v) => Err(GetTargetStatesError::FoundSimIoForGlobal(v)), + } } #[track_caller] fn insert_new_base(&mut self, target_base: Interned, declared_in_block: usize) { @@ -1807,13 +1881,26 @@ impl AssertValidityState { let result = self.get_target_states(*target, &|target_state, exact_target_unknown| { Self::set_connect_target_written(target_state, is_lhs, block, exact_target_unknown); }); - if result.is_err() { - if is_lhs { - panic!("at {source_location}: tried to connect to not-yet-defined item: {target}"); - } else { + match result { + Ok(()) => {} + Err(GetTargetStatesError::NotFound) => { + if is_lhs { + panic!( + "at {source_location}: tried to connect to not-yet-defined item: {target}" + ); + } else { + panic!( + "at {source_location}: tried to connect from not-yet-defined item: {target}" + ); + } + } + Err(GetTargetStatesError::IsGlobal) => { + // no error + } + Err(GetTargetStatesError::FoundSimIoForGlobal(v)) => { panic!( - "at {source_location}: tried to connect from not-yet-defined item: {target}" - ); + "at {source_location}: fayalite::expr::ops::SimIoForGlobal is not allowed in Modules: {v:?}" + ) } } } @@ -2118,7 +2205,8 @@ impl transform::visit::Visitor for AssertExprValidity<'_> { | ExprEnum::CastToBits(_) | ExprEnum::CastBitsTo(_) | ExprEnum::ToTraceAsString(_) - | ExprEnum::TraceAsStringAsInner(_) => v.default_visit(self), + | ExprEnum::TraceAsStringAsInner(_) + | ExprEnum::FormalInput(_) => v.default_visit(self), ExprEnum::VariantAccess(_) | ExprEnum::ModuleIO(_) | ExprEnum::Instance(_) @@ -2134,6 +2222,7 @@ impl transform::visit::Visitor for AssertExprValidity<'_> { Err(InvalidExpr::ExprIsNotVisible(v.to_expr())) } } + ExprEnum::SimIoForGlobal(_) => Err(InvalidExpr::ExprIsNotVisible(v.to_expr())), } } } @@ -2369,7 +2458,7 @@ impl RegBuilder>, Option>, T> ty, } = self; ModuleBuilder::with(|module_builder| { - let scoped_name = ScopedNameId(module_builder.name, NameId(name, Id::new())); + let scoped_name = ScopedNameId(module_builder.name.into(), NameId(name, Id::new())); let reg = Reg::new_unchecked(scoped_name, source_location, ty, clock_domain, init); let retval = reg.to_expr(); // convert before borrow_mut since ModuleBuilder could be reentered by T::canonical() @@ -2765,6 +2854,9 @@ pub fn annotate(target: Expr, annotations: impl IntoAnnotations) { instance, } .into(), + TargetBase::FormalInput(_) | TargetBase::SimIoForGlobal(_) => { + unreachable!("not a valid annotation target") + } }; ModuleBuilder::with(|m| { unwrap!(m.impl_.borrow_mut().body.builder_normal_body_opt()) @@ -2779,7 +2871,7 @@ pub fn annotate(target: Expr, annotations: impl IntoAnnotations) { #[track_caller] pub fn wire_with_loc(name: &str, source_location: SourceLocation, ty: T) -> Expr { ModuleBuilder::with(|m| { - let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new())); + let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new())); let wire = Wire::::new_unchecked(scoped_name, source_location, ty); let retval = wire.to_expr(); let canonical_wire = wire.canonical(); @@ -2811,7 +2903,7 @@ fn incomplete_declaration( source_location: SourceLocation, ) -> Rc> { ModuleBuilder::with(|m| { - let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new())); + let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new())); let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete { name: scoped_name, source_location, @@ -2987,7 +3079,7 @@ pub fn instance_with_loc( source_location: SourceLocation, ) -> Expr { ModuleBuilder::with(|m| { - let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new())); + let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new())); let instance = Instance:: { scoped_name, instantiated, @@ -3026,7 +3118,7 @@ fn memory_impl( source_location: SourceLocation, ) -> MemBuilder { ModuleBuilder::with(|m| { - let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new())); + let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new())); let (retval, target_mem) = MemBuilder::new(scoped_name, source_location, mem_element_type); let mut impl_ = m.impl_.borrow_mut(); let body = impl_.body.builder_normal_body(); @@ -3181,7 +3273,7 @@ impl ModuleIO { NameId(self.bundle_field.name, self.id) } pub fn scoped_name(&self) -> ScopedNameId { - ScopedNameId(self.containing_module_name, self.name_id()) + ScopedNameId(self.containing_module_name.into(), self.name_id()) } pub fn source_location(&self) -> SourceLocation { self.source_location @@ -3254,10 +3346,102 @@ impl fmt::Debug for InstantiatedModule { } } +#[derive(PartialEq, Eq, Hash, Clone, Copy)] +pub enum InstantiatedModuleOrGlobal { + Global, + InstantiatedModule(InstantiatedModule), +} + +impl InstantiatedModuleOrGlobal { + pub fn leaf_module_source_location(self) -> SourceLocation { + match self { + Self::Global => SourceLocation::builtin(), + Self::InstantiatedModule(v) => v.leaf_module().source_location(), + } + } +} + +impl From for InstantiatedModuleOrGlobal { + fn from(value: InstantiatedModule) -> Self { + Self::InstantiatedModule(value) + } +} + +impl fmt::Debug for InstantiatedModuleOrGlobal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Global => f.write_str("Global"), + Self::InstantiatedModule(v) => v.fmt(f), + } + } +} + #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub struct TargetInInstantiatedModule { - pub instantiated_module: InstantiatedModule, - pub target: Target, +pub struct TargetInInstantiatedModuleOrGlobal { + instantiated_module_or_global: InstantiatedModuleOrGlobal, + target: Target, +} + +impl TargetInInstantiatedModuleOrGlobal { + #[track_caller] + pub fn new(instantiated_module_or_global: InstantiatedModuleOrGlobal, target: Target) -> Self { + match ( + instantiated_module_or_global, + target.base().target_name().0.0, + ) { + (InstantiatedModuleOrGlobal::Global, NameIdOrGlobal::Global) + | (InstantiatedModuleOrGlobal::InstantiatedModule(_), NameIdOrGlobal::NameId(_)) => { + Self { + instantiated_module_or_global, + target, + } + } + (InstantiatedModuleOrGlobal::Global, NameIdOrGlobal::NameId(_)) + | (InstantiatedModuleOrGlobal::InstantiatedModule(_), NameIdOrGlobal::Global) => { + panic!( + "instantiated_module_or_global doesn't match target.base().target_name().0.0:\n\ + instantiated_module_or_global: {instantiated_module_or_global:?}\n\ + target: {target:?}" + ) + } + } + } + #[track_caller] + pub fn from_target( + instantiated_module: impl Into, + target: Target, + ) -> Self { + let instantiated_module = instantiated_module.into(); + Self { + instantiated_module_or_global: match target.base().target_name().0.0 { + NameIdOrGlobal::Global => InstantiatedModuleOrGlobal::Global, + NameIdOrGlobal::NameId(name_id) => { + let InstantiatedModuleOrGlobal::InstantiatedModule(instantiated_module) = + instantiated_module + else { + panic!( + "target is in a module, but no InstantiatedModule was provided: {target:#?}" + ); + }; + assert_eq!( + name_id, + instantiated_module.leaf_module().name_id(), + "target isn't contained in module:\n\ + target: {target:#?}\n\ + instantiated_module: {instantiated_module:?}", + ); + InstantiatedModuleOrGlobal::InstantiatedModule(instantiated_module) + } + }, + target, + } + } + pub fn instantiated_module_or_global(self) -> InstantiatedModuleOrGlobal { + self.instantiated_module_or_global + } + pub fn target(self) -> Target { + self.target + } } #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] diff --git a/crates/fayalite/src/module/transform/deduce_resets.rs b/crates/fayalite/src/module/transform/deduce_resets.rs index 4595e84..611401b 100644 --- a/crates/fayalite/src/module/transform/deduce_resets.rs +++ b/crates/fayalite/src/module/transform/deduce_resets.rs @@ -1215,6 +1215,10 @@ impl RunPass

for ExprEnum { ExprEnum::RegSync(expr) => reg_expr_run_pass(expr, pass_args), ExprEnum::RegAsync(expr) => reg_expr_run_pass(expr, pass_args), ExprEnum::MemPort(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), + ExprEnum::FormalInput(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)), + ExprEnum::SimIoForGlobal(_) => { + unreachable!("Module is known to not contain SimIoForGlobal from validation") + } } } } @@ -1932,6 +1936,7 @@ impl_run_pass_copy!([] SVAttributeAnnotation); impl_run_pass_copy!([] UInt); impl_run_pass_copy!([] usize); impl_run_pass_copy!([] FormalKind); +impl_run_pass_copy!([] crate::formal::FormalInput); impl_run_pass_copy!([] PhantomConst); macro_rules! impl_run_pass_for_struct { @@ -2248,6 +2253,12 @@ impl RunPass

for TargetBase { &TargetBase::RegAsync(v) => v.into(), TargetBase::Wire(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Wire)), TargetBase::Instance(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Instance)), + TargetBase::FormalInput(v) => { + return Ok(v.run_pass(pass_args)?.map(TargetBase::FormalInput)); + } + TargetBase::SimIoForGlobal(_) => { + unreachable!("Module is known to not contain SimIoForGlobal from validation") + } }; Ok(reg.run_pass(pass_args)?.map(|reg| match reg { AnyReg::Reg(reg) => TargetBase::Reg(reg), diff --git a/crates/fayalite/src/module/transform/simplify_enums.rs b/crates/fayalite/src/module/transform/simplify_enums.rs index c52939c..280701d 100644 --- a/crates/fayalite/src/module/transform/simplify_enums.rs +++ b/crates/fayalite/src/module/transform/simplify_enums.rs @@ -101,7 +101,7 @@ struct ModuleState { impl ModuleState { fn gen_name(&mut self, name: &str) -> ScopedNameId { - ScopedNameId(self.module_name, NameId(name.intern(), Id::new())) + ScopedNameId(self.module_name.into(), NameId(name.intern(), Id::new())) } } @@ -824,7 +824,9 @@ impl Folder for State { | ExprEnum::Wire(_) | ExprEnum::Reg(_) | ExprEnum::RegSync(_) - | ExprEnum::RegAsync(_) => op.default_fold(self)?, + | ExprEnum::RegAsync(_) + | ExprEnum::FormalInput(_) + | ExprEnum::SimIoForGlobal(_) => op.default_fold(self)?, }; self.module_state_stack .last_mut() diff --git a/crates/fayalite/src/module/transform/visit.rs b/crates/fayalite/src/module/transform/visit.rs index 7b4cd2a..17fd88c 100644 --- a/crates/fayalite/src/module/transform/visit.rs +++ b/crates/fayalite/src/module/transform/visit.rs @@ -18,13 +18,13 @@ use crate::{ TargetPathTraceAsStringInner, }, }, - formal::FormalKind, + formal::{FormalInput, FormalInputKind, FormalKind}, int::{Bool, SIntType, SIntValue, Size, UIntType, UIntValue}, intern::{Intern, Interned}, memory::{Mem, MemPort, PortKind, PortName, PortType, ReadUnderWrite}, module::{ AnnotatedModuleIO, Block, BlockId, ExternModuleBody, ExternModuleParameter, - ExternModuleParameterValue, Instance, Module, ModuleBody, ModuleIO, NameId, + ExternModuleParameterValue, Instance, Module, ModuleBody, ModuleIO, NameId, NameIdOrGlobal, NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire, }, @@ -482,4 +482,30 @@ impl, State: ?Sized + Visitor> Visit for &'_ mut } } +impl Visit for NameIdOrGlobal { + fn visit(&self, state: &mut State) -> Result<(), ::Error> { + state.visit_name_id_or_global(self) + } + + fn default_visit(&self, state: &mut State) -> Result<(), ::Error> { + match self { + Self::Global => Ok(()), + Self::NameId(name_id) => name_id.visit(state), + } + } +} + +impl Fold for NameIdOrGlobal { + fn fold(self, state: &mut State) -> Result::Error> { + state.fold_name_id_or_global(self) + } + + fn default_fold(self, state: &mut State) -> Result::Error> { + match self { + Self::Global => Ok(Self::Global), + Self::NameId(name_id) => Ok(Self::NameId(name_id.fold(state)?)), + } + } +} + include!(concat!(env!("OUT_DIR"), "/visit.rs")); diff --git a/crates/fayalite/src/prelude.rs b/crates/fayalite/src/prelude.rs index cebbddd..69feeb5 100644 --- a/crates/fayalite/src/prelude.rs +++ b/crates/fayalite/src/prelude.rs @@ -16,8 +16,8 @@ pub use crate::{ ReduceBits, ToExpr, ToTraceAsString, ValueType, repeat, }, formal::{ - MakeFormalExpr, all_const, all_seq, any_const, any_seq, formal_global_clock, formal_reset, - hdl_assert, hdl_assert_with_enable, hdl_assume, hdl_assume_with_enable, hdl_cover, + all_const, all_seq, any_const, any_seq, formal_global_clock, formal_reset, hdl_assert, + hdl_assert_with_enable, hdl_assume, hdl_assume_with_enable, hdl_cover, hdl_cover_with_enable, }, hdl, hdl_module, diff --git a/crates/fayalite/src/reg.rs b/crates/fayalite/src/reg.rs index 7f50655..2e4ab16 100644 --- a/crates/fayalite/src/reg.rs +++ b/crates/fayalite/src/reg.rs @@ -79,6 +79,7 @@ impl Reg { if let Some(init) = init { assert_eq!(ty, init.ty(), "register's type must match init type"); } + scoped_name.0.assert_is_name_id(); Self { name: scoped_name, source_location, @@ -94,7 +95,7 @@ impl Reg { self.containing_module_name_id().0 } pub fn containing_module_name_id(&self) -> NameId { - self.name.0 + self.name.0.unwrap_name_id() } pub fn name(&self) -> Interned { self.name_id().0 diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index 1247fd8..3bd8466 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -6,26 +6,29 @@ use crate::{ bundle::{BundleField, BundleType}, expr::{ - Flow, + ExprEnum, Flow, + ops::SimIoForGlobal, target::{ - GetTarget, Target, TargetPathArrayElement, TargetPathBundleField, TargetPathElement, - TargetPathTraceAsStringInner, + GetTarget, Target, TargetBase, TargetChild, TargetPathArrayElement, + TargetPathBundleField, TargetPathElement, TargetPathTraceAsStringInner, }, }, + formal::FormalInput, int::BoolOrIntType, intern::{ - Intern, InternSlice, Interned, InternedCompare, PtrEqWithTypeId, SupportsPtrEqWithTypeId, + Intern, InternSlice, Interned, InternedCompare, InternedSliceIter, Memoize, + PtrEqWithTypeId, SupportsPtrEqWithTypeId, }, module::{ - ModuleIO, + ModuleIO, StmtFormal, transform::visit::{Fold, Folder, Visit, Visitor}, }, prelude::*, reset::ResetType, sim::{ compiler::{ - Compiled, CompiledBundleField, CompiledExternModule, CompiledTypeLayoutBody, - CompiledValue, ExternModuleClockForPast, + Compiled, CompiledAssert, CompiledBundleField, CompiledExternModule, + CompiledTypeLayoutBody, CompiledValue, ExternModuleClockForPast, }, interpreter::{ BreakAction, BreakpointsSet, RunResult, SmallUInt, State, @@ -50,7 +53,7 @@ use std::{ any::Any, cell::{Cell, RefCell}, collections::{BTreeMap, BTreeSet}, - fmt, + fmt::{self, Write}, future::{Future, IntoFuture}, hash::Hash, mem, @@ -315,6 +318,14 @@ impl_trace_decl! { ty: CanonicalType, flow: Flow, }), + FormalInput(TraceFormalInput { + fn children(self) -> _ { + [*self.child].intern_slice() + } + name: Interned, + child: Interned, + formal_input: FormalInput, + }), Bundle(TraceBundle { fn children(self) -> _ { self.fields @@ -1288,9 +1299,14 @@ impl SimulationModuleState { #[track_caller] fn get_io( &self, - mut target: Target, - which_module: WhichModule, + target: &mut Interned, + which_module: WhichModule<'_>, ) -> CompiledValue { + match which_module { + WhichModule::Main { global_io } => *target = global_io.to_sim_io_target(*target), + WhichModule::Extern { .. } => {} + } + let mut target = **target; assert!( target.canonical_ty().is_passive(), "simulator read/write expression must have a passive type \ @@ -1317,9 +1333,9 @@ impl SimulationModuleState { }; } match which_module { - WhichModule::Main => panic!( + WhichModule::Main { .. } => panic!( "simulator read/write expression must be \ - an array element/field of `Simulation::io()`" + an array element/field of `Simulation::io()` or `Simulation::global_io()`" ), WhichModule::Extern { .. } => panic!( "simulator read/write expression must be \ @@ -1329,18 +1345,18 @@ impl SimulationModuleState { } } #[track_caller] - fn is_reset_async(&self, io: Expr, which_module: WhichModule) -> bool { - let Some(target) = io.target() else { + fn is_reset_async(&self, io: Expr, which_module: WhichModule<'_>) -> bool { + let Some(mut target) = io.target() else { match which_module { - WhichModule::Main => panic!( - "can't read from an expression that's not a field/element of `Simulation::io()`" + WhichModule::Main { .. } => panic!( + "can't read from an expression that's not a field/element of `Simulation::io()` or `Simulation::global_io()`" ), WhichModule::Extern { .. } => panic!( "can't read from an expression that's not based on one of this module's inputs/outputs" ), } }; - match self.get_io(*target, which_module).layout.ty { + match self.get_io(&mut target, which_module).layout.ty { CanonicalType::UInt(_) | CanonicalType::SInt(_) | CanonicalType::Bool(_) @@ -1360,24 +1376,24 @@ impl SimulationModuleState { fn read_helper_current( &self, io: Expr, - which_module: WhichModule, + which_module: WhichModule<'_>, ) -> MaybeNeedsSettle> { - let Some(target) = io.target() else { + let Some(mut target) = io.target() else { match which_module { - WhichModule::Main => panic!( - "can't read from an expression that's not a field/element of `Simulation::io()`" + WhichModule::Main { .. } => panic!( + "can't read from an expression that's not a field/element of `Simulation::io()` or `Simulation::global_io()`" ), WhichModule::Extern { .. } => panic!( "can't read from an expression that's not based on one of this module's inputs/outputs" ), } }; - let compiled_value = self.get_io(*target, which_module); + let compiled_value = self.get_io(&mut target, which_module); match target.flow() { Flow::Source => { if !self.uninitialized_ios.is_empty() { match which_module { - WhichModule::Main => { + WhichModule::Main { .. } => { panic!( "can't read from an output before initializing all inputs\nuninitialized_ios={:#?}", SortedSetDebug(&self.uninitialized_ios), @@ -1396,7 +1412,9 @@ impl SimulationModuleState { Flow::Sink => { if self.uninitialized_ios.contains_key(&*target) { match which_module { - WhichModule::Main => panic!("can't read from an uninitialized input"), + WhichModule::Main { .. } => { + panic!("can't read from an uninitialized input") + } WhichModule::Extern { .. } => { panic!("can't read from an uninitialized output"); } @@ -1412,7 +1430,7 @@ impl SimulationModuleState { &self, io: Expr, read_time: ReadTime, - which_module: WhichModule, + which_module: WhichModule<'_>, ) -> MaybeNeedsSettle> { match read_time { ReadTime::Current => self.read_helper_current(io, which_module), @@ -1438,22 +1456,22 @@ impl SimulationModuleState { fn write_helper( &mut self, io: Expr, - which_module: WhichModule, + which_module: WhichModule<'_>, ) -> CompiledValue { - let Some(target) = io.target() else { + let Some(mut target) = io.target() else { match which_module { - WhichModule::Main => panic!( - "can't write to an expression that's not a field/element of `Simulation::io()`" + WhichModule::Main { .. } => panic!( + "can't write to an expression that's not a field/element of `Simulation::io()` or `Simulation::global_io()`" ), WhichModule::Extern { .. } => panic!( "can't write to an expression that's not based on one of this module's outputs" ), } }; - let compiled_value = self.get_io(*target, which_module); + let compiled_value = self.get_io(&mut target, which_module); match target.flow() { Flow::Source => match which_module { - WhichModule::Main => panic!("can't write to an output"), + WhichModule::Main { .. } => panic!("can't write to an output"), WhichModule::Extern { .. } => panic!("can't write to an input"), }, Flow::Sink => {} @@ -1573,9 +1591,9 @@ impl fmt::Debug for SimulationExternModuleState { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -enum WhichModule { - Main, +#[derive(Copy, Clone)] +enum WhichModule<'a> { + Main { global_io: &'a SimulationGlobalIo }, Extern { module_index: usize }, } @@ -1986,6 +2004,7 @@ impl SensitivitySet { struct SimulationImpl { state: interpreter::State, io: Expr, + global_io: SimulationGlobalIo, main_module: SimulationModuleState, extern_modules: Box<[SimulationExternModuleState]>, trace_decls: TraceModule, @@ -2005,6 +2024,7 @@ struct SimulationImpl { >, waiting_sensitivity_sets_by_address: HashMap<*const SensitivitySet, Rc>, trace_as_string_buf: String, + asserts: Interned<[CompiledAssert]>, } impl fmt::Debug for SimulationImpl { @@ -2082,6 +2102,7 @@ impl SimulationImpl { let Self { state, io: self_io, + global_io, main_module, extern_modules, trace_decls, @@ -2095,10 +2116,15 @@ impl SimulationImpl { waiting_sensitivity_sets_by_compiled_value, waiting_sensitivity_sets_by_address, trace_as_string_buf: _, + asserts, } = self; f.debug_struct("Simulation") .field("state", state) .field("io", io.unwrap_or(self_io)) + .field( + "global_io", + &fmt::from_fn(|f| f.debug_map().entries(global_io.global_io).finish()), + ) .field("main_module", main_module) .field("extern_modules", extern_modules) .field("trace_decls", trace_decls) @@ -2118,6 +2144,7 @@ impl SimulationImpl { "waiting_sensitivity_sets_by_compiled_value", &DebugSensitivitySetsByCompiledValue(waiting_sensitivity_sets_by_compiled_value), ) + .field("asserts", asserts) .finish_non_exhaustive() } fn new(compiled: Compiled) -> Self { @@ -2160,22 +2187,29 @@ impl SimulationImpl { Self { state: State::new(compiled.insns), io: compiled.io.to_expr(), + global_io: SimulationGlobalIo::new(compiled.global_io), main_module: SimulationModuleState::new( compiled - .io - .ty() - .fields() - .into_iter() - .zip(compiled.base_module.module_io) - .map(|(BundleField { name, .. }, value)| { - ( - io_target.join( - TargetPathElement::from(TargetPathBundleField { name }) - .intern_sized(), - ), - value, - ) - }), + .global_io + .iter() + .map(|&(global_io, value)| (global_io.into(), value)) + .chain( + compiled + .io + .ty() + .fields() + .into_iter() + .zip(compiled.base_module.module_io) + .map(|(BundleField { name, .. }, value)| { + ( + io_target.join( + TargetPathElement::from(TargetPathBundleField { name }) + .intern_sized(), + ), + value, + ) + }), + ), &[], ), extern_modules, @@ -2202,6 +2236,7 @@ impl SimulationImpl { waiting_sensitivity_sets_by_compiled_value: HashMap::default(), waiting_sensitivity_sets_by_address: HashMap::default(), trace_as_string_buf: String::with_capacity(256), + asserts: compiled.asserts, } } fn write_traces( @@ -2729,6 +2764,50 @@ impl SimulationImpl { self.cancel_wake_after_change(&sensitivity_set); } } + #[track_caller] + #[cold] + fn handle_failed_asserts(&mut self, assert_failed_log: Vec) -> ! { + let mut message = format!( + "Assertions/Assumptions failed at time {:?}:\n", + self.event_queue.lock().instant, + ); + for assert_failed_index in assert_failed_log { + let CompiledAssert { + instantiated_module, + stmt_formal: + StmtFormal { + kind, + clk: _, + pred: _, + en: _, + text, + source_location, + }, + } = self.asserts[assert_failed_index]; + writeln!( + message, + "at {source_location}: in {instantiated_module:?}: {} failed: {text}", + kind.as_str() + ) + .unwrap(); + } + panic!("{message}") + } + #[track_caller] + fn check_for_failed_asserts(&mut self) { + if self.state.assert_failed_log.is_empty() { + return; + } + if let Some(Event { + instant: _, + kind: EventKind::State, + }) = self.event_queue.peek_first_event_for_now() + { + return; + } + let assert_failed_log = mem::take(&mut self.state.assert_failed_log); + self.handle_failed_asserts(assert_failed_log); + } fn write_traces_after_event(&mut self) { if let Some(Event { instant: _, @@ -2831,6 +2910,7 @@ impl SimulationImpl { } } this.write_traces_after_event(); + this.check_for_failed_asserts(); this.check_waiting_sensitivity_sets(); } else { event_queue = first_entry.into_event_queue_lock(); @@ -2852,18 +2932,23 @@ impl SimulationImpl { fn settle(this_ref: &Rc>) { Self::run_until(this_ref, &mut Some); } - fn get_module(&self, which_module: WhichModule) -> &SimulationModuleState { + fn get_module(&self, which_module: WhichModule<'_>) -> &SimulationModuleState { match which_module { - WhichModule::Main => &self.main_module, + WhichModule::Main { .. } => &self.main_module, WhichModule::Extern { module_index } => &self.extern_modules[module_index].module_state, } } - fn get_module_mut(&mut self, which_module: WhichModule) -> &mut SimulationModuleState { + fn get_module_mut_and_which_module( + &mut self, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, + ) -> (&mut SimulationModuleState, WhichModule<'_>) { + let which_module = which_module(&self.global_io); match which_module { - WhichModule::Main => &mut self.main_module, - WhichModule::Extern { module_index } => { - &mut self.extern_modules[module_index].module_state - } + WhichModule::Main { .. } => (&mut self.main_module, which_module), + WhichModule::Extern { module_index } => ( + &mut self.extern_modules[module_index].module_state, + which_module, + ), } } #[track_caller] @@ -2871,18 +2956,23 @@ impl SimulationImpl { &mut self, io: Expr, read_time: ReadTime, - which_module: WhichModule, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, ) -> MaybeNeedsSettle { + let which_module = which_module(&self.global_io); self.get_module(which_module) .read_helper(Expr::canonical(io), read_time, which_module) .map(|compiled_value| ReadBitFn { compiled_value }) .apply_no_settle(&mut self.state) } #[track_caller] - fn write_bit(&mut self, io: Expr, value: bool, which_module: WhichModule) { - let compiled_value = self - .get_module_mut(which_module) - .write_helper(io, which_module); + fn write_bit( + &mut self, + io: Expr, + value: bool, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, + ) { + let (module, which_module) = self.get_module_mut_and_which_module(which_module); + let compiled_value = module.write_helper(io, which_module); self.event_queue.add_event_for_now(EventKind::State); match compiled_value.range.len().as_single() { Some(TypeLenSingle::SmallSlot) => { @@ -2900,8 +2990,9 @@ impl SimulationImpl { &mut self, io: Expr, read_time: ReadTime, - which_module: WhichModule, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, ) -> MaybeNeedsSettle, I::Value> { + let which_module = which_module(&self.global_io); self.get_module(which_module) .read_helper(Expr::canonical(io), read_time, which_module) .map(|compiled_value| ReadBoolOrIntFn { compiled_value, io }) @@ -2912,11 +3003,10 @@ impl SimulationImpl { &mut self, io: Expr, value: I::Value, - which_module: WhichModule, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, ) { - let compiled_value = self - .get_module_mut(which_module) - .write_helper(Expr::canonical(io), which_module); + let (module, which_module) = self.get_module_mut_and_which_module(which_module); + let compiled_value = module.write_helper(Expr::canonical(io), which_module); self.event_queue.add_event_for_now(EventKind::State); let value: BigInt = value.into(); match compiled_value.range.len().as_single() { @@ -3148,7 +3238,12 @@ impl SimulationImpl { any_change.get() } #[track_caller] - fn is_reset_async(&self, io: Expr, which_module: WhichModule) -> bool { + fn is_reset_async( + &self, + io: Expr, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, + ) -> bool { + let which_module = which_module(&self.global_io); self.get_module(which_module) .is_reset_async(io, which_module) } @@ -3157,11 +3252,12 @@ impl SimulationImpl { &mut self, io: Expr, read_time: ReadTime, - which_module: WhichModule, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, ) -> ( CompiledValue, MaybeNeedsSettle>, ) { + let which_module = which_module(&self.global_io); let compiled_value = self .get_module(which_module) .read_helper(io, read_time, which_module); @@ -3189,11 +3285,10 @@ impl SimulationImpl { &mut self, io: Expr, value: &SimValue, - which_module: WhichModule, + which_module: impl for<'a> Fn(&'a SimulationGlobalIo) -> WhichModule<'a>, ) { - let compiled_value = self - .get_module_mut(which_module) - .write_helper(io, which_module); + let (module, which_module) = self.get_module_mut_and_which_module(which_module); + let compiled_value = module.write_helper(io, which_module); self.event_queue.add_event_for_now(EventKind::State); assert_eq!(io.ty(), value.ty()); Self::read_write_sim_value_helper( @@ -3370,6 +3465,318 @@ impl Drop for SimulationImpl { } } +#[derive(Clone)] +pub struct SimulationGlobalIo { + global_io: Interned<[(SimIoForGlobal, CompiledValue)]>, + global_io_map: Rc>, +} + +impl Default for SimulationGlobalIo { + fn default() -> Self { + Self { + global_io: Interned::default(), + global_io_map: Rc::default(), + } + } +} + +impl fmt::Debug for SimulationGlobalIo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_map().entries(self.global_io).finish() + } +} + +impl SimulationGlobalIo { + fn new(global_io: Interned<[(SimIoForGlobal, CompiledValue)]>) -> Self { + Self { + global_io, + global_io_map: Rc::new(HashMap::from_iter( + global_io + .iter() + .enumerate() + .map(|(index, &(global, _))| (global, index)), + )), + } + } + #[must_use] + pub fn iter(&self) -> SimulationGlobalIoIter { + SimulationGlobalIoIter { + global_io: self.global_io.into_iter(), + } + } + #[must_use] + pub fn globals(&self) -> SimulationGlobalIoGlobalsIter { + SimulationGlobalIoGlobalsIter { + global_io: self.global_io.into_iter(), + } + } + #[must_use] + pub fn exprs(&self) -> SimulationGlobalIoExprsIter { + SimulationGlobalIoExprsIter { + global_io: self.global_io.into_iter(), + } + } + #[must_use] + pub fn len(&self) -> usize { + self.global_io.len() + } + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + #[must_use] + pub fn contains(&self, global: FormalInput) -> bool { + self.global_io_map + .contains_key(&SimIoForGlobal::new(global)) + } + #[must_use] + pub fn get(&self, global: FormalInput) -> Option> { + self.contains(global) + .then(|| SimIoForGlobal::new(global).to_expr()) + } + #[must_use] + pub fn expr_to_global(&self, expr: Expr) -> Option { + let global = match *Expr::expr_enum(expr) { + ExprEnum::FormalInput(global) => global, + ExprEnum::SimIoForGlobal(expr) => expr.global(), + _ => return None, + }; + self.global_io_map + .contains_key(&SimIoForGlobal::new(global)) + .then_some(global) + } + #[must_use] + fn to_sim_io_target(&self, target: Interned) -> Interned { + #[derive(Copy, Clone, PartialEq, Eq, Hash)] + struct FormalInputExprToSimIoExpr; + impl Memoize for FormalInputExprToSimIoExpr { + type Input = Interned; + type InputOwned = Interned; + type Output = Interned; + + fn inner(self, input: &Self::Input) -> Self::Output { + match **input { + Target::Base(base) => match *base { + TargetBase::ModuleIO(_) + | TargetBase::MemPort(_) + | TargetBase::Reg(_) + | TargetBase::RegSync(_) + | TargetBase::RegAsync(_) + | TargetBase::Wire(_) + | TargetBase::Instance(_) + | TargetBase::SimIoForGlobal(_) => *input, + TargetBase::FormalInput(global) => { + Target::from(SimIoForGlobal::new(global)).intern() + } + }, + Target::Child(child) => Target::Child(TargetChild::new( + self.get_owned(child.parent()), + child.path_element(), + )) + .intern_sized(), + } + } + } + match *target.base() { + TargetBase::ModuleIO(_) + | TargetBase::MemPort(_) + | TargetBase::Reg(_) + | TargetBase::RegSync(_) + | TargetBase::RegAsync(_) + | TargetBase::Wire(_) + | TargetBase::Instance(_) + | TargetBase::SimIoForGlobal(_) => target, + TargetBase::FormalInput(global) => { + if self.contains(global) { + FormalInputExprToSimIoExpr.get_owned(target) + } else { + target + } + } + } + } +} + +impl IntoIterator for SimulationGlobalIo { + type Item = (FormalInput, Expr); + type IntoIter = SimulationGlobalIoIter; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl IntoIterator for &'_ SimulationGlobalIo { + type Item = (FormalInput, Expr); + type IntoIter = SimulationGlobalIoIter; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl IntoIterator for &'_ mut SimulationGlobalIo { + type Item = (FormalInput, Expr); + type IntoIter = SimulationGlobalIoIter; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +macro_rules! make_simulation_global_io_iter { + ( + impl $SimulationGlobalIoIter:ident { + fn $global_io_to_item:ident( + $global_io_to_item_arg:ident: (SimIoForGlobal, CompiledValue), + ) -> $item_ty:ty + $global_io_to_item_block:block + } + ) => { + #[derive(Clone, Default)] + pub struct $SimulationGlobalIoIter { + global_io: InternedSliceIter<(SimIoForGlobal, CompiledValue)>, + } + + impl $SimulationGlobalIoIter { + fn $global_io_to_item( + $global_io_to_item_arg: (SimIoForGlobal, CompiledValue), + ) -> $item_ty + $global_io_to_item_block + } + + impl Iterator for $SimulationGlobalIoIter { + type Item = $item_ty; + + fn next(&mut self) -> Option { + self.global_io.next().map(Self::global_io_to_item) + } + + fn size_hint(&self) -> (usize, Option) { + self.global_io.size_hint() + } + + fn count(self) -> usize { + self.global_io.count() + } + + fn last(mut self) -> Option { + self.next_back() + } + + fn nth(&mut self, n: usize) -> Option { + self.global_io.nth(n).map(Self::global_io_to_item) + } + + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.global_io.map(Self::global_io_to_item).fold(init, f) + } + } + + impl std::iter::FusedIterator for $SimulationGlobalIoIter {} + + impl DoubleEndedIterator for $SimulationGlobalIoIter { + fn next_back(&mut self) -> Option { + self.global_io.next_back().map(Self::global_io_to_item) + } + + fn nth_back(&mut self, n: usize) -> Option { + self.global_io.nth_back(n).map(Self::global_io_to_item) + } + + fn rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.global_io.map(Self::global_io_to_item).rfold(init, f) + } + } + + impl ExactSizeIterator for $SimulationGlobalIoIter {} + }; +} + +make_simulation_global_io_iter! { + impl SimulationGlobalIoIter { + fn global_io_to_item( + v: (SimIoForGlobal, CompiledValue), + ) -> (FormalInput, Expr) { + let (global, _) = v; + (global.global(), global.to_expr()) + } + } +} + +impl SimulationGlobalIoIter { + #[must_use] + pub fn globals(self) -> SimulationGlobalIoGlobalsIter { + SimulationGlobalIoGlobalsIter { + global_io: self.global_io, + } + } + #[must_use] + pub fn exprs(self) -> SimulationGlobalIoExprsIter { + SimulationGlobalIoExprsIter { + global_io: self.global_io, + } + } +} + +impl fmt::Debug for SimulationGlobalIoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SimulationGlobalIoIter") + .field(&fmt::from_fn(|f| { + f.debug_map().entries(self.clone()).finish() + })) + .finish() + } +} + +make_simulation_global_io_iter! { + impl SimulationGlobalIoGlobalsIter { + fn global_io_to_item( + v: (SimIoForGlobal, CompiledValue), + ) -> FormalInput { + let (global, _) = v; + global.global() + } + } +} + +impl fmt::Debug for SimulationGlobalIoGlobalsIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SimulationGlobalIoGlobalsIter") + .field(&fmt::from_fn(|f| { + f.debug_set().entries(self.clone()).finish() + })) + .finish() + } +} + +make_simulation_global_io_iter! { + impl SimulationGlobalIoExprsIter { + fn global_io_to_item( + v: (SimIoForGlobal, CompiledValue), + ) -> Expr { + let (global, _) = v; + global.to_expr() + } + } +} + +impl fmt::Debug for SimulationGlobalIoExprsIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SimulationGlobalIoExprsIter") + .field(&fmt::from_fn(|f| { + f.debug_set().entries(self.clone()).finish() + })) + .finish() + } +} + pub struct Simulation { sim_impl: Rc>, io: Expr, @@ -3444,14 +3851,15 @@ macro_rules! impl_simulation_methods { ( async_await = ($($async:tt, $await:tt)?), track_caller = ($(#[$track_caller:tt])?), - which_module = |$self:ident| $which_module:expr, + which_module = |$self:ident, $global_io:ident| $which_module:expr, ) => { $(#[$track_caller])? pub $($async)? fn read_bool_or_int(&mut $self, io: Expr) -> I::Value { - let retval = $self - .sim_impl - .borrow_mut() - .read_bool_or_int(io, ReadTime::Current, $which_module); + let retval = $self.sim_impl.borrow_mut().read_bool_or_int( + io, + ReadTime::Current, + |$global_io: &SimulationGlobalIo| $which_module, + ); $self.settle_if_needed(retval)$(.$await)? } $(#[$track_caller])? @@ -3464,64 +3872,74 @@ macro_rules! impl_simulation_methods { $self.sim_impl.borrow_mut().write_bool_or_int( io, SimValue::into_value(value), - $which_module, + |$global_io: &SimulationGlobalIo| $which_module, ); } $(#[$track_caller])? pub $($async)? fn write_clock(&mut $self, io: Expr, value: bool) { - $self.sim_impl - .borrow_mut() - .write_bit(Expr::canonical(io), value, $which_module); + $self.sim_impl.borrow_mut().write_bit( + Expr::canonical(io), + value, + |$global_io: &SimulationGlobalIo| $which_module, + ); } $(#[$track_caller])? pub $($async)? fn read_clock(&mut $self, io: Expr) -> bool { - let retval = $self - .sim_impl - .borrow_mut() - .read_bit(Expr::canonical(io), ReadTime::Current, $which_module); + let retval = $self.sim_impl.borrow_mut().read_bit( + Expr::canonical(io), + ReadTime::Current, + |$global_io: &SimulationGlobalIo| $which_module, + ); $self.settle_if_needed(retval)$(.$await)? } $(#[$track_caller])? pub $($async)? fn write_bool(&mut $self, io: Expr, value: bool) { - $self.sim_impl - .borrow_mut() - .write_bit(Expr::canonical(io), value, $which_module); + $self.sim_impl.borrow_mut().write_bit( + Expr::canonical(io), + value, + |$global_io: &SimulationGlobalIo| $which_module, + ); } $(#[$track_caller])? pub $($async)? fn read_bool(&mut $self, io: Expr) -> bool { - let retval = $self - .sim_impl - .borrow_mut() - .read_bit(Expr::canonical(io), ReadTime::Current, $which_module); + let retval = $self.sim_impl.borrow_mut().read_bit( + Expr::canonical(io), + ReadTime::Current, + |$global_io: &SimulationGlobalIo| $which_module, + ); $self.settle_if_needed(retval)$(.$await)? } $(#[$track_caller])? pub $($async)? fn write_reset(&mut $self, io: Expr, value: bool) { - $self.sim_impl - .borrow_mut() - .write_bit(Expr::canonical(io), value, $which_module); + $self.sim_impl.borrow_mut().write_bit( + Expr::canonical(io), + value, + |$global_io: &SimulationGlobalIo| $which_module, + ); } $(#[$track_caller])? pub $($async)? fn read_reset(&mut $self, io: Expr) -> bool { - let retval = $self - .sim_impl - .borrow_mut() - .read_bit(Expr::canonical(io), ReadTime::Current, $which_module); + let retval = $self.sim_impl.borrow_mut().read_bit( + Expr::canonical(io), + ReadTime::Current, + |$global_io: &SimulationGlobalIo| $which_module, + ); $self.settle_if_needed(retval)$(.$await)? } #[track_caller] pub fn is_reset_async(&$self, io: Expr) -> bool { - $self - .sim_impl - .borrow_mut() - .is_reset_async(Expr::canonical(io), $which_module) + $self.sim_impl.borrow().is_reset_async( + Expr::canonical(io), + |$global_io: &SimulationGlobalIo| $which_module, + ) } $(#[$track_caller])? pub $($async)? fn read(&mut $self, io: Expr) -> SimValue { - let retval = $self - .sim_impl - .borrow_mut() - .read(Expr::canonical(io), ReadTime::Current, $which_module).1; + let retval = $self.sim_impl.borrow_mut().read( + Expr::canonical(io), + ReadTime::Current, + |$global_io: &SimulationGlobalIo| $which_module, + ).1; SimValue::from_canonical($self.settle_if_needed(retval)$(.$await)?) } $(#[$track_caller])? @@ -3529,7 +3947,7 @@ macro_rules! impl_simulation_methods { $self.sim_impl.borrow_mut().write( Expr::canonical(io), &SimValue::into_canonical(value.into_sim_value_with_type(io.ty())), - $which_module, + |$global_io: &SimulationGlobalIo| $which_module, ); } }; @@ -3568,6 +3986,9 @@ impl Simulation { pub fn io(&self) -> Expr { self.io.to_expr() } + pub fn global_io(&self) -> SimulationGlobalIo { + self.sim_impl.borrow().global_io.clone() + } pub fn from_compiled(compiled: Compiled) -> Self { let sim_impl = SimulationImpl::new(compiled.canonical()); Self { @@ -3593,7 +4014,7 @@ impl Simulation { impl_simulation_methods!( async_await = (), track_caller = (#[track_caller]), - which_module = |self| WhichModule::Main, + which_module = |self, global_io| WhichModule::Main { global_io }, ); #[doc(hidden)] /// This is explicitly unstable and may be changed/removed at any time @@ -3662,7 +4083,7 @@ impl ExternModuleSimulationState { let (key, value) = self .sim_impl .borrow_mut() - .read(io, ReadTime::Current, which_module); + .read(io, ReadTime::Current, |_| which_module); let value = self.settle_if_needed(value).await; let key = Rc::new(key); if sensitivity_set.compiled_values.insert(key.clone()) { @@ -3934,7 +4355,7 @@ impl ExternModuleSimulationState { let retval = self.sim_impl.borrow_mut().read_bool_or_int( io, ReadTime::Past { clock_for_past }, - WhichModule::Extern { + |_| WhichModule::Extern { module_index: self.module_index, }, ); @@ -3950,7 +4371,7 @@ impl ExternModuleSimulationState { let retval = self.sim_impl.borrow_mut().read_bit( Expr::canonical(io), ReadTime::Past { clock_for_past }, - WhichModule::Extern { + |_| WhichModule::Extern { module_index: self.module_index, }, ); @@ -3966,7 +4387,7 @@ impl ExternModuleSimulationState { let retval = self.sim_impl.borrow_mut().read_bit( Expr::canonical(io), ReadTime::Past { clock_for_past }, - WhichModule::Extern { + |_| WhichModule::Extern { module_index: self.module_index, }, ); @@ -3986,7 +4407,7 @@ impl ExternModuleSimulationState { let retval = self.sim_impl.borrow_mut().read_bit( Expr::canonical(io), ReadTime::Past { clock_for_past }, - WhichModule::Extern { + |_| WhichModule::Extern { module_index: self.module_index, }, ); @@ -4009,7 +4430,7 @@ impl ExternModuleSimulationState { .read( Expr::canonical(io), ReadTime::Past { clock_for_past }, - WhichModule::Extern { + |_| WhichModule::Extern { module_index: self.module_index, }, ) @@ -4019,7 +4440,7 @@ impl ExternModuleSimulationState { impl_simulation_methods!( async_await = (async, await), track_caller = (), - which_module = |self| WhichModule::Extern { module_index: self.module_index }, + which_module = |self, _global_io| WhichModule::Extern { module_index: self.module_index }, ); } diff --git a/crates/fayalite/src/sim/compiler.rs b/crates/fayalite/src/sim/compiler.rs index 4d6d9bc..c3c47fd 100644 --- a/crates/fayalite/src/sim/compiler.rs +++ b/crates/fayalite/src/sim/compiler.rs @@ -7,30 +7,32 @@ use crate::{ bundle::{BundleField, BundleType}, enum_::{EnumType, EnumVariant}, expr::{ - ExprEnum, Flow, ValueType, ops, + ExprEnum, Flow, ValueType, + ops::{self, SimIoForGlobal}, target::{ GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement, TargetPathToTraceAsString, TargetPathTraceAsStringInner, }, }, + formal::FormalKind, int::BoolOrIntType, intern::{Intern, InternSlice, Interned, Memoize}, memory::PortKind, module::{ - AnnotatedModuleIO, Block, ExternModuleBody, Id, InstantiatedModule, ModuleBody, NameId, - NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, - StmtInstance, StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule, - transform::deduce_resets::deduce_resets, + AnnotatedModuleIO, Block, ExternModuleBody, Id, InstantiatedModule, + InstantiatedModuleOrGlobal, ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, + StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, + StmtWire, TargetInInstantiatedModuleOrGlobal, transform::deduce_resets::deduce_resets, }, prelude::*, reset::{ResetType, ResetTypeDispatch}, sim::{ ExternModuleSimulation, SimTrace, SimTraceKind, SimTraces, TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl, TraceEnumDiscriminant, TraceEnumWithFields, - TraceFieldlessEnum, TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, - TraceMemoryLocation, TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, - TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceTraceAsString, TraceUInt, - TraceWire, + TraceFieldlessEnum, TraceFormalInput, TraceInstance, TraceLocation, TraceMem, TraceMemPort, + TraceMemoryId, TraceMemoryLocation, TraceModule, TraceModuleIO, TracePhantomConst, + TraceReg, TraceSInt, TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, + TraceTraceAsString, TraceUInt, TraceWire, interpreter::{ self, Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding, InsnsBuildingDone, InsnsBuildingKind, Label, PrefixLinesWrapper, SmallUInt, @@ -44,7 +46,7 @@ use crate::{ }, }, ty::{OpaqueSimValueSize, StaticType, TraceAsString}, - util::{HashMap, chain}, + util::{HashMap, HashSet, chain}, }; use bitvec::vec::BitVec; use num_bigint::BigInt; @@ -1751,6 +1753,19 @@ struct Memory { ports: Vec, } +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub(crate) struct CompiledAssert { + pub(crate) instantiated_module: Interned, + pub(crate) stmt_formal: StmtFormal, +} + +#[derive(Debug)] +struct Assert { + compiled_assert: CompiledAssert, + clk_triggered: StatePartIndex, + pred: StatePartIndex, +} + #[derive(Copy, Clone)] enum MakeTraceDeclTarget { Expr(Expr), @@ -1802,10 +1817,10 @@ pub struct Compiler { base_module: Interned>, modules: HashMap, extern_modules: Vec, - compiled_values: HashMap>, + compiled_values: HashMap>, compiled_exprs: HashMap, CompiledExpr>, compiled_exprs_to_values: HashMap, CompiledValue>, - decl_conditions: HashMap>, + decl_conditions: HashMap>, compiled_values_to_dyn_array_indexes: HashMap, StatePartIndex>, compiled_value_bool_dest_is_small_map: @@ -1818,6 +1833,10 @@ pub struct Compiler { traces: SimTraces>>, memories: Vec, dump_assignments_dot: Option>>, + global_io: Vec<(SimIoForGlobal, CompiledValue)>, + global_io_set: HashSet, + global_trace_decls: Vec, + asserts: Vec, } macro_rules! impl_compiler { @@ -1833,7 +1852,7 @@ macro_rules! impl_compiler { impl Compiler { fn make_trace_scalar_helper( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, target: MakeTraceDeclTarget, source_location: SourceLocation, empty_kind: impl FnOnce() -> SimTraceKind, @@ -1841,7 +1860,7 @@ macro_rules! impl_compiler { ) -> TraceLocation { match target { MakeTraceDeclTarget::Expr(target) => { - let compiled_value = self.compile_expr(instantiated_module, target); + let compiled_value = self.compile_expr(instantiated_module_or_global, target); let compiled_value = self.compiled_expr_to_value(compiled_value, source_location); if compiled_value.range.is_empty() { TraceLocation::Scalar(self.new_sim_trace(empty_kind())) @@ -1871,7 +1890,7 @@ macro_rules! impl_compiler { } fn make_trace_scalar( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, target: MakeTraceDeclTarget, name: Interned, source_location: SourceLocation, @@ -1880,7 +1899,7 @@ macro_rules! impl_compiler { match target.ty() { CanonicalType::UInt(ty) => TraceUInt { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || unreachable!(), @@ -1895,7 +1914,7 @@ macro_rules! impl_compiler { .into(), CanonicalType::SInt(ty) => TraceSInt { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || unreachable!(), @@ -1910,7 +1929,7 @@ macro_rules! impl_compiler { .into(), CanonicalType::Bool(_) => TraceBool { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || unreachable!(), @@ -1927,7 +1946,7 @@ macro_rules! impl_compiler { assert_eq!(ty.discriminant_bit_width(), ty.type_properties().bit_width); let location = match target { MakeTraceDeclTarget::Expr(target) => { - let compiled_value = self.compile_expr(instantiated_module, target); + let compiled_value = self.compile_expr(instantiated_module_or_global, target); let compiled_value = self.compiled_expr_to_value(compiled_value, source_location); let discriminant = self.compile_enum_discriminant( @@ -1964,7 +1983,7 @@ macro_rules! impl_compiler { CanonicalType::Bundle(_) => unreachable!(), CanonicalType::AsyncReset(_) => TraceAsyncReset { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || unreachable!(), @@ -1978,7 +1997,7 @@ macro_rules! impl_compiler { .into(), CanonicalType::SyncReset(_) => TraceSyncReset { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || unreachable!(), @@ -1993,7 +2012,7 @@ macro_rules! impl_compiler { CanonicalType::Reset(_) => unreachable!(), CanonicalType::Clock(_) => TraceClock { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || unreachable!(), @@ -2007,7 +2026,7 @@ macro_rules! impl_compiler { .into(), CanonicalType::PhantomConst(ty) => TracePhantomConst { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || SimTraceKind::PhantomConst { ty }, @@ -2022,7 +2041,7 @@ macro_rules! impl_compiler { .into(), CanonicalType::DynSimOnly(ty) => TraceSimOnly { location: self.make_trace_scalar_helper( - instantiated_module, + instantiated_module_or_global, target, source_location, || unreachable!(), @@ -2038,7 +2057,7 @@ macro_rules! impl_compiler { CanonicalType::TraceAsString(ty) => { let location = match target { MakeTraceDeclTarget::Expr(target) => { - let compiled_value = self.compile_expr(instantiated_module, target); + let compiled_value = self.compile_expr(instantiated_module_or_global, target); let CompiledValue { layout, range, write: _ } = self.compiled_expr_to_value(compiled_value, source_location).map_ty(Type::from_canonical); TraceLocation::Scalar(self.new_sim_trace(SimTraceKind::TraceAsString { @@ -2314,6 +2333,10 @@ impl Compiler { traces: SimTraces(Vec::new()), memories: Vec::new(), dump_assignments_dot: None, + global_io: Vec::new(), + global_io_set: HashSet::default(), + global_trace_decls: Vec::new(), + asserts: Vec::new(), } } #[doc(hidden)] @@ -2333,16 +2356,17 @@ impl Compiler { } fn make_trace_decl_child( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: impl Into, target: MakeTraceDeclTarget, name: Interned, source_location: SourceLocation, ) -> TraceDecl { + let instantiated_module_or_global = instantiated_module_or_global.into(); match target.ty() { CanonicalType::Array(ty) => { let elements = Interned::from_iter((0..ty.len()).map(|index| { self.make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, match target { MakeTraceDeclTarget::Expr(target) => MakeTraceDeclTarget::Expr( Expr::::from_canonical(target)[index], @@ -2375,12 +2399,18 @@ impl Compiler { } CanonicalType::Enum(ty) => { if ty.variants().iter().all(|v| v.ty.is_none()) { - self.make_trace_scalar(instantiated_module, target, name, source_location) + self.make_trace_scalar( + instantiated_module_or_global, + target, + name, + source_location, + ) } else { let flow = target.flow(); let location = match target { MakeTraceDeclTarget::Expr(target) => { - let compiled_value = self.compile_expr(instantiated_module, target); + let compiled_value = + self.compile_expr(instantiated_module_or_global, target); let compiled_value = self.compiled_expr_to_value(compiled_value, source_location); let discriminant = self.compile_enum_discriminant( @@ -2419,7 +2449,7 @@ impl Compiler { |(variant_index, variant)| { variant.ty.map(|variant_ty| { self.make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, match target { MakeTraceDeclTarget::Expr(target) => { MakeTraceDeclTarget::Expr( @@ -2464,7 +2494,7 @@ impl Compiler { let fields = Interned::from_iter(ty.fields().iter().zip(ty.field_offsets()).map( |(field, field_offset)| { self.make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, match target { MakeTraceDeclTarget::Expr(target) => { MakeTraceDeclTarget::Expr(Expr::field( @@ -2514,22 +2544,23 @@ impl Compiler { | CanonicalType::DynSimOnly(_) | CanonicalType::PhantomConst(_) | CanonicalType::TraceAsString(_) => { - self.make_trace_scalar(instantiated_module, target, name, source_location) + self.make_trace_scalar(instantiated_module_or_global, target, name, source_location) } } } fn make_trace_decl( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: impl Into, target_base: TargetBase, ) -> TraceDecl { + let instantiated_module_or_global = instantiated_module_or_global.into(); let target = MakeTraceDeclTarget::Expr(target_base.to_expr()); match target_base { TargetBase::ModuleIO(module_io) => TraceModuleIO { name: module_io.name(), child: self .make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, target, module_io.name(), module_io.source_location(), @@ -2542,7 +2573,7 @@ impl Compiler { TargetBase::MemPort(mem_port) => { let name = Intern::intern_owned(mem_port.port_name().to_string()); let TraceDecl::Scope(TraceScope::Bundle(bundle)) = self.make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, target, name, mem_port.source_location(), @@ -2560,7 +2591,7 @@ impl Compiler { name: reg.name(), child: self .make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, target, reg.name(), reg.source_location(), @@ -2573,7 +2604,7 @@ impl Compiler { name: reg.name(), child: self .make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, target, reg.name(), reg.source_location(), @@ -2586,7 +2617,7 @@ impl Compiler { name: reg.name(), child: self .make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, target, reg.name(), reg.source_location(), @@ -2599,7 +2630,7 @@ impl Compiler { name: wire.name(), child: self .make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, target, wire.name(), wire.source_location(), @@ -2610,13 +2641,18 @@ impl Compiler { .into(), TargetBase::Instance(instance) => { let TraceDecl::Scope(TraceScope::Bundle(instance_io)) = self.make_trace_decl_child( - instantiated_module, + instantiated_module_or_global, target, instance.name(), instance.source_location(), ) else { unreachable!() }; + let InstantiatedModuleOrGlobal::InstantiatedModule(instantiated_module) = + instantiated_module_or_global + else { + unreachable!(); + }; let compiled_module = &self.modules[&InstantiatedModule::Child { parent: instantiated_module.intern(), instance: instance.intern(), @@ -2629,23 +2665,45 @@ impl Compiler { } .into() } + TargetBase::FormalInput(formal_input) => TraceFormalInput { + name: formal_input.name(), + child: self + .make_trace_decl_child( + instantiated_module_or_global, + target, + formal_input.name(), + formal_input.source_location(), + ) + .intern(), + formal_input, + } + .into(), + TargetBase::SimIoForGlobal(_) => { + unreachable!("Module is known to not contain SimIoForGlobal from validation") + } } } fn compile_value( &mut self, - target: TargetInInstantiatedModule, + target: TargetInInstantiatedModuleOrGlobal, ) -> CompiledValue { if let Some(&retval) = self.compiled_values.get(&target) { return retval; } - let retval = match target.target { + let mut new_global_io = None; + let retval = match target.target() { Target::Base(base) => { let unprefixed_layout = CompiledTypeLayout::get(base.canonical_ty()); - let layout = unprefixed_layout.with_prefixed_debug_names(&format!( - "{:?}.{:?}", - target.instantiated_module, - base.target_name() - )); + let layout = unprefixed_layout.with_prefixed_debug_names(&match target + .instantiated_module_or_global() + { + InstantiatedModuleOrGlobal::Global => { + format!("{:?}", base.target_name()) + } + InstantiatedModuleOrGlobal::InstantiatedModule(instantiated_module) => { + format!("{instantiated_module:?}.{:?}", base.target_name()) + } + }); let range = self.insns.allocate_variable(&layout.layout); let write = match *base { TargetBase::ModuleIO(_) @@ -2655,7 +2713,7 @@ impl Compiler { TargetBase::Reg(_) | TargetBase::RegSync(_) | TargetBase::RegAsync(_) => { let write_layout = unprefixed_layout.with_prefixed_debug_names(&format!( "{:?}.{:?}$next", - target.instantiated_module, + target.instantiated_module_or_global(), base.target_name() )); Some(( @@ -2663,6 +2721,16 @@ impl Compiler { self.insns.allocate_variable(&write_layout.layout), )) } + TargetBase::FormalInput(formal_input) => { + if self.global_io_set.insert(SimIoForGlobal::new(formal_input)) { + new_global_io = + Some((formal_input, target.instantiated_module_or_global(), *base)); + } + None + } + TargetBase::SimIoForGlobal(_) => unreachable!( + "Module is known to not contain SimIoForGlobal from validation" + ), }; CompiledValue { range, @@ -2671,10 +2739,10 @@ impl Compiler { } } Target::Child(target_child) => { - let parent = self.compile_value(TargetInInstantiatedModule { - instantiated_module: target.instantiated_module, - target: *target_child.parent(), - }); + let parent = self.compile_value(TargetInInstantiatedModuleOrGlobal::new( + target.instantiated_module_or_global(), + *target_child.parent(), + )); match *target_child.path_element() { TargetPathElement::BundleField(TargetPathBundleField { name }) => { parent.map_ty(Bundle::from_canonical).field_by_name(name) @@ -2693,6 +2761,12 @@ impl Compiler { } }; self.compiled_values.insert(target, retval); + if let Some((new_global_io, instantiated_module_or_global, base)) = new_global_io { + let trace_decl = self.make_trace_decl(instantiated_module_or_global, base); + self.global_trace_decls.push(trace_decl); + self.global_io + .push((SimIoForGlobal::new(new_global_io), retval)); + } retval } fn add_assignment>( @@ -2707,18 +2781,20 @@ impl Compiler { } fn simple_big_expr_input( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, input: Expr, ) -> StatePartIndex { - let input = self.compile_expr(instantiated_module, input); - let input = - self.compiled_expr_to_value(input, instantiated_module.leaf_module().source_location()); + let input = self.compile_expr(instantiated_module_or_global, input); + let input = self.compiled_expr_to_value( + input, + instantiated_module_or_global.leaf_module_source_location(), + ); assert_eq!(input.range.len(), TypeLen::big_slot()); input.range.big_slots.start } fn compile_expr_helper( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, dest_ty: CanonicalType, make_insns: impl FnOnce(&mut Self, TypeIndexRange) -> Vec, ) -> CompiledValue { @@ -2733,24 +2809,24 @@ impl Compiler { self.add_assignment( Interned::default(), insns, - instantiated_module.leaf_module().source_location(), + instantiated_module_or_global.leaf_module_source_location(), ); retval } fn simple_nary_big_expr_helper( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, dest_ty: CanonicalType, make_insns: impl FnOnce(StatePartIndex) -> Vec, ) -> CompiledValue { - self.compile_expr_helper(instantiated_module, dest_ty, |_, dest| { + self.compile_expr_helper(instantiated_module_or_global, dest_ty, |_, dest| { assert_eq!(dest.len(), TypeLen::big_slot()); make_insns(dest.big_slots.start) }) } fn simple_nary_big_expr( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, dest_ty: CanonicalType, inputs: [Expr; N], make_insns: impl FnOnce( @@ -2758,8 +2834,9 @@ impl Compiler { [StatePartIndex; N], ) -> Vec, ) -> CompiledValue { - let inputs = inputs.map(|input| self.simple_big_expr_input(instantiated_module, input)); - self.simple_nary_big_expr_helper(instantiated_module, dest_ty, |dest| { + let inputs = + inputs.map(|input| self.simple_big_expr_input(instantiated_module_or_global, input)); + self.simple_nary_big_expr_helper(instantiated_module_or_global, dest_ty, |dest| { make_insns(dest, inputs) }) } @@ -2851,20 +2928,22 @@ impl Compiler { } fn compile_cast_scalar_to_bits( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, arg: Expr, cast_fn: impl FnOnce(Expr) -> Expr, ) -> CompiledValue { let arg = Expr::::from_canonical(arg); let retval = cast_fn(arg); - let retval = self.compile_expr(instantiated_module, Expr::canonical(retval)); - let retval = self - .compiled_expr_to_value(retval, instantiated_module.leaf_module().source_location()); + let retval = self.compile_expr(instantiated_module_or_global, Expr::canonical(retval)); + let retval = self.compiled_expr_to_value( + retval, + instantiated_module_or_global.leaf_module_source_location(), + ); retval.map_ty(UInt::from_canonical) } fn compile_cast_aggregate_to_bits( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, parts: impl IntoIterator>, ) -> CompiledValue { let retval = parts @@ -2872,22 +2951,26 @@ impl Compiler { .map(|part| part.cast_to_bits()) .reduce(|accumulator, part| accumulator | (part << accumulator.ty().width)) .unwrap_or_else(|| UInt[0].zero().to_expr()); - let retval = self.compile_expr(instantiated_module, Expr::canonical(retval)); - let retval = self - .compiled_expr_to_value(retval, instantiated_module.leaf_module().source_location()); + let retval = self.compile_expr(instantiated_module_or_global, Expr::canonical(retval)); + let retval = self.compiled_expr_to_value( + retval, + instantiated_module_or_global.leaf_module_source_location(), + ); retval.map_ty(UInt::from_canonical) } fn compile_cast_to_bits( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, expr: ops::CastToBits, ) -> CompiledValue { match expr.arg().ty() { CanonicalType::UInt(_) => { - self.compile_cast_scalar_to_bits(instantiated_module, expr.arg(), |arg| arg) + self.compile_cast_scalar_to_bits(instantiated_module_or_global, expr.arg(), |arg| { + arg + }) } CanonicalType::SInt(ty) => self.compile_cast_scalar_to_bits( - instantiated_module, + instantiated_module_or_global, expr.arg(), |arg: Expr| arg.cast_to(ty.as_same_width_uint()), ), @@ -2896,33 +2979,33 @@ impl Compiler { | CanonicalType::SyncReset(_) | CanonicalType::Reset(_) | CanonicalType::Clock(_) => self.compile_cast_scalar_to_bits( - instantiated_module, + instantiated_module_or_global, expr.arg(), |arg: Expr| arg.cast_to(UInt[1]), ), CanonicalType::Array(ty) => self.compile_cast_aggregate_to_bits( - instantiated_module, + instantiated_module_or_global, (0..ty.len()).map(|index| Expr::::from_canonical(expr.arg())[index]), ), CanonicalType::Enum(ty) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, UInt[ty.type_properties().bit_width].canonical(), [Expr::canonical(expr.arg())], |dest, [src]| vec![Insn::Copy { dest, src }], ) .map_ty(UInt::from_canonical), CanonicalType::Bundle(ty) => self.compile_cast_aggregate_to_bits( - instantiated_module, + instantiated_module_or_global, ty.fields().iter().map(|field| { Expr::field(Expr::::from_canonical(expr.arg()), &field.name) }), ), CanonicalType::PhantomConst(_) | CanonicalType::DynSimOnly(_) => { - self.compile_cast_aggregate_to_bits(instantiated_module, []) + self.compile_cast_aggregate_to_bits(instantiated_module_or_global, []) } CanonicalType::TraceAsString(_) => self.compile_cast_to_bits( - instantiated_module, + instantiated_module_or_global, ops::CastToBits::new( ops::TraceAsStringAsInner::new(Expr::from_canonical(expr.arg())).to_expr(), ), @@ -2931,7 +3014,7 @@ impl Compiler { } fn compile_cast_bits_to_or_uninit( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, arg: Option>, ty: CanonicalType, ) -> CompiledValue { @@ -2960,7 +3043,7 @@ impl Compiler { } ty @ CanonicalType::Enum(_) => { return self.simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, ty, [Expr::canonical(arg.unwrap_or_else(|| { UInt::new_dyn(ty.bit_width()).zero().to_expr() @@ -3005,16 +3088,20 @@ impl Compiler { ), CanonicalType::PhantomConst(ty) => { if let Some(arg) = arg { - let _ = self.compile_expr(instantiated_module, Expr::canonical(arg)); + let _ = self.compile_expr(instantiated_module_or_global, Expr::canonical(arg)); } Expr::canonical(ty.to_expr()) } CanonicalType::DynSimOnly(ty) => { assert!(arg.is_none(), "can't cast bits to SimOnly"); - return self.compile_expr_helper(instantiated_module, ty.canonical(), |_, dest| { - assert_eq!(dest.len(), TypeLen::sim_only_slot()); - vec![] - }); + return self.compile_expr_helper( + instantiated_module_or_global, + ty.canonical(), + |_, dest| { + assert_eq!(dest.len(), TypeLen::sim_only_slot()); + vec![] + }, + ); } CanonicalType::TraceAsString(ty) => Expr::canonical( ops::ToTraceAsString::new( @@ -3027,24 +3114,27 @@ impl Compiler { .to_expr(), ), }; - let retval = self.compile_expr(instantiated_module, Expr::canonical(retval)); - self.compiled_expr_to_value(retval, instantiated_module.leaf_module().source_location()) + let retval = self.compile_expr(instantiated_module_or_global, Expr::canonical(retval)); + self.compiled_expr_to_value( + retval, + instantiated_module_or_global.leaf_module_source_location(), + ) } fn compile_aggregate_literal( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: InstantiatedModuleOrGlobal, dest_ty: CanonicalType, inputs: Interned<[Expr]>, ) -> CompiledValue { - self.compile_expr_helper(instantiated_module, dest_ty, |this, dest| { + self.compile_expr_helper(instantiated_module_or_global, dest_ty, |this, dest| { let mut insns = Vec::new(); let mut offset = TypeIndex::ZERO; for input in inputs { - let input = this.compile_expr(instantiated_module, input); + let input = this.compile_expr(instantiated_module_or_global, input); let input = this .compiled_expr_to_value( input, - instantiated_module.leaf_module().source_location(), + instantiated_module_or_global.leaf_module_source_location(), ) .range; insns.extend( @@ -3057,9 +3147,10 @@ impl Compiler { } fn compile_expr( &mut self, - instantiated_module: InstantiatedModule, + instantiated_module_or_global: impl Into, expr: Expr, ) -> CompiledExpr { + let instantiated_module_or_global = instantiated_module_or_global.into(); if let Some(&retval) = self.compiled_exprs.get(&expr) { return retval; } @@ -3094,30 +3185,32 @@ impl Compiler { CanonicalType::DynSimOnly(_) => unreachable!(), CanonicalType::TraceAsString(_) => unreachable!(), }; - self.simple_nary_big_expr(instantiated_module, expr.ty(), [arg], |dest, [src]| match ( - src_signed, - dest_signed, - ) { - (false, false) | (true, true) => { - vec![Insn::Copy { dest, src }] - } - (false, true) => vec![Insn::CastToSInt { - dest, - src, - dest_width: 1, - }], - (true, false) => vec![Insn::CastToUInt { - dest, - src, - dest_width: 1, - }], - }) + self.simple_nary_big_expr( + instantiated_module_or_global, + expr.ty(), + [arg], + |dest, [src]| match (src_signed, dest_signed) { + (false, false) | (true, true) => { + vec![Insn::Copy { dest, src }] + } + (false, true) => vec![Insn::CastToSInt { + dest, + src, + dest_width: 1, + }], + (true, false) => vec![Insn::CastToUInt { + dest, + src, + dest_width: 1, + }], + }, + ) .into() }; let retval: CompiledExpr<_> = match *Expr::expr_enum(expr) { ExprEnum::UIntLiteral(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [], |dest, []| { @@ -3130,7 +3223,7 @@ impl Compiler { .into(), ExprEnum::SIntLiteral(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [], |dest, []| { @@ -3142,21 +3235,38 @@ impl Compiler { ) .into(), ExprEnum::BoolLiteral(expr) => self - .simple_nary_big_expr(instantiated_module, Bool.canonical(), [], |dest, []| { - vec![Insn::Const { - dest, - value: BigInt::from(expr).intern_sized(), - }] - }) + .simple_nary_big_expr( + instantiated_module_or_global, + Bool.canonical(), + [], + |dest, []| { + vec![Insn::Const { + dest, + value: BigInt::from(expr).intern_sized(), + }] + }, + ) .into(), ExprEnum::PhantomConst(_) => self - .compile_aggregate_literal(instantiated_module, expr.ty(), Interned::default()) + .compile_aggregate_literal( + instantiated_module_or_global, + expr.ty(), + Interned::default(), + ) .into(), ExprEnum::BundleLiteral(literal) => self - .compile_aggregate_literal(instantiated_module, expr.ty(), literal.field_values()) + .compile_aggregate_literal( + instantiated_module_or_global, + expr.ty(), + literal.field_values(), + ) .into(), ExprEnum::ArrayLiteral(literal) => self - .compile_aggregate_literal(instantiated_module, expr.ty(), literal.element_values()) + .compile_aggregate_literal( + instantiated_module_or_global, + expr.ty(), + literal.element_values(), + ) .into(), ExprEnum::EnumLiteral(expr) => { let enum_bits_ty = UInt[expr.ty().type_properties().bit_width]; @@ -3174,16 +3284,16 @@ impl Compiler { .to_expr() }; self.compile_expr( - instantiated_module, + instantiated_module_or_global, enum_bits.cast_bits_to(expr.ty().canonical()), ) } ExprEnum::Uninit(expr) => self - .compile_cast_bits_to_or_uninit(instantiated_module, None, expr.ty()) + .compile_cast_bits_to_or_uninit(instantiated_module_or_global, None, expr.ty()) .into(), ExprEnum::NotU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.arg().ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3197,7 +3307,7 @@ impl Compiler { .into(), ExprEnum::NotS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.arg().ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| vec![Insn::NotS { dest, src }], @@ -3205,7 +3315,7 @@ impl Compiler { .into(), ExprEnum::NotB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.arg().ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3219,7 +3329,7 @@ impl Compiler { .into(), ExprEnum::Neg(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| vec![Insn::Neg { dest, src }], @@ -3227,7 +3337,7 @@ impl Compiler { .into(), ExprEnum::BitAndU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::And { dest, lhs, rhs }], @@ -3235,7 +3345,7 @@ impl Compiler { .into(), ExprEnum::BitAndS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::And { dest, lhs, rhs }], @@ -3243,7 +3353,7 @@ impl Compiler { .into(), ExprEnum::BitAndB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::And { dest, lhs, rhs }], @@ -3251,7 +3361,7 @@ impl Compiler { .into(), ExprEnum::BitOrU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Or { dest, lhs, rhs }], @@ -3259,7 +3369,7 @@ impl Compiler { .into(), ExprEnum::BitOrS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Or { dest, lhs, rhs }], @@ -3267,7 +3377,7 @@ impl Compiler { .into(), ExprEnum::BitOrB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Or { dest, lhs, rhs }], @@ -3275,7 +3385,7 @@ impl Compiler { .into(), ExprEnum::BitXorU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Xor { dest, lhs, rhs }], @@ -3283,7 +3393,7 @@ impl Compiler { .into(), ExprEnum::BitXorS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Xor { dest, lhs, rhs }], @@ -3291,7 +3401,7 @@ impl Compiler { .into(), ExprEnum::BitXorB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Xor { dest, lhs, rhs }], @@ -3299,7 +3409,7 @@ impl Compiler { .into(), ExprEnum::AddU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Add { dest, lhs, rhs }], @@ -3307,7 +3417,7 @@ impl Compiler { .into(), ExprEnum::AddS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Add { dest, lhs, rhs }], @@ -3315,7 +3425,7 @@ impl Compiler { .into(), ExprEnum::SubU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| { @@ -3330,7 +3440,7 @@ impl Compiler { .into(), ExprEnum::SubS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::SubS { dest, lhs, rhs }], @@ -3338,7 +3448,7 @@ impl Compiler { .into(), ExprEnum::MulU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Mul { dest, lhs, rhs }], @@ -3346,7 +3456,7 @@ impl Compiler { .into(), ExprEnum::MulS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Mul { dest, lhs, rhs }], @@ -3354,7 +3464,7 @@ impl Compiler { .into(), ExprEnum::DivU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Div { dest, lhs, rhs }], @@ -3362,7 +3472,7 @@ impl Compiler { .into(), ExprEnum::DivS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Div { dest, lhs, rhs }], @@ -3370,7 +3480,7 @@ impl Compiler { .into(), ExprEnum::RemU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Rem { dest, lhs, rhs }], @@ -3378,7 +3488,7 @@ impl Compiler { .into(), ExprEnum::RemS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::Rem { dest, lhs, rhs }], @@ -3386,7 +3496,7 @@ impl Compiler { .into(), ExprEnum::DynShlU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::DynShl { dest, lhs, rhs }], @@ -3394,7 +3504,7 @@ impl Compiler { .into(), ExprEnum::DynShlS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::DynShl { dest, lhs, rhs }], @@ -3402,7 +3512,7 @@ impl Compiler { .into(), ExprEnum::DynShrU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::DynShr { dest, lhs, rhs }], @@ -3410,7 +3520,7 @@ impl Compiler { .into(), ExprEnum::DynShrS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::DynShr { dest, lhs, rhs }], @@ -3418,7 +3528,7 @@ impl Compiler { .into(), ExprEnum::FixedShlU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs())], |dest, [lhs]| { @@ -3432,7 +3542,7 @@ impl Compiler { .into(), ExprEnum::FixedShlS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs())], |dest, [lhs]| { @@ -3446,7 +3556,7 @@ impl Compiler { .into(), ExprEnum::FixedShrU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs())], |dest, [lhs]| { @@ -3460,7 +3570,7 @@ impl Compiler { .into(), ExprEnum::FixedShrS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.lhs())], |dest, [lhs]| { @@ -3474,7 +3584,7 @@ impl Compiler { .into(), ExprEnum::CmpLtB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpLt { dest, lhs, rhs }], @@ -3482,7 +3592,7 @@ impl Compiler { .into(), ExprEnum::CmpLeB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpLe { dest, lhs, rhs }], @@ -3490,7 +3600,7 @@ impl Compiler { .into(), ExprEnum::CmpGtB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), // swap both comparison direction and lhs/rhs [Expr::canonical(expr.rhs()), Expr::canonical(expr.lhs())], @@ -3499,7 +3609,7 @@ impl Compiler { .into(), ExprEnum::CmpGeB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), // swap both comparison direction and lhs/rhs [Expr::canonical(expr.rhs()), Expr::canonical(expr.lhs())], @@ -3508,7 +3618,7 @@ impl Compiler { .into(), ExprEnum::CmpEqB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpEq { dest, lhs, rhs }], @@ -3516,7 +3626,7 @@ impl Compiler { .into(), ExprEnum::CmpNeB(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpNe { dest, lhs, rhs }], @@ -3524,7 +3634,7 @@ impl Compiler { .into(), ExprEnum::CmpLtU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpLt { dest, lhs, rhs }], @@ -3532,7 +3642,7 @@ impl Compiler { .into(), ExprEnum::CmpLeU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpLe { dest, lhs, rhs }], @@ -3540,7 +3650,7 @@ impl Compiler { .into(), ExprEnum::CmpGtU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), // swap both comparison direction and lhs/rhs [Expr::canonical(expr.rhs()), Expr::canonical(expr.lhs())], @@ -3549,7 +3659,7 @@ impl Compiler { .into(), ExprEnum::CmpGeU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), // swap both comparison direction and lhs/rhs [Expr::canonical(expr.rhs()), Expr::canonical(expr.lhs())], @@ -3558,7 +3668,7 @@ impl Compiler { .into(), ExprEnum::CmpEqU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpEq { dest, lhs, rhs }], @@ -3566,7 +3676,7 @@ impl Compiler { .into(), ExprEnum::CmpNeU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpNe { dest, lhs, rhs }], @@ -3574,7 +3684,7 @@ impl Compiler { .into(), ExprEnum::CmpLtS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpLt { dest, lhs, rhs }], @@ -3582,7 +3692,7 @@ impl Compiler { .into(), ExprEnum::CmpLeS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpLe { dest, lhs, rhs }], @@ -3590,7 +3700,7 @@ impl Compiler { .into(), ExprEnum::CmpGtS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), // swap both comparison direction and lhs/rhs [Expr::canonical(expr.rhs()), Expr::canonical(expr.lhs())], @@ -3599,7 +3709,7 @@ impl Compiler { .into(), ExprEnum::CmpGeS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), // swap both comparison direction and lhs/rhs [Expr::canonical(expr.rhs()), Expr::canonical(expr.lhs())], @@ -3608,7 +3718,7 @@ impl Compiler { .into(), ExprEnum::CmpEqS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpEq { dest, lhs, rhs }], @@ -3616,7 +3726,7 @@ impl Compiler { .into(), ExprEnum::CmpNeS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, Bool.canonical(), [Expr::canonical(expr.lhs()), Expr::canonical(expr.rhs())], |dest, [lhs, rhs]| vec![Insn::CmpNe { dest, lhs, rhs }], @@ -3624,7 +3734,7 @@ impl Compiler { .into(), ExprEnum::CastUIntToUInt(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3638,7 +3748,7 @@ impl Compiler { .into(), ExprEnum::CastUIntToSInt(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3652,7 +3762,7 @@ impl Compiler { .into(), ExprEnum::CastSIntToUInt(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3666,7 +3776,7 @@ impl Compiler { .into(), ExprEnum::CastSIntToSInt(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, expr.ty().canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3706,76 +3816,90 @@ impl Compiler { ExprEnum::CastClockToUInt(expr) => cast_bit(Expr::canonical(expr.arg())), ExprEnum::CastClockToSInt(expr) => cast_bit(Expr::canonical(expr.arg())), ExprEnum::FieldAccess(expr) => self - .compile_expr(instantiated_module, Expr::canonical(expr.base())) + .compile_expr(instantiated_module_or_global, Expr::canonical(expr.base())) .map_ty(Bundle::from_canonical) .field_by_index(expr.field_index()), ExprEnum::VariantAccess(variant_access) => { let start = variant_access.base().ty().discriminant_bit_width(); let len = expr.ty().bit_width(); self.compile_expr( - instantiated_module, + instantiated_module_or_global, variant_access.base().cast_to_bits()[start..start + len] .cast_bits_to(expr.ty()), ) } ExprEnum::ArrayIndex(expr) => self - .compile_expr(instantiated_module, Expr::canonical(expr.base())) + .compile_expr(instantiated_module_or_global, Expr::canonical(expr.base())) .map_ty(Array::from_canonical) .element(expr.element_index()), ExprEnum::DynArrayIndex(expr) => { - let element_index = - self.compile_expr(instantiated_module, Expr::canonical(expr.element_index())); + let element_index = self.compile_expr( + instantiated_module_or_global, + Expr::canonical(expr.element_index()), + ); let element_index = self.compiled_expr_to_value( element_index, - instantiated_module.leaf_module().source_location(), + instantiated_module_or_global.leaf_module_source_location(), ); let index_slot = self.compiled_value_to_dyn_array_index( element_index.map_ty(UInt::from_canonical), - instantiated_module.leaf_module().source_location(), + instantiated_module_or_global.leaf_module_source_location(), ); - self.compile_expr(instantiated_module, Expr::canonical(expr.base())) + self.compile_expr(instantiated_module_or_global, Expr::canonical(expr.base())) .map_ty(Array::from_canonical) .element_dyn(index_slot) } ExprEnum::ReduceBitAndU(expr) => if expr.arg().ty().width() == 0 { - self.compile_expr(instantiated_module, Expr::canonical(true.to_expr())) + self.compile_expr( + instantiated_module_or_global, + Expr::canonical(true.to_expr()), + ) } else { self.compile_expr( - instantiated_module, + instantiated_module_or_global, Expr::canonical(expr.arg().cmp_eq(expr.arg().ty().from_int_wrapping(-1))), ) } .into(), ExprEnum::ReduceBitAndS(expr) => if expr.arg().ty().width() == 0 { - self.compile_expr(instantiated_module, Expr::canonical(true.to_expr())) + self.compile_expr( + instantiated_module_or_global, + Expr::canonical(true.to_expr()), + ) } else { self.compile_expr( - instantiated_module, + instantiated_module_or_global, Expr::canonical(expr.arg().cmp_eq(expr.arg().ty().from_int_wrapping(-1))), ) } .into(), ExprEnum::ReduceBitOrU(expr) => if expr.arg().ty().width() == 0 { - self.compile_expr(instantiated_module, Expr::canonical(false.to_expr())) + self.compile_expr( + instantiated_module_or_global, + Expr::canonical(false.to_expr()), + ) } else { self.compile_expr( - instantiated_module, + instantiated_module_or_global, Expr::canonical(expr.arg().cmp_ne(expr.arg().ty().from_int_wrapping(0))), ) } .into(), ExprEnum::ReduceBitOrS(expr) => if expr.arg().ty().width() == 0 { - self.compile_expr(instantiated_module, Expr::canonical(false.to_expr())) + self.compile_expr( + instantiated_module_or_global, + Expr::canonical(false.to_expr()), + ) } else { self.compile_expr( - instantiated_module, + instantiated_module_or_global, Expr::canonical(expr.arg().cmp_ne(expr.arg().ty().from_int_wrapping(0))), ) } .into(), ExprEnum::ReduceBitXorU(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, UInt::<1>::TYPE.canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3789,7 +3913,7 @@ impl Compiler { .into(), ExprEnum::ReduceBitXorS(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, UInt::<1>::TYPE.canonical(), [Expr::canonical(expr.arg())], |dest, [src]| { @@ -3803,7 +3927,7 @@ impl Compiler { .into(), ExprEnum::SliceUInt(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, UInt::new_dyn(expr.range().len()).canonical(), [Expr::canonical(expr.base())], |dest, [src]| { @@ -3818,7 +3942,7 @@ impl Compiler { .into(), ExprEnum::SliceSInt(expr) => self .simple_nary_big_expr( - instantiated_module, + instantiated_module_or_global, UInt::new_dyn(expr.range().len()).canonical(), [Expr::canonical(expr.base())], |dest, [src]| { @@ -3832,62 +3956,75 @@ impl Compiler { ) .into(), ExprEnum::CastToBits(expr) => self - .compile_cast_to_bits(instantiated_module, expr) + .compile_cast_to_bits(instantiated_module_or_global, expr) .map_ty(CanonicalType::UInt) .into(), ExprEnum::CastBitsTo(expr) => self - .compile_cast_bits_to_or_uninit(instantiated_module, Some(expr.arg()), expr.ty()) + .compile_cast_bits_to_or_uninit( + instantiated_module_or_global, + Some(expr.arg()), + expr.ty(), + ) .into(), ExprEnum::ToTraceAsString(expr) => self - .compile_expr(instantiated_module, expr.inner()) + .compile_expr(instantiated_module_or_global, expr.inner()) .wrap_in_trace_as_string(expr.ty()) .map_ty(|ty| ty.canonical()), ExprEnum::TraceAsStringAsInner(expr) => self - .compile_expr(instantiated_module, Expr::canonical(expr.arg())) + .compile_expr(instantiated_module_or_global, Expr::canonical(expr.arg())) .map_ty(TraceAsString::from_canonical) .inner(), ExprEnum::ModuleIO(expr) => self - .compile_value(TargetInInstantiatedModule { - instantiated_module, - target: expr.into(), - }) + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) .into(), ExprEnum::Instance(expr) => self - .compile_value(TargetInInstantiatedModule { - instantiated_module, - target: expr.into(), - }) + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) .into(), ExprEnum::Wire(expr) => self - .compile_value(TargetInInstantiatedModule { - instantiated_module, - target: expr.into(), - }) + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) .into(), ExprEnum::Reg(expr) => self - .compile_value(TargetInInstantiatedModule { - instantiated_module, - target: expr.into(), - }) + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) .into(), ExprEnum::RegSync(expr) => self - .compile_value(TargetInInstantiatedModule { - instantiated_module, - target: expr.into(), - }) + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) .into(), ExprEnum::RegAsync(expr) => self - .compile_value(TargetInInstantiatedModule { - instantiated_module, - target: expr.into(), - }) + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) .into(), ExprEnum::MemPort(expr) => self - .compile_value(TargetInInstantiatedModule { - instantiated_module, - target: expr.into(), - }) + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) .into(), + ExprEnum::FormalInput(expr) => self + .compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module_or_global, + expr.into(), + )) + .into(), + ExprEnum::SimIoForGlobal(_) => { + unreachable!("Module is known to not contain SimIoForGlobal from validation"); + } }; self.compiled_exprs.insert(expr, retval); retval @@ -4013,10 +4150,11 @@ impl Compiler { let Some(target) = lhs.target() else { unreachable!("connect lhs must have target"); }; - let lhs_decl_conditions = self.decl_conditions[&TargetInInstantiatedModule { - instantiated_module: lhs_instantiated_module, - target: target.base().into(), - }]; + let lhs_decl_conditions = self.decl_conditions + [&TargetInInstantiatedModuleOrGlobal::from_target( + lhs_instantiated_module, + target.base().into(), + )]; let lhs = self.compile_expr(lhs_instantiated_module, lhs); let rhs = self.compile_expr(rhs_instantiated_module, rhs); let rhs = self.compiled_expr_to_value(rhs, source_location); @@ -4257,10 +4395,8 @@ impl Compiler { StmtDeclaration::RegAsync(v) => v.reg.into(), StmtDeclaration::Instance(v) => v.instance.into(), }; - let target = TargetInInstantiatedModule { - instantiated_module: *parent_module, - target: target_base.into(), - }; + let target = + TargetInInstantiatedModuleOrGlobal::from_target(*parent_module, target_base.into()); self.decl_conditions.insert(target, conditions); let compiled_value = self.compile_value(target); match declaration { @@ -4324,6 +4460,56 @@ impl Compiler { } self.make_trace_decl(*parent_module, target_base) } + fn compile_stmt_formal( + &mut self, + stmt_formal: StmtFormal, + instantiated_module: Interned, + conditions: Interned<[Cond]>, + ) { + let StmtFormal { + kind, + clk, + pred, + en, + text: _, + source_location, + } = stmt_formal; + let clk = self.compile_expr(*instantiated_module, Expr::canonical(clk)); + let clk = self + .compiled_expr_to_value(clk, source_location) + .map_ty(Clock::from_canonical); + let clk = self.compile_clock(clk, source_location); + let pred = self.compile_expr(*instantiated_module, Expr::canonical(pred | !en)); + let pred = self.compiled_expr_to_value(pred, source_location); + let pred_layout = CompiledTypeLayout::get(Bool.canonical()); + let pred_wire = CompiledValue { + layout: pred_layout, + range: self.insns.allocate_variable(&pred_layout.layout), + write: None, + }; + let true_value = self.compile_expr(*instantiated_module, Expr::canonical(true.to_expr())); + let true_value = self.compiled_expr_to_value(true_value, source_location); + self.compile_simple_connect( + [].intern_slice(), + pred_wire.into(), + true_value, + source_location, + ); + self.compile_simple_connect(conditions, pred_wire.into(), pred, source_location); + match kind { + FormalKind::Assert | FormalKind::Assume => {} + FormalKind::Cover => todo!("simulating hdl_cover isn't implemented: {stmt_formal:?}"), + } + let pred = self.compiled_value_bool_dest_is_small(pred_wire, source_location); + self.asserts.push(Assert { + compiled_assert: CompiledAssert { + instantiated_module, + stmt_formal, + }, + clk_triggered: clk.clk_triggered, + pred, + }); + } fn allocate_delay_chain( &mut self, len: usize, @@ -4825,10 +5011,10 @@ impl Compiler { .iter() .map(|&port| { let target_base = TargetBase::MemPort(port); - let target = TargetInInstantiatedModule { + let target = TargetInInstantiatedModuleOrGlobal::from_target( instantiated_module, - target: target_base.into(), - }; + target_base.into(), + ); self.decl_conditions.insert(target, conditions); let TraceDecl::Scope(TraceScope::MemPort(trace_port)) = self.make_trace_decl(instantiated_module, target_base) @@ -5077,7 +5263,9 @@ impl Compiler { rhs, source_location, ), - Stmt::Formal(StmtFormal { .. }) => todo!("implement simulating formal statements"), + Stmt::Formal(stmt_formal) => { + self.compile_stmt_formal(stmt_formal, parent_module, conditions); + } Stmt::If(StmtIf { cond, source_location, @@ -5144,10 +5332,8 @@ impl Compiler { instantiated_module: InstantiatedModule, clock_for_past: Target, ) -> ExternModuleClockForPast { - let clock_for_past = TargetInInstantiatedModule { - instantiated_module, - target: clock_for_past, - }; + let clock_for_past = + TargetInInstantiatedModuleOrGlobal::from_target(instantiated_module, clock_for_past); let clock_for_past = self .compile_value(clock_for_past) .map_ty(Clock::from_canonical); @@ -5191,10 +5377,11 @@ impl Compiler { module_io, }| { let target_base = TargetBase::from(module_io); - let current = self.compile_value(TargetInInstantiatedModule { - instantiated_module, - target: target_base.into(), - }); + let current = + self.compile_value(TargetInInstantiatedModuleOrGlobal::from_target( + instantiated_module, + target_base.into(), + )); let unprefixed_layout = CompiledTypeLayout::get(module_io.ty()); let past_layout = unprefixed_layout.with_prefixed_debug_names(&format!( "{module_prefix}{:?}$past({trimmed_clock_for_past_debug_name})", @@ -5232,10 +5419,10 @@ impl Compiler { annotations: _, module_io, }| { - let target = TargetInInstantiatedModule { - instantiated_module: *module, - target: Target::from(module_io), - }; + let target = TargetInInstantiatedModuleOrGlobal::from_target( + *module, + Target::from(module_io), + ); self.decl_conditions.insert(target, Interned::default()); trace_decls.push(self.make_trace_decl(*module, module_io.into())); self.compile_value(target) @@ -5432,27 +5619,51 @@ impl Compiler { } } } + fn process_asserts(&mut self) { + for (assert_index, assert) in self.asserts.iter().enumerate() { + let Assert { + ref compiled_assert, + clk_triggered, + pred, + } = *assert; + self.insns.push( + Insn::Assert { + clk_triggered, + pred, + assert_index, + }, + compiled_assert.stmt_formal.source_location, + ); + } + } pub fn compile(mut self) -> Compiled { - let base_module = + let mut base_module = *self.compile_module(InstantiatedModule::Base(self.base_module).intern_sized()); self.process_assignments(); self.process_registers(); self.process_memories(); + self.process_asserts(); let clocks_triggered = self.process_clocks(); self.insns .push(Insn::Return, self.base_module.source_location()); + base_module.trace_decls.children = self + .global_trace_decls + .into_iter() + .chain(base_module.trace_decls.children) + .collect(); Compiled { insns: Insns::from(self.insns).intern_sized(), base_module, extern_modules: Intern::intern_owned(self.extern_modules), io: Instance::new_unchecked( ScopedNameId( - NameId("".intern(), Id::new()), + NameId("".intern(), Id::new()).into(), self.original_base_module.name_id(), ), self.original_base_module, self.original_base_module.source_location(), ), + global_io: Interned::from_iter(self.global_io), traces: SimTraces(Intern::intern_owned(self.traces.0)), trace_memories: Interned::from_iter(self.memories.iter().map( |&Memory { @@ -5463,6 +5674,11 @@ impl Compiler { }| (memory, trace), )), clocks_triggered, + asserts: Interned::from_iter( + self.asserts + .into_iter() + .map(|assert| assert.compiled_assert), + ), } } } @@ -5479,9 +5695,11 @@ pub struct Compiled { pub(crate) base_module: CompiledModule, pub(crate) extern_modules: Interned<[CompiledExternModule]>, pub(crate) io: Instance, + pub(crate) global_io: Interned<[(SimIoForGlobal, CompiledValue)]>, pub(crate) traces: SimTraces]>>, pub(crate) trace_memories: Interned<[(StatePartIndex, TraceMem)]>, pub(crate) clocks_triggered: Interned<[StatePartIndex]>, + pub(crate) asserts: Interned<[CompiledAssert]>, } impl Compiled { @@ -5494,18 +5712,22 @@ impl Compiled { base_module, extern_modules, io, + global_io, traces, trace_memories, clocks_triggered, + asserts, } = self; Compiled { insns, base_module, extern_modules, io: Instance::from_canonical(io.canonical()), + global_io, traces, trace_memories, clocks_triggered, + asserts, } } pub fn from_canonical(canonical: Compiled) -> Self { @@ -5514,18 +5736,22 @@ impl Compiled { base_module, extern_modules, io, + global_io, traces, trace_memories, clocks_triggered, + asserts, } = canonical; Self { insns, base_module, extern_modules, io: Instance::from_canonical(io.canonical()), + global_io, traces, trace_memories, clocks_triggered, + asserts, } } } diff --git a/crates/fayalite/src/sim/interpreter.rs b/crates/fayalite/src/sim/interpreter.rs index 6b3eced..ee3331f 100644 --- a/crates/fayalite/src/sim/interpreter.rs +++ b/crates/fayalite/src/sim/interpreter.rs @@ -980,6 +980,7 @@ macro_rules! make_state { pub(crate) insns: Interned>, pub(crate) pc: usize, pub(crate) memory_write_log: Vec<(StatePartIndex, usize)>, + pub(crate) assert_failed_log: Vec, $(pub(crate) $state_plural_field: StatePart<$state_kind>,)* $(pub(crate) $type_plural_field: StatePart<$type_kind>,)* } @@ -990,6 +991,7 @@ macro_rules! make_state { insns: _, pc, memory_write_log, + assert_failed_log, $($state_plural_field,)* $($type_plural_field,)* } = self; @@ -997,6 +999,7 @@ macro_rules! make_state { .field("insns", &InsnsOfState(self)) .field("pc", pc) .field("memory_write_log", memory_write_log) + .field("assert_failed_log", assert_failed_log) $(.field(stringify!($state_plural_field), $state_plural_field))* $(.field(stringify!($type_plural_field), $type_plural_field))* .finish() @@ -1009,6 +1012,7 @@ macro_rules! make_state { insns, pc: 0, memory_write_log: Vec::with_capacity(32), + assert_failed_log: Vec::new(), $($state_plural_field: StatePart::new(&insns.state_layout.$state_plural_field.layout_data),)* $($type_plural_field: StatePart::new(&insns.state_layout.ty.$type_plural_field.layout_data),)* } @@ -1020,6 +1024,7 @@ macro_rules! make_state { pc: self.pc, orig_pc: &mut self.pc, memory_write_log: &mut self.memory_write_log, + assert_failed_log: &mut self.assert_failed_log, $($state_plural_field: self.$state_plural_field.borrow(),)* $($type_plural_field: self.$type_plural_field.borrow(),)* } @@ -1042,6 +1047,7 @@ macro_rules! make_state { pub(crate) orig_pc: &'a mut usize, pub(crate) pc: usize, pub(crate) memory_write_log: &'a mut Vec<(StatePartIndex, usize)>, + pub(crate) assert_failed_log: &'a mut Vec, $(pub(crate) $state_plural_field: BorrowedStatePart<'a, $state_kind>,)* $(pub(crate) $type_plural_field: BorrowedStatePart<'a, $type_kind>,)* } @@ -1299,6 +1305,7 @@ impl State { insns: _, pc, memory_write_log: _, + assert_failed_log: _, memories: _, small_slots: _, big_slots: _, @@ -1338,6 +1345,10 @@ impl BorrowedState<'_> { self.memory_write_log.push(log_entry); } } + #[cold] + fn assert_failed(&mut self, assert_index: usize) { + self.assert_failed_log.push(assert_index); + } } fn bigint_pow2(width: usize) -> Interned { @@ -2105,6 +2116,19 @@ impl_insns! { state.log_memory_write(memory, addr); next!(); } + Assert { + #[kind = Input] + clk_triggered: StatePartIndex, + #[kind = Input] + pred: StatePartIndex, + #[kind = Immediate] + assert_index: usize, + } => { + if state.small_slots[clk_triggered] != 0 && state.small_slots[pred] == 0 { + state.assert_failed(assert_index); + } + next!(); + } Return => { break RunResult::Return(()); } diff --git a/crates/fayalite/src/sim/vcd.rs b/crates/fayalite/src/sim/vcd.rs index 09e7d66..17ad206 100644 --- a/crates/fayalite/src/sim/vcd.rs +++ b/crates/fayalite/src/sim/vcd.rs @@ -9,11 +9,11 @@ use crate::{ prelude::PhantomConst, sim::{ TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl, - TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance, - TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule, - TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, TraceScalar, TraceScalarId, - TraceScope, TraceSimOnly, TraceSyncReset, TraceTraceAsString, TraceUInt, TraceWire, - TraceWriter, TraceWriterDecls, + TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceFormalInput, + TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, + TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, TraceScalar, + TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceTraceAsString, TraceUInt, + TraceWire, TraceWriter, TraceWriterDecls, time::{SimDuration, SimInstant}, value::DynSimOnlyValue, }, @@ -766,6 +766,7 @@ impl WriteTrace for TraceScope { Self::Wire(v) => v.write_trace(writer, arg), Self::Reg(v) => v.write_trace(writer, arg), Self::ModuleIO(v) => v.write_trace(writer, arg), + Self::FormalInput(v) => v.write_trace(writer, arg), Self::Bundle(v) => v.write_trace(writer, arg), Self::Array(v) => v.write_trace(writer, arg), Self::EnumWithFields(v) => v.write_trace(writer, arg), @@ -963,6 +964,27 @@ impl WriteTrace for TraceModuleIO { } } +impl WriteTrace for TraceFormalInput { + fn write_trace(self, writer: &mut W, mut arg: A) -> io::Result<()> { + let ArgModuleBody { properties, scope } = arg.module_body(); + let Self { + name: _, + child, + formal_input: _, + } = self; + child.write_trace( + writer, + ArgInType { + source_var_type: "wire", + sink_var_type: "wire", + duplex_var_type: "wire", + properties, + scope: Some(scope), + }, + ) + } +} + impl WriteTrace for TraceBundle { fn write_trace(self, writer: &mut W, mut arg: A) -> io::Result<()> { let ArgInType { diff --git a/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs b/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs index 2d498e7..620e78c 100644 --- a/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs +++ b/crates/fayalite/src/vendor/xilinx/yosys_nextpnr_prjxray.rs @@ -595,6 +595,9 @@ impl Visitor for XdcFileWriter { v, instance.source_location(), )? {}, + TargetBase::FormalInput(_) | TargetBase::SimIoForGlobal(_) => { + unreachable!("base.is_valid_annotation_target() is known to be false") + } } } } diff --git a/crates/fayalite/src/wire.rs b/crates/fayalite/src/wire.rs index a350d9a..d167c5f 100644 --- a/crates/fayalite/src/wire.rs +++ b/crates/fayalite/src/wire.rs @@ -58,11 +58,13 @@ impl Wire { ty: T::from_canonical(ty), } } + #[track_caller] pub fn new_unchecked( scoped_name: ScopedNameId, source_location: SourceLocation, ty: T, ) -> Self { + scoped_name.0.assert_is_name_id(); Self { name: scoped_name, source_location, @@ -76,7 +78,7 @@ impl Wire { self.containing_module_name_id().0 } pub fn containing_module_name_id(&self) -> NameId { - self.name.0 + self.name.0.unwrap_name_id() } pub fn name(&self) -> Interned { self.name_id().0 diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index 5c62933..aa028f4 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -3683,20 +3683,176 @@ circuit check_formal: %[[ input pred1: UInt<1> @[module-XXXXXXXXXX.rs 6:1] input pred2: UInt<1> @[module-XXXXXXXXXX.rs 7:1] input pred3: UInt<1> @[module-XXXXXXXXXX.rs 8:1] - inst formal_reset of formal_reset @[formal.rs 185:24] + inst formal_reset of formal_reset @[builtin 1:1] assert(clk, pred1, and(en1, not(formal_reset.rst)), "en check 1") @[module-XXXXXXXXXX.rs 9:1] - inst formal_reset_1 of formal_reset @[formal.rs 185:24] - assume(clk, pred2, and(en2, not(formal_reset_1.rst)), "en check 2") @[module-XXXXXXXXXX.rs 10:1] - inst formal_reset_2 of formal_reset @[formal.rs 185:24] - cover(clk, pred3, and(en3, not(formal_reset_2.rst)), "en check 3") @[module-XXXXXXXXXX.rs 11:1] - inst formal_reset_3 of formal_reset @[formal.rs 185:24] - assert(clk, pred1, and(UInt<1>(0h1), not(formal_reset_3.rst)), "check 1") @[module-XXXXXXXXXX.rs 12:1] - inst formal_reset_4 of formal_reset @[formal.rs 185:24] - assume(clk, pred2, and(UInt<1>(0h1), not(formal_reset_4.rst)), "check 2") @[module-XXXXXXXXXX.rs 13:1] - inst formal_reset_5 of formal_reset @[formal.rs 185:24] - cover(clk, pred3, and(UInt<1>(0h1), not(formal_reset_5.rst)), "check 3") @[module-XXXXXXXXXX.rs 14:1] - extmodule formal_reset: @[formal.rs 169:5] - output rst: UInt<1> @[formal.rs 172:32] + assume(clk, pred2, and(en2, not(formal_reset.rst)), "en check 2") @[module-XXXXXXXXXX.rs 10:1] + cover(clk, pred3, and(en3, not(formal_reset.rst)), "en check 3") @[module-XXXXXXXXXX.rs 11:1] + assert(clk, pred1, and(UInt<1>(0h1), not(formal_reset.rst)), "check 1") @[module-XXXXXXXXXX.rs 12:1] + assume(clk, pred2, and(UInt<1>(0h1), not(formal_reset.rst)), "check 2") @[module-XXXXXXXXXX.rs 13:1] + cover(clk, pred3, and(UInt<1>(0h1), not(formal_reset.rst)), "check 3") @[module-XXXXXXXXXX.rs 14:1] + extmodule formal_reset: @[builtin 1:1] + output rst: UInt<1> @[builtin 1:1] + defname = __fayalite_formal_reset +"#, + }; +} + +#[hdl_module(outline_generated)] +pub fn check_formal_input() { + #[hdl] + let bool_in: Bool = m.input(); + #[hdl] + let bool_out: Bool = m.output(); + #[hdl] + let any_const_out1: Bool = m.output(); + #[hdl] + let any_const_out2: UInt<16> = m.output(); + #[hdl] + let any_const_out3: SInt<12> = m.output(); + #[hdl] + let any_seq_out: UInt<10> = m.output(); + #[hdl] + let all_const_out: UInt<10> = m.output(); + #[hdl] + let all_seq_out: UInt<10> = m.output(); + + #[hdl] + let bool_reg = reg_builder() + .clock_domain( + #[hdl] + ClockDomain { + clk: formal_global_clock(), + rst: formal_reset(), + }, + ) + .reset(false); + + connect(bool_reg, bool_in); + connect(bool_out, bool_reg); + connect(any_const_out1, any_const(StaticType::TYPE)); + connect(any_const_out2, any_const(StaticType::TYPE)); + connect(any_const_out3, any_const(StaticType::TYPE)); + connect(any_seq_out, any_seq(StaticType::TYPE)); + connect(all_const_out, all_const(StaticType::TYPE)); + connect(all_seq_out, all_seq(StaticType::TYPE)); +} + +#[test] +fn test_formal_input() { + let _n = SourceLocation::normalize_files_for_tests(); + let m = check_formal_input(); + dbg!(m); + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + "/test/check_formal_input.fir": r#"FIRRTL version 3.2.0 +circuit check_formal_input: %[[ + { + "class": "firrtl.AttributeAnnotation", + "description": "gclk", + "target": "~check_formal_input|check_formal_input>formal_global_clock" + }, + { + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~check_formal_input|check_formal_input>formal_global_clock" + }, + { + "class": "firrtl.AttributeAnnotation", + "description": "anyconst", + "target": "~check_formal_input|check_formal_input>any_const" + }, + { + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~check_formal_input|check_formal_input>any_const" + }, + { + "class": "firrtl.AttributeAnnotation", + "description": "anyconst", + "target": "~check_formal_input|check_formal_input>any_const_1" + }, + { + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~check_formal_input|check_formal_input>any_const_1" + }, + { + "class": "firrtl.AttributeAnnotation", + "description": "anyconst", + "target": "~check_formal_input|check_formal_input>any_const_2" + }, + { + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~check_formal_input|check_formal_input>any_const_2" + }, + { + "class": "firrtl.AttributeAnnotation", + "description": "anyseq", + "target": "~check_formal_input|check_formal_input>any_seq" + }, + { + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~check_formal_input|check_formal_input>any_seq" + }, + { + "class": "firrtl.AttributeAnnotation", + "description": "allconst", + "target": "~check_formal_input|check_formal_input>all_const" + }, + { + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~check_formal_input|check_formal_input>all_const" + }, + { + "class": "firrtl.AttributeAnnotation", + "description": "allseq", + "target": "~check_formal_input|check_formal_input>all_seq" + }, + { + "class": "firrtl.transforms.DontTouchAnnotation", + "target": "~check_formal_input|check_formal_input>all_seq" + }, + { + "class": "firrtl.transforms.BlackBoxInlineAnno", + "name": "fayalite_formal_reset.v", + "text": "module __fayalite_formal_reset(output rst);\n assign rst = $initstate;\nendmodule\n", + "target": "~check_formal_input|formal_reset" + } +]] + type Ty0 = {clk: Clock, rst: UInt<1>} + type Ty1 = {rst: UInt<1>} + module check_formal_input: @[module-XXXXXXXXXX.rs 1:1] + input bool_in: UInt<1> @[module-XXXXXXXXXX.rs 2:1] + output bool_out: UInt<1> @[module-XXXXXXXXXX.rs 3:1] + output any_const_out1: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + output any_const_out2: UInt<16> @[module-XXXXXXXXXX.rs 5:1] + output any_const_out3: SInt<12> @[module-XXXXXXXXXX.rs 6:1] + output any_seq_out: UInt<10> @[module-XXXXXXXXXX.rs 7:1] + output all_const_out: UInt<10> @[module-XXXXXXXXXX.rs 8:1] + output all_seq_out: UInt<10> @[module-XXXXXXXXXX.rs 9:1] + wire _bundle_literal_expr_1: Ty0 + connect _bundle_literal_expr_1.clk, asClock(UInt<1>(0h0)) + connect _bundle_literal_expr_1.rst, UInt<1>(0h0) + reg formal_global_clock: UInt<1>, _bundle_literal_expr_1.clk @[builtin 1:1] + inst formal_reset of formal_reset @[builtin 1:1] + reg any_const: UInt<1>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 13:1] + reg any_const_1: UInt<16>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 15:1] + reg any_const_2: SInt<12>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 17:1] + reg any_seq: UInt<10>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 19:1] + reg all_const: UInt<10>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 21:1] + reg all_seq: UInt<10>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 23:1] + wire _bundle_literal_expr: Ty0 + connect _bundle_literal_expr.clk, asClock(formal_global_clock) + connect _bundle_literal_expr.rst, formal_reset.rst + regreset bool_reg: UInt<1>, _bundle_literal_expr.clk, _bundle_literal_expr.rst, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 10:1] + connect bool_reg, bool_in @[module-XXXXXXXXXX.rs 11:1] + connect bool_out, bool_reg @[module-XXXXXXXXXX.rs 12:1] + connect any_const_out1, any_const @[module-XXXXXXXXXX.rs 14:1] + connect any_const_out2, any_const_1 @[module-XXXXXXXXXX.rs 16:1] + connect any_const_out3, any_const_2 @[module-XXXXXXXXXX.rs 18:1] + connect any_seq_out, any_seq @[module-XXXXXXXXXX.rs 20:1] + connect all_const_out, all_const @[module-XXXXXXXXXX.rs 22:1] + connect all_seq_out, all_seq @[module-XXXXXXXXXX.rs 24:1] + extmodule formal_reset: @[builtin 1:1] + output rst: UInt<1> @[builtin 1:1] defname = __fayalite_formal_reset "#, }; diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index 80ae4c2..223c4bc 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -5,6 +5,7 @@ use bitvec::{order::Lsb0, view::BitView}; use fayalite::{ assert_export_firrtl, firrtl::ExportOptions, + formal::FormalInputKind, memory::{ReadStruct, ReadWriteStruct, WriteStruct, splat_mask}, module::{ instance_with_loc, memory_with_init_and_loc, reg_builder_with_loc, @@ -16,7 +17,12 @@ use fayalite::{ ty::SimValueDebug, util::{RcWriter, ready_valid::queue}, }; -use std::{collections::BTreeMap, num::NonZeroUsize, rc::Rc}; +use std::{ + collections::BTreeMap, + num::NonZeroUsize, + panic::{AssertUnwindSafe, catch_unwind, resume_unwind}, + rc::Rc, +}; #[hdl_module(outline_generated)] pub fn connect_const() { @@ -3610,3 +3616,136 @@ circuit sim_trace_as_string: %[[ ", }; } + +#[hdl_module(outline_generated)] +pub fn formal_counter(count_modulus: u8, asserted_max_count: u8) { + #[hdl] + let cd = wire(); + connect( + cd, + #[hdl] + ClockDomain { + clk: formal_global_clock(), + rst: formal_reset(), + }, + ); + #[hdl] + let count_reg: UInt<8> = reg_builder().clock_domain(cd).reset(0u8); + let next_count = count_reg + 1u8; + #[hdl] + if next_count.cmp_lt(count_modulus) { + connect_any(count_reg, next_count); + } else { + connect(count_reg, 0u8); + } + #[hdl] + let count: UInt<8> = m.output(); + connect(count, count_reg); + #[hdl] + let enable_assert: Bool = m.input(); + #[hdl] + if enable_assert { + hdl_assert(cd.clk, count_reg.cmp_le(asserted_max_count), ""); + } + #[hdl] + let any_seq_out: UInt<16> = m.output(); + connect(any_seq_out, any_seq(any_seq_out.ty())); +} + +#[hdl] +#[test] +fn test_formal_counter() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(formal_counter(10, 10)); + let _checked_vcd_output = + checked_vcd_output!(&mut sim, "tests/sim/expected/test_formal_counter.vcd"); + let Some((_, any_seq_in)) = sim + .global_io() + .into_iter() + .find(|(global, _)| global.kind() == FormalInputKind::AnySeq) + else { + panic!("can't find any_seq"); + }; + let any_seq_in = Expr::>::from_canonical(any_seq_in); + sim.write_clock(formal_global_clock(), false); + sim.write_reset(formal_reset(), true); + sim.write(any_seq_in, 0u16); + sim.write(sim.io().enable_assert, true); + sim.advance_time(SimDuration::from_micros(1)); + assert_eq!(sim.read(sim.io().any_seq_out).as_int(), 0u16); + sim.write_clock(formal_global_clock(), true); + sim.write(any_seq_in, 1234u16); + assert_eq!(sim.read(sim.io().any_seq_out).as_int(), 1234u16); + assert_eq!(sim.read(sim.io().count).as_int(), 0); + sim.write_reset(formal_reset(), false); + sim.advance_time(SimDuration::from_micros(1)); + for i in 0..32u8 { + assert_eq!(i % 10, sim.read(sim.io().count).as_int()); + sim.write_clock(formal_global_clock(), false); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(formal_global_clock(), true); + sim.advance_time(SimDuration::from_micros(1)); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/test_formal_counter.txt") { + panic!(); + } +} + +#[cfg(panic = "unwind")] +#[hdl] +#[test] +fn test_formal_counter_assert() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(formal_counter(10, 8)); + let _checked_vcd_output = checked_vcd_output!( + &mut sim, + "tests/sim/expected/test_formal_counter_assert.vcd" + ); + let Some((_, any_seq_in)) = sim + .global_io() + .into_iter() + .find(|(global, _)| global.kind() == FormalInputKind::AnySeq) + else { + panic!("can't find any_seq"); + }; + let any_seq_in = Expr::>::from_canonical(any_seq_in); + let half_us = SimDuration::from_nanos(500); + sim.write_clock(formal_global_clock(), false); + sim.write_reset(formal_reset(), true); + sim.write(any_seq_in, 0u16); + sim.write(sim.io().enable_assert, false); + sim.advance_time(half_us); + assert_eq!(sim.read(sim.io().any_seq_out).as_int(), 0u16); + sim.write_clock(formal_global_clock(), true); + sim.write(any_seq_in, 1234u16); + assert_eq!(sim.read(sim.io().any_seq_out).as_int(), 1234u16); + assert_eq!(sim.read(sim.io().count).as_int(), 0); + sim.write_reset(formal_reset(), false); + sim.advance_time(half_us); + const PANIC_MSG: &str = "Assertions/Assumptions failed at time 20.500000000000 \u{3bc}s:\n\ +at module-XXXXXXXXXX.rs:12:1: in InstantiatedModule(formal_counter: formal_counter): assert failed: \n"; + const EXPECTED_FAILURE_CYCLE: u8 = 19; + for i in 0.. { + dbg!(i); + assert_eq!(i % 10, sim.read(sim.io().count).as_int()); + sim.write(sim.io().enable_assert, i > 15); + sim.write_clock(formal_global_clock(), false); + sim.advance_time(half_us); + match catch_unwind(AssertUnwindSafe(|| { + sim.write_clock(formal_global_clock(), true); + sim.advance_time(half_us); + })) { + Ok(()) => assert!(i < EXPECTED_FAILURE_CYCLE), + Err(e) => match e.downcast::() { + Ok(e) if *e == PANIC_MSG => { + assert_eq!(i, EXPECTED_FAILURE_CYCLE); + break; + } + Ok(e) => resume_unwind(e), + Err(e) => resume_unwind(e), + }, + } + } +} diff --git a/crates/fayalite/tests/sim/expected/array_rw.txt b/crates/fayalite/tests/sim/expected/array_rw.txt index 271ec3c..e6a0a7a 100644 --- a/crates/fayalite/tests/sim/expected/array_rw.txt +++ b/crates/fayalite/tests/sim/expected/array_rw.txt @@ -419,6 +419,7 @@ Simulation { }, pc: 38, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -497,6 +498,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -1759,5 +1761,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt index 74c03a4..8013727 100644 --- a/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt +++ b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt @@ -76,6 +76,7 @@ Simulation { }, pc: 5, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -101,6 +102,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -186,5 +188,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/connect_const.txt b/crates/fayalite/tests/sim/expected/connect_const.txt index 8193fc5..9ec4a83 100644 --- a/crates/fayalite/tests/sim/expected/connect_const.txt +++ b/crates/fayalite/tests/sim/expected/connect_const.txt @@ -54,6 +54,7 @@ Simulation { }, pc: 2, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -77,6 +78,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -138,5 +140,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/connect_const_reset.txt b/crates/fayalite/tests/sim/expected/connect_const_reset.txt index 5a64923..dfbc3b9 100644 --- a/crates/fayalite/tests/sim/expected/connect_const_reset.txt +++ b/crates/fayalite/tests/sim/expected/connect_const_reset.txt @@ -80,6 +80,7 @@ Simulation { }, pc: 5, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -106,6 +107,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -206,5 +208,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/counter_async.txt b/crates/fayalite/tests/sim/expected/counter_async.txt index 20d27ac..c05ed80 100644 --- a/crates/fayalite/tests/sim/expected/counter_async.txt +++ b/crates/fayalite/tests/sim/expected/counter_async.txt @@ -180,6 +180,7 @@ Simulation { }, pc: 19, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -216,6 +217,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -385,5 +387,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/counter_sync.txt b/crates/fayalite/tests/sim/expected/counter_sync.txt index baa08e7..5834877 100644 --- a/crates/fayalite/tests/sim/expected/counter_sync.txt +++ b/crates/fayalite/tests/sim/expected/counter_sync.txt @@ -162,6 +162,7 @@ Simulation { }, pc: 16, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -197,6 +198,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -366,5 +368,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/duplicate_names.txt b/crates/fayalite/tests/sim/expected/duplicate_names.txt index 76338e8..3a4c115 100644 --- a/crates/fayalite/tests/sim/expected/duplicate_names.txt +++ b/crates/fayalite/tests/sim/expected/duplicate_names.txt @@ -72,6 +72,7 @@ Simulation { }, pc: 4, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -97,6 +98,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [], uninitialized_ios: {}, @@ -169,5 +171,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/enum_with_simple_body.txt b/crates/fayalite/tests/sim/expected/enum_with_simple_body.txt index 6b5af1c..e7c6a85 100644 --- a/crates/fayalite/tests/sim/expected/enum_with_simple_body.txt +++ b/crates/fayalite/tests/sim/expected/enum_with_simple_body.txt @@ -409,6 +409,7 @@ Simulation { }, pc: 45, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -465,6 +466,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -745,5 +747,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/enums.txt b/crates/fayalite/tests/sim/expected/enums.txt index d2da2d9..a539f96 100644 --- a/crates/fayalite/tests/sim/expected/enums.txt +++ b/crates/fayalite/tests/sim/expected/enums.txt @@ -1184,6 +1184,7 @@ Simulation { }, pc: 133, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -1324,6 +1325,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -1955,5 +1957,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/extern_module.txt b/crates/fayalite/tests/sim/expected/extern_module.txt index 48a3af5..fa003d3 100644 --- a/crates/fayalite/tests/sim/expected/extern_module.txt +++ b/crates/fayalite/tests/sim/expected/extern_module.txt @@ -44,6 +44,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -67,6 +68,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -261,5 +263,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/extern_module2.txt b/crates/fayalite/tests/sim/expected/extern_module2.txt index d488666..8c03792 100644 --- a/crates/fayalite/tests/sim/expected/extern_module2.txt +++ b/crates/fayalite/tests/sim/expected/extern_module2.txt @@ -48,6 +48,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -72,6 +73,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -416,5 +418,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/last_connect.txt b/crates/fayalite/tests/sim/expected/last_connect.txt index c5d1341..e62c0b7 100644 --- a/crates/fayalite/tests/sim/expected/last_connect.txt +++ b/crates/fayalite/tests/sim/expected/last_connect.txt @@ -407,6 +407,7 @@ Simulation { }, pc: 44, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -464,6 +465,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -705,5 +707,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/many_memories.txt b/crates/fayalite/tests/sim/expected/many_memories.txt index 0d1a6db..1cb60ae 100644 --- a/crates/fayalite/tests/sim/expected/many_memories.txt +++ b/crates/fayalite/tests/sim/expected/many_memories.txt @@ -2728,6 +2728,7 @@ Simulation { }, pc: 256, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -3183,6 +3184,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -7927,5 +7929,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/memories.txt b/crates/fayalite/tests/sim/expected/memories.txt index c96da4f..f2f4fb6 100644 --- a/crates/fayalite/tests/sim/expected/memories.txt +++ b/crates/fayalite/tests/sim/expected/memories.txt @@ -494,6 +494,7 @@ Simulation { }, pc: 41, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -579,6 +580,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -1650,5 +1652,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/memories2.txt b/crates/fayalite/tests/sim/expected/memories2.txt index 1f78fcf..239802c 100644 --- a/crates/fayalite/tests/sim/expected/memories2.txt +++ b/crates/fayalite/tests/sim/expected/memories2.txt @@ -526,6 +526,7 @@ Simulation { }, pc: 52, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -607,6 +608,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -1285,5 +1287,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/memories3.txt b/crates/fayalite/tests/sim/expected/memories3.txt index 75720a8..1fcbab1 100644 --- a/crates/fayalite/tests/sim/expected/memories3.txt +++ b/crates/fayalite/tests/sim/expected/memories3.txt @@ -1336,6 +1336,7 @@ Simulation { }, pc: 129, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1495,6 +1496,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -3345,5 +3347,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/mod1.txt b/crates/fayalite/tests/sim/expected/mod1.txt index a1de89a..ab144d3 100644 --- a/crates/fayalite/tests/sim/expected/mod1.txt +++ b/crates/fayalite/tests/sim/expected/mod1.txt @@ -187,6 +187,7 @@ Simulation { }, pc: 17, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -225,6 +226,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -577,5 +579,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/phantom_const.txt b/crates/fayalite/tests/sim/expected/phantom_const.txt index c9adae4..60ccff5 100644 --- a/crates/fayalite/tests/sim/expected/phantom_const.txt +++ b/crates/fayalite/tests/sim/expected/phantom_const.txt @@ -172,6 +172,7 @@ Simulation { }, pc: 16, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -215,6 +216,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -527,5 +529,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_1_false_false.txt b/crates/fayalite/tests/sim/expected/queue_1_false_false.txt index e349bbd..6586ce5 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_false_false.txt @@ -1083,6 +1083,7 @@ Simulation { }, pc: 134, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1201,6 +1202,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2160,5 +2162,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_1_false_true.txt b/crates/fayalite/tests/sim/expected/queue_1_false_true.txt index 3a31636..3fabc74 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_false_true.txt @@ -1064,6 +1064,7 @@ Simulation { }, pc: 132, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1180,6 +1181,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2139,5 +2141,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_1_true_false.txt b/crates/fayalite/tests/sim/expected/queue_1_true_false.txt index 9dd3851..54a2d06 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_true_false.txt @@ -1093,6 +1093,7 @@ Simulation { }, pc: 136, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1211,6 +1212,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2170,5 +2172,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_1_true_true.txt b/crates/fayalite/tests/sim/expected/queue_1_true_true.txt index 5762f24..f0e86e5 100644 --- a/crates/fayalite/tests/sim/expected/queue_1_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_1_true_true.txt @@ -1074,6 +1074,7 @@ Simulation { }, pc: 134, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1190,6 +1191,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2149,5 +2151,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_2_false_false.txt b/crates/fayalite/tests/sim/expected/queue_2_false_false.txt index c2cb51a..6bf6992 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_false_false.txt @@ -1098,6 +1098,7 @@ Simulation { }, pc: 135, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1219,6 +1220,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2178,5 +2180,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_2_false_true.txt b/crates/fayalite/tests/sim/expected/queue_2_false_true.txt index f229451..2fe8866 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_false_true.txt @@ -1079,6 +1079,7 @@ Simulation { }, pc: 133, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1198,6 +1199,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2157,5 +2159,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_2_true_false.txt b/crates/fayalite/tests/sim/expected/queue_2_true_false.txt index e137316..cc340b8 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_true_false.txt @@ -1108,6 +1108,7 @@ Simulation { }, pc: 137, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1229,6 +1230,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2188,5 +2190,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_2_true_true.txt b/crates/fayalite/tests/sim/expected/queue_2_true_true.txt index 5203027..9cc2206 100644 --- a/crates/fayalite/tests/sim/expected/queue_2_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_2_true_true.txt @@ -1089,6 +1089,7 @@ Simulation { }, pc: 135, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1208,6 +1209,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2167,5 +2169,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_3_false_false.txt b/crates/fayalite/tests/sim/expected/queue_3_false_false.txt index f5641ce..1086ca0 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_false_false.txt @@ -1125,6 +1125,7 @@ Simulation { }, pc: 139, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1248,6 +1249,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2187,5 +2189,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_3_false_true.txt b/crates/fayalite/tests/sim/expected/queue_3_false_true.txt index cde5489..1e95f7b 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_false_true.txt @@ -1106,6 +1106,7 @@ Simulation { }, pc: 137, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1227,6 +1228,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2166,5 +2168,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_3_true_false.txt b/crates/fayalite/tests/sim/expected/queue_3_true_false.txt index d943150..be9e7ef 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_true_false.txt @@ -1135,6 +1135,7 @@ Simulation { }, pc: 141, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1258,6 +1259,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2197,5 +2199,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_3_true_true.txt b/crates/fayalite/tests/sim/expected/queue_3_true_true.txt index 4a0f664..3e691c1 100644 --- a/crates/fayalite/tests/sim/expected/queue_3_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_3_true_true.txt @@ -1116,6 +1116,7 @@ Simulation { }, pc: 139, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1237,6 +1238,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2176,5 +2178,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_4_false_false.txt b/crates/fayalite/tests/sim/expected/queue_4_false_false.txt index 4e0a067..c220ba9 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_false_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_false_false.txt @@ -1104,6 +1104,7 @@ Simulation { }, pc: 135, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1227,6 +1228,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2186,5 +2188,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_4_false_true.txt b/crates/fayalite/tests/sim/expected/queue_4_false_true.txt index a374f44..896783b 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_false_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_false_true.txt @@ -1085,6 +1085,7 @@ Simulation { }, pc: 133, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1206,6 +1207,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2165,5 +2167,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_4_true_false.txt b/crates/fayalite/tests/sim/expected/queue_4_true_false.txt index 7d20f26..4f500fa 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_true_false.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_true_false.txt @@ -1114,6 +1114,7 @@ Simulation { }, pc: 137, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1237,6 +1238,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2196,5 +2198,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/queue_4_true_true.txt b/crates/fayalite/tests/sim/expected/queue_4_true_true.txt index a0ee509..bf97cd2 100644 --- a/crates/fayalite/tests/sim/expected/queue_4_true_true.txt +++ b/crates/fayalite/tests/sim/expected/queue_4_true_true.txt @@ -1095,6 +1095,7 @@ Simulation { }, pc: 135, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -1216,6 +1217,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2175,5 +2177,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/ripple_counter.txt b/crates/fayalite/tests/sim/expected/ripple_counter.txt index 6562d4d..9641ed5 100644 --- a/crates/fayalite/tests/sim/expected/ripple_counter.txt +++ b/crates/fayalite/tests/sim/expected/ripple_counter.txt @@ -636,6 +636,7 @@ Simulation { }, pc: 69, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -725,6 +726,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -1790,5 +1792,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/shift_register.txt b/crates/fayalite/tests/sim/expected/shift_register.txt index 1eaa378..70ebccd 100644 --- a/crates/fayalite/tests/sim/expected/shift_register.txt +++ b/crates/fayalite/tests/sim/expected/shift_register.txt @@ -254,6 +254,7 @@ Simulation { }, pc: 34, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -293,6 +294,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -545,5 +547,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_fork_join.txt b/crates/fayalite/tests/sim/expected/sim_fork_join.txt index c66e77e..b291af7 100644 --- a/crates/fayalite/tests/sim/expected/sim_fork_join.txt +++ b/crates/fayalite/tests/sim/expected/sim_fork_join.txt @@ -60,6 +60,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -87,6 +88,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -521,5 +523,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt b/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt index ae88960..1b0efd5 100644 --- a/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt +++ b/crates/fayalite/tests/sim/expected/sim_fork_join_scope.txt @@ -60,6 +60,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -87,6 +88,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -521,5 +523,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_only_connects.txt b/crates/fayalite/tests/sim/expected/sim_only_connects.txt index 2ae2fbe..241ef46 100644 --- a/crates/fayalite/tests/sim/expected/sim_only_connects.txt +++ b/crates/fayalite/tests/sim/expected/sim_only_connects.txt @@ -375,6 +375,7 @@ Simulation { }, pc: 41, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -475,6 +476,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -1768,5 +1770,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_read_past.txt b/crates/fayalite/tests/sim/expected/sim_read_past.txt index f771434..3866eb9 100644 --- a/crates/fayalite/tests/sim/expected/sim_read_past.txt +++ b/crates/fayalite/tests/sim/expected/sim_read_past.txt @@ -512,6 +512,7 @@ Simulation { }, pc: 57, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -591,6 +592,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -9726,5 +9728,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt index 5584b73..b55fd8c 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt @@ -48,6 +48,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -72,6 +73,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -539,5 +541,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt index f03c25a..29870da 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt @@ -48,6 +48,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -72,6 +73,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -539,5 +541,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt index c93d6c1..0885cc9 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt @@ -48,6 +48,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -72,6 +73,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -497,5 +499,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt index f13af84..068edb2 100644 --- a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt @@ -48,6 +48,7 @@ Simulation { }, pc: 0, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [], }, @@ -72,6 +73,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -497,5 +499,6 @@ Simulation { }, ), }, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_trace_as_string.txt b/crates/fayalite/tests/sim/expected/sim_trace_as_string.txt index 0dd374c..4befbfc 100644 --- a/crates/fayalite/tests/sim/expected/sim_trace_as_string.txt +++ b/crates/fayalite/tests/sim/expected/sim_trace_as_string.txt @@ -494,6 +494,7 @@ Simulation { }, pc: 43, memory_write_log: [], + assert_failed_log: [], memories: StatePart { value: [ MemoryData { @@ -570,6 +571,7 @@ Simulation { .. }, }, + global_io: {}, main_module: SimulationModuleState { base_targets: [ Instance { @@ -2250,5 +2252,6 @@ Simulation { }), waiting_sensitivity_sets_by_address: {}, waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [], .. } \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/test_formal_counter.txt b/crates/fayalite/tests/sim/expected/test_formal_counter.txt new file mode 100644 index 0000000..fc90a1a --- /dev/null +++ b/crates/fayalite/tests/sim/expected/test_formal_counter.txt @@ -0,0 +1,855 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 5, + debug_data: [ + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + ], + .. + }, + big_slots: StatePartLayout { + len: 26, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::enable_assert", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::any_seq_out", + ty: UInt<16>, + }, + SlotDebugData { + name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::cd.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::cd.rst", + ty: SyncReset, + }, + SlotDebugData { + name: ".clk", + ty: Clock, + }, + SlotDebugData { + name: ".rst", + ty: SyncReset, + }, + SlotDebugData { + name: "<>::formal_global_clock", + ty: Clock, + }, + SlotDebugData { + name: "<>::formal_reset", + ty: SyncReset, + }, + SlotDebugData { + name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg", + ty: UInt<8>, + }, + SlotDebugData { + name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg$next", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<9>, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "<>::any_seq", + ty: UInt<16>, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + memories: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + insns: [ + // at: module-XXXXXXXXXX.rs:15:1 + 0: Copy { + dest: StatePartIndex(2), // (0x4d2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::any_seq_out", ty: UInt<16> }, + src: StatePartIndex(25), // (0x4d2) SlotDebugData { name: "<>::any_seq", ty: UInt<16> }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 1: Copy { + dest: StatePartIndex(19), // (0x0) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(8), // (0x0) SlotDebugData { name: "<>::formal_reset", ty: SyncReset }, + }, + 2: NotU { + dest: StatePartIndex(20), // (0x1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(19), // (0x0) SlotDebugData { name: "", ty: Bool }, + width: 1, + }, + 3: Const { + dest: StatePartIndex(18), // (0x1) SlotDebugData { name: "", ty: Bool }, + value: 0x1, + }, + 4: And { + dest: StatePartIndex(21), // (0x1) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(18), // (0x1) SlotDebugData { name: "", ty: Bool }, + rhs: StatePartIndex(20), // (0x1) SlotDebugData { name: "", ty: Bool }, + }, + 5: NotU { + dest: StatePartIndex(22), // (0x0) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(21), // (0x1) SlotDebugData { name: "", ty: Bool }, + width: 1, + }, + // at: module-XXXXXXXXXX.rs:12:1 + 6: Copy { + dest: StatePartIndex(24), // (0x1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(18), // (0x1) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:9:1 + 7: Copy { + dest: StatePartIndex(0), // (0x2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count", ty: UInt<8> }, + src: StatePartIndex(9), // (0x2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 8: Const { + dest: StatePartIndex(14), // (0xa) SlotDebugData { name: "", ty: UInt<8> }, + value: 0xa, + }, + 9: CmpLe { + dest: StatePartIndex(17), // (0x1) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(9), // (0x2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg", ty: UInt<8> }, + rhs: StatePartIndex(14), // (0xa) SlotDebugData { name: "", ty: UInt<8> }, + }, + 10: Or { + dest: StatePartIndex(23), // (0x1) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(17), // (0x1) SlotDebugData { name: "", ty: Bool }, + rhs: StatePartIndex(22), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:11:1 + 11: BranchIfZero { + target: 13, + value: StatePartIndex(1), // (0x1) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::enable_assert", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:12:1 + 12: Copy { + dest: StatePartIndex(24), // (0x1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(23), // (0x1) SlotDebugData { name: "", ty: Bool }, + }, + 13: IsNonZeroDestIsSmall { + dest: StatePartIndex(4), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(24), // (0x1) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 14: Const { + dest: StatePartIndex(12), // (0x1) SlotDebugData { name: "", ty: UInt<8> }, + value: 0x1, + }, + 15: Add { + dest: StatePartIndex(13), // (0x3) SlotDebugData { name: "", ty: UInt<9> }, + lhs: StatePartIndex(9), // (0x2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg", ty: UInt<8> }, + rhs: StatePartIndex(12), // (0x1) SlotDebugData { name: "", ty: UInt<8> }, + }, + 16: CmpLt { + dest: StatePartIndex(15), // (0x1) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(13), // (0x3) SlotDebugData { name: "", ty: UInt<9> }, + rhs: StatePartIndex(14), // (0xa) SlotDebugData { name: "", ty: UInt<8> }, + }, + 17: CastToUInt { + dest: StatePartIndex(16), // (0x3) SlotDebugData { name: "", ty: UInt<8> }, + src: StatePartIndex(13), // (0x3) SlotDebugData { name: "", ty: UInt<9> }, + dest_width: 8, + }, + // at: module-XXXXXXXXXX.rs:4:1 + 18: Copy { + dest: StatePartIndex(10), // (0x3) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg$next", ty: UInt<8> }, + src: StatePartIndex(9), // (0x2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:5:1 + 19: BranchIfZero { + target: 21, + value: StatePartIndex(15), // (0x1) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:6:1 + 20: Copy { + dest: StatePartIndex(10), // (0x3) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg$next", ty: UInt<8> }, + src: StatePartIndex(16), // (0x3) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 21: Const { + dest: StatePartIndex(11), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + value: 0x0, + }, + // at: module-XXXXXXXXXX.rs:5:1 + 22: BranchIfNonZero { + target: 24, + value: StatePartIndex(15), // (0x1) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:7:1 + 23: Copy { + dest: StatePartIndex(10), // (0x3) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg$next", ty: UInt<8> }, + src: StatePartIndex(11), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 24: Copy { + dest: StatePartIndex(5), // (0x1) SlotDebugData { name: ".clk", ty: Clock }, + src: StatePartIndex(7), // (0x1) SlotDebugData { name: "<>::formal_global_clock", ty: Clock }, + }, + 25: Copy { + dest: StatePartIndex(6), // (0x0) SlotDebugData { name: ".rst", ty: SyncReset }, + src: StatePartIndex(8), // (0x0) SlotDebugData { name: "<>::formal_reset", ty: SyncReset }, + }, + // at: module-XXXXXXXXXX.rs:3:1 + 26: Copy { + dest: StatePartIndex(3), // (0x1) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::cd.clk", ty: Clock }, + src: StatePartIndex(5), // (0x1) SlotDebugData { name: ".clk", ty: Clock }, + }, + 27: Copy { + dest: StatePartIndex(4), // (0x0) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::cd.rst", ty: SyncReset }, + src: StatePartIndex(6), // (0x0) SlotDebugData { name: ".rst", ty: SyncReset }, + }, + // at: module-XXXXXXXXXX.rs:4:1 + 28: IsNonZeroDestIsSmall { + dest: StatePartIndex(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(3), // (0x1) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::cd.clk", ty: Clock }, + }, + 29: AndSmall { + dest: StatePartIndex(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + rhs: StatePartIndex(0), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 30: IsNonZeroDestIsSmall { + dest: StatePartIndex(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(4), // (0x0) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::cd.rst", ty: SyncReset }, + }, + 31: BranchIfSmallZero { + target: 36, + value: StatePartIndex(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 32: BranchIfSmallNonZero { + target: 35, + value: StatePartIndex(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 33: Copy { + dest: StatePartIndex(9), // (0x2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg", ty: UInt<8> }, + src: StatePartIndex(10), // (0x3) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg$next", ty: UInt<8> }, + }, + 34: Branch { + target: 36, + }, + 35: Copy { + dest: StatePartIndex(9), // (0x2) SlotDebugData { name: "InstantiatedModule(formal_counter: formal_counter).formal_counter::count_reg", ty: UInt<8> }, + src: StatePartIndex(11), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + }, + // at: module-XXXXXXXXXX.rs:12:1 + 36: Assert { + clk_triggered: StatePartIndex(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + pred: StatePartIndex(4), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + assert_index: 0, + }, + // at: module-XXXXXXXXXX.rs:4:1 + 37: XorSmallImmediate { + dest: StatePartIndex(0), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + rhs: 0x1, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 38: Return, + ], + .. + }, + pc: 38, + memory_write_log: [], + assert_failed_log: [], + memories: StatePart { + value: [], + }, + small_slots: StatePart { + value: [ + 0, + 0, + 1, + 0, + 1, + ], + }, + big_slots: StatePart { + value: [ + 2, + 1, + 1234, + 1, + 0, + 1, + 0, + 1, + 0, + 2, + 3, + 0, + 1, + 3, + 10, + 1, + 3, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 1234, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::formal_counter, + instantiated: Module { + name: formal_counter, + .. + }, + }, + global_io: { + SimIoForGlobal( + formal_global_clock, + ): CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "<>::formal_global_clock", + ty: Clock, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 7, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }, + SimIoForGlobal( + formal_reset, + ): CompiledValue { + layout: CompiledTypeLayout { + ty: SyncReset, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "<>::formal_reset", + ty: SyncReset, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 8, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }, + SimIoForGlobal( + any_seq( + UInt<16>, + ), + ): CompiledValue { + layout: CompiledTypeLayout { + ty: UInt<16>, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "<>::any_seq", + ty: UInt<16>, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + body: Scalar, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 5, len: 0 }, + big_slots: StatePartIndexRange { start: 25, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }, + }, + main_module: SimulationModuleState { + base_targets: [ + SimIoForGlobal( + formal_global_clock, + ), + SimIoForGlobal( + formal_reset, + ), + SimIoForGlobal( + any_seq( + UInt<16>, + ), + ), + Instance { + name: ::formal_counter, + instantiated: Module { + name: formal_counter, + .. + }, + }.count, + Instance { + name: ::formal_counter, + instantiated: Module { + name: formal_counter, + .. + }, + }.enable_assert, + Instance { + name: ::formal_counter, + instantiated: Module { + name: formal_counter, + .. + }, + }.any_seq_out, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::formal_counter, + instantiated: Module { + name: formal_counter, + .. + }, + }.any_seq_out, + Instance { + name: ::formal_counter, + instantiated: Module { + name: formal_counter, + .. + }, + }.count, + Instance { + name: ::formal_counter, + instantiated: Module { + name: formal_counter, + .. + }, + }.enable_assert, + SimIoForGlobal( + any_seq( + UInt<16>, + ), + ), + SimIoForGlobal( + formal_global_clock, + ), + SimIoForGlobal( + formal_reset, + ), + }, + did_initial_settle: true, + clocks_for_past: {}, + }, + extern_modules: [], + trace_decls: TraceModule { + name: "formal_counter", + children: [ + TraceFormalInput { + name: "formal_global_clock", + child: TraceClock { + location: TraceScalarId(5), + name: "formal_global_clock", + flow: Source, + }, + formal_input: formal_global_clock, + }, + TraceFormalInput { + name: "formal_reset", + child: TraceSyncReset { + location: TraceScalarId(6), + name: "formal_reset", + flow: Source, + }, + formal_input: formal_reset, + }, + TraceFormalInput { + name: "any_seq", + child: TraceUInt { + location: TraceScalarId(8), + name: "any_seq", + ty: UInt<16>, + flow: Source, + }, + formal_input: any_seq( + UInt<16>, + ), + }, + TraceModuleIO { + name: "count", + child: TraceUInt { + location: TraceScalarId(0), + name: "count", + ty: UInt<8>, + flow: Sink, + }, + ty: UInt<8>, + flow: Sink, + }, + TraceModuleIO { + name: "enable_assert", + child: TraceBool { + location: TraceScalarId(1), + name: "enable_assert", + flow: Source, + }, + ty: Bool, + flow: Source, + }, + TraceModuleIO { + name: "any_seq_out", + child: TraceUInt { + location: TraceScalarId(2), + name: "any_seq_out", + ty: UInt<16>, + flow: Sink, + }, + ty: UInt<16>, + flow: Sink, + }, + TraceWire { + name: "cd", + child: TraceBundle { + name: "cd", + fields: [ + TraceClock { + location: TraceScalarId(3), + name: "clk", + flow: Duplex, + }, + TraceSyncReset { + location: TraceScalarId(4), + name: "rst", + flow: Duplex, + }, + ], + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + flow: Duplex, + }, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + }, + TraceReg { + name: "count_reg", + child: TraceUInt { + location: TraceScalarId(7), + name: "count_reg", + ty: UInt<8>, + flow: Duplex, + }, + ty: UInt<8>, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigUInt { + index: StatePartIndex(0), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0x02, + last_state: 0x01, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigBool { + index: StatePartIndex(1), + }, + maybe_changed: false, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigUInt { + index: StatePartIndex(2), + ty: UInt<16>, + }, + maybe_changed: true, + state: 0x04d2, + last_state: 0x04d2, + }, + SimTrace { + id: TraceScalarId(3), + kind: BigClock { + index: StatePartIndex(3), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(4), + kind: BigSyncReset { + index: StatePartIndex(4), + }, + maybe_changed: true, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(5), + kind: BigClock { + index: StatePartIndex(7), + }, + maybe_changed: true, + state: 0x1, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(6), + kind: BigSyncReset { + index: StatePartIndex(8), + }, + maybe_changed: true, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(7), + kind: BigUInt { + index: StatePartIndex(9), + ty: UInt<8>, + }, + maybe_changed: true, + state: 0x02, + last_state: 0x01, + }, + SimTrace { + id: TraceScalarId(8), + kind: BigUInt { + index: StatePartIndex(25), + ty: UInt<16>, + }, + maybe_changed: true, + state: 0x04d2, + last_state: 0x04d2, + }, + ], + trace_memories: {}, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [ + StatePartIndex(1), + ], + event_queue: EventQueue(EventQueueData { + instant: 66 μs, + events: {}, + }), + waiting_sensitivity_sets_by_address: {}, + waiting_sensitivity_sets_by_compiled_value: {}, + asserts: [ + CompiledAssert { + instantiated_module: InstantiatedModule(formal_counter: formal_counter), + stmt_formal: assert { + clk: Wire(formal_counter::cd: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }).clk, + pred: CmpLeU { + lhs: Reg { + name: formal_counter::count_reg, + ty: UInt<8>, + clock_domain: Wire(formal_counter::cd: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }), + init: Some( + 0x0_u8, + ), + .. + }, + rhs: 0xA_u8, + literal_bits: Err( + NotALiteralExpr, + ), + }, + en: BitAndB { + lhs: true, + rhs: NotB { + arg: CastSyncResetToBool { + arg: formal_reset, + literal_bits: Err( + NotALiteralExpr, + ), + }, + literal_bits: Err( + NotALiteralExpr, + ), + }, + literal_bits: Err( + NotALiteralExpr, + ), + }, + text: "", + .. + }, + }, + ], + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/test_formal_counter.vcd b/crates/fayalite/tests/sim/expected/test_formal_counter.vcd new file mode 100644 index 0000000..1ba1b18 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/test_formal_counter.vcd @@ -0,0 +1,290 @@ +$timescale 1 ps $end +$scope module formal_counter $end +$var wire 1 ekAK2 formal_global_clock $end +$var wire 1 qTY9h formal_reset $end +$var wire 16 /roOY any_seq $end +$var wire 8 }eN0d count $end +$var wire 1 2f=;S enable_assert $end +$var wire 16 L-uG? any_seq_out $end +$scope struct cd $end +$var wire 1 -e"5` clk $end +$var wire 1 IC0;$ rst $end +$upscope $end +$var reg 8 ^:T_4 count_reg $end +$upscope $end +$enddefinitions $end +$dumpvars +b0 }eN0d +12f=;S +b0 L-uG? +0-e"5` +1IC0;$ +0ekAK2 +1qTY9h +b0 ^:T_4 +b0 /roOY +$end +#1000000 +b10011010010 L-uG? +1-e"5` +1ekAK2 +b10011010010 /roOY +0IC0;$ +0qTY9h +#2000000 +0-e"5` +0ekAK2 +#3000000 +b1 }eN0d +1-e"5` +1ekAK2 +b1 ^:T_4 +#4000000 +0-e"5` +0ekAK2 +#5000000 +b10 }eN0d +1-e"5` +1ekAK2 +b10 ^:T_4 +#6000000 +0-e"5` +0ekAK2 +#7000000 +b11 }eN0d +1-e"5` +1ekAK2 +b11 ^:T_4 +#8000000 +0-e"5` +0ekAK2 +#9000000 +b100 }eN0d +1-e"5` +1ekAK2 +b100 ^:T_4 +#10000000 +0-e"5` +0ekAK2 +#11000000 +b101 }eN0d +1-e"5` +1ekAK2 +b101 ^:T_4 +#12000000 +0-e"5` +0ekAK2 +#13000000 +b110 }eN0d +1-e"5` +1ekAK2 +b110 ^:T_4 +#14000000 +0-e"5` +0ekAK2 +#15000000 +b111 }eN0d +1-e"5` +1ekAK2 +b111 ^:T_4 +#16000000 +0-e"5` +0ekAK2 +#17000000 +b1000 }eN0d +1-e"5` +1ekAK2 +b1000 ^:T_4 +#18000000 +0-e"5` +0ekAK2 +#19000000 +b1001 }eN0d +1-e"5` +1ekAK2 +b1001 ^:T_4 +#20000000 +0-e"5` +0ekAK2 +#21000000 +b0 }eN0d +1-e"5` +1ekAK2 +b0 ^:T_4 +#22000000 +0-e"5` +0ekAK2 +#23000000 +b1 }eN0d +1-e"5` +1ekAK2 +b1 ^:T_4 +#24000000 +0-e"5` +0ekAK2 +#25000000 +b10 }eN0d +1-e"5` +1ekAK2 +b10 ^:T_4 +#26000000 +0-e"5` +0ekAK2 +#27000000 +b11 }eN0d +1-e"5` +1ekAK2 +b11 ^:T_4 +#28000000 +0-e"5` +0ekAK2 +#29000000 +b100 }eN0d +1-e"5` +1ekAK2 +b100 ^:T_4 +#30000000 +0-e"5` +0ekAK2 +#31000000 +b101 }eN0d +1-e"5` +1ekAK2 +b101 ^:T_4 +#32000000 +0-e"5` +0ekAK2 +#33000000 +b110 }eN0d +1-e"5` +1ekAK2 +b110 ^:T_4 +#34000000 +0-e"5` +0ekAK2 +#35000000 +b111 }eN0d +1-e"5` +1ekAK2 +b111 ^:T_4 +#36000000 +0-e"5` +0ekAK2 +#37000000 +b1000 }eN0d +1-e"5` +1ekAK2 +b1000 ^:T_4 +#38000000 +0-e"5` +0ekAK2 +#39000000 +b1001 }eN0d +1-e"5` +1ekAK2 +b1001 ^:T_4 +#40000000 +0-e"5` +0ekAK2 +#41000000 +b0 }eN0d +1-e"5` +1ekAK2 +b0 ^:T_4 +#42000000 +0-e"5` +0ekAK2 +#43000000 +b1 }eN0d +1-e"5` +1ekAK2 +b1 ^:T_4 +#44000000 +0-e"5` +0ekAK2 +#45000000 +b10 }eN0d +1-e"5` +1ekAK2 +b10 ^:T_4 +#46000000 +0-e"5` +0ekAK2 +#47000000 +b11 }eN0d +1-e"5` +1ekAK2 +b11 ^:T_4 +#48000000 +0-e"5` +0ekAK2 +#49000000 +b100 }eN0d +1-e"5` +1ekAK2 +b100 ^:T_4 +#50000000 +0-e"5` +0ekAK2 +#51000000 +b101 }eN0d +1-e"5` +1ekAK2 +b101 ^:T_4 +#52000000 +0-e"5` +0ekAK2 +#53000000 +b110 }eN0d +1-e"5` +1ekAK2 +b110 ^:T_4 +#54000000 +0-e"5` +0ekAK2 +#55000000 +b111 }eN0d +1-e"5` +1ekAK2 +b111 ^:T_4 +#56000000 +0-e"5` +0ekAK2 +#57000000 +b1000 }eN0d +1-e"5` +1ekAK2 +b1000 ^:T_4 +#58000000 +0-e"5` +0ekAK2 +#59000000 +b1001 }eN0d +1-e"5` +1ekAK2 +b1001 ^:T_4 +#60000000 +0-e"5` +0ekAK2 +#61000000 +b0 }eN0d +1-e"5` +1ekAK2 +b0 ^:T_4 +#62000000 +0-e"5` +0ekAK2 +#63000000 +b1 }eN0d +1-e"5` +1ekAK2 +b1 ^:T_4 +#64000000 +0-e"5` +0ekAK2 +#65000000 +b10 }eN0d +1-e"5` +1ekAK2 +b10 ^:T_4 +#66000000 diff --git a/crates/fayalite/tests/sim/expected/test_formal_counter_assert.vcd b/crates/fayalite/tests/sim/expected/test_formal_counter_assert.vcd new file mode 100644 index 0000000..c9b1655 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/test_formal_counter_assert.vcd @@ -0,0 +1,194 @@ +$timescale 1 ps $end +$scope module formal_counter $end +$var wire 1 ekAK2 formal_global_clock $end +$var wire 1 qTY9h formal_reset $end +$var wire 16 /roOY any_seq $end +$var wire 8 }eN0d count $end +$var wire 1 2f=;S enable_assert $end +$var wire 16 L-uG? any_seq_out $end +$scope struct cd $end +$var wire 1 -e"5` clk $end +$var wire 1 IC0;$ rst $end +$upscope $end +$var reg 8 ^:T_4 count_reg $end +$upscope $end +$enddefinitions $end +$dumpvars +b0 }eN0d +02f=;S +b0 L-uG? +0-e"5` +1IC0;$ +0ekAK2 +1qTY9h +b0 ^:T_4 +b0 /roOY +$end +#500000 +b10011010010 L-uG? +1-e"5` +1ekAK2 +b10011010010 /roOY +0IC0;$ +0qTY9h +#1000000 +0-e"5` +0ekAK2 +#1500000 +b1 }eN0d +1-e"5` +1ekAK2 +b1 ^:T_4 +#2000000 +0-e"5` +0ekAK2 +#2500000 +b10 }eN0d +1-e"5` +1ekAK2 +b10 ^:T_4 +#3000000 +0-e"5` +0ekAK2 +#3500000 +b11 }eN0d +1-e"5` +1ekAK2 +b11 ^:T_4 +#4000000 +0-e"5` +0ekAK2 +#4500000 +b100 }eN0d +1-e"5` +1ekAK2 +b100 ^:T_4 +#5000000 +0-e"5` +0ekAK2 +#5500000 +b101 }eN0d +1-e"5` +1ekAK2 +b101 ^:T_4 +#6000000 +0-e"5` +0ekAK2 +#6500000 +b110 }eN0d +1-e"5` +1ekAK2 +b110 ^:T_4 +#7000000 +0-e"5` +0ekAK2 +#7500000 +b111 }eN0d +1-e"5` +1ekAK2 +b111 ^:T_4 +#8000000 +0-e"5` +0ekAK2 +#8500000 +b1000 }eN0d +1-e"5` +1ekAK2 +b1000 ^:T_4 +#9000000 +0-e"5` +0ekAK2 +#9500000 +b1001 }eN0d +1-e"5` +1ekAK2 +b1001 ^:T_4 +#10000000 +0-e"5` +0ekAK2 +#10500000 +b0 }eN0d +1-e"5` +1ekAK2 +b0 ^:T_4 +#11000000 +0-e"5` +0ekAK2 +#11500000 +b1 }eN0d +1-e"5` +1ekAK2 +b1 ^:T_4 +#12000000 +0-e"5` +0ekAK2 +#12500000 +b10 }eN0d +1-e"5` +1ekAK2 +b10 ^:T_4 +#13000000 +0-e"5` +0ekAK2 +#13500000 +b11 }eN0d +1-e"5` +1ekAK2 +b11 ^:T_4 +#14000000 +0-e"5` +0ekAK2 +#14500000 +b100 }eN0d +1-e"5` +1ekAK2 +b100 ^:T_4 +#15000000 +0-e"5` +0ekAK2 +#15500000 +b101 }eN0d +1-e"5` +1ekAK2 +b101 ^:T_4 +#16000000 +0-e"5` +0ekAK2 +#16500000 +b110 }eN0d +1-e"5` +1ekAK2 +b110 ^:T_4 +#17000000 +12f=;S +0-e"5` +0ekAK2 +#17500000 +b111 }eN0d +1-e"5` +1ekAK2 +b111 ^:T_4 +#18000000 +0-e"5` +0ekAK2 +#18500000 +b1000 }eN0d +1-e"5` +1ekAK2 +b1000 ^:T_4 +#19000000 +0-e"5` +0ekAK2 +#19500000 +b1001 }eN0d +1-e"5` +1ekAK2 +b1001 ^:T_4 +#20000000 +0-e"5` +0ekAK2 +#20500000 +b0 }eN0d +1-e"5` +1ekAK2 +b0 ^:T_4 diff --git a/crates/fayalite/visit_types.json b/crates/fayalite/visit_types.json index f3af962..1267aa7 100644 --- a/crates/fayalite/visit_types.json +++ b/crates/fayalite/visit_types.json @@ -151,6 +151,11 @@ "$kind": "Opaque" } }, + "NameIdOrGlobal": { + "data": { + "$kind": "ManualImpl" + } + }, "ScopedNameId": { "data": { "$kind": "Struct", @@ -1043,6 +1048,13 @@ "fold_where": "T: Fold", "visit_where": "T: Visit" }, + "ops::SimIoForGlobal": { + "data": { + "$kind": "Struct", + "$constructor": "ops::SimIoForGlobal::new", + "global()": "Visible" + } + }, "BlockId": { "data": { "$kind": "Opaque" @@ -1277,7 +1289,9 @@ "RegSync": "Visible", "RegAsync": "Visible", "Wire": "Visible", - "Instance": "Visible" + "Instance": "Visible", + "FormalInput": "Visible", + "SimIoForGlobal": "Visible" } }, "TargetChild": { @@ -1349,6 +1363,21 @@ "generics": "", "fold_where": "T: Fold", "visit_where": "T: Visit" + }, + "FormalInput": { + "data": { + "$kind": "Struct", + "$constructor": "FormalInput::new", + "kind()": "Visible", + "name_id()": "Visible", + "ty()": "Visible", + "source_location()": "Visible" + } + }, + "FormalInputKind": { + "data": { + "$kind": "Opaque" + } } } } \ No newline at end of file From ffca1a279d79507c025a8d969bfff18295760c02 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 5 Jun 2026 00:41:51 -0700 Subject: [PATCH 15/15] switch ready_valid::queue formal proofs to use formal_global_clock --- crates/fayalite/src/util/ready_valid.rs | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/crates/fayalite/src/util/ready_valid.rs b/crates/fayalite/src/util/ready_valid.rs index a15b837..66f0aea 100644 --- a/crates/fayalite/src/util/ready_valid.rs +++ b/crates/fayalite/src/util/ready_valid.rs @@ -241,15 +241,13 @@ mod tests { /// happens to be in phase with the offending input or output). #[hdl_module] fn queue_test(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) { - #[hdl] - let clk: Clock = m.input(); #[hdl] let cd = wire(); connect( cd, #[hdl] ClockDomain { - clk, + clk: formal_global_clock(), rst: formal_reset().to_reset(), }, ); @@ -280,7 +278,7 @@ mod tests { #[hdl] let index_to_check = wire(index_ty); connect(index_to_check, any_const(index_ty)); - hdl_assume(clk, index_to_check.cmp_lt(capacity.get()), ""); + hdl_assume(cd.clk, index_to_check.cmp_lt(capacity.get()), ""); // instantiate and connect the queue #[hdl] @@ -300,13 +298,13 @@ mod tests { let expected_count_reg = reg_builder().clock_domain(cd).reset(count_ty.zero()); #[hdl] if ReadyValid::firing(dut.inp) & !ReadyValid::firing(dut.out) { - hdl_assert(clk, expected_count_reg.cmp_ne(capacity.get()), ""); + hdl_assert(cd.clk, expected_count_reg.cmp_ne(capacity.get()), ""); connect_any(expected_count_reg, expected_count_reg + 1u8); } else if !ReadyValid::firing(dut.inp) & ReadyValid::firing(dut.out) { - hdl_assert(clk, expected_count_reg.cmp_ne(count_ty.zero()), ""); + hdl_assert(cd.clk, expected_count_reg.cmp_ne(count_ty.zero()), ""); connect_any(expected_count_reg, expected_count_reg - 1u8); } - hdl_assert(clk, expected_count_reg.cmp_eq(dut.count), ""); + hdl_assert(cd.clk, expected_count_reg.cmp_eq(dut.count), ""); // keep an independent write index into the FIFO's circular buffer #[hdl] @@ -374,7 +372,7 @@ mod tests { match inp_firing_data { // ... and we are not receiving data, then we must not // transmit any data. - HdlNone => hdl_assert(clk, HdlOption::is_none(out_firing_data), ""), + HdlNone => hdl_assert(cd.clk, HdlOption::is_none(out_firing_data), ""), // If we are indeed receiving some data... HdlSome(data_in) => { #[hdl] @@ -382,7 +380,9 @@ mod tests { // ... and transmitting at the same time, we // must be transmitting the input data itself, // since the holding register is empty. - HdlSome(data_out) => hdl_assert(clk, data_out.cmp_eq(data_in), ""), + HdlSome(data_out) => { + hdl_assert(cd.clk, data_out.cmp_eq(data_in), "") + } // If we are receiving, but not transmitting, // store the received data in the holding // register. @@ -397,11 +397,11 @@ mod tests { match out_firing_data { // ... and we are not transmitting it, we cannot // receive any more data. - HdlNone => hdl_assert(clk, HdlOption::is_none(inp_firing_data), ""), + HdlNone => hdl_assert(cd.clk, HdlOption::is_none(inp_firing_data), ""), // If we are transmitting a previously stored value... HdlSome(data_out) => { // ... it must be the same data we stored earlier. - hdl_assert(clk, data_out.cmp_eq(stored), ""); + hdl_assert(cd.clk, data_out.cmp_eq(stored), ""); // Also, accept new data, if any. Otherwise, // let the holding register become empty. connect(stored_reg, inp_firing_data); @@ -417,17 +417,17 @@ mod tests { connect(dut.dbg.index_to_check, index_to_check); #[hdl] if let HdlSome(stored) = stored_reg { - hdl_assert(clk, stored.cmp_eq(dut.dbg.stored), ""); + hdl_assert(cd.clk, stored.cmp_eq(dut.dbg.stored), ""); } // sync the read and write indices - hdl_assert(clk, inp_index_reg.cmp_eq(dut.dbg.inp_index), ""); - hdl_assert(clk, out_index_reg.cmp_eq(dut.dbg.out_index), ""); + hdl_assert(cd.clk, inp_index_reg.cmp_eq(dut.dbg.inp_index), ""); + hdl_assert(cd.clk, out_index_reg.cmp_eq(dut.dbg.out_index), ""); // the indices should never go past the capacity, but induction // doesn't know that... - hdl_assert(clk, inp_index_reg.cmp_lt(capacity.get()), ""); - hdl_assert(clk, out_index_reg.cmp_lt(capacity.get()), ""); + hdl_assert(cd.clk, inp_index_reg.cmp_lt(capacity.get()), ""); + hdl_assert(cd.clk, out_index_reg.cmp_lt(capacity.get()), ""); // strongly constrain the state of the holding register // @@ -455,7 +455,7 @@ mod tests { connect(expected_stored, pending_reads.cmp_lt(dut.count)); // sync with the state of the holding register hdl_assert( - clk, + cd.clk, expected_stored.cmp_eq(HdlOption::is_some(stored_reg)), "", );