From d4ea8260512e54c5187c1c59bd9bac47a319f86d Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 15 Jan 2025 19:04:40 -0800 Subject: [PATCH] sim: fix "label address not set" bug when the last Assignment is conditional --- crates/fayalite/src/sim.rs | 3 + crates/fayalite/tests/sim.rs | 36 ++++ .../expected/conditional_assignment_last.txt | 189 ++++++++++++++++++ .../expected/conditional_assignment_last.vcd | 14 ++ 4 files changed, 242 insertions(+) create mode 100644 crates/fayalite/tests/sim/expected/conditional_assignment_last.txt create mode 100644 crates/fayalite/tests/sim/expected/conditional_assignment_last.vcd diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index cb6228d..f630f5a 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -4773,6 +4773,9 @@ impl Compiler { } self.insns.extend(insns.iter().copied(), *source_location); } + for CondStackEntry { cond: _, end_label } in cond_stack { + self.insns.define_label_at_next_insn(end_label); + } } fn process_clocks(&mut self) -> Interned<[StatePartIndex]> { mem::take(&mut self.clock_triggers) diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index cae08de..8c8a10f 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -1407,3 +1407,39 @@ fn test_array_rw() { panic!(); } } + +#[hdl_module(outline_generated)] +pub fn conditional_assignment_last() { + #[hdl] + let i: Bool = m.input(); + #[hdl] + let w = wire(); + connect(w, true); + #[hdl] + if i { + connect(w, false); + } +} + +#[test] +fn test_conditional_assignment_last() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(conditional_assignment_last()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + sim.write(sim.io().i, false); + sim.advance_time(SimDuration::from_micros(1)); + sim.write(sim.io().i, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.flush_traces().unwrap(); + let vcd = String::from_utf8(writer.take()).unwrap(); + println!("####### VCD:\n{vcd}\n#######"); + if vcd != include_str!("sim/expected/conditional_assignment_last.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/conditional_assignment_last.txt") { + panic!(); + } +} diff --git a/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt new file mode 100644 index 0000000..186e5a5 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/conditional_assignment_last.txt @@ -0,0 +1,189 @@ +Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 4, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::i", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::w", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + ], + .. + }, + }, + memories: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + insns: [ + // at: module-XXXXXXXXXX.rs:1:1 + 0: Const { + dest: StatePartIndex(3), // (0x0) SlotDebugData { name: "", ty: Bool }, + value: 0x0, + }, + 1: Const { + dest: StatePartIndex(2), // (0x1) SlotDebugData { name: "", ty: Bool }, + value: 0x1, + }, + // at: module-XXXXXXXXXX.rs:4:1 + 2: Copy { + dest: StatePartIndex(1), // (0x0) SlotDebugData { name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::w", ty: Bool }, + src: StatePartIndex(2), // (0x1) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:5:1 + 3: BranchIfZero { + target: 5, + value: StatePartIndex(0), // (0x1) SlotDebugData { name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::i", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:6:1 + 4: Copy { + dest: StatePartIndex(1), // (0x0) SlotDebugData { name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::w", ty: Bool }, + src: StatePartIndex(3), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 5: Return, + ], + .. + }, + pc: 5, + memory_write_log: [], + memories: StatePart { + value: [], + }, + small_slots: StatePart { + value: [], + }, + big_slots: StatePart { + value: [ + 1, + 0, + 1, + 0, + ], + }, + }, + io: Instance { + name: ::conditional_assignment_last, + instantiated: Module { + name: conditional_assignment_last, + .. + }, + }, + uninitialized_inputs: {}, + io_targets: { + Instance { + name: ::conditional_assignment_last, + instantiated: Module { + name: conditional_assignment_last, + .. + }, + }.i: CompiledValue { + layout: CompiledTypeLayout { + ty: Bool, + layout: TypeLayout { + small_slots: StatePartLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::i", + ty: Bool, + }, + ], + .. + }, + }, + body: Scalar, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 0, len: 1 }, + }, + write: None, + }, + }, + made_initial_step: true, + needs_settle: false, + trace_decls: TraceModule { + name: "conditional_assignment_last", + children: [ + TraceModuleIO { + name: "i", + child: TraceBool { + location: TraceScalarId(0), + name: "i", + flow: Source, + }, + ty: Bool, + flow: Source, + }, + TraceWire { + name: "w", + child: TraceBool { + location: TraceScalarId(1), + name: "w", + flow: Duplex, + }, + ty: Bool, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigBool { + index: StatePartIndex(0), + }, + state: 0x1, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigBool { + index: StatePartIndex(1), + }, + state: 0x0, + last_state: 0x1, + }, + ], + trace_memories: {}, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + instant: 2 μs, + clocks_triggered: [], + .. +} \ No newline at end of file diff --git a/crates/fayalite/tests/sim/expected/conditional_assignment_last.vcd b/crates/fayalite/tests/sim/expected/conditional_assignment_last.vcd new file mode 100644 index 0000000..dd9a85a --- /dev/null +++ b/crates/fayalite/tests/sim/expected/conditional_assignment_last.vcd @@ -0,0 +1,14 @@ +$timescale 1 ps $end +$scope module conditional_assignment_last $end +$var wire 1 ! i $end +$var wire 1 " w $end +$upscope $end +$enddefinitions $end +$dumpvars +0! +1" +$end +#1000000 +1! +0" +#2000000