diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index 35da336..5887dee 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -54,7 +54,7 @@ use std::{ future::{Future, IntoFuture}, hash::Hash, mem, - pin::Pin, + pin::{Pin, pin}, ptr, rc::Rc, sync::{Arc, Mutex}, @@ -1187,6 +1187,33 @@ impl SimulationModuleState { } } #[track_caller] + fn is_reset_async(&self, io: Expr, which_module: WhichModule) -> bool { + let Some(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::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 { + CanonicalType::UInt(_) + | CanonicalType::SInt(_) + | CanonicalType::Bool(_) + | CanonicalType::Array(_) + | CanonicalType::Enum(_) + | CanonicalType::Bundle(_) + | CanonicalType::Reset(_) + | CanonicalType::Clock(_) + | CanonicalType::PhantomConst(_) + | CanonicalType::DynSimOnly(_) => unreachable!(), + CanonicalType::AsyncReset(_) => true, + CanonicalType::SyncReset(_) => false, + } + } + #[track_caller] fn read_helper( &self, io: Expr, @@ -2085,6 +2112,23 @@ impl SimulationImpl { } } let sensitivity_set = Rc::new(sensitivity_set); + struct CancelOnDrop<'a> { + this: &'a RefCell, + sensitivity_set: &'a Rc, + } + impl Drop for CancelOnDrop<'_> { + fn drop(&mut self) { + let Self { + this, + sensitivity_set, + } = self; + this.borrow_mut().cancel_wake_after_change(&sensitivity_set); + } + } + let _cancel_on_drop = CancelOnDrop { + this, + sensitivity_set: &sensitivity_set, + }; let mut timeout_instant = None; std::future::poll_fn(|cx| { if sensitivity_set.changed.get() { @@ -2125,7 +2169,6 @@ impl SimulationImpl { } }) .await; - this.borrow_mut().cancel_wake_after_change(&sensitivity_set); } #[must_use] #[track_caller] @@ -2628,6 +2671,11 @@ impl SimulationImpl { any_change.get() } #[track_caller] + fn is_reset_async(&self, io: Expr, which_module: WhichModule) -> bool { + self.get_module(which_module) + .is_reset_async(io, which_module) + } + #[track_caller] fn read( &mut self, io: Expr, @@ -2969,6 +3017,13 @@ macro_rules! impl_simulation_methods { .read_bit(Expr::canonical(io), $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) + } $(#[$track_caller])? pub $($async)? fn read(&mut $self, io: Expr) -> SimValue { let retval = $self @@ -3143,6 +3198,99 @@ impl ExternModuleSimulationState { pub async fn fork_join(&mut self, futures: F) -> F::Output { F::fork_join(futures, self).await } + async fn resettable_helper( + &mut self, + cancellable: &Cell, + wait_for_reset: impl AsyncFn(Self), + main: impl AsyncFn(Self), + ) -> ! { + let mut wait_for_reset_invocation = pin!(Some(wait_for_reset(self.forked_state()))); + let mut main_invocation = pin!(Some(main(self.forked_state()))); + std::future::poll_fn(|cx: &mut std::task::Context<'_>| { + loop { + if cancellable.get() && wait_for_reset_invocation.is_none() { + cancellable.set(false); + main_invocation.set(Some(main(self.forked_state()))); + wait_for_reset_invocation.set(Some(wait_for_reset(self.forked_state()))) + } + match main_invocation.as_mut().as_pin_mut().map(|f| f.poll(cx)) { + None | Some(Poll::Pending) => {} + Some(Poll::Ready(())) => { + main_invocation.set(None); + continue; + } + } + match wait_for_reset_invocation + .as_mut() + .as_pin_mut() + .map(|f| f.poll(cx)) + { + None | Some(Poll::Pending) => {} + Some(Poll::Ready(())) => { + wait_for_reset_invocation.set(None); + continue; + } + } + return Poll::Pending; + } + }) + .await + } + /// When `cd.rst` is deduced to be an [`AsyncReset`]: + /// * when `cd.rst` is asserted or when first called, `reset` is invoked and any running `run` invocation is cancelled. + /// * when `cd.rst` is de-asserted and when `reset` finishes, `run` is invoked. + /// + /// When `cd.rst` is deduced to be a [`SyncReset`]: + /// * when there's a positive-going clock edge on `cd.clk` and `cd.rst` is asserted or when first called, `reset` is invoked and any running `run` invocation is cancelled. + /// * when `reset` finishes, `run` is invoked. + pub async fn resettable( + &mut self, + cd: impl ToExpr>, + reset: impl AsyncFn(Self) -> T, + run: impl AsyncFn(Self, T), + ) -> ! { + let cd = cd.to_expr(); + let rst = cd.rst; + if self.is_reset_async(rst) { + let cancellable = Cell::new(false); + let wait_for_reset = |mut this: Self| async move { + while this.read_reset(rst).await { + this.wait_for_changes([rst], None).await; + } + while !this.read_reset(rst).await { + this.wait_for_changes([rst], None).await; + } + }; + let main = |mut this: Self| async { + let run_arg = reset(this.forked_state()).await; + cancellable.set(true); + while this.read_reset(rst).await { + this.wait_for_changes([rst], None).await; + } + run(this, run_arg).await + }; + self.resettable_helper(&cancellable, wait_for_reset, main) + .await + } else { + let clk = cd.clk; + let wait_for_reset = |mut this: Self| async move { + loop { + this.wait_for_clock_edge(clk).await; + if this.read_reset(rst).await { + return; + } + } + }; + let cancellable = Cell::new(false); + let main = |this: Self| async { + let run_arg = reset(this.forked_state()).await; + cancellable.set(true); + run(this, run_arg).await + }; + self.resettable_helper(&cancellable, wait_for_reset, main) + .await + } + } fn forked_state(&self) -> Self { let Self { ref sim_impl, diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index b055ffa..1f452c9 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -2108,3 +2108,139 @@ fn test_sim_fork_join() { panic!(); } } + +#[hdl_module(outline_generated, extern)] +pub fn sim_resettable_counter() { + #[hdl] + let cd: ClockDomain = m.input(); + #[hdl] + let out: UInt<8> = m.output(); + m.extern_module_simulation_fn((cd, out), |(cd, out), mut sim| async move { + sim.resettable( + cd, + |mut sim: ExternModuleSimulationState| async move { + sim.write(out, 0u8).await; + }, + |mut sim: ExternModuleSimulationState, ()| async move { + loop { + sim.wait_for_clock_edge(cd.clk).await; + let v: u8 = sim + .read(out) + .await + .to_bigint() + .try_into() + .expect("known to be in range"); + sim.write(out, v.wrapping_add(1)).await; + } + }, + ) + .await + }); +} + +fn test_sim_resettable_counter_helper( + sim: &mut Simulation>, + immediate_reset: bool, +) { + sim.write_clock(sim.io().cd.clk, false); + sim.write_reset(sim.io().cd.rst, immediate_reset); + for _ in 0..2 { + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, false); + sim.write_reset(sim.io().cd.rst, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, false); + sim.write_reset(sim.io().cd.rst, false); + for expected in 0..3u8 { + assert_eq!(sim.read(sim.io().out), expected.to_sim_value()); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, false); + } + } +} + +#[test] +fn test_sim_resettable_counter_sync() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(sim_resettable_counter::()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + test_sim_resettable_counter_helper(&mut sim, false); + sim.flush_traces().unwrap(); + let vcd = String::from_utf8(writer.take()).unwrap(); + println!("####### VCD:\n{vcd}\n#######"); + if vcd != include_str!("sim/expected/sim_resettable_counter_sync.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/sim_resettable_counter_sync.txt") { + panic!(); + } +} + +#[test] +fn test_sim_resettable_counter_sync_immediate_reset() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(sim_resettable_counter::()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + test_sim_resettable_counter_helper(&mut sim, true); + sim.flush_traces().unwrap(); + let vcd = String::from_utf8(writer.take()).unwrap(); + println!("####### VCD:\n{vcd}\n#######"); + if vcd != include_str!("sim/expected/sim_resettable_counter_sync_immediate_reset.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/sim_resettable_counter_sync_immediate_reset.txt") { + panic!(); + } +} + +#[test] +fn test_sim_resettable_counter_async() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(sim_resettable_counter::()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + test_sim_resettable_counter_helper(&mut sim, false); + sim.flush_traces().unwrap(); + let vcd = String::from_utf8(writer.take()).unwrap(); + println!("####### VCD:\n{vcd}\n#######"); + if vcd != include_str!("sim/expected/sim_resettable_counter_async.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/sim_resettable_counter_async.txt") { + panic!(); + } +} + +#[test] +fn test_sim_resettable_counter_async_immediate_reset() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(sim_resettable_counter::()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + test_sim_resettable_counter_helper(&mut sim, true); + sim.flush_traces().unwrap(); + let vcd = String::from_utf8(writer.take()).unwrap(); + println!("####### VCD:\n{vcd}\n#######"); + if vcd != include_str!("sim/expected/sim_resettable_counter_async_immediate_reset.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/sim_resettable_counter_async_immediate_reset.txt") { + panic!(); + } +} diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt new file mode 100644 index 0000000..351f944 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.txt @@ -0,0 +1,550 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 3, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst", + ty: AsyncReset, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::out", + 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: Return, + ], + .. + }, + pc: 0, + memory_write_log: [], + memories: StatePart { + value: [], + }, + small_slots: StatePart { + value: [], + }, + big_slots: StatePart { + value: [ + 0, + 0, + 3, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }, + main_module: SimulationModuleState { + base_targets: [ + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.clk, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.rst, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + }, + did_initial_settle: true, + }, + extern_modules: [ + SimulationExternModuleState { + module_state: SimulationModuleState { + base_targets: [ + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ], + uninitialized_ios: {}, + io_targets: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }.clk, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }.rst, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + did_initial_settle: true, + }, + sim: ExternModuleSimulation { + generator: SimGeneratorFn { + args: ( + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ), + f: ..., + }, + sim_io_to_generator_map: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }: ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }: ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + source_location: SourceLocation( + module-XXXXXXXXXX.rs:4:1, + ), + }, + running_generator: Some( + ..., + ), + }, + ], + trace_decls: TraceModule { + name: "sim_resettable_counter", + children: [ + TraceModuleIO { + name: "cd", + child: TraceBundle { + name: "cd", + fields: [ + TraceClock { + location: TraceScalarId(0), + name: "clk", + flow: Source, + }, + TraceAsyncReset { + location: TraceScalarId(1), + name: "rst", + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + flow: Source, + }, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + flow: Source, + }, + TraceModuleIO { + name: "out", + child: TraceUInt { + location: TraceScalarId(2), + name: "out", + ty: UInt<8>, + flow: Sink, + }, + ty: UInt<8>, + flow: Sink, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigClock { + index: StatePartIndex(0), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigAsyncReset { + index: StatePartIndex(1), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigUInt { + index: StatePartIndex(2), + ty: UInt<8>, + }, + state: 0x03, + last_state: 0x03, + }, + ], + trace_memories: {}, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [], + event_queue: EventQueue(EventQueueData { + instant: 20 μs, + events: {}, + }), + waiting_sensitivity_sets_by_address: { + SensitivitySet { + id: 16, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: AsyncReset, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + ty: AsyncReset, + }, + ], + .. + }, + 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: 1, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: AsyncReset, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + SensitivitySet { + id: 23, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + }, + waiting_sensitivity_sets_by_compiled_value: { + CompiledValue { + layout: CompiledTypeLayout { + ty: AsyncReset, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + ty: AsyncReset, + }, + ], + .. + }, + 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: 1, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: ( + SimValue { + ty: AsyncReset, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + { + SensitivitySet { + id: 16, + .. + }, + }, + ), + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: ( + SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + { + SensitivitySet { + id: 23, + .. + }, + }, + ), + }, + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.vcd b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.vcd new file mode 100644 index 0000000..f05658f --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async.vcd @@ -0,0 +1,68 @@ +$timescale 1 ps $end +$scope module sim_resettable_counter $end +$scope struct cd $end +$var wire 1 ! clk $end +$var wire 1 " rst $end +$upscope $end +$var wire 8 # out $end +$upscope $end +$enddefinitions $end +$dumpvars +0! +0" +b0 # +$end +#1000000 +1! +b1 # +#2000000 +0! +1" +b0 # +#3000000 +1! +#4000000 +0! +0" +#5000000 +1! +b1 # +#6000000 +0! +#7000000 +1! +b10 # +#8000000 +0! +#9000000 +1! +b11 # +#10000000 +0! +#11000000 +1! +b100 # +#12000000 +0! +1" +b0 # +#13000000 +1! +#14000000 +0! +0" +#15000000 +1! +b1 # +#16000000 +0! +#17000000 +1! +b10 # +#18000000 +0! +#19000000 +1! +b11 # +#20000000 +0! 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 new file mode 100644 index 0000000..abd7cf6 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.txt @@ -0,0 +1,550 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 3, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst", + ty: AsyncReset, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::out", + 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: Return, + ], + .. + }, + pc: 0, + memory_write_log: [], + memories: StatePart { + value: [], + }, + small_slots: StatePart { + value: [], + }, + big_slots: StatePart { + value: [ + 0, + 0, + 3, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }, + main_module: SimulationModuleState { + base_targets: [ + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.clk, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.rst, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + }, + did_initial_settle: true, + }, + extern_modules: [ + SimulationExternModuleState { + module_state: SimulationModuleState { + base_targets: [ + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ], + uninitialized_ios: {}, + io_targets: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }.clk, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }.rst, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + did_initial_settle: true, + }, + sim: ExternModuleSimulation { + generator: SimGeneratorFn { + args: ( + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ), + f: ..., + }, + sim_io_to_generator_map: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }: ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }: ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + source_location: SourceLocation( + module-XXXXXXXXXX.rs:4:1, + ), + }, + running_generator: Some( + ..., + ), + }, + ], + trace_decls: TraceModule { + name: "sim_resettable_counter", + children: [ + TraceModuleIO { + name: "cd", + child: TraceBundle { + name: "cd", + fields: [ + TraceClock { + location: TraceScalarId(0), + name: "clk", + flow: Source, + }, + TraceAsyncReset { + location: TraceScalarId(1), + name: "rst", + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + flow: Source, + }, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: AsyncReset, + }, + flow: Source, + }, + TraceModuleIO { + name: "out", + child: TraceUInt { + location: TraceScalarId(2), + name: "out", + ty: UInt<8>, + flow: Sink, + }, + ty: UInt<8>, + flow: Sink, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigClock { + index: StatePartIndex(0), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigAsyncReset { + index: StatePartIndex(1), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigUInt { + index: StatePartIndex(2), + ty: UInt<8>, + }, + state: 0x03, + last_state: 0x03, + }, + ], + trace_memories: {}, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [], + event_queue: EventQueue(EventQueueData { + instant: 20 μs, + events: {}, + }), + waiting_sensitivity_sets_by_address: { + SensitivitySet { + id: 13, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: AsyncReset, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + ty: AsyncReset, + }, + ], + .. + }, + 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: 1, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: AsyncReset, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + SensitivitySet { + id: 20, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + }, + waiting_sensitivity_sets_by_compiled_value: { + CompiledValue { + layout: CompiledTypeLayout { + ty: AsyncReset, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + ty: AsyncReset, + }, + ], + .. + }, + 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: 1, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: ( + SimValue { + ty: AsyncReset, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + { + SensitivitySet { + id: 13, + .. + }, + }, + ), + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: ( + SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + { + SensitivitySet { + id: 20, + .. + }, + }, + ), + }, + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.vcd b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.vcd new file mode 100644 index 0000000..99f7b86 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_async_immediate_reset.vcd @@ -0,0 +1,65 @@ +$timescale 1 ps $end +$scope module sim_resettable_counter $end +$scope struct cd $end +$var wire 1 ! clk $end +$var wire 1 " rst $end +$upscope $end +$var wire 8 # out $end +$upscope $end +$enddefinitions $end +$dumpvars +0! +1" +b0 # +$end +#1000000 +1! +#2000000 +0! +#3000000 +1! +#4000000 +0! +0" +#5000000 +1! +b1 # +#6000000 +0! +#7000000 +1! +b10 # +#8000000 +0! +#9000000 +1! +b11 # +#10000000 +0! +#11000000 +1! +b100 # +#12000000 +0! +1" +b0 # +#13000000 +1! +#14000000 +0! +0" +#15000000 +1! +b1 # +#16000000 +0! +#17000000 +1! +b10 # +#18000000 +0! +#19000000 +1! +b11 # +#20000000 +0! diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt new file mode 100644 index 0000000..8ff0c2f --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.txt @@ -0,0 +1,505 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 3, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst", + ty: SyncReset, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::out", + 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: Return, + ], + .. + }, + pc: 0, + memory_write_log: [], + memories: StatePart { + value: [], + }, + small_slots: StatePart { + value: [], + }, + big_slots: StatePart { + value: [ + 0, + 0, + 3, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }, + main_module: SimulationModuleState { + base_targets: [ + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.clk, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.rst, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + }, + did_initial_settle: true, + }, + extern_modules: [ + SimulationExternModuleState { + module_state: SimulationModuleState { + base_targets: [ + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ], + uninitialized_ios: {}, + io_targets: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }.clk, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }.rst, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + did_initial_settle: true, + }, + sim: ExternModuleSimulation { + generator: SimGeneratorFn { + args: ( + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ), + f: ..., + }, + sim_io_to_generator_map: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }: ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }: ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + source_location: SourceLocation( + module-XXXXXXXXXX.rs:4:1, + ), + }, + running_generator: Some( + ..., + ), + }, + ], + trace_decls: TraceModule { + name: "sim_resettable_counter", + children: [ + TraceModuleIO { + name: "cd", + child: TraceBundle { + name: "cd", + fields: [ + TraceClock { + location: TraceScalarId(0), + name: "clk", + flow: Source, + }, + TraceSyncReset { + location: TraceScalarId(1), + name: "rst", + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + flow: Source, + }, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + flow: Source, + }, + TraceModuleIO { + name: "out", + child: TraceUInt { + location: TraceScalarId(2), + name: "out", + ty: UInt<8>, + flow: Sink, + }, + ty: UInt<8>, + flow: Sink, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigClock { + index: StatePartIndex(0), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigSyncReset { + index: StatePartIndex(1), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigUInt { + index: StatePartIndex(2), + ty: UInt<8>, + }, + state: 0x03, + last_state: 0x03, + }, + ], + trace_memories: {}, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [], + event_queue: EventQueue(EventQueueData { + instant: 20 μs, + events: {}, + }), + waiting_sensitivity_sets_by_address: { + SensitivitySet { + id: 42, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + SensitivitySet { + id: 43, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + }, + waiting_sensitivity_sets_by_compiled_value: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: ( + SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + { + SensitivitySet { + id: 42, + .. + }, + SensitivitySet { + id: 43, + .. + }, + }, + ), + }, + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.vcd b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.vcd new file mode 100644 index 0000000..39c2641 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync.vcd @@ -0,0 +1,70 @@ +$timescale 1 ps $end +$scope module sim_resettable_counter $end +$scope struct cd $end +$var wire 1 ! clk $end +$var wire 1 " rst $end +$upscope $end +$var wire 8 # out $end +$upscope $end +$enddefinitions $end +$dumpvars +0! +0" +b0 # +$end +#1000000 +1! +b1 # +#2000000 +0! +1" +#3000000 +1! +b10 # +b0 # +#4000000 +0! +0" +#5000000 +1! +b1 # +#6000000 +0! +#7000000 +1! +b10 # +#8000000 +0! +#9000000 +1! +b11 # +#10000000 +0! +#11000000 +1! +b100 # +#12000000 +0! +1" +#13000000 +1! +b101 # +b0 # +#14000000 +0! +0" +#15000000 +1! +b1 # +#16000000 +0! +#17000000 +1! +b10 # +#18000000 +0! +#19000000 +1! +b11 # +#20000000 +0! 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 new file mode 100644 index 0000000..e681947 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.txt @@ -0,0 +1,505 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 3, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk", + ty: Clock, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst", + ty: SyncReset, + }, + SlotDebugData { + name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::out", + 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: Return, + ], + .. + }, + pc: 0, + memory_write_log: [], + memories: StatePart { + value: [], + }, + small_slots: StatePart { + value: [], + }, + big_slots: StatePart { + value: [ + 0, + 0, + 3, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }, + main_module: SimulationModuleState { + base_targets: [ + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.clk, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.cd.rst, + Instance { + name: ::sim_resettable_counter, + instantiated: Module { + name: sim_resettable_counter, + .. + }, + }.out, + }, + did_initial_settle: true, + }, + extern_modules: [ + SimulationExternModuleState { + module_state: SimulationModuleState { + base_targets: [ + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ], + uninitialized_ios: {}, + io_targets: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }.clk, + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }.rst, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + did_initial_settle: true, + }, + sim: ExternModuleSimulation { + generator: SimGeneratorFn { + args: ( + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + ), + f: ..., + }, + sim_io_to_generator_map: { + ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }: ModuleIO { + name: sim_resettable_counter::cd, + is_input: true, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + .. + }, + ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }: ModuleIO { + name: sim_resettable_counter::out, + is_input: false, + ty: UInt<8>, + .. + }, + }, + source_location: SourceLocation( + module-XXXXXXXXXX.rs:4:1, + ), + }, + running_generator: Some( + ..., + ), + }, + ], + trace_decls: TraceModule { + name: "sim_resettable_counter", + children: [ + TraceModuleIO { + name: "cd", + child: TraceBundle { + name: "cd", + fields: [ + TraceClock { + location: TraceScalarId(0), + name: "clk", + flow: Source, + }, + TraceSyncReset { + location: TraceScalarId(1), + name: "rst", + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + flow: Source, + }, + ty: Bundle { + /* offset = 0 */ + clk: Clock, + /* offset = 1 */ + rst: SyncReset, + }, + flow: Source, + }, + TraceModuleIO { + name: "out", + child: TraceUInt { + location: TraceScalarId(2), + name: "out", + ty: UInt<8>, + flow: Sink, + }, + ty: UInt<8>, + flow: Sink, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigClock { + index: StatePartIndex(0), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigSyncReset { + index: StatePartIndex(1), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigUInt { + index: StatePartIndex(2), + ty: UInt<8>, + }, + state: 0x03, + last_state: 0x03, + }, + ], + trace_memories: {}, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [], + event_queue: EventQueue(EventQueueData { + instant: 20 μs, + events: {}, + }), + waiting_sensitivity_sets_by_address: { + SensitivitySet { + id: 43, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + SensitivitySet { + id: 44, + values: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + }, + changed: Cell { + value: false, + }, + .. + }, + }, + waiting_sensitivity_sets_by_compiled_value: { + CompiledValue { + layout: CompiledTypeLayout { + ty: Clock, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "", + 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: 0, len: 1 }, + sim_only_slots: StatePartIndexRange { start: 0, len: 0 }, + }, + write: None, + }: ( + SimValue { + ty: Clock, + value: OpaqueSimValue { + bits: 0x0_u1, + sim_only_values: [], + }, + }, + { + SensitivitySet { + id: 43, + .. + }, + SensitivitySet { + id: 44, + .. + }, + }, + ), + }, + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.vcd b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.vcd new file mode 100644 index 0000000..3cb97e2 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/sim_resettable_counter_sync_immediate_reset.vcd @@ -0,0 +1,70 @@ +$timescale 1 ps $end +$scope module sim_resettable_counter $end +$scope struct cd $end +$var wire 1 ! clk $end +$var wire 1 " rst $end +$upscope $end +$var wire 8 # out $end +$upscope $end +$enddefinitions $end +$dumpvars +0! +1" +b0 # +$end +#1000000 +1! +b1 # +b0 # +#2000000 +0! +#3000000 +1! +b1 # +b0 # +#4000000 +0! +0" +#5000000 +1! +b1 # +#6000000 +0! +#7000000 +1! +b10 # +#8000000 +0! +#9000000 +1! +b11 # +#10000000 +0! +#11000000 +1! +b100 # +#12000000 +0! +1" +#13000000 +1! +b101 # +b0 # +#14000000 +0! +0" +#15000000 +1! +b1 # +#16000000 +0! +#17000000 +1! +b10 # +#18000000 +0! +#19000000 +1! +b11 # +#20000000 +0!