fix Simulator panicking when you use PhantomConst
This commit is contained in:
parent
840c5e1895
commit
0b77d1bea0
11 changed files with 756 additions and 55 deletions
|
|
@ -300,9 +300,7 @@ macro_rules! define_uint_in_range_type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn new(start: Start::SizeType, end: End::SizeType) -> Self {
|
pub fn new(start: Start::SizeType, end: End::SizeType) -> Self {
|
||||||
Self::from_phantom_const_range(PhantomConst::new(
|
Self::from_phantom_const_range(PhantomConst::new_sized($SerdeRange { start, end }))
|
||||||
$SerdeRange { start, end }.intern_sized(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
pub fn bit_width(self) -> usize {
|
pub fn bit_width(self) -> usize {
|
||||||
self.value.width()
|
self.value.width()
|
||||||
|
|
|
||||||
|
|
@ -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.
|
/// 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)]
|
/// #[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
/// pub struct Config {
|
/// pub struct Config {
|
||||||
/// pub foo: usize,
|
/// 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:
|
/// // you can then use Fayalite's standard syntax for creating dynamic types at runtime:
|
||||||
/// let bar = Bundle::new(Default::default());
|
/// 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];
|
/// let ty = WrapMyArray[config];
|
||||||
/// assert_eq!(ty.my_array, Array[bar][12]);
|
/// 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.
|
/// 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)]
|
/// # #[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
/// # pub struct ConfigItem {}
|
/// # pub struct ConfigItem {}
|
||||||
/// # impl 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:
|
/// // 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];
|
/// let ty = FlagPerItem[config];
|
||||||
/// assert_eq!(ty.flags, Array[Bool][5]);
|
/// assert_eq!(ty.flags, Array[Bool][5]);
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ impl<T: Type + PhantomConstValue> Index<T> for PhantomConstWithoutGenerics {
|
||||||
type Output = PhantomConst<T>;
|
type Output = PhantomConst<T>;
|
||||||
|
|
||||||
fn index(&self, value: T) -> &Self::Output {
|
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<T: ?Sized + PhantomConstValue> Memoize for PhantomConstCanonicalMemoize<T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
|
impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
|
||||||
pub fn new(value: Interned<T>) -> Self {
|
pub fn new_interned(value: Interned<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: LazyInterned::Interned(value),
|
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<U: Intern + std::ops::Deref<Target = T>>(value: U) -> Self
|
||||||
|
where
|
||||||
|
T: ToOwned<Owned = U>,
|
||||||
|
{
|
||||||
|
Self::new_interned(value.intern_deref())
|
||||||
|
}
|
||||||
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self {
|
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: LazyInterned::new_lazy(v),
|
value: LazyInterned::new_lazy(v),
|
||||||
|
|
@ -245,7 +260,7 @@ impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
|
||||||
if let Some(&retval) = <dyn Any>::downcast_ref::<PhantomConst>(&self) {
|
if let Some(&retval) = <dyn Any>::downcast_ref::<PhantomConst>(&self) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
<PhantomConst>::new(
|
<PhantomConst>::new_interned(
|
||||||
PhantomConstCanonicalMemoize::<T, false>(PhantomData).get_owned(self.get()),
|
PhantomConstCanonicalMemoize::<T, false>(PhantomData).get_owned(self.get()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +268,7 @@ impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
|
||||||
if let Some(&retval) = <dyn Any>::downcast_ref::<Self>(&canonical_type) {
|
if let Some(&retval) = <dyn Any>::downcast_ref::<Self>(&canonical_type) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
Self::new(
|
Self::new_interned(
|
||||||
PhantomConstCanonicalMemoize::<T, true>(PhantomData).get_owned(canonical_type.get()),
|
PhantomConstCanonicalMemoize::<T, true>(PhantomData).get_owned(canonical_type.get()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -346,7 +361,9 @@ impl<'de, T: ?Sized + PhantomConstValue> Deserialize<'de> for PhantomConst<T> {
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
match SerdeType::<T>::deserialize(deserializer)? {
|
match SerdeType::<T>::deserialize(deserializer)? {
|
||||||
SerdeCanonicalType::PhantomConst(SerdePhantomConst(value)) => Ok(Self::new(value)),
|
SerdeCanonicalType::PhantomConst(SerdePhantomConst(value)) => {
|
||||||
|
Ok(Self::new_interned(value))
|
||||||
|
}
|
||||||
ty => Err(Error::invalid_value(
|
ty => Err(Error::invalid_value(
|
||||||
serde::de::Unexpected::Other(ty.as_serde_unexpected_str()),
|
serde::de::Unexpected::Other(ty.as_serde_unexpected_str()),
|
||||||
&"a PhantomConst",
|
&"a PhantomConst",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::{intern::Intern, prelude::*};
|
use crate::prelude::*;
|
||||||
use ordered_float::NotNan;
|
use ordered_float::NotNan;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -26,12 +26,9 @@ impl ClockInput {
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
clk: Clock,
|
clk: Clock,
|
||||||
properties: PhantomConst::new(
|
properties: PhantomConst::new_sized(ClockInputProperties {
|
||||||
ClockInputProperties {
|
|
||||||
frequency: NotNan::new(frequency).expect("just checked"),
|
frequency: NotNan::new(frequency).expect("just checked"),
|
||||||
}
|
}),
|
||||||
.intern_sized(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn frequency(self) -> f64 {
|
pub fn frequency(self) -> f64 {
|
||||||
|
|
|
||||||
|
|
@ -416,6 +416,15 @@ impl_trace_decl! {
|
||||||
name: Interned<str>,
|
name: Interned<str>,
|
||||||
flow: Flow,
|
flow: Flow,
|
||||||
}),
|
}),
|
||||||
|
PhantomConst(TracePhantomConst {
|
||||||
|
fn location(self) -> _ {
|
||||||
|
self.location
|
||||||
|
}
|
||||||
|
location: TraceLocation,
|
||||||
|
name: Interned<str>,
|
||||||
|
ty: PhantomConst,
|
||||||
|
flow: Flow,
|
||||||
|
}),
|
||||||
SimOnly(TraceSimOnly {
|
SimOnly(TraceSimOnly {
|
||||||
fn location(self) -> _ {
|
fn location(self) -> _ {
|
||||||
self.location
|
self.location
|
||||||
|
|
@ -526,6 +535,11 @@ pub trait TraceWriter: fmt::Debug + 'static {
|
||||||
variant_index: usize,
|
variant_index: usize,
|
||||||
ty: Enum,
|
ty: Enum,
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
|
fn set_signal_phantom_const(
|
||||||
|
&mut self,
|
||||||
|
id: TraceScalarId,
|
||||||
|
ty: PhantomConst,
|
||||||
|
) -> Result<(), Self::Error>;
|
||||||
fn set_signal_sim_only_value(
|
fn set_signal_sim_only_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: TraceScalarId,
|
id: TraceScalarId,
|
||||||
|
|
@ -585,6 +599,11 @@ trait TraceWriterDynTrait: fmt::Debug + 'static {
|
||||||
variant_index: usize,
|
variant_index: usize,
|
||||||
ty: Enum,
|
ty: Enum,
|
||||||
) -> std::io::Result<()>;
|
) -> 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(
|
fn set_signal_sim_only_value_dyn(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: TraceScalarId,
|
id: TraceScalarId,
|
||||||
|
|
@ -649,6 +668,13 @@ impl<T: TraceWriter> TraceWriterDynTrait for T {
|
||||||
.map_err(err_into_io)?,
|
.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(
|
fn set_signal_sim_only_value_dyn(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: TraceScalarId,
|
id: TraceScalarId,
|
||||||
|
|
@ -720,6 +746,13 @@ impl TraceWriter for DynTraceWriter {
|
||||||
self.0
|
self.0
|
||||||
.set_signal_enum_discriminant_dyn(id, variant_index, ty)
|
.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(
|
fn set_signal_sim_only_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: TraceScalarId,
|
id: TraceScalarId,
|
||||||
|
|
@ -895,12 +928,16 @@ pub(crate) enum SimTraceKind {
|
||||||
index: StatePartIndex<StatePartKindSimOnlySlots>,
|
index: StatePartIndex<StatePartKindSimOnlySlots>,
|
||||||
ty: DynSimOnly,
|
ty: DynSimOnly,
|
||||||
},
|
},
|
||||||
|
PhantomConst {
|
||||||
|
ty: PhantomConst,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub(crate) enum SimTraceState {
|
pub(crate) enum SimTraceState {
|
||||||
Bits(BitVec),
|
Bits(BitVec),
|
||||||
SimOnly(DynSimOnlyValue),
|
SimOnly(DynSimOnlyValue),
|
||||||
|
PhantomConst,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for SimTraceState {
|
impl Clone for SimTraceState {
|
||||||
|
|
@ -908,6 +945,7 @@ impl Clone for SimTraceState {
|
||||||
match self {
|
match self {
|
||||||
Self::Bits(v) => Self::Bits(v.clone()),
|
Self::Bits(v) => Self::Bits(v.clone()),
|
||||||
Self::SimOnly(v) => Self::SimOnly(v.clone()),
|
Self::SimOnly(v) => Self::SimOnly(v.clone()),
|
||||||
|
Self::PhantomConst => Self::PhantomConst,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn clone_from(&mut self, source: &Self) {
|
fn clone_from(&mut self, source: &Self) {
|
||||||
|
|
@ -956,6 +994,7 @@ impl fmt::Debug for SimTraceState {
|
||||||
match self {
|
match self {
|
||||||
SimTraceState::Bits(v) => BitSliceWriteWithBase(v).fmt(f),
|
SimTraceState::Bits(v) => BitSliceWriteWithBase(v).fmt(f),
|
||||||
SimTraceState::SimOnly(v) => 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 } => {
|
SimTraceKind::EnumDiscriminant { index: _, ty } => {
|
||||||
SimTraceState::Bits(BitVec::repeat(false, ty.discriminant_bit_width()))
|
SimTraceState::Bits(BitVec::repeat(false, ty.discriminant_bit_width()))
|
||||||
}
|
}
|
||||||
|
SimTraceKind::PhantomConst { .. } => SimTraceState::PhantomConst,
|
||||||
SimTraceKind::SimOnly { index: _, ty } => SimTraceState::SimOnly(ty.default_value()),
|
SimTraceKind::SimOnly { index: _, ty } => SimTraceState::SimOnly(ty.default_value()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1097,6 +1137,7 @@ impl SimulationModuleState {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CompiledTypeLayoutBody::PhantomConst => false,
|
||||||
CompiledTypeLayoutBody::Bundle { .. } => {
|
CompiledTypeLayoutBody::Bundle { .. } => {
|
||||||
let value = value.map_ty(Bundle::from_canonical);
|
let value = value.map_ty(Bundle::from_canonical);
|
||||||
let mut sub_targets = Vec::new();
|
let mut sub_targets = Vec::new();
|
||||||
|
|
@ -1910,6 +1951,9 @@ impl SimulationImpl {
|
||||||
ty,
|
ty,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
SimTraceKind::PhantomConst { ty } => {
|
||||||
|
trace_writer.set_signal_phantom_const(id, ty)?
|
||||||
|
}
|
||||||
SimTraceKind::SimOnly { .. } => {
|
SimTraceKind::SimOnly { .. } => {
|
||||||
trace_writer.set_signal_sim_only_value(id, state.unwrap_sim_only_ref())?
|
trace_writer.set_signal_sim_only_value(id, state.unwrap_sim_only_ref())?
|
||||||
}
|
}
|
||||||
|
|
@ -1980,6 +2024,7 @@ impl SimulationImpl {
|
||||||
.unwrap_bits_mut()
|
.unwrap_bits_mut()
|
||||||
.set(0, self.state.small_slots[index] != 0);
|
.set(0, self.state.small_slots[index] != 0);
|
||||||
}
|
}
|
||||||
|
SimTraceKind::PhantomConst { .. } => {}
|
||||||
SimTraceKind::SimOnly { index, ty: _ } => {
|
SimTraceKind::SimOnly { index, ty: _ } => {
|
||||||
state
|
state
|
||||||
.unwrap_sim_only_mut()
|
.unwrap_sim_only_mut()
|
||||||
|
|
@ -2545,6 +2590,7 @@ impl SimulationImpl {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CompiledTypeLayoutBody::PhantomConst => {}
|
||||||
CompiledTypeLayoutBody::Bundle { fields } => {
|
CompiledTypeLayoutBody::Bundle { fields } => {
|
||||||
let ty = Bundle::from_canonical(compiled_value.layout.ty);
|
let ty = Bundle::from_canonical(compiled_value.layout.ty);
|
||||||
for (
|
for (
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ use crate::{
|
||||||
ExternModuleSimulation, SimTrace, SimTraceKind, SimTraces, TraceArray, TraceAsyncReset,
|
ExternModuleSimulation, SimTrace, SimTraceKind, SimTraces, TraceArray, TraceAsyncReset,
|
||||||
TraceBool, TraceBundle, TraceClock, TraceDecl, TraceEnumDiscriminant, TraceEnumWithFields,
|
TraceBool, TraceBundle, TraceClock, TraceDecl, TraceEnumDiscriminant, TraceEnumWithFields,
|
||||||
TraceFieldlessEnum, TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId,
|
TraceFieldlessEnum, TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId,
|
||||||
TraceMemoryLocation, TraceModule, TraceModuleIO, TraceReg, TraceSInt, TraceScalarId,
|
TraceMemoryLocation, TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt,
|
||||||
TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire,
|
TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire,
|
||||||
interpreter::{
|
interpreter::{
|
||||||
Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding,
|
Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding,
|
||||||
InsnsBuildingDone, InsnsBuildingKind, Label, SmallUInt, StatePartArrayIndex,
|
InsnsBuildingDone, InsnsBuildingKind, Label, SmallUInt, StatePartArrayIndex,
|
||||||
|
|
@ -85,6 +85,7 @@ pub(crate) struct CompiledBundleField {
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
pub(crate) enum CompiledTypeLayoutBody {
|
pub(crate) enum CompiledTypeLayoutBody {
|
||||||
Scalar,
|
Scalar,
|
||||||
|
PhantomConst,
|
||||||
Array {
|
Array {
|
||||||
/// debug names are ignored, use parent's layout instead
|
/// debug names are ignored, use parent's layout instead
|
||||||
element: Interned<CompiledTypeLayout<CanonicalType>>,
|
element: Interned<CompiledTypeLayout<CanonicalType>>,
|
||||||
|
|
@ -165,14 +166,11 @@ impl<T: Type> CompiledTypeLayout<T> {
|
||||||
body: CompiledTypeLayoutBody::Array { element },
|
body: CompiledTypeLayoutBody::Array { element },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CanonicalType::PhantomConst(_) => {
|
CanonicalType::PhantomConst(_) => CompiledTypeLayout {
|
||||||
let unit_layout = CompiledTypeLayout::get(());
|
|
||||||
CompiledTypeLayout {
|
|
||||||
ty: *input,
|
ty: *input,
|
||||||
layout: unit_layout.layout,
|
layout: TypeLayout::empty(),
|
||||||
body: unit_layout.body,
|
body: CompiledTypeLayoutBody::PhantomConst,
|
||||||
}
|
},
|
||||||
}
|
|
||||||
CanonicalType::Bundle(bundle) => {
|
CanonicalType::Bundle(bundle) => {
|
||||||
let mut layout = TypeLayout::empty();
|
let mut layout = TypeLayout::empty();
|
||||||
let fields = bundle
|
let fields = bundle
|
||||||
|
|
@ -1681,12 +1679,16 @@ macro_rules! impl_compiler {
|
||||||
instantiated_module: InstantiatedModule,
|
instantiated_module: InstantiatedModule,
|
||||||
target: MakeTraceDeclTarget,
|
target: MakeTraceDeclTarget,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
|
empty_kind: impl FnOnce() -> SimTraceKind,
|
||||||
$($type_singular_field: impl FnOnce(StatePartIndex<$type_kind>) -> SimTraceKind,)*
|
$($type_singular_field: impl FnOnce(StatePartIndex<$type_kind>) -> SimTraceKind,)*
|
||||||
) -> TraceLocation {
|
) -> TraceLocation {
|
||||||
match target {
|
match target {
|
||||||
MakeTraceDeclTarget::Expr(target) => {
|
MakeTraceDeclTarget::Expr(target) => {
|
||||||
let compiled_value = self.compile_expr(instantiated_module, target);
|
let compiled_value = self.compile_expr(instantiated_module, target);
|
||||||
let compiled_value = self.compiled_expr_to_value(compiled_value, source_location);
|
let compiled_value = self.compiled_expr_to_value(compiled_value, source_location);
|
||||||
|
if compiled_value.range.is_empty() {
|
||||||
|
TraceLocation::Scalar(self.new_sim_trace(empty_kind()))
|
||||||
|
} else {
|
||||||
TraceLocation::Scalar(self.new_sim_trace(match compiled_value.range.len().as_single() {
|
TraceLocation::Scalar(self.new_sim_trace(match compiled_value.range.len().as_single() {
|
||||||
$(Some(TypeLenSingle::$type_singular_variant) => {
|
$(Some(TypeLenSingle::$type_singular_variant) => {
|
||||||
$type_singular_field(compiled_value.range.$type_plural_field.start)
|
$type_singular_field(compiled_value.range.$type_plural_field.start)
|
||||||
|
|
@ -1694,6 +1696,7 @@ macro_rules! impl_compiler {
|
||||||
None => unreachable!(),
|
None => unreachable!(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
MakeTraceDeclTarget::Memory {
|
MakeTraceDeclTarget::Memory {
|
||||||
id,
|
id,
|
||||||
depth,
|
depth,
|
||||||
|
|
@ -1723,9 +1726,10 @@ macro_rules! impl_compiler {
|
||||||
instantiated_module,
|
instantiated_module,
|
||||||
target,
|
target,
|
||||||
source_location,
|
source_location,
|
||||||
|
|| unreachable!(),
|
||||||
|index| SimTraceKind::SmallUInt { index, ty },
|
|index| SimTraceKind::SmallUInt { index, ty },
|
||||||
|index| SimTraceKind::BigUInt { index, ty },
|
|index| SimTraceKind::BigUInt { index, ty },
|
||||||
|_| unreachable!(""),
|
|_| unreachable!(),
|
||||||
),
|
),
|
||||||
name,
|
name,
|
||||||
ty,
|
ty,
|
||||||
|
|
@ -1737,9 +1741,10 @@ macro_rules! impl_compiler {
|
||||||
instantiated_module,
|
instantiated_module,
|
||||||
target,
|
target,
|
||||||
source_location,
|
source_location,
|
||||||
|
|| unreachable!(),
|
||||||
|index| SimTraceKind::SmallSInt { index, ty },
|
|index| SimTraceKind::SmallSInt { index, ty },
|
||||||
|index| SimTraceKind::BigSInt { index, ty },
|
|index| SimTraceKind::BigSInt { index, ty },
|
||||||
|_| unreachable!(""),
|
|_| unreachable!(),
|
||||||
),
|
),
|
||||||
name,
|
name,
|
||||||
ty,
|
ty,
|
||||||
|
|
@ -1751,9 +1756,10 @@ macro_rules! impl_compiler {
|
||||||
instantiated_module,
|
instantiated_module,
|
||||||
target,
|
target,
|
||||||
source_location,
|
source_location,
|
||||||
|
|| unreachable!(),
|
||||||
|index| SimTraceKind::SmallBool { index },
|
|index| SimTraceKind::SmallBool { index },
|
||||||
|index| SimTraceKind::BigBool { index },
|
|index| SimTraceKind::BigBool { index },
|
||||||
|_| unreachable!(""),
|
|_| unreachable!(),
|
||||||
),
|
),
|
||||||
name,
|
name,
|
||||||
flow,
|
flow,
|
||||||
|
|
@ -1798,15 +1804,16 @@ macro_rules! impl_compiler {
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
CanonicalType::Bundle(_) | CanonicalType::PhantomConst(_) => unreachable!(),
|
CanonicalType::Bundle(_) => unreachable!(),
|
||||||
CanonicalType::AsyncReset(_) => TraceAsyncReset {
|
CanonicalType::AsyncReset(_) => TraceAsyncReset {
|
||||||
location: self.make_trace_scalar_helper(
|
location: self.make_trace_scalar_helper(
|
||||||
instantiated_module,
|
instantiated_module,
|
||||||
target,
|
target,
|
||||||
source_location,
|
source_location,
|
||||||
|
|| unreachable!(),
|
||||||
|index| SimTraceKind::SmallAsyncReset { index },
|
|index| SimTraceKind::SmallAsyncReset { index },
|
||||||
|index| SimTraceKind::BigAsyncReset { index },
|
|index| SimTraceKind::BigAsyncReset { index },
|
||||||
|_| unreachable!(""),
|
|_| unreachable!(),
|
||||||
),
|
),
|
||||||
name,
|
name,
|
||||||
flow,
|
flow,
|
||||||
|
|
@ -1817,9 +1824,10 @@ macro_rules! impl_compiler {
|
||||||
instantiated_module,
|
instantiated_module,
|
||||||
target,
|
target,
|
||||||
source_location,
|
source_location,
|
||||||
|
|| unreachable!(),
|
||||||
|index| SimTraceKind::SmallSyncReset { index },
|
|index| SimTraceKind::SmallSyncReset { index },
|
||||||
|index| SimTraceKind::BigSyncReset { index },
|
|index| SimTraceKind::BigSyncReset { index },
|
||||||
|_| unreachable!(""),
|
|_| unreachable!(),
|
||||||
),
|
),
|
||||||
name,
|
name,
|
||||||
flow,
|
flow,
|
||||||
|
|
@ -1831,21 +1839,38 @@ macro_rules! impl_compiler {
|
||||||
instantiated_module,
|
instantiated_module,
|
||||||
target,
|
target,
|
||||||
source_location,
|
source_location,
|
||||||
|
|| unreachable!(),
|
||||||
|index| SimTraceKind::SmallClock { index },
|
|index| SimTraceKind::SmallClock { index },
|
||||||
|index| SimTraceKind::BigClock { index },
|
|index| SimTraceKind::BigClock { index },
|
||||||
|_| unreachable!(""),
|
|_| unreachable!(),
|
||||||
),
|
),
|
||||||
name,
|
name,
|
||||||
flow,
|
flow,
|
||||||
}
|
}
|
||||||
.into(),
|
.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 {
|
CanonicalType::DynSimOnly(ty) => TraceSimOnly {
|
||||||
location: self.make_trace_scalar_helper(
|
location: self.make_trace_scalar_helper(
|
||||||
instantiated_module,
|
instantiated_module,
|
||||||
target,
|
target,
|
||||||
source_location,
|
source_location,
|
||||||
|_| unreachable!(""),
|
|| unreachable!(),
|
||||||
|_| unreachable!(""),
|
|_| unreachable!(),
|
||||||
|
|_| unreachable!(),
|
||||||
|index| SimTraceKind::SimOnly { index, ty },
|
|index| SimTraceKind::SimOnly { index, ty },
|
||||||
),
|
),
|
||||||
name,
|
name,
|
||||||
|
|
@ -2295,16 +2320,10 @@ impl Compiler {
|
||||||
| CanonicalType::SyncReset(_)
|
| CanonicalType::SyncReset(_)
|
||||||
| CanonicalType::Reset(_)
|
| CanonicalType::Reset(_)
|
||||||
| CanonicalType::Clock(_)
|
| CanonicalType::Clock(_)
|
||||||
| CanonicalType::DynSimOnly(_) => {
|
| CanonicalType::DynSimOnly(_)
|
||||||
|
| CanonicalType::PhantomConst(_) => {
|
||||||
self.make_trace_scalar(instantiated_module, target, name, source_location)
|
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(
|
fn make_trace_decl(
|
||||||
|
|
@ -4293,6 +4312,7 @@ impl Compiler {
|
||||||
start += element_bit_width;
|
start += element_bit_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CompiledTypeLayoutBody::PhantomConst => {}
|
||||||
CompiledTypeLayoutBody::Bundle { fields } => {
|
CompiledTypeLayoutBody::Bundle { fields } => {
|
||||||
let CompiledTypeLayoutBody::Bundle {
|
let CompiledTypeLayoutBody::Bundle {
|
||||||
fields: mask_fields,
|
fields: mask_fields,
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,14 @@ use crate::{
|
||||||
expr::Flow,
|
expr::Flow,
|
||||||
int::UInt,
|
int::UInt,
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
|
prelude::PhantomConst,
|
||||||
sim::{
|
sim::{
|
||||||
TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl,
|
TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl,
|
||||||
TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance,
|
TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance,
|
||||||
TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule,
|
TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule,
|
||||||
TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId, TraceScope, TraceSimOnly,
|
TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, TraceScalar, TraceScalarId,
|
||||||
TraceSyncReset, TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
|
TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire, TraceWriter,
|
||||||
|
TraceWriterDecls,
|
||||||
time::{SimDuration, SimInstant},
|
time::{SimDuration, SimInstant},
|
||||||
value::DynSimOnlyValue,
|
value::DynSimOnlyValue,
|
||||||
},
|
},
|
||||||
|
|
@ -283,6 +285,7 @@ impl WriteTrace for TraceScalar {
|
||||||
Self::Clock(v) => v.write_trace(writer, arg),
|
Self::Clock(v) => v.write_trace(writer, arg),
|
||||||
Self::SyncReset(v) => v.write_trace(writer, arg),
|
Self::SyncReset(v) => v.write_trace(writer, arg),
|
||||||
Self::AsyncReset(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),
|
Self::SimOnly(v) => v.write_trace(writer, arg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -549,6 +552,33 @@ impl WriteTrace for TraceAsyncReset {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WriteTrace for TracePhantomConst {
|
||||||
|
fn write_trace<W: io::Write, A: Arg>(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 {
|
impl WriteTrace for TraceSimOnly {
|
||||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||||
let ArgInType {
|
let ArgInType {
|
||||||
|
|
@ -1091,6 +1121,16 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
|
||||||
write_enum_discriminant_value_change(&mut self.writer, variant_index, ty, id.as_usize())
|
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(
|
fn set_signal_sim_only_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: TraceScalarId,
|
id: TraceScalarId,
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ impl From<SerdeCanonicalType> for CanonicalType {
|
||||||
SerdeCanonicalType::Reset => Self::Reset(Reset),
|
SerdeCanonicalType::Reset => Self::Reset(Reset),
|
||||||
SerdeCanonicalType::Clock => Self::Clock(Clock),
|
SerdeCanonicalType::Clock => Self::Clock(Clock),
|
||||||
SerdeCanonicalType::PhantomConst(value) => {
|
SerdeCanonicalType::PhantomConst(value) => {
|
||||||
Self::PhantomConst(PhantomConst::new(value.0))
|
Self::PhantomConst(PhantomConst::new_interned(value.0))
|
||||||
}
|
}
|
||||||
SerdeCanonicalType::DynSimOnly(value) => Self::DynSimOnly(value),
|
SerdeCanonicalType::DynSimOnly(value) => Self::DynSimOnly(value),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2244,3 +2244,41 @@ fn test_sim_resettable_counter_async_immediate_reset() {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[hdl_module(outline_generated)]
|
||||||
|
pub fn phantom_const() {
|
||||||
|
#[hdl]
|
||||||
|
let out: Array<PhantomConst<Vec<String>>, 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!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
514
crates/fayalite/tests/sim/expected/phantom_const.txt
Normal file
514
crates/fayalite/tests/sim/expected/phantom_const.txt
Normal file
|
|
@ -0,0 +1,514 @@
|
||||||
|
Simulation {
|
||||||
|
state: State {
|
||||||
|
insns: Insns {
|
||||||
|
state_layout: StateLayout {
|
||||||
|
ty: TypeLayout {
|
||||||
|
small_slots: StatePartLayout<SmallSlots> {
|
||||||
|
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<BigSlots> {
|
||||||
|
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<SimOnlySlots> {
|
||||||
|
len: 0,
|
||||||
|
debug_data: [],
|
||||||
|
layout_data: [],
|
||||||
|
..
|
||||||
|
},
|
||||||
|
},
|
||||||
|
memories: StatePartLayout<Memories> {
|
||||||
|
len: 1,
|
||||||
|
debug_data: [
|
||||||
|
(),
|
||||||
|
],
|
||||||
|
layout_data: [
|
||||||
|
MemoryData {
|
||||||
|
array_type: Array<PhantomConst("mem_element"), 1>,
|
||||||
|
data: [
|
||||||
|
// len = 0x1
|
||||||
|
[0x0]: 0x0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
..
|
||||||
|
},
|
||||||
|
},
|
||||||
|
insns: [
|
||||||
|
// at: module-XXXXXXXXXX.rs:1:1
|
||||||
|
0: Const {
|
||||||
|
dest: StatePartIndex<BigSlots>(5), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
value: 0x0,
|
||||||
|
},
|
||||||
|
1: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Clock },
|
||||||
|
src: StatePartIndex<BigSlots>(5), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:6:1
|
||||||
|
2: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(2), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.clk", ty: Clock },
|
||||||
|
src: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Clock },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:7:1
|
||||||
|
3: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.en", ty: Bool },
|
||||||
|
src: StatePartIndex<BigSlots>(5), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:1:1
|
||||||
|
4: Const {
|
||||||
|
dest: StatePartIndex<BigSlots>(3), // (0x0) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
value: 0x0,
|
||||||
|
},
|
||||||
|
5: CastToUInt {
|
||||||
|
dest: StatePartIndex<BigSlots>(4), // (0x0) SlotDebugData { name: "", ty: UInt<0> },
|
||||||
|
src: StatePartIndex<BigSlots>(3), // (0x0) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
dest_width: 0,
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:5:1
|
||||||
|
6: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(0), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.addr", ty: UInt<0> },
|
||||||
|
src: StatePartIndex<BigSlots>(4), // (0x0) SlotDebugData { name: "", ty: UInt<0> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:3:1
|
||||||
|
7: CastBigToArrayIndex {
|
||||||
|
dest: StatePartIndex<SmallSlots>(4), // (0x0 0) SlotDebugData { name: "", ty: UInt<0> },
|
||||||
|
src: StatePartIndex<BigSlots>(0), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.addr", ty: UInt<0> },
|
||||||
|
},
|
||||||
|
8: IsNonZeroDestIsSmall {
|
||||||
|
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.en", ty: Bool },
|
||||||
|
},
|
||||||
|
9: BranchIfSmallZero {
|
||||||
|
target: 11,
|
||||||
|
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
10: Branch {
|
||||||
|
target: 11,
|
||||||
|
},
|
||||||
|
11: IsNonZeroDestIsSmall {
|
||||||
|
dest: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
src: StatePartIndex<BigSlots>(2), // (0x0) SlotDebugData { name: "InstantiatedModule(phantom_const: phantom_const).phantom_const::mem::r0.clk", ty: Clock },
|
||||||
|
},
|
||||||
|
12: AndSmall {
|
||||||
|
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
lhs: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
rhs: StatePartIndex<SmallSlots>(0), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
13: BranchIfSmallZero {
|
||||||
|
target: 14,
|
||||||
|
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
14: XorSmallImmediate {
|
||||||
|
dest: StatePartIndex<SmallSlots>(0), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||||
|
lhs: StatePartIndex<SmallSlots>(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<PhantomConst("mem_element"), 1>,
|
||||||
|
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: <simulator>::phantom_const,
|
||||||
|
instantiated: Module {
|
||||||
|
name: phantom_const,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
},
|
||||||
|
main_module: SimulationModuleState {
|
||||||
|
base_targets: [
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::phantom_const,
|
||||||
|
instantiated: Module {
|
||||||
|
name: phantom_const,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.out,
|
||||||
|
],
|
||||||
|
uninitialized_ios: {},
|
||||||
|
io_targets: {
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::phantom_const,
|
||||||
|
instantiated: Module {
|
||||||
|
name: phantom_const,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.out,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::phantom_const,
|
||||||
|
instantiated: Module {
|
||||||
|
name: phantom_const,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.out[0],
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::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<PhantomConst(["a","b"]), 2>,
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
ty: Array<PhantomConst(["a","b"]), 2>,
|
||||||
|
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<PhantomConst("mem_element"), 1>,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
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<BigSlots>(0),
|
||||||
|
ty: UInt<0>,
|
||||||
|
},
|
||||||
|
state: 0x0,
|
||||||
|
last_state: 0x0,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(3),
|
||||||
|
kind: BigBool {
|
||||||
|
index: StatePartIndex<BigSlots>(1),
|
||||||
|
},
|
||||||
|
state: 0x0,
|
||||||
|
last_state: 0x0,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(4),
|
||||||
|
kind: BigClock {
|
||||||
|
index: StatePartIndex<BigSlots>(2),
|
||||||
|
},
|
||||||
|
state: 0x0,
|
||||||
|
last_state: 0x0,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(5),
|
||||||
|
kind: PhantomConst {
|
||||||
|
ty: PhantomConst(
|
||||||
|
"mem_element",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
state: PhantomConst,
|
||||||
|
last_state: PhantomConst,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
trace_memories: {
|
||||||
|
StatePartIndex<Memories>(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<PhantomConst("mem_element"), 1>,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
trace_writers: [
|
||||||
|
Running(
|
||||||
|
VcdWriter {
|
||||||
|
finished_init: true,
|
||||||
|
timescale: 1 ps,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
clocks_triggered: [
|
||||||
|
StatePartIndex<SmallSlots>(1),
|
||||||
|
],
|
||||||
|
event_queue: EventQueue(EventQueueData {
|
||||||
|
instant: 1 μs,
|
||||||
|
events: {},
|
||||||
|
}),
|
||||||
|
waiting_sensitivity_sets_by_address: {},
|
||||||
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
..
|
||||||
|
}
|
||||||
31
crates/fayalite/tests/sim/expected/phantom_const.vcd
Normal file
31
crates/fayalite/tests/sim/expected/phantom_const.vcd
Normal file
|
|
@ -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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue