forked from libre-chip/fayalite
Compare commits
10 commits
c0c5b550bc
...
5028401a5a
Author | SHA1 | Date | |
---|---|---|---|
5028401a5a | |||
e0f978fbb6 | |||
ec3a61513b | |||
fdc73b5f3b | |||
a115585d5a | |||
ab9ff4f2db | |||
d1bd176b28 | |||
920d8d875f | |||
d453755bb2 | |||
450e1004b6 |
41 changed files with 8842 additions and 7737 deletions
|
@ -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;
|
||||
|
@ -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,
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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))),
|
||||
),
|
||||
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;
|
||||
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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
extern crate self as fayalite;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use bitvec as __bitvec;
|
||||
#[doc(hidden)]
|
||||
pub use std as __std;
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
665
crates/fayalite/src/sim/value.rs
Normal file
665
crates/fayalite/src/sim/value.rs
Normal 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);
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
122
crates/fayalite/src/util/alternating_cell.rs
Normal file
122
crates/fayalite/src/util/alternating_cell.rs
Normal 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()
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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: [
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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: [
|
||||
|
|
220
crates/fayalite/tests/sim/expected/extern_module.txt
Normal file
220
crates/fayalite/tests/sim/expected/extern_module.txt
Normal 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: [],
|
||||
..
|
||||
}
|
51
crates/fayalite/tests/sim/expected/extern_module.vcd
Normal file
51
crates/fayalite/tests/sim/expected/extern_module.vcd
Normal 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
|
310
crates/fayalite/tests/sim/expected/extern_module2.txt
Normal file
310
crates/fayalite/tests/sim/expected/extern_module2.txt
Normal 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: [],
|
||||
..
|
||||
}
|
150
crates/fayalite/tests/sim/expected/extern_module2.vcd
Normal file
150
crates/fayalite/tests/sim/expected/extern_module2.vcd
Normal 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
|
@ -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
|
@ -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: [
|
||||
|
|
1498
crates/fayalite/tests/sim/expected/ripple_counter.txt
Normal file
1498
crates/fayalite/tests/sim/expected/ripple_counter.txt
Normal file
File diff suppressed because it is too large
Load diff
1753
crates/fayalite/tests/sim/expected/ripple_counter.vcd
Normal file
1753
crates/fayalite/tests/sim/expected/ripple_counter.vcd
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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: [
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue