1
0
Fork 0

Compare commits

...

10 commits

45 changed files with 15690 additions and 1320 deletions

View file

@ -12,7 +12,7 @@ Fayalite is a library for designing digital hardware -- a hardware description l
[Blinky example]: crates/fayalite/examples/blinky.rs [Blinky example]: crates/fayalite/examples/blinky.rs
This uses the container image containing all the external programs and files that Fayalite needs to build for FPGAs, the sources for the container image are in https://git.libre-chip.org/libre-chip/fayalite-deps This uses the container image containing all the external programs and files that Fayalite needs to build for FPGAs, the sources for the container image are in <https://git.libre-chip.org/libre-chip/fayalite-deps>
Steps: Steps:

View file

@ -87,7 +87,11 @@ impl ParsedBundle {
no_static: _, no_static: _,
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq: _, cmp_eq: _,
ref get,
} = options.body; } = options.body;
if let Some((get, ..)) = get {
errors.error(get, "#[hdl(get(...))] is not allowed on structs");
}
let mut fields = match fields { let mut fields = match fields {
syn::Fields::Named(fields) => fields, syn::Fields::Named(fields) => fields,
syn::Fields::Unnamed(fields) => { syn::Fields::Unnamed(fields) => {
@ -445,6 +449,7 @@ impl ToTokens for ParsedBundle {
no_static, no_static,
no_runtime_generics, no_runtime_generics,
cmp_eq, cmp_eq,
get: _,
} = &options.body; } = &options.body;
let target = get_target(target, ident); let target = get_target(target, ident);
let mut item_attrs = attrs.clone(); let mut item_attrs = attrs.clone();

View file

@ -159,10 +159,14 @@ impl ParsedEnum {
no_static: _, no_static: _,
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq, cmp_eq,
ref get,
} = options.body; } = options.body;
if let Some((cmp_eq,)) = cmp_eq { if let Some((cmp_eq,)) = cmp_eq {
errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for enums"); errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for enums");
} }
if let Some((get, ..)) = get {
errors.error(get, "#[hdl(get(...))] is not allowed on enums");
}
attrs.retain(|attr| { attrs.retain(|attr| {
if attr.path().is_ident("repr") { if attr.path().is_ident("repr") {
errors.error(attr, "#[repr] is not supported on #[hdl] enums"); errors.error(attr, "#[repr] is not supported on #[hdl] enums");
@ -225,6 +229,7 @@ impl ToTokens for ParsedEnum {
no_static, no_static,
no_runtime_generics, no_runtime_generics,
cmp_eq: _, // TODO: implement cmp_eq for enums cmp_eq: _, // TODO: implement cmp_eq for enums
get: _,
} = &options.body; } = &options.body;
let target = get_target(target, ident); let target = get_target(target, ident);
let mut struct_attrs = attrs.clone(); let mut struct_attrs = attrs.clone();

View file

@ -3,29 +3,264 @@
use crate::{ use crate::{
Errors, HdlAttr, Errors, HdlAttr,
hdl_type_common::{ hdl_type_common::{
ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, TypesParser, ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType,
get_target, PhantomConstGetBound, TypesParser, WrappedInConst, common_derives, get_target, known_items,
}, },
kw, kw,
}; };
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::ToTokens; use quote::{ToTokens, format_ident, quote_spanned};
use syn::{Attribute, Generics, Ident, ItemType, Token, Type, Visibility, parse_quote_spanned}; use syn::{
Attribute, Expr, Fields, GenericParam, Generics, Ident, ItemStruct, ItemType, Token, Type,
TypeGroup, TypeParam, TypeParen, Visibility, parse_quote_spanned, punctuated::Pair,
token::Paren,
};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct ParsedTypeAlias { pub(crate) struct PhantomConstAccessorTypeParam {
pub(crate) attrs: Vec<Attribute>, attrs: Vec<Attribute>,
pub(crate) options: HdlAttr<ItemOptions, kw::hdl>, ident: Ident,
pub(crate) vis: Visibility, colon_token: Token![:],
pub(crate) type_token: Token![type], phantom_const_get_bound: PhantomConstGetBound,
pub(crate) ident: Ident, plus_token: Option<Token![+]>,
pub(crate) generics: MaybeParsed<ParsedGenerics, Generics>, }
pub(crate) eq_token: Token![=],
pub(crate) ty: MaybeParsed<ParsedType, Type>, impl From<PhantomConstAccessorTypeParam> for TypeParam {
pub(crate) semi_token: Token![;], fn from(value: PhantomConstAccessorTypeParam) -> Self {
let PhantomConstAccessorTypeParam {
attrs,
ident,
colon_token,
phantom_const_get_bound,
plus_token,
} = value;
TypeParam {
attrs,
ident,
colon_token: Some(colon_token),
bounds: FromIterator::from_iter([Pair::new(
phantom_const_get_bound.into(),
plus_token,
)]),
eq_token: None,
default: None,
}
}
}
impl From<PhantomConstAccessorTypeParam> for GenericParam {
fn from(value: PhantomConstAccessorTypeParam) -> Self {
TypeParam::from(value).into()
}
}
impl PhantomConstAccessorTypeParam {
fn parse_opt(generic_param: GenericParam) -> Option<Self> {
let GenericParam::Type(TypeParam {
attrs,
ident,
colon_token,
bounds,
eq_token: None,
default: None,
}) = generic_param
else {
return None;
};
let colon_token = colon_token.unwrap_or(Token![:](ident.span()));
let mut bounds = bounds.into_pairs();
let (bound, plus_token) = bounds.next()?.into_tuple();
let phantom_const_get_bound = PhantomConstGetBound::parse_type_param_bound(bound)
.ok()?
.ok()?;
let None = bounds.next() else {
return None;
};
Some(Self {
attrs,
ident,
colon_token,
phantom_const_get_bound,
plus_token,
})
}
}
#[derive(Clone, Debug)]
pub(crate) struct PhantomConstAccessorGenerics {
lt_token: Token![<],
type_param: PhantomConstAccessorTypeParam,
comma_token: Option<Token![,]>,
gt_token: Token![>],
}
impl From<PhantomConstAccessorGenerics> for Generics {
fn from(value: PhantomConstAccessorGenerics) -> Self {
let PhantomConstAccessorGenerics {
lt_token,
type_param,
comma_token,
gt_token,
} = value;
Generics {
lt_token: Some(lt_token),
params: FromIterator::from_iter([Pair::new(type_param.into(), comma_token)]),
gt_token: Some(gt_token),
where_clause: None,
}
}
}
impl<'a> From<&'a PhantomConstAccessorGenerics> for Generics {
fn from(value: &'a PhantomConstAccessorGenerics) -> Self {
value.clone().into()
}
}
impl PhantomConstAccessorGenerics {
fn parse_opt(generics: Generics) -> Option<Self> {
let Generics {
lt_token,
params,
gt_token,
where_clause: None,
} = generics
else {
return None;
};
let mut params = params.into_pairs();
let (generic_param, comma_token) = params.next()?.into_tuple();
let type_param = PhantomConstAccessorTypeParam::parse_opt(generic_param)?;
let span = type_param.ident.span();
let lt_token = lt_token.unwrap_or(Token![<](span));
let gt_token = gt_token.unwrap_or(Token![>](span));
let None = params.next() else {
return None;
};
Some(Self {
lt_token,
type_param,
comma_token,
gt_token,
})
}
}
#[derive(Clone, Debug)]
pub(crate) enum ParsedTypeAlias {
TypeAlias {
attrs: Vec<Attribute>,
options: HdlAttr<ItemOptions, kw::hdl>,
vis: Visibility,
type_token: Token![type],
ident: Ident,
generics: MaybeParsed<ParsedGenerics, Generics>,
eq_token: Token![=],
ty: MaybeParsed<ParsedType, Type>,
semi_token: Token![;],
},
PhantomConstAccessor {
attrs: Vec<Attribute>,
options: HdlAttr<ItemOptions, kw::hdl>,
get: (kw::get, Paren, Expr),
vis: Visibility,
type_token: Token![type],
ident: Ident,
generics: PhantomConstAccessorGenerics,
eq_token: Token![=],
ty: Type,
ty_is_dyn_size: Option<known_items::DynSize>,
semi_token: Token![;],
},
} }
impl ParsedTypeAlias { impl ParsedTypeAlias {
fn ty_is_dyn_size(ty: &Type) -> Option<known_items::DynSize> {
match ty {
Type::Group(TypeGroup {
group_token: _,
elem,
}) => Self::ty_is_dyn_size(elem),
Type::Paren(TypeParen {
paren_token: _,
elem,
}) => Self::ty_is_dyn_size(elem),
Type::Path(syn::TypePath { qself: None, path }) => {
known_items::DynSize::parse_path(path.clone()).ok()
}
_ => None,
}
}
fn parse_phantom_const_accessor(
item: ItemType,
mut errors: Errors,
options: HdlAttr<ItemOptions, kw::hdl>,
get: (kw::get, Paren, Expr),
) -> syn::Result<Self> {
let ItemType {
attrs,
vis,
type_token,
ident,
generics,
eq_token,
ty,
semi_token,
} = item;
let ItemOptions {
outline_generated: _,
ref target,
custom_bounds,
no_static,
no_runtime_generics,
cmp_eq,
get: _,
} = options.body;
if let Some((no_static,)) = no_static {
errors.error(no_static, "no_static is not valid on type aliases");
}
if let Some((target, ..)) = target {
errors.error(
target,
"target is not implemented on PhantomConstGet type aliases",
);
}
if let Some((no_runtime_generics,)) = no_runtime_generics {
errors.error(
no_runtime_generics,
"no_runtime_generics is not implemented on PhantomConstGet type aliases",
);
}
if let Some((cmp_eq,)) = cmp_eq {
errors.error(cmp_eq, "cmp_eq is not valid on type aliases");
}
if let Some((custom_bounds,)) = custom_bounds {
errors.error(
custom_bounds,
"custom_bounds is not implemented on PhantomConstGet type aliases",
);
}
let Some(generics) = PhantomConstAccessorGenerics::parse_opt(generics) else {
errors.error(ident, "#[hdl(get(...))] type alias must be of the form:\ntype MyTypeGetter<P: PhantomConstGet<MyType>> = RetType;");
errors.finish()?;
unreachable!();
};
errors.finish()?;
let ty_is_dyn_size = Self::ty_is_dyn_size(&ty);
Ok(Self::PhantomConstAccessor {
attrs,
options,
get,
vis,
type_token,
ident,
generics,
eq_token,
ty: *ty,
ty_is_dyn_size,
semi_token,
})
}
fn parse(item: ItemType) -> syn::Result<Self> { fn parse(item: ItemType) -> syn::Result<Self> {
let ItemType { let ItemType {
mut attrs, mut attrs,
@ -51,7 +286,25 @@ impl ParsedTypeAlias {
no_static, no_static,
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq, cmp_eq,
ref mut get,
} = options.body; } = options.body;
if let Some(get) = get.take() {
return Self::parse_phantom_const_accessor(
ItemType {
attrs,
vis,
type_token,
ident,
generics,
eq_token,
ty,
semi_token,
},
errors,
options,
get,
);
}
if let Some((no_static,)) = no_static { if let Some((no_static,)) = no_static {
errors.error(no_static, "no_static is not valid on type aliases"); errors.error(no_static, "no_static is not valid on type aliases");
} }
@ -67,7 +320,7 @@ impl ParsedTypeAlias {
}; };
let ty = TypesParser::maybe_run(generics.as_ref(), *ty, &mut errors); let ty = TypesParser::maybe_run(generics.as_ref(), *ty, &mut errors);
errors.finish()?; errors.finish()?;
Ok(Self { Ok(Self::TypeAlias {
attrs, attrs,
options, options,
vis, vis,
@ -83,7 +336,8 @@ impl ParsedTypeAlias {
impl ToTokens for ParsedTypeAlias { impl ToTokens for ParsedTypeAlias {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let Self { match self {
Self::TypeAlias {
attrs, attrs,
options, options,
vis, vis,
@ -93,7 +347,7 @@ impl ToTokens for ParsedTypeAlias {
eq_token, eq_token,
ty, ty,
semi_token, semi_token,
} = self; } => {
let ItemOptions { let ItemOptions {
outline_generated: _, outline_generated: _,
target, target,
@ -101,6 +355,7 @@ impl ToTokens for ParsedTypeAlias {
no_static: _, no_static: _,
no_runtime_generics, no_runtime_generics,
cmp_eq: _, cmp_eq: _,
get: _,
} = &options.body; } = &options.body;
let target = get_target(target, ident); let target = get_target(target, ident);
let mut type_attrs = attrs.clone(); let mut type_attrs = attrs.clone();
@ -126,11 +381,110 @@ impl ToTokens for ParsedTypeAlias {
}) })
} }
} }
Self::PhantomConstAccessor {
attrs,
options,
get: (_get_kw, _get_paren, get_expr),
vis,
type_token,
ident,
generics,
eq_token,
ty,
ty_is_dyn_size,
semi_token,
} => {
let ItemOptions {
outline_generated: _,
target: _,
custom_bounds: _,
no_static: _,
no_runtime_generics: _,
cmp_eq: _,
get: _,
} = &options.body;
let span = ident.span();
let mut type_attrs = attrs.clone();
type_attrs.push(parse_quote_spanned! {span=>
#[allow(type_alias_bounds)]
});
let type_param_ident = &generics.type_param.ident;
let syn_generics = Generics::from(generics);
ItemType {
attrs: type_attrs,
vis: vis.clone(),
type_token: *type_token,
ident: ident.clone(),
generics: syn_generics.clone(),
eq_token: *eq_token,
ty: parse_quote_spanned! {span=>
<#ty as ::fayalite::phantom_const::ReturnSelfUnchanged<#type_param_ident>>::Type
},
semi_token: *semi_token,
}
.to_tokens(tokens);
let generics_accumulation_ident =
format_ident!("__{}__GenericsAccumulation", ident);
ItemStruct {
attrs: vec![
common_derives(span),
parse_quote_spanned! {span=>
#[allow(non_camel_case_types)]
},
],
vis: vis.clone(),
struct_token: Token![struct](span),
ident: generics_accumulation_ident.clone(),
generics: Generics::default(),
fields: Fields::Unnamed(parse_quote_spanned! {span=>
(())
}),
semi_token: Some(Token![;](span)),
}
.to_tokens(tokens);
quote_spanned! {span=>
#[allow(non_upper_case_globals, dead_code)]
#vis const #ident: #generics_accumulation_ident = #generics_accumulation_ident(());
}
.to_tokens(tokens);
let mut wrapped_in_const = WrappedInConst::new(tokens, span);
let tokens = wrapped_in_const.inner();
let (impl_generics, _type_generics, where_clause) = syn_generics.split_for_impl();
let phantom_const_get_ty = &generics.type_param.phantom_const_get_bound.ty;
let index_output = if let Some(ty_is_dyn_size) = ty_is_dyn_size {
known_items::usize(ty_is_dyn_size.span).to_token_stream()
} else {
ty.to_token_stream()
};
quote_spanned! {span=>
#[allow(non_upper_case_globals)]
#[automatically_derived]
impl #impl_generics ::fayalite::__std::ops::Index<#type_param_ident>
for #generics_accumulation_ident
#where_clause
{
type Output = #index_output;
fn index(&self, __param: #type_param_ident) -> &Self::Output {
::fayalite::phantom_const::type_alias_phantom_const_get_helper::<#phantom_const_get_ty, #index_output>(
__param,
#get_expr,
)
}
}
}
.to_tokens(tokens);
}
}
}
} }
pub(crate) fn hdl_type_alias_impl(item: ItemType) -> syn::Result<TokenStream> { pub(crate) fn hdl_type_alias_impl(item: ItemType) -> syn::Result<TokenStream> {
let item = ParsedTypeAlias::parse(item)?; let item = ParsedTypeAlias::parse(item)?;
let outline_generated = item.options.body.outline_generated; let outline_generated = match &item {
ParsedTypeAlias::TypeAlias { options, .. }
| ParsedTypeAlias::PhantomConstAccessor { options, .. } => options.body.outline_generated,
};
let mut contents = item.to_token_stream(); let mut contents = item.to_token_stream();
if outline_generated.is_some() { if outline_generated.is_some() {
contents = crate::outline_generated(contents, "hdl-type-alias-"); contents = crate::outline_generated(contents, "hdl-type-alias-");

View file

@ -8,9 +8,9 @@ use syn::{
AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup, AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup,
ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed, ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed,
FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct, FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct,
Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, Turbofish, Type, Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound, Turbofish,
TypeGenerics, TypeGroup, TypeParam, TypeParen, TypePath, TypeTuple, Visibility, WhereClause, Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath, TypeTuple,
WherePredicate, Visibility, WhereClause, WherePredicate,
parse::{Parse, ParseStream}, parse::{Parse, ParseStream},
parse_quote, parse_quote_spanned, parse_quote, parse_quote_spanned,
punctuated::{Pair, Punctuated}, punctuated::{Pair, Punctuated},
@ -27,6 +27,7 @@ crate::options! {
NoStatic(no_static), NoStatic(no_static),
NoRuntimeGenerics(no_runtime_generics), NoRuntimeGenerics(no_runtime_generics),
CmpEq(cmp_eq), CmpEq(cmp_eq),
Get(get, Expr),
} }
} }
@ -2045,6 +2046,7 @@ pub(crate) mod known_items {
impl_known_item!(::fayalite::int::Size); impl_known_item!(::fayalite::int::Size);
impl_known_item!(::fayalite::int::UInt); impl_known_item!(::fayalite::int::UInt);
impl_known_item!(::fayalite::int::UIntType); impl_known_item!(::fayalite::int::UIntType);
impl_known_item!(::fayalite::phantom_const::PhantomConstGet);
impl_known_item!(::fayalite::reset::ResetType); impl_known_item!(::fayalite::reset::ResetType);
impl_known_item!(::fayalite::ty::CanonicalType); impl_known_item!(::fayalite::ty::CanonicalType);
impl_known_item!(::fayalite::ty::StaticType); impl_known_item!(::fayalite::ty::StaticType);
@ -2063,6 +2065,174 @@ pub(crate) mod known_items {
); );
} }
#[derive(Clone, Debug)]
pub(crate) struct PhantomConstGetBound {
pub(crate) phantom_const_get: known_items::PhantomConstGet,
pub(crate) colon2_token: Option<Token![::]>,
pub(crate) lt_token: Token![<],
pub(crate) ty: Type,
pub(crate) comma_token: Option<Token![,]>,
pub(crate) gt_token: Token![>],
}
impl PhantomConstGetBound {
pub(crate) fn parse_path_with_arguments(path: Path) -> syn::Result<Result<Self, Path>> {
match known_items::PhantomConstGet::parse_path_with_arguments(path) {
Ok((phantom_const_get, arguments)) => {
Self::parse_path_and_arguments(phantom_const_get, arguments).map(Ok)
}
Err(path) => Ok(Err(path)),
}
}
pub(crate) fn parse_path_and_arguments(
phantom_const_get: known_items::PhantomConstGet,
arguments: PathArguments,
) -> syn::Result<Self> {
let error = |arguments: PathArguments, message: &str| {
let mut path = phantom_const_get.path.clone();
path.segments.last_mut().expect("known to exist").arguments = arguments;
syn::Error::new_spanned(path, message)
};
match arguments {
PathArguments::None => Err(error(arguments, "missing generics for PhantomConstGet")),
PathArguments::AngleBracketed(AngleBracketedGenericArguments {
colon2_token,
lt_token,
args,
gt_token,
}) => {
let error = |args: Punctuated<GenericArgument, Token![,]>, message| {
error(
PathArguments::AngleBracketed(AngleBracketedGenericArguments {
colon2_token,
lt_token,
args,
gt_token,
}),
message,
)
};
let mut args = args.into_pairs().peekable();
let Some((generic_argument, comma_token)) = args.next().map(Pair::into_tuple)
else {
return Err(error(
Default::default(),
"PhantomConstGet takes a type argument but no generic arguments were supplied",
));
};
if args.peek().is_some() {
return Err(error(
[Pair::new(generic_argument, comma_token)]
.into_iter()
.chain(args)
.collect(),
"PhantomConstGet takes a single type argument but too many generic arguments were supplied",
));
};
let GenericArgument::Type(ty) = generic_argument else {
return Err(error(
Punctuated::from_iter([Pair::new(generic_argument, comma_token)]),
"PhantomConstGet requires a type argument",
));
};
Ok(Self {
phantom_const_get,
colon2_token,
lt_token,
ty,
comma_token,
gt_token,
})
}
PathArguments::Parenthesized(_) => Err(error(
arguments,
"parenthetical generics are not valid for PhantomConstGet",
)),
}
}
pub(crate) fn parse_type_param_bound(
bound: TypeParamBound,
) -> syn::Result<Result<Self, TypeParamBound>> {
let TypeParamBound::Trait(TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path,
}) = bound
else {
return Ok(Err(bound));
};
Ok(match Self::parse_path_with_arguments(path)? {
Ok(v) => Ok(v),
Err(path) => Err(TypeParamBound::Trait(TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path,
})),
})
}
}
impl ToTokens for PhantomConstGetBound {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self {
phantom_const_get,
colon2_token,
lt_token,
ty,
comma_token,
gt_token,
} = self;
phantom_const_get.to_tokens(tokens);
colon2_token.to_tokens(tokens);
lt_token.to_tokens(tokens);
ty.to_tokens(tokens);
comma_token.to_tokens(tokens);
gt_token.to_tokens(tokens);
}
}
impl From<PhantomConstGetBound> for Path {
fn from(value: PhantomConstGetBound) -> Self {
let PhantomConstGetBound {
phantom_const_get,
colon2_token,
lt_token,
ty,
comma_token,
gt_token,
} = value;
let mut path = phantom_const_get.path;
path.segments.last_mut().expect("known to exist").arguments =
PathArguments::AngleBracketed(AngleBracketedGenericArguments {
colon2_token,
lt_token,
args: FromIterator::from_iter([Pair::new(GenericArgument::Type(ty), comma_token)]),
gt_token,
});
path
}
}
impl From<PhantomConstGetBound> for TraitBound {
fn from(value: PhantomConstGetBound) -> Self {
let path = Path::from(value);
TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path,
}
}
}
impl From<PhantomConstGetBound> for TypeParamBound {
fn from(value: PhantomConstGetBound) -> Self {
TraitBound::from(value).into()
}
}
macro_rules! impl_bounds { macro_rules! impl_bounds {
( (
#[struct = $struct_type:ident] #[struct = $struct_type:ident]
@ -2070,6 +2240,10 @@ macro_rules! impl_bounds {
$( $(
$Variant:ident, $Variant:ident,
)* )*
$(
#[has_body]
$VariantHasBody:ident($variant_has_body_ty:ty),
)*
$( $(
#[unknown] #[unknown]
$Unknown:ident, $Unknown:ident,
@ -2079,6 +2253,7 @@ macro_rules! impl_bounds {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
$vis enum $enum_type { $vis enum $enum_type {
$($Variant(known_items::$Variant),)* $($Variant(known_items::$Variant),)*
$($VariantHasBody($variant_has_body_ty),)*
$($Unknown(syn::TypeParamBound),)? $($Unknown(syn::TypeParamBound),)?
} }
@ -2088,31 +2263,42 @@ macro_rules! impl_bounds {
} }
})* })*
$(impl From<$variant_has_body_ty> for $enum_type {
fn from(v: $variant_has_body_ty) -> Self {
Self::$VariantHasBody(v)
}
})*
impl ToTokens for $enum_type { impl ToTokens for $enum_type {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
match self { match self {
$(Self::$Variant(v) => v.to_tokens(tokens),)* $(Self::$Variant(v) => v.to_tokens(tokens),)*
$(Self::$VariantHasBody(v) => v.to_tokens(tokens),)*
$(Self::$Unknown(v) => v.to_tokens(tokens),)? $(Self::$Unknown(v) => v.to_tokens(tokens),)?
} }
} }
} }
impl $enum_type { impl $enum_type {
$vis fn parse_path(path: Path) -> Result<Self, Path> { $vis fn parse_path_with_arguments(path: Path) -> syn::Result<Result<Self, Path>> {
#![allow(unreachable_code)] #![allow(unreachable_code)]
$(let path = match known_items::$Variant::parse_path(path) { $(let path = match known_items::$Variant::parse_path(path) {
Ok(v) => return Ok(Self::$Variant(v)), Ok(v) => return Ok(Ok(Self::$Variant(v))),
Err(path) => path, Err(path) => path,
};)* };)*
$(return Ok(Self::$Unknown(syn::TraitBound { $(let path = match <$variant_has_body_ty>::parse_path_with_arguments(path)? {
Ok(v) => return Ok(Ok(Self::$VariantHasBody(v))),
Err(path) => path,
};)*
$(return Ok(Ok(Self::$Unknown(syn::TraitBound {
paren_token: None, paren_token: None,
modifier: syn::TraitBoundModifier::None, modifier: syn::TraitBoundModifier::None,
lifetimes: None, lifetimes: None,
path, path,
}.into()));)? }.into())));)?
Err(path) Ok(Err(path))
} }
$vis fn parse_type_param_bound(mut type_param_bound: syn::TypeParamBound) -> Result<Self, syn::TypeParamBound> { $vis fn parse_type_param_bound(mut type_param_bound: syn::TypeParamBound) -> syn::Result<Result<Self, syn::TypeParamBound>> {
#![allow(unreachable_code)] #![allow(unreachable_code)]
if let syn::TypeParamBound::Trait(mut trait_bound) = type_param_bound { if let syn::TypeParamBound::Trait(mut trait_bound) = type_param_bound {
if let syn::TraitBound { if let syn::TraitBound {
@ -2121,24 +2307,24 @@ macro_rules! impl_bounds {
lifetimes: None, lifetimes: None,
path: _, path: _,
} = trait_bound { } = trait_bound {
match Self::parse_path(trait_bound.path) { match Self::parse_path_with_arguments(trait_bound.path)? {
Ok(retval) => return Ok(retval), Ok(retval) => return Ok(Ok(retval)),
Err(path) => trait_bound.path = path, Err(path) => trait_bound.path = path,
} }
} }
type_param_bound = trait_bound.into(); type_param_bound = trait_bound.into();
} }
$(return Ok(Self::$Unknown(type_param_bound));)? $(return Ok(Ok(Self::$Unknown(type_param_bound)));)?
Err(type_param_bound) Ok(Err(type_param_bound))
} }
} }
impl Parse for $enum_type { impl Parse for $enum_type {
fn parse(input: ParseStream) -> syn::Result<Self> { fn parse(input: ParseStream) -> syn::Result<Self> {
Self::parse_type_param_bound(input.parse()?) Self::parse_type_param_bound(input.parse()?)?
.map_err(|type_param_bound| syn::Error::new_spanned( .map_err(|type_param_bound| syn::Error::new_spanned(
type_param_bound, type_param_bound,
format_args!("expected one of: {}", [$(stringify!($Variant)),*].join(", ")), format_args!("expected one of: {}", [$(stringify!($Variant),)* $(stringify!($VariantHasBody)),*].join(", ")),
)) ))
} }
} }
@ -2147,6 +2333,7 @@ macro_rules! impl_bounds {
#[allow(non_snake_case)] #[allow(non_snake_case)]
$vis struct $struct_type { $vis struct $struct_type {
$($vis $Variant: Option<known_items::$Variant>,)* $($vis $Variant: Option<known_items::$Variant>,)*
$($vis $VariantHasBody: Option<$variant_has_body_ty>,)*
$($vis $Unknown: Vec<syn::TypeParamBound>,)? $($vis $Unknown: Vec<syn::TypeParamBound>,)?
} }
@ -2159,6 +2346,11 @@ macro_rules! impl_bounds {
separator = Some(<Token![+]>::default()); separator = Some(<Token![+]>::default());
v.to_tokens(tokens); v.to_tokens(tokens);
})* })*
$(if let Some(v) = &self.$VariantHasBody {
separator.to_tokens(tokens);
separator = Some(<Token![+]>::default());
v.to_tokens(tokens);
})*
$(for v in &self.$Unknown { $(for v in &self.$Unknown {
separator.to_tokens(tokens); separator.to_tokens(tokens);
separator = Some(<Token![+]>::default()); separator = Some(<Token![+]>::default());
@ -2172,6 +2364,7 @@ macro_rules! impl_bounds {
#[allow(non_snake_case)] #[allow(non_snake_case)]
$vis struct Iter { $vis struct Iter {
$($Variant: Option<known_items::$Variant>,)* $($Variant: Option<known_items::$Variant>,)*
$($VariantHasBody: Option<$variant_has_body_ty>,)*
$($Unknown: std::vec::IntoIter<syn::TypeParamBound>,)? $($Unknown: std::vec::IntoIter<syn::TypeParamBound>,)?
} }
@ -2182,6 +2375,7 @@ macro_rules! impl_bounds {
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
Iter { Iter {
$($Variant: self.$Variant,)* $($Variant: self.$Variant,)*
$($VariantHasBody: self.$VariantHasBody,)*
$($Unknown: self.$Unknown.into_iter(),)? $($Unknown: self.$Unknown.into_iter(),)?
} }
} }
@ -2196,6 +2390,11 @@ macro_rules! impl_bounds {
return Some($enum_type::$Variant(value)); return Some($enum_type::$Variant(value));
} }
)* )*
$(
if let Some(value) = self.$VariantHasBody.take() {
return Some($enum_type::$VariantHasBody(value));
}
)*
$( $(
if let Some(value) = self.$Unknown.next() { if let Some(value) = self.$Unknown.next() {
return Some($enum_type::$Unknown(value)); return Some($enum_type::$Unknown(value));
@ -2211,6 +2410,11 @@ macro_rules! impl_bounds {
init = f(init, $enum_type::$Variant(value)); init = f(init, $enum_type::$Variant(value));
} }
)* )*
$(
if let Some(value) = self.$VariantHasBody.take() {
init = f(init, $enum_type::$VariantHasBody(value));
}
)*
$( $(
if let Some(value) = self.$Unknown.next() { if let Some(value) = self.$Unknown.next() {
init = f(init, $enum_type::$Unknown(value)); init = f(init, $enum_type::$Unknown(value));
@ -2227,6 +2431,9 @@ macro_rules! impl_bounds {
$($enum_type::$Variant(v) => { $($enum_type::$Variant(v) => {
self.$Variant = Some(v); self.$Variant = Some(v);
})* })*
$($enum_type::$VariantHasBody(v) => {
self.$VariantHasBody = Some(v);
})*
$($enum_type::$Unknown(v) => { $($enum_type::$Unknown(v) => {
self.$Unknown.push(v); self.$Unknown.push(v);
})? })?
@ -2248,6 +2455,9 @@ macro_rules! impl_bounds {
$(if let Some(v) = v.$Variant { $(if let Some(v) = v.$Variant {
self.$Variant = Some(v); self.$Variant = Some(v);
})* })*
$(if let Some(v) = v.$VariantHasBody {
self.$VariantHasBody = Some(v);
})*
$(self.$Unknown.extend(v.$Unknown);)* $(self.$Unknown.extend(v.$Unknown);)*
}); });
} }
@ -2302,6 +2512,8 @@ impl_bounds! {
Size, Size,
StaticType, StaticType,
Type, Type,
#[has_body]
PhantomConstGet(PhantomConstGetBound),
#[unknown] #[unknown]
Unknown, Unknown,
} }
@ -2317,6 +2529,8 @@ impl_bounds! {
ResetType, ResetType,
StaticType, StaticType,
Type, Type,
#[has_body]
PhantomConstGet(PhantomConstGetBound),
#[unknown] #[unknown]
Unknown, Unknown,
} }
@ -2332,6 +2546,7 @@ impl From<ParsedTypeBound> for ParsedBound {
ParsedTypeBound::ResetType(v) => ParsedBound::ResetType(v), ParsedTypeBound::ResetType(v) => ParsedBound::ResetType(v),
ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v), ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v),
ParsedTypeBound::Type(v) => ParsedBound::Type(v), ParsedTypeBound::Type(v) => ParsedBound::Type(v),
ParsedTypeBound::PhantomConstGet(v) => ParsedBound::PhantomConstGet(v),
ParsedTypeBound::Unknown(v) => ParsedBound::Unknown(v), ParsedTypeBound::Unknown(v) => ParsedBound::Unknown(v),
} }
} }
@ -2347,6 +2562,7 @@ impl From<ParsedTypeBounds> for ParsedBounds {
ResetType, ResetType,
StaticType, StaticType,
Type, Type,
PhantomConstGet,
Unknown, Unknown,
} = value; } = value;
Self { Self {
@ -2359,6 +2575,7 @@ impl From<ParsedTypeBounds> for ParsedBounds {
Size: None, Size: None,
StaticType, StaticType,
Type, Type,
PhantomConstGet,
Unknown, Unknown,
} }
} }
@ -2395,6 +2612,10 @@ impl ParsedTypeBound {
ParsedTypeBound::Type(known_items::Type(span)), ParsedTypeBound::Type(known_items::Type(span)),
]), ]),
Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]), Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]),
Self::PhantomConstGet(v) => ParsedTypeBounds::from_iter([
ParsedTypeBound::from(v),
ParsedTypeBound::Type(known_items::Type(span)),
]),
Self::Unknown(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::Unknown(v)]), Self::Unknown(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::Unknown(v)]),
} }
} }
@ -2430,6 +2651,7 @@ impl From<ParsedSizeTypeBounds> for ParsedBounds {
Size, Size,
StaticType: None, StaticType: None,
Type: None, Type: None,
PhantomConstGet: None,
Unknown: vec![], Unknown: vec![],
} }
} }
@ -2532,6 +2754,9 @@ impl ParsedBound {
Self::Size(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::Size(v)), Self::Size(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::Size(v)),
Self::StaticType(v) => ParsedBoundCategory::Type(ParsedTypeBound::StaticType(v)), Self::StaticType(v) => ParsedBoundCategory::Type(ParsedTypeBound::StaticType(v)),
Self::Type(v) => ParsedBoundCategory::Type(ParsedTypeBound::Type(v)), Self::Type(v) => ParsedBoundCategory::Type(ParsedTypeBound::Type(v)),
Self::PhantomConstGet(v) => {
ParsedBoundCategory::Type(ParsedTypeBound::PhantomConstGet(v))
}
Self::Unknown(v) => ParsedBoundCategory::Unknown(v), Self::Unknown(v) => ParsedBoundCategory::Unknown(v),
} }
} }
@ -3417,7 +3642,8 @@ impl ParsedGenerics {
| ParsedTypeBound::BundleType(_) | ParsedTypeBound::BundleType(_)
| ParsedTypeBound::EnumType(_) | ParsedTypeBound::EnumType(_)
| ParsedTypeBound::IntType(_) | ParsedTypeBound::IntType(_)
| ParsedTypeBound::ResetType(_) => { | ParsedTypeBound::ResetType(_)
| ParsedTypeBound::PhantomConstGet(_) => {
errors.error(bound, "bounds on mask types are not implemented"); errors.error(bound, "bounds on mask types are not implemented");
} }
ParsedTypeBound::StaticType(bound) => { ParsedTypeBound::StaticType(bound) => {

View file

@ -76,6 +76,7 @@ mod kw {
custom_keyword!(connect_inexact); custom_keyword!(connect_inexact);
custom_keyword!(custom_bounds); custom_keyword!(custom_bounds);
custom_keyword!(flip); custom_keyword!(flip);
custom_keyword!(get);
custom_keyword!(hdl); custom_keyword!(hdl);
custom_keyword!(hdl_module); custom_keyword!(hdl_module);
custom_keyword!(incomplete_wire); custom_keyword!(incomplete_wire);

View file

@ -12,7 +12,7 @@ use crate::{
}; };
use base64::{Engine, prelude::BASE64_URL_SAFE_NO_PAD}; use base64::{Engine, prelude::BASE64_URL_SAFE_NO_PAD};
use clap::builder::OsStringValueParser; use clap::builder::OsStringValueParser;
use eyre::{Context, bail, ensure, eyre}; use eyre::{Context, ensure, eyre};
use serde::{ use serde::{
Deserialize, Deserializer, Serialize, Serializer, Deserialize, Deserializer, Serialize, Serializer,
de::{DeserializeOwned, Error}, de::{DeserializeOwned, Error},
@ -26,6 +26,7 @@ use std::{
io::Write, io::Write,
marker::PhantomData, marker::PhantomData,
path::{Path, PathBuf}, path::{Path, PathBuf},
process::ExitStatus,
sync::OnceLock, sync::OnceLock,
}; };
@ -365,13 +366,17 @@ impl ExternalJobCaching {
.stdin(std::process::Stdio::null()); .stdin(std::process::Stdio::null());
Ok(cmd) Ok(cmd)
} }
pub fn run<F: FnOnce(std::process::Command) -> eyre::Result<()>>( pub fn run<F>(
self, self,
command_line: Interned<[Interned<OsStr>]>, command_line: Interned<[Interned<OsStr>]>,
input_file_paths: impl IntoIterator<Item = Interned<Path>>, input_file_paths: impl IntoIterator<Item = Interned<Path>>,
output_file_paths: impl IntoIterator<Item = Interned<Path>> + Clone, output_file_paths: impl IntoIterator<Item = Interned<Path>> + Clone,
run_fn: F, run_fn: F,
) -> eyre::Result<()> { exit_status_to_error: impl FnOnce(ExitStatus) -> eyre::Report,
) -> eyre::Result<()>
where
F: FnOnce(std::process::Command) -> eyre::Result<Result<(), ExitStatus>>,
{
let mut hasher = JobCacheHasher::default(); let mut hasher = JobCacheHasher::default();
hasher.hash_iter(command_line.iter(), |hasher, arg| { hasher.hash_iter(command_line.iter(), |hasher, arg| {
hasher.hash_sized_os_str(arg) hasher.hash_sized_os_str(arg)
@ -419,7 +424,26 @@ impl ExternalJobCaching {
}) })
.expect("spawn shouldn't fail"); .expect("spawn shouldn't fail");
run_fn(cmd) run_fn(cmd)
}); })?;
if let Err(exit_status) = result {
// check if the user may have terminated it or something, don't cache the failure
let user_maybe_terminated;
#[cfg(unix)]
{
user_maybe_terminated = std::os::unix::process::ExitStatusExt::signal(&exit_status)
.is_some()
|| exit_status.code().is_none_or(|code| code > 1);
}
#[cfg(not(unix))]
{
user_maybe_terminated = !exit_status.success();
}
if user_maybe_terminated {
let _ = std::fs::remove_file(self.cache_json_path);
return Err(exit_status_to_error(exit_status));
}
}
let result = result.map_err(exit_status_to_error);
ExternalJobCacheV2 { ExternalJobCacheV2 {
version: ExternalJobCacheVersion::CURRENT, version: ExternalJobCacheVersion::CURRENT,
inputs_hash, inputs_hash,
@ -444,16 +468,26 @@ impl ExternalJobCaching {
.write_to_file(self.cache_json_path)?; .write_to_file(self.cache_json_path)?;
result result
} }
pub fn run_maybe_cached<F: FnOnce(std::process::Command) -> eyre::Result<()>>( pub fn run_maybe_cached<F>(
this: Option<Self>, this: Option<Self>,
command_line: Interned<[Interned<OsStr>]>, command_line: Interned<[Interned<OsStr>]>,
input_file_paths: impl IntoIterator<Item = Interned<Path>>, input_file_paths: impl IntoIterator<Item = Interned<Path>>,
output_file_paths: impl IntoIterator<Item = Interned<Path>> + Clone, output_file_paths: impl IntoIterator<Item = Interned<Path>> + Clone,
run_fn: F, run_fn: F,
) -> eyre::Result<()> { exit_status_to_error: impl FnOnce(ExitStatus) -> eyre::Report,
) -> eyre::Result<()>
where
F: FnOnce(std::process::Command) -> eyre::Result<Result<(), ExitStatus>>,
{
match this { match this {
Some(this) => this.run(command_line, input_file_paths, output_file_paths, run_fn), Some(this) => this.run(
None => run_fn(Self::make_command(command_line)?), command_line,
input_file_paths,
output_file_paths,
run_fn,
exit_status_to_error,
),
None => run_fn(Self::make_command(command_line)?)?.map_err(exit_status_to_error),
} }
} }
} }
@ -1119,10 +1153,12 @@ impl<T: ExternalCommand> JobKind for ExternalCommandJobKind<T> {
} }
let status = acquired_job.run_command(cmd, |cmd| cmd.status())?; let status = acquired_job.run_command(cmd, |cmd| cmd.status())?;
if !status.success() { if !status.success() {
bail!("running {command_line:?} failed: {status}") Ok(Err(status))
} else {
Ok(Ok(()))
} }
Ok(())
}, },
|status| eyre!("running {command_line:?} failed: {status}"),
)?; )?;
Ok(job Ok(job
.output_paths() .output_paths()

View file

@ -703,8 +703,12 @@ impl JobGraph {
} }
let mut running_jobs = HashMap::default(); let mut running_jobs = HashMap::default();
let (finished_jobs_sender, finished_jobs_receiver) = mpsc::channel(); let (finished_jobs_sender, finished_jobs_receiver) = mpsc::channel();
let mut next_finished_job = None;
loop { loop {
while let Some(finished_job) = finished_jobs_receiver.try_recv().ok() { if let Some(finished_job) = next_finished_job
.take()
.or_else(|| finished_jobs_receiver.try_recv().ok())
{
let Some(RunningJob { job, thread }) = running_jobs.remove(&finished_job) let Some(RunningJob { job, thread }) = running_jobs.remove(&finished_job)
else { else {
unreachable!(); unreachable!();
@ -736,6 +740,7 @@ impl JobGraph {
} }
} }
} }
continue;
} }
if let Some(WaitingJobState { if let Some(WaitingJobState {
job_node_id, job_node_id,
@ -791,12 +796,15 @@ impl JobGraph {
.expect("failed to spawn thread for job"), .expect("failed to spawn thread for job"),
}, },
); );
continue;
} }
if running_jobs.is_empty() { if running_jobs.is_empty() {
assert!(item_name_to_waiting_jobs_map.is_empty()); assert!(item_name_to_waiting_jobs_map.is_empty());
assert!(ready_jobs.is_empty()); assert!(ready_jobs.is_empty());
return Ok(()); return Ok(());
} }
// nothing to do yet, block to avoid busy waiting
next_finished_job = finished_jobs_receiver.recv().ok();
} }
}) })
} }

View file

@ -4,6 +4,18 @@
// TODO: enable: // TODO: enable:
// #![warn(missing_docs)] // #![warn(missing_docs)]
#![deny(
rustdoc::bare_urls,
rustdoc::broken_intra_doc_links,
rustdoc::invalid_codeblock_attributes,
rustdoc::invalid_html_tags,
rustdoc::invalid_rust_codeblocks,
rustdoc::private_doc_tests,
rustdoc::private_intra_doc_links,
rustdoc::redundant_explicit_links,
rustdoc::unescaped_backticks
)]
//! [Main Documentation][_docs] //! [Main Documentation][_docs]
extern crate self as fayalite; extern crate self as fayalite;
@ -74,6 +86,135 @@ macro_rules! __cfg_expansion_helper {
pub use fayalite_proc_macros::hdl_module; pub use fayalite_proc_macros::hdl_module;
#[doc(inline)] #[doc(inline)]
/// The `#[hdl]` attribute is supported on several different kinds of [Rust Items](https://doc.rust-lang.org/reference/items.html):
///
/// # Functions and Methods
/// Enable's the stuff that you can use inside a [module's body](crate::_docs::modules::module_bodies),
/// but without being a module or changing the function's signature.
/// The only exception is that you can't use stuff that requires the automatically-provided `m` variable.
///
/// # Structs
// TODO: expand on struct docs
/// e.g.:
/// ```
/// # use fayalite::prelude::*;
/// # #[hdl]
/// # pub struct OtherStruct {}
/// #[hdl]
/// pub struct MyStruct {
/// #[hdl(flip)]
/// pub a: UInt<5>,
/// pub b: Bool,
/// #[hdl(flip)]
/// pub c: OtherStruct,
/// }
/// ```
///
/// # Enums
// TODO: expand on enum docs
/// e.g.:
/// ```
/// # use fayalite::prelude::*;
/// # #[hdl]
/// # pub struct MyStruct {}
/// #[hdl]
/// pub enum MyEnum {
/// A(UInt<3>),
/// B,
/// C(MyStruct),
/// }
/// ```
///
/// # Type Aliases
///
/// There's three different ways you can create a type alias:
///
/// # Normal Type Alias
///
/// This works exactly how you'd expect:
/// ```
/// # use fayalite::prelude::*;
/// # #[hdl]
/// # pub struct MyStruct<T: Type> {
/// # v: T,
/// # }
/// #[hdl]
/// pub type MyType<T: Type> = MyStruct<T>;
///
/// // you can then use Fayalite's standard syntax for creating dynamic types at runtime:
///
/// let ty = MyType[UInt[3]];
/// assert_eq!(ty, MyStruct[UInt[3]]);
/// ```
///
/// # Type Alias that gets a [`Type`] from a [`PhantomConst`]
///
/// This allows you to use some computed property of a [`PhantomConst`] to get a [`Type`] that you can use in other #[hdl] types.
///
/// ```
/// # use fayalite::{intern::Intern, prelude::*};
/// #[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
/// pub struct Config {
/// pub foo: usize,
/// pub bar: Bundle,
/// }
///
/// // the expression inside `get` is called with `Interned<Config>` and returns `Array<Bundle>`
/// #[hdl(get(|config| Array[config.bar][config.foo]))]
/// pub type GetMyArray<P: PhantomConstGet<Config>> = Array<Bundle>;
///
/// // you can then use it in other types:
///
/// #[hdl(no_static)]
/// pub struct WrapMyArray<P: PhantomConstGet<Config>> {
/// pub my_array: GetMyArray<P>,
/// }
///
/// // you can then use Fayalite's standard syntax for creating dynamic types at runtime:
/// let bar = Bundle::new(Default::default());
/// let config = PhantomConst::new(Config { foo: 12, bar }.intern_sized());
/// let ty = WrapMyArray[config];
/// assert_eq!(ty.my_array, Array[bar][12]);
/// ```
///
/// # Type Alias that gets a [`Size`] from a [`PhantomConst`]
///
/// This allows you to use some computed property of a [`PhantomConst`] to get a [`Size`] that you can use in other #[hdl] types.
///
/// ```
/// # use fayalite::{intern::Intern, prelude::*};
/// # #[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
/// # pub struct ConfigItem {}
/// # impl ConfigItem {
/// # pub fn new() -> Self {
/// # Self {}
/// # }
/// # }
/// #[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
/// pub struct Config {
/// pub items: Vec<ConfigItem>,
/// }
///
/// // the expression inside `get` is called with `Interned<Config>` and returns `usize` (not DynSize)
/// #[hdl(get(|config| config.items.len()))]
/// pub type GetItemsLen<P: PhantomConstGet<Config>> = DynSize; // must be DynSize
///
/// // you can then use it in other types:
///
/// #[hdl(no_static)]
/// pub struct FlagPerItem<P: PhantomConstGet<Config>> {
/// pub flags: ArrayType<Bool, GetItemsLen<P>>,
/// }
///
/// // you can then use Fayalite's standard syntax for creating dynamic types at runtime:
/// let config = PhantomConst::new(Config { items: vec![ConfigItem::new(); 5] }.intern_sized());
/// let ty = FlagPerItem[config];
/// assert_eq!(ty.flags, Array[Bool][5]);
/// ```
///
/// [`PhantomConst`]: crate::phantom_const::PhantomConst
/// [`Size`]: crate::int::Size
/// [`Type`]: crate::ty::Type
pub use fayalite_proc_macros::hdl; pub use fayalite_proc_macros::hdl;
pub use bitvec; pub use bitvec;

View file

@ -415,3 +415,71 @@ impl<T: ?Sized + PhantomConstValue> ToSimValueWithType<CanonicalType> for Phanto
SimValue::into_canonical(SimValue::from_value(Self::from_canonical(ty), *self)) SimValue::into_canonical(SimValue::from_value(Self::from_canonical(ty), *self))
} }
} }
mod sealed {
pub trait Sealed<T: ?Sized> {}
}
pub trait PhantomConstGet<T: ?Sized + PhantomConstValue>: sealed::Sealed<T> {
fn get(&self) -> Interned<T>;
}
impl<T: ?Sized + PhantomConstValue, This: ?Sized + std::ops::Deref<Target: PhantomConstGet<T>>>
sealed::Sealed<T> for This
{
}
impl<T: ?Sized + PhantomConstValue, This: ?Sized + std::ops::Deref<Target: PhantomConstGet<T>>>
PhantomConstGet<T> for This
{
fn get(&self) -> Interned<T> {
This::Target::get(&**self)
}
}
macro_rules! impl_phantom_const_get {
(
impl PhantomConstGet<$T:ident> for $ty:ty {
fn $get:ident(&$get_self:ident) -> _ $get_body:block
}
) => {
impl<$T: ?Sized + PhantomConstValue> sealed::Sealed<$T> for $ty {}
impl<$T: ?Sized + PhantomConstValue> PhantomConstGet<$T> for $ty {
fn $get(&$get_self) -> Interned<$T> $get_body
}
};
}
impl_phantom_const_get! {
impl PhantomConstGet<T> for PhantomConst<T> {
fn get(&self) -> _ {
PhantomConst::get(*self)
}
}
}
impl_phantom_const_get! {
impl PhantomConstGet<T> for Expr<PhantomConst<T>> {
fn get(&self) -> _ {
PhantomConst::get(Expr::ty(*self))
}
}
}
#[doc(hidden)]
pub trait ReturnSelfUnchanged<T: ?Sized> {
type Type: ?Sized;
}
impl<This: ?Sized, T: ?Sized> ReturnSelfUnchanged<T> for This {
type Type = This;
}
#[doc(hidden)]
pub fn type_alias_phantom_const_get_helper<T: ?Sized + PhantomConstValue, R: Intern + Clone>(
param: impl PhantomConstGet<T>,
get: impl FnOnce(Interned<T>) -> R,
) -> &'static R {
Interned::into_inner(get(param.get()).intern_sized())
}

View file

@ -27,7 +27,7 @@ pub use crate::{
Instance, Module, ModuleBuilder, annotate, connect, connect_any, incomplete_wire, instance, Instance, Module, ModuleBuilder, annotate, connect, connect_any, incomplete_wire, instance,
memory, memory_array, memory_with_init, reg_builder, wire, memory, memory_array, memory_with_init, reg_builder, wire,
}, },
phantom_const::PhantomConst, phantom_const::{PhantomConst, PhantomConstGet},
platform::{DynPlatform, Platform, PlatformIOBuilder, peripherals}, platform::{DynPlatform, Platform, PlatformIOBuilder, peripherals},
reg::Reg, reg::Reg,
reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset}, reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset},

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,6 @@ use fayalite::{
bundle::BundleType, bundle::BundleType,
enum_::EnumType, enum_::EnumType,
int::{BoolOrIntType, IntType}, int::{BoolOrIntType, IntType},
phantom_const::PhantomConst,
prelude::*, prelude::*,
ty::StaticType, ty::StaticType,
}; };
@ -197,3 +196,21 @@ check_bounds!(CheckBoundsTTT2<#[a, Type] A: BundleType +, #[b, Type] B: Type +,
check_bounds!(CheckBoundsTTT3<#[a, Type] A: EnumType +, #[b, Type] B: Type +, #[c, Type] C: Type +>); check_bounds!(CheckBoundsTTT3<#[a, Type] A: EnumType +, #[b, Type] B: Type +, #[c, Type] C: Type +>);
check_bounds!(CheckBoundsTTT4<#[a, Type] A: IntType +, #[b, Type] B: Type +, #[c, Type] C: Type +>); check_bounds!(CheckBoundsTTT4<#[a, Type] A: IntType +, #[b, Type] B: Type +, #[c, Type] C: Type +>);
check_bounds!(CheckBoundsTTT5<#[a, Type] A: StaticType +, #[b, Type] B: Type +, #[c, Type] C: Type +>); check_bounds!(CheckBoundsTTT5<#[a, Type] A: StaticType +, #[b, Type] B: Type +, #[c, Type] C: Type +>);
#[derive(Clone, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)]
pub struct MyPhantomConstInner {
pub a: usize,
pub b: UInt,
}
#[hdl(outline_generated, get(|v| v.a))]
pub type GetA<P: PhantomConstGet<MyPhantomConstInner>> = DynSize;
#[hdl(outline_generated, get(|v| v.b))]
pub type GetB<P: PhantomConstGet<MyPhantomConstInner>> = UInt;
#[hdl(outline_generated, no_static)]
pub struct MyTypeWithPhantomConstParameter<P: PhantomConstGet<MyPhantomConstInner>> {
pub a: ArrayType<Bool, GetA<P>>,
pub b: HdlOption<GetB<P>>,
}

View file

@ -3,7 +3,7 @@
use fayalite::{ use fayalite::{
memory::{ReadStruct, ReadWriteStruct, WriteStruct}, memory::{ReadStruct, ReadWriteStruct, WriteStruct},
module::{instance_with_loc, reg_builder_with_loc}, module::{instance_with_loc, memory_with_init_and_loc, reg_builder_with_loc},
prelude::*, prelude::*,
reset::ResetType, reset::ResetType,
sim::vcd::VcdWriterDecls, sim::vcd::VcdWriterDecls,
@ -1261,6 +1261,310 @@ fn test_memories3() {
} }
} }
#[hdl_module(outline_generated)]
pub fn many_memories() {
#[hdl]
let r: Array<ReadStruct<Bool, ConstUsize<4>>, 8> = m.input();
#[hdl]
let w: Array<WriteStruct<Bool, ConstUsize<4>>, 8> = m.input();
for (mem_index, (r, w)) in r.into_iter().zip(w).enumerate() {
let mut mem = memory_with_init_and_loc(
&format!("mem_{mem_index}"),
(0..16)
.map(|bit_index| mem_index.pow(5).to_expr()[bit_index])
.collect::<Vec<_>>(),
SourceLocation::caller(),
);
connect_any(mem.new_read_port(), r);
connect_any(mem.new_write_port(), w);
}
}
#[hdl]
#[test]
fn test_many_memories() {
let _n = SourceLocation::normalize_files_for_tests();
let mut sim = Simulation::new(many_memories());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
for r in sim.io().r {
sim.write_clock(r.clk, false);
}
for w in sim.io().w {
sim.write_clock(w.clk, false);
}
#[hdl(cmp_eq)]
struct IO {
r_addr: UInt<4>,
r_en: Bool,
r_data: Array<Bool, 8>,
w_addr: UInt<4>,
w_en: Bool,
w_data: Array<Bool, 8>,
w_mask: Array<Bool, 8>,
}
let io_cycles = [
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: false,
r_data: [false; 8],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [false; 8],
},
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
r_data: [false, true, false, true, false, true, false, true],
w_addr: 0_hdl_u4,
w_en: true,
w_data: [true; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
r_data: [true; 8],
w_addr: 0_hdl_u4,
w_en: true,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
r_data: [false; 8],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 1_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 2_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, true, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 3_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 4_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, true, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 5_hdl_u4,
r_en: true,
r_data: [false, false, true, true, false, true, true, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 6_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, false, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 7_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 8_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 9_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xA_hdl_u4,
r_en: true,
r_data: [false, false, false, false, true, true, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xB_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, true, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xC_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xD_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xE_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xF_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
];
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl(sim)]
let IO {
r_addr,
r_en,
r_data: _,
w_addr,
w_en,
w_data,
w_mask,
} = expected;
for (((r, w), w_data), w_mask) in sim
.io()
.r
.into_iter()
.zip(sim.io().w)
.zip(w_data.iter())
.zip(w_mask.iter())
{
sim.write(r.addr, &r_addr);
sim.write(r.en, &r_en);
sim.write(w.addr, &w_addr);
sim.write(w.en, &w_en);
sim.write(w.data, w_data);
sim.write(w.mask, w_mask);
}
let io = #[hdl(sim)]
IO {
r_addr,
r_en,
r_data: std::array::from_fn(|i| sim.read(sim.io().r[i].data)),
w_addr,
w_en,
w_data,
w_mask,
};
assert_eq!(
expected,
io,
"vcd:\n{}\ncycle: {cycle}",
String::from_utf8(writer.take()).unwrap(),
);
sim.advance_time(SimDuration::from_micros(1));
for r in sim.io().r {
sim.write_clock(r.clk, true);
}
for w in sim.io().w {
sim.write_clock(w.clk, true);
}
sim.advance_time(SimDuration::from_micros(1));
for r in sim.io().r {
sim.write_clock(r.clk, false);
}
for w in sim.io().w {
sim.write_clock(w.clk, false);
}
}
sim.flush_traces().unwrap();
let vcd = String::from_utf8(writer.take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
if vcd != include_str!("sim/expected/many_memories.vcd") {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != include_str!("sim/expected/many_memories.txt") {
panic!();
}
}
#[hdl_module(outline_generated)] #[hdl_module(outline_generated)]
pub fn duplicate_names() { pub fn duplicate_names() {
#[hdl] #[hdl]
@ -1722,3 +2026,85 @@ fn test_sim_only_connects() {
panic!(); panic!();
} }
} }
#[hdl_module(outline_generated, extern)]
pub fn sim_fork_join<const N: usize>()
where
ConstUsize<N>: KnownSize,
{
#[hdl]
let clocks: Array<Clock, N> = m.input();
#[hdl]
let outputs: Array<UInt<8>, N> = m.output();
m.extern_module_simulation_fn((clocks, outputs), |(clocks, outputs), mut sim| async move {
sim.write(outputs, [0u8; N]).await;
loop {
sim.fork_join(
clocks
.into_iter()
.zip(outputs)
.map(|(clock, output)| {
move |mut sim: ExternModuleSimulationState| async move {
sim.wait_for_clock_edge(clock).await;
let v = sim
.read_bool_or_int(output)
.await
.to_bigint()
.try_into()
.expect("known to be in range");
sim.write(output, 1u8.wrapping_add(v)).await;
}
})
.collect::<Vec<_>>(),
)
.await;
}
});
}
#[test]
fn test_sim_fork_join() {
let _n = SourceLocation::normalize_files_for_tests();
const N: usize = 3;
let mut sim = Simulation::new(sim_fork_join::<N>());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
sim.write(sim.io().clocks, [false; N]);
let mut clocks_triggered = [false; N];
let mut expected = [0u8; N];
for i0 in 0..N {
for i1 in 0..N {
for i2 in 0..N {
for i3 in 0..N {
let indexes = [i0, i1, i2, i3];
for i in indexes {
sim.advance_time(SimDuration::from_micros(1));
sim.write(sim.io().clocks[i], true);
sim.advance_time(SimDuration::from_micros(1));
sim.write(sim.io().clocks[i], false);
if !clocks_triggered[i] {
expected[i] = expected[i].wrapping_add(1);
}
clocks_triggered[i] = true;
if clocks_triggered == [true; N] {
clocks_triggered = [false; N];
}
let output = sim.read(sim.io().outputs);
assert_eq!(output, expected.to_sim_value(), "indexes={indexes:?} i={i}");
}
}
}
}
}
sim.flush_traces().unwrap();
let vcd = String::from_utf8(writer.take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
if vcd != include_str!("sim/expected/sim_fork_join.vcd") {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != include_str!("sim/expected/sim_fork_join.txt") {
panic!();
}
}

View file

@ -828,7 +828,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "array_rw", name: "array_rw",
children: [ children: [
@ -1699,7 +1698,12 @@ Simulation {
}, },
), ),
], ],
instant: 34 μs,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 34 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -124,7 +124,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "conditional_assignment_last", name: "conditional_assignment_last",
children: [ children: [
@ -177,7 +176,12 @@ Simulation {
}, },
), ),
], ],
instant: 2 μs,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 2 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -100,7 +100,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "connect_const", name: "connect_const",
children: [ children: [
@ -130,7 +129,12 @@ Simulation {
], ],
trace_memories: {}, trace_memories: {},
trace_writers: [], trace_writers: [],
instant: 0 s,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 0 s,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -143,7 +143,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "connect_const_reset", name: "connect_const_reset",
children: [ children: [
@ -197,7 +196,12 @@ Simulation {
}, },
), ),
], ],
instant: 1 μs,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 1 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -263,7 +263,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "counter", name: "counter",
children: [ children: [
@ -329,7 +328,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x0,
}, },
SimTrace { SimTrace {
id: TraceScalarId(1), id: TraceScalarId(1),
@ -355,7 +354,7 @@ Simulation {
ty: UInt<4>, ty: UInt<4>,
}, },
state: 0x3, state: 0x3,
last_state: 0x3, last_state: 0x2,
}, },
], ],
trace_memories: {}, trace_memories: {},
@ -368,9 +367,14 @@ Simulation {
}, },
), ),
], ],
instant: 66 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(1), StatePartIndex<SmallSlots>(1),
], ],
event_queue: EventQueue(EventQueueData {
instant: 66 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -26,192 +26,192 @@ b11 $
0! 0!
#3000000 #3000000
1! 1!
b100 $
b100 # b100 #
b100 $
#4000000 #4000000
0! 0!
#5000000 #5000000
1! 1!
b101 $
b101 # b101 #
b101 $
#6000000 #6000000
0! 0!
#7000000 #7000000
1! 1!
b110 $
b110 # b110 #
b110 $
#8000000 #8000000
0! 0!
#9000000 #9000000
1! 1!
b111 $
b111 # b111 #
b111 $
#10000000 #10000000
0! 0!
#11000000 #11000000
1! 1!
b1000 $
b1000 # b1000 #
b1000 $
#12000000 #12000000
0! 0!
#13000000 #13000000
1! 1!
b1001 $
b1001 # b1001 #
b1001 $
#14000000 #14000000
0! 0!
#15000000 #15000000
1! 1!
b1010 $
b1010 # b1010 #
b1010 $
#16000000 #16000000
0! 0!
#17000000 #17000000
1! 1!
b1011 $
b1011 # b1011 #
b1011 $
#18000000 #18000000
0! 0!
#19000000 #19000000
1! 1!
b1100 $
b1100 # b1100 #
b1100 $
#20000000 #20000000
0! 0!
#21000000 #21000000
1! 1!
b1101 $
b1101 # b1101 #
b1101 $
#22000000 #22000000
0! 0!
#23000000 #23000000
1! 1!
b1110 $
b1110 # b1110 #
b1110 $
#24000000 #24000000
0! 0!
#25000000 #25000000
1! 1!
b1111 $
b1111 # b1111 #
b1111 $
#26000000 #26000000
0! 0!
#27000000 #27000000
1! 1!
b0 $
b0 # b0 #
b0 $
#28000000 #28000000
0! 0!
#29000000 #29000000
1! 1!
b1 $
b1 # b1 #
b1 $
#30000000 #30000000
0! 0!
#31000000 #31000000
1! 1!
b10 $
b10 # b10 #
b10 $
#32000000 #32000000
0! 0!
#33000000 #33000000
1! 1!
b11 $
b11 # b11 #
b11 $
#34000000 #34000000
0! 0!
#35000000 #35000000
1! 1!
b100 $
b100 # b100 #
b100 $
#36000000 #36000000
0! 0!
#37000000 #37000000
1! 1!
b101 $
b101 # b101 #
b101 $
#38000000 #38000000
0! 0!
#39000000 #39000000
1! 1!
b110 $
b110 # b110 #
b110 $
#40000000 #40000000
0! 0!
#41000000 #41000000
1! 1!
b111 $
b111 # b111 #
b111 $
#42000000 #42000000
0! 0!
#43000000 #43000000
1! 1!
b1000 $
b1000 # b1000 #
b1000 $
#44000000 #44000000
0! 0!
#45000000 #45000000
1! 1!
b1001 $
b1001 # b1001 #
b1001 $
#46000000 #46000000
0! 0!
#47000000 #47000000
1! 1!
b1010 $
b1010 # b1010 #
b1010 $
#48000000 #48000000
0! 0!
#49000000 #49000000
1! 1!
b1011 $
b1011 # b1011 #
b1011 $
#50000000 #50000000
0! 0!
#51000000 #51000000
1! 1!
b1100 $
b1100 # b1100 #
b1100 $
#52000000 #52000000
0! 0!
#53000000 #53000000
1! 1!
b1101 $
b1101 # b1101 #
b1101 $
#54000000 #54000000
0! 0!
#55000000 #55000000
1! 1!
b1110 $
b1110 # b1110 #
b1110 $
#56000000 #56000000
0! 0!
#57000000 #57000000
1! 1!
b1111 $
b1111 # b1111 #
b1111 $
#58000000 #58000000
0! 0!
#59000000 #59000000
1! 1!
b0 $
b0 # b0 #
b0 $
#60000000 #60000000
0! 0!
#61000000 #61000000
1! 1!
b1 $
b1 # b1 #
b1 $
#62000000 #62000000
0! 0!
#63000000 #63000000
1! 1!
b10 $
b10 # b10 #
b10 $
#64000000 #64000000
0! 0!
#65000000 #65000000
1! 1!
b11 $
b11 # b11 #
b11 $
#66000000 #66000000

View file

@ -244,7 +244,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "counter", name: "counter",
children: [ children: [
@ -310,7 +309,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x0,
}, },
SimTrace { SimTrace {
id: TraceScalarId(1), id: TraceScalarId(1),
@ -336,7 +335,7 @@ Simulation {
ty: UInt<4>, ty: UInt<4>,
}, },
state: 0x3, state: 0x3,
last_state: 0x3, last_state: 0x2,
}, },
], ],
trace_memories: {}, trace_memories: {},
@ -349,9 +348,14 @@ Simulation {
}, },
), ),
], ],
instant: 66 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(1), StatePartIndex<SmallSlots>(1),
], ],
event_queue: EventQueue(EventQueueData {
instant: 66 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -16,199 +16,199 @@ b0 $
$end $end
#1000000 #1000000
1! 1!
b11 $
b11 # b11 #
b11 $
0" 0"
#2000000 #2000000
0! 0!
#3000000 #3000000
1! 1!
b100 $
b100 # b100 #
b100 $
#4000000 #4000000
0! 0!
#5000000 #5000000
1! 1!
b101 $
b101 # b101 #
b101 $
#6000000 #6000000
0! 0!
#7000000 #7000000
1! 1!
b110 $
b110 # b110 #
b110 $
#8000000 #8000000
0! 0!
#9000000 #9000000
1! 1!
b111 $
b111 # b111 #
b111 $
#10000000 #10000000
0! 0!
#11000000 #11000000
1! 1!
b1000 $
b1000 # b1000 #
b1000 $
#12000000 #12000000
0! 0!
#13000000 #13000000
1! 1!
b1001 $
b1001 # b1001 #
b1001 $
#14000000 #14000000
0! 0!
#15000000 #15000000
1! 1!
b1010 $
b1010 # b1010 #
b1010 $
#16000000 #16000000
0! 0!
#17000000 #17000000
1! 1!
b1011 $
b1011 # b1011 #
b1011 $
#18000000 #18000000
0! 0!
#19000000 #19000000
1! 1!
b1100 $
b1100 # b1100 #
b1100 $
#20000000 #20000000
0! 0!
#21000000 #21000000
1! 1!
b1101 $
b1101 # b1101 #
b1101 $
#22000000 #22000000
0! 0!
#23000000 #23000000
1! 1!
b1110 $
b1110 # b1110 #
b1110 $
#24000000 #24000000
0! 0!
#25000000 #25000000
1! 1!
b1111 $
b1111 # b1111 #
b1111 $
#26000000 #26000000
0! 0!
#27000000 #27000000
1! 1!
b0 $
b0 # b0 #
b0 $
#28000000 #28000000
0! 0!
#29000000 #29000000
1! 1!
b1 $
b1 # b1 #
b1 $
#30000000 #30000000
0! 0!
#31000000 #31000000
1! 1!
b10 $
b10 # b10 #
b10 $
#32000000 #32000000
0! 0!
#33000000 #33000000
1! 1!
b11 $
b11 # b11 #
b11 $
#34000000 #34000000
0! 0!
#35000000 #35000000
1! 1!
b100 $
b100 # b100 #
b100 $
#36000000 #36000000
0! 0!
#37000000 #37000000
1! 1!
b101 $
b101 # b101 #
b101 $
#38000000 #38000000
0! 0!
#39000000 #39000000
1! 1!
b110 $
b110 # b110 #
b110 $
#40000000 #40000000
0! 0!
#41000000 #41000000
1! 1!
b111 $
b111 # b111 #
b111 $
#42000000 #42000000
0! 0!
#43000000 #43000000
1! 1!
b1000 $
b1000 # b1000 #
b1000 $
#44000000 #44000000
0! 0!
#45000000 #45000000
1! 1!
b1001 $
b1001 # b1001 #
b1001 $
#46000000 #46000000
0! 0!
#47000000 #47000000
1! 1!
b1010 $
b1010 # b1010 #
b1010 $
#48000000 #48000000
0! 0!
#49000000 #49000000
1! 1!
b1011 $
b1011 # b1011 #
b1011 $
#50000000 #50000000
0! 0!
#51000000 #51000000
1! 1!
b1100 $
b1100 # b1100 #
b1100 $
#52000000 #52000000
0! 0!
#53000000 #53000000
1! 1!
b1101 $
b1101 # b1101 #
b1101 $
#54000000 #54000000
0! 0!
#55000000 #55000000
1! 1!
b1110 $
b1110 # b1110 #
b1110 $
#56000000 #56000000
0! 0!
#57000000 #57000000
1! 1!
b1111 $
b1111 # b1111 #
b1111 $
#58000000 #58000000
0! 0!
#59000000 #59000000
1! 1!
b0 $
b0 # b0 #
b0 $
#60000000 #60000000
0! 0!
#61000000 #61000000
1! 1!
b1 $
b1 # b1 #
b1 $
#62000000 #62000000
0! 0!
#63000000 #63000000
1! 1!
b10 $
b10 # b10 #
b10 $
#64000000 #64000000
0! 0!
#65000000 #65000000
1! 1!
b11 $
b11 # b11 #
b11 $
#66000000 #66000000

View file

@ -104,7 +104,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "duplicate_names", name: "duplicate_names",
children: [ children: [
@ -160,7 +159,12 @@ Simulation {
}, },
), ),
], ],
instant: 1 μs,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 1 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -1456,7 +1456,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "enums", name: "enums",
children: [ children: [
@ -1744,7 +1743,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x0,
}, },
SimTrace { SimTrace {
id: TraceScalarId(1), id: TraceScalarId(1),
@ -1924,9 +1923,14 @@ Simulation {
}, },
), ),
], ],
instant: 16 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(3), StatePartIndex<SmallSlots>(3),
], ],
event_queue: EventQueue(EventQueueData {
instant: 16 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -186,14 +186,8 @@ Simulation {
running_generator: Some( running_generator: Some(
..., ...,
), ),
wait_targets: {
Instant(
20.500000000000 μs,
),
},
}, },
], ],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "extern_module", name: "extern_module",
children: [ children: [
@ -247,7 +241,14 @@ Simulation {
}, },
), ),
], ],
instant: 20 μs,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 20 μs,
events: {
Event { instant: 20.500000000000 μs, kind: ExternModule(0) }: 1,
},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -6,8 +6,9 @@ $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
0! 0!
1" 0"
$end $end
1"
#500000 #500000
#1500000 #1500000
0" 0"

View file

@ -234,55 +234,8 @@ Simulation {
running_generator: Some( 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,
}, },
], ],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
},
value: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
},
},
},
],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "extern_module2", name: "extern_module2",
children: [ children: [
@ -356,7 +309,113 @@ Simulation {
}, },
), ),
], ],
instant: 60 μs,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 60 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {
SensitivitySet {
id: 59,
values: {
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
},
changed: Cell {
value: false,
},
..
},
},
waiting_sensitivity_sets_by_compiled_value: {
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: (
SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
{
SensitivitySet {
id: 59,
..
},
},
),
},
.. ..
} }

View file

@ -8,8 +8,9 @@ $enddefinitions $end
$dumpvars $dumpvars
1! 1!
0" 0"
b1001000 # b0 #
$end $end
b1001000 #
#1000000 #1000000
1" 1"
b1100101 # b1100101 #

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -721,7 +721,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "memories", name: "memories",
children: [ children: [
@ -1616,10 +1615,15 @@ Simulation {
}, },
), ),
], ],
instant: 22 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(1), StatePartIndex<SmallSlots>(1),
StatePartIndex<SmallSlots>(6), StatePartIndex<SmallSlots>(6),
], ],
event_queue: EventQueue(EventQueueData {
instant: 22 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -234,13 +234,13 @@ b100000 6
b10000 9 b10000 9
b100000 I b100000 I
1# 1#
1(
1/
14
b10000 $ b10000 $
b100000 % b100000 %
1(
1/
b10000 0 b10000 0
b100000 1 b100000 1
14
#4000000 #4000000
0# 0#
0( 0(
@ -256,11 +256,11 @@ b1000000 6
b10000 9 b10000 9
b1000000 I b1000000 I
1# 1#
b1000000 %
1( 1(
1/ 1/
14
b1000000 %
b1000000 1 b1000000 1
14
#6000000 #6000000
0# 0#
0( 0(
@ -278,11 +278,11 @@ b1100000 6
b1010000 9 b1010000 9
b1000000 I b1000000 I
1# 1#
b1010000 $
1( 1(
1/ 1/
14
b1010000 $
b1010000 0 b1010000 0
14
#8000000 #8000000
0# 0#
0( 0(

View file

@ -679,7 +679,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "memories2", name: "memories2",
children: [ children: [
@ -1260,9 +1259,14 @@ Simulation {
}, },
), ),
], ],
instant: 22 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(3), StatePartIndex<SmallSlots>(3),
], ],
event_queue: EventQueue(EventQueueData {
instant: 22 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -100,8 +100,8 @@ $end
1) 1)
#1250000 #1250000
1# 1#
1*
b11 $ b11 $
1*
sHdlSome\x20(1) + sHdlSome\x20(1) +
1, 1,
#1500000 #1500000
@ -113,8 +113,8 @@ sHdlSome\x20(1) +
0) 0)
#2250000 #2250000
1# 1#
1*
b0 $ b0 $
1*
sHdlNone\x20(0) + sHdlNone\x20(0) +
0, 0,
#2500000 #2500000
@ -303,8 +303,8 @@ b11 !
b11 ( b11 (
#17250000 #17250000
1# 1#
1*
b11 $ b11 $
1*
sHdlSome\x20(1) + sHdlSome\x20(1) +
1, 1,
#17500000 #17500000
@ -316,8 +316,8 @@ b10 !
b10 ( b10 (
#18250000 #18250000
1# 1#
1*
b0 $ b0 $
1*
sHdlNone\x20(0) + sHdlNone\x20(0) +
0, 0,
#18500000 #18500000
@ -339,8 +339,8 @@ b1 !
b1 ( b1 (
#20250000 #20250000
1# 1#
1*
b1 $ b1 $
1*
sHdlSome\x20(1) + sHdlSome\x20(1) +
#20500000 #20500000
#20750000 #20750000
@ -353,8 +353,8 @@ b0 (
0) 0)
#21250000 #21250000
1# 1#
1*
b0 $ b0 $
1*
sHdlNone\x20(0) + sHdlNone\x20(0) +
#21500000 #21500000
#21750000 #21750000

View file

@ -1763,7 +1763,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "memories3", name: "memories3",
children: [ children: [
@ -3275,10 +3274,15 @@ Simulation {
}, },
), ),
], ],
instant: 15 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(1), StatePartIndex<SmallSlots>(1),
StatePartIndex<SmallSlots>(6), StatePartIndex<SmallSlots>(6),
], ],
event_queue: EventQueue(EventQueueData {
instant: 15 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -420,6 +420,10 @@ b10000 T
1\ 1\
#3250000 #3250000
1# 1#
b110100 %
b1111000 '
b10011010 (
b11110000 +
1. 1.
1A 1A
b110100 C b110100 C
@ -427,10 +431,6 @@ b1111000 E
b10011010 F b10011010 F
b11110000 I b11110000 I
1L 1L
b110100 %
b1111000 '
b10011010 (
b11110000 +
#3500000 #3500000
#3750000 #3750000
0# 0#
@ -508,6 +508,14 @@ b1010100 '"
b110010 /" b110010 /"
b10000 7" b10000 7"
1# 1#
b11111110 $
b11011100 %
b10111010 &
b10011000 '
b1110110 (
b1010100 )
b110010 *
b10000 +
1. 1.
1A 1A
b11111110 B b11111110 B
@ -519,14 +527,6 @@ b1010100 G
b110010 H b110010 H
b10000 I b10000 I
1L 1L
b11111110 $
b11011100 %
b10111010 &
b10011000 '
b1110110 (
b1010100 )
b110010 *
b10000 +
#6500000 #6500000
#6750000 #6750000
0# 0#
@ -562,6 +562,14 @@ b1000110 ("
b10001010 0" b10001010 0"
b11001110 8" b11001110 8"
1# 1#
b0 $
b0 %
b0 &
b0 '
b0 (
b0 )
b0 *
b0 +
1. 1.
1A 1A
b0 B b0 B
@ -573,14 +581,6 @@ b0 G
b0 H b0 H
b0 I b0 I
1L 1L
b0 $
b0 %
b0 &
b0 '
b0 (
b0 )
b0 *
b0 +
#7500000 #7500000
#7750000 #7750000
0# 0#
@ -688,6 +688,14 @@ b1 !
b1 ? b1 ?
#10250000 #10250000
1# 1#
b11111110 $
b11011100 %
b10111010 &
b10011000 '
b1110110 (
b1010100 )
b110010 *
b10000 +
1. 1.
1A 1A
b11111110 B b11111110 B
@ -699,14 +707,6 @@ b1010100 G
b110010 H b110010 H
b10000 I b10000 I
1L 1L
b11111110 $
b11011100 %
b10111010 &
b10011000 '
b1110110 (
b1010100 )
b110010 *
b10000 +
#10500000 #10500000
#10750000 #10750000
0# 0#
@ -718,6 +718,14 @@ b10 !
b10 ? b10 ?
#11250000 #11250000
1# 1#
b10011 $
b1010111 %
b10011011 &
b11011111 '
b10 (
b1000110 )
b10001010 *
b11001110 +
1. 1.
1A 1A
b10011 B b10011 B
@ -729,14 +737,6 @@ b1000110 G
b10001010 H b10001010 H
b11001110 I b11001110 I
1L 1L
b10011 $
b1010111 %
b10011011 &
b11011111 '
b10 (
b1000110 )
b10001010 *
b11001110 +
#11500000 #11500000
#11750000 #11750000
0# 0#
@ -748,6 +748,14 @@ b11 !
b11 ? b11 ?
#12250000 #12250000
1# 1#
b1110100 $
b1100101 %
b1110011 &
b1110100 '
b1101001 (
b1101110 )
b1100111 *
b100001 +
1. 1.
1A 1A
b1110100 B b1110100 B
@ -759,14 +767,6 @@ b1101110 G
b1100111 H b1100111 H
b100001 I b100001 I
1L 1L
b1110100 $
b1100101 %
b1110011 &
b1110100 '
b1101001 (
b1101110 )
b1100111 *
b100001 +
#12500000 #12500000
#12750000 #12750000
0# 0#
@ -780,6 +780,14 @@ b0 ?
0@ 0@
#13250000 #13250000
1# 1#
b1101101 $
b1101111 %
b1110010 &
b1100101 '
b100000 (
b1110100 )
b1110011 *
b1110100 +
1. 1.
1A 1A
b1101101 B b1101101 B
@ -791,14 +799,6 @@ b1110100 G
b1110011 H b1110011 H
b1110100 I b1110100 I
1L 1L
b1101101 $
b1101111 %
b1110010 &
b1100101 '
b100000 (
b1110100 )
b1110011 *
b1110100 +
#13500000 #13500000
#13750000 #13750000
0# 0#
@ -808,6 +808,14 @@ b1110100 +
#14000000 #14000000
#14250000 #14250000
1# 1#
b0 $
b0 %
b0 &
b0 '
b0 (
b0 )
b0 *
b0 +
1. 1.
1A 1A
b0 B b0 B
@ -819,14 +827,6 @@ b0 G
b0 H b0 H
b0 I b0 I
1L 1L
b0 $
b0 %
b0 &
b0 '
b0 (
b0 )
b0 *
b0 +
#14500000 #14500000
#14750000 #14750000
0# 0#

View file

@ -276,7 +276,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "mod1", name: "mod1",
children: [ children: [
@ -558,7 +557,12 @@ Simulation {
}, },
), ),
], ],
instant: 2 μs,
clocks_triggered: [], clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 2 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -827,52 +827,6 @@ Simulation {
running_generator: Some( 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(ripple_counter.bit_reg_1: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 3, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 33, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
},
value: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
},
},
}, },
SimulationExternModuleState { SimulationExternModuleState {
module_state: SimulationModuleState { module_state: SimulationModuleState {
@ -956,52 +910,6 @@ Simulation {
running_generator: Some( 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(ripple_counter.bit_reg_3: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 6, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 44, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
},
value: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
},
},
}, },
SimulationExternModuleState { SimulationExternModuleState {
module_state: SimulationModuleState { module_state: SimulationModuleState {
@ -1085,55 +993,8 @@ Simulation {
running_generator: Some( 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(ripple_counter.bit_reg_5: sw_reg).sw_reg::clk",
ty: Clock,
}, },
], ],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 9, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 55, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
},
value: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
},
},
},
],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "ripple_counter", name: "ripple_counter",
children: [ children: [
@ -1593,11 +1454,315 @@ Simulation {
}, },
), ),
], ],
instant: 256 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(1), StatePartIndex<SmallSlots>(1),
StatePartIndex<SmallSlots>(4), StatePartIndex<SmallSlots>(4),
StatePartIndex<SmallSlots>(7), StatePartIndex<SmallSlots>(7),
], ],
event_queue: EventQueue(EventQueueData {
instant: 256 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {
SensitivitySet {
id: 152,
values: {
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(ripple_counter.bit_reg_5: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 9, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 55, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
},
changed: Cell {
value: false,
},
..
},
SensitivitySet {
id: 167,
values: {
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(ripple_counter.bit_reg_3: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 6, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 44, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
},
changed: Cell {
value: false,
},
..
},
SensitivitySet {
id: 170,
values: {
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(ripple_counter.bit_reg_1: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 3, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 33, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
},
changed: Cell {
value: false,
},
..
},
},
waiting_sensitivity_sets_by_compiled_value: {
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(ripple_counter.bit_reg_1: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 3, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 33, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: (
SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
{
SensitivitySet {
id: 170,
..
},
},
),
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(ripple_counter.bit_reg_3: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 6, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 44, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: (
SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
{
SensitivitySet {
id: 167,
..
},
},
),
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(ripple_counter.bit_reg_5: sw_reg).sw_reg::clk",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 9, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 55, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: (
SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
{
SensitivitySet {
id: 152,
..
},
},
),
},
.. ..
} }

File diff suppressed because it is too large Load diff

View file

@ -339,7 +339,6 @@ Simulation {
did_initial_settle: true, did_initial_settle: true,
}, },
extern_modules: [], extern_modules: [],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "shift_register", name: "shift_register",
children: [ children: [
@ -440,7 +439,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x0,
}, },
SimTrace { SimTrace {
id: TraceScalarId(1), id: TraceScalarId(1),
@ -509,9 +508,14 @@ Simulation {
}, },
), ),
], ],
instant: 66 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(1), StatePartIndex<SmallSlots>(1),
], ],
event_queue: EventQueue(EventQueueData {
instant: 66 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
.. ..
} }

