expand SimValue support

This commit is contained in:
Jacob Lifshay 2025-03-30 00:55:38 -07:00
parent 5028401a5a
commit a40eaaa2da
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
13 changed files with 864 additions and 342 deletions

View file

@ -8,7 +8,7 @@ use crate::{
},
int::{Bool, DynSize},
intern::{Intern, Interned},
sim::value::{SimValue, SimValuePartialEq, ToSimValue},
sim::value::{SimValue, SimValuePartialEq, ToSimValue, ToSimValueWithType},
source_location::SourceLocation,
ty::{
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, OpaqueSimValue,
@ -562,29 +562,29 @@ macro_rules! impl_tuples {
BundleLiteral::new(ty, field_values[..].intern()).to_expr()
}
}
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<CanonicalType> for ($($T,)*) {
impl<$($T: ToSimValueWithType<CanonicalType>,)*> ToSimValueWithType<CanonicalType> for ($($T,)*) {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(ToSimValue::<Bundle>::to_sim_value(self, Bundle::from_canonical(ty)))
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(ToSimValueWithType::<Bundle>::to_sim_value_with_type(self, Bundle::from_canonical(ty)))
}
#[track_caller]
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType>
fn into_sim_value_with_type(self, ty: CanonicalType) -> SimValue<CanonicalType>
{
SimValue::into_canonical(ToSimValue::<Bundle>::into_sim_value(self, Bundle::from_canonical(ty)))
SimValue::into_canonical(ToSimValueWithType::<Bundle>::into_sim_value_with_type(self, Bundle::from_canonical(ty)))
}
}
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<Bundle> for ($($T,)*) {
impl<$($T: ToSimValueWithType<CanonicalType>,)*> ToSimValueWithType<Bundle> for ($($T,)*) {
#[track_caller]
fn to_sim_value(&self, ty: Bundle) -> SimValue<Bundle> {
fn to_sim_value_with_type(&self, ty: Bundle) -> SimValue<Bundle> {
let ($($var,)*) = self;
let [$($ty_var,)*] = *ty.fields() else {
panic!("bundle has wrong number of fields");
};
$(let $var = $var.to_sim_value($ty_var.ty);)*
ToSimValue::into_sim_value(($($var,)*), ty)
$(let $var = $var.to_sim_value_with_type($ty_var.ty);)*
ToSimValueWithType::into_sim_value_with_type(($($var,)*), ty)
}
#[track_caller]
fn into_sim_value(self, ty: Bundle) -> SimValue<Bundle> {
fn into_sim_value_with_type(self, ty: Bundle) -> SimValue<Bundle> {
#![allow(unused_mut)]
#![allow(clippy::unused_unit)]
let ($($var,)*) = self;
@ -592,29 +592,44 @@ macro_rules! impl_tuples {
panic!("bundle has wrong number of fields");
};
let mut bits = BitVec::new();
$(let $var = $var.into_sim_value($ty_var.ty);
$(let $var = $var.into_sim_value_with_type($ty_var.ty);
assert_eq!(SimValue::ty(&$var), $ty_var.ty);
bits.extend_from_bitslice(SimValue::bits(&$var).bits());
)*
bits.into_sim_value(ty)
bits.into_sim_value_with_type(ty)
}
}
impl<$($T: ToSimValue<$Ty>, $Ty: Type,)*> ToSimValue<($($Ty,)*)> for ($($T,)*) {
impl<$($T: ToSimValueWithType<$Ty>, $Ty: Type,)*> ToSimValueWithType<($($Ty,)*)> for ($($T,)*) {
#[track_caller]
fn to_sim_value(&self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
fn to_sim_value_with_type(&self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
let ($($var,)*) = self;
let ($($ty_var,)*) = ty;
$(let $var = $var.to_sim_value($ty_var);)*
$(let $var = $var.to_sim_value_with_type($ty_var);)*
SimValue::from_value(ty, ($($var,)*))
}
#[track_caller]
fn into_sim_value(self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
fn into_sim_value_with_type(self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
let ($($var,)*) = self;
let ($($ty_var,)*) = ty;
$(let $var = $var.into_sim_value($ty_var);)*
$(let $var = $var.into_sim_value_with_type($ty_var);)*
SimValue::from_value(ty, ($($var,)*))
}
}
impl<$($T: ToSimValue,)*> ToSimValue for ($($T,)*) {
type Type = ($($T::Type,)*);
#[track_caller]
fn to_sim_value(&self) -> SimValue<Self::Type> {
let ($($var,)*) = self;
$(let $var = $var.to_sim_value();)*
SimValue::from_value(($(SimValue::ty(&$var),)*), ($($var,)*))
}
#[track_caller]
fn into_sim_value(self) -> SimValue<Self::Type> {
let ($($var,)*) = self;
$(let $var = $var.to_sim_value();)*
SimValue::from_value(($(SimValue::ty(&$var),)*), ($($var,)*))
}
}
impl<$($Lhs: Type + ExprPartialEq<$Rhs>, $Rhs: Type,)*> ExprPartialEq<($($Rhs,)*)> for ($($Lhs,)*) {
fn cmp_eq(lhs: Expr<Self>, rhs: Expr<($($Rhs,)*)>) -> Expr<Bool> {
let ($($lhs_var,)*) = *lhs;
@ -674,7 +689,7 @@ impl_tuples! {
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
type BaseType = Bundle;
type MaskType = ();
type SimValue = ();
type SimValue = PhantomData<T>;
type MatchVariant = PhantomData<T>;
type MatchActiveScope = ();
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
@ -709,7 +724,7 @@ impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert!(bits.is_empty());
()
*self
}
fn sim_value_clone_from_bits(&self, _value: &mut Self::SimValue, bits: &BitSlice) {
assert!(bits.is_empty());
@ -764,26 +779,38 @@ impl<T: ?Sized + Send + Sync + 'static> ToExpr for PhantomData<T> {
}
}
impl<T: ?Sized + Send + Sync + 'static> ToSimValue<Self> for PhantomData<T> {
impl<T: ?Sized + Send + Sync + 'static> ToSimValue for PhantomData<T> {
type Type = PhantomData<T>;
#[track_caller]
fn to_sim_value(&self, ty: Self) -> SimValue<Self> {
ToSimValue::into_sim_value(BitVec::new(), ty)
fn to_sim_value(&self) -> SimValue<Self> {
SimValue::from_value(*self, *self)
}
}
impl<T: ?Sized> ToSimValue<Bundle> for PhantomData<T> {
impl<T: ?Sized + Send + Sync + 'static> ToSimValueWithType<Self> for PhantomData<T> {
#[track_caller]
fn to_sim_value(&self, ty: Bundle) -> SimValue<Bundle> {
fn to_sim_value_with_type(&self, ty: Self) -> SimValue<Self> {
SimValue::from_value(ty, *self)
}
}
impl<T: ?Sized> ToSimValueWithType<Bundle> for PhantomData<T> {
#[track_caller]
fn to_sim_value_with_type(&self, ty: Bundle) -> SimValue<Bundle> {
assert!(ty.fields().is_empty());
ToSimValue::into_sim_value(BitVec::new(), ty)
ToSimValueWithType::into_sim_value_with_type(BitVec::new(), ty)
}
}
impl<T: ?Sized> ToSimValue<CanonicalType> for PhantomData<T> {
impl<T: ?Sized> ToSimValueWithType<CanonicalType> for PhantomData<T> {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
let ty = Bundle::from_canonical(ty);
assert!(ty.fields().is_empty());
SimValue::into_canonical(ToSimValue::into_sim_value(BitVec::new(), ty))
SimValue::into_canonical(ToSimValueWithType::into_sim_value_with_type(
BitVec::new(),
ty,
))
}
}

View file

@ -2,12 +2,13 @@
// See Notices.txt for copyright information
use crate::{
array::ArrayType,
expr::{
target::{GetTarget, Target},
Expr, NotALiteralExpr, ToExpr, ToLiteralBits,
},
intern::{Intern, Interned, Memoize},
sim::value::SimValue,
sim::value::{SimValue, ToSimValueWithType},
source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
util::{interned_bit, ConstBool, ConstUsize, GenericConstBool, GenericConstUsize},
@ -58,7 +59,8 @@ pub trait KnownSize:
+ std::fmt::Debug
+ IntoIterator<Item = SimValue<Element>>
+ TryFrom<Vec<SimValue<Element>>>
+ Into<Vec<SimValue<Element>>>;
+ Into<Vec<SimValue<Element>>>
+ ToSimValueWithType<ArrayType<Element, Self>>;
}
macro_rules! known_widths {
@ -120,7 +122,8 @@ pub trait Size:
+ std::fmt::Debug
+ IntoIterator<Item = SimValue<Element>>
+ TryFrom<Vec<SimValue<Element>>>
+ Into<Vec<SimValue<Element>>>;
+ Into<Vec<SimValue<Element>>>
+ ToSimValueWithType<ArrayType<Element, Self>>;
const KNOWN_VALUE: Option<usize>;
type SizeType: SizeType<Size = Self>
+ Copy

View file

@ -11,7 +11,7 @@ use crate::{
},
int::Bool,
intern::{Intern, Interned, InternedCompare, LazyInterned, Memoize},
sim::value::{SimValue, SimValuePartialEq},
sim::value::{SimValue, SimValuePartialEq, ToSimValue, ToSimValueWithType},
source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
};
@ -248,7 +248,7 @@ impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
type BaseType = PhantomConst;
type MaskType = ();
type SimValue = ();
type SimValue = PhantomConst<T>;
impl_match_variant_as_self!();
fn mask_type(&self) -> Self::MaskType {
@ -272,15 +272,17 @@ impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert!(bits.is_empty());
()
*self
}
fn sim_value_clone_from_bits(&self, _value: &mut Self::SimValue, bits: &BitSlice) {
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert!(bits.is_empty());
assert_eq!(*value, *self);
}
fn sim_value_to_bits(&self, _value: &Self::SimValue, bits: &mut BitSlice) {
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert!(bits.is_empty());
assert_eq!(*value, *self);
}
}
@ -334,3 +336,23 @@ impl<T: ?Sized + PhantomConstValue> SimValuePartialEq<Self> for PhantomConst<T>
true
}
}
impl<T: ?Sized + PhantomConstValue> ToSimValue for PhantomConst<T> {
type Type = PhantomConst<T>;
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_value(*self, *self)
}
}
impl<T: ?Sized + PhantomConstValue> ToSimValueWithType<PhantomConst<T>> for PhantomConst<T> {
fn to_sim_value_with_type(&self, ty: PhantomConst<T>) -> SimValue<PhantomConst<T>> {
SimValue::from_value(ty, *self)
}
}
impl<T: ?Sized + PhantomConstValue> ToSimValueWithType<CanonicalType> for PhantomConst<T> {
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_value(Self::from_canonical(ty), *self))
}
}

View file

@ -7531,10 +7531,10 @@ macro_rules! impl_simulation_methods {
SimValue::from_canonical($self.settle_if_needed(retval)$(.$await)?)
}
$(#[$track_caller])?
pub $($async)? fn write<IO: Type, V: value::ToSimValue<IO>>(&mut $self, io: Expr<IO>, value: V) {
pub $($async)? fn write<IO: Type, V: value::ToSimValueWithType<IO>>(&mut $self, io: Expr<IO>, value: V) {
$self.sim_impl.borrow_mut().write(
Expr::canonical(io),
&SimValue::into_canonical(value.into_sim_value(Expr::ty(io))),
&SimValue::into_canonical(value.into_sim_value_with_type(Expr::ty(io))),
$which_module,
);
}

View file

@ -9,7 +9,7 @@ use crate::{
expr::{CastBitsTo, Expr, ToExpr},
int::{Bool, IntType, KnownSize, SInt, SIntType, SIntValue, Size, UInt, UIntType, UIntValue},
reset::{AsyncReset, Reset, SyncReset},
ty::{CanonicalType, Type},
ty::{CanonicalType, StaticType, Type},
util::{
alternating_cell::{AlternatingCell, AlternatingCellMethods},
ConstUsize,
@ -307,122 +307,223 @@ impl SimValuePartialEq<Bool> for Bool {
}
}
pub trait ToSimValue<T: Type> {
pub trait ToSimValue: ToSimValueWithType<<Self as ToSimValue>::Type> {
type Type: Type;
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T>;
fn to_sim_value(&self) -> SimValue<Self::Type>;
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T>
fn into_sim_value(self) -> SimValue<Self::Type>
where
Self: Sized,
{
self.to_sim_value(ty)
self.to_sim_value()
}
#[track_caller]
fn arc_into_sim_value(self: Arc<Self>, ty: T) -> SimValue<T> {
self.to_sim_value(ty)
fn arc_into_sim_value(self: Arc<Self>) -> SimValue<Self::Type> {
self.to_sim_value()
}
#[track_caller]
fn arc_to_sim_value(self: &Arc<Self>, ty: T) -> SimValue<T> {
self.to_sim_value(ty)
fn arc_to_sim_value(self: &Arc<Self>) -> SimValue<Self::Type> {
self.to_sim_value()
}
}
impl<T: Type> ToSimValue<T> for SimValue<T> {
pub trait ToSimValueWithType<T: Type> {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
assert_eq!(SimValue::ty(self), ty);
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T>;
#[track_caller]
fn into_sim_value_with_type(self, ty: T) -> SimValue<T>
where
Self: Sized,
{
self.to_sim_value_with_type(ty)
}
#[track_caller]
fn arc_into_sim_value_with_type(self: Arc<Self>, ty: T) -> SimValue<T> {
self.to_sim_value_with_type(ty)
}
#[track_caller]
fn arc_to_sim_value_with_type(self: &Arc<Self>, ty: T) -> SimValue<T> {
self.to_sim_value_with_type(ty)
}
}
macro_rules! forward_to_sim_value_with_type {
([$($generics:tt)*] $ty:ty) => {
impl<$($generics)*> ToSimValueWithType<<Self as ToSimValue>::Type> for $ty {
fn to_sim_value_with_type(&self, ty: <Self as ToSimValue>::Type) -> SimValue<<Self as ToSimValue>::Type> {
let retval = Self::to_sim_value(self);
assert_eq!(SimValue::ty(&retval), ty);
retval
}
#[track_caller]
fn into_sim_value_with_type(self, ty: <Self as ToSimValue>::Type) -> SimValue<<Self as ToSimValue>::Type>
where
Self: Sized,
{
let retval = Self::into_sim_value(self);
assert_eq!(SimValue::ty(&retval), ty);
retval
}
#[track_caller]
fn arc_into_sim_value_with_type(self: Arc<Self>, ty: <Self as ToSimValue>::Type) -> SimValue<<Self as ToSimValue>::Type> {
let retval = Self::arc_into_sim_value(self);
assert_eq!(SimValue::ty(&retval), ty);
retval
}
#[track_caller]
fn arc_to_sim_value_with_type(self: &Arc<Self>, ty: <Self as ToSimValue>::Type) -> SimValue<<Self as ToSimValue>::Type> {
let retval = Self::arc_to_sim_value(self);
assert_eq!(SimValue::ty(&retval), ty);
retval
}
}
};
}
impl<T: Type> ToSimValue for SimValue<T> {
type Type = T;
fn to_sim_value(&self) -> SimValue<Self::Type> {
self.clone()
}
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T> {
assert_eq!(SimValue::ty(&self), ty);
fn into_sim_value(self) -> SimValue<Self::Type> {
self
}
}
impl<T: Type> ToSimValue<T> for BitVec {
forward_to_sim_value_with_type!([T: Type] SimValue<T>);
impl<T: Type> ToSimValueWithType<T> for BitVec {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
self.clone().into_sim_value(ty)
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
self.clone().into_sim_value_with_type(ty)
}
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T> {
Arc::new(self).arc_into_sim_value(ty)
fn into_sim_value_with_type(self, ty: T) -> SimValue<T> {
Arc::new(self).arc_into_sim_value_with_type(ty)
}
#[track_caller]
fn arc_into_sim_value(self: Arc<Self>, ty: T) -> SimValue<T> {
fn arc_into_sim_value_with_type(self: Arc<Self>, ty: T) -> SimValue<T> {
SimValue::from_bits(ty, UIntValue::new_dyn(self))
}
#[track_caller]
fn arc_to_sim_value(self: &Arc<Self>, ty: T) -> SimValue<T> {
fn arc_to_sim_value_with_type(self: &Arc<Self>, ty: T) -> SimValue<T> {
SimValue::from_bits(ty, UIntValue::new_dyn(self.clone()))
}
}
impl<T: Type> ToSimValue<T> for bitvec::boxed::BitBox {
impl<T: Type> ToSimValueWithType<T> for bitvec::boxed::BitBox {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
self.clone().into_sim_value(ty)
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
self.clone().into_sim_value_with_type(ty)
}
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T> {
self.into_bitvec().into_sim_value(ty)
fn into_sim_value_with_type(self, ty: T) -> SimValue<T> {
self.into_bitvec().into_sim_value_with_type(ty)
}
}
impl<T: Type> ToSimValue<T> for BitSlice {
impl<T: Type> ToSimValueWithType<T> for BitSlice {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
self.to_bitvec().into_sim_value(ty)
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
self.to_bitvec().into_sim_value_with_type(ty)
}
}
impl<This: ?Sized + ToSimValue<T>, T: Type> ToSimValue<T> for &'_ This {
fn to_sim_value(&self, ty: T) -> SimValue<T> {
This::to_sim_value(self, ty)
impl<This: ?Sized + ToSimValue> ToSimValue for &'_ This {
type Type = This::Type;
fn to_sim_value(&self) -> SimValue<Self::Type> {
This::to_sim_value(self)
}
}
impl<This: ?Sized + ToSimValue<T>, T: Type> ToSimValue<T> for &'_ mut This {
fn to_sim_value(&self, ty: T) -> SimValue<T> {
This::to_sim_value(self, ty)
impl<This: ?Sized + ToSimValueWithType<T>, T: Type> ToSimValueWithType<T> for &'_ This {
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
This::to_sim_value_with_type(self, ty)
}
}
impl<This: ?Sized + ToSimValue<T>, T: Type> ToSimValue<T> for Arc<This> {
fn to_sim_value(&self, ty: T) -> SimValue<T> {
This::arc_to_sim_value(self, ty)
}
fn into_sim_value(self, ty: T) -> SimValue<T> {
This::arc_into_sim_value(self, ty)
impl<This: ?Sized + ToSimValue> ToSimValue for &'_ mut This {
type Type = This::Type;
fn to_sim_value(&self) -> SimValue<Self::Type> {
This::to_sim_value(self)
}
}
impl<This: ?Sized + ToSimValue<T> + Send + Sync + 'static, T: Type> ToSimValue<T>
impl<This: ?Sized + ToSimValueWithType<T>, T: Type> ToSimValueWithType<T> for &'_ mut This {
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
This::to_sim_value_with_type(self, ty)
}
}
impl<This: ?Sized + ToSimValue> ToSimValue for Arc<This> {
type Type = This::Type;
fn to_sim_value(&self) -> SimValue<Self::Type> {
This::arc_to_sim_value(self)
}
fn into_sim_value(self) -> SimValue<Self::Type> {
This::arc_into_sim_value(self)
}
}
impl<This: ?Sized + ToSimValueWithType<T>, T: Type> ToSimValueWithType<T> for Arc<This> {
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
This::arc_to_sim_value_with_type(self, ty)
}
fn into_sim_value_with_type(self, ty: T) -> SimValue<T> {
This::arc_into_sim_value_with_type(self, ty)
}
}
impl<This: ?Sized + ToSimValue + Send + Sync + 'static> ToSimValue
for crate::intern::Interned<This>
{
fn to_sim_value(&self, ty: T) -> SimValue<T> {
This::to_sim_value(self, ty)
type Type = This::Type;
fn to_sim_value(&self) -> SimValue<Self::Type> {
This::to_sim_value(self)
}
}
impl<This: ToSimValue<T>, T: Type> ToSimValue<T> for Box<This> {
fn to_sim_value(&self, ty: T) -> SimValue<T> {
This::to_sim_value(self, ty)
impl<This: ?Sized + ToSimValueWithType<T> + Send + Sync + 'static, T: Type> ToSimValueWithType<T>
for crate::intern::Interned<This>
{
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
This::to_sim_value_with_type(self, ty)
}
fn into_sim_value(self, ty: T) -> SimValue<T> {
This::into_sim_value(*self, ty)
}
impl<This: ToSimValue> ToSimValue for Box<This> {
type Type = This::Type;
fn to_sim_value(&self) -> SimValue<Self::Type> {
This::to_sim_value(self)
}
fn into_sim_value(self) -> SimValue<Self::Type> {
This::into_sim_value(*self)
}
}
impl<This: ToSimValueWithType<T>, T: Type> ToSimValueWithType<T> for Box<This> {
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
This::to_sim_value_with_type(self, ty)
}
fn into_sim_value_with_type(self, ty: T) -> SimValue<T> {
This::into_sim_value_with_type(*self, ty)
}
}
impl<T: Type, Len: Size> SimValue<ArrayType<T, Len>> {
#[track_caller]
pub fn from_array_elements<I: IntoIterator<Item: ToSimValue<T>>>(
pub fn from_array_elements<I: IntoIterator<Item: ToSimValueWithType<T>>>(
ty: ArrayType<T, Len>,
elements: I,
) -> Self {
@ -430,23 +531,32 @@ impl<T: Type, Len: Size> SimValue<ArrayType<T, Len>> {
let elements = Vec::from_iter(
elements
.into_iter()
.map(|element| element.into_sim_value(element_ty)),
.map(|element| element.into_sim_value_with_type(element_ty)),
);
assert_eq!(elements.len(), ty.len());
SimValue::from_value(ty, elements.try_into().ok().expect("already checked len"))
}
}
impl<Element: ToSimValue<T>, T: Type> ToSimValue<Array<T>> for [Element] {
impl<Element: ToSimValueWithType<T>, T: Type> ToSimValueWithType<Array<T>> for [Element] {
#[track_caller]
fn to_sim_value(&self, ty: Array<T>) -> SimValue<Array<T>> {
fn to_sim_value_with_type(&self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<CanonicalType>> ToSimValue<CanonicalType> for [Element] {
impl<Element: ToSimValue<Type: StaticType>> ToSimValue for [Element] {
type Type = Array<Element::Type>;
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_array_elements(ArrayType::new_dyn(StaticType::TYPE, self.len()), self)
}
}
impl<Element: ToSimValueWithType<CanonicalType>> ToSimValueWithType<CanonicalType> for [Element] {
#[track_caller]
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
@ -454,71 +564,61 @@ impl<Element: ToSimValue<CanonicalType>> ToSimValue<CanonicalType> for [Element]
}
}
impl<Element: ToSimValue<T>, T: Type, const N: usize> ToSimValue<Array<T, N>> for [Element; N]
impl<Element: ToSimValueWithType<T>, T: Type, const N: usize> ToSimValueWithType<Array<T, N>>
for [Element; N]
where
ConstUsize<N>: KnownSize,
{
#[track_caller]
fn to_sim_value(&self, ty: Array<T, N>) -> SimValue<Array<T, N>> {
fn to_sim_value_with_type(&self, ty: Array<T, N>) -> SimValue<Array<T, N>> {
SimValue::from_array_elements(ty, self)
}
#[track_caller]
fn into_sim_value(self, ty: Array<T, N>) -> SimValue<Array<T, N>> {
fn into_sim_value_with_type(self, ty: Array<T, N>) -> SimValue<Array<T, N>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<T>, T: Type, const N: usize> ToSimValue<Array<T>> for [Element; N] {
#[track_caller]
fn to_sim_value(&self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
impl<Element: ToSimValue<Type: StaticType>, const N: usize> ToSimValue for [Element; N]
where
ConstUsize<N>: KnownSize,
{
type Type = Array<Element::Type, N>;
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_array_elements(StaticType::TYPE, self)
}
#[track_caller]
fn into_sim_value(self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
fn into_sim_value(self) -> SimValue<Self::Type> {
SimValue::from_array_elements(StaticType::TYPE, self)
}
}
impl<Element: ToSimValue<CanonicalType>, const N: usize> ToSimValue<CanonicalType>
impl<Element: ToSimValueWithType<T>, T: Type, const N: usize> ToSimValueWithType<Array<T>>
for [Element; N]
{
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
))
}
#[track_caller]
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
))
}
}
impl<Element: ToSimValue<T>, T: Type> ToSimValue<Array<T>> for Vec<Element> {
#[track_caller]
fn to_sim_value(&self, ty: Array<T>) -> SimValue<Array<T>> {
fn to_sim_value_with_type(&self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
#[track_caller]
fn into_sim_value(self, ty: Array<T>) -> SimValue<Array<T>> {
fn into_sim_value_with_type(self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<CanonicalType>> ToSimValue<CanonicalType> for Vec<Element> {
impl<Element: ToSimValueWithType<CanonicalType>, const N: usize> ToSimValueWithType<CanonicalType>
for [Element; N]
{
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
))
}
#[track_caller]
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType> {
fn into_sim_value_with_type(self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
@ -526,37 +626,131 @@ impl<Element: ToSimValue<CanonicalType>> ToSimValue<CanonicalType> for Vec<Eleme
}
}
impl<T: Type> ToSimValue<T> for Expr<T> {
impl<Element: ToSimValueWithType<T>, T: Type> ToSimValueWithType<Array<T>> for Vec<Element> {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
assert_eq!(Expr::ty(*self), ty);
fn to_sim_value_with_type(&self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
#[track_caller]
fn into_sim_value_with_type(self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<Type: StaticType>> ToSimValue for Vec<Element> {
type Type = Array<Element::Type>;
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_array_elements(ArrayType::new_dyn(StaticType::TYPE, self.len()), self)
}
fn into_sim_value(self) -> SimValue<Self::Type> {
SimValue::from_array_elements(ArrayType::new_dyn(StaticType::TYPE, self.len()), self)
}
}
impl<Element: ToSimValueWithType<CanonicalType>> ToSimValueWithType<CanonicalType>
for Vec<Element>
{
#[track_caller]
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
))
}
#[track_caller]
fn into_sim_value_with_type(self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
))
}
}
impl<Element: ToSimValueWithType<T>, T: Type> ToSimValueWithType<Array<T>> for Box<[Element]> {
#[track_caller]
fn to_sim_value_with_type(&self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
#[track_caller]
fn into_sim_value_with_type(self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<Type: StaticType>> ToSimValue for Box<[Element]> {
type Type = Array<Element::Type>;
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_array_elements(ArrayType::new_dyn(StaticType::TYPE, self.len()), self)
}
fn into_sim_value(self) -> SimValue<Self::Type> {
SimValue::from_array_elements(ArrayType::new_dyn(StaticType::TYPE, self.len()), self)
}
}
impl<Element: ToSimValueWithType<CanonicalType>> ToSimValueWithType<CanonicalType>
for Box<[Element]>
{
#[track_caller]
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
))
}
#[track_caller]
fn into_sim_value_with_type(self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(SimValue::from_array_elements(
<Array>::from_canonical(ty),
self,
))
}
}
impl<T: Type> ToSimValue for Expr<T> {
type Type = T;
#[track_caller]
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_bitslice(
ty,
Expr::ty(*self),
&crate::expr::ToLiteralBits::to_literal_bits(self)
.expect("must be a literal expression"),
)
}
}
forward_to_sim_value_with_type!([T: Type] Expr<T>);
macro_rules! impl_to_sim_value_for_bool_like {
($ty:ident) => {
impl ToSimValue<$ty> for bool {
fn to_sim_value(&self, ty: $ty) -> SimValue<$ty> {
impl ToSimValueWithType<$ty> for bool {
fn to_sim_value_with_type(&self, ty: $ty) -> SimValue<$ty> {
SimValue::from_value(ty, *self)
}
}
};
}
impl ToSimValue for bool {
type Type = Bool;
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_value(Bool, *self)
}
}
impl_to_sim_value_for_bool_like!(Bool);
impl_to_sim_value_for_bool_like!(AsyncReset);
impl_to_sim_value_for_bool_like!(SyncReset);
impl_to_sim_value_for_bool_like!(Reset);
impl_to_sim_value_for_bool_like!(Clock);
impl ToSimValue<CanonicalType> for bool {
impl ToSimValueWithType<CanonicalType> for bool {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
match ty {
CanonicalType::UInt(_)
| CanonicalType::SInt(_)
@ -579,19 +773,22 @@ impl ToSimValue<CanonicalType> for bool {
macro_rules! impl_to_sim_value_for_primitive_int {
($prim:ident) => {
impl ToSimValue<<$prim as ToExpr>::Type> for $prim {
impl ToSimValue for $prim {
type Type = <$prim as ToExpr>::Type;
#[track_caller]
fn to_sim_value(
&self,
ty: <$prim as ToExpr>::Type,
) -> SimValue<<$prim as ToExpr>::Type> {
SimValue::from_value(ty, (*self).into())
) -> SimValue<Self::Type> {
SimValue::from_value(StaticType::TYPE, (*self).into())
}
}
impl ToSimValue<<<$prim as ToExpr>::Type as IntType>::Dyn> for $prim {
forward_to_sim_value_with_type!([] $prim);
impl ToSimValueWithType<<<$prim as ToExpr>::Type as IntType>::Dyn> for $prim {
#[track_caller]
fn to_sim_value(
fn to_sim_value_with_type(
&self,
ty: <<$prim as ToExpr>::Type as IntType>::Dyn,
) -> SimValue<<<$prim as ToExpr>::Type as IntType>::Dyn> {
@ -602,11 +799,11 @@ macro_rules! impl_to_sim_value_for_primitive_int {
}
}
impl ToSimValue<CanonicalType> for $prim {
impl ToSimValueWithType<CanonicalType> for $prim {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
let ty: <<$prim as ToExpr>::Type as IntType>::Dyn = Type::from_canonical(ty);
SimValue::into_canonical(self.to_sim_value(ty))
SimValue::into_canonical(self.to_sim_value_with_type(ty))
}
}
};
@ -627,35 +824,51 @@ impl_to_sim_value_for_primitive_int!(isize);
macro_rules! impl_to_sim_value_for_int_value {
($IntValue:ident, $Int:ident, $IntType:ident) => {
impl<Width: KnownSize> ToSimValue<$IntType<Width>> for $IntValue<Width> {
fn to_sim_value(&self, ty: $IntType<Width>) -> SimValue<$IntType<Width>> {
self.bits().to_sim_value(ty)
impl<Width: Size> ToSimValue for $IntValue<Width> {
type Type = $IntType<Width>;
fn to_sim_value(&self) -> SimValue<Self::Type> {
SimValue::from_value(self.ty(), self.clone())
}
fn into_sim_value(self, ty: $IntType<Width>) -> SimValue<$IntType<Width>> {
self.into_bits().into_sim_value(ty)
fn into_sim_value(self) -> SimValue<Self::Type> {
SimValue::from_value(self.ty(), self)
}
}
impl<Width: Size> ToSimValue<$Int> for $IntValue<Width> {
fn to_sim_value(&self, ty: $Int) -> SimValue<$Int> {
self.bits().to_sim_value(ty)
impl<Width: Size> ToSimValueWithType<$IntType<Width>> for $IntValue<Width> {
fn to_sim_value_with_type(&self, ty: $IntType<Width>) -> SimValue<$IntType<Width>> {
SimValue::from_value(ty, self.clone())
}
fn into_sim_value(self, ty: $Int) -> SimValue<$Int> {
self.into_bits().into_sim_value(ty)
fn into_sim_value_with_type(self, ty: $IntType<Width>) -> SimValue<$IntType<Width>> {
SimValue::from_value(ty, self)
}
}
impl<Width: Size> ToSimValue<CanonicalType> for $IntValue<Width> {
impl<Width: KnownSize> ToSimValueWithType<$Int> for $IntValue<Width> {
fn to_sim_value_with_type(&self, ty: $Int) -> SimValue<$Int> {
self.bits().to_sim_value_with_type(ty)
}
fn into_sim_value_with_type(self, ty: $Int) -> SimValue<$Int> {
self.into_bits().into_sim_value_with_type(ty)
}
}
impl<Width: Size> ToSimValueWithType<CanonicalType> for $IntValue<Width> {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(self.to_sim_value($Int::from_canonical(ty)))
fn to_sim_value_with_type(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(
self.to_sim_value_with_type($IntType::<Width>::from_canonical(ty)),
)
}
#[track_caller]
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(self.into_sim_value($Int::from_canonical(ty)))
fn into_sim_value_with_type(self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(
self.into_sim_value_with_type($IntType::<Width>::from_canonical(ty)),
)
}
}
};

View file

@ -11,6 +11,7 @@ use crate::{
intern::{Intern, Interned},
phantom_const::PhantomConst,
reset::{AsyncReset, Reset, SyncReset},
sim::value::{SimValue, ToSimValueWithType},
source_location::SourceLocation,
util::ConstUsize,
};
@ -269,7 +270,7 @@ pub trait Type:
{
type BaseType: BaseType;
type MaskType: Type<MaskType = Self::MaskType>;
type SimValue: fmt::Debug + Clone + 'static;
type SimValue: fmt::Debug + Clone + 'static + ToSimValueWithType<Self>;
type MatchVariant: 'static + Send + Sync;
type MatchActiveScope;
type MatchVariantAndInactiveScope: MatchVariantAndInactiveScope<
@ -389,6 +390,15 @@ impl OpaqueSimValue {
}
}
impl<T: Type<SimValue = OpaqueSimValue>> ToSimValueWithType<T> for OpaqueSimValue {
fn to_sim_value_with_type(&self, ty: T) -> SimValue<T> {
SimValue::from_value(ty, self.clone())
}
fn into_sim_value_with_type(self, ty: T) -> SimValue<T> {
SimValue::from_value(ty, self)
}
}
pub trait StaticType: Type {
const TYPE: Self;
const MASK_TYPE: Self::MaskType;

View file

@ -7,13 +7,7 @@ use fayalite::{
module::{instance_with_loc, reg_builder_with_loc},
prelude::*,
reset::ResetType,
sim::{
time::SimDuration,
value::{SimValue, ToSimValue},
vcd::VcdWriterDecls,
Simulation,
},
ty::StaticType,
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation},
util::RcWriter,
};
use std::num::NonZeroUsize;
@ -391,113 +385,110 @@ fn test_enums() {
let mut sim = Simulation::new(enums());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
sim.write_bool(sim.io().en, false);
sim.write_bool_or_int(sim.io().which_in, 0_hdl_u2);
sim.write_bool_or_int(sim.io().data_in, 0_hdl_u4);
sim.write(sim.io().cd.clk, false);
sim.write(sim.io().cd.rst, true);
sim.write(sim.io().en, false);
sim.write(sim.io().which_in, 0_hdl_u2);
sim.write(sim.io().data_in, 0_hdl_u4);
sim.advance_time(SimDuration::from_micros(1));
sim.write_clock(sim.io().cd.clk, true);
sim.write(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(100));
sim.write_reset(sim.io().cd.rst, false);
sim.write(sim.io().cd.rst, false);
sim.advance_time(SimDuration::from_nanos(900));
type BOutTy = HdlOption<(UInt<1>, Bool)>;
#[derive(Debug, PartialEq)]
#[hdl(cmp_eq)]
struct IO {
en: bool,
which_in: u8,
data_in: u8,
which_out: u8,
data_out: u8,
b_out: SimValue<BOutTy>,
en: Bool,
which_in: UInt<2>,
data_in: UInt<4>,
which_out: UInt<2>,
data_out: UInt<4>,
b_out: HdlOption<(UInt<1>, Bool)>,
}
let io_cycles = [
#[hdl(sim)]
IO {
en: false,
which_in: 0,
data_in: 0,
which_out: 0,
data_out: 0,
b_out: HdlNone().to_sim_value(StaticType::TYPE),
which_in: 0_hdl_u2,
data_in: 0_hdl_u4,
which_out: 0_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlNone(),
},
#[hdl(sim)]
IO {
en: true,
which_in: 1,
data_in: 0,
which_out: 0,
data_out: 0,
b_out: HdlNone().to_sim_value(StaticType::TYPE),
which_in: 1_hdl_u2,
data_in: 0_hdl_u4,
which_out: 0_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlNone(),
},
#[hdl(sim)]
IO {
en: false,
which_in: 0,
data_in: 0,
which_out: 1,
data_out: 0,
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
which_in: 0_hdl_u2,
data_in: 0_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlSome((0_hdl_u1, false)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 1,
data_in: 0xF,
which_out: 1,
data_out: 0,
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
which_in: 1_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlSome((0_hdl_u1, false)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 1,
data_in: 0xF,
which_out: 1,
data_out: 0x3,
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
which_in: 1_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0x3_hdl_u4,
b_out: HdlSome((1_hdl_u1, true)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 2,
data_in: 0xF,
which_out: 1,
data_out: 0x3,
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
which_in: 2_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0x3_hdl_u4,
b_out: HdlSome((1_hdl_u1, true)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 2,
data_in: 0xF,
which_out: 2,
data_out: 0xF,
b_out: HdlNone().to_sim_value(StaticType::TYPE),
which_in: 2_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 2_hdl_u2,
data_out: 0xF_hdl_u4,
b_out: HdlNone(),
},
];
for (
cycle,
expected @ IO {
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl(sim)]
let IO {
en,
which_in,
data_in,
which_out: _,
data_out: _,
b_out: _,
},
) in io_cycles.into_iter().enumerate()
{
sim.write_bool(sim.io().en, en);
sim.write_bool_or_int(sim.io().which_in, which_in.cast_to_static());
sim.write_bool_or_int(sim.io().data_in, data_in.cast_to_static());
let io = IO {
} = expected;
sim.write(sim.io().en, &en);
sim.write(sim.io().which_in, &which_in);
sim.write(sim.io().data_in, &data_in);
let io = #[hdl(sim)]
IO {
en,
which_in,
data_in,
which_out: sim
.read_bool_or_int(sim.io().which_out)
.to_bigint()
.try_into()
.expect("known to be in range"),
data_out: sim
.read_bool_or_int(sim.io().data_out)
.to_bigint()
.try_into()
.expect("known to be in range"),
which_out: sim.read(sim.io().which_out),
data_out: sim.read(sim.io().data_out),
b_out: sim.read(sim.io().b_out),
};
assert_eq!(
@ -559,7 +550,7 @@ fn test_memories() {
w_mask: (Bool, Bool),
}
let io_cycles = [
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: false,
@ -569,7 +560,7 @@ fn test_memories() {
w_data: (0u8, 0i8),
w_mask: (false, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -579,7 +570,7 @@ fn test_memories() {
w_data: (0x10u8, 0x20i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -589,7 +580,7 @@ fn test_memories() {
w_data: (0x30u8, 0x40i8),
w_mask: (false, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -599,7 +590,7 @@ fn test_memories() {
w_data: (0x50u8, 0x60i8),
w_mask: (true, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -609,7 +600,7 @@ fn test_memories() {
w_data: (0x70u8, -0x80i8),
w_mask: (false, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -619,7 +610,7 @@ fn test_memories() {
w_data: (0x90u8, 0xA0u8 as i8),
w_mask: (false, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -629,7 +620,7 @@ fn test_memories() {
w_data: (0x90u8, 0xA0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -639,7 +630,7 @@ fn test_memories() {
w_data: (0xB0u8, 0xC0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -649,7 +640,7 @@ fn test_memories() {
w_data: (0xD0u8, 0xE0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 1_hdl_u4,
r_en: true,
@ -659,7 +650,7 @@ fn test_memories() {
w_data: (0xD0u8, 0xE0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 2_hdl_u4,
r_en: true,
@ -671,7 +662,7 @@ fn test_memories() {
},
];
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl]
#[hdl(sim)]
let IO {
r_addr,
r_en,
@ -681,13 +672,13 @@ fn test_memories() {
w_data,
w_mask,
} = expected;
sim.write(sim.io().r.addr, r_addr);
sim.write(sim.io().r.en, r_en);
sim.write(sim.io().w.addr, w_addr);
sim.write(sim.io().w.en, w_en);
sim.write(sim.io().w.data, w_data);
sim.write(sim.io().w.mask, w_mask);
let io = (#[hdl]
sim.write(sim.io().r.addr, &r_addr);
sim.write(sim.io().r.en, &r_en);
sim.write(sim.io().w.addr, &w_addr);
sim.write(sim.io().w.en, &w_en);
sim.write(sim.io().w.data, &w_data);
sim.write(sim.io().w.mask, &w_mask);
let io = #[hdl(sim)]
IO {
r_addr,
r_en,
@ -696,20 +687,19 @@ fn test_memories() {
w_en,
w_data,
w_mask,
})
.to_sim_value(StaticType::TYPE);
};
assert_eq!(
expected.to_sim_value(StaticType::TYPE),
expected,
io,
"vcd:\n{}\ncycle: {cycle}",
String::from_utf8(writer.take()).unwrap(),
);
sim.advance_time(SimDuration::from_micros(1));
sim.write_clock(sim.io().r.clk, true);
sim.write_clock(sim.io().w.clk, true);
sim.write(sim.io().r.clk, true);
sim.write(sim.io().w.clk, true);
sim.advance_time(SimDuration::from_micros(1));
sim.write_clock(sim.io().r.clk, false);
sim.write_clock(sim.io().w.clk, false);
sim.write(sim.io().r.clk, false);
sim.write(sim.io().w.clk, false);
}
sim.flush_traces().unwrap();
let vcd = String::from_utf8(writer.take()).unwrap();