diff --git a/crates/fayalite/src/expr.rs b/crates/fayalite/src/expr.rs index 3309fb1..dcc7128 100644 --- a/crates/fayalite/src/expr.rs +++ b/crates/fayalite/src/expr.rs @@ -1723,3 +1723,188 @@ impl<'a, T: Type> ToSimValueInner<'a> for &'a SimValue { Cow::Borrowed(&**this) } } + +pub trait ToTraceAsString: ValueType { + type Output: ValueType, ValueCategory = Self::ValueCategory>; + fn to_trace_as_string_with_ty(&self, ty: TraceAsString) -> Self::Output; + fn into_trace_as_string_with_ty(self, ty: TraceAsString) -> Self::Output + where + Self: Sized; + fn to_trace_as_string(&self) -> Self::Output; + fn into_trace_as_string(self) -> Self::Output + where + Self: Sized; +} + +impl< + T: ?Sized + + ValueType + + ToTraceAsStringImpl<::Type, ::ValueCategory>, +> ToTraceAsString for T +{ + type Output = T::ImplOutput; + fn to_trace_as_string_with_ty(&self, ty: TraceAsString) -> Self::Output { + Self::to_trace_as_string_with_ty_impl(self, ty) + } + fn into_trace_as_string_with_ty(self, ty: TraceAsString) -> Self::Output + where + Self: Sized, + { + Self::into_trace_as_string_with_ty_impl(self, ty) + } + fn to_trace_as_string(&self) -> Self::Output { + Self::to_trace_as_string_impl(self) + } + fn into_trace_as_string(self) -> Self::Output + where + Self: Sized, + { + Self::into_trace_as_string_impl(self) + } +} + +pub trait ToTraceAsStringImpl { + type ImplOutput: ValueType, ValueCategory = C>; + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput; + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized; + fn to_trace_as_string_with_ty_impl(this: &Self, ty: TraceAsString) -> Self::ImplOutput; + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized; +} + +impl + ToTraceAsStringImpl for T +{ + type ImplOutput = crate::ty::TraceAsStringSimValue; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new(this) + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new(this) + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty) + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty) + } +} + +impl + ToTraceAsStringImpl for T +{ + type ImplOutput = SimValue>; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new(this).into_sim_value() + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new(this).into_sim_value() + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty).into_sim_value() + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + crate::ty::TraceAsStringSimValue::new_with_ty(this, ty).into_sim_value() + } +} + +impl ToTraceAsStringImpl for T { + type ImplOutput = Expr>; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + let this = this.to_expr(); + ops::AsTraceAsString::new(Expr::canonical(this), TraceAsString::new(this.ty())).to_expr() + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + let this = this.to_expr(); + ops::AsTraceAsString::new(Expr::canonical(this), TraceAsString::new(this.ty())).to_expr() + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + let this = this.to_expr(); + ops::AsTraceAsString::new( + Expr::canonical(this), + ty.with_new_inner_ty(this.ty().intern_sized()), + ) + .to_expr() + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + let this = this.to_expr(); + ops::AsTraceAsString::new( + Expr::canonical(this), + ty.with_new_inner_ty(this.ty().intern_sized()), + ) + .to_expr() + } +} + +impl ToTraceAsStringImpl + for T +{ + type ImplOutput = Valueless>; + + fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput { + Valueless::new(TraceAsString::new(this.ty())) + } + + fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput + where + Self: Sized, + { + Valueless::new(TraceAsString::new(this.ty())) + } + + fn to_trace_as_string_with_ty_impl( + this: &Self, + ty: TraceAsString, + ) -> Self::ImplOutput { + Valueless::new(ty.with_new_inner_ty(this.ty().intern_sized())) + } + + fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString) -> Self::ImplOutput + where + Self: Sized, + { + Valueless::new(ty.with_new_inner_ty(this.ty().intern_sized())) + } +} diff --git a/crates/fayalite/src/expr/ops.rs b/crates/fayalite/src/expr/ops.rs index 22a0d99..24acee2 100644 --- a/crates/fayalite/src/expr/ops.rs +++ b/crates/fayalite/src/expr/ops.rs @@ -45,6 +45,9 @@ use std::{ }, }; +#[cfg(test)] +mod test_ops_impls; + macro_rules! make_impls { ( $([$($args:tt)*])? @@ -584,9 +587,6 @@ macro_rules! make_impls { #[cfg(test)] pub(crate) use make_impls; -#[cfg(test)] -mod test_ops_impls; - macro_rules! impl_simple_binary_op_trait { ( [$($LLifetimes:tt)*][$($LBounds:tt)*] ($($L:tt)*), diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index f39f800..830c2ac 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -1454,6 +1454,9 @@ enum TargetStateInner { Decomposed { subtargets: HashMap, TargetState>, }, + Transparent { + subtarget: Box, + }, } #[derive(Debug)] @@ -1496,6 +1499,7 @@ impl TargetState { subtarget.assert_written(); } } + TargetStateInner::Transparent { subtarget } => subtarget.assert_written(), } } fn merge_conditional_sub_blocks_into_block( @@ -1535,6 +1539,9 @@ impl TargetState { i.merge_conditional_sub_blocks_into_block(target_block, sub_blocks.clone()); } } + TargetStateInner::Transparent { subtarget } => { + subtarget.merge_conditional_sub_blocks_into_block(target_block, sub_blocks) + } } } fn new(target: Interned, declared_in_block: usize) -> Self { @@ -1589,14 +1596,15 @@ impl TargetState { declared_in_block, written_in_blocks: RefCell::default(), }, - CanonicalType::TraceAsString(_) => { - return Self::new( - target - .join(Intern::intern_sized(TargetPathTraceAsStringInner {}.into())) - .intern_sized(), + CanonicalType::TraceAsString(_) => TargetStateInner::Transparent { + subtarget: Box::new(Self::new( + Target::intern_sized( + target + .join(Intern::intern_sized(TargetPathTraceAsStringInner {}.into())), + ), declared_in_block, - ); - } + )), + }, }, } } @@ -1746,6 +1754,9 @@ impl AssertValidityState { } } } + TargetStateInner::Transparent { subtarget } => { + Self::set_connect_target_written(subtarget, is_lhs, block, exact_target_unknown); + } } } #[track_caller] diff --git a/crates/fayalite/src/prelude.rs b/crates/fayalite/src/prelude.rs index 4c5bfdf..42038ca 100644 --- a/crates/fayalite/src/prelude.rs +++ b/crates/fayalite/src/prelude.rs @@ -13,7 +13,7 @@ pub use crate::{ enum_::{Enum, HdlNone, HdlOption, HdlSome}, expr::{ CastBitsTo, CastTo, CastToBits, Expr, HdlPartialEq, HdlPartialOrd, MakeUninitExpr, - ReduceBits, ToExpr, ValueType, repeat, + ReduceBits, ToExpr, ToTraceAsString, ValueType, repeat, }, formal::{ MakeFormalExpr, all_const, all_seq, any_const, any_seq, formal_global_clock, formal_reset, @@ -38,7 +38,7 @@ pub use crate::{ }, source_location::SourceLocation, testing::{FormalMode, assert_formal}, - ty::{AsMask, CanonicalType, Type}, + ty::{AsMask, CanonicalType, TraceAsString, Type}, util::{ConstUsize, GenericConstUsize}, wire::Wire, }; diff --git a/crates/fayalite/src/sim/value.rs b/crates/fayalite/src/sim/value.rs index 79515ac..24bc1ef 100644 --- a/crates/fayalite/src/sim/value.rs +++ b/crates/fayalite/src/sim/value.rs @@ -19,20 +19,19 @@ use crate::{ impl_match_variant_as_self, }, util::{ - ConstUsize, HashMap, + ConstUsize, alternating_cell::{AlternatingCell, AlternatingCellMethods}, + serde_by_id::{SerdeById, SerdeByIdProperties, SerdeByIdTable, SerdeByIdTrait}, }, }; use bitvec::{slice::BitSlice, vec::BitVec}; -use hashbrown::hash_map::Entry; use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _, ser::Error as _}; use std::{ borrow::{Borrow, BorrowMut, Cow}, - fmt::{self, Write}, - hash::{BuildHasher, Hash, Hasher, RandomState}, + fmt, num::NonZero, ops::{Deref, DerefMut, Index, IndexMut}, - sync::{Arc, Mutex}, + sync::Arc, }; pub(crate) mod sim_only_value_unsafe; @@ -1228,80 +1227,17 @@ macro_rules! impl_to_sim_value_for_int_value { impl_to_sim_value_for_int_value!(UIntValue, UInt, UIntType); impl_to_sim_value_for_int_value!(SIntValue, SInt, SIntType); -#[derive(Default)] -struct DynSimOnlySerdeTableRest { - from_serde: HashMap, - serde_id_random_state: RandomState, - buffer: String, -} - -impl DynSimOnlySerdeTableRest { - #[cold] - fn add_new(&mut self, ty: DynSimOnly) -> DynSimOnlySerdeId { - let mut try_number = 0u64; - let mut hasher = self.serde_id_random_state.build_hasher(); - // extract more bits of randomness from TypeId -- its Hash impl only hashes 64-bits - write!(self.buffer, "{:?}", ty.type_id()).expect("shouldn't ever fail"); - self.buffer.hash(&mut hasher); - loop { - let mut hasher = hasher.clone(); - try_number.hash(&mut hasher); - try_number += 1; - let retval = DynSimOnlySerdeId(std::array::from_fn(|i| { - let mut hasher = hasher.clone(); - i.hash(&mut hasher); - hasher.finish() as u32 - })); - match self.from_serde.entry(retval) { - Entry::Occupied(_) => continue, - Entry::Vacant(e) => { - e.insert(ty); - return retval; - } - } - } +impl SerdeByIdTrait for DynSimOnly { + fn serde_by_id_properties(&self) -> SerdeByIdProperties { + self.serde_by_id_properties_inner() } -} -#[derive(Default)] -struct DynSimOnlySerdeTable { - to_serde: HashMap, - rest: DynSimOnlySerdeTableRest, -} - -static DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE: Mutex> = Mutex::new(None); - -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] -#[serde(transparent)] -struct DynSimOnlySerdeId([u32; 4]); - -impl From for DynSimOnlySerdeId { - fn from(ty: DynSimOnly) -> Self { - let mut locked = DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE - .lock() - .expect("shouldn't be poison"); - let DynSimOnlySerdeTable { to_serde, rest } = locked.get_or_insert_default(); - match to_serde.entry(ty) { - Entry::Occupied(occupied_entry) => *occupied_entry.get(), - Entry::Vacant(vacant_entry) => *vacant_entry.insert(rest.add_new(ty)), - } + fn static_table() -> &'static SerdeByIdTable { + static TABLE: SerdeByIdTable = SerdeByIdTable::new(); + &TABLE } -} -impl DynSimOnlySerdeId { - fn ty(self) -> Option { - let locked = DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE - .lock() - .expect("shouldn't be poison"); - Some(*locked.as_ref()?.rest.from_serde.get(&self)?) - } -} - -#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] -struct DynSimOnlySerde<'a> { - random_id: DynSimOnlySerdeId, - #[serde(borrow)] - type_name: Cow<'a, str>, + const NAME: &'static str = "DynSimOnly"; } impl Serialize for DynSimOnly { @@ -1309,11 +1245,7 @@ impl Serialize for DynSimOnly { where S: Serializer, { - DynSimOnlySerde { - random_id: (*self).into(), - type_name: Cow::Borrowed(self.type_name()), - } - .serialize(serializer) + SerdeById { inner: *self }.serialize(serializer) } } @@ -1322,16 +1254,7 @@ impl<'de> Deserialize<'de> for DynSimOnly { where D: Deserializer<'de>, { - let deserialized = DynSimOnlySerde::deserialize(deserializer)?; - let retval = deserialized - .random_id - .ty() - .filter(|ty| ty.type_name() == deserialized.type_name); - retval.ok_or_else(|| { - D::Error::custom( - "doesn't match any DynSimOnly that was serialized this time this program was run", - ) - }) + Ok(SerdeById::deserialize(deserializer)?.inner) } } diff --git a/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs b/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs index 2424c03..bcbcdc6 100644 --- a/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs +++ b/crates/fayalite/src/sim/value/sim_only_value_unsafe.rs @@ -3,7 +3,10 @@ //! `unsafe` parts of [`DynSimOnlyValue`] -use crate::expr::{ValueType, value_category::ValueCategoryValue}; +use crate::{ + expr::{ValueType, value_category::ValueCategoryValue}, + util::serde_by_id::SerdeByIdProperties, +}; use serde::{Serialize, de::DeserializeOwned}; use std::{ any::{self, TypeId}, @@ -33,6 +36,7 @@ unsafe trait DynSimOnlyTrait: 'static + Send + Sync { &self, json_str: &str, ) -> serde_json::Result>; + fn serde_by_id_properties_inner(&self) -> SerdeByIdProperties; } /// Safety: `type_id_dyn` is implemented correctly @@ -55,6 +59,9 @@ unsafe impl DynSimOnlyTrait for SimOnly { ) -> serde_json::Result> { Ok(Rc::::new(serde_json::from_str(json_str)?)) } + fn serde_by_id_properties_inner(&self) -> SerdeByIdProperties { + SerdeByIdProperties::of::() + } } /// Safety: @@ -151,6 +158,9 @@ impl DynSimOnly { pub fn default_value(self) -> DynSimOnlyValue { DynSimOnlyValue(self.ty.default_value()) } + pub(super) fn serde_by_id_properties_inner(self) -> SerdeByIdProperties { + self.ty.serde_by_id_properties_inner() + } } impl PartialEq for DynSimOnly { diff --git a/crates/fayalite/src/ty.rs b/crates/fayalite/src/ty.rs index 2988a7d..5599ad4 100644 --- a/crates/fayalite/src/ty.rs +++ b/crates/fayalite/src/ty.rs @@ -6,7 +6,7 @@ use crate::{ bundle::{Bundle, BundleField, BundleType}, clock::Clock, enum_::{Enum, EnumType, EnumVariant}, - expr::{Expr, ToExpr, ValueType, ops}, + expr::{Expr, HdlPartialEqImpl, HdlPartialOrdImpl, ToExpr, ValueType, Valueless, ops}, int::{Bool, SInt, UInt, UIntValue}, intern::{Intern, Interned, LazyInterned, Memoize, SupportsPtrEqWithTypeId}, module::transform::visit::{Fold, Folder, Visit, Visitor}, @@ -23,6 +23,7 @@ use crate::{ use bitvec::{slice::BitSlice, vec::BitVec}; use serde::{Deserialize, Deserializer, Serialize, Serializer, de::DeserializeOwned}; use std::{ + borrow::Cow, fmt::{self, Write}, hash::Hash, iter::{FusedIterator, Sum}, @@ -997,9 +998,6 @@ impl OpaqueSimValue { pub fn sim_only_values(&self) -> &[DynSimOnlyValue] { &self.sim_only_values } - pub(crate) fn sim_only_values_vec(&self) -> &Vec { - &self.sim_only_values - } pub fn sim_only_values_mut(&mut self) -> &mut Vec { &mut self.sim_only_values } @@ -1463,14 +1461,14 @@ impl SimValueDebug for TraceAsString { value: &::SimValue, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { - T::sim_value_debug(value, f) + T::sim_value_debug(value.inner(), f) } } impl Type for TraceAsString { type BaseType = TraceAsString; type MaskType = T::MaskType; - type SimValue = TraceAsStringSimValue; + type SimValue = TraceAsStringSimValue; type MatchVariant = Expr; type MatchActiveScope = (); type MatchVariantAndInactiveScope = MatchVariantWithoutScope; @@ -1507,7 +1505,8 @@ impl Type for TraceAsString { fn sim_value_from_opaque(&self, opaque: OpaqueSimValueSlice<'_>) -> Self::SimValue { TraceAsStringSimValue { - inner: self.inner_ty.sim_value_from_opaque(opaque), + inner: SimValue::from_opaque(self.inner_ty(), opaque.to_owned()), + trace_as_string: self.trace_as_string.interned(), } } @@ -1594,101 +1593,217 @@ impl Index for TraceAsStringWithoutGenerics { } } -#[derive(Copy, Clone, Eq, Ord, Hash, Default, Serialize, Deserialize)] -pub struct TraceAsStringSimValue { +#[derive(Clone)] +pub struct TraceAsStringSimValue { + inner: SimValue, + trace_as_string: Interned, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename = "TraceAsStringSimValue")] +struct TraceAsStringSimValueSerde { inner: T, + trace_as_string: crate::util::serde_by_id::SerdeById>, } -impl TraceAsStringSimValue { - pub const fn new(inner: T) -> Self { - Self { inner } - } - pub fn into_inner(this: Self) -> T { - let Self { inner } = this; - inner +impl + Serialize> Serialize for TraceAsStringSimValue { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let Self { + inner, + trace_as_string, + } = self; + TraceAsStringSimValueSerde { + inner, + trace_as_string: crate::util::serde_by_id::SerdeById { + inner: *trace_as_string, + }, + } + .serialize(serializer) } } -impl ValueType for TraceAsStringSimValue { - type Type = TraceAsString; - type ValueCategory = T::ValueCategory; - - fn ty(&self) -> Self::Type { - TraceAsString::new(self.inner.ty()) - } -} - -impl ToExpr for TraceAsStringSimValue { - fn to_expr(&self) -> Expr { - let inner = self.inner.to_expr(); - ops::AsTraceAsString::new(Expr::canonical(inner), TraceAsString::new(inner.ty())).to_expr() - } -} - -impl, Ty: Type> ToSimValueWithType> +impl<'de, T: Type> + Deserialize<'de>> Deserialize<'de> for TraceAsStringSimValue { - fn to_sim_value_with_type(&self, ty: TraceAsString) -> SimValue> { - let inner = self.inner.to_sim_value_with_type(ty.inner_ty()); - let inner = SimValue::into_value(inner); - SimValue::from_value(ty, TraceAsStringSimValue { inner }) - } - fn into_sim_value_with_type(self, ty: TraceAsString) -> SimValue> { - let inner = self.inner.into_sim_value_with_type(ty.inner_ty()); - let inner = SimValue::into_value(inner); - SimValue::from_value(ty, TraceAsStringSimValue { inner }) + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let TraceAsStringSimValueSerde { + inner, + trace_as_string: + crate::util::serde_by_id::SerdeById { + inner: trace_as_string, + }, + } = Deserialize::deserialize(deserializer)?; + Ok(Self { + inner, + trace_as_string, + }) } } -impl ToSimValue for TraceAsStringSimValue { - fn to_sim_value(&self) -> SimValue { - self.to_sim_value_with_type(self.ty()) +impl TraceAsStringSimValue { + pub fn new_with_ty(inner: impl ToSimValueWithType, ty: TraceAsString) -> Self { + Self { + inner: inner.into_sim_value_with_type(ty.inner_ty()), + trace_as_string: ty.trace_as_string.interned(), + } } - fn into_sim_value(self) -> SimValue { - let ty = self.ty(); - self.into_sim_value_with_type(ty) + pub fn new(inner: impl ToSimValue) -> Self { + let inner = inner.into_sim_value(); + Self { + trace_as_string: TraceAsString::new(inner.ty()).trace_as_string.interned(), + inner, + } } -} - -impl std::ops::Deref for TraceAsStringSimValue { - type Target = T; - - fn deref(&self) -> &Self::Target { + pub fn into_inner(self) -> SimValue { + self.inner + } + pub fn inner(&self) -> &SimValue { &self.inner } -} - -impl std::ops::DerefMut for TraceAsStringSimValue { - fn deref_mut(&mut self) -> &mut Self::Target { + pub fn inner_mut(&mut self) -> &mut SimValue { &mut self.inner } } -impl fmt::Debug for TraceAsStringSimValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { inner } = self; - fmt::Debug::fmt(inner, f) +impl ValueType for TraceAsStringSimValue { + type Type = TraceAsString; + type ValueCategory = crate::expr::value_category::ValueCategoryValue; + + fn ty(&self) -> Self::Type { + let inner_ty = self.inner.ty().intern_sized(); + if self + .trace_as_string + .can_substitute_type(inner_ty.canonical()) + { + TraceAsString { + inner_ty: LazyInterned::Interned(inner_ty), + trace_as_string: LazyInterned::Interned(self.trace_as_string), + } + } else { + TraceAsString::new_interned(inner_ty) + } } } -impl fmt::Display for TraceAsStringSimValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { inner } = self; - fmt::Display::fmt(inner, f) +impl ToExpr for TraceAsStringSimValue { + #[track_caller] + fn to_expr(&self) -> Expr { + let inner = self.inner.to_expr(); + let inner_canonical = Expr::canonical(inner); + let inner_ty = inner.ty().intern_sized(); + let ty = if self + .trace_as_string + .can_substitute_type(inner_canonical.ty()) + { + TraceAsString { + inner_ty: LazyInterned::Interned(inner_ty), + trace_as_string: LazyInterned::Interned(self.trace_as_string), + } + } else { + TraceAsString::new_interned(inner_ty) + }; + ops::AsTraceAsString::new(inner_canonical, ty).to_expr() } } -impl, U> PartialOrd> for TraceAsStringSimValue { +impl ToSimValueWithType> for TraceAsStringSimValue { + fn to_sim_value_with_type(&self, ty: TraceAsString) -> SimValue> { + let inner = self.inner.to_sim_value_with_type(ty.inner_ty()); + SimValue::from_value( + ty, + TraceAsStringSimValue { + inner, + trace_as_string: ty.trace_as_string.interned(), + }, + ) + } + fn into_sim_value_with_type(self, ty: TraceAsString) -> SimValue> { + let inner = self.inner.into_sim_value_with_type(ty.inner_ty()); + SimValue::from_value( + ty, + TraceAsStringSimValue { + inner, + trace_as_string: ty.trace_as_string.interned(), + }, + ) + } +} + +impl ToSimValue for TraceAsStringSimValue { + fn to_sim_value(&self) -> SimValue { + SimValue::from_value(self.ty(), self.clone()) + } + fn into_sim_value(self) -> SimValue { + SimValue::from_value(self.ty(), self) + } +} + +impl fmt::Debug for TraceAsStringSimValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.inner, f) + } +} + +impl> fmt::Display for TraceAsStringSimValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.inner, f) + } +} + +impl Ord for TraceAsStringSimValue +where + SimValue: Ord, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.inner.cmp(&other.inner) + } +} + +impl PartialOrd> for TraceAsStringSimValue +where + SimValue: PartialOrd>, +{ fn partial_cmp(&self, other: &TraceAsStringSimValue) -> Option { - let Self { inner } = self; - inner.partial_cmp(&other.inner) + self.inner.partial_cmp(&other.inner) } } -impl, U> PartialEq> for TraceAsStringSimValue { +impl Eq for TraceAsStringSimValue where SimValue: Eq {} + +impl Hash for TraceAsStringSimValue +where + SimValue: Hash, +{ + fn hash(&self, state: &mut H) { + self.inner.hash(state); + } +} + +impl Default for TraceAsStringSimValue +where + SimValue: Default, +{ + fn default() -> Self { + let inner = SimValue::default(); + Self { + trace_as_string: TraceAsString::new(inner.ty()).trace_as_string.interned(), + inner, + } + } +} + +impl PartialEq> for TraceAsStringSimValue +where + SimValue: PartialEq>, +{ fn eq(&self, other: &TraceAsStringSimValue) -> bool { - let Self { inner } = self; - *inner == other.inner + self.inner == other.inner } } @@ -1711,3 +1826,259 @@ impl, State: ?Sized + Visitor> Visit for TraceAsSt self.interned_inner_ty().visit(state) } } + +fn trace_as_string_cow_into_inner( + this: Cow<'_, SimValue>>, +) -> Cow<'_, SimValue> { + match this { + Cow::Borrowed(v) => Cow::Borrowed(&v.inner), + Cow::Owned(v) => Cow::Owned(SimValue::into_value(v).inner), + } +} + +fn trace_as_string_cow_into_inner_value( + this: Cow<'_, TraceAsStringSimValue>, +) -> Cow<'_, T::SimValue> { + match this { + Cow::Borrowed(v) => Cow::Borrowed(&v.inner), + Cow::Owned(v) => Cow::Owned(SimValue::into_value(v.inner)), + } +} + +impl, U: Type> HdlPartialEqImpl> for TraceAsString { + #[track_caller] + fn cmp_value_eq( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialEqImpl::cmp_value_eq( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_ne( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialEqImpl::cmp_value_ne( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_sim_value_eq( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialEqImpl::cmp_sim_value_eq( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_ne( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialEqImpl::cmp_sim_value_ne( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_expr_eq(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialEqImpl::cmp_expr_eq(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_ne(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialEqImpl::cmp_expr_ne(*lhs, *rhs) + } + + #[track_caller] + fn cmp_valueless_eq(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialEqImpl::cmp_valueless_eq( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_ne(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialEqImpl::cmp_valueless_ne( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } +} + +impl, U: Type> HdlPartialOrdImpl> for TraceAsString { + #[track_caller] + fn cmp_value_lt( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_lt( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_le( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_le( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_gt( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_gt( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_value_ge( + lhs: Self, + lhs_value: Cow<'_, Self::SimValue>, + rhs: TraceAsString, + rhs_value: Cow<'_, as Type>::SimValue>, + ) -> bool { + HdlPartialOrdImpl::cmp_value_ge( + lhs.inner_ty(), + trace_as_string_cow_into_inner_value(lhs_value), + rhs.inner_ty(), + trace_as_string_cow_into_inner_value(rhs_value), + ) + } + + #[track_caller] + fn cmp_sim_value_lt( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_lt( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_le( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_le( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_gt( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_gt( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_sim_value_ge( + lhs: Cow<'_, SimValue>, + rhs: Cow<'_, SimValue>>, + ) -> SimValue { + HdlPartialOrdImpl::cmp_sim_value_ge( + trace_as_string_cow_into_inner(lhs), + trace_as_string_cow_into_inner(rhs), + ) + } + + #[track_caller] + fn cmp_expr_lt(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_lt(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_le(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_le(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_gt(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_gt(*lhs, *rhs) + } + + #[track_caller] + fn cmp_expr_ge(lhs: Expr, rhs: Expr>) -> Expr { + HdlPartialOrdImpl::cmp_expr_ge(*lhs, *rhs) + } + + #[track_caller] + fn cmp_valueless_lt(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_lt( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_le(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_le( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_gt(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_gt( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } + + #[track_caller] + fn cmp_valueless_ge(lhs: Valueless, rhs: Valueless>) -> Valueless { + HdlPartialOrdImpl::cmp_valueless_ge( + Valueless::new(lhs.ty().inner_ty()), + Valueless::new(rhs.ty().inner_ty()), + ) + } +} diff --git a/crates/fayalite/src/ty/serde_impls.rs b/crates/fayalite/src/ty/serde_impls.rs index 126c4b0..d5b5551 100644 --- a/crates/fayalite/src/ty/serde_impls.rs +++ b/crates/fayalite/src/ty/serde_impls.rs @@ -39,6 +39,7 @@ impl<'de, T: ?Sized + PhantomConstValue> Deserialize<'de> for SerdePhantomConst< #[derive(Serialize, Deserialize)] #[serde(rename = "CanonicalType")] +#[expect(private_interfaces)] pub(crate) enum SerdeCanonicalType< ArrayElement = CanonicalType, ThePhantomConst = SerdePhantomConst>, diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index 238259c..176c3fe 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -13,7 +13,7 @@ use fayalite::{ prelude::*, reset::ResetType, sim::vcd::VcdWriterDecls, - ty::{SimValueDebug, StaticType, TraceAsString, TraceAsStringSimValue}, + ty::SimValueDebug, util::{RcWriter, ready_valid::queue}, }; use std::{collections::BTreeMap, num::NonZeroUsize, rc::Rc}; @@ -3061,10 +3061,7 @@ pub fn sim_trace_as_string() { #[hdl] let write: WriteStruct, 2>, ConstUsize<8>> = m.input(); #[hdl] - let mut mem = memory_with_init( - [[Expr::as_trace_as_string(HasCustomDebug::new_sim(Ok("")).to_expr(), StaticType::TYPE); 2]; - 4], - ); + let mut mem = memory_with_init([[HasCustomDebug::new_sim(Ok("")).to_trace_as_string(); 2]; 4]); let read_port = mem.new_read_port(); connect(read_port.clk, clk); connect_any(read_port.addr, read.addr); @@ -3156,7 +3153,7 @@ fn test_sim_trace_as_string() { sim.write(sim.io().write.en, write_addr.is_some()); sim.write( sim.io().write.data, - write_data.map(|v| TraceAsStringSimValue::new(HasCustomDebug::new_sim(v))), + write_data.map(|v| HasCustomDebug::new_sim(v).to_trace_as_string()), ); sim.write( sim.io().write.mask, @@ -3172,7 +3169,7 @@ fn test_sim_trace_as_string() { .map(HasCustomDebug::new_sim) .into_sim_value(); assert!( - **read_data == *expected_read_data, + *read_data.inner() == expected_read_data, "{read_data:#?}\n!= {expected_read_data:#?}", ); } diff --git a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr index dbdf937..8eff725 100644 --- a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr +++ b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr @@ -55,7 +55,7 @@ error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'sta note: required because it appears within the type `DynSimOnlyValue` --> src/sim/value/sim_only_value_unsafe.rs | - 271 | pub struct DynSimOnlyValue(Rc); + 281 | pub struct DynSimOnlyValue(Rc); | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` --> $RUST/core/src/marker.rs @@ -75,12 +75,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 895 | pub struct OpaqueSimValue { + 896 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 52 | struct SimValueInner { + 51 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -95,7 +95,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 161 | pub struct SimValue { + 160 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` --> src/intern.rs @@ -194,7 +194,7 @@ error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'sta note: required because it appears within the type `DynSimOnlyValue` --> src/sim/value/sim_only_value_unsafe.rs | - 271 | pub struct DynSimOnlyValue(Rc); + 281 | pub struct DynSimOnlyValue(Rc); | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` --> $RUST/core/src/marker.rs @@ -214,12 +214,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 895 | pub struct OpaqueSimValue { + 896 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 52 | struct SimValueInner { + 51 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -234,7 +234,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 161 | pub struct SimValue { + 160 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `intern_sized` --> src/intern.rs @@ -306,7 +306,7 @@ error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'sta note: required because it appears within the type `DynSimOnlyValue` --> src/sim/value/sim_only_value_unsafe.rs | - 271 | pub struct DynSimOnlyValue(Rc); + 281 | pub struct DynSimOnlyValue(Rc); | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` --> $RUST/core/src/marker.rs @@ -326,12 +326,12 @@ note: required because it appears within the type `Vec` note: required because it appears within the type `OpaqueSimValue` --> src/ty.rs | - 895 | pub struct OpaqueSimValue { + 896 | pub struct OpaqueSimValue { | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` --> src/sim/value.rs | - 52 | struct SimValueInner { + 51 | struct SimValueInner { | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` --> $RUST/core/src/cell.rs @@ -346,7 +346,7 @@ note: required because it appears within the type `util::alternating_cell::Alter note: required because it appears within the type `fayalite::prelude::SimValue<()>` --> src/sim/value.rs | - 161 | pub struct SimValue { + 160 | pub struct SimValue { | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` --> src/intern.rs