View file

@ -52,9 +52,9 @@ $end
0! 0!
#11000000 #11000000
1! 1!
1$
0& 0&
1( 1(
1$
#12000000 #12000000
0! 0!
1# 1#
@ -67,10 +67,10 @@ $end
0# 0#
#15000000 #15000000
1! 1!
0$
0% 0%
1& 1&
0( 0(
0$
#16000000 #16000000
0! 0!
1# 1#
@ -83,23 +83,23 @@ $end
0! 0!
#19000000 #19000000
1! 1!
1$
1& 1&
0' 0'
1( 1(
1$
#20000000 #20000000
0! 0!
#21000000 #21000000
1! 1!
0$
1' 1'
0( 0(
0$
#22000000 #22000000
0! 0!
#23000000 #23000000
1! 1!
1(
1$ 1$
1(
#24000000 #24000000
0! 0!
0# 0#
@ -120,8 +120,8 @@ $end
0! 0!
#31000000 #31000000
1! 1!
0(
0$ 0$
0(
#32000000 #32000000
0! 0!
#33000000 #33000000

View file

@ -0,0 +1,523 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 6,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::clocks[0]",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::clocks[1]",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::clocks[2]",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::outputs[0]",
ty: UInt<8>,
},
SlotDebugData {
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::outputs[1]",
ty: UInt<8>,
},
SlotDebugData {
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::outputs[2]",
ty: UInt<8>,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
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,
0,
0,
49,
50,
50,
],
},
sim_only_slots: StatePart {
value: [],
},
},
io: Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
},
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.clocks,
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.outputs,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.clocks,
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.clocks[0],
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.clocks[1],
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.clocks[2],
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.outputs,
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.outputs[0],
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.outputs[1],
Instance {
name: <simulator>::sim_fork_join,
instantiated: Module {
name: sim_fork_join,
..
},
}.outputs[2],
},
did_initial_settle: true,
},
extern_modules: [
SimulationExternModuleState {
module_state: SimulationModuleState {
base_targets: [
ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
},
ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
},
],
uninitialized_ios: {},
io_targets: {
ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
},
ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
}[0],
ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
}[1],
ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
}[2],
ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
},
ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
}[0],
ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
}[1],
ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
}[2],
},
did_initial_settle: true,
},
sim: ExternModuleSimulation {
generator: SimGeneratorFn {
args: (
ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
},
ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
},
),
f: ...,
},
sim_io_to_generator_map: {
ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
}: ModuleIO {
name: sim_fork_join::clocks,
is_input: true,
ty: Array<Clock, 3>,
..
},
ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
}: ModuleIO {
name: sim_fork_join::outputs,
is_input: false,
ty: Array<UInt<8>, 3>,
..
},
},
source_location: SourceLocation(
module-XXXXXXXXXX.rs:4:1,
),
},
running_generator: Some(
...,
),
},
],
trace_decls: TraceModule {
name: "sim_fork_join",
children: [
TraceModuleIO {
name: "clocks",
child: TraceArray {
name: "clocks",
elements: [
TraceClock {
location: TraceScalarId(0),
name: "[0]",
flow: Source,
},
TraceClock {
location: TraceScalarId(1),
name: "[1]",
flow: Source,
},
TraceClock {
location: TraceScalarId(2),
name: "[2]",
flow: Source,
},
],
ty: Array<Clock, 3>,
flow: Source,
},
ty: Array<Clock, 3>,
flow: Source,
},
TraceModuleIO {
name: "outputs",
child: TraceArray {
name: "outputs",
elements: [
TraceUInt {
location: TraceScalarId(3),
name: "[0]",
ty: UInt<8>,
flow: Sink,
},
TraceUInt {
location: TraceScalarId(4),
name: "[1]",
ty: UInt<8>,
flow: Sink,
},
TraceUInt {
location: TraceScalarId(5),
name: "[2]",
ty: UInt<8>,
flow: Sink,
},
],
ty: Array<UInt<8>, 3>,
flow: Sink,
},
ty: Array<UInt<8>, 3>,
flow: Sink,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigClock {
index: StatePartIndex<BigSlots>(0),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(1),
kind: BigClock {
index: StatePartIndex<BigSlots>(1),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(2),
kind: BigClock {
index: StatePartIndex<BigSlots>(2),
},
state: 0x0,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(3),
kind: BigUInt {
index: StatePartIndex<BigSlots>(3),
ty: UInt<8>,
},
state: 0x31,
last_state: 0x31,
},
SimTrace {
id: TraceScalarId(4),
kind: BigUInt {
index: StatePartIndex<BigSlots>(4),
ty: UInt<8>,
},
state: 0x32,
last_state: 0x32,
},
SimTrace {
id: TraceScalarId(5),
kind: BigUInt {
index: StatePartIndex<BigSlots>(5),
ty: UInt<8>,
},
state: 0x32,
last_state: 0x32,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 648 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {
SensitivitySet {
id: 198,
values: {
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
},
changed: Cell {
value: false,
},
..
},
},
waiting_sensitivity_sets_by_compiled_value: {
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 0, len: 0 },
},
write: None,
}: (
SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x0_u1,
sim_only_values: [],
},
},
{
SensitivitySet {
id: 198,
..
},
},
),
},
..
}

File diff suppressed because it is too large Load diff

View file

@ -717,52 +717,6 @@ Simulation {
running_generator: Some( 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: "",
ty: Clock,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 4, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 6, len: 0 },
},
write: None,
},
value: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
},
},
}, },
SimulationExternModuleState { SimulationExternModuleState {
module_state: SimulationModuleState { module_state: SimulationModuleState {
@ -922,55 +876,8 @@ Simulation {
running_generator: Some( 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: "",
ty: Clock,
}, },
], ],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 4, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 12, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 13, len: 0 },
},
write: None,
},
value: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
},
},
},
],
state_ready_to_run: false,
trace_decls: TraceModule { trace_decls: TraceModule {
name: "sim_only_connects", name: "sim_only_connects",
children: [ children: [
@ -1628,9 +1535,214 @@ Simulation {
}, },
), ),
], ],
instant: 16 μs,
clocks_triggered: [ clocks_triggered: [
StatePartIndex<SmallSlots>(1), StatePartIndex<SmallSlots>(1),
], ],
event_queue: EventQueue(EventQueueData {
instant: 16 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {
SensitivitySet {
id: 30,
values: {
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 4, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 6, len: 0 },
},
write: None,
}: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
},
changed: Cell {
value: false,
},
..
},
SensitivitySet {
id: 31,
values: {
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 4, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 12, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 13, len: 0 },
},
write: None,
}: SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
},
changed: Cell {
value: false,
},
..
},
},
waiting_sensitivity_sets_by_compiled_value: {
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 4, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 6, len: 0 },
},
write: None,
}: (
SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
{
SensitivitySet {
id: 30,
..
},
},
),
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,
},
],
..
},
sim_only_slots: StatePartLayout<SimOnlySlots> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 4, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 12, len: 1 },
sim_only_slots: StatePartIndexRange<SimOnlySlots> { start: 13, len: 0 },
},
write: None,
}: (
SimValue {
ty: Clock,
value: OpaqueSimValue {
bits: 0x1_u1,
sim_only_values: [],
},
},
{
SensitivitySet {
id: 31,
..
},
},
),
},
.. ..
} }

