diff --git a/crates/fayalite/src/int/uint_in_range.rs b/crates/fayalite/src/int/uint_in_range.rs index 970a439..65d3092 100644 --- a/crates/fayalite/src/int/uint_in_range.rs +++ b/crates/fayalite/src/int/uint_in_range.rs @@ -300,9 +300,7 @@ macro_rules! define_uint_in_range_type { } } pub fn new(start: Start::SizeType, end: End::SizeType) -> Self { - Self::from_phantom_const_range(PhantomConst::new( - $SerdeRange { start, end }.intern_sized(), - )) + Self::from_phantom_const_range(PhantomConst::new_sized($SerdeRange { start, end })) } pub fn bit_width(self) -> usize { self.value.width() diff --git a/crates/fayalite/src/lib.rs b/crates/fayalite/src/lib.rs index 96ee1f7..156aeed 100644 --- a/crates/fayalite/src/lib.rs +++ b/crates/fayalite/src/lib.rs @@ -152,7 +152,7 @@ pub use fayalite_proc_macros::hdl_module; /// This allows you to use some computed property of a [`PhantomConst`] to get a [`Type`] that you can use in other #[hdl] types. /// /// ``` -/// # use fayalite::{intern::Intern, prelude::*}; +/// # use fayalite::prelude::*; /// #[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)] /// pub struct Config { /// pub foo: usize, @@ -172,7 +172,7 @@ pub use fayalite_proc_macros::hdl_module; /// /// // you can then use Fayalite's standard syntax for creating dynamic types at runtime: /// let bar = Bundle::new(Default::default()); -/// let config = PhantomConst::new(Config { foo: 12, bar }.intern_sized()); +/// let config = PhantomConst::new_sized(Config { foo: 12, bar }); /// let ty = WrapMyArray[config]; /// assert_eq!(ty.my_array, Array[bar][12]); /// ``` @@ -182,7 +182,7 @@ pub use fayalite_proc_macros::hdl_module; /// This allows you to use some computed property of a [`PhantomConst`] to get a [`Size`] that you can use in other #[hdl] types. /// /// ``` -/// # use fayalite::{intern::Intern, prelude::*}; +/// # use fayalite::prelude::*; /// # #[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)] /// # pub struct ConfigItem {} /// # impl ConfigItem { @@ -207,7 +207,7 @@ pub use fayalite_proc_macros::hdl_module; /// } /// /// // you can then use Fayalite's standard syntax for creating dynamic types at runtime: -/// let config = PhantomConst::new(Config { items: vec![ConfigItem::new(); 5] }.intern_sized()); +/// let config = PhantomConst::new_sized(Config { items: vec![ConfigItem::new(); 5] }); /// let ty = FlagPerItem[config]; /// assert_eq!(ty.flags, Array[Bool][5]); /// ``` diff --git a/crates/fayalite/src/phantom_const.rs b/crates/fayalite/src/phantom_const.rs index 9f25166..eb6a758 100644 --- a/crates/fayalite/src/phantom_const.rs +++ b/crates/fayalite/src/phantom_const.rs @@ -131,7 +131,7 @@ impl Index for PhantomConstWithoutGenerics { type Output = PhantomConst; fn index(&self, value: T) -> &Self::Output { - Interned::into_inner(PhantomConst::new(value.intern()).intern_sized()) + Interned::into_inner(PhantomConst::new(&value).intern_sized()) } } @@ -222,11 +222,26 @@ impl Memoize for PhantomConstCanonicalMemoize PhantomConst { - pub fn new(value: Interned) -> Self { + pub fn new_interned(value: Interned) -> Self { Self { value: LazyInterned::Interned(value), } } + pub fn new_sized(value: T) -> Self + where + T: Clone, + { + Self::new_interned(value.intern_sized()) + } + pub fn new(value: &T) -> Self { + Self::new_interned(value.intern()) + } + pub fn new_deref>(value: U) -> Self + where + T: ToOwned, + { + Self::new_interned(value.intern_deref()) + } pub const fn new_lazy(v: &'static dyn LazyInternedTrait) -> Self { Self { value: LazyInterned::new_lazy(v), @@ -245,7 +260,7 @@ impl PhantomConst { if let Some(&retval) = ::downcast_ref::(&self) { return retval; } - ::new( + ::new_interned( PhantomConstCanonicalMemoize::(PhantomData).get_owned(self.get()), ) } @@ -253,7 +268,7 @@ impl PhantomConst { if let Some(&retval) = ::downcast_ref::(&canonical_type) { return retval; } - Self::new( + Self::new_interned( PhantomConstCanonicalMemoize::(PhantomData).get_owned(canonical_type.get()), ) } @@ -346,7 +361,9 @@ impl<'de, T: ?Sized + PhantomConstValue> Deserialize<'de> for PhantomConst { D: Deserializer<'de>, { match SerdeType::::deserialize(deserializer)? { - SerdeCanonicalType::PhantomConst(SerdePhantomConst(value)) => Ok(Self::new(value)), + SerdeCanonicalType::PhantomConst(SerdePhantomConst(value)) => { + Ok(Self::new_interned(value)) + } ty => Err(Error::invalid_value( serde::de::Unexpected::Other(ty.as_serde_unexpected_str()), &"a PhantomConst", diff --git a/crates/fayalite/src/platform/peripherals.rs b/crates/fayalite/src/platform/peripherals.rs index 90c6640..387142d 100644 --- a/crates/fayalite/src/platform/peripherals.rs +++ b/crates/fayalite/src/platform/peripherals.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information -use crate::{intern::Intern, prelude::*}; +use crate::prelude::*; use ordered_float::NotNan; use serde::{Deserialize, Serialize}; @@ -26,12 +26,9 @@ impl ClockInput { ); Self { clk: Clock, - properties: PhantomConst::new( - ClockInputProperties { - frequency: NotNan::new(frequency).expect("just checked"), - } - .intern_sized(), - ), + properties: PhantomConst::new_sized(ClockInputProperties { + frequency: NotNan::new(frequency).expect("just checked"), + }), } } pub fn frequency(self) -> f64 { diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index 5887dee..b19eeb0 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -416,6 +416,15 @@ impl_trace_decl! { name: Interned, flow: Flow, }), + PhantomConst(TracePhantomConst { + fn location(self) -> _ { + self.location + } + location: TraceLocation, + name: Interned, + ty: PhantomConst, + flow: Flow, + }), SimOnly(TraceSimOnly { fn location(self) -> _ { self.location @@ -526,6 +535,11 @@ pub trait TraceWriter: fmt::Debug + 'static { variant_index: usize, ty: Enum, ) -> Result<(), Self::Error>; + fn set_signal_phantom_const( + &mut self, + id: TraceScalarId, + ty: PhantomConst, + ) -> Result<(), Self::Error>; fn set_signal_sim_only_value( &mut self, id: TraceScalarId, @@ -585,6 +599,11 @@ trait TraceWriterDynTrait: fmt::Debug + 'static { variant_index: usize, ty: Enum, ) -> std::io::Result<()>; + fn set_signal_phantom_const_dyn( + &mut self, + id: TraceScalarId, + ty: PhantomConst, + ) -> std::io::Result<()>; fn set_signal_sim_only_value_dyn( &mut self, id: TraceScalarId, @@ -649,6 +668,13 @@ impl TraceWriterDynTrait for T { .map_err(err_into_io)?, ) } + fn set_signal_phantom_const_dyn( + &mut self, + id: TraceScalarId, + ty: PhantomConst, + ) -> std::io::Result<()> { + Ok(TraceWriter::set_signal_phantom_const(self, id, ty).map_err(err_into_io)?) + } fn set_signal_sim_only_value_dyn( &mut self, id: TraceScalarId, @@ -720,6 +746,13 @@ impl TraceWriter for DynTraceWriter { self.0 .set_signal_enum_discriminant_dyn(id, variant_index, ty) } + fn set_signal_phantom_const( + &mut self, + id: TraceScalarId, + ty: PhantomConst, + ) -> Result<(), Self::Error> { + self.0.set_signal_phantom_const_dyn(id, ty) + } fn set_signal_sim_only_value( &mut self, id: TraceScalarId, @@ -895,12 +928,16 @@ pub(crate) enum SimTraceKind { index: StatePartIndex, ty: DynSimOnly, }, + PhantomConst { + ty: PhantomConst, + }, } #[derive(PartialEq, Eq)] pub(crate) enum SimTraceState { Bits(BitVec), SimOnly(DynSimOnlyValue), + PhantomConst, } impl Clone for SimTraceState { @@ -908,6 +945,7 @@ impl Clone for SimTraceState { match self { Self::Bits(v) => Self::Bits(v.clone()), Self::SimOnly(v) => Self::SimOnly(v.clone()), + Self::PhantomConst => Self::PhantomConst, } } fn clone_from(&mut self, source: &Self) { @@ -956,6 +994,7 @@ impl fmt::Debug for SimTraceState { match self { SimTraceState::Bits(v) => BitSliceWriteWithBase(v).fmt(f), SimTraceState::SimOnly(v) => v.fmt(f), + SimTraceState::PhantomConst => f.debug_tuple("PhantomConst").finish(), } } } @@ -982,6 +1021,7 @@ impl SimTraceKind { SimTraceKind::EnumDiscriminant { index: _, ty } => { SimTraceState::Bits(BitVec::repeat(false, ty.discriminant_bit_width())) } + SimTraceKind::PhantomConst { .. } => SimTraceState::PhantomConst, SimTraceKind::SimOnly { index: _, ty } => SimTraceState::SimOnly(ty.default_value()), } } @@ -1097,6 +1137,7 @@ impl SimulationModuleState { true } } + CompiledTypeLayoutBody::PhantomConst => false, CompiledTypeLayoutBody::Bundle { .. } => { let value = value.map_ty(Bundle::from_canonical); let mut sub_targets = Vec::new(); @@ -1910,6 +1951,9 @@ impl SimulationImpl { ty, )?; } + SimTraceKind::PhantomConst { ty } => { + trace_writer.set_signal_phantom_const(id, ty)? + } SimTraceKind::SimOnly { .. } => { trace_writer.set_signal_sim_only_value(id, state.unwrap_sim_only_ref())? } @@ -1980,6 +2024,7 @@ impl SimulationImpl { .unwrap_bits_mut() .set(0, self.state.small_slots[index] != 0); } + SimTraceKind::PhantomConst { .. } => {} SimTraceKind::SimOnly { index, ty: _ } => { state .unwrap_sim_only_mut() @@ -2545,6 +2590,7 @@ impl SimulationImpl { ); } } + CompiledTypeLayoutBody::PhantomConst => {} CompiledTypeLayoutBody::Bundle { fields } => { let ty = Bundle::from_canonical(compiled_value.layout.ty); for ( diff --git a/crates/fayalite/src/sim/compiler.rs b/crates/fayalite/src/sim/compiler.rs index fbede7b..98e5abf 100644 --- a/crates/fayalite/src/sim/compiler.rs +++ b/crates/fayalite/src/sim/compiler.rs @@ -28,8 +28,8 @@ use crate::{ ExternModuleSimulation, SimTrace, SimTraceKind, SimTraces, TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl, TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, - TraceMemoryLocation, TraceModule, TraceModuleIO, TraceReg, TraceSInt, TraceScalarId, - TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire, + TraceMemoryLocation, TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, + TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire, interpreter::{ Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding, InsnsBuildingDone, InsnsBuildingKind, Label, SmallUInt, StatePartArrayIndex, @@ -85,6 +85,7 @@ pub(crate) struct CompiledBundleField { #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] pub(crate) enum CompiledTypeLayoutBody { Scalar, + PhantomConst, Array { /// debug names are ignored, use parent's layout instead element: Interned>, @@ -165,14 +166,11 @@ impl CompiledTypeLayout { body: CompiledTypeLayoutBody::Array { element }, } } - CanonicalType::PhantomConst(_) => { - let unit_layout = CompiledTypeLayout::get(()); - CompiledTypeLayout { - ty: *input, - layout: unit_layout.layout, - body: unit_layout.body, - } - } + CanonicalType::PhantomConst(_) => CompiledTypeLayout { + ty: *input, + layout: TypeLayout::empty(), + body: CompiledTypeLayoutBody::PhantomConst, + }, CanonicalType::Bundle(bundle) => { let mut layout = TypeLayout::empty(); let fields = bundle @@ -1681,18 +1679,23 @@ macro_rules! impl_compiler { instantiated_module: InstantiatedModule, target: MakeTraceDeclTarget, source_location: SourceLocation, + empty_kind: impl FnOnce() -> SimTraceKind, $($type_singular_field: impl FnOnce(StatePartIndex<$type_kind>) -> SimTraceKind,)* ) -> TraceLocation { match target { MakeTraceDeclTarget::Expr(target) => { let compiled_value = self.compile_expr(instantiated_module, target); let compiled_value = self.compiled_expr_to_value(compiled_value, source_location); - TraceLocation::Scalar(self.new_sim_trace(match compiled_value.range.len().as_single() { - $(Some(TypeLenSingle::$type_singular_variant) => { - $type_singular_field(compiled_value.range.$type_plural_field.start) - })* - None => unreachable!(), - })) + if compiled_value.range.is_empty() { + TraceLocation::Scalar(self.new_sim_trace(empty_kind())) + } else { + TraceLocation::Scalar(self.new_sim_trace(match compiled_value.range.len().as_single() { + $(Some(TypeLenSingle::$type_singular_variant) => { + $type_singular_field(compiled_value.range.$type_plural_field.start) + })* + None => unreachable!(), + })) + } } MakeTraceDeclTarget::Memory { id, @@ -1723,9 +1726,10 @@ macro_rules! impl_compiler { instantiated_module, target, source_location, + || unreachable!(), |index| SimTraceKind::SmallUInt { index, ty }, |index| SimTraceKind::BigUInt { index, ty }, - |_| unreachable!(""), + |_| unreachable!(), ), name, ty, @@ -1737,9 +1741,10 @@ macro_rules! impl_compiler { instantiated_module, target, source_location, + || unreachable!(), |index| SimTraceKind::SmallSInt { index, ty }, |index| SimTraceKind::BigSInt { index, ty }, - |_| unreachable!(""), + |_| unreachable!(), ), name, ty, @@ -1751,9 +1756,10 @@ macro_rules! impl_compiler { instantiated_module, target, source_location, + || unreachable!(), |index| SimTraceKind::SmallBool { index }, |index| SimTraceKind::BigBool { index }, - |_| unreachable!(""), + |_| unreachable!(), ), name, flow, @@ -1798,15 +1804,16 @@ macro_rules! impl_compiler { } .into() } - CanonicalType::Bundle(_) | CanonicalType::PhantomConst(_) => unreachable!(), + CanonicalType::Bundle(_) => unreachable!(), CanonicalType::AsyncReset(_) => TraceAsyncReset { location: self.make_trace_scalar_helper( instantiated_module, target, source_location, + || unreachable!(), |index| SimTraceKind::SmallAsyncReset { index }, |index| SimTraceKind::BigAsyncReset { index }, - |_| unreachable!(""), + |_| unreachable!(), ), name, flow, @@ -1817,9 +1824,10 @@ macro_rules! impl_compiler { instantiated_module, target, source_location, + || unreachable!(), |index| SimTraceKind::SmallSyncReset { index }, |index| SimTraceKind::BigSyncReset { index }, - |_| unreachable!(""), + |_| unreachable!(), ), name, flow, @@ -1831,21 +1839,38 @@ macro_rules! impl_compiler { instantiated_module, target, source_location, + || unreachable!(), |index| SimTraceKind::SmallClock { index }, |index| SimTraceKind::BigClock { index }, - |_| unreachable!(""), + |_| unreachable!(), ), name, flow, } .into(), + CanonicalType::PhantomConst(ty) => TracePhantomConst { + location: self.make_trace_scalar_helper( + instantiated_module, + target, + source_location, + || SimTraceKind::PhantomConst { ty }, + |_| unreachable!(), + |_| unreachable!(), + |_| unreachable!(), + ), + name, + ty, + flow, + } + .into(), CanonicalType::DynSimOnly(ty) => TraceSimOnly { location: self.make_trace_scalar_helper( instantiated_module, target, source_location, - |_| unreachable!(""), - |_| unreachable!(""), + || unreachable!(), + |_| unreachable!(), + |_| unreachable!(), |index| SimTraceKind::SimOnly { index, ty }, ), name, @@ -2295,16 +2320,10 @@ impl Compiler { | CanonicalType::SyncReset(_) | CanonicalType::Reset(_) | CanonicalType::Clock(_) - | CanonicalType::DynSimOnly(_) => { + | CanonicalType::DynSimOnly(_) + | CanonicalType::PhantomConst(_) => { self.make_trace_scalar(instantiated_module, target, name, source_location) } - CanonicalType::PhantomConst(_) => TraceBundle { - name, - fields: Interned::default(), - ty: Bundle::new(Interned::default()), - flow: target.flow(), - } - .into(), } } fn make_trace_decl( @@ -4293,6 +4312,7 @@ impl Compiler { start += element_bit_width; } } + CompiledTypeLayoutBody::PhantomConst => {} CompiledTypeLayoutBody::Bundle { fields } => { let CompiledTypeLayoutBody::Bundle { fields: mask_fields, diff --git a/crates/fayalite/src/sim/vcd.rs b/crates/fayalite/src/sim/vcd.rs index e66c3ee..6ba37b3 100644 --- a/crates/fayalite/src/sim/vcd.rs +++ b/crates/fayalite/src/sim/vcd.rs @@ -6,12 +6,14 @@ use crate::{ expr::Flow, int::UInt, intern::{Intern, Interned}, + prelude::PhantomConst, sim::{ TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl, TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule, - TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId, TraceScope, TraceSimOnly, - TraceSyncReset, TraceUInt, TraceWire, TraceWriter, TraceWriterDecls, + TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, TraceScalar, TraceScalarId, + TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire, TraceWriter, + TraceWriterDecls, time::{SimDuration, SimInstant}, value::DynSimOnlyValue, }, @@ -283,6 +285,7 @@ impl WriteTrace for TraceScalar { Self::Clock(v) => v.write_trace(writer, arg), Self::SyncReset(v) => v.write_trace(writer, arg), Self::AsyncReset(v) => v.write_trace(writer, arg), + Self::PhantomConst(v) => v.write_trace(writer, arg), Self::SimOnly(v) => v.write_trace(writer, arg), } } @@ -549,6 +552,33 @@ impl WriteTrace for TraceAsyncReset { } } +impl WriteTrace for TracePhantomConst { + 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, + MemoryElementPartBody::Scalar, + writer, + "string", + 1, + location, + scope.new_identifier(name), + ) + } +} + impl WriteTrace for TraceSimOnly { fn write_trace(self, writer: &mut W, mut arg: A) -> io::Result<()> { let ArgInType { @@ -1091,6 +1121,16 @@ impl TraceWriter for VcdWriter { write_enum_discriminant_value_change(&mut self.writer, variant_index, ty, id.as_usize()) } + fn set_signal_phantom_const( + &mut self, + id: TraceScalarId, + ty: PhantomConst, + ) -> Result<(), Self::Error> { + // avoid multi-line strings because GTKWave can't display them properly: + // https://github.com/gtkwave/gtkwave/issues/460 + write_string_value_change(&mut self.writer, format_args!("{ty:?}"), id.as_usize()) + } + fn set_signal_sim_only_value( &mut self, id: TraceScalarId, diff --git a/crates/fayalite/src/ty/serde_impls.rs b/crates/fayalite/src/ty/serde_impls.rs index 1ca916b..af324f9 100644 --- a/crates/fayalite/src/ty/serde_impls.rs +++ b/crates/fayalite/src/ty/serde_impls.rs @@ -127,7 +127,7 @@ impl From for CanonicalType { SerdeCanonicalType::Reset => Self::Reset(Reset), SerdeCanonicalType::Clock => Self::Clock(Clock), SerdeCanonicalType::PhantomConst(value) => { - Self::PhantomConst(PhantomConst::new(value.0)) + Self::PhantomConst(PhantomConst::new_interned(value.0)) } SerdeCanonicalType::DynSimOnly(value) => Self::DynSimOnly(value), } diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index 1f452c9..75f7cef 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -2244,3 +2244,41 @@ fn test_sim_resettable_counter_async_immediate_reset() { panic!(); } } + +#[hdl_module(outline_generated)] +pub fn phantom_const() { + #[hdl] + let out: Array>, 2> = + m.output(Array::new_static(PhantomConst::new_sized(vec![ + "a".into(), + "b".into(), + ]))); + let _ = out; + #[hdl] + let mut mem = memory(PhantomConst::new("mem_element")); + mem.depth(1); + let port = mem.new_read_port(); + connect_any(port.addr, 0u8); + connect(port.clk, false.to_clock()); + connect(port.en, false); +} + +#[test] +fn test_phantom_const() { + let _n = SourceLocation::normalize_files_for_tests(); + let mut sim = Simulation::new(phantom_const()); + let mut writer = RcWriter::default(); + sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); + 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/phantom_const.vcd") { + panic!(); + } + let sim_debug = format!("{sim:#?}"); + println!("#######\n{sim_debug}\n#######"); + if sim_debug != include_str!("sim/expected/phantom_const.txt") { + panic!(); + } +} diff --git a/crates/fayalite/tests/sim/expected/phantom_const.txt b/crates/fayalite/tests/sim/expected/phantom_const.txt new file mode 100644 index 0000000..dbc8f12 --- /dev/null +++ b/crates/fayalite/tests/sim/expected/phantom_const.txt @@ -0,0 +1,514 @@ +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: UInt<0>, + }, + ], + .. + }, + big_slots: StatePartLayout { + len: 7, + debug_data: [ + SlotDebugData { + name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.addr", + ty: UInt<0>, + }, + SlotDebugData { + name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.en", + ty: Bool, + }, + SlotDebugData { + name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.clk", + ty: Clock, + }, + SlotDebugData { + name: "", + ty: UInt<8>, + }, + SlotDebugData { + name: "", + ty: UInt<0>, + }, + SlotDebugData { + name: "", + ty: Bool, + }, + SlotDebugData { + name: "", + ty: Clock, + }, + ], + .. + }, + sim_only_slots: StatePartLayout { + len: 0, + debug_data: [], + layout_data: [], + .. + }, + }, + memories: StatePartLayout { + len: 1, + debug_data: [ + (), + ], + layout_data: [ + MemoryData { + array_type: Array, + data: [ + // len = 0x1 + [0x0]: 0x0, + ], + }, + ], + .. + }, + }, + insns: [ + // at: module-XXXXXXXXXX.rs:1:1 + 0: Const { + dest: StatePartIndex(5), // (0x0) SlotDebugData { name: "", ty: Bool }, + value: 0x0, + }, + 1: Copy { + dest: StatePartIndex(6), // (0x0) SlotDebugData { name: "", ty: Clock }, + src: StatePartIndex(5), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:6:1 + 2: Copy { + dest: StatePartIndex(2), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.clk", ty: Clock }, + src: StatePartIndex(6), // (0x0) SlotDebugData { name: "", ty: Clock }, + }, + // at: module-XXXXXXXXXX.rs:7:1 + 3: Copy { + dest: StatePartIndex(1), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.en", ty: Bool }, + src: StatePartIndex(5), // (0x0) SlotDebugData { name: "", ty: Bool }, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 4: Const { + dest: StatePartIndex(3), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + value: 0x0, + }, + 5: CastToUInt { + dest: StatePartIndex(4), // (0x0) SlotDebugData { name: "", ty: UInt<0> }, + src: StatePartIndex(3), // (0x0) SlotDebugData { name: "", ty: UInt<8> }, + dest_width: 0, + }, + // at: module-XXXXXXXXXX.rs:5:1 + 6: Copy { + dest: StatePartIndex(0), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.addr", ty: UInt<0> }, + src: StatePartIndex(4), // (0x0) SlotDebugData { name: "", ty: UInt<0> }, + }, + // at: module-XXXXXXXXXX.rs:3:1 + 7: CastBigToArrayIndex { + dest: StatePartIndex(4), // (0x0 0) SlotDebugData { name: "", ty: UInt<0> }, + src: StatePartIndex(0), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.addr", ty: UInt<0> }, + }, + 8: IsNonZeroDestIsSmall { + dest: StatePartIndex(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(1), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.en", ty: Bool }, + }, + 9: BranchIfSmallZero { + target: 11, + value: StatePartIndex(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 10: Branch { + target: 11, + }, + 11: IsNonZeroDestIsSmall { + dest: StatePartIndex(2), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + src: StatePartIndex(2), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.clk", ty: Clock }, + }, + 12: AndSmall { + dest: StatePartIndex(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(2), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + rhs: StatePartIndex(0), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + }, + 13: BranchIfSmallZero { + target: 14, + value: StatePartIndex(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + }, + 14: XorSmallImmediate { + dest: StatePartIndex(0), // (0x1 1) SlotDebugData { name: "", ty: Bool }, + lhs: StatePartIndex(2), // (0x0 0) SlotDebugData { name: "", ty: Bool }, + rhs: 0x1, + }, + // at: module-XXXXXXXXXX.rs:1:1 + 15: Return, + ], + .. + }, + pc: 15, + memory_write_log: [], + memories: StatePart { + value: [ + MemoryData { + array_type: Array, + data: [ + // len = 0x1 + [0x0]: 0x0, + ], + }, + ], + }, + small_slots: StatePart { + value: [ + 1, + 0, + 0, + 0, + 0, + ], + }, + big_slots: StatePart { + value: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + }, + sim_only_slots: StatePart { + value: [], + }, + }, + io: Instance { + name: ::phantom_const, + instantiated: Module { + name: phantom_const, + .. + }, + }, + main_module: SimulationModuleState { + base_targets: [ + Instance { + name: ::phantom_const, + instantiated: Module { + name: phantom_const, + .. + }, + }.out, + ], + uninitialized_ios: {}, + io_targets: { + Instance { + name: ::phantom_const, + instantiated: Module { + name: phantom_const, + .. + }, + }.out, + Instance { + name: ::phantom_const, + instantiated: Module { + name: phantom_const, + .. + }, + }.out[0], + Instance { + name: ::phantom_const, + instantiated: Module { + name: phantom_const, + .. + }, + }.out[1], + }, + did_initial_settle: true, + }, + extern_modules: [], + trace_decls: TraceModule { + name: "phantom_const", + children: [ + TraceModuleIO { + name: "out", + child: TraceArray { + name: "out", + elements: [ + TracePhantomConst { + location: TraceScalarId(0), + name: "[0]", + ty: PhantomConst( + ["a","b"], + ), + flow: Sink, + }, + TracePhantomConst { + location: TraceScalarId(1), + name: "[1]", + ty: PhantomConst( + ["a","b"], + ), + flow: Sink, + }, + ], + ty: Array, + flow: Sink, + }, + ty: Array, + flow: Sink, + }, + TraceMem { + id: TraceMemoryId(0), + name: "mem", + stride: 0, + element_type: TracePhantomConst { + location: TraceMemoryLocation { + id: TraceMemoryId(0), + depth: 1, + stride: 0, + start: 0, + len: 0, + }, + name: "mem", + ty: PhantomConst( + "mem_element", + ), + flow: Duplex, + }, + ports: [ + TraceMemPort { + name: "r0", + bundle: TraceBundle { + name: "r0", + fields: [ + TraceUInt { + location: TraceScalarId(2), + name: "addr", + ty: UInt<0>, + flow: Sink, + }, + TraceBool { + location: TraceScalarId(3), + name: "en", + flow: Sink, + }, + TraceClock { + location: TraceScalarId(4), + name: "clk", + flow: Sink, + }, + TracePhantomConst { + location: TraceScalarId(5), + name: "data", + ty: PhantomConst( + "mem_element", + ), + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<0>, + /* offset = 0 */ + en: Bool, + /* offset = 1 */ + clk: Clock, + #[hdl(flip)] /* offset = 2 */ + data: PhantomConst( + "mem_element", + ), + }, + flow: Sink, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<0>, + /* offset = 0 */ + en: Bool, + /* offset = 1 */ + clk: Clock, + #[hdl(flip)] /* offset = 2 */ + data: PhantomConst( + "mem_element", + ), + }, + }, + ], + array_type: Array, + }, + ], + }, + traces: [ + SimTrace { + id: TraceScalarId(0), + kind: PhantomConst { + ty: PhantomConst( + ["a","b"], + ), + }, + state: PhantomConst, + last_state: PhantomConst, + }, + SimTrace { + id: TraceScalarId(1), + kind: PhantomConst { + ty: PhantomConst( + ["a","b"], + ), + }, + state: PhantomConst, + last_state: PhantomConst, + }, + SimTrace { + id: TraceScalarId(2), + kind: BigUInt { + index: StatePartIndex(0), + ty: UInt<0>, + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(3), + kind: BigBool { + index: StatePartIndex(1), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(4), + kind: BigClock { + index: StatePartIndex(2), + }, + state: 0x0, + last_state: 0x0, + }, + SimTrace { + id: TraceScalarId(5), + kind: PhantomConst { + ty: PhantomConst( + "mem_element", + ), + }, + state: PhantomConst, + last_state: PhantomConst, + }, + ], + trace_memories: { + StatePartIndex(0): TraceMem { + id: TraceMemoryId(0), + name: "mem", + stride: 0, + element_type: TracePhantomConst { + location: TraceMemoryLocation { + id: TraceMemoryId(0), + depth: 1, + stride: 0, + start: 0, + len: 0, + }, + name: "mem", + ty: PhantomConst( + "mem_element", + ), + flow: Duplex, + }, + ports: [ + TraceMemPort { + name: "r0", + bundle: TraceBundle { + name: "r0", + fields: [ + TraceUInt { + location: TraceScalarId(2), + name: "addr", + ty: UInt<0>, + flow: Sink, + }, + TraceBool { + location: TraceScalarId(3), + name: "en", + flow: Sink, + }, + TraceClock { + location: TraceScalarId(4), + name: "clk", + flow: Sink, + }, + TracePhantomConst { + location: TraceScalarId(5), + name: "data", + ty: PhantomConst( + "mem_element", + ), + flow: Source, + }, + ], + ty: Bundle { + /* offset = 0 */ + addr: UInt<0>, + /* offset = 0 */ + en: Bool, + /* offset = 1 */ + clk: Clock, + #[hdl(flip)] /* offset = 2 */ + data: PhantomConst( + "mem_element", + ), + }, + flow: Sink, + }, + ty: Bundle { + /* offset = 0 */ + addr: UInt<0>, + /* offset = 0 */ + en: Bool, + /* offset = 1 */ + clk: Clock, + #[hdl(flip)] /* offset = 2 */ + data: PhantomConst( + "mem_element", + ), + }, + }, + ], + array_type: Array, + }, + }, + trace_writers: [ + Running( + VcdWriter { + finished_init: true, + timescale: 1 ps, + .. + }, + ), + ], + clocks_triggered: [ + StatePartIndex(1), + ], + event_queue: EventQueue(EventQueueData { + instant: 1 μ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/phantom_const.vcd b/crates/fayalite/tests/sim/expected/phantom_const.vcd new file mode 100644 index 0000000..ba3869b --- /dev/null +++ b/crates/fayalite/tests/sim/expected/phantom_const.vcd @@ -0,0 +1,31 @@ +$timescale 1 ps $end +$scope module phantom_const $end +$scope struct out $end +$var string 1 ! \[0] $end +$var string 1 " \[1] $end +$upscope $end +$scope struct mem $end +$scope struct contents $end +$scope struct \[0] $end +$var string 1 ' mem $end +$upscope $end +$upscope $end +$scope struct r0 $end +$var string 0 # addr $end +$var wire 1 $ en $end +$var wire 1 % clk $end +$var string 1 & data $end +$upscope $end +$upscope $end +$upscope $end +$enddefinitions $end +$dumpvars +s0 ' +sPhantomConst([\"a\",\"b\"]) ! +sPhantomConst([\"a\",\"b\"]) " +s0 # +0$ +0% +sPhantomConst(\"mem_element\") & +$end +#1000000