Compare commits

...

10 commits

41 changed files with 8842 additions and 7737 deletions

View file

@ -30,7 +30,9 @@ pub(crate) struct ParsedBundle {
pub(crate) field_flips: Vec<Option<HdlAttr<kw::flip, kw::hdl>>>,
pub(crate) mask_type_ident: Ident,
pub(crate) mask_type_match_variant_ident: Ident,
pub(crate) mask_type_sim_value_ident: Ident,
pub(crate) match_variant_ident: Ident,
pub(crate) sim_value_ident: Ident,
pub(crate) builder_ident: Ident,
pub(crate) mask_type_builder_ident: Ident,
}
@ -125,7 +127,9 @@ impl ParsedBundle {
field_flips,
mask_type_ident: format_ident!("__{}__MaskType", ident),
mask_type_match_variant_ident: format_ident!("__{}__MaskType__MatchVariant", ident),
mask_type_sim_value_ident: format_ident!("__{}__MaskType__SimValue", ident),
match_variant_ident: format_ident!("__{}__MatchVariant", ident),
sim_value_ident: format_ident!("__{}__SimValue", ident),
mask_type_builder_ident: format_ident!("__{}__MaskType__Builder", ident),
builder_ident: format_ident!("__{}__Builder", ident),
ident,
@ -427,7 +431,9 @@ impl ToTokens for ParsedBundle {
field_flips,
mask_type_ident,
mask_type_match_variant_ident,
mask_type_sim_value_ident,
match_variant_ident,
sim_value_ident,
builder_ident,
mask_type_builder_ident,
} = self;
@ -523,7 +529,7 @@ impl ToTokens for ParsedBundle {
semi_token: None,
}
.to_tokens(tokens);
let mut mask_type_match_variant_fields = mask_type_fields;
let mut mask_type_match_variant_fields = mask_type_fields.clone();
for Field { ty, .. } in &mut mask_type_match_variant_fields.named {
*ty = parse_quote_spanned! {span=>
::fayalite::expr::Expr<#ty>
@ -565,6 +571,58 @@ impl ToTokens for ParsedBundle {
semi_token: None,
}
.to_tokens(tokens);
let mut mask_type_sim_value_fields = mask_type_fields;
for Field { ty, .. } in &mut mask_type_sim_value_fields.named {
*ty = parse_quote_spanned! {span=>
::fayalite::sim::value::SimValue<#ty>
};
}
ItemStruct {
attrs: vec![
parse_quote_spanned! {span=>
#[::fayalite::__std::prelude::v1::derive(
::fayalite::__std::fmt::Debug,
::fayalite::__std::clone::Clone,
)]
},
parse_quote_spanned! {span=>
#[allow(non_camel_case_types, dead_code)]
},
],
vis: vis.clone(),
struct_token: *struct_token,
ident: mask_type_sim_value_ident.clone(),
generics: generics.into(),
fields: Fields::Named(mask_type_sim_value_fields),
semi_token: None,
}
.to_tokens(tokens);
let mut sim_value_fields = FieldsNamed::from(fields.clone());
for Field { ty, .. } in &mut sim_value_fields.named {
*ty = parse_quote_spanned! {span=>
::fayalite::sim::value::SimValue<#ty>
};
}
ItemStruct {
attrs: vec![
parse_quote_spanned! {span=>
#[::fayalite::__std::prelude::v1::derive(
::fayalite::__std::fmt::Debug,
::fayalite::__std::clone::Clone,
)]
},
parse_quote_spanned! {span=>
#[allow(non_camel_case_types, dead_code)]
},
],
vis: vis.clone(),
struct_token: *struct_token,
ident: sim_value_ident.clone(),
generics: generics.into(),
fields: Fields::Named(sim_value_fields),
semi_token: None,
}
.to_tokens(tokens);
let this_token = Ident::new("__this", span);
let fields_token = Ident::new("__fields", span);
let self_token = Token![self](span);
@ -615,6 +673,25 @@ impl ToTokens for ParsedBundle {
}
},
));
let sim_value_from_bits_fields = Vec::from_iter(fields.named().into_iter().map(|field| {
let ident: &Ident = field.ident().as_ref().unwrap();
quote_spanned! {span=>
#ident: v.field_from_bits(),
}
}));
let sim_value_clone_from_bits_fields =
Vec::from_iter(fields.named().into_iter().map(|field| {
let ident: &Ident = field.ident().as_ref().unwrap();
quote_spanned! {span=>
v.field_clone_from_bits(&mut value.#ident);
}
}));
let sim_value_to_bits_fields = Vec::from_iter(fields.named().into_iter().map(|field| {
let ident: &Ident = field.ident().as_ref().unwrap();
quote_spanned! {span=>
v.field_to_bits(&value.#ident);
}
}));
let fields_len = fields.named().into_iter().len();
quote_spanned! {span=>
#[automatically_derived]
@ -623,6 +700,7 @@ impl ToTokens for ParsedBundle {
{
type BaseType = ::fayalite::bundle::Bundle;
type MaskType = #mask_type_ident #type_generics;
type SimValue = #mask_type_sim_value_ident #type_generics;
type MatchVariant = #mask_type_match_variant_ident #type_generics;
type MatchActiveScope = ();
type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
@ -660,6 +738,34 @@ impl ToTokens for ParsedBundle {
fn source_location() -> ::fayalite::source_location::SourceLocation {
::fayalite::source_location::SourceLocation::caller()
}
fn sim_value_from_bits(
&self,
bits: &::fayalite::__bitvec::slice::BitSlice,
) -> <Self as ::fayalite::ty::Type>::SimValue {
#![allow(unused_mut, unused_variables)]
let mut v = ::fayalite::bundle::BundleSimValueFromBits::new(*self, bits);
#mask_type_sim_value_ident {
#(#sim_value_from_bits_fields)*
}
}
fn sim_value_clone_from_bits(
&self,
value: &mut <Self as ::fayalite::ty::Type>::SimValue,
bits: &::fayalite::__bitvec::slice::BitSlice,
) {
#![allow(unused_mut, unused_variables)]
let mut v = ::fayalite::bundle::BundleSimValueFromBits::new(*self, bits);
#(#sim_value_clone_from_bits_fields)*
}
fn sim_value_to_bits(
&self,
value: &<Self as ::fayalite::ty::Type>::SimValue,
bits: &mut ::fayalite::__bitvec::slice::BitSlice,
) {
#![allow(unused_mut, unused_variables)]
let mut v = ::fayalite::bundle::BundleSimValueToBits::new(*self, bits);
#(#sim_value_to_bits_fields)*
}
}
#[automatically_derived]
impl #impl_generics ::fayalite::bundle::BundleType for #mask_type_ident #type_generics
@ -696,6 +802,7 @@ impl ToTokens for ParsedBundle {
{
type BaseType = ::fayalite::bundle::Bundle;
type MaskType = #mask_type_ident #type_generics;
type SimValue = #sim_value_ident #type_generics;
type MatchVariant = #match_variant_ident #type_generics;
type MatchActiveScope = ();
type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
@ -735,6 +842,34 @@ impl ToTokens for ParsedBundle {
fn source_location() -> ::fayalite::source_location::SourceLocation {
::fayalite::source_location::SourceLocation::caller()
}
fn sim_value_from_bits(
&self,
bits: &::fayalite::__bitvec::slice::BitSlice,
) -> <Self as ::fayalite::ty::Type>::SimValue {
#![allow(unused_mut, unused_variables)]
let mut v = ::fayalite::bundle::BundleSimValueFromBits::new(*self, bits);
#sim_value_ident {
#(#sim_value_from_bits_fields)*
}
}
fn sim_value_clone_from_bits(
&self,
value: &mut <Self as ::fayalite::ty::Type>::SimValue,
bits: &::fayalite::__bitvec::slice::BitSlice,
) {
#![allow(unused_mut, unused_variables)]
let mut v = ::fayalite::bundle::BundleSimValueFromBits::new(*self, bits);
#(#sim_value_clone_from_bits_fields)*
}
fn sim_value_to_bits(
&self,
value: &<Self as ::fayalite::ty::Type>::SimValue,
bits: &mut ::fayalite::__bitvec::slice::BitSlice,
) {
#![allow(unused_mut, unused_variables)]
let mut v = ::fayalite::bundle::BundleSimValueToBits::new(*self, bits);
#(#sim_value_to_bits_fields)*
}
}
#[automatically_derived]
impl #impl_generics ::fayalite::bundle::BundleType for #target #type_generics
@ -768,23 +903,33 @@ impl ToTokens for ParsedBundle {
}
.to_tokens(tokens);
if let Some((cmp_eq,)) = cmp_eq {
let mut where_clause =
let mut expr_where_clause =
Generics::from(generics)
.where_clause
.unwrap_or_else(|| syn::WhereClause {
where_token: Token![where](span),
predicates: Punctuated::new(),
});
let mut sim_value_where_clause = expr_where_clause.clone();
let mut fields_sim_value_eq = vec![];
let mut fields_cmp_eq = vec![];
let mut fields_cmp_ne = vec![];
for field in fields.named() {
let field_ident = field.ident();
let field_ty = field.ty();
where_clause
expr_where_clause
.predicates
.push(parse_quote_spanned! {cmp_eq.span=>
#field_ty: ::fayalite::expr::ops::ExprPartialEq<#field_ty>
});
sim_value_where_clause
.predicates
.push(parse_quote_spanned! {cmp_eq.span=>
#field_ty: ::fayalite::sim::value::SimValuePartialEq<#field_ty>
});
fields_sim_value_eq.push(quote_spanned! {span=>
::fayalite::sim::value::SimValuePartialEq::sim_value_eq(&__lhs.#field_ident, &__rhs.#field_ident)
});
fields_cmp_eq.push(quote_spanned! {span=>
::fayalite::expr::ops::ExprPartialEq::cmp_eq(__lhs.#field_ident, __rhs.#field_ident)
});
@ -792,9 +937,13 @@ impl ToTokens for ParsedBundle {
::fayalite::expr::ops::ExprPartialEq::cmp_ne(__lhs.#field_ident, __rhs.#field_ident)
});
}
let sim_value_eq_body;
let cmp_eq_body;
let cmp_ne_body;
if fields_len == 0 {
sim_value_eq_body = quote_spanned! {span=>
true
};
cmp_eq_body = quote_spanned! {span=>
::fayalite::expr::ToExpr::to_expr(&true)
};
@ -802,6 +951,9 @@ impl ToTokens for ParsedBundle {
::fayalite::expr::ToExpr::to_expr(&false)
};
} else {
sim_value_eq_body = quote_spanned! {span=>
#(#fields_sim_value_eq)&&*
};
cmp_eq_body = quote_spanned! {span=>
#(#fields_cmp_eq)&*
};
@ -812,7 +964,7 @@ impl ToTokens for ParsedBundle {
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics ::fayalite::expr::ops::ExprPartialEq<Self> for #target #type_generics
#where_clause
#expr_where_clause
{
fn cmp_eq(
__lhs: ::fayalite::expr::Expr<Self>,
@ -827,6 +979,17 @@ impl ToTokens for ParsedBundle {
#cmp_ne_body
}
}
#[automatically_derived]
impl #impl_generics ::fayalite::sim::value::SimValuePartialEq<Self> for #target #type_generics
#sim_value_where_clause
{
fn sim_value_eq(
__lhs: &::fayalite::sim::value::SimValue<Self>,
__rhs: &::fayalite::sim::value::SimValue<Self>,
) -> bool {
#sim_value_eq_body
}
}
}
.to_tokens(tokens);
}

View file

@ -129,6 +129,7 @@ pub(crate) struct ParsedEnum {
pub(crate) brace_token: Brace,
pub(crate) variants: Punctuated<ParsedVariant, Token![,]>,
pub(crate) match_variant_ident: Ident,
pub(crate) sim_value_ident: Ident,
}
impl ParsedEnum {
@ -190,6 +191,7 @@ impl ParsedEnum {
brace_token,
variants,
match_variant_ident: format_ident!("__{}__MatchVariant", ident),
sim_value_ident: format_ident!("__{}__SimValue", ident),
ident,
})
}
@ -207,6 +209,7 @@ impl ToTokens for ParsedEnum {
brace_token,
variants,
match_variant_ident,
sim_value_ident,
} = self;
let span = ident.span();
let ItemOptions {
@ -409,6 +412,106 @@ impl ToTokens for ParsedEnum {
)),
}
.to_tokens(tokens);
let mut enum_attrs = attrs.clone();
enum_attrs.push(parse_quote_spanned! {span=>
#[::fayalite::__std::prelude::v1::derive(
::fayalite::__std::fmt::Debug,
::fayalite::__std::clone::Clone,
)]
});
enum_attrs.push(parse_quote_spanned! {span=>
#[allow(dead_code, non_camel_case_types)]
});
let sim_value_has_unknown_variant = !variants.len().is_power_of_two();
let sim_value_unknown_variant_name = sim_value_has_unknown_variant.then(|| {
let mut name = String::new();
let unknown = "Unknown";
loop {
let orig_len = name.len();
name.push_str(unknown);
if variants.iter().all(|v| v.ident != name) {
break Ident::new(&name, span);
}
name.truncate(orig_len);
name.push('_');
}
});
let sim_value_unknown_variant =
sim_value_unknown_variant_name
.as_ref()
.map(|unknown_variant_name| {
Pair::End(parse_quote_spanned! {span=>
#unknown_variant_name(::fayalite::enum_::UnknownVariantSimValue)
})
});
ItemEnum {
attrs: enum_attrs,
vis: vis.clone(),
enum_token: *enum_token,
ident: sim_value_ident.clone(),
generics: generics.into(),
brace_token: *brace_token,
variants: Punctuated::from_iter(
variants
.pairs()
.map_pair_value_ref(
|ParsedVariant {
attrs,
options: _,
ident,
field,
}| Variant {
attrs: attrs.clone(),
ident: ident.clone(),
fields: match field {
Some(ParsedVariantField {
paren_token,
attrs,
options: _,
ty,
comma_token,
}) => Fields::Unnamed(FieldsUnnamed {
paren_token: *paren_token,
unnamed: Punctuated::from_iter([
Pair::new(
Field {
attrs: attrs.clone(),
vis: Visibility::Inherited,
mutability: FieldMutability::None,
ident: None,
colon_token: None,
ty: parse_quote_spanned! {span=>
::fayalite::sim::value::SimValue<#ty>
},
},
Some(comma_token.unwrap_or(Token![,](ident.span()))),
),
Pair::new(
Field {
attrs: vec![],
vis: Visibility::Inherited,
mutability: FieldMutability::None,
ident: None,
colon_token: None,
ty: parse_quote_spanned! {span=>
::fayalite::enum_::EnumPaddingSimValue
},
},
None,
),
]),
}),
None => Fields::Unnamed(parse_quote_spanned! {span=>
(::fayalite::enum_::EnumPaddingSimValue)
}),
},
discriminant: None,
},
)
.chain(sim_value_unknown_variant),
),
}
.to_tokens(tokens);
let self_token = Token![self](span);
for (index, ParsedVariant { ident, field, .. }) in variants.iter().enumerate() {
if let Some(ParsedVariantField { ty, .. }) = field {
@ -534,6 +637,142 @@ impl ToTokens for ParsedEnum {
}
},
));
let sim_value_from_bits_unknown_match_arm = if let Some(sim_value_unknown_variant_name) =
&sim_value_unknown_variant_name
{
quote_spanned! {span=>
_ => #sim_value_ident::#sim_value_unknown_variant_name(v.unknown_variant_from_bits()),
}
} else {
quote_spanned! {span=>
_ => ::fayalite::__std::unreachable!(),
}
};
let sim_value_from_bits_match_arms = Vec::from_iter(
variants
.iter()
.enumerate()
.map(
|(
index,
ParsedVariant {
attrs: _,
options: _,
ident,
field,
},
)| {
if let Some(_) = field {
quote_spanned! {span=>
#index => {
let (field, padding) = v.variant_with_field_from_bits();
#sim_value_ident::#ident(field, padding)
}
}
} else {
quote_spanned! {span=>
#index => #sim_value_ident::#ident(
v.variant_no_field_from_bits(),
),
}
}
},
)
.chain([sim_value_from_bits_unknown_match_arm]),
);
let sim_value_clone_from_bits_unknown_match_arm =
if let Some(sim_value_unknown_variant_name) = &sim_value_unknown_variant_name {
quote_spanned! {span=>
_ => if let #sim_value_ident::#sim_value_unknown_variant_name(value) = value {
v.unknown_variant_clone_from_bits(value);
} else {
*value = #sim_value_ident::#sim_value_unknown_variant_name(
v.unknown_variant_from_bits(),
);
},
}
} else {
quote_spanned! {span=>
_ => ::fayalite::__std::unreachable!(),
}
};
let sim_value_clone_from_bits_match_arms = Vec::from_iter(
variants
.iter()
.enumerate()
.map(
|(
index,
ParsedVariant {
attrs: _,
options: _,
ident,
field,
},
)| {
if let Some(_) = field {
quote_spanned! {span=>
#index => if let #sim_value_ident::#ident(field, padding) = value {
v.variant_with_field_clone_from_bits(field, padding);
} else {
let (field, padding) = v.variant_with_field_from_bits();
*value = #sim_value_ident::#ident(field, padding);
},
}
} else {
quote_spanned! {span=>
#index => if let #sim_value_ident::#ident(padding) = value {
v.variant_no_field_clone_from_bits(padding);
} else {
*value = #sim_value_ident::#ident(
v.variant_no_field_from_bits(),
);
},
}
}
},
)
.chain([sim_value_clone_from_bits_unknown_match_arm]),
);
let sim_value_to_bits_match_arms = Vec::from_iter(
variants
.iter()
.enumerate()
.map(
|(
index,
ParsedVariant {
attrs: _,
options: _,
ident,
field,
},
)| {
if let Some(_) = field {
quote_spanned! {span=>
#sim_value_ident::#ident(field, padding) => {
v.variant_with_field_to_bits(#index, field, padding);
}
}
} else {
quote_spanned! {span=>
#sim_value_ident::#ident(padding) => {
v.variant_no_field_to_bits(#index, padding);
}
}
}
},
)
.chain(sim_value_unknown_variant_name.as_ref().map(
|sim_value_unknown_variant_name| {
quote_spanned! {span=>
#sim_value_ident::#sim_value_unknown_variant_name(value) => {
v.unknown_variant_to_bits(value);
}
}
},
)),
);
let variants_len = variants.len();
quote_spanned! {span=>
#[automatically_derived]
@ -542,6 +781,7 @@ impl ToTokens for ParsedEnum {
{
type BaseType = ::fayalite::enum_::Enum;
type MaskType = ::fayalite::int::Bool;
type SimValue = #sim_value_ident #type_generics;
type MatchVariant = #match_variant_ident #type_generics;
type MatchActiveScope = ::fayalite::module::Scope;
type MatchVariantAndInactiveScope = ::fayalite::enum_::EnumMatchVariantAndInactiveScope<Self>;
@ -574,6 +814,35 @@ impl ToTokens for ParsedEnum {
fn source_location() -> ::fayalite::source_location::SourceLocation {
::fayalite::source_location::SourceLocation::caller()
}
fn sim_value_from_bits(
&self,
bits: &::fayalite::__bitvec::slice::BitSlice,
) -> <Self as ::fayalite::ty::Type>::SimValue {
let v = ::fayalite::enum_::EnumSimValueFromBits::new(*self, bits);
match v.discriminant() {
#(#sim_value_from_bits_match_arms)*
}
}
fn sim_value_clone_from_bits(
&self,
value: &mut <Self as ::fayalite::ty::Type>::SimValue,
bits: &::fayalite::__bitvec::slice::BitSlice,
) {
let v = ::fayalite::enum_::EnumSimValueFromBits::new(*self, bits);
match v.discriminant() {
#(#sim_value_clone_from_bits_match_arms)*
}
}
fn sim_value_to_bits(
&self,
value: &<Self as ::fayalite::ty::Type>::SimValue,
bits: &mut ::fayalite::__bitvec::slice::BitSlice,
) {
let v = ::fayalite::enum_::EnumSimValueToBits::new(*self, bits);
match value {
#(#sim_value_to_bits_match_arms)*
}
}
}
#[automatically_derived]
impl #impl_generics ::fayalite::enum_::EnumType for #target #type_generics

View file

@ -377,7 +377,7 @@ impl ModuleFn {
module_kind,
vis,
sig,
block,
mut block,
struct_generics,
the_struct,
} = match self.0 {
@ -439,6 +439,12 @@ impl ModuleFn {
body_sig
.inputs
.insert(0, parse_quote! { m: &::fayalite::module::ModuleBuilder });
block.stmts.insert(
0,
parse_quote! {
let _ = m;
},
);
let body_fn = ItemFn {
attrs: vec![],
vis: Visibility::Inherited,

View file

@ -1,6 +1,8 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use bitvec::slice::BitSlice;
use crate::{
expr::{
ops::{ArrayLiteral, ExprFromIterator, ExprIntoIterator, ExprPartialEq},
@ -9,6 +11,7 @@ use crate::{
int::{Bool, DynSize, KnownSize, Size, SizeType, DYN_SIZE},
intern::{Intern, Interned, LazyInterned},
module::transform::visit::{Fold, Folder, Visit, Visitor},
sim::value::{SimValue, SimValuePartialEq},
source_location::SourceLocation,
ty::{
CanonicalType, MatchVariantWithoutScope, StaticType, Type, TypeProperties, TypeWithDeref,
@ -142,6 +145,7 @@ impl<T: Type + Visit<State>, Len: Size, State: Visitor + ?Sized> Visit<State>
impl<T: Type, Len: Size> Type for ArrayType<T, Len> {
type BaseType = Array;
type MaskType = ArrayType<T::MaskType, Len>;
type SimValue = Len::ArraySimValue<T>;
type MatchVariant = Len::ArrayMatch<T>;
type MatchActiveScope = ();
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Len::ArrayMatch<T>>;
@ -178,9 +182,48 @@ impl<T: Type, Len: Size> Type for ArrayType<T, Len> {
Len::from_usize(array.len()),
)
}
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), self.type_properties.bit_width);
let element = self.element();
let element_bit_width = element.canonical().bit_width();
TryFrom::try_from(Vec::from_iter((0..self.len()).map(|i| {
SimValue::from_bitslice(element, &bits[i * element_bit_width..][..element_bit_width])
})))
.ok()
.expect("used correct length")
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), self.type_properties.bit_width);
let element_ty = self.element();
let element_bit_width = element_ty.canonical().bit_width();
let value: &mut [SimValue<T>] = value.as_mut();
assert_eq!(self.len(), value.len());
for (i, element_value) in value.iter_mut().enumerate() {
assert_eq!(SimValue::ty(element_value), element_ty);
SimValue::bits_mut(element_value)
.bits_mut()
.copy_from_bitslice(&bits[i * element_bit_width..][..element_bit_width]);
}
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), self.type_properties.bit_width);
let element_ty = self.element();
let element_bit_width = element_ty.canonical().bit_width();
let value: &[SimValue<T>] = value.as_ref();
assert_eq!(self.len(), value.len());
for (i, element_value) in value.iter().enumerate() {
assert_eq!(SimValue::ty(element_value), element_ty);
bits[i * element_bit_width..][..element_bit_width]
.copy_from_bitslice(SimValue::bits(element_value).bits());
}
}
}
impl<T: Type, Len: Size> TypeWithDeref for ArrayType<T, Len> {
@ -247,6 +290,18 @@ where
}
}
impl<Lhs: Type, Rhs: Type, Len: Size> SimValuePartialEq<ArrayType<Rhs, Len>> for ArrayType<Lhs, Len>
where
Lhs: SimValuePartialEq<Rhs>,
{
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<ArrayType<Rhs, Len>>) -> bool {
AsRef::<[_]>::as_ref(&**this)
.iter()
.zip(AsRef::<[_]>::as_ref(&**other))
.all(|(l, r)| SimValuePartialEq::sim_value_eq(l, r))
}
}
impl<T: Type, Len: Size> ExprIntoIterator for ArrayType<T, Len> {
type Item = T;
type ExprIntoIter = ExprArrayIter<T, Len>;

View file

@ -8,14 +8,14 @@ use crate::{
},
int::{Bool, DynSize},
intern::{Intern, Interned},
sim::{SimValue, ToSimValue},
sim::value::{SimValue, SimValuePartialEq, ToSimValue},
source_location::SourceLocation,
ty::{
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, StaticType, Type,
TypeProperties, TypeWithDeref,
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, OpaqueSimValue,
StaticType, Type, TypeProperties, TypeWithDeref,
},
};
use bitvec::vec::BitVec;
use bitvec::{slice::BitSlice, vec::BitVec};
use hashbrown::HashMap;
use std::{fmt, marker::PhantomData};
@ -216,6 +216,7 @@ impl Bundle {
impl Type for Bundle {
type BaseType = Bundle;
type MaskType = Bundle;
type SimValue = OpaqueSimValue;
impl_match_variant_as_self!();
fn mask_type(&self) -> Self::MaskType {
Self::new(Interned::from_iter(self.0.fields.into_iter().map(
@ -239,6 +240,20 @@ impl Type for Bundle {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), self.type_properties().bit_width);
OpaqueSimValue::from_bitslice(bits)
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), self.type_properties().bit_width);
assert_eq!(value.bit_width(), self.type_properties().bit_width);
value.bits_mut().bits_mut().copy_from_bitslice(bits);
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), self.type_properties().bit_width);
assert_eq!(value.bit_width(), self.type_properties().bit_width);
bits.copy_from_bitslice(value.bits().bits());
}
}
pub trait BundleType: Type<BaseType = Bundle> {
@ -247,6 +262,93 @@ pub trait BundleType: Type<BaseType = Bundle> {
fn fields(&self) -> Interned<[BundleField]>;
}
pub struct BundleSimValueFromBits<'a> {
fields: std::slice::Iter<'static, BundleField>,
bits: &'a BitSlice,
}
impl<'a> BundleSimValueFromBits<'a> {
#[track_caller]
pub fn new<T: BundleType>(bundle_ty: T, bits: &'a BitSlice) -> Self {
let fields = bundle_ty.fields();
assert_eq!(
bits.len(),
fields
.iter()
.map(|BundleField { ty, .. }| ty.bit_width())
.sum::<usize>()
);
Self {
fields: Interned::into_inner(fields).iter(),
bits,
}
}
#[track_caller]
fn field_ty_and_bits<T: Type>(&mut self) -> (T, &'a BitSlice) {
let Some(&BundleField {
name: _,
flipped: _,
ty,
}) = self.fields.next()
else {
panic!("tried to read too many fields from BundleSimValueFromBits");
};
let (field_bits, rest) = self.bits.split_at(ty.bit_width());
self.bits = rest;
(T::from_canonical(ty), field_bits)
}
#[track_caller]
pub fn field_from_bits<T: Type>(&mut self) -> SimValue<T> {
let (field_ty, field_bits) = self.field_ty_and_bits::<T>();
SimValue::from_bitslice(field_ty, field_bits)
}
#[track_caller]
pub fn field_clone_from_bits<T: Type>(&mut self, field_value: &mut SimValue<T>) {
let (field_ty, field_bits) = self.field_ty_and_bits::<T>();
assert_eq!(field_ty, SimValue::ty(field_value));
SimValue::bits_mut(field_value)
.bits_mut()
.copy_from_bitslice(field_bits);
}
}
pub struct BundleSimValueToBits<'a> {
fields: std::slice::Iter<'static, BundleField>,
bits: &'a mut BitSlice,
}
impl<'a> BundleSimValueToBits<'a> {
#[track_caller]
pub fn new<T: BundleType>(bundle_ty: T, bits: &'a mut BitSlice) -> Self {
let fields = bundle_ty.fields();
assert_eq!(
bits.len(),
fields
.iter()
.map(|BundleField { ty, .. }| ty.bit_width())
.sum::<usize>()
);
Self {
fields: Interned::into_inner(fields).iter(),
bits,
}
}
#[track_caller]
pub fn field_to_bits<T: Type>(&mut self, field_value: &SimValue<T>) {
let Some(&BundleField {
name: _,
flipped: _,
ty,
}) = self.fields.next()
else {
panic!("tried to read too many fields from BundleSimValueFromBits");
};
assert_eq!(T::from_canonical(ty), SimValue::ty(field_value));
self.bits[..ty.bit_width()].copy_from_bitslice(SimValue::bits(field_value).bits());
self.bits = &mut std::mem::take(&mut self.bits)[ty.bit_width()..];
}
}
#[derive(Default)]
pub struct NoBuilder;
@ -353,6 +455,7 @@ macro_rules! impl_tuples {
impl<$($T: Type,)*> Type for ($($T,)*) {
type BaseType = Bundle;
type MaskType = ($($T::MaskType,)*);
type SimValue = ($(SimValue<$T>,)*);
type MatchVariant = ($(Expr<$T>,)*);
type MatchActiveScope = ();
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
@ -391,6 +494,24 @@ macro_rules! impl_tuples {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
#![allow(unused_mut, unused_variables)]
let mut v = BundleSimValueFromBits::new(*self, bits);
$(let $var = v.field_from_bits();)*
($($var,)*)
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
#![allow(unused_mut, unused_variables)]
let mut v = BundleSimValueFromBits::new(*self, bits);
let ($($var,)*) = value;
$(v.field_clone_from_bits($var);)*
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
#![allow(unused_mut, unused_variables)]
let mut v = BundleSimValueToBits::new(*self, bits);
let ($($var,)*) = value;
$(v.field_to_bits($var);)*
}
}
impl<$($T: Type,)*> BundleType for ($($T,)*) {
type Builder = TupleBuilder<($(Unfilled<$T>,)*)>;
@ -444,16 +565,12 @@ macro_rules! impl_tuples {
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<CanonicalType> for ($($T,)*) {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
ToSimValue::<Bundle>::to_sim_value(self, Bundle::from_canonical(ty)).into_canonical()
SimValue::into_canonical(ToSimValue::<Bundle>::to_sim_value(self, Bundle::from_canonical(ty)))
}
#[track_caller]
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType>
{
ToSimValue::<Bundle>::into_sim_value(self, Bundle::from_canonical(ty)).into_canonical()
}
#[track_caller]
fn box_into_sim_value(self: Box<Self>, ty: CanonicalType) -> SimValue<CanonicalType> {
ToSimValue::<Bundle>::box_into_sim_value(self, Bundle::from_canonical(ty)).into_canonical()
SimValue::into_canonical(ToSimValue::<Bundle>::into_sim_value(self, Bundle::from_canonical(ty)))
}
}
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<Bundle> for ($($T,)*) {
@ -474,24 +591,12 @@ macro_rules! impl_tuples {
let [$($ty_var,)*] = *ty.fields() else {
panic!("bundle has wrong number of fields");
};
let mut bits: Option<BitVec> = None;
let mut bits = BitVec::new();
$(let $var = $var.into_sim_value($ty_var.ty);
assert_eq!($var.ty(), $ty_var.ty);
if !$var.bits().is_empty() {
if let Some(bits) = &mut bits {
bits.extend_from_bitslice($var.bits());
} else {
let mut $var = $var.into_bits();
$var.reserve(ty.type_properties().bit_width - $var.len());
bits = Some($var);
}
}
assert_eq!(SimValue::ty(&$var), $ty_var.ty);
bits.extend_from_bitslice(SimValue::bits(&$var).bits());
)*
bits.unwrap_or_else(BitVec::new).into_sim_value(ty)
}
#[track_caller]
fn box_into_sim_value(self: Box<Self>, ty: Bundle) -> SimValue<Bundle> {
Self::into_sim_value(*self, ty)
bits.into_sim_value(ty)
}
}
impl<$($T: ToSimValue<$Ty>, $Ty: Type,)*> ToSimValue<($($Ty,)*)> for ($($T,)*) {
@ -499,19 +604,15 @@ macro_rules! impl_tuples {
fn to_sim_value(&self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
let ($($var,)*) = self;
let ($($ty_var,)*) = ty;
$(let $var = $var.to_sim_value($ty_var).into_canonical();)*
SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical()))
$(let $var = $var.to_sim_value($ty_var);)*
SimValue::from_value(ty, ($($var,)*))
}
#[track_caller]
fn into_sim_value(self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
let ($($var,)*) = self;
let ($($ty_var,)*) = ty;
$(let $var = $var.into_sim_value($ty_var).into_canonical();)*
SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical()))
}
#[track_caller]
fn box_into_sim_value(self: Box<Self>, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
Self::into_sim_value(*self, ty)
$(let $var = $var.into_sim_value($ty_var);)*
SimValue::from_value(ty, ($($var,)*))
}
}
impl<$($Lhs: Type + ExprPartialEq<$Rhs>, $Rhs: Type,)*> ExprPartialEq<($($Rhs,)*)> for ($($Lhs,)*) {
@ -537,6 +638,15 @@ macro_rules! impl_tuples {
.any_one_bits()
}
}
impl<$($Lhs: SimValuePartialEq<$Rhs>, $Rhs: Type,)*> SimValuePartialEq<($($Rhs,)*)> for ($($Lhs,)*) {
fn sim_value_eq(lhs: &SimValue<Self>, rhs: &SimValue<($($Rhs,)*)>) -> bool {
let ($($lhs_var,)*) = &**lhs;
let ($($rhs_var,)*) = &**rhs;
let retval = true;
$(let retval = retval && $lhs_var == $rhs_var;)*
retval
}
}
};
([$($lhs:tt)*] [$rhs_first:tt $($rhs:tt)*]) => {
impl_tuples!([$($lhs)*] []);
@ -564,6 +674,7 @@ impl_tuples! {
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
type BaseType = Bundle;
type MaskType = ();
type SimValue = ();
type MatchVariant = PhantomData<T>;
type MatchActiveScope = ();
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
@ -596,6 +707,16 @@ impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert!(bits.is_empty());
()
}
fn sim_value_clone_from_bits(&self, _value: &mut Self::SimValue, bits: &BitSlice) {
assert!(bits.is_empty());
}
fn sim_value_to_bits(&self, _value: &Self::SimValue, bits: &mut BitSlice) {
assert!(bits.is_empty());
}
}
pub struct PhantomDataBuilder<T: ?Sized + Send + Sync + 'static>(PhantomData<T>);
@ -663,6 +784,6 @@ impl<T: ?Sized> ToSimValue<CanonicalType> for PhantomData<T> {
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
let ty = Bundle::from_canonical(ty);
assert!(ty.fields().is_empty());
ToSimValue::into_sim_value(BitVec::new(), ty).into_canonical()
SimValue::into_canonical(ToSimValue::into_sim_value(BitVec::new(), ty))
}
}

View file

@ -8,6 +8,7 @@ use crate::{
source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
};
use bitvec::slice::BitSlice;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct Clock;
@ -15,6 +16,7 @@ pub struct Clock;
impl Type for Clock {
type BaseType = Clock;
type MaskType = Bool;
type SimValue = bool;
impl_match_variant_as_self!();
@ -36,6 +38,21 @@ impl Type for Clock {
};
retval
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), 1);
bits[0]
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), 1);
*value = bits[0];
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), 1);
bits.set(0, *value);
}
}
impl Clock {

View file

@ -7,17 +7,22 @@ use crate::{
Expr, ToExpr,
},
hdl,
int::Bool,
int::{Bool, UIntValue},
intern::{Intern, Interned},
module::{
connect, enum_match_variants_helper, incomplete_wire, wire,
EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope,
},
sim::value::{SimValue, SimValuePartialEq},
source_location::SourceLocation,
ty::{CanonicalType, MatchVariantAndInactiveScope, StaticType, Type, TypeProperties},
ty::{
CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, StaticType, Type,
TypeProperties,
},
};
use bitvec::{order::Lsb0, slice::BitSlice, view::BitView};
use hashbrown::HashMap;
use std::{convert::Infallible, fmt, iter::FusedIterator};
use std::{convert::Infallible, fmt, iter::FusedIterator, sync::Arc};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct EnumVariant {
@ -152,6 +157,12 @@ impl EnumTypePropertiesBuilder {
variant_count: variant_count + 1,
}
}
#[must_use]
pub fn variants(self, variants: impl IntoIterator<Item = EnumVariant>) -> Self {
variants.into_iter().fold(self, |this, variant| {
this.variant(variant.ty.map(CanonicalType::type_properties))
})
}
pub const fn finish(self) -> TypeProperties {
assert!(
self.variant_count != 0,
@ -325,6 +336,7 @@ impl EnumType for Enum {
impl Type for Enum {
type BaseType = Enum;
type MaskType = Bool;
type SimValue = OpaqueSimValue;
type MatchVariant = Option<Expr<CanonicalType>>;
type MatchActiveScope = Scope;
type MatchVariantAndInactiveScope = EnumMatchVariantAndInactiveScope<Self>;
@ -355,6 +367,296 @@ impl Type for Enum {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), self.type_properties().bit_width);
OpaqueSimValue::from_bitslice(bits)
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), self.type_properties().bit_width);
assert_eq!(value.bit_width(), self.type_properties().bit_width);
value.bits_mut().bits_mut().copy_from_bitslice(bits);
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), self.type_properties().bit_width);
assert_eq!(value.bit_width(), self.type_properties().bit_width);
bits.copy_from_bitslice(value.bits().bits());
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
pub struct EnumPaddingSimValue {
bits: Option<UIntValue>,
}
impl EnumPaddingSimValue {
pub fn bit_width(&self) -> Option<usize> {
self.bits.as_ref().map(UIntValue::width)
}
pub fn bits(&self) -> &Option<UIntValue> {
&self.bits
}
pub fn bits_mut(&mut self) -> &mut Option<UIntValue> {
&mut self.bits
}
pub fn into_bits(self) -> Option<UIntValue> {
self.bits
}
pub fn from_bits(bits: Option<UIntValue>) -> Self {
Self { bits }
}
pub fn from_bitslice(v: &BitSlice) -> Self {
Self {
bits: Some(UIntValue::new(Arc::new(v.to_bitvec()))),
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct UnknownVariantSimValue {
discriminant: usize,
body_bits: UIntValue,
}
impl UnknownVariantSimValue {
pub fn discriminant(&self) -> usize {
self.discriminant
}
pub fn body_bits(&self) -> &UIntValue {
&self.body_bits
}
pub fn body_bits_mut(&mut self) -> &mut UIntValue {
&mut self.body_bits
}
pub fn into_body_bits(self) -> UIntValue {
self.body_bits
}
pub fn into_parts(self) -> (usize, UIntValue) {
(self.discriminant, self.body_bits)
}
pub fn new(discriminant: usize, body_bits: UIntValue) -> Self {
Self {
discriminant,
body_bits,
}
}
}
pub struct EnumSimValueFromBits<'a> {
variants: Interned<[EnumVariant]>,
discriminant: usize,
body_bits: &'a BitSlice,
}
impl<'a> EnumSimValueFromBits<'a> {
#[track_caller]
pub fn new<T: EnumType>(ty: T, bits: &'a BitSlice) -> Self {
let variants = ty.variants();
let bit_width = EnumTypePropertiesBuilder::new()
.variants(variants)
.finish()
.bit_width;
assert_eq!(bit_width, bits.len());
let (discriminant_bits, body_bits) =
bits.split_at(discriminant_bit_width_impl(variants.len()));
let mut discriminant = 0usize;
discriminant.view_bits_mut::<Lsb0>()[..discriminant_bits.len()]
.copy_from_bitslice(discriminant_bits);
Self {
variants,
discriminant,
body_bits,
}
}
pub fn discriminant(&self) -> usize {
self.discriminant
}
#[track_caller]
#[cold]
fn usage_error(&self, clone: bool) -> ! {
let clone = if clone { "clone_" } else { "" };
match self.variants.get(self.discriminant) {
None => {
panic!("should have called EnumSimValueFromBits::unknown_variant_{clone}from_bits");
}
Some(EnumVariant { ty: None, .. }) => {
panic!(
"should have called EnumSimValueFromBits::variant_no_field_{clone}from_bits"
);
}
Some(EnumVariant { ty: Some(_), .. }) => {
panic!(
"should have called EnumSimValueFromBits::variant_with_field_{clone}from_bits"
);
}
}
}
#[track_caller]
fn known_variant(&self, clone: bool) -> (Option<CanonicalType>, &'a BitSlice, &'a BitSlice) {
let Some(EnumVariant { ty, .. }) = self.variants.get(self.discriminant) else {
self.usage_error(clone);
};
let variant_bit_width = ty.map_or(0, CanonicalType::bit_width);
let (variant_bits, padding_bits) = self.body_bits.split_at(variant_bit_width);
(*ty, variant_bits, padding_bits)
}
#[track_caller]
pub fn unknown_variant_from_bits(self) -> UnknownVariantSimValue {
let None = self.variants.get(self.discriminant) else {
self.usage_error(false);
};
UnknownVariantSimValue::new(
self.discriminant,
UIntValue::new(Arc::new(self.body_bits.to_bitvec())),
)
}
#[track_caller]
pub fn unknown_variant_clone_from_bits(self, value: &mut UnknownVariantSimValue) {
let None = self.variants.get(self.discriminant) else {
self.usage_error(true);
};
value.discriminant = self.discriminant;
assert_eq!(value.body_bits.width(), self.body_bits.len());
value
.body_bits
.bits_mut()
.copy_from_bitslice(self.body_bits);
}
#[track_caller]
pub fn variant_no_field_from_bits(self) -> EnumPaddingSimValue {
let (None, _variant_bits, padding_bits) = self.known_variant(false) else {
self.usage_error(false);
};
EnumPaddingSimValue::from_bitslice(padding_bits)
}
#[track_caller]
pub fn variant_with_field_from_bits<T: Type>(self) -> (SimValue<T>, EnumPaddingSimValue) {
let (Some(variant_ty), variant_bits, padding_bits) = self.known_variant(false) else {
self.usage_error(false);
};
(
SimValue::from_bitslice(T::from_canonical(variant_ty), variant_bits),
EnumPaddingSimValue::from_bitslice(padding_bits),
)
}
#[track_caller]
fn clone_padding_from_bits(padding: &mut EnumPaddingSimValue, padding_bits: &BitSlice) {
match padding.bits_mut() {
None => *padding = EnumPaddingSimValue::from_bitslice(padding_bits),
Some(padding) => {
assert_eq!(padding.width(), padding_bits.len());
padding.bits_mut().copy_from_bitslice(padding_bits);
}
}
}
#[track_caller]
pub fn variant_no_field_clone_from_bits(self, padding: &mut EnumPaddingSimValue) {
let (None, _variant_bits, padding_bits) = self.known_variant(true) else {
self.usage_error(true);
};
Self::clone_padding_from_bits(padding, padding_bits);
}
#[track_caller]
pub fn variant_with_field_clone_from_bits<T: Type>(
self,
value: &mut SimValue<T>,
padding: &mut EnumPaddingSimValue,
) {
let (Some(variant_ty), variant_bits, padding_bits) = self.known_variant(true) else {
self.usage_error(true);
};
assert_eq!(SimValue::ty(value), T::from_canonical(variant_ty));
SimValue::bits_mut(value)
.bits_mut()
.copy_from_bitslice(variant_bits);
Self::clone_padding_from_bits(padding, padding_bits);
}
}
pub struct EnumSimValueToBits<'a> {
variants: Interned<[EnumVariant]>,
bit_width: usize,
discriminant_bit_width: usize,
bits: &'a mut BitSlice,
}
impl<'a> EnumSimValueToBits<'a> {
#[track_caller]
pub fn new<T: EnumType>(ty: T, bits: &'a mut BitSlice) -> Self {
let variants = ty.variants();
let bit_width = EnumTypePropertiesBuilder::new()
.variants(variants)
.finish()
.bit_width;
assert_eq!(bit_width, bits.len());
Self {
variants,
bit_width,
discriminant_bit_width: discriminant_bit_width_impl(variants.len()),
bits,
}
}
#[track_caller]
fn discriminant_to_bits(&mut self, mut discriminant: usize) {
let orig_discriminant = discriminant;
let discriminant_bits =
&mut discriminant.view_bits_mut::<Lsb0>()[..self.discriminant_bit_width];
self.bits[..self.discriminant_bit_width].copy_from_bitslice(discriminant_bits);
discriminant_bits.fill(false);
assert!(
discriminant == 0,
"{orig_discriminant:#x} is too big to fit in enum discriminant bits",
);
}
#[track_caller]
pub fn unknown_variant_to_bits(mut self, value: &UnknownVariantSimValue) {
self.discriminant_to_bits(value.discriminant);
let None = self.variants.get(value.discriminant) else {
panic!("can't use UnknownVariantSimValue to set known discriminant");
};
assert_eq!(
self.bit_width - self.discriminant_bit_width,
value.body_bits.width()
);
self.bits[self.discriminant_bit_width..].copy_from_bitslice(value.body_bits.bits());
}
#[track_caller]
fn known_variant(
mut self,
discriminant: usize,
padding: &EnumPaddingSimValue,
) -> (Option<CanonicalType>, &'a mut BitSlice) {
self.discriminant_to_bits(discriminant);
let variant_ty = self.variants[discriminant].ty;
let variant_bit_width = variant_ty.map_or(0, CanonicalType::bit_width);
let padding_bits = &mut self.bits[self.discriminant_bit_width..][variant_bit_width..];
if let Some(padding) = padding.bits() {
assert_eq!(padding.width(), padding_bits.len());
padding_bits.copy_from_bitslice(padding.bits());
} else {
padding_bits.fill(false);
}
let variant_bits = &mut self.bits[self.discriminant_bit_width..][..variant_bit_width];
(variant_ty, variant_bits)
}
#[track_caller]
pub fn variant_no_field_to_bits(self, discriminant: usize, padding: &EnumPaddingSimValue) {
let (None, _variant_bits) = self.known_variant(discriminant, padding) else {
panic!("expected variant to have no field");
};
}
#[track_caller]
pub fn variant_with_field_to_bits<T: Type>(
self,
discriminant: usize,
value: &SimValue<T>,
padding: &EnumPaddingSimValue,
) {
let (Some(variant_ty), variant_bits) = self.known_variant(discriminant, padding) else {
panic!("expected variant to have a field");
};
assert_eq!(SimValue::ty(value), T::from_canonical(variant_ty));
variant_bits.copy_from_bitslice(SimValue::bits(value).bits());
}
}
#[hdl]
@ -417,6 +719,25 @@ impl<Lhs: Type + ExprPartialEq<Rhs>, Rhs: Type> ExprPartialEq<HdlOption<Rhs>> fo
}
}
impl<Lhs: SimValuePartialEq<Rhs>, Rhs: Type> SimValuePartialEq<HdlOption<Rhs>> for HdlOption<Lhs> {
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<HdlOption<Rhs>>) -> bool {
type SimValueMatch<T> = <T as Type>::SimValue;
match (&**this, &**other) {
(SimValueMatch::<Self>::HdlNone(_), SimValueMatch::<HdlOption<Rhs>>::HdlNone(_)) => {
true
}
(SimValueMatch::<Self>::HdlSome(..), SimValueMatch::<HdlOption<Rhs>>::HdlNone(_))
| (SimValueMatch::<Self>::HdlNone(_), SimValueMatch::<HdlOption<Rhs>>::HdlSome(..)) => {
false
}
(
SimValueMatch::<Self>::HdlSome(l, _),
SimValueMatch::<HdlOption<Rhs>>::HdlSome(r, _),
) => l == r,
}
}
}
#[allow(non_snake_case)]
pub fn HdlNone<T: StaticType>() -> Expr<HdlOption<T>> {
HdlOption[T::TYPE].HdlNone()

View file

@ -700,6 +700,7 @@ impl<T: ToExpr + ?Sized> CastToBits for T {
}
pub trait CastBitsTo {
#[track_caller]
fn cast_bits_to<T: Type>(&self, ty: T) -> Expr<T>;
}

View file

@ -2258,6 +2258,7 @@ impl<'a> Exporter<'a> {
ModuleBody::Extern(ExternModuleBody {
verilog_name,
parameters,
simulation: _,
}) => {
let verilog_name = Ident(verilog_name);
writeln!(body, "{indent}defname = {verilog_name}").unwrap();

View file

@ -7,6 +7,7 @@ use crate::{
Expr, NotALiteralExpr, ToExpr, ToLiteralBits,
},
intern::{Intern, Interned, Memoize},
sim::value::SimValue,
source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
util::{interned_bit, ConstBool, ConstUsize, GenericConstBool, GenericConstUsize},
@ -49,6 +50,15 @@ pub trait KnownSize:
+ IntoIterator<Item = Expr<Element>>
+ TryFrom<Vec<Expr<Element>>>
+ Into<Vec<Expr<Element>>>;
type ArraySimValue<Element: Type>: AsRef<[SimValue<Element>]>
+ AsMut<[SimValue<Element>]>
+ BorrowMut<[SimValue<Element>]>
+ 'static
+ Clone
+ std::fmt::Debug
+ IntoIterator<Item = SimValue<Element>>
+ TryFrom<Vec<SimValue<Element>>>
+ Into<Vec<SimValue<Element>>>;
}
macro_rules! known_widths {
@ -60,6 +70,7 @@ macro_rules! known_widths {
}> {
const SIZE: Self = Self;
type ArrayMatch<Element: Type> = [Expr<Element>; Self::VALUE];
type ArraySimValue<Element: Type> = [SimValue<Element>; Self::VALUE];
}
};
([2 $($rest:tt)*] $($bits:literal)+) => {
@ -72,6 +83,7 @@ macro_rules! known_widths {
impl KnownSize for ConstUsize<{2 $(* $rest)*}> {
const SIZE: Self = Self;
type ArrayMatch<Element: Type> = [Expr<Element>; Self::VALUE];
type ArraySimValue<Element: Type> = [SimValue<Element>; Self::VALUE];
}
};
}
@ -100,6 +112,15 @@ pub trait Size:
+ IntoIterator<Item = Expr<Element>>
+ TryFrom<Vec<Expr<Element>>>
+ Into<Vec<Expr<Element>>>;
type ArraySimValue<Element: Type>: AsRef<[SimValue<Element>]>
+ AsMut<[SimValue<Element>]>
+ BorrowMut<[SimValue<Element>]>
+ 'static
+ Clone
+ std::fmt::Debug
+ IntoIterator<Item = SimValue<Element>>
+ TryFrom<Vec<SimValue<Element>>>
+ Into<Vec<SimValue<Element>>>;
const KNOWN_VALUE: Option<usize>;
type SizeType: SizeType<Size = Self>
+ Copy
@ -125,6 +146,7 @@ impl SizeType for usize {
impl Size for DynSize {
type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
type ArraySimValue<Element: Type> = Box<[SimValue<Element>]>;
const KNOWN_VALUE: Option<usize> = None;
type SizeType = usize;
@ -147,6 +169,7 @@ impl<T: KnownSize> SizeType for T {
impl<T: KnownSize> Size for T {
type ArrayMatch<Element: Type> = <T as KnownSize>::ArrayMatch<Element>;
type ArraySimValue<Element: Type> = <T as KnownSize>::ArraySimValue<Element>;
const KNOWN_VALUE: Option<usize> = Some(T::VALUE);
@ -287,6 +310,7 @@ macro_rules! impl_int {
impl<Width: Size> Type for $name<Width> {
type BaseType = $pretty_name;
type MaskType = Bool;
type SimValue = $value<Width>;
impl_match_variant_as_self!();
fn mask_type(&self) -> Self::MaskType {
Bool
@ -306,6 +330,20 @@ macro_rules! impl_int {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), self.width());
$value::new(Arc::new(bits.to_bitvec()))
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), self.width());
assert_eq!(value.width(), self.width());
value.bits_mut().copy_from_bitslice(bits);
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), self.width());
assert_eq!(value.width(), self.width());
bits.copy_from_bitslice(value.bits());
}
}
impl<Width: KnownSize> StaticType for $name<Width> {
@ -331,7 +369,7 @@ macro_rules! impl_int {
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
#[derive(Clone, Eq, Hash)]
pub struct $value<Width: Size = DynSize> {
bits: Arc<BitVec>,
_phantom: PhantomData<Width>,
@ -351,9 +389,15 @@ macro_rules! impl_int {
}
}
impl<Width: Size> PartialOrd for $value<Width> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
impl<LhsWidth: Size, RhsWidth: Size> PartialEq<$value<RhsWidth>> for $value<LhsWidth> {
fn eq(&self, other: &$value<RhsWidth>) -> bool {
self.to_bigint() == other.to_bigint()
}
}
impl<LhsWidth: Size, RhsWidth: Size> PartialOrd<$value<RhsWidth>> for $value<LhsWidth> {
fn partial_cmp(&self, other: &$value<RhsWidth>) -> Option<std::cmp::Ordering> {
Some(self.to_bigint().cmp(&other.to_bigint()))
}
}
@ -401,6 +445,9 @@ macro_rules! impl_int {
pub fn bits(&self) -> &Arc<BitVec> {
&self.bits
}
pub fn bits_mut(&mut self) -> &mut BitSlice {
Arc::<BitVec>::make_mut(&mut self.bits)
}
}
impl<Width: Size> ToLiteralBits for $value<Width> {
@ -621,6 +668,12 @@ pub trait BoolOrIntType: Type + sealed::BoolOrIntTypeSealed {
let bitslice = &BitSlice::<u8, Lsb0>::from_slice(&bytes)[..width];
bits.clone_from_bitslice(bitslice);
}
fn bits_equal_bigint_wrapping(v: &BigInt, bits: &BitSlice) -> bool {
bits.iter()
.by_vals()
.enumerate()
.all(|(bit_index, bit): (usize, bool)| v.bit(bit_index as u64) == bit)
}
fn bits_to_bigint(bits: &BitSlice) -> BigInt {
let sign_byte = if Self::Signed::VALUE && bits.last().as_deref().copied().unwrap_or(false) {
0xFF
@ -742,6 +795,7 @@ impl Bool {
impl Type for Bool {
type BaseType = Bool;
type MaskType = Bool;
type SimValue = bool;
impl_match_variant_as_self!();
fn mask_type(&self) -> Self::MaskType {
Bool
@ -759,6 +813,18 @@ impl Type for Bool {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), 1);
bits[0]
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), 1);
*value = bits[0];
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), 1);
bits.set(0, *value);
}
}
impl StaticType for Bool {

View file

@ -8,6 +8,8 @@
extern crate self as fayalite;
#[doc(hidden)]
pub use bitvec as __bitvec;
#[doc(hidden)]
pub use std as __std;

View file

@ -21,6 +21,7 @@ use crate::{
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
reg::Reg,
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
sim::{ExternModuleSimGenerator, ExternModuleSimulation},
source_location::SourceLocation,
ty::{CanonicalType, Type},
util::ScopedRef,
@ -33,6 +34,7 @@ use std::{
collections::VecDeque,
convert::Infallible,
fmt,
future::IntoFuture,
hash::{Hash, Hasher},
iter::FusedIterator,
marker::PhantomData,
@ -1081,6 +1083,7 @@ pub struct ExternModuleBody<
> {
pub verilog_name: Interned<str>,
pub parameters: P,
pub simulation: Option<ExternModuleSimulation>,
}
impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
@ -1088,11 +1091,13 @@ impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
let ExternModuleBody {
verilog_name,
parameters,
simulation,
} = value;
let parameters = Intern::intern_owned(parameters);
Self {
verilog_name,
parameters,
simulation,
}
}
}
@ -1283,10 +1288,12 @@ impl<T: BundleType> fmt::Debug for DebugModuleBody<T> {
ModuleBody::Extern(ExternModuleBody {
verilog_name,
parameters,
simulation,
}) => {
debug_struct
.field("verilog_name", verilog_name)
.field("parameters", parameters);
.field("parameters", parameters)
.field("simulation", simulation);
}
}
debug_struct.finish_non_exhaustive()
@ -1761,6 +1768,7 @@ impl AssertValidityState {
ModuleBody::Extern(ExternModuleBody {
verilog_name: _,
parameters: _,
simulation: _,
}) => {}
ModuleBody::Normal(NormalModuleBody { body }) => {
let body = self.make_block_index(body);
@ -2108,6 +2116,7 @@ impl ModuleBuilder {
ModuleKind::Extern => ModuleBody::Extern(ExternModuleBody {
verilog_name: name.0,
parameters: vec![],
simulation: None,
}),
ModuleKind::Normal => ModuleBody::Normal(NormalModuleBody {
body: BuilderModuleBody {
@ -2174,6 +2183,7 @@ impl ModuleBuilder {
.builder_extern_body()
.verilog_name = name.intern();
}
#[track_caller]
pub fn parameter(&self, name: impl AsRef<str>, value: ExternModuleParameterValue) {
let name = name.as_ref();
self.impl_
@ -2186,6 +2196,7 @@ impl ModuleBuilder {
value,
});
}
#[track_caller]
pub fn parameter_int(&self, name: impl AsRef<str>, value: impl Into<BigInt>) {
let name = name.as_ref();
let value = value.into();
@ -2199,6 +2210,7 @@ impl ModuleBuilder {
value: ExternModuleParameterValue::Integer(value),
});
}
#[track_caller]
pub fn parameter_str(&self, name: impl AsRef<str>, value: impl AsRef<str>) {
let name = name.as_ref();
let value = value.as_ref();
@ -2212,6 +2224,7 @@ impl ModuleBuilder {
value: ExternModuleParameterValue::String(value.intern()),
});
}
#[track_caller]
pub fn parameter_raw_verilog(&self, name: impl AsRef<str>, raw_verilog: impl AsRef<str>) {
let name = name.as_ref();
let raw_verilog = raw_verilog.as_ref();
@ -2225,6 +2238,26 @@ impl ModuleBuilder {
value: ExternModuleParameterValue::RawVerilog(raw_verilog.intern()),
});
}
#[track_caller]
pub fn extern_module_simulation<G: ExternModuleSimGenerator>(&self, generator: G) {
let mut impl_ = self.impl_.borrow_mut();
let simulation = &mut impl_.body.builder_extern_body().simulation;
if simulation.is_some() {
panic!("already added an extern module simulation");
}
*simulation = Some(ExternModuleSimulation::new(generator));
}
#[track_caller]
pub fn extern_module_simulation_fn<
Args: fmt::Debug + Clone + Hash + Eq + Send + Sync + 'static,
Fut: IntoFuture<Output = ()> + 'static,
>(
&self,
args: Args,
f: fn(Args, crate::sim::ExternModuleSimulationState) -> Fut,
) {
self.extern_module_simulation(crate::sim::SimGeneratorFn { args, f });
}
}
#[track_caller]

View file

@ -31,6 +31,7 @@ use crate::{
phantom_const::PhantomConst,
reg::Reg,
reset::{AsyncReset, Reset, ResetType, SyncReset},
sim::ExternModuleSimulation,
source_location::SourceLocation,
ty::{CanonicalType, Type},
wire::Wire,

View file

@ -1,10 +1,17 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use bitvec::slice::BitSlice;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
expr::{
ops::{ExprPartialEq, ExprPartialOrd},
Expr, ToExpr,
},
int::Bool,
intern::{Intern, Interned, InternedCompare, LazyInterned, Memoize},
sim::value::{SimValue, SimValuePartialEq},
source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
};
@ -84,7 +91,7 @@ impl<'de> Deserialize<'de> for PhantomConstCanonicalValue {
}
pub trait PhantomConstValue: Intern + InternedCompare + Serialize + fmt::Debug {
fn deserialize<'de, D>(deserializer: D) -> Result<Interned<Self>, D::Error>
fn deserialize_value<'de, D>(deserializer: D) -> Result<Interned<Self>, D::Error>
where
D: serde::Deserializer<'de>;
}
@ -94,7 +101,7 @@ where
T: ?Sized + Intern + InternedCompare + Serialize + fmt::Debug,
Interned<T>: DeserializeOwned,
{
fn deserialize<'de, D>(deserializer: D) -> Result<Interned<Self>, D::Error>
fn deserialize_value<'de, D>(deserializer: D) -> Result<Interned<Self>, D::Error>
where
D: serde::Deserializer<'de>,
{
@ -189,7 +196,8 @@ impl<T: ?Sized + PhantomConstValue> Memoize for PhantomConstCanonicalMemoize<T,
type Output = Interned<T>;
fn inner(self, input: &Self::Input) -> Self::Output {
PhantomConstValue::deserialize(input.as_json_value()).expect("deserialization failed ")
PhantomConstValue::deserialize_value(input.as_json_value())
.expect("deserialization failed ")
}
}
@ -240,6 +248,7 @@ impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
type BaseType = PhantomConst;
type MaskType = ();
type SimValue = ();
impl_match_variant_as_self!();
fn mask_type(&self) -> Self::MaskType {
@ -260,6 +269,19 @@ impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert!(bits.is_empty());
()
}
fn sim_value_clone_from_bits(&self, _value: &mut Self::SimValue, bits: &BitSlice) {
assert!(bits.is_empty());
}
fn sim_value_to_bits(&self, _value: &Self::SimValue, bits: &mut BitSlice) {
assert!(bits.is_empty());
}
}
impl<T: ?Sized + PhantomConstValue> StaticType for PhantomConst<T>
@ -271,3 +293,44 @@ where
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
}
impl<T: ?Sized + PhantomConstValue> ExprPartialEq<Self> for PhantomConst<T> {
fn cmp_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
assert_eq!(Expr::ty(lhs), Expr::ty(rhs));
true.to_expr()
}
fn cmp_ne(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
assert_eq!(Expr::ty(lhs), Expr::ty(rhs));
false.to_expr()
}
}
impl<T: ?Sized + PhantomConstValue> ExprPartialOrd<Self> for PhantomConst<T> {
fn cmp_lt(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
assert_eq!(Expr::ty(lhs), Expr::ty(rhs));
false.to_expr()
}
fn cmp_le(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
assert_eq!(Expr::ty(lhs), Expr::ty(rhs));
true.to_expr()
}
fn cmp_gt(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
assert_eq!(Expr::ty(lhs), Expr::ty(rhs));
false.to_expr()
}
fn cmp_ge(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
assert_eq!(Expr::ty(lhs), Expr::ty(rhs));
true.to_expr()
}
}
impl<T: ?Sized + PhantomConstValue> SimValuePartialEq<Self> for PhantomConst<T> {
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<Self>) -> bool {
assert_eq!(SimValue::ty(this), SimValue::ty(other));
true
}
}

View file

@ -7,6 +7,7 @@ use crate::{
source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
};
use bitvec::slice::BitSlice;
mod sealed {
pub trait ResetTypeSealed {}
@ -45,6 +46,7 @@ macro_rules! reset_type {
impl Type for $name {
type BaseType = $name;
type MaskType = Bool;
type SimValue = bool;
impl_match_variant_as_self!();
@ -66,6 +68,21 @@ macro_rules! reset_type {
};
retval
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), 1);
bits[0]
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), 1);
*value = bits[0];
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), 1);
bits.set(0, *value);
}
}
impl $name {

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,665 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
array::{Array, ArrayType},
bundle::{Bundle, BundleType},
clock::Clock,
enum_::{Enum, EnumType},
expr::{CastBitsTo, Expr, ToExpr},
int::{Bool, IntType, KnownSize, SInt, SIntType, SIntValue, Size, UInt, UIntType, UIntValue},
reset::{AsyncReset, Reset, SyncReset},
ty::{CanonicalType, Type},
util::{
alternating_cell::{AlternatingCell, AlternatingCellMethods},
ConstUsize,
},
};
use bitvec::{slice::BitSlice, vec::BitVec};
use std::{
fmt,
ops::{Deref, DerefMut},
sync::Arc,
};
#[derive(Copy, Clone, Eq, PartialEq)]
enum ValidFlags {
BothValid = 0,
OnlyValueValid = 1,
OnlyBitsValid = 2,
}
#[derive(Clone)]
struct SimValueInner<T: Type> {
value: T::SimValue,
bits: UIntValue,
valid_flags: ValidFlags,
ty: T,
}
impl<T: Type> SimValueInner<T> {
fn fill_bits(&mut self) {
match self.valid_flags {
ValidFlags::BothValid | ValidFlags::OnlyBitsValid => {}
ValidFlags::OnlyValueValid => {
self.ty.sim_value_to_bits(&self.value, self.bits.bits_mut());
self.valid_flags = ValidFlags::BothValid;
}
}
}
fn into_bits(mut self) -> UIntValue {
self.fill_bits();
self.bits
}
fn bits_mut(&mut self) -> &mut UIntValue {
self.fill_bits();
self.valid_flags = ValidFlags::OnlyBitsValid;
&mut self.bits
}
fn fill_value(&mut self) {
match self.valid_flags {
ValidFlags::BothValid | ValidFlags::OnlyValueValid => {}
ValidFlags::OnlyBitsValid => {
self.ty
.sim_value_clone_from_bits(&mut self.value, self.bits.bits());
self.valid_flags = ValidFlags::BothValid;
}
}
}
fn into_value(mut self) -> T::SimValue {
self.fill_value();
self.value
}
fn value_mut(&mut self) -> &mut T::SimValue {
self.fill_value();
self.valid_flags = ValidFlags::OnlyValueValid;
&mut self.value
}
}
impl<T: Type> AlternatingCellMethods for SimValueInner<T> {
fn unique_to_shared(&mut self) {
match self.valid_flags {
ValidFlags::BothValid => return,
ValidFlags::OnlyValueValid => {
self.ty.sim_value_to_bits(&self.value, self.bits.bits_mut())
}
ValidFlags::OnlyBitsValid => self
.ty
.sim_value_clone_from_bits(&mut self.value, self.bits.bits()),
}
self.valid_flags = ValidFlags::BothValid;
}
fn shared_to_unique(&mut self) {}
}
pub struct SimValue<T: Type> {
inner: AlternatingCell<SimValueInner<T>>,
}
impl<T: Type + Clone> Clone for SimValue<T> {
fn clone(&self) -> Self {
Self {
inner: AlternatingCell::new_unique(self.inner.share().clone()),
}
}
}
impl<T: Type> SimValue<T> {
#[track_caller]
pub fn from_bits(ty: T, bits: UIntValue) -> Self {
assert_eq!(ty.canonical().bit_width(), bits.width());
let inner = SimValueInner {
value: ty.sim_value_from_bits(bits.bits()),
bits,
valid_flags: ValidFlags::BothValid,
ty,
};
Self {
inner: AlternatingCell::new_shared(inner),
}
}
#[track_caller]
pub fn from_bitslice(ty: T, bits: &BitSlice) -> Self {
Self::from_bits(ty, UIntValue::new(Arc::new(bits.to_bitvec())))
}
pub fn from_value(ty: T, value: T::SimValue) -> Self {
let inner = SimValueInner {
bits: UIntValue::new_dyn(Arc::new(BitVec::repeat(false, ty.canonical().bit_width()))),
value,
valid_flags: ValidFlags::OnlyValueValid,
ty,
};
Self {
inner: AlternatingCell::new_unique(inner),
}
}
pub fn ty(this: &Self) -> T {
this.inner.share().ty
}
pub fn into_bits(this: Self) -> UIntValue {
this.inner.into_inner().into_bits()
}
pub fn into_ty_and_bits(this: Self) -> (T, UIntValue) {
let inner = this.inner.into_inner();
(inner.ty, inner.into_bits())
}
pub fn bits(this: &Self) -> &UIntValue {
&this.inner.share().bits
}
pub fn bits_mut(this: &mut Self) -> &mut UIntValue {
this.inner.unique().bits_mut()
}
pub fn into_value(this: Self) -> T::SimValue {
this.inner.into_inner().into_value()
}
pub fn value(this: &Self) -> &T::SimValue {
&this.inner.share().value
}
pub fn value_mut(this: &mut Self) -> &mut T::SimValue {
this.inner.unique().value_mut()
}
#[track_caller]
pub fn from_canonical(v: SimValue<CanonicalType>) -> Self {
let (ty, bits) = SimValue::into_ty_and_bits(v);
Self::from_bits(T::from_canonical(ty), bits)
}
pub fn into_canonical(this: Self) -> SimValue<CanonicalType> {
let (ty, bits) = Self::into_ty_and_bits(this);
SimValue::from_bits(ty.canonical(), bits)
}
pub fn canonical(this: &Self) -> SimValue<CanonicalType> {
SimValue::from_bits(Self::ty(this).canonical(), Self::bits(this).clone())
}
#[track_caller]
pub fn from_dyn_int(v: SimValue<T::Dyn>) -> Self
where
T: IntType,
{
let (ty, bits) = SimValue::into_ty_and_bits(v);
SimValue::from_bits(T::from_dyn_int(ty), bits)
}
pub fn into_dyn_int(this: Self) -> SimValue<T::Dyn>
where
T: IntType,
{
let (ty, bits) = Self::into_ty_and_bits(this);
SimValue::from_bits(ty.as_dyn_int(), bits)
}
pub fn to_dyn_int(this: &Self) -> SimValue<T::Dyn>
where
T: IntType,
{
SimValue::from_bits(Self::ty(this).as_dyn_int(), Self::bits(&this).clone())
}
#[track_caller]
pub fn from_bundle(v: SimValue<Bundle>) -> Self
where
T: BundleType,
{
let (ty, bits) = SimValue::into_ty_and_bits(v);
SimValue::from_bits(T::from_canonical(CanonicalType::Bundle(ty)), bits)
}
pub fn into_bundle(this: Self) -> SimValue<Bundle>
where
T: BundleType,
{
let (ty, bits) = Self::into_ty_and_bits(this);
SimValue::from_bits(Bundle::from_canonical(ty.canonical()), bits)
}
pub fn to_bundle(this: &Self) -> SimValue<Bundle>
where
T: BundleType,
{
SimValue::from_bits(
Bundle::from_canonical(Self::ty(this).canonical()),
Self::bits(&this).clone(),
)
}
#[track_caller]
pub fn from_enum(v: SimValue<Enum>) -> Self
where
T: EnumType,
{
let (ty, bits) = SimValue::into_ty_and_bits(v);
SimValue::from_bits(T::from_canonical(CanonicalType::Enum(ty)), bits)
}
pub fn into_enum(this: Self) -> SimValue<Enum>
where
T: EnumType,
{
let (ty, bits) = Self::into_ty_and_bits(this);
SimValue::from_bits(Enum::from_canonical(ty.canonical()), bits)
}
pub fn to_enum(this: &Self) -> SimValue<Enum>
where
T: EnumType,
{
SimValue::from_bits(
Enum::from_canonical(Self::ty(this).canonical()),
Self::bits(&this).clone(),
)
}
}
impl<T: Type> Deref for SimValue<T> {
type Target = T::SimValue;
fn deref(&self) -> &Self::Target {
Self::value(self)
}
}
impl<T: Type> DerefMut for SimValue<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
Self::value_mut(self)
}
}
impl<T: Type> fmt::Debug for SimValue<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let inner = self.inner.share();
f.debug_struct("SimValue")
.field("ty", &inner.ty)
.field("value", &inner.value)
.finish()
}
}
impl<T: Type> ToExpr for SimValue<T> {
type Type = T;
#[track_caller]
fn to_expr(&self) -> Expr<Self::Type> {
let inner = self.inner.share();
inner.bits.cast_bits_to(inner.ty)
}
}
pub trait SimValuePartialEq<T: Type = Self>: Type {
#[track_caller]
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<T>) -> bool;
}
impl<T: SimValuePartialEq<U>, U: Type> PartialEq<SimValue<U>> for SimValue<T> {
#[track_caller]
fn eq(&self, other: &SimValue<U>) -> bool {
T::sim_value_eq(self, other)
}
}
impl<LhsWidth: Size, RhsWidth: Size> SimValuePartialEq<UIntType<RhsWidth>> for UIntType<LhsWidth> {
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<UIntType<RhsWidth>>) -> bool {
**this == **other
}
}
impl<LhsWidth: Size, RhsWidth: Size> SimValuePartialEq<SIntType<RhsWidth>> for SIntType<LhsWidth> {
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<SIntType<RhsWidth>>) -> bool {
**this == **other
}
}
impl SimValuePartialEq<Bool> for Bool {
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<Bool>) -> bool {
**this == **other
}
}
pub trait ToSimValue<T: Type> {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T>;
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T>
where
Self: Sized,
{
self.to_sim_value(ty)
}
#[track_caller]
fn arc_into_sim_value(self: Arc<Self>, ty: T) -> SimValue<T> {
self.to_sim_value(ty)
}
#[track_caller]
fn arc_to_sim_value(self: &Arc<Self>, ty: T) -> SimValue<T> {
self.to_sim_value(ty)
}
}
impl<T: Type> ToSimValue<T> for SimValue<T> {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
assert_eq!(SimValue::ty(self), ty);
self.clone()
}
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T> {
assert_eq!(SimValue::ty(&self), ty);
self
}
}
impl<T: Type> ToSimValue<T> for BitVec {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
self.clone().into_sim_value(ty)
}
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T> {
Arc::new(self).arc_into_sim_value(ty)
}
#[track_caller]
fn arc_into_sim_value(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> {
SimValue::from_bits(ty, UIntValue::new_dyn(self.clone()))
}
}
impl<T: Type> ToSimValue<T> for bitvec::boxed::BitBox {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
self.clone().into_sim_value(ty)
}
#[track_caller]
fn into_sim_value(self, ty: T) -> SimValue<T> {
self.into_bitvec().into_sim_value(ty)
}
}
impl<T: Type> ToSimValue<T> for BitSlice {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
self.to_bitvec().into_sim_value(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<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 + 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<T> + Send + Sync + 'static, T: Type> ToSimValue<T>
for crate::intern::Interned<This>
{
fn to_sim_value(&self, ty: T) -> SimValue<T> {
This::to_sim_value(self, ty)
}
}
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)
}
fn into_sim_value(self, ty: T) -> SimValue<T> {
This::into_sim_value(*self, ty)
}
}
impl<T: Type, Len: Size> SimValue<ArrayType<T, Len>> {
#[track_caller]
pub fn from_array_elements<I: IntoIterator<Item: ToSimValue<T>>>(
ty: ArrayType<T, Len>,
elements: I,
) -> Self {
let element_ty = ty.element();
let elements = Vec::from_iter(
elements
.into_iter()
.map(|element| element.into_sim_value(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] {
#[track_caller]
fn to_sim_value(&self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<CanonicalType>> ToSimValue<CanonicalType> for [Element] {
#[track_caller]
fn to_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, const N: usize> ToSimValue<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>> {
SimValue::from_array_elements(ty, self)
}
#[track_caller]
fn into_sim_value(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)
}
#[track_caller]
fn into_sim_value(self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<CanonicalType>, const N: usize> ToSimValue<CanonicalType>
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>> {
SimValue::from_array_elements(ty, self)
}
#[track_caller]
fn into_sim_value(self, ty: Array<T>) -> SimValue<Array<T>> {
SimValue::from_array_elements(ty, self)
}
}
impl<Element: ToSimValue<CanonicalType>> ToSimValue<CanonicalType> for Vec<Element> {
#[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<T: Type> ToSimValue<T> for Expr<T> {
#[track_caller]
fn to_sim_value(&self, ty: T) -> SimValue<T> {
assert_eq!(Expr::ty(*self), ty);
SimValue::from_bitslice(
ty,
&crate::expr::ToLiteralBits::to_literal_bits(self)
.expect("must be a literal expression"),
)
}
}
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> {
SimValue::from_value(ty, *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 {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
match ty {
CanonicalType::UInt(_)
| CanonicalType::SInt(_)
| CanonicalType::Array(_)
| CanonicalType::Enum(_)
| CanonicalType::Bundle(_)
| CanonicalType::PhantomConst(_) => {
panic!("can't create SimValue from bool: expected value of type: {ty:?}");
}
CanonicalType::Bool(_)
| CanonicalType::AsyncReset(_)
| CanonicalType::SyncReset(_)
| CanonicalType::Reset(_)
| CanonicalType::Clock(_) => {
SimValue::from_bits(ty, UIntValue::new(Arc::new(BitVec::repeat(*self, 1))))
}
}
}
}
macro_rules! impl_to_sim_value_for_primitive_int {
($prim:ident) => {
impl ToSimValue<<$prim as ToExpr>::Type> for $prim {
#[track_caller]
fn to_sim_value(
&self,
ty: <$prim as ToExpr>::Type,
) -> SimValue<<$prim as ToExpr>::Type> {
SimValue::from_value(ty, (*self).into())
}
}
impl ToSimValue<<<$prim as ToExpr>::Type as IntType>::Dyn> for $prim {
#[track_caller]
fn to_sim_value(
&self,
ty: <<$prim as ToExpr>::Type as IntType>::Dyn,
) -> SimValue<<<$prim as ToExpr>::Type as IntType>::Dyn> {
SimValue::from_value(
ty,
<<$prim as ToExpr>::Type as Type>::SimValue::from(*self).as_dyn_int(),
)
}
}
impl ToSimValue<CanonicalType> for $prim {
#[track_caller]
fn to_sim_value(&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))
}
}
};
}
impl_to_sim_value_for_primitive_int!(u8);
impl_to_sim_value_for_primitive_int!(u16);
impl_to_sim_value_for_primitive_int!(u32);
impl_to_sim_value_for_primitive_int!(u64);
impl_to_sim_value_for_primitive_int!(u128);
impl_to_sim_value_for_primitive_int!(usize);
impl_to_sim_value_for_primitive_int!(i8);
impl_to_sim_value_for_primitive_int!(i16);
impl_to_sim_value_for_primitive_int!(i32);
impl_to_sim_value_for_primitive_int!(i64);
impl_to_sim_value_for_primitive_int!(i128);
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)
}
fn into_sim_value(self, ty: $IntType<Width>) -> SimValue<$IntType<Width>> {
self.into_bits().into_sim_value(ty)
}
}
impl<Width: Size> ToSimValue<$Int> for $IntValue<Width> {
fn to_sim_value(&self, ty: $Int) -> SimValue<$Int> {
self.bits().to_sim_value(ty)
}
fn into_sim_value(self, ty: $Int) -> SimValue<$Int> {
self.into_bits().into_sim_value(ty)
}
}
impl<Width: Size> ToSimValue<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)))
}
#[track_caller]
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType> {
SimValue::into_canonical(self.into_sim_value($Int::from_canonical(ty)))
}
}
};
}
impl_to_sim_value_for_int_value!(UIntValue, UInt, UIntType);
impl_to_sim_value_for_int_value!(SIntValue, SInt, SIntType);