View file

@ -72,22 +72,22 @@ s{} 8
$end $end
#1000000 #1000000
1! 1!
s{\"extra\":\x20\"value\"} $
1' 1'
s{\"extra\":\x20\"value\"} )
1+ 1+
s{\"extra\":\x20\"value\"} -
10 10
11 11
15 15
s{\"extra\":\x20\"value\"} $
s{\"extra\":\x20\"value\"} )
s{\"extra\":\x20\"value\"} -
s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} *
s{\"bar\":\x20\"\",\x20\"foo\":\x20\"baz\"} 4
s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} % s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} %
s{\"bar\":\x20\"\",\x20\"foo\":\x20\"baz\"} & s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} *
s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} . s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} .
s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 3 s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 3
s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 7 s{\"bar\":\x20\"\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 7
s{\"bar\":\x20\"\",\x20\"foo\":\x20\"baz\"} 8 s{\"bar\":\x20\"baz\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} &
s{\"bar\":\x20\"baz\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 4
s{\"bar\":\x20\"baz\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 8
#2000000 #2000000
0! 0!
0" 0"
@ -107,9 +107,6 @@ s{\"extra\":\x20\"value\"} /
00 00
11 11
15 15
s{\"bar\":\x20\"baz\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 4
s{\"bar\":\x20\"baz\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} &
s{\"bar\":\x20\"baz\",\x20\"extra\":\x20\"value\",\x20\"foo\":\x20\"baz\"} 8
#4000000 #4000000
0! 0!
0' 0'