diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index 4780ea2..857ced9 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -16,9 +16,9 @@ use crate::{ int::BoolOrIntType, intern::{Intern, Interned, Memoize}, module::{ - AnnotatedModuleIO, Block, Id, InstantiatedModule, ModuleBody, NameId, NormalModuleBody, - ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, - StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule, + transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule, + ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, + StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule, }, prelude::*, sim::{ @@ -1183,6 +1183,7 @@ impl Assignment { #[derive(Debug)] pub struct Compiler { insns: Insns, + original_base_module: Interned>, base_module: Interned>, modules: HashMap, compiled_values: HashMap>, @@ -1197,8 +1198,12 @@ pub struct Compiler { impl Compiler { pub fn new(base_module: Interned>) -> Self { + let original_base_module = base_module; + let base_module = deduce_resets(base_module, true) + .unwrap_or_else(|e| panic!("failed to deduce reset types: {e}")); Self { insns: Insns::new(), + original_base_module, base_module, modules: HashMap::new(), compiled_values: HashMap::new(), @@ -1295,7 +1300,7 @@ impl Compiler { flow, } .into(), - CanonicalType::Reset(ty) => todo!(), + CanonicalType::Reset(_) => unreachable!(), CanonicalType::Clock(ty) => TraceClock { id: self.make_trace_scalar_helper( target, @@ -2945,10 +2950,10 @@ impl Compiler { io: Instance::new_unchecked( ScopedNameId( NameId("".intern(), Id::new()), - self.base_module.name_id(), + self.original_base_module.name_id(), ), - self.base_module, - self.base_module.source_location(), + self.original_base_module, + self.original_base_module.source_location(), ), traces: Intern::intern_owned(self.traces), } diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index 78db49f..606d92b 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -156,6 +156,266 @@ fn test_connect_const() { assert_eq!(sim.read_bool_or_int(sim.io().o), UIntValue::from(5u8)); } +#[hdl_module(outline_generated)] +pub fn connect_const_reset() { + #[hdl] + let reset_out: Reset = m.output(); + #[hdl] + let bit_out: Bool = m.output(); + connect(reset_out, true.to_async_reset().to_reset()); + connect(bit_out, reset_out.cast_to_static()); +} + +#[test] +fn test_connect_const_reset() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(connect_const_reset()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + sim.settle_step(); + 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 + != r#"$timescale 1 ps $end +$scope module connect_const_reset $end +$var wire 1 ! reset_out $end +$var wire 1 " bit_out $end +$upscope $end +$enddefinitions $end +$dumpvars +1 ! +1 " +$end +#1000000 +"# { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug + != r#"Simulation { + state: State { + insns: Insns { + state_layout: StateLayout { + ty: TypeLayout { + small_slots: StatePartAllocationLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartAllocationLayout { + len: 5, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out", + ty: AsyncReset, + }, + SlotDebugData { + name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::bit_out", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: AsyncReset, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + ], + .. + }, + }, + }, + insns: [ + // at: module-XXXXXXXXXX.rs:1:1 + Const { + dest: StatePartIndex(2), // SlotDebugData { name: "", ty: Bool }, + value: 1, + }, + Copy { + dest: StatePartIndex(3), // SlotDebugData { name: "", ty: AsyncReset }, + src: StatePartIndex(2), // SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:4:1 + Copy { + dest: StatePartIndex(0), // SlotDebugData { name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out", ty: AsyncReset }, + src: StatePartIndex(3), // SlotDebugData { name: "", ty: AsyncReset }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + Copy { + dest: StatePartIndex(4), // SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(0), // SlotDebugData { name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out", ty: AsyncReset }, + }, + // at: module-XXXXXXXXXX.rs:5:1 + Copy { + dest: StatePartIndex(1), // SlotDebugData { name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::bit_out", ty: Bool }, + src: StatePartIndex(4), // SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + Return, + ], + .. + }, + pc: 5, + small_slots: StatePart { + value: [], + }, + big_slots: StatePart { + value: [ + 1, + 1, + 1, + 1, + 1, + ], + }, + }, + io: Instance { + name: ::connect_const_reset, + instantiated: Module { + name: connect_const_reset, + .. + }, + }, + uninitialized_inputs: {}, + io_targets: { + Instance { + name: ::connect_const_reset, + instantiated: Module { + name: connect_const_reset, + .. + }, + }.bit_out: CompiledValue { + layout: CompiledTypeLayout { + ty: Bool, + layout: TypeLayout { + small_slots: StatePartAllocationLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartAllocationLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::bit_out", + ty: Bool, + }, + ], + .. + }, + }, + body: Scalar, + }, + range: TypeIndexRange { + small_slots: StatePartIndexRange { start: 0, len: 0 }, + big_slots: StatePartIndexRange { start: 1, len: 1 }, + }, + write: None, + }, + Instance { + name: ::connect_const_reset, + instantiated: Module { + name: connect_const_reset, + .. + }, + }.reset_out: CompiledValue { + layout: CompiledTypeLayout { + ty: AsyncReset, + layout: TypeLayout { + small_slots: StatePartAllocationLayout { + len: 0, + debug_data: [], + .. + }, + big_slots: StatePartAllocationLayout { + len: 1, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out", + ty: AsyncReset, + }, + ], + .. + }, + }, + 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: "connect_const_reset", + children: [ + TraceModuleIO { + name: "reset_out", + child: TraceAsyncReset { + id: TraceScalarId(0), + name: "reset_out", + flow: Sink, + }, + ty: AsyncReset, + flow: Sink, + }, + TraceModuleIO { + name: "bit_out", + child: TraceBool { + id: TraceScalarId(1), + name: "bit_out", + flow: Sink, + }, + ty: Bool, + flow: Sink, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: BigAsyncReset { + index: StatePartIndex(0), + }, + state: 0x1, + last_state: 0x1, + }, + SimTrace { + id: TraceScalarId(1), + kind: BigBool { + index: StatePartIndex(1), + }, + state: 0x1, + last_state: 0x1, + }, + ], + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + instant: 1 μs, +}"# { + panic!(); + } + assert_eq!(sim.read_bool_or_int(sim.io().bit_out), true); +} + #[hdl_module(outline_generated)] pub fn mod1_child() { #[hdl]