View file

@ -7,14 +7,15 @@ use crate::{
clock::Clock,
enum_::Enum,
expr::Expr,
int::{Bool, SInt, UInt},
int::{Bool, SInt, UInt, UIntValue},
intern::{Intern, Interned},
phantom_const::PhantomConst,
reset::{AsyncReset, Reset, SyncReset},
source_location::SourceLocation,
util::ConstUsize,
};
use std::{fmt, hash::Hash, iter::FusedIterator, ops::Index};
use bitvec::slice::BitSlice;
use std::{fmt, hash::Hash, iter::FusedIterator, ops::Index, sync::Arc};
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
#[non_exhaustive]
@ -268,6 +269,7 @@ pub trait Type:
{
type BaseType: BaseType;
type MaskType: Type<MaskType = Self::MaskType>;
type SimValue: fmt::Debug + Clone + 'static;
type MatchVariant: 'static + Send + Sync;
type MatchActiveScope;
type MatchVariantAndInactiveScope: MatchVariantAndInactiveScope<
@ -285,6 +287,9 @@ pub trait Type:
fn canonical(&self) -> CanonicalType;
fn from_canonical(canonical_type: CanonicalType) -> Self;
fn source_location() -> SourceLocation;
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue;
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice);
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice);
}
pub trait BaseType: Type<BaseType = Self> + sealed::BaseTypeSealed + Into<CanonicalType> {}
@ -314,6 +319,7 @@ pub trait TypeWithDeref: Type {
impl Type for CanonicalType {
type BaseType = CanonicalType;
type MaskType = CanonicalType;
type SimValue = OpaqueSimValue;
impl_match_variant_as_self!();
fn mask_type(&self) -> Self::MaskType {
match self {
@ -339,6 +345,48 @@ impl Type for CanonicalType {
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn sim_value_from_bits(&self, bits: &BitSlice) -> Self::SimValue {
assert_eq!(bits.len(), self.bit_width());
OpaqueSimValue::from_bitslice(bits)
}
fn sim_value_clone_from_bits(&self, value: &mut Self::SimValue, bits: &BitSlice) {
assert_eq!(bits.len(), self.bit_width());
assert_eq!(value.bit_width(), self.bit_width());
value.bits_mut().bits_mut().copy_from_bitslice(bits);
}
fn sim_value_to_bits(&self, value: &Self::SimValue, bits: &mut BitSlice) {
assert_eq!(bits.len(), self.bit_width());
assert_eq!(value.bit_width(), self.bit_width());
bits.copy_from_bitslice(value.bits().bits());
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct OpaqueSimValue {
bits: UIntValue,
}
impl OpaqueSimValue {
pub fn bit_width(&self) -> usize {
self.bits.width()
}
pub fn bits(&self) -> &UIntValue {
&self.bits
}
pub fn bits_mut(&mut self) -> &mut UIntValue {
&mut self.bits
}
pub fn into_bits(self) -> UIntValue {
self.bits
}
pub fn from_bits(bits: UIntValue) -> Self {
Self { bits }
}
pub fn from_bitslice(v: &BitSlice) -> Self {
Self {
bits: UIntValue::new(Arc::new(v.to_bitvec())),
}
}
}
pub trait StaticType: Type {

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
pub(crate) mod alternating_cell;
mod const_bool;
mod const_cmp;
mod const_usize;

View file

@ -0,0 +1,122 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::util::DebugAsDisplay;
use std::{
cell::{Cell, UnsafeCell},
fmt,
};
pub(crate) trait AlternatingCellMethods {
fn unique_to_shared(&mut self);
fn shared_to_unique(&mut self);
}
#[derive(Copy, Clone, Debug)]
enum State {
Unique,
Shared,
Locked,
}
pub(crate) struct AlternatingCell<T: ?Sized> {
state: Cell<State>,
value: UnsafeCell<T>,
}
impl<T: ?Sized + fmt::Debug + AlternatingCellMethods> fmt::Debug for AlternatingCell<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("AlternatingCell")
.field(
self.try_share()
.as_ref()
.map(|v| -> &dyn fmt::Debug { v })
.unwrap_or(&DebugAsDisplay("<...>")),
)
.finish()
}
}
impl<T: ?Sized> AlternatingCell<T> {
pub(crate) const fn new_shared(value: T) -> Self
where
T: Sized,
{
Self {
state: Cell::new(State::Shared),
value: UnsafeCell::new(value),
}
}
pub(crate) const fn new_unique(value: T) -> Self
where
T: Sized,
{
Self {
state: Cell::new(State::Unique),
value: UnsafeCell::new(value),
}
}
pub(crate) fn is_unique(&self) -> bool {
matches!(self.state.get(), State::Unique)
}
pub(crate) fn is_shared(&self) -> bool {
matches!(self.state.get(), State::Shared)
}
pub(crate) fn into_inner(self) -> T
where
T: Sized,
{
self.value.into_inner()
}
pub(crate) fn try_share(&self) -> Option<&T>
where
T: AlternatingCellMethods,
{
match self.state.get() {
State::Shared => {}
State::Unique => {
struct Locked<'a>(&'a Cell<State>);
impl Drop for Locked<'_> {
fn drop(&mut self) {
self.0.set(State::Shared);
}
}
self.state.set(State::Locked);
let lock = Locked(&self.state);
// Safety: state is Locked, so nothing else will
// access value while calling unique_to_shared.
unsafe { &mut *self.value.get() }.unique_to_shared();
drop(lock);
}
State::Locked => return None,
}
// Safety: state is Shared so nothing will create any mutable
// references until the returned reference's lifetime expires.
Some(unsafe { &*self.value.get() })
}
#[track_caller]
pub(crate) fn share(&self) -> &T
where
T: AlternatingCellMethods,
{
let Some(retval) = self.try_share() else {
panic!("`share` called recursively");
};
retval
}
pub(crate) fn unique(&mut self) -> &mut T
where
T: AlternatingCellMethods,
{
match self.state.get() {
State::Shared => {
self.state.set(State::Unique);
self.value.get_mut().shared_to_unique();
}
State::Unique => {}
State::Locked => unreachable!(),
}
self.value.get_mut()
}
}

View file

@ -3,9 +3,16 @@
use fayalite::{
int::UIntValue,
memory::{ReadStruct, ReadWriteStruct, WriteStruct},
module::{instance_with_loc, reg_builder_with_loc},
prelude::*,
reset::ResetType,
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation, ToSimValue},
sim::{
time::SimDuration,
value::{SimValue, ToSimValue},
vcd::VcdWriterDecls,
Simulation,
},
ty::StaticType,
util::RcWriter,
};
@ -395,32 +402,14 @@ fn test_enums() {
sim.write_reset(sim.io().cd.rst, false);
sim.advance_time(SimDuration::from_nanos(900));
type BOutTy = HdlOption<(UInt<1>, Bool)>;
#[derive(Debug)]
#[derive(Debug, PartialEq)]
struct IO {
en: bool,
which_in: u8,
data_in: u8,
which_out: u8,
data_out: u8,
b_out: Expr<BOutTy>,
}
impl PartialEq for IO {
fn eq(&self, other: &Self) -> bool {
let Self {
en,
which_in,
data_in,
which_out,
data_out,
b_out,
} = *self;
en == other.en
&& which_in == other.which_in
&& data_in == other.data_in
&& which_out == other.which_out
&& data_out == other.data_out
&& b_out.to_sim_value(BOutTy::TYPE) == other.b_out.to_sim_value(BOutTy::TYPE)
}
b_out: SimValue<BOutTy>,
}
let io_cycles = [
IO {
@ -429,7 +418,7 @@ fn test_enums() {
data_in: 0,
which_out: 0,
data_out: 0,
b_out: HdlNone(),
b_out: HdlNone().to_sim_value(StaticType::TYPE),
},
IO {
en: true,
@ -437,7 +426,7 @@ fn test_enums() {
data_in: 0,
which_out: 0,
data_out: 0,
b_out: HdlNone(),
b_out: HdlNone().to_sim_value(StaticType::TYPE),
},
IO {
en: false,
@ -445,7 +434,7 @@ fn test_enums() {
data_in: 0,
which_out: 1,
data_out: 0,
b_out: HdlSome((0_hdl_u1, false)),
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
},
IO {
en: true,
@ -453,7 +442,7 @@ fn test_enums() {
data_in: 0xF,
which_out: 1,
data_out: 0,
b_out: HdlSome((0_hdl_u1, false)),
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
},
IO {
en: true,
@ -461,7 +450,7 @@ fn test_enums() {
data_in: 0xF,
which_out: 1,
data_out: 0x3,
b_out: HdlSome((1_hdl_u1, true)),
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
},
IO {
en: true,
@ -469,7 +458,7 @@ fn test_enums() {
data_in: 0xF,
which_out: 1,
data_out: 0x3,
b_out: HdlSome((1_hdl_u1, true)),
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
},
IO {
en: true,
@ -477,7 +466,7 @@ fn test_enums() {
data_in: 0xF,
which_out: 2,
data_out: 0xF,
b_out: HdlNone(),
b_out: HdlNone().to_sim_value(StaticType::TYPE),
},
];
for (
@ -509,7 +498,7 @@ fn test_enums() {
.to_bigint()
.try_into()
.expect("known to be in range"),
b_out: sim.read(sim.io().b_out).to_expr(),
b_out: sim.read(sim.io().b_out),
};
assert_eq!(
expected,
@ -538,9 +527,9 @@ fn test_enums() {
#[hdl_module(outline_generated)]
pub fn memories() {
#[hdl]
let r: fayalite::memory::ReadStruct<(UInt<8>, SInt<8>), ConstUsize<4>> = m.input();
let r: ReadStruct<(UInt<8>, SInt<8>), ConstUsize<4>> = m.input();
#[hdl]
let w: fayalite::memory::WriteStruct<(UInt<8>, SInt<8>), ConstUsize<4>> = m.input();
let w: WriteStruct<(UInt<8>, SInt<8>), ConstUsize<4>> = m.input();
#[hdl]
let mut mem = memory_with_init([(0x01u8, 0x23i8); 16]);
mem.read_latency(0);
@ -559,120 +548,131 @@ fn test_memories() {
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
sim.write_clock(sim.io().r.clk, false);
sim.write_clock(sim.io().w.clk, false);
#[derive(Debug, PartialEq, Eq)]
#[hdl(cmp_eq)]
struct IO {
r_addr: u8,
r_en: bool,
r_data: (u8, i8),
w_addr: u8,
w_en: bool,
w_data: (u8, i8),
w_mask: (bool, bool),
r_addr: UInt<4>,
r_en: Bool,
r_data: (UInt<8>, SInt<8>),
w_addr: UInt<4>,
w_en: Bool,
w_data: (UInt<8>, SInt<8>),
w_mask: (Bool, Bool),
}
let io_cycles = [
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: false,
r_data: (0, 0),
w_addr: 0,
r_data: (0u8, 0i8),
w_addr: 0_hdl_u4,
w_en: false,
w_data: (0, 0),
w_data: (0u8, 0i8),
w_mask: (false, false),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x1, 0x23),
w_addr: 0,
r_data: (0x1u8, 0x23i8),
w_addr: 0_hdl_u4,
w_en: true,
w_data: (0x10, 0x20),
w_data: (0x10u8, 0x20i8),
w_mask: (true, true),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x10, 0x20),
w_addr: 0,
r_data: (0x10u8, 0x20i8),
w_addr: 0_hdl_u4,
w_en: true,
w_data: (0x30, 0x40),
w_data: (0x30u8, 0x40i8),
w_mask: (false, true),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x10, 0x40),
w_addr: 0,
r_data: (0x10u8, 0x40i8),
w_addr: 0_hdl_u4,
w_en: true,
w_data: (0x50, 0x60),
w_data: (0x50u8, 0x60i8),
w_mask: (true, false),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x50, 0x40),
w_addr: 0,
r_data: (0x50u8, 0x40i8),
w_addr: 0_hdl_u4,
w_en: true,
w_data: (0x70, -0x80),
w_data: (0x70u8, -0x80i8),
w_mask: (false, false),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x50, 0x40),
w_addr: 0,
r_data: (0x50u8, 0x40i8),
w_addr: 0_hdl_u4,
w_en: false,
w_data: (0x90, 0xA0u8 as i8),
w_data: (0x90u8, 0xA0u8 as i8),
w_mask: (false, false),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x50, 0x40),
w_addr: 1,
r_data: (0x50u8, 0x40i8),
w_addr: 1_hdl_u4,
w_en: true,
w_data: (0x90, 0xA0u8 as i8),
w_data: (0x90u8, 0xA0u8 as i8),
w_mask: (true, true),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x50, 0x40),
w_addr: 2,
r_data: (0x50u8, 0x40i8),
w_addr: 2_hdl_u4,
w_en: true,
w_data: (0xB0, 0xC0u8 as i8),
w_data: (0xB0u8, 0xC0u8 as i8),
w_mask: (true, true),
},
#[hdl]
IO {
r_addr: 0,
r_addr: 0_hdl_u4,
r_en: true,
r_data: (0x50, 0x40),
w_addr: 2,
r_data: (0x50u8, 0x40i8),
w_addr: 2_hdl_u4,
w_en: false,
w_data: (0xD0, 0xE0u8 as i8),
w_data: (0xD0u8, 0xE0u8 as i8),
w_mask: (true, true),
},
#[hdl]
IO {
r_addr: 1,
r_addr: 1_hdl_u4,
r_en: true,
r_data: (0x90, 0xA0u8 as i8),
w_addr: 2,
r_data: (0x90u8, 0xA0u8 as i8),
w_addr: 2_hdl_u4,
w_en: false,
w_data: (0xD0, 0xE0u8 as i8),
w_data: (0xD0u8, 0xE0u8 as i8),
w_mask: (true, true),
},
#[hdl]
IO {
r_addr: 2,
r_addr: 2_hdl_u4,
r_en: true,
r_data: (0xB0, 0xC0u8 as i8),
w_addr: 2,
r_data: (0xB0u8, 0xC0u8 as i8),
w_addr: 2_hdl_u4,
w_en: false,
w_data: (0xD0, 0xE0u8 as i8),
w_data: (0xD0u8, 0xE0u8 as i8),
w_mask: (true, true),
},
];
for (
cycle,
expected @ IO {
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl]
let IO {
r_addr,
r_en,
r_data: _,
@ -680,37 +680,26 @@ fn test_memories() {
w_en,
w_data,
w_mask,
},
) in io_cycles.into_iter().enumerate()
{
sim.write_bool_or_int(sim.io().r.addr, r_addr.cast_to_static());
sim.write_bool(sim.io().r.en, r_en);
sim.write_bool_or_int(sim.io().w.addr, w_addr.cast_to_static());
sim.write_bool(sim.io().w.en, w_en);
sim.write_bool_or_int(sim.io().w.data.0, w_data.0);
sim.write_bool_or_int(sim.io().w.data.1, w_data.1);
sim.write_bool(sim.io().w.mask.0, w_mask.0);
sim.write_bool(sim.io().w.mask.1, w_mask.1);
let io = IO {
} = 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]
IO {
r_addr,
r_en,
r_data: (
sim.read_bool_or_int(sim.io().r.data.0)
.to_bigint()
.try_into()
.expect("known to be in range"),
sim.read_bool_or_int(sim.io().r.data.1)
.to_bigint()
.try_into()
.expect("known to be in range"),
),
r_data: sim.read(sim.io().r.data),
w_addr,
w_en,
w_data,
w_mask,
};
})
.to_sim_value(StaticType::TYPE);
assert_eq!(
expected,
expected.to_sim_value(StaticType::TYPE),
io,
"vcd:\n{}\ncycle: {cycle}",
String::from_utf8(writer.take()).unwrap(),
@ -738,7 +727,7 @@ fn test_memories() {
#[hdl_module(outline_generated)]
pub fn memories2() {
#[hdl]
let rw: fayalite::memory::ReadWriteStruct<UInt<2>, ConstUsize<3>> = m.input();
let rw: ReadWriteStruct<UInt<2>, ConstUsize<3>> = m.input();
#[hdl]
let mut mem = memory_with_init([HdlSome(true); 5]);
mem.read_latency(1);
@ -1011,9 +1000,9 @@ fn test_memories2() {
#[hdl_module(outline_generated)]
pub fn memories3() {
#[hdl]
let r: fayalite::memory::ReadStruct<Array<UInt<8>, 8>, ConstUsize<3>> = m.input();
let r: ReadStruct<Array<UInt<8>, 8>, ConstUsize<3>> = m.input();
#[hdl]
let w: fayalite::memory::WriteStruct<Array<UInt<8>, 8>, ConstUsize<3>> = m.input();
let w: WriteStruct<Array<UInt<8>, 8>, ConstUsize<3>> = m.input();
#[hdl]
let mut mem: MemBuilder<Array<UInt<8>, 8>> = memory();
mem.depth(8);
@ -1443,3 +1432,172 @@ fn test_conditional_assignment_last() {
panic!();
}
}
#[hdl_module(outline_generated, extern)]
pub fn extern_module() {
#[hdl]
let i: Bool = m.input();
#[hdl]
let o: Bool = m.output();
m.extern_module_simulation_fn((i, o), |(i, o), mut sim| async move {
sim.write(o, true).await;
sim.advance_time(SimDuration::from_nanos(500)).await;
let mut invert = false;
loop {
sim.advance_time(SimDuration::from_micros(1)).await;
let v = sim.read_bool(i).await;
sim.write(o, v ^ invert).await;
invert = !invert;
}
});
}
#[test]
fn test_extern_module() {
let _n = SourceLocation::normalize_files_for_tests();
let mut sim = Simulation::new(extern_module());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
sim.write(sim.io().i, false);
sim.advance_time(SimDuration::from_micros(10));
sim.write(sim.io().i, true);
sim.advance_time(SimDuration::from_micros(10));
sim.flush_traces().unwrap();
let vcd = String::from_utf8(writer.take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
if vcd != include_str!("sim/expected/extern_module.vcd") {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != include_str!("sim/expected/extern_module.txt") {
panic!();
}
}
#[hdl_module(outline_generated, extern)]
pub fn extern_module2() {
#[hdl]
let en: Bool = m.input();
#[hdl]
let clk: Clock = m.input();
#[hdl]
let o: UInt<8> = m.output();
m.extern_module_simulation_fn((en, clk, o), |(en, clk, o), mut sim| async move {
for b in "Hello, World!\n".bytes().cycle() {
sim.write(o, b).await;
loop {
sim.wait_for_clock_edge(clk).await;
if sim.read_bool(en).await {
break;
}
}
}
});
}
#[test]
fn test_extern_module2() {
let _n = SourceLocation::normalize_files_for_tests();
let mut sim = Simulation::new(extern_module2());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
for i in 0..30 {
sim.write(sim.io().en, i % 10 < 5);
sim.write(sim.io().clk, false);
sim.advance_time(SimDuration::from_micros(1));
sim.write(sim.io().clk, true);
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/extern_module2.vcd") {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != include_str!("sim/expected/extern_module2.txt") {
panic!();
}
}
// use an extern module to simulate a register to test that the
// simulator can handle chains of alternating circuits and extern modules.
#[hdl_module(outline_generated, extern)]
pub fn sw_reg() {
#[hdl]
let clk: Clock = m.input();
#[hdl]
let o: Bool = m.output();
m.extern_module_simulation_fn((clk, o), |(clk, o), mut sim| async move {
let mut state = false;
loop {
sim.write(o, state).await;
sim.wait_for_clock_edge(clk).await;
state = !state;
}
});
}
#[hdl_module(outline_generated)]
pub fn ripple_counter() {
#[hdl]
let clk: Clock = m.input();
#[hdl]
let o: UInt<6> = m.output();
#[hdl]
let bits: Array<Bool, 6> = wire();
connect_any(o, bits.cast_to_bits());
let mut clk_in = clk;
for (i, bit) in bits.into_iter().enumerate() {
if i % 2 == 0 {
let bit_reg = reg_builder_with_loc(&format!("bit_reg_{i}"), SourceLocation::caller())
.clock_domain(
#[hdl]
ClockDomain {
clk: clk_in,
rst: false.to_sync_reset(),
},
)
.no_reset(Bool)
.build();
connect(bit, bit_reg);
connect(bit_reg, !bit_reg);
} else {
let bit_reg =
instance_with_loc(&format!("bit_reg_{i}"), sw_reg(), SourceLocation::caller());
connect(bit_reg.clk, clk_in);
connect(bit, bit_reg.o);
}
clk_in = bit.to_clock();
}
}
#[test]
fn test_ripple_counter() {
let _n = SourceLocation::normalize_files_for_tests();
let mut sim = Simulation::new(ripple_counter());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
for _ in 0..0x80 {
sim.write(sim.io().clk, false);
sim.advance_time(SimDuration::from_micros(1));
sim.write(sim.io().clk, true);
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/ripple_counter.vcd") {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != include_str!("sim/expected/ripple_counter.txt") {
panic!();
}
}

File diff suppressed because it is too large Load diff

View file

@ -92,45 +92,30 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::conditional_assignment_last,
instantiated: Module {
name: conditional_assignment_last,
..
},
}.i: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::i",
ty: Bool,
},
],
..
},
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::conditional_assignment_last,
instantiated: Module {
name: conditional_assignment_last,
..
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
}.i,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::conditional_assignment_last,
instantiated: Module {
name: conditional_assignment_last,
..
},
}.i,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "conditional_assignment_last",
children: [

View file

@ -68,45 +68,30 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::connect_const,
instantiated: Module {
name: connect_const,
..
},
}.o: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<8>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const: connect_const).connect_const::o",
ty: UInt<8>,
},
],
..
},
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::connect_const,
instantiated: Module {
name: connect_const,
..
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
}.o,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::connect_const,
instantiated: Module {
name: connect_const,
..
},
}.o,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "connect_const",
children: [

View file

@ -97,79 +97,44 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
}.bit_out: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::bit_out",
ty: Bool,
},
],
..
},
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
}.reset_out: CompiledValue {
layout: CompiledTypeLayout {
ty: AsyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out",
ty: AsyncReset,
},
],
..
},
}.reset_out,
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
}.bit_out,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
}.bit_out,
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
}.reset_out,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "connect_const_reset",
children: [

View file

@ -203,213 +203,58 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: AsyncReset,
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.rst",
ty: AsyncReset,
},
],
..
},
}.cd,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: AsyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: AsyncReset,
},
],
..
},
},
body: Scalar,
},
},
],
}.count,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.rst: CompiledValue {
layout: CompiledTypeLayout {
ty: AsyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: AsyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.count: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
}.cd,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.clk,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.rst,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.count,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "counter",
children: [

View file

@ -184,213 +184,58 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.rst",
ty: SyncReset,
},
],
..
},
}.cd,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
},
],
}.count,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.rst: CompiledValue {
layout: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.count: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
}.cd,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.clk,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.rst,
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.count,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "counter",
children: [

View file

@ -88,10 +88,14 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {},
made_initial_step: true,
needs_settle: false,
main_module: SimulationModuleState {
base_targets: [],
uninitialized_ios: {},
io_targets: {},
did_initial_settle: true,
},
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "duplicate_names",
children: [

View file

@ -1215,389 +1215,128 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.b_out: CompiledValue {
layout: CompiledTypeLayout {
ty: Enum {
HdlNone,
HdlSome(Bundle {0: UInt<1>, 1: Bool}),
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::b_out",
ty: Enum {
HdlNone,
HdlSome(Bundle {0: UInt<1>, 1: Bool}),
},
},
],
..
},
}.cd,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 7, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.cd: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::cd.rst",
ty: SyncReset,
},
],
..
},
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
},
],
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.cd.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.cd.rst: CompiledValue {
layout: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.data_in: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::data_in",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 4, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.data_out: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::data_out",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 6, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.en: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::en",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.which_in: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::which_in",
ty: UInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 3, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.which_out: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(enums: enums).enums::which_out",
ty: UInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 5, len: 1 },
},
write: None,
}.en,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.which_in,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.data_in,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.which_out,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.data_out,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.b_out,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.b_out,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.cd,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.cd.clk,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.cd.rst,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.data_in,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.data_out,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.en,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.which_in,
Instance {
name: <simulator>::enums,
instantiated: Module {
name: enums,
..
},
}.which_out,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "enums",
children: [

View file

@ -0,0 +1,220 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(extern_module: extern_module).extern_module::i",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(extern_module: extern_module).extern_module::o",
ty: Bool,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:1:1
0: Return,
],
..
},
pc: 0,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [],
},
big_slots: StatePart {
value: [
1,
1,
],
},
},
io: Instance {
name: <simulator>::extern_module,
instantiated: Module {
name: extern_module,
..
},
},
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::extern_module,
instantiated: Module {
name: extern_module,
..
},
}.i,
Instance {
name: <simulator>::extern_module,
instantiated: Module {
name: extern_module,
..
},
}.o,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::extern_module,
instantiated: Module {
name: extern_module,
..
},
}.i,
Instance {
name: <simulator>::extern_module,
instantiated: Module {
name: extern_module,
..
},
}.o,
},
did_initial_settle: true,
},
extern_modules: [
SimulationExternModuleState {
module_state: SimulationModuleState {
base_targets: [
ModuleIO {
name: extern_module::i,
is_input: true,
ty: Bool,
..
},
ModuleIO {
name: extern_module::o,
is_input: false,
ty: Bool,
..
},
],
uninitialized_ios: {},
io_targets: {
ModuleIO {
name: extern_module::i,
is_input: true,
ty: Bool,
..
},
ModuleIO {
name: extern_module::o,
is_input: false,
ty: Bool,
..
},
},
did_initial_settle: true,
},
sim: ExternModuleSimulation {
generator: SimGeneratorFn {
args: (
ModuleIO {
name: extern_module::i,
is_input: true,
ty: Bool,
..
},
ModuleIO {
name: extern_module::o,
is_input: false,
ty: Bool,
..
},
),
f: ...,
},
source_location: SourceLocation(
module-XXXXXXXXXX.rs:4:1,
),
},
running_generator: Some(
...,
),
wait_targets: {
Instant(
20.500000000000 μs,
),
},
},
],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "extern_module",
children: [
TraceModuleIO {
name: "i",
child: TraceBool {
location: TraceScalarId(0),
name: "i",
flow: Source,
},
ty: Bool,
flow: Source,
},
TraceModuleIO {
name: "o",
child: TraceBool {
location: TraceScalarId(1),
name: "o",
flow: Sink,
},
ty: Bool,
flow: Sink,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigBool {
index: StatePartIndex<BigSlots>(0),
},
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(1),
kind: BigBool {
index: StatePartIndex<BigSlots>(1),
},
state: 0x1,
last_state: 0x1,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 20 μs,
clocks_triggered: [],
..
}

View file

@ -0,0 +1,51 @@
$timescale 1 ps $end
$scope module extern_module $end
$var wire 1 ! i $end
$var wire 1 " o $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
1"
$end
#500000
#1500000
0"
#2500000
1"
#3500000
0"
#4500000
1"
#5500000
0"
#6500000
1"
#7500000
0"
#8500000
1"
#9500000
0"
#10000000
1!
#10500000
#11500000
1"
#12500000
0"
#13500000
1"
#14500000
0"
#15500000
1"
#16500000
0"
#17500000
1"
#18500000
0"
#19500000
1"
#20000000

View file

@ -0,0 +1,310 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 3,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::en",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::o",
ty: UInt<8>,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:1:1
0: Return,
],
..
},
pc: 0,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [],
},
big_slots: StatePart {
value: [
0,
1,
101,
],
},
},
io: Instance {
name: <simulator>::extern_module2,
instantiated: Module {
name: extern_module2,
..
},
},
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::extern_module2,
instantiated: Module {
name: extern_module2,
..
},
}.en,
Instance {
name: <simulator>::extern_module2,
instantiated: Module {
name: extern_module2,
..
},
}.clk,
Instance {
name: <simulator>::extern_module2,
instantiated: Module {
name: extern_module2,
..
},
}.o,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::extern_module2,
instantiated: Module {
name: extern_module2,
..
},
}.clk,
Instance {
name: <simulator>::extern_module2,
instantiated: Module {
name: extern_module2,
..
},
}.en,
Instance {
name: <simulator>::extern_module2,
instantiated: Module {
name: extern_module2,
..
},
}.o,
},
did_initial_settle: true,
},
extern_modules: [
SimulationExternModuleState {
module_state: SimulationModuleState {
base_targets: [
ModuleIO {
name: extern_module2::en,
is_input: true,
ty: Bool,
..
},
ModuleIO {
name: extern_module2::clk,
is_input: true,
ty: Clock,
..
},
ModuleIO {
name: extern_module2::o,
is_input: false,
ty: UInt<8>,
..
},
],
uninitialized_ios: {},
io_targets: {
ModuleIO {
name: extern_module2::clk,
is_input: true,
ty: Clock,
..
},
ModuleIO {
name: extern_module2::en,
is_input: true,
ty: Bool,
..
},
ModuleIO {
name: extern_module2::o,
is_input: false,
ty: UInt<8>,
..
},
},
did_initial_settle: true,
},
sim: ExternModuleSimulation {
generator: SimGeneratorFn {
args: (
ModuleIO {
name: extern_module2::en,
is_input: true,
ty: Bool,
..
},
ModuleIO {
name: extern_module2::clk,
is_input: true,
ty: Clock,
..
},
ModuleIO {
name: extern_module2::o,
is_input: false,
ty: UInt<8>,
..
},
),
f: ...,
},
source_location: SourceLocation(
module-XXXXXXXXXX.rs:5:1,
),
},
running_generator: Some(
...,
),
wait_targets: {
Change {
key: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::clk",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
value: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
},
},
},
},
},
],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "extern_module2",
children: [
TraceModuleIO {
name: "en",
child: TraceBool {
location: TraceScalarId(0),
name: "en",
flow: Source,
},
ty: Bool,
flow: Source,
},
TraceModuleIO {
name: "clk",
child: TraceClock {
location: TraceScalarId(1),
name: "clk",
flow: Source,
},
ty: Clock,
flow: Source,
},
TraceModuleIO {
name: "o",
child: TraceUInt {
location: TraceScalarId(2),
name: "o",
ty: UInt<8>,
flow: Sink,
},
ty: UInt<8>,
flow: Sink,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigBool {
index: StatePartIndex<BigSlots>(0),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(1),
kind: BigClock {
index: StatePartIndex<BigSlots>(1),
},
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(2),
kind: BigUInt {
index: StatePartIndex<BigSlots>(2),
ty: UInt<8>,
},
state: 0x65,
last_state: 0x65,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 60 μs,
clocks_triggered: [],
..
}

View file

@ -0,0 +1,150 @@
$timescale 1 ps $end
$scope module extern_module2 $end
$var wire 1 ! en $end
$var wire 1 " clk $end
$var wire 8 # o $end
$upscope $end
$enddefinitions $end
$dumpvars
1!
0"
b1001000 #
$end
#1000000
1"
b1100101 #
#2000000
0"
#3000000
1"
b1101100 #
#4000000
0"
#5000000
1"
#6000000
0"
#7000000
1"
b1101111 #
#8000000
0"
#9000000
1"
b101100 #
#10000000
0!
0"
#11000000
1"
#12000000
0"
#13000000
1"
#14000000
0"
#15000000
1"
#16000000
0"
#17000000
1"
#18000000
0"
#19000000
1"
#20000000
1!
0"
#21000000
1"
b100000 #
#22000000
0"
#23000000
1"
b1010111 #
#24000000
0"
#25000000
1"
b1101111 #
#26000000
0"
#27000000
1"
b1110010 #
#28000000
0"
#29000000
1"
b1101100 #
#30000000
0!
0"
#31000000
1"
#32000000
0"
#33000000
1"
#34000000
0"
#35000000
1"
#36000000
0"
#37000000
1"
#38000000
0"
#39000000
1"
#40000000
1!
0"
#41000000
1"
b1100100 #
#42000000
0"
#43000000
1"
b100001 #
#44000000
0"
#45000000
1"
b1010 #
#46000000
0"
#47000000
1"
b1001000 #
#48000000
0"
#49000000
1"
b1100101 #
#50000000
0!
0"
#51000000
1"
#52000000
0"
#53000000
1"
#54000000
0"
#55000000
1"
#56000000
0"
#57000000
1"
#58000000
0"
#59000000
1"
#60000000

File diff suppressed because it is too large Load diff

View file

@ -598,514 +598,79 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
addr: UInt<3>,
/* offset = 3 */
en: Bool,
/* offset = 4 */
clk: Clock,
#[hdl(flip)] /* offset = 5 */
rdata: UInt<2>,
/* offset = 7 */
wmode: Bool,
/* offset = 8 */
wdata: UInt<2>,
/* offset = 10 */
wmask: Bool,
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 7,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(memories2: memories2).memories2::rw.addr",
ty: UInt<3>,
},
SlotDebugData {
name: "InstantiatedModule(memories2: memories2).memories2::rw.en",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(memories2: memories2).memories2::rw.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(memories2: memories2).memories2::rw.rdata",
ty: UInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(memories2: memories2).memories2::rw.wmode",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(memories2: memories2).memories2::rw.wdata",
ty: UInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(memories2: memories2).memories2::rw.wmask",
ty: Bool,
},
],
..
},
}.rw,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: UInt<3>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<3>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(2),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(3),
},
ty: CompiledTypeLayout {
ty: UInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<2>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(4),
},
ty: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(5),
},
ty: CompiledTypeLayout {
ty: UInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<2>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(6),
},
ty: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
},
],
}.rw,
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 7 },
},
write: None,
},
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.addr: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<3>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<3>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.en: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.rdata: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 3, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.wdata: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 5, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.wmask: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 6, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.wmode: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 4, len: 1 },
},
write: None,
}.rw.addr,
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.clk,
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.en,
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.rdata,
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.wdata,
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.wmask,
Instance {
name: <simulator>::memories2,
instantiated: Module {
name: memories2,
..
},
}.rw.wmode,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "memories2",
children: [

File diff suppressed because it is too large Load diff

View file

@ -216,313 +216,58 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
#[hdl(flip)] /* offset = 0 */
i: UInt<4>,
/* offset = 4 */
o: SInt<2>,
#[hdl(flip)] /* offset = 6 */
i2: SInt<2>,
/* offset = 8 */
o2: UInt<4>,
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 4,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.i",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.o",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.i2",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.o2",
ty: UInt<4>,
},
],
..
},
}.o,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(2),
},
ty: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(3),
},
ty: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
},
],
}.o,
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 4 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.i: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.i2: CompiledValue {
layout: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.o: CompiledValue {
layout: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.o2: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 3, len: 1 },
},
write: None,
}.o.i,
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.i2,
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.o,
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.o2,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "mod1",
children: [

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -265,247 +265,72 @@ Simulation {
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.rst",
ty: SyncReset,
},
],
..
},
}.cd,
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
},
],
}.d,
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd.rst: CompiledValue {
layout: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.d: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::d",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.q: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::q",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 3, len: 1 },
},
write: None,
}.q,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd,
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd.clk,
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd.rst,
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.d,
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.q,
},
did_initial_settle: true,
},
made_initial_step: true,
needs_settle: false,
extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule {
name: "shift_register",
children: [

View file

@ -160,7 +160,8 @@
"data": {
"$kind": "Struct",
"verilog_name": "Visible",
"parameters": "Visible"
"parameters": "Visible",
"simulation": "Visible"
}
},
"ExternModuleParameter": {
@ -1269,6 +1270,11 @@
"$kind": "Opaque"
},
"generics": "<T: ?Sized + crate::phantom_const::PhantomConstValue>"
},
"ExternModuleSimulation": {
"data": {
"$kind": "Opaque"
}
}
}
}