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) field_flips: Vec<Option<HdlAttr<kw::flip, kw::hdl>>>,
|
||||||
pub(crate) mask_type_ident: Ident,
|
pub(crate) mask_type_ident: Ident,
|
||||||
pub(crate) mask_type_match_variant_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) match_variant_ident: Ident,
|
||||||
|
pub(crate) sim_value_ident: Ident,
|
||||||
pub(crate) builder_ident: Ident,
|
pub(crate) builder_ident: Ident,
|
||||||
pub(crate) mask_type_builder_ident: Ident,
|
pub(crate) mask_type_builder_ident: Ident,
|
||||||
}
|
}
|
||||||
|
@ -125,7 +127,9 @@ impl ParsedBundle {
|
||||||
field_flips,
|
field_flips,
|
||||||
mask_type_ident: format_ident!("__{}__MaskType", ident),
|
mask_type_ident: format_ident!("__{}__MaskType", ident),
|
||||||
mask_type_match_variant_ident: format_ident!("__{}__MaskType__MatchVariant", 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),
|
match_variant_ident: format_ident!("__{}__MatchVariant", ident),
|
||||||
|
sim_value_ident: format_ident!("__{}__SimValue", ident),
|
||||||
mask_type_builder_ident: format_ident!("__{}__MaskType__Builder", ident),
|
mask_type_builder_ident: format_ident!("__{}__MaskType__Builder", ident),
|
||||||
builder_ident: format_ident!("__{}__Builder", ident),
|
builder_ident: format_ident!("__{}__Builder", ident),
|
||||||
ident,
|
ident,
|
||||||
|
@ -427,7 +431,9 @@ impl ToTokens for ParsedBundle {
|
||||||
field_flips,
|
field_flips,
|
||||||
mask_type_ident,
|
mask_type_ident,
|
||||||
mask_type_match_variant_ident,
|
mask_type_match_variant_ident,
|
||||||
|
mask_type_sim_value_ident,
|
||||||
match_variant_ident,
|
match_variant_ident,
|
||||||
|
sim_value_ident,
|
||||||
builder_ident,
|
builder_ident,
|
||||||
mask_type_builder_ident,
|
mask_type_builder_ident,
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -523,7 +529,7 @@ impl ToTokens for ParsedBundle {
|
||||||
semi_token: None,
|
semi_token: None,
|
||||||
}
|
}
|
||||||
.to_tokens(tokens);
|
.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 {
|
for Field { ty, .. } in &mut mask_type_match_variant_fields.named {
|
||||||
*ty = parse_quote_spanned! {span=>
|
*ty = parse_quote_spanned! {span=>
|
||||||
::fayalite::expr::Expr<#ty>
|
::fayalite::expr::Expr<#ty>
|
||||||
|
@ -565,6 +571,58 @@ impl ToTokens for ParsedBundle {
|
||||||
semi_token: None,
|
semi_token: None,
|
||||||
}
|
}
|
||||||
.to_tokens(tokens);
|
.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 this_token = Ident::new("__this", span);
|
||||||
let fields_token = Ident::new("__fields", span);
|
let fields_token = Ident::new("__fields", span);
|
||||||
let self_token = Token;
|
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();
|
let fields_len = fields.named().into_iter().len();
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
@ -623,6 +700,7 @@ impl ToTokens for ParsedBundle {
|
||||||
{
|
{
|
||||||
type BaseType = ::fayalite::bundle::Bundle;
|
type BaseType = ::fayalite::bundle::Bundle;
|
||||||
type MaskType = #mask_type_ident #type_generics;
|
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 MatchVariant = #mask_type_match_variant_ident #type_generics;
|
||||||
type MatchActiveScope = ();
|
type MatchActiveScope = ();
|
||||||
type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
|
type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
|
||||||
|
@ -660,6 +738,34 @@ impl ToTokens for ParsedBundle {
|
||||||
fn source_location() -> ::fayalite::source_location::SourceLocation {
|
fn source_location() -> ::fayalite::source_location::SourceLocation {
|
||||||
::fayalite::source_location::SourceLocation::caller()
|
::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]
|
#[automatically_derived]
|
||||||
impl #impl_generics ::fayalite::bundle::BundleType for #mask_type_ident #type_generics
|
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 BaseType = ::fayalite::bundle::Bundle;
|
||||||
type MaskType = #mask_type_ident #type_generics;
|
type MaskType = #mask_type_ident #type_generics;
|
||||||
|
type SimValue = #sim_value_ident #type_generics;
|
||||||
type MatchVariant = #match_variant_ident #type_generics;
|
type MatchVariant = #match_variant_ident #type_generics;
|
||||||
type MatchActiveScope = ();
|
type MatchActiveScope = ();
|
||||||
type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
|
type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
|
||||||
|
@ -735,6 +842,34 @@ impl ToTokens for ParsedBundle {
|
||||||
fn source_location() -> ::fayalite::source_location::SourceLocation {
|
fn source_location() -> ::fayalite::source_location::SourceLocation {
|
||||||
::fayalite::source_location::SourceLocation::caller()
|
::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]
|
#[automatically_derived]
|
||||||
impl #impl_generics ::fayalite::bundle::BundleType for #target #type_generics
|
impl #impl_generics ::fayalite::bundle::BundleType for #target #type_generics
|
||||||
|
@ -768,23 +903,33 @@ impl ToTokens for ParsedBundle {
|
||||||
}
|
}
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
if let Some((cmp_eq,)) = cmp_eq {
|
if let Some((cmp_eq,)) = cmp_eq {
|
||||||
let mut where_clause =
|
let mut expr_where_clause =
|
||||||
Generics::from(generics)
|
Generics::from(generics)
|
||||||
.where_clause
|
.where_clause
|
||||||
.unwrap_or_else(|| syn::WhereClause {
|
.unwrap_or_else(|| syn::WhereClause {
|
||||||
where_token: Token,
|
where_token: Token,
|
||||||
predicates: Punctuated::new(),
|
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_eq = vec![];
|
||||||
let mut fields_cmp_ne = vec![];
|
let mut fields_cmp_ne = vec![];
|
||||||
for field in fields.named() {
|
for field in fields.named() {
|
||||||
let field_ident = field.ident();
|
let field_ident = field.ident();
|
||||||
let field_ty = field.ty();
|
let field_ty = field.ty();
|
||||||
where_clause
|
expr_where_clause
|
||||||
.predicates
|
.predicates
|
||||||
.push(parse_quote_spanned! {cmp_eq.span=>
|
.push(parse_quote_spanned! {cmp_eq.span=>
|
||||||
#field_ty: ::fayalite::expr::ops::ExprPartialEq<#field_ty>
|
#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=>
|
fields_cmp_eq.push(quote_spanned! {span=>
|
||||||
::fayalite::expr::ops::ExprPartialEq::cmp_eq(__lhs.#field_ident, __rhs.#field_ident)
|
::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)
|
::fayalite::expr::ops::ExprPartialEq::cmp_ne(__lhs.#field_ident, __rhs.#field_ident)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let sim_value_eq_body;
|
||||||
let cmp_eq_body;
|
let cmp_eq_body;
|
||||||
let cmp_ne_body;
|
let cmp_ne_body;
|
||||||
if fields_len == 0 {
|
if fields_len == 0 {
|
||||||
|
sim_value_eq_body = quote_spanned! {span=>
|
||||||
|
true
|
||||||
|
};
|
||||||
cmp_eq_body = quote_spanned! {span=>
|
cmp_eq_body = quote_spanned! {span=>
|
||||||
::fayalite::expr::ToExpr::to_expr(&true)
|
::fayalite::expr::ToExpr::to_expr(&true)
|
||||||
};
|
};
|
||||||
|
@ -802,6 +951,9 @@ impl ToTokens for ParsedBundle {
|
||||||
::fayalite::expr::ToExpr::to_expr(&false)
|
::fayalite::expr::ToExpr::to_expr(&false)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
sim_value_eq_body = quote_spanned! {span=>
|
||||||
|
#(#fields_sim_value_eq)&&*
|
||||||
|
};
|
||||||
cmp_eq_body = quote_spanned! {span=>
|
cmp_eq_body = quote_spanned! {span=>
|
||||||
#(#fields_cmp_eq)&*
|
#(#fields_cmp_eq)&*
|
||||||
};
|
};
|
||||||
|
@ -812,7 +964,7 @@ impl ToTokens for ParsedBundle {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics ::fayalite::expr::ops::ExprPartialEq<Self> for #target #type_generics
|
impl #impl_generics ::fayalite::expr::ops::ExprPartialEq<Self> for #target #type_generics
|
||||||
#where_clause
|
#expr_where_clause
|
||||||
{
|
{
|
||||||
fn cmp_eq(
|
fn cmp_eq(
|
||||||
__lhs: ::fayalite::expr::Expr<Self>,
|
__lhs: ::fayalite::expr::Expr<Self>,
|
||||||
|
@ -827,6 +979,17 @@ impl ToTokens for ParsedBundle {
|
||||||
#cmp_ne_body
|
#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);
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ pub(crate) struct ParsedEnum {
|
||||||
pub(crate) brace_token: Brace,
|
pub(crate) brace_token: Brace,
|
||||||
pub(crate) variants: Punctuated<ParsedVariant, Token![,]>,
|
pub(crate) variants: Punctuated<ParsedVariant, Token![,]>,
|
||||||
pub(crate) match_variant_ident: Ident,
|
pub(crate) match_variant_ident: Ident,
|
||||||
|
pub(crate) sim_value_ident: Ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParsedEnum {
|
impl ParsedEnum {
|
||||||
|
@ -190,6 +191,7 @@ impl ParsedEnum {
|
||||||
brace_token,
|
brace_token,
|
||||||
variants,
|
variants,
|
||||||
match_variant_ident: format_ident!("__{}__MatchVariant", ident),
|
match_variant_ident: format_ident!("__{}__MatchVariant", ident),
|
||||||
|
sim_value_ident: format_ident!("__{}__SimValue", ident),
|
||||||
ident,
|
ident,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -207,6 +209,7 @@ impl ToTokens for ParsedEnum {
|
||||||
brace_token,
|
brace_token,
|
||||||
variants,
|
variants,
|
||||||
match_variant_ident,
|
match_variant_ident,
|
||||||
|
sim_value_ident,
|
||||||
} = self;
|
} = self;
|
||||||
let span = ident.span();
|
let span = ident.span();
|
||||||
let ItemOptions {
|
let ItemOptions {
|
||||||
|
@ -409,6 +412,106 @@ impl ToTokens for ParsedEnum {
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
.to_tokens(tokens);
|
.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;
|
let self_token = Token;
|
||||||
for (index, ParsedVariant { ident, field, .. }) in variants.iter().enumerate() {
|
for (index, ParsedVariant { ident, field, .. }) in variants.iter().enumerate() {
|
||||||
if let Some(ParsedVariantField { ty, .. }) = field {
|
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();
|
let variants_len = variants.len();
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
@ -542,6 +781,7 @@ impl ToTokens for ParsedEnum {
|
||||||
{
|
{
|
||||||
type BaseType = ::fayalite::enum_::Enum;
|
type BaseType = ::fayalite::enum_::Enum;
|
||||||
type MaskType = ::fayalite::int::Bool;
|
type MaskType = ::fayalite::int::Bool;
|
||||||
|
type SimValue = #sim_value_ident #type_generics;
|
||||||
type MatchVariant = #match_variant_ident #type_generics;
|
type MatchVariant = #match_variant_ident #type_generics;
|
||||||
type MatchActiveScope = ::fayalite::module::Scope;
|
type MatchActiveScope = ::fayalite::module::Scope;
|
||||||
type MatchVariantAndInactiveScope = ::fayalite::enum_::EnumMatchVariantAndInactiveScope<Self>;
|
type MatchVariantAndInactiveScope = ::fayalite::enum_::EnumMatchVariantAndInactiveScope<Self>;
|
||||||
|
@ -574,6 +814,35 @@ impl ToTokens for ParsedEnum {
|
||||||
fn source_location() -> ::fayalite::source_location::SourceLocation {
|
fn source_location() -> ::fayalite::source_location::SourceLocation {
|
||||||
::fayalite::source_location::SourceLocation::caller()
|
::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]
|
#[automatically_derived]
|
||||||
impl #impl_generics ::fayalite::enum_::EnumType for #target #type_generics
|
impl #impl_generics ::fayalite::enum_::EnumType for #target #type_generics
|
||||||
|
|
|
@ -377,7 +377,7 @@ impl ModuleFn {
|
||||||
module_kind,
|
module_kind,
|
||||||
vis,
|
vis,
|
||||||
sig,
|
sig,
|
||||||
block,
|
mut block,
|
||||||
struct_generics,
|
struct_generics,
|
||||||
the_struct,
|
the_struct,
|
||||||
} = match self.0 {
|
} = match self.0 {
|
||||||
|
@ -439,6 +439,12 @@ impl ModuleFn {
|
||||||
body_sig
|
body_sig
|
||||||
.inputs
|
.inputs
|
||||||
.insert(0, parse_quote! { m: &::fayalite::module::ModuleBuilder });
|
.insert(0, parse_quote! { m: &::fayalite::module::ModuleBuilder });
|
||||||
|
block.stmts.insert(
|
||||||
|
0,
|
||||||
|
parse_quote! {
|
||||||
|
let _ = m;
|
||||||
|
},
|
||||||
|
);
|
||||||
let body_fn = ItemFn {
|
let body_fn = ItemFn {
|
||||||
attrs: vec![],
|
attrs: vec![],
|
||||||
vis: Visibility::Inherited,
|
vis: Visibility::Inherited,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use bitvec::slice::BitSlice;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
expr::{
|
expr::{
|
||||||
ops::{ArrayLiteral, ExprFromIterator, ExprIntoIterator, ExprPartialEq},
|
ops::{ArrayLiteral, ExprFromIterator, ExprIntoIterator, ExprPartialEq},
|
||||||
|
@ -9,6 +11,7 @@ use crate::{
|
||||||
int::{Bool, DynSize, KnownSize, Size, SizeType, DYN_SIZE},
|
int::{Bool, DynSize, KnownSize, Size, SizeType, DYN_SIZE},
|
||||||
intern::{Intern, Interned, LazyInterned},
|
intern::{Intern, Interned, LazyInterned},
|
||||||
module::transform::visit::{Fold, Folder, Visit, Visitor},
|
module::transform::visit::{Fold, Folder, Visit, Visitor},
|
||||||
|
sim::value::{SimValue, SimValuePartialEq},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{
|
ty::{
|
||||||
CanonicalType, MatchVariantWithoutScope, StaticType, Type, TypeProperties, TypeWithDeref,
|
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> {
|
impl<T: Type, Len: Size> Type for ArrayType<T, Len> {
|
||||||
type BaseType = Array;
|
type BaseType = Array;
|
||||||
type MaskType = ArrayType<T::MaskType, Len>;
|
type MaskType = ArrayType<T::MaskType, Len>;
|
||||||
|
type SimValue = Len::ArraySimValue<T>;
|
||||||
type MatchVariant = Len::ArrayMatch<T>;
|
type MatchVariant = Len::ArrayMatch<T>;
|
||||||
type MatchActiveScope = ();
|
type MatchActiveScope = ();
|
||||||
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Len::ArrayMatch<T>>;
|
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()),
|
Len::from_usize(array.len()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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> {
|
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> {
|
impl<T: Type, Len: Size> ExprIntoIterator for ArrayType<T, Len> {
|
||||||
type Item = T;
|
type Item = T;
|
||||||
type ExprIntoIter = ExprArrayIter<T, Len>;
|
type ExprIntoIter = ExprArrayIter<T, Len>;
|
||||||
|
|
|
@ -8,14 +8,14 @@ use crate::{
|
||||||
},
|
},
|
||||||
int::{Bool, DynSize},
|
int::{Bool, DynSize},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
sim::{SimValue, ToSimValue},
|
sim::value::{SimValue, SimValuePartialEq, ToSimValue},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{
|
ty::{
|
||||||
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, StaticType, Type,
|
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, OpaqueSimValue,
|
||||||
TypeProperties, TypeWithDeref,
|
StaticType, Type, TypeProperties, TypeWithDeref,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bitvec::vec::BitVec;
|
use bitvec::{slice::BitSlice, vec::BitVec};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::{fmt, marker::PhantomData};
|
use std::{fmt, marker::PhantomData};
|
||||||
|
|
||||||
|
@ -216,6 +216,7 @@ impl Bundle {
|
||||||
impl Type for Bundle {
|
impl Type for Bundle {
|
||||||
type BaseType = Bundle;
|
type BaseType = Bundle;
|
||||||
type MaskType = Bundle;
|
type MaskType = Bundle;
|
||||||
|
type SimValue = OpaqueSimValue;
|
||||||
impl_match_variant_as_self!();
|
impl_match_variant_as_self!();
|
||||||
fn mask_type(&self) -> Self::MaskType {
|
fn mask_type(&self) -> Self::MaskType {
|
||||||
Self::new(Interned::from_iter(self.0.fields.into_iter().map(
|
Self::new(Interned::from_iter(self.0.fields.into_iter().map(
|
||||||
|
@ -239,6 +240,20 @@ impl Type for Bundle {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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> {
|
pub trait BundleType: Type<BaseType = Bundle> {
|
||||||
|
@ -247,6 +262,93 @@ pub trait BundleType: Type<BaseType = Bundle> {
|
||||||
fn fields(&self) -> Interned<[BundleField]>;
|
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)]
|
#[derive(Default)]
|
||||||
pub struct NoBuilder;
|
pub struct NoBuilder;
|
||||||
|
|
||||||
|
@ -353,6 +455,7 @@ macro_rules! impl_tuples {
|
||||||
impl<$($T: Type,)*> Type for ($($T,)*) {
|
impl<$($T: Type,)*> Type for ($($T,)*) {
|
||||||
type BaseType = Bundle;
|
type BaseType = Bundle;
|
||||||
type MaskType = ($($T::MaskType,)*);
|
type MaskType = ($($T::MaskType,)*);
|
||||||
|
type SimValue = ($(SimValue<$T>,)*);
|
||||||
type MatchVariant = ($(Expr<$T>,)*);
|
type MatchVariant = ($(Expr<$T>,)*);
|
||||||
type MatchActiveScope = ();
|
type MatchActiveScope = ();
|
||||||
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
|
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
|
||||||
|
@ -391,6 +494,24 @@ macro_rules! impl_tuples {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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,)*) {
|
impl<$($T: Type,)*> BundleType for ($($T,)*) {
|
||||||
type Builder = TupleBuilder<($(Unfilled<$T>,)*)>;
|
type Builder = TupleBuilder<($(Unfilled<$T>,)*)>;
|
||||||
|
@ -444,16 +565,12 @@ macro_rules! impl_tuples {
|
||||||
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<CanonicalType> for ($($T,)*) {
|
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<CanonicalType> for ($($T,)*) {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
|
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]
|
#[track_caller]
|
||||||
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType>
|
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType>
|
||||||
{
|
{
|
||||||
ToSimValue::<Bundle>::into_sim_value(self, Bundle::from_canonical(ty)).into_canonical()
|
SimValue::into_canonical(ToSimValue::<Bundle>::into_sim_value(self, Bundle::from_canonical(ty)))
|
||||||
}
|
|
||||||
#[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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<Bundle> for ($($T,)*) {
|
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<Bundle> for ($($T,)*) {
|
||||||
|
@ -474,24 +591,12 @@ macro_rules! impl_tuples {
|
||||||
let [$($ty_var,)*] = *ty.fields() else {
|
let [$($ty_var,)*] = *ty.fields() else {
|
||||||
panic!("bundle has wrong number of fields");
|
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);
|
$(let $var = $var.into_sim_value($ty_var.ty);
|
||||||
assert_eq!($var.ty(), $ty_var.ty);
|
assert_eq!(SimValue::ty(&$var), $ty_var.ty);
|
||||||
if !$var.bits().is_empty() {
|
bits.extend_from_bitslice(SimValue::bits(&$var).bits());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
)*
|
||||||
bits.unwrap_or_else(BitVec::new).into_sim_value(ty)
|
bits.into_sim_value(ty)
|
||||||
}
|
|
||||||
#[track_caller]
|
|
||||||
fn box_into_sim_value(self: Box<Self>, ty: Bundle) -> SimValue<Bundle> {
|
|
||||||
Self::into_sim_value(*self, ty)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<$($T: ToSimValue<$Ty>, $Ty: Type,)*> ToSimValue<($($Ty,)*)> for ($($T,)*) {
|
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,)*)> {
|
fn to_sim_value(&self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
|
||||||
let ($($var,)*) = self;
|
let ($($var,)*) = self;
|
||||||
let ($($ty_var,)*) = ty;
|
let ($($ty_var,)*) = ty;
|
||||||
$(let $var = $var.to_sim_value($ty_var).into_canonical();)*
|
$(let $var = $var.to_sim_value($ty_var);)*
|
||||||
SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical()))
|
SimValue::from_value(ty, ($($var,)*))
|
||||||
}
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn into_sim_value(self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
|
fn into_sim_value(self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
|
||||||
let ($($var,)*) = self;
|
let ($($var,)*) = self;
|
||||||
let ($($ty_var,)*) = ty;
|
let ($($ty_var,)*) = ty;
|
||||||
$(let $var = $var.into_sim_value($ty_var).into_canonical();)*
|
$(let $var = $var.into_sim_value($ty_var);)*
|
||||||
SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical()))
|
SimValue::from_value(ty, ($($var,)*))
|
||||||
}
|
|
||||||
#[track_caller]
|
|
||||||
fn box_into_sim_value(self: Box<Self>, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
|
|
||||||
Self::into_sim_value(*self, ty)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<$($Lhs: Type + ExprPartialEq<$Rhs>, $Rhs: Type,)*> ExprPartialEq<($($Rhs,)*)> for ($($Lhs,)*) {
|
impl<$($Lhs: Type + ExprPartialEq<$Rhs>, $Rhs: Type,)*> ExprPartialEq<($($Rhs,)*)> for ($($Lhs,)*) {
|
||||||
|
@ -537,6 +638,15 @@ macro_rules! impl_tuples {
|
||||||
.any_one_bits()
|
.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)*]) => {
|
([$($lhs:tt)*] [$rhs_first:tt $($rhs:tt)*]) => {
|
||||||
impl_tuples!([$($lhs)*] []);
|
impl_tuples!([$($lhs)*] []);
|
||||||
|
@ -564,6 +674,7 @@ impl_tuples! {
|
||||||
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
|
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
|
||||||
type BaseType = Bundle;
|
type BaseType = Bundle;
|
||||||
type MaskType = ();
|
type MaskType = ();
|
||||||
|
type SimValue = ();
|
||||||
type MatchVariant = PhantomData<T>;
|
type MatchVariant = PhantomData<T>;
|
||||||
type MatchActiveScope = ();
|
type MatchActiveScope = ();
|
||||||
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
|
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
|
||||||
|
@ -596,6 +707,16 @@ impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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>);
|
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> {
|
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
|
||||||
let ty = Bundle::from_canonical(ty);
|
let ty = Bundle::from_canonical(ty);
|
||||||
assert!(ty.fields().is_empty());
|
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,
|
source_location::SourceLocation,
|
||||||
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
|
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
|
||||||
};
|
};
|
||||||
|
use bitvec::slice::BitSlice;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
|
||||||
pub struct Clock;
|
pub struct Clock;
|
||||||
|
@ -15,6 +16,7 @@ pub struct Clock;
|
||||||
impl Type for Clock {
|
impl Type for Clock {
|
||||||
type BaseType = Clock;
|
type BaseType = Clock;
|
||||||
type MaskType = Bool;
|
type MaskType = Bool;
|
||||||
|
type SimValue = bool;
|
||||||
|
|
||||||
impl_match_variant_as_self!();
|
impl_match_variant_as_self!();
|
||||||
|
|
||||||
|
@ -36,6 +38,21 @@ impl Type for Clock {
|
||||||
};
|
};
|
||||||
retval
|
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 {
|
impl Clock {
|
||||||
|
|
|
@ -7,17 +7,22 @@ use crate::{
|
||||||
Expr, ToExpr,
|
Expr, ToExpr,
|
||||||
},
|
},
|
||||||
hdl,
|
hdl,
|
||||||
int::Bool,
|
int::{Bool, UIntValue},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
module::{
|
module::{
|
||||||
connect, enum_match_variants_helper, incomplete_wire, wire,
|
connect, enum_match_variants_helper, incomplete_wire, wire,
|
||||||
EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope,
|
EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope,
|
||||||
},
|
},
|
||||||
|
sim::value::{SimValue, SimValuePartialEq},
|
||||||
source_location::SourceLocation,
|
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 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)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct EnumVariant {
|
pub struct EnumVariant {
|
||||||
|
@ -152,6 +157,12 @@ impl EnumTypePropertiesBuilder {
|
||||||
variant_count: variant_count + 1,
|
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 {
|
pub const fn finish(self) -> TypeProperties {
|
||||||
assert!(
|
assert!(
|
||||||
self.variant_count != 0,
|
self.variant_count != 0,
|
||||||
|
@ -325,6 +336,7 @@ impl EnumType for Enum {
|
||||||
impl Type for Enum {
|
impl Type for Enum {
|
||||||
type BaseType = Enum;
|
type BaseType = Enum;
|
||||||
type MaskType = Bool;
|
type MaskType = Bool;
|
||||||
|
type SimValue = OpaqueSimValue;
|
||||||
type MatchVariant = Option<Expr<CanonicalType>>;
|
type MatchVariant = Option<Expr<CanonicalType>>;
|
||||||
type MatchActiveScope = Scope;
|
type MatchActiveScope = Scope;
|
||||||
type MatchVariantAndInactiveScope = EnumMatchVariantAndInactiveScope<Self>;
|
type MatchVariantAndInactiveScope = EnumMatchVariantAndInactiveScope<Self>;
|
||||||
|
@ -355,6 +367,296 @@ impl Type for Enum {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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]
|
#[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)]
|
#[allow(non_snake_case)]
|
||||||
pub fn HdlNone<T: StaticType>() -> Expr<HdlOption<T>> {
|
pub fn HdlNone<T: StaticType>() -> Expr<HdlOption<T>> {
|
||||||
HdlOption[T::TYPE].HdlNone()
|
HdlOption[T::TYPE].HdlNone()
|
||||||
|
|
|
@ -700,6 +700,7 @@ impl<T: ToExpr + ?Sized> CastToBits for T {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CastBitsTo {
|
pub trait CastBitsTo {
|
||||||
|
#[track_caller]
|
||||||
fn cast_bits_to<T: Type>(&self, ty: T) -> Expr<T>;
|
fn cast_bits_to<T: Type>(&self, ty: T) -> Expr<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2258,6 +2258,7 @@ impl<'a> Exporter<'a> {
|
||||||
ModuleBody::Extern(ExternModuleBody {
|
ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation: _,
|
||||||
}) => {
|
}) => {
|
||||||
let verilog_name = Ident(verilog_name);
|
let verilog_name = Ident(verilog_name);
|
||||||
writeln!(body, "{indent}defname = {verilog_name}").unwrap();
|
writeln!(body, "{indent}defname = {verilog_name}").unwrap();
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
Expr, NotALiteralExpr, ToExpr, ToLiteralBits,
|
Expr, NotALiteralExpr, ToExpr, ToLiteralBits,
|
||||||
},
|
},
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
|
sim::value::SimValue,
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
|
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
|
||||||
util::{interned_bit, ConstBool, ConstUsize, GenericConstBool, GenericConstUsize},
|
util::{interned_bit, ConstBool, ConstUsize, GenericConstBool, GenericConstUsize},
|
||||||
|
@ -49,6 +50,15 @@ pub trait KnownSize:
|
||||||
+ IntoIterator<Item = Expr<Element>>
|
+ IntoIterator<Item = Expr<Element>>
|
||||||
+ TryFrom<Vec<Expr<Element>>>
|
+ TryFrom<Vec<Expr<Element>>>
|
||||||
+ Into<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 {
|
macro_rules! known_widths {
|
||||||
|
@ -60,6 +70,7 @@ macro_rules! known_widths {
|
||||||
}> {
|
}> {
|
||||||
const SIZE: Self = Self;
|
const SIZE: Self = Self;
|
||||||
type ArrayMatch<Element: Type> = [Expr<Element>; Self::VALUE];
|
type ArrayMatch<Element: Type> = [Expr<Element>; Self::VALUE];
|
||||||
|
type ArraySimValue<Element: Type> = [SimValue<Element>; Self::VALUE];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
([2 $($rest:tt)*] $($bits:literal)+) => {
|
([2 $($rest:tt)*] $($bits:literal)+) => {
|
||||||
|
@ -72,6 +83,7 @@ macro_rules! known_widths {
|
||||||
impl KnownSize for ConstUsize<{2 $(* $rest)*}> {
|
impl KnownSize for ConstUsize<{2 $(* $rest)*}> {
|
||||||
const SIZE: Self = Self;
|
const SIZE: Self = Self;
|
||||||
type ArrayMatch<Element: Type> = [Expr<Element>; Self::VALUE];
|
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>>
|
+ IntoIterator<Item = Expr<Element>>
|
||||||
+ TryFrom<Vec<Expr<Element>>>
|
+ TryFrom<Vec<Expr<Element>>>
|
||||||
+ Into<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>;
|
const KNOWN_VALUE: Option<usize>;
|
||||||
type SizeType: SizeType<Size = Self>
|
type SizeType: SizeType<Size = Self>
|
||||||
+ Copy
|
+ Copy
|
||||||
|
@ -125,6 +146,7 @@ impl SizeType for usize {
|
||||||
|
|
||||||
impl Size for DynSize {
|
impl Size for DynSize {
|
||||||
type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
|
type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
|
||||||
|
type ArraySimValue<Element: Type> = Box<[SimValue<Element>]>;
|
||||||
const KNOWN_VALUE: Option<usize> = None;
|
const KNOWN_VALUE: Option<usize> = None;
|
||||||
type SizeType = usize;
|
type SizeType = usize;
|
||||||
|
|
||||||
|
@ -147,6 +169,7 @@ impl<T: KnownSize> SizeType for T {
|
||||||
|
|
||||||
impl<T: KnownSize> Size for T {
|
impl<T: KnownSize> Size for T {
|
||||||
type ArrayMatch<Element: Type> = <T as KnownSize>::ArrayMatch<Element>;
|
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);
|
const KNOWN_VALUE: Option<usize> = Some(T::VALUE);
|
||||||
|
|
||||||
|
@ -287,6 +310,7 @@ macro_rules! impl_int {
|
||||||
impl<Width: Size> Type for $name<Width> {
|
impl<Width: Size> Type for $name<Width> {
|
||||||
type BaseType = $pretty_name;
|
type BaseType = $pretty_name;
|
||||||
type MaskType = Bool;
|
type MaskType = Bool;
|
||||||
|
type SimValue = $value<Width>;
|
||||||
impl_match_variant_as_self!();
|
impl_match_variant_as_self!();
|
||||||
fn mask_type(&self) -> Self::MaskType {
|
fn mask_type(&self) -> Self::MaskType {
|
||||||
Bool
|
Bool
|
||||||
|
@ -306,6 +330,20 @@ macro_rules! impl_int {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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> {
|
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> {
|
pub struct $value<Width: Size = DynSize> {
|
||||||
bits: Arc<BitVec>,
|
bits: Arc<BitVec>,
|
||||||
_phantom: PhantomData<Width>,
|
_phantom: PhantomData<Width>,
|
||||||
|
@ -351,9 +389,15 @@ macro_rules! impl_int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Width: Size> PartialOrd for $value<Width> {
|
impl<LhsWidth: Size, RhsWidth: Size> PartialEq<$value<RhsWidth>> for $value<LhsWidth> {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
fn eq(&self, other: &$value<RhsWidth>) -> bool {
|
||||||
Some(self.cmp(other))
|
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> {
|
pub fn bits(&self) -> &Arc<BitVec> {
|
||||||
&self.bits
|
&self.bits
|
||||||
}
|
}
|
||||||
|
pub fn bits_mut(&mut self) -> &mut BitSlice {
|
||||||
|
Arc::<BitVec>::make_mut(&mut self.bits)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Width: Size> ToLiteralBits for $value<Width> {
|
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];
|
let bitslice = &BitSlice::<u8, Lsb0>::from_slice(&bytes)[..width];
|
||||||
bits.clone_from_bitslice(bitslice);
|
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 {
|
fn bits_to_bigint(bits: &BitSlice) -> BigInt {
|
||||||
let sign_byte = if Self::Signed::VALUE && bits.last().as_deref().copied().unwrap_or(false) {
|
let sign_byte = if Self::Signed::VALUE && bits.last().as_deref().copied().unwrap_or(false) {
|
||||||
0xFF
|
0xFF
|
||||||
|
@ -742,6 +795,7 @@ impl Bool {
|
||||||
impl Type for Bool {
|
impl Type for Bool {
|
||||||
type BaseType = Bool;
|
type BaseType = Bool;
|
||||||
type MaskType = Bool;
|
type MaskType = Bool;
|
||||||
|
type SimValue = bool;
|
||||||
impl_match_variant_as_self!();
|
impl_match_variant_as_self!();
|
||||||
fn mask_type(&self) -> Self::MaskType {
|
fn mask_type(&self) -> Self::MaskType {
|
||||||
Bool
|
Bool
|
||||||
|
@ -759,6 +813,18 @@ impl Type for Bool {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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 {
|
impl StaticType for Bool {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
extern crate self as fayalite;
|
extern crate self as fayalite;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use bitvec as __bitvec;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use std as __std;
|
pub use std as __std;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
||||||
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
||||||
|
sim::{ExternModuleSimGenerator, ExternModuleSimulation},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
util::ScopedRef,
|
util::ScopedRef,
|
||||||
|
@ -33,6 +34,7 @@ use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
fmt,
|
fmt,
|
||||||
|
future::IntoFuture,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
iter::FusedIterator,
|
iter::FusedIterator,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
@ -1081,6 +1083,7 @@ pub struct ExternModuleBody<
|
||||||
> {
|
> {
|
||||||
pub verilog_name: Interned<str>,
|
pub verilog_name: Interned<str>,
|
||||||
pub parameters: P,
|
pub parameters: P,
|
||||||
|
pub simulation: Option<ExternModuleSimulation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
|
impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
|
||||||
|
@ -1088,11 +1091,13 @@ impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
|
||||||
let ExternModuleBody {
|
let ExternModuleBody {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation,
|
||||||
} = value;
|
} = value;
|
||||||
let parameters = Intern::intern_owned(parameters);
|
let parameters = Intern::intern_owned(parameters);
|
||||||
Self {
|
Self {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1283,10 +1288,12 @@ impl<T: BundleType> fmt::Debug for DebugModuleBody<T> {
|
||||||
ModuleBody::Extern(ExternModuleBody {
|
ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name,
|
verilog_name,
|
||||||
parameters,
|
parameters,
|
||||||
|
simulation,
|
||||||
}) => {
|
}) => {
|
||||||
debug_struct
|
debug_struct
|
||||||
.field("verilog_name", verilog_name)
|
.field("verilog_name", verilog_name)
|
||||||
.field("parameters", parameters);
|
.field("parameters", parameters)
|
||||||
|
.field("simulation", simulation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug_struct.finish_non_exhaustive()
|
debug_struct.finish_non_exhaustive()
|
||||||
|
@ -1761,6 +1768,7 @@ impl AssertValidityState {
|
||||||
ModuleBody::Extern(ExternModuleBody {
|
ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name: _,
|
verilog_name: _,
|
||||||
parameters: _,
|
parameters: _,
|
||||||
|
simulation: _,
|
||||||
}) => {}
|
}) => {}
|
||||||
ModuleBody::Normal(NormalModuleBody { body }) => {
|
ModuleBody::Normal(NormalModuleBody { body }) => {
|
||||||
let body = self.make_block_index(body);
|
let body = self.make_block_index(body);
|
||||||
|
@ -2108,6 +2116,7 @@ impl ModuleBuilder {
|
||||||
ModuleKind::Extern => ModuleBody::Extern(ExternModuleBody {
|
ModuleKind::Extern => ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name: name.0,
|
verilog_name: name.0,
|
||||||
parameters: vec![],
|
parameters: vec![],
|
||||||
|
simulation: None,
|
||||||
}),
|
}),
|
||||||
ModuleKind::Normal => ModuleBody::Normal(NormalModuleBody {
|
ModuleKind::Normal => ModuleBody::Normal(NormalModuleBody {
|
||||||
body: BuilderModuleBody {
|
body: BuilderModuleBody {
|
||||||
|
@ -2174,6 +2183,7 @@ impl ModuleBuilder {
|
||||||
.builder_extern_body()
|
.builder_extern_body()
|
||||||
.verilog_name = name.intern();
|
.verilog_name = name.intern();
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn parameter(&self, name: impl AsRef<str>, value: ExternModuleParameterValue) {
|
pub fn parameter(&self, name: impl AsRef<str>, value: ExternModuleParameterValue) {
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
self.impl_
|
self.impl_
|
||||||
|
@ -2186,6 +2196,7 @@ impl ModuleBuilder {
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn parameter_int(&self, name: impl AsRef<str>, value: impl Into<BigInt>) {
|
pub fn parameter_int(&self, name: impl AsRef<str>, value: impl Into<BigInt>) {
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
let value = value.into();
|
let value = value.into();
|
||||||
|
@ -2199,6 +2210,7 @@ impl ModuleBuilder {
|
||||||
value: ExternModuleParameterValue::Integer(value),
|
value: ExternModuleParameterValue::Integer(value),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn parameter_str(&self, name: impl AsRef<str>, value: impl AsRef<str>) {
|
pub fn parameter_str(&self, name: impl AsRef<str>, value: impl AsRef<str>) {
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
let value = value.as_ref();
|
let value = value.as_ref();
|
||||||
|
@ -2212,6 +2224,7 @@ impl ModuleBuilder {
|
||||||
value: ExternModuleParameterValue::String(value.intern()),
|
value: ExternModuleParameterValue::String(value.intern()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn parameter_raw_verilog(&self, name: impl AsRef<str>, raw_verilog: impl AsRef<str>) {
|
pub fn parameter_raw_verilog(&self, name: impl AsRef<str>, raw_verilog: impl AsRef<str>) {
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
let raw_verilog = raw_verilog.as_ref();
|
let raw_verilog = raw_verilog.as_ref();
|
||||||
|
@ -2225,6 +2238,26 @@ impl ModuleBuilder {
|
||||||
value: ExternModuleParameterValue::RawVerilog(raw_verilog.intern()),
|
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]
|
#[track_caller]
|
||||||
|
|
|
@ -31,6 +31,7 @@ use crate::{
|
||||||
phantom_const::PhantomConst,
|
phantom_const::PhantomConst,
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, SyncReset},
|
||||||
|
sim::ExternModuleSimulation,
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use bitvec::slice::BitSlice;
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
expr::{
|
||||||
|
ops::{ExprPartialEq, ExprPartialOrd},
|
||||||
|
Expr, ToExpr,
|
||||||
|
},
|
||||||
|
int::Bool,
|
||||||
intern::{Intern, Interned, InternedCompare, LazyInterned, Memoize},
|
intern::{Intern, Interned, InternedCompare, LazyInterned, Memoize},
|
||||||
|
sim::value::{SimValue, SimValuePartialEq},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
|
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 {
|
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
|
where
|
||||||
D: serde::Deserializer<'de>;
|
D: serde::Deserializer<'de>;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +101,7 @@ where
|
||||||
T: ?Sized + Intern + InternedCompare + Serialize + fmt::Debug,
|
T: ?Sized + Intern + InternedCompare + Serialize + fmt::Debug,
|
||||||
Interned<T>: DeserializeOwned,
|
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
|
where
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
|
@ -189,7 +196,8 @@ impl<T: ?Sized + PhantomConstValue> Memoize for PhantomConstCanonicalMemoize<T,
|
||||||
type Output = Interned<T>;
|
type Output = Interned<T>;
|
||||||
|
|
||||||
fn inner(self, input: &Self::Input) -> Self::Output {
|
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> {
|
impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
|
||||||
type BaseType = PhantomConst;
|
type BaseType = PhantomConst;
|
||||||
type MaskType = ();
|
type MaskType = ();
|
||||||
|
type SimValue = ();
|
||||||
impl_match_variant_as_self!();
|
impl_match_variant_as_self!();
|
||||||
|
|
||||||
fn mask_type(&self) -> Self::MaskType {
|
fn mask_type(&self) -> Self::MaskType {
|
||||||
|
@ -260,6 +269,19 @@ impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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>
|
impl<T: ?Sized + PhantomConstValue> StaticType for PhantomConst<T>
|
||||||
|
@ -271,3 +293,44 @@ where
|
||||||
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
||||||
const MASK_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,
|
source_location::SourceLocation,
|
||||||
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
|
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
|
||||||
};
|
};
|
||||||
|
use bitvec::slice::BitSlice;
|
||||||
|
|
||||||
mod sealed {
|
mod sealed {
|
||||||
pub trait ResetTypeSealed {}
|
pub trait ResetTypeSealed {}
|
||||||
|
@ -45,6 +46,7 @@ macro_rules! reset_type {
|
||||||
impl Type for $name {
|
impl Type for $name {
|
||||||
type BaseType = $name;
|
type BaseType = $name;
|
||||||
type MaskType = Bool;
|
type MaskType = Bool;
|
||||||
|
type SimValue = bool;
|
||||||
|
|
||||||
impl_match_variant_as_self!();
|
impl_match_variant_as_self!();
|
||||||
|
|
||||||
|
@ -66,6 +68,21 @@ macro_rules! reset_type {
|
||||||
};
|
};
|
||||||
retval
|
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 {
|
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,
|
clock::Clock,
|
||||||
enum_::Enum,
|
enum_::Enum,
|
||||||
expr::Expr,
|
expr::Expr,
|
||||||
int::{Bool, SInt, UInt},
|
int::{Bool, SInt, UInt, UIntValue},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
phantom_const::PhantomConst,
|
phantom_const::PhantomConst,
|
||||||
reset::{AsyncReset, Reset, SyncReset},
|
reset::{AsyncReset, Reset, SyncReset},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
util::ConstUsize,
|
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)]
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -268,6 +269,7 @@ pub trait Type:
|
||||||
{
|
{
|
||||||
type BaseType: BaseType;
|
type BaseType: BaseType;
|
||||||
type MaskType: Type<MaskType = Self::MaskType>;
|
type MaskType: Type<MaskType = Self::MaskType>;
|
||||||
|
type SimValue: fmt::Debug + Clone + 'static;
|
||||||
type MatchVariant: 'static + Send + Sync;
|
type MatchVariant: 'static + Send + Sync;
|
||||||
type MatchActiveScope;
|
type MatchActiveScope;
|
||||||
type MatchVariantAndInactiveScope: MatchVariantAndInactiveScope<
|
type MatchVariantAndInactiveScope: MatchVariantAndInactiveScope<
|
||||||
|
@ -285,6 +287,9 @@ pub trait Type:
|
||||||
fn canonical(&self) -> CanonicalType;
|
fn canonical(&self) -> CanonicalType;
|
||||||
fn from_canonical(canonical_type: CanonicalType) -> Self;
|
fn from_canonical(canonical_type: CanonicalType) -> Self;
|
||||||
fn source_location() -> SourceLocation;
|
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> {}
|
pub trait BaseType: Type<BaseType = Self> + sealed::BaseTypeSealed + Into<CanonicalType> {}
|
||||||
|
@ -314,6 +319,7 @@ pub trait TypeWithDeref: Type {
|
||||||
impl Type for CanonicalType {
|
impl Type for CanonicalType {
|
||||||
type BaseType = CanonicalType;
|
type BaseType = CanonicalType;
|
||||||
type MaskType = CanonicalType;
|
type MaskType = CanonicalType;
|
||||||
|
type SimValue = OpaqueSimValue;
|
||||||
impl_match_variant_as_self!();
|
impl_match_variant_as_self!();
|
||||||
fn mask_type(&self) -> Self::MaskType {
|
fn mask_type(&self) -> Self::MaskType {
|
||||||
match self {
|
match self {
|
||||||
|
@ -339,6 +345,48 @@ impl Type for CanonicalType {
|
||||||
fn source_location() -> SourceLocation {
|
fn source_location() -> SourceLocation {
|
||||||
SourceLocation::builtin()
|
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 {
|
pub trait StaticType: Type {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
pub(crate) mod alternating_cell;
|
||||||
mod const_bool;
|
mod const_bool;
|
||||||
mod const_cmp;
|
mod const_cmp;
|
||||||
mod const_usize;
|
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::{
|
use fayalite::{
|
||||||
int::UIntValue,
|
int::UIntValue,
|
||||||
|
memory::{ReadStruct, ReadWriteStruct, WriteStruct},
|
||||||
|
module::{instance_with_loc, reg_builder_with_loc},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reset::ResetType,
|
reset::ResetType,
|
||||||
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation, ToSimValue},
|
sim::{
|
||||||
|
time::SimDuration,
|
||||||
|
value::{SimValue, ToSimValue},
|
||||||
|
vcd::VcdWriterDecls,
|
||||||
|
Simulation,
|
||||||
|
},
|
||||||
ty::StaticType,
|
ty::StaticType,
|
||||||
util::RcWriter,
|
util::RcWriter,
|
||||||
};
|
};
|
||||||
|
@ -395,32 +402,14 @@ fn test_enums() {
|
||||||
sim.write_reset(sim.io().cd.rst, false);
|
sim.write_reset(sim.io().cd.rst, false);
|
||||||
sim.advance_time(SimDuration::from_nanos(900));
|
sim.advance_time(SimDuration::from_nanos(900));
|
||||||
type BOutTy = HdlOption<(UInt<1>, Bool)>;
|
type BOutTy = HdlOption<(UInt<1>, Bool)>;
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct IO {
|
struct IO {
|
||||||
en: bool,
|
en: bool,
|
||||||
which_in: u8,
|
which_in: u8,
|
||||||
data_in: u8,
|
data_in: u8,
|
||||||
which_out: u8,
|
which_out: u8,
|
||||||
data_out: u8,
|
data_out: u8,
|
||||||
b_out: Expr<BOutTy>,
|
b_out: SimValue<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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let io_cycles = [
|
let io_cycles = [
|
||||||
IO {
|
IO {
|
||||||
|
@ -429,7 +418,7 @@ fn test_enums() {
|
||||||
data_in: 0,
|
data_in: 0,
|
||||||
which_out: 0,
|
which_out: 0,
|
||||||
data_out: 0,
|
data_out: 0,
|
||||||
b_out: HdlNone(),
|
b_out: HdlNone().to_sim_value(StaticType::TYPE),
|
||||||
},
|
},
|
||||||
IO {
|
IO {
|
||||||
en: true,
|
en: true,
|
||||||
|
@ -437,7 +426,7 @@ fn test_enums() {
|
||||||
data_in: 0,
|
data_in: 0,
|
||||||
which_out: 0,
|
which_out: 0,
|
||||||
data_out: 0,
|
data_out: 0,
|
||||||
b_out: HdlNone(),
|
b_out: HdlNone().to_sim_value(StaticType::TYPE),
|
||||||
},
|
},
|
||||||
IO {
|
IO {
|
||||||
en: false,
|
en: false,
|
||||||
|
@ -445,7 +434,7 @@ fn test_enums() {
|
||||||
data_in: 0,
|
data_in: 0,
|
||||||
which_out: 1,
|
which_out: 1,
|
||||||
data_out: 0,
|
data_out: 0,
|
||||||
b_out: HdlSome((0_hdl_u1, false)),
|
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
|
||||||
},
|
},
|
||||||
IO {
|
IO {
|
||||||
en: true,
|
en: true,
|
||||||
|
@ -453,7 +442,7 @@ fn test_enums() {
|
||||||
data_in: 0xF,
|
data_in: 0xF,
|
||||||
which_out: 1,
|
which_out: 1,
|
||||||
data_out: 0,
|
data_out: 0,
|
||||||
b_out: HdlSome((0_hdl_u1, false)),
|
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
|
||||||
},
|
},
|
||||||
IO {
|
IO {
|
||||||
en: true,
|
en: true,
|
||||||
|
@ -461,7 +450,7 @@ fn test_enums() {
|
||||||
data_in: 0xF,
|
data_in: 0xF,
|
||||||
which_out: 1,
|
which_out: 1,
|
||||||
data_out: 0x3,
|
data_out: 0x3,
|
||||||
b_out: HdlSome((1_hdl_u1, true)),
|
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
|
||||||
},
|
},
|
||||||
IO {
|
IO {
|
||||||
en: true,
|
en: true,
|
||||||
|
@ -469,7 +458,7 @@ fn test_enums() {
|
||||||
data_in: 0xF,
|
data_in: 0xF,
|
||||||
which_out: 1,
|
which_out: 1,
|
||||||
data_out: 0x3,
|
data_out: 0x3,
|
||||||
b_out: HdlSome((1_hdl_u1, true)),
|
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
|
||||||
},
|
},
|
||||||
IO {
|
IO {
|
||||||
en: true,
|
en: true,
|
||||||
|
@ -477,7 +466,7 @@ fn test_enums() {
|
||||||
data_in: 0xF,
|
data_in: 0xF,
|
||||||
which_out: 2,
|
which_out: 2,
|
||||||
data_out: 0xF,
|
data_out: 0xF,
|
||||||
b_out: HdlNone(),
|
b_out: HdlNone().to_sim_value(StaticType::TYPE),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
for (
|
for (
|
||||||
|
@ -509,7 +498,7 @@ fn test_enums() {
|
||||||
.to_bigint()
|
.to_bigint()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("known to be in range"),
|
.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!(
|
assert_eq!(
|
||||||
expected,
|
expected,
|
||||||
|
@ -538,9 +527,9 @@ fn test_enums() {
|
||||||
#[hdl_module(outline_generated)]
|
#[hdl_module(outline_generated)]
|
||||||
pub fn memories() {
|
pub fn memories() {
|
||||||
#[hdl]
|
#[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]
|
#[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]
|
#[hdl]
|
||||||
let mut mem = memory_with_init([(0x01u8, 0x23i8); 16]);
|
let mut mem = memory_with_init([(0x01u8, 0x23i8); 16]);
|
||||||
mem.read_latency(0);
|
mem.read_latency(0);
|
||||||
|
@ -559,120 +548,131 @@ fn test_memories() {
|
||||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||||
sim.write_clock(sim.io().r.clk, false);
|
sim.write_clock(sim.io().r.clk, false);
|
||||||
sim.write_clock(sim.io().w.clk, false);
|
sim.write_clock(sim.io().w.clk, false);
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[hdl(cmp_eq)]
|
||||||
struct IO {
|
struct IO {
|
||||||
r_addr: u8,
|
r_addr: UInt<4>,
|
||||||
r_en: bool,
|
r_en: Bool,
|
||||||
r_data: (u8, i8),
|
r_data: (UInt<8>, SInt<8>),
|
||||||
w_addr: u8,
|
w_addr: UInt<4>,
|
||||||
w_en: bool,
|
w_en: Bool,
|
||||||
w_data: (u8, i8),
|
w_data: (UInt<8>, SInt<8>),
|
||||||
w_mask: (bool, bool),
|
w_mask: (Bool, Bool),
|
||||||
}
|
}
|
||||||
let io_cycles = [
|
let io_cycles = [
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: false,
|
r_en: false,
|
||||||
r_data: (0, 0),
|
r_data: (0u8, 0i8),
|
||||||
w_addr: 0,
|
w_addr: 0_hdl_u4,
|
||||||
w_en: false,
|
w_en: false,
|
||||||
w_data: (0, 0),
|
w_data: (0u8, 0i8),
|
||||||
w_mask: (false, false),
|
w_mask: (false, false),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x1, 0x23),
|
r_data: (0x1u8, 0x23i8),
|
||||||
w_addr: 0,
|
w_addr: 0_hdl_u4,
|
||||||
w_en: true,
|
w_en: true,
|
||||||
w_data: (0x10, 0x20),
|
w_data: (0x10u8, 0x20i8),
|
||||||
w_mask: (true, true),
|
w_mask: (true, true),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x10, 0x20),
|
r_data: (0x10u8, 0x20i8),
|
||||||
w_addr: 0,
|
w_addr: 0_hdl_u4,
|
||||||
w_en: true,
|
w_en: true,
|
||||||
w_data: (0x30, 0x40),
|
w_data: (0x30u8, 0x40i8),
|
||||||
w_mask: (false, true),
|
w_mask: (false, true),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x10, 0x40),
|
r_data: (0x10u8, 0x40i8),
|
||||||
w_addr: 0,
|
w_addr: 0_hdl_u4,
|
||||||
w_en: true,
|
w_en: true,
|
||||||
w_data: (0x50, 0x60),
|
w_data: (0x50u8, 0x60i8),
|
||||||
w_mask: (true, false),
|
w_mask: (true, false),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x50, 0x40),
|
r_data: (0x50u8, 0x40i8),
|
||||||
w_addr: 0,
|
w_addr: 0_hdl_u4,
|
||||||
w_en: true,
|
w_en: true,
|
||||||
w_data: (0x70, -0x80),
|
w_data: (0x70u8, -0x80i8),
|
||||||
w_mask: (false, false),
|
w_mask: (false, false),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x50, 0x40),
|
r_data: (0x50u8, 0x40i8),
|
||||||
w_addr: 0,
|
w_addr: 0_hdl_u4,
|
||||||
w_en: false,
|
w_en: false,
|
||||||
w_data: (0x90, 0xA0u8 as i8),
|
w_data: (0x90u8, 0xA0u8 as i8),
|
||||||
w_mask: (false, false),
|
w_mask: (false, false),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x50, 0x40),
|
r_data: (0x50u8, 0x40i8),
|
||||||
w_addr: 1,
|
w_addr: 1_hdl_u4,
|
||||||
w_en: true,
|
w_en: true,
|
||||||
w_data: (0x90, 0xA0u8 as i8),
|
w_data: (0x90u8, 0xA0u8 as i8),
|
||||||
w_mask: (true, true),
|
w_mask: (true, true),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x50, 0x40),
|
r_data: (0x50u8, 0x40i8),
|
||||||
w_addr: 2,
|
w_addr: 2_hdl_u4,
|
||||||
w_en: true,
|
w_en: true,
|
||||||
w_data: (0xB0, 0xC0u8 as i8),
|
w_data: (0xB0u8, 0xC0u8 as i8),
|
||||||
w_mask: (true, true),
|
w_mask: (true, true),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 0,
|
r_addr: 0_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x50, 0x40),
|
r_data: (0x50u8, 0x40i8),
|
||||||
w_addr: 2,
|
w_addr: 2_hdl_u4,
|
||||||
w_en: false,
|
w_en: false,
|
||||||
w_data: (0xD0, 0xE0u8 as i8),
|
w_data: (0xD0u8, 0xE0u8 as i8),
|
||||||
w_mask: (true, true),
|
w_mask: (true, true),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 1,
|
r_addr: 1_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0x90, 0xA0u8 as i8),
|
r_data: (0x90u8, 0xA0u8 as i8),
|
||||||
w_addr: 2,
|
w_addr: 2_hdl_u4,
|
||||||
w_en: false,
|
w_en: false,
|
||||||
w_data: (0xD0, 0xE0u8 as i8),
|
w_data: (0xD0u8, 0xE0u8 as i8),
|
||||||
w_mask: (true, true),
|
w_mask: (true, true),
|
||||||
},
|
},
|
||||||
|
#[hdl]
|
||||||
IO {
|
IO {
|
||||||
r_addr: 2,
|
r_addr: 2_hdl_u4,
|
||||||
r_en: true,
|
r_en: true,
|
||||||
r_data: (0xB0, 0xC0u8 as i8),
|
r_data: (0xB0u8, 0xC0u8 as i8),
|
||||||
w_addr: 2,
|
w_addr: 2_hdl_u4,
|
||||||
w_en: false,
|
w_en: false,
|
||||||
w_data: (0xD0, 0xE0u8 as i8),
|
w_data: (0xD0u8, 0xE0u8 as i8),
|
||||||
w_mask: (true, true),
|
w_mask: (true, true),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
for (
|
for (cycle, expected) in io_cycles.into_iter().enumerate() {
|
||||||
cycle,
|
#[hdl]
|
||||||
expected @ IO {
|
let IO {
|
||||||
r_addr,
|
r_addr,
|
||||||
r_en,
|
r_en,
|
||||||
r_data: _,
|
r_data: _,
|
||||||
|
@ -680,37 +680,26 @@ fn test_memories() {
|
||||||
w_en,
|
w_en,
|
||||||
w_data,
|
w_data,
|
||||||
w_mask,
|
w_mask,
|
||||||
},
|
} = expected;
|
||||||
) in io_cycles.into_iter().enumerate()
|
sim.write(sim.io().r.addr, r_addr);
|
||||||
{
|
sim.write(sim.io().r.en, r_en);
|
||||||
sim.write_bool_or_int(sim.io().r.addr, r_addr.cast_to_static());
|
sim.write(sim.io().w.addr, w_addr);
|
||||||
sim.write_bool(sim.io().r.en, r_en);
|
sim.write(sim.io().w.en, w_en);
|
||||||
sim.write_bool_or_int(sim.io().w.addr, w_addr.cast_to_static());
|
sim.write(sim.io().w.data, w_data);
|
||||||
sim.write_bool(sim.io().w.en, w_en);
|
sim.write(sim.io().w.mask, w_mask);
|
||||||
sim.write_bool_or_int(sim.io().w.data.0, w_data.0);
|
let io = (#[hdl]
|
||||||
sim.write_bool_or_int(sim.io().w.data.1, w_data.1);
|
IO {
|
||||||
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 {
|
|
||||||
r_addr,
|
r_addr,
|
||||||
r_en,
|
r_en,
|
||||||
r_data: (
|
r_data: sim.read(sim.io().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"),
|
|
||||||
),
|
|
||||||
w_addr,
|
w_addr,
|
||||||
w_en,
|
w_en,
|
||||||
w_data,
|
w_data,
|
||||||
w_mask,
|
w_mask,
|
||||||
};
|
})
|
||||||
|
.to_sim_value(StaticType::TYPE);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expected,
|
expected.to_sim_value(StaticType::TYPE),
|
||||||
io,
|
io,
|
||||||
"vcd:\n{}\ncycle: {cycle}",
|
"vcd:\n{}\ncycle: {cycle}",
|
||||||
String::from_utf8(writer.take()).unwrap(),
|
String::from_utf8(writer.take()).unwrap(),
|
||||||
|
@ -738,7 +727,7 @@ fn test_memories() {
|
||||||
#[hdl_module(outline_generated)]
|
#[hdl_module(outline_generated)]
|
||||||
pub fn memories2() {
|
pub fn memories2() {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let rw: fayalite::memory::ReadWriteStruct<UInt<2>, ConstUsize<3>> = m.input();
|
let rw: ReadWriteStruct<UInt<2>, ConstUsize<3>> = m.input();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let mut mem = memory_with_init([HdlSome(true); 5]);
|
let mut mem = memory_with_init([HdlSome(true); 5]);
|
||||||
mem.read_latency(1);
|
mem.read_latency(1);
|
||||||
|
@ -1011,9 +1000,9 @@ fn test_memories2() {
|
||||||
#[hdl_module(outline_generated)]
|
#[hdl_module(outline_generated)]
|
||||||
pub fn memories3() {
|
pub fn memories3() {
|
||||||
#[hdl]
|
#[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]
|
#[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]
|
#[hdl]
|
||||||
let mut mem: MemBuilder<Array<UInt<8>, 8>> = memory();
|
let mut mem: MemBuilder<Array<UInt<8>, 8>> = memory();
|
||||||
mem.depth(8);
|
mem.depth(8);
|
||||||
|
@ -1443,3 +1432,172 @@ fn test_conditional_assignment_last() {
|
||||||
panic!();
|
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: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::conditional_assignment_last,
|
name: <simulator>::conditional_assignment_last,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: conditional_assignment_last,
|
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Scalar,
|
}.i,
|
||||||
},
|
],
|
||||||
range: TypeIndexRange {
|
uninitialized_ios: {},
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
io_targets: {
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
|
Instance {
|
||||||
},
|
name: <simulator>::conditional_assignment_last,
|
||||||
write: None,
|
instantiated: Module {
|
||||||
|
name: conditional_assignment_last,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.i,
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "conditional_assignment_last",
|
name: "conditional_assignment_last",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -68,45 +68,30 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uninitialized_inputs: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::connect_const,
|
name: <simulator>::connect_const,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: connect_const,
|
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>,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Scalar,
|
}.o,
|
||||||
},
|
],
|
||||||
range: TypeIndexRange {
|
uninitialized_ios: {},
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
io_targets: {
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
|
Instance {
|
||||||
},
|
name: <simulator>::connect_const,
|
||||||
write: None,
|
instantiated: Module {
|
||||||
|
name: connect_const,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.o,
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "connect_const",
|
name: "connect_const",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -97,79 +97,44 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uninitialized_inputs: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::connect_const_reset,
|
name: <simulator>::connect_const_reset,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: connect_const_reset,
|
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Scalar,
|
}.reset_out,
|
||||||
},
|
Instance {
|
||||||
range: TypeIndexRange {
|
name: <simulator>::connect_const_reset,
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
instantiated: Module {
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
|
name: connect_const_reset,
|
||||||
},
|
..
|
||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Scalar,
|
}.bit_out,
|
||||||
},
|
],
|
||||||
range: TypeIndexRange {
|
uninitialized_ios: {},
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
io_targets: {
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
|
Instance {
|
||||||
},
|
name: <simulator>::connect_const_reset,
|
||||||
write: None,
|
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,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "connect_const_reset",
|
name: "connect_const_reset",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -203,213 +203,58 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uninitialized_inputs: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::counter,
|
name: <simulator>::counter,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: counter,
|
name: counter,
|
||||||
..
|
..
|
||||||
},
|
|
||||||
}.cd: CompiledValue {
|
|
||||||
layout: CompiledTypeLayout {
|
|
||||||
ty: Bundle {
|
|
||||||
/* offset = 0 */
|
|
||||||
clk: Clock,
|
|
||||||
/* offset = 1 */
|
|
||||||
rst: AsyncReset,
|
|
||||||
},
|
},
|
||||||
layout: TypeLayout {
|
}.cd,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
Instance {
|
||||||
len: 0,
|
name: <simulator>::counter,
|
||||||
debug_data: [],
|
instantiated: Module {
|
||||||
..
|
name: counter,
|
||||||
},
|
..
|
||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Bundle {
|
}.count,
|
||||||
fields: [
|
],
|
||||||
CompiledBundleField {
|
uninitialized_ios: {},
|
||||||
offset: TypeIndex {
|
io_targets: {
|
||||||
small_slots: StatePartIndex<SmallSlots>(0),
|
Instance {
|
||||||
big_slots: StatePartIndex<BigSlots>(0),
|
name: <simulator>::counter,
|
||||||
},
|
instantiated: Module {
|
||||||
ty: CompiledTypeLayout {
|
name: counter,
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
}.cd,
|
||||||
range: TypeIndexRange {
|
Instance {
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
name: <simulator>::counter,
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
|
instantiated: Module {
|
||||||
},
|
name: counter,
|
||||||
write: None,
|
..
|
||||||
},
|
},
|
||||||
Instance {
|
}.cd.clk,
|
||||||
name: <simulator>::counter,
|
Instance {
|
||||||
instantiated: Module {
|
name: <simulator>::counter,
|
||||||
name: counter,
|
instantiated: Module {
|
||||||
..
|
name: counter,
|
||||||
},
|
..
|
||||||
}.cd.clk: CompiledValue {
|
},
|
||||||
layout: CompiledTypeLayout {
|
}.cd.rst,
|
||||||
ty: Clock,
|
Instance {
|
||||||
layout: TypeLayout {
|
name: <simulator>::counter,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
instantiated: Module {
|
||||||
len: 0,
|
name: counter,
|
||||||
debug_data: [],
|
..
|
||||||
..
|
},
|
||||||
},
|
}.count,
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "counter",
|
name: "counter",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -184,213 +184,58 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uninitialized_inputs: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::counter,
|
name: <simulator>::counter,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: counter,
|
name: counter,
|
||||||
..
|
..
|
||||||
},
|
|
||||||
}.cd: CompiledValue {
|
|
||||||
layout: CompiledTypeLayout {
|
|
||||||
ty: Bundle {
|
|
||||||
/* offset = 0 */
|
|
||||||
clk: Clock,
|
|
||||||
/* offset = 1 */
|
|
||||||
rst: SyncReset,
|
|
||||||
},
|
},
|
||||||
layout: TypeLayout {
|
}.cd,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
Instance {
|
||||||
len: 0,
|
name: <simulator>::counter,
|
||||||
debug_data: [],
|
instantiated: Module {
|
||||||
..
|
name: counter,
|
||||||
},
|
..
|
||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Bundle {
|
}.count,
|
||||||
fields: [
|
],
|
||||||
CompiledBundleField {
|
uninitialized_ios: {},
|
||||||
offset: TypeIndex {
|
io_targets: {
|
||||||
small_slots: StatePartIndex<SmallSlots>(0),
|
Instance {
|
||||||
big_slots: StatePartIndex<BigSlots>(0),
|
name: <simulator>::counter,
|
||||||
},
|
instantiated: Module {
|
||||||
ty: CompiledTypeLayout {
|
name: counter,
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
}.cd,
|
||||||
range: TypeIndexRange {
|
Instance {
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
name: <simulator>::counter,
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
|
instantiated: Module {
|
||||||
},
|
name: counter,
|
||||||
write: None,
|
..
|
||||||
},
|
},
|
||||||
Instance {
|
}.cd.clk,
|
||||||
name: <simulator>::counter,
|
Instance {
|
||||||
instantiated: Module {
|
name: <simulator>::counter,
|
||||||
name: counter,
|
instantiated: Module {
|
||||||
..
|
name: counter,
|
||||||
},
|
..
|
||||||
}.cd.clk: CompiledValue {
|
},
|
||||||
layout: CompiledTypeLayout {
|
}.cd.rst,
|
||||||
ty: Clock,
|
Instance {
|
||||||
layout: TypeLayout {
|
name: <simulator>::counter,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
instantiated: Module {
|
||||||
len: 0,
|
name: counter,
|
||||||
debug_data: [],
|
..
|
||||||
..
|
},
|
||||||
},
|
}.count,
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "counter",
|
name: "counter",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -88,10 +88,14 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uninitialized_inputs: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {},
|
base_targets: [],
|
||||||
made_initial_step: true,
|
uninitialized_ios: {},
|
||||||
needs_settle: false,
|
io_targets: {},
|
||||||
|
did_initial_settle: true,
|
||||||
|
},
|
||||||
|
extern_modules: [],
|
||||||
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "duplicate_names",
|
name: "duplicate_names",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -1215,389 +1215,128 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uninitialized_inputs: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::enums,
|
name: <simulator>::enums,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: enums,
|
name: enums,
|
||||||
..
|
..
|
||||||
},
|
|
||||||
}.b_out: CompiledValue {
|
|
||||||
layout: CompiledTypeLayout {
|
|
||||||
ty: Enum {
|
|
||||||
HdlNone,
|
|
||||||
HdlSome(Bundle {0: UInt<1>, 1: Bool}),
|
|
||||||
},
|
},
|
||||||
layout: TypeLayout {
|
}.cd,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
Instance {
|
||||||
len: 0,
|
name: <simulator>::enums,
|
||||||
debug_data: [],
|
instantiated: Module {
|
||||||
..
|
name: enums,
|
||||||
},
|
..
|
||||||
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}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Scalar,
|
}.en,
|
||||||
},
|
Instance {
|
||||||
range: TypeIndexRange {
|
name: <simulator>::enums,
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
instantiated: Module {
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 7, len: 1 },
|
name: enums,
|
||||||
},
|
..
|
||||||
write: None,
|
},
|
||||||
},
|
}.which_in,
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::enums,
|
name: <simulator>::enums,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: enums,
|
name: enums,
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
}.cd: CompiledValue {
|
}.data_in,
|
||||||
layout: CompiledTypeLayout {
|
Instance {
|
||||||
ty: Bundle {
|
name: <simulator>::enums,
|
||||||
/* offset = 0 */
|
instantiated: Module {
|
||||||
clk: Clock,
|
name: enums,
|
||||||
/* offset = 1 */
|
..
|
||||||
rst: SyncReset,
|
},
|
||||||
},
|
}.which_out,
|
||||||
layout: TypeLayout {
|
Instance {
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
name: <simulator>::enums,
|
||||||
len: 0,
|
instantiated: Module {
|
||||||
debug_data: [],
|
name: enums,
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
big_slots: StatePartLayout<BigSlots> {
|
}.data_out,
|
||||||
len: 2,
|
Instance {
|
||||||
debug_data: [
|
name: <simulator>::enums,
|
||||||
SlotDebugData {
|
instantiated: Module {
|
||||||
name: "InstantiatedModule(enums: enums).enums::cd.clk",
|
name: enums,
|
||||||
ty: Clock,
|
..
|
||||||
},
|
},
|
||||||
SlotDebugData {
|
}.b_out,
|
||||||
name: "InstantiatedModule(enums: enums).enums::cd.rst",
|
],
|
||||||
ty: SyncReset,
|
uninitialized_ios: {},
|
||||||
},
|
io_targets: {
|
||||||
],
|
Instance {
|
||||||
..
|
name: <simulator>::enums,
|
||||||
},
|
instantiated: Module {
|
||||||
},
|
name: enums,
|
||||||
body: Bundle {
|
..
|
||||||
fields: [
|
},
|
||||||
CompiledBundleField {
|
}.b_out,
|
||||||
offset: TypeIndex {
|
Instance {
|
||||||
small_slots: StatePartIndex<SmallSlots>(0),
|
name: <simulator>::enums,
|
||||||
big_slots: StatePartIndex<BigSlots>(0),
|
instantiated: Module {
|
||||||
},
|
name: enums,
|
||||||
ty: CompiledTypeLayout {
|
..
|
||||||
ty: Clock,
|
},
|
||||||
layout: TypeLayout {
|
}.cd,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
Instance {
|
||||||
len: 0,
|
name: <simulator>::enums,
|
||||||
debug_data: [],
|
instantiated: Module {
|
||||||
..
|
name: enums,
|
||||||
},
|
..
|
||||||
big_slots: StatePartLayout<BigSlots> {
|
},
|
||||||
len: 1,
|
}.cd.clk,
|
||||||
debug_data: [
|
Instance {
|
||||||
SlotDebugData {
|
name: <simulator>::enums,
|
||||||
name: "",
|
instantiated: Module {
|
||||||
ty: Clock,
|
name: enums,
|
||||||
},
|
..
|
||||||
],
|
},
|
||||||
..
|
}.cd.rst,
|
||||||
},
|
Instance {
|
||||||
},
|
name: <simulator>::enums,
|
||||||
body: Scalar,
|
instantiated: Module {
|
||||||
},
|
name: enums,
|
||||||
},
|
..
|
||||||
CompiledBundleField {
|
},
|
||||||
offset: TypeIndex {
|
}.data_in,
|
||||||
small_slots: StatePartIndex<SmallSlots>(0),
|
Instance {
|
||||||
big_slots: StatePartIndex<BigSlots>(1),
|
name: <simulator>::enums,
|
||||||
},
|
instantiated: Module {
|
||||||
ty: CompiledTypeLayout {
|
name: enums,
|
||||||
ty: SyncReset,
|
..
|
||||||
layout: TypeLayout {
|
},
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
}.data_out,
|
||||||
len: 0,
|
Instance {
|
||||||
debug_data: [],
|
name: <simulator>::enums,
|
||||||
..
|
instantiated: Module {
|
||||||
},
|
name: enums,
|
||||||
big_slots: StatePartLayout<BigSlots> {
|
..
|
||||||
len: 1,
|
},
|
||||||
debug_data: [
|
}.en,
|
||||||
SlotDebugData {
|
Instance {
|
||||||
name: "",
|
name: <simulator>::enums,
|
||||||
ty: SyncReset,
|
instantiated: Module {
|
||||||
},
|
name: enums,
|
||||||
],
|
..
|
||||||
..
|
},
|
||||||
},
|
}.which_in,
|
||||||
},
|
Instance {
|
||||||
body: Scalar,
|
name: <simulator>::enums,
|
||||||
},
|
instantiated: Module {
|
||||||
},
|
name: enums,
|
||||||
],
|
..
|
||||||
},
|
},
|
||||||
},
|
}.which_out,
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "enums",
|
name: "enums",
|
||||||
children: [
|
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: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::memories2,
|
name: <simulator>::memories2,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: memories2,
|
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,
|
|
||||||
},
|
},
|
||||||
layout: TypeLayout {
|
}.rw,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
],
|
||||||
len: 0,
|
uninitialized_ios: {},
|
||||||
debug_data: [],
|
io_targets: {
|
||||||
..
|
Instance {
|
||||||
},
|
name: <simulator>::memories2,
|
||||||
big_slots: StatePartLayout<BigSlots> {
|
instantiated: Module {
|
||||||
len: 7,
|
name: memories2,
|
||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Bundle {
|
}.rw,
|
||||||
fields: [
|
Instance {
|
||||||
CompiledBundleField {
|
name: <simulator>::memories2,
|
||||||
offset: TypeIndex {
|
instantiated: Module {
|
||||||
small_slots: StatePartIndex<SmallSlots>(0),
|
name: memories2,
|
||||||
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.addr,
|
||||||
range: TypeIndexRange {
|
Instance {
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
name: <simulator>::memories2,
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 7 },
|
instantiated: Module {
|
||||||
},
|
name: memories2,
|
||||||
write: None,
|
..
|
||||||
},
|
},
|
||||||
Instance {
|
}.rw.clk,
|
||||||
name: <simulator>::memories2,
|
Instance {
|
||||||
instantiated: Module {
|
name: <simulator>::memories2,
|
||||||
name: memories2,
|
instantiated: Module {
|
||||||
..
|
name: memories2,
|
||||||
},
|
..
|
||||||
}.rw.addr: CompiledValue {
|
},
|
||||||
layout: CompiledTypeLayout {
|
}.rw.en,
|
||||||
ty: UInt<3>,
|
Instance {
|
||||||
layout: TypeLayout {
|
name: <simulator>::memories2,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
instantiated: Module {
|
||||||
len: 0,
|
name: memories2,
|
||||||
debug_data: [],
|
..
|
||||||
..
|
},
|
||||||
},
|
}.rw.rdata,
|
||||||
big_slots: StatePartLayout<BigSlots> {
|
Instance {
|
||||||
len: 1,
|
name: <simulator>::memories2,
|
||||||
debug_data: [
|
instantiated: Module {
|
||||||
SlotDebugData {
|
name: memories2,
|
||||||
name: "",
|
..
|
||||||
ty: UInt<3>,
|
},
|
||||||
},
|
}.rw.wdata,
|
||||||
],
|
Instance {
|
||||||
..
|
name: <simulator>::memories2,
|
||||||
},
|
instantiated: Module {
|
||||||
},
|
name: memories2,
|
||||||
body: Scalar,
|
..
|
||||||
},
|
},
|
||||||
range: TypeIndexRange {
|
}.rw.wmask,
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
Instance {
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
|
name: <simulator>::memories2,
|
||||||
},
|
instantiated: Module {
|
||||||
write: None,
|
name: memories2,
|
||||||
},
|
..
|
||||||
Instance {
|
},
|
||||||
name: <simulator>::memories2,
|
}.rw.wmode,
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "memories2",
|
name: "memories2",
|
||||||
children: [
|
children: [
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -216,313 +216,58 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uninitialized_inputs: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::mod1,
|
name: <simulator>::mod1,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: mod1,
|
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>,
|
|
||||||
},
|
},
|
||||||
layout: TypeLayout {
|
}.o,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
],
|
||||||
len: 0,
|
uninitialized_ios: {},
|
||||||
debug_data: [],
|
io_targets: {
|
||||||
..
|
Instance {
|
||||||
},
|
name: <simulator>::mod1,
|
||||||
big_slots: StatePartLayout<BigSlots> {
|
instantiated: Module {
|
||||||
len: 4,
|
name: mod1,
|
||||||
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>,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Bundle {
|
}.o,
|
||||||
fields: [
|
Instance {
|
||||||
CompiledBundleField {
|
name: <simulator>::mod1,
|
||||||
offset: TypeIndex {
|
instantiated: Module {
|
||||||
small_slots: StatePartIndex<SmallSlots>(0),
|
name: mod1,
|
||||||
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.i,
|
||||||
range: TypeIndexRange {
|
Instance {
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
name: <simulator>::mod1,
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 4 },
|
instantiated: Module {
|
||||||
},
|
name: mod1,
|
||||||
write: None,
|
..
|
||||||
},
|
},
|
||||||
Instance {
|
}.o.i2,
|
||||||
name: <simulator>::mod1,
|
Instance {
|
||||||
instantiated: Module {
|
name: <simulator>::mod1,
|
||||||
name: mod1,
|
instantiated: Module {
|
||||||
..
|
name: mod1,
|
||||||
},
|
..
|
||||||
}.o.i: CompiledValue {
|
},
|
||||||
layout: CompiledTypeLayout {
|
}.o.o,
|
||||||
ty: UInt<4>,
|
Instance {
|
||||||
layout: TypeLayout {
|
name: <simulator>::mod1,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
instantiated: Module {
|
||||||
len: 0,
|
name: mod1,
|
||||||
debug_data: [],
|
..
|
||||||
..
|
},
|
||||||
},
|
}.o.o2,
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "mod1",
|
name: "mod1",
|
||||||
children: [
|
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: {},
|
main_module: SimulationModuleState {
|
||||||
io_targets: {
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
name: <simulator>::shift_register,
|
name: <simulator>::shift_register,
|
||||||
instantiated: Module {
|
instantiated: Module {
|
||||||
name: shift_register,
|
name: shift_register,
|
||||||
..
|
..
|
||||||
},
|
|
||||||
}.cd: CompiledValue {
|
|
||||||
layout: CompiledTypeLayout {
|
|
||||||
ty: Bundle {
|
|
||||||
/* offset = 0 */
|
|
||||||
clk: Clock,
|
|
||||||
/* offset = 1 */
|
|
||||||
rst: SyncReset,
|
|
||||||
},
|
},
|
||||||
layout: TypeLayout {
|
}.cd,
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
Instance {
|
||||||
len: 0,
|
name: <simulator>::shift_register,
|
||||||
debug_data: [],
|
instantiated: Module {
|
||||||
..
|
name: shift_register,
|
||||||
},
|
..
|
||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
body: Bundle {
|
}.d,
|
||||||
fields: [
|
Instance {
|
||||||
CompiledBundleField {
|
name: <simulator>::shift_register,
|
||||||
offset: TypeIndex {
|
instantiated: Module {
|
||||||
small_slots: StatePartIndex<SmallSlots>(0),
|
name: shift_register,
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
}.q,
|
||||||
range: TypeIndexRange {
|
],
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
uninitialized_ios: {},
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
|
io_targets: {
|
||||||
},
|
Instance {
|
||||||
write: None,
|
name: <simulator>::shift_register,
|
||||||
},
|
instantiated: Module {
|
||||||
Instance {
|
name: shift_register,
|
||||||
name: <simulator>::shift_register,
|
..
|
||||||
instantiated: Module {
|
},
|
||||||
name: shift_register,
|
}.cd,
|
||||||
..
|
Instance {
|
||||||
},
|
name: <simulator>::shift_register,
|
||||||
}.cd.clk: CompiledValue {
|
instantiated: Module {
|
||||||
layout: CompiledTypeLayout {
|
name: shift_register,
|
||||||
ty: Clock,
|
..
|
||||||
layout: TypeLayout {
|
},
|
||||||
small_slots: StatePartLayout<SmallSlots> {
|
}.cd.clk,
|
||||||
len: 0,
|
Instance {
|
||||||
debug_data: [],
|
name: <simulator>::shift_register,
|
||||||
..
|
instantiated: Module {
|
||||||
},
|
name: shift_register,
|
||||||
big_slots: StatePartLayout<BigSlots> {
|
..
|
||||||
len: 1,
|
},
|
||||||
debug_data: [
|
}.cd.rst,
|
||||||
SlotDebugData {
|
Instance {
|
||||||
name: "",
|
name: <simulator>::shift_register,
|
||||||
ty: Clock,
|
instantiated: Module {
|
||||||
},
|
name: shift_register,
|
||||||
],
|
..
|
||||||
..
|
},
|
||||||
},
|
}.d,
|
||||||
},
|
Instance {
|
||||||
body: Scalar,
|
name: <simulator>::shift_register,
|
||||||
},
|
instantiated: Module {
|
||||||
range: TypeIndexRange {
|
name: shift_register,
|
||||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
..
|
||||||
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
|
},
|
||||||
},
|
}.q,
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
made_initial_step: true,
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "shift_register",
|
name: "shift_register",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -160,7 +160,8 @@
|
||||||
"data": {
|
"data": {
|
||||||
"$kind": "Struct",
|
"$kind": "Struct",
|
||||||
"verilog_name": "Visible",
|
"verilog_name": "Visible",
|
||||||
"parameters": "Visible"
|
"parameters": "Visible",
|
||||||
|
"simulation": "Visible"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ExternModuleParameter": {
|
"ExternModuleParameter": {
|
||||||
|
@ -1269,6 +1270,11 @@
|
||||||
"$kind": "Opaque"
|
"$kind": "Opaque"
|
||||||
},
|
},
|
||||||
"generics": "<T: ?Sized + crate::phantom_const::PhantomConstValue>"
|
"generics": "<T: ?Sized + crate::phantom_const::PhantomConstValue>"
|
||||||
|
},
|
||||||
|
"ExternModuleSimulation": {
|
||||||
|
"data": {
|
||||||
|
"$kind": "Opaque"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue