Compare commits

..

26 commits

Author SHA1 Message Date
2266315944
redo #[hdl(sim)] match/let destructuring to support matching values of type Type::SimValue 2026-05-03 23:23:17 -07:00
7e9d7739fb
use #[hdl(cmp_eq)] for HdlOption and implement conversion <-> Option 2026-05-01 18:46:36 -07:00
7516ec3c24
implement #[hdl(cmp_eq)] for enums 2026-05-01 18:34:49 -07:00
8e4eeef723
add support for custom debug/display formatting of #[hdl] structs/enums
also cleans up default debug formatting to use the struct/enum name
(or MaskType<StructName>) instead of the implementation detail type name.
2026-04-30 23:10:49 -07:00
402f457c68
sim: Speed up updating traces by tracking which traces are written to 2026-04-30 19:12:20 -07:00
8cff3687f7
Run Rocq tests.
Some checks failed
/ test (push) Has been cancelled
2026-03-30 19:36:24 -03:00
80b92c7dd3
change vcd output to have module contents under instance's name, more closely matching how it works in verilog 2026-03-26 18:21:14 -07:00
2aa41137d4
add simulator tests for queue() 2026-03-24 23:30:15 -07:00
a0b2dc085c
add test that simulator handles last-connect semantics properly 2026-03-24 23:29:30 -07:00
a8a541b357
sim/compiler: fix registers so they properly retain their old value when not written 2026-03-24 23:26:47 -07:00
52c41bb5db
display signals when panicking because not all inputs/outputs are written yet 2026-03-24 23:25:14 -07:00
a93e66d8ab
update ui test's expected output for having rust-src available 2026-03-17 20:43:46 -07:00
eb3ca59053
add rust-src to CI 2026-03-17 20:42:54 -07:00
dbed947408
change VCD id generation to be based on hashing the path, making them better for git diff 2026-02-23 20:05:10 -08:00
cb4e1f42c0
silence unused import warning 2026-02-23 16:07:46 -08:00
8c270b0e35
silence warning for enums with only one variant 2026-02-23 16:07:05 -08:00
c632e5d570
speed up simulation by optimizing SimulationImpl::read_traces
this makes cpu/crates/cpu/tests/next_pc.rs take 56s instead of 168s
2026-02-04 15:41:09 -08:00
1bc835803b
speed up LazyInterned by redoing caching using RwLock and add a thread-local cache 2026-02-03 18:00:36 -08:00
9db3240644
fix UI test's expected output 2026-02-03 18:00:36 -08:00
caa097db0b
change rust version to 1.93.0 2026-02-03 17:29:59 -08:00
a96efa9696
cache interned UInt/SInt types 2026-02-02 17:51:30 -08:00
4ac1bcbc0a
change Interner to use a sharded hash table 2026-02-02 15:49:26 -08:00
39810043ea
move Interner into new mod interner 2026-02-02 15:44:37 -08:00
26b0dc3fd8
change Interner to pub(crate) 2026-02-02 15:42:12 -08:00
11281a9842
add a thread-local cache when using TypeIdMap 2026-02-01 21:19:32 -08:00
e366793204
don't compare function pointers -- they're non-deterministic 2026-01-12 03:11:36 -08:00
129 changed files with 80598 additions and 10577 deletions

View file

@ -16,6 +16,9 @@ jobs:
- uses: https://git.libre-chip.org/mirrors/rust-cache@v2 - uses: https://git.libre-chip.org/mirrors/rust-cache@v2
with: with:
save-if: ${{ github.ref == 'refs/heads/master' }} save-if: ${{ github.ref == 'refs/heads/master' }}
- run: rustup override set 1.93.0
- run: rustup component add rust-src
- run: make -C rocq-demo
- run: cargo test - run: cargo test
- run: cargo build --tests --features=unstable-doc - run: cargo build --tests --features=unstable-doc
- run: cargo test --doc --features=unstable-doc - run: cargo test --doc --features=unstable-doc

6
Cargo.lock generated
View file

@ -319,10 +319,12 @@ dependencies = [
"jobslot", "jobslot",
"num-bigint", "num-bigint",
"num-traits", "num-traits",
"once_cell",
"ordered-float", "ordered-float",
"petgraph", "petgraph",
"serde", "serde",
"serde_json", "serde_json",
"sha2",
"tempfile", "tempfile",
"trybuild", "trybuild",
"vec_map", "vec_map",
@ -521,9 +523,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]] [[package]]
name = "ordered-float" name = "ordered-float"

View file

@ -11,7 +11,7 @@ edition = "2024"
repository = "https://git.libre-chip.org/libre-chip/fayalite" repository = "https://git.libre-chip.org/libre-chip/fayalite"
keywords = ["hdl", "hardware", "semiconductors", "firrtl", "fpga"] keywords = ["hdl", "hardware", "semiconductors", "firrtl", "fpga"]
categories = ["simulation", "development-tools", "compilers"] categories = ["simulation", "development-tools", "compilers"]
rust-version = "1.89.0" rust-version = "1.93.0"
[workspace.dependencies] [workspace.dependencies]
fayalite-proc-macros = { version = "=0.3.0", path = "crates/fayalite-proc-macros" } fayalite-proc-macros = { version = "=0.3.0", path = "crates/fayalite-proc-macros" }
@ -30,6 +30,7 @@ indexmap = { version = "2.5.0", features = ["serde"] }
jobslot = "0.2.23" jobslot = "0.2.23"
num-bigint = "0.4.6" num-bigint = "0.4.6"
num-traits = "0.2.16" num-traits = "0.2.16"
once_cell = "1.21.3"
ordered-float = { version = "5.1.0", features = ["serde"] } ordered-float = { version = "5.1.0", features = ["serde"] }
petgraph = "0.8.1" petgraph = "0.8.1"
prettyplease = "0.2.20" prettyplease = "0.2.20"

View file

@ -257,5 +257,6 @@ no_op_fold!(syn::Token![let]);
no_op_fold!(syn::Token![mut]); no_op_fold!(syn::Token![mut]);
no_op_fold!(syn::Token![static]); no_op_fold!(syn::Token![static]);
no_op_fold!(syn::Token![struct]); no_op_fold!(syn::Token![struct]);
no_op_fold!(syn::Token![type]);
no_op_fold!(syn::Token![where]); no_op_fold!(syn::Token![where]);
no_op_fold!(usize); no_op_fold!(usize);

View file

@ -3,8 +3,9 @@
use crate::{ use crate::{
Errors, HdlAttr, PairsIterExt, Errors, HdlAttr, PairsIterExt,
hdl_type_common::{ hdl_type_common::{
ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedField, ParsedFieldsNamed, ParsedGenerics, CustomDebugOptions, CustomDebugTrait, ItemOptions, MakeHdlTypeExpr, MaybeParsed,
SplitForImpl, TypesParser, WrappedInConst, common_derives, get_target, ParsedField, ParsedFieldsNamed, ParsedGenerics, SplitForImpl, TypesParser, WrappedInConst,
common_derives, create_struct_debug_impl, get_target,
}, },
kw, kw,
}; };
@ -30,6 +31,7 @@ pub(crate) struct ParsedBundle {
pub(crate) fields: MaybeParsed<ParsedFieldsNamed, FieldsNamed>, pub(crate) fields: MaybeParsed<ParsedFieldsNamed, FieldsNamed>,
pub(crate) field_flips: Vec<Option<HdlAttr<kw::flip, kw::hdl>>>, pub(crate) field_flips: Vec<Option<HdlAttr<kw::flip, kw::hdl>>>,
pub(crate) mask_type_ident: Ident, pub(crate) mask_type_ident: Ident,
pub(crate) mask_type_name: String,
pub(crate) mask_type_match_variant_ident: Ident, pub(crate) mask_type_match_variant_ident: Ident,
pub(crate) mask_type_sim_value_ident: Ident, pub(crate) mask_type_sim_value_ident: Ident,
pub(crate) match_variant_ident: Ident, pub(crate) match_variant_ident: Ident,
@ -88,6 +90,8 @@ impl ParsedBundle {
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq: _, cmp_eq: _,
ref get, ref get,
custom_debug: _,
custom_sim_display: _,
} = options.body; } = options.body;
if let Some((get, ..)) = get { if let Some((get, ..)) = get {
errors.error(get, "#[hdl(get(...))] is not allowed on structs"); errors.error(get, "#[hdl(get(...))] is not allowed on structs");
@ -131,6 +135,7 @@ impl ParsedBundle {
fields, fields,
field_flips, field_flips,
mask_type_ident: format_ident!("__{}__MaskType", ident), mask_type_ident: format_ident!("__{}__MaskType", ident),
mask_type_name: format!("MaskType<{}>", ident),
mask_type_match_variant_ident: format_ident!("__{}__MaskType__MatchVariant", ident), mask_type_match_variant_ident: format_ident!("__{}__MaskType__MatchVariant", ident),
mask_type_sim_value_ident: format_ident!("__{}__MaskType__SimValue", ident), mask_type_sim_value_ident: format_ident!("__{}__MaskType__SimValue", ident),
match_variant_ident: format_ident!("__{}__MatchVariant", ident), match_variant_ident: format_ident!("__{}__MatchVariant", ident),
@ -448,6 +453,7 @@ impl ToTokens for ParsedBundle {
fields, fields,
field_flips, field_flips,
mask_type_ident, mask_type_ident,
mask_type_name,
mask_type_match_variant_ident, mask_type_match_variant_ident,
mask_type_sim_value_ident, mask_type_sim_value_ident,
match_variant_ident, match_variant_ident,
@ -464,11 +470,20 @@ impl ToTokens for ParsedBundle {
no_runtime_generics, no_runtime_generics,
cmp_eq, cmp_eq,
get: _, get: _,
custom_debug: _,
custom_sim_display,
} = &options.body; } = &options.body;
let CustomDebugOptions {
type_: custom_debug_type,
sim: custom_debug_sim,
mask_type: custom_debug_mask_type,
mask_sim: custom_debug_mask_sim,
} = options.body.custom_debug();
let target = get_target(target, ident); let target = get_target(target, ident);
let struct_name = ident.to_string();
let mut item_attrs = attrs.clone(); let mut item_attrs = attrs.clone();
item_attrs.push(common_derives(span)); item_attrs.push(common_derives(span, false));
ItemStruct { let type_struct = ItemStruct {
attrs: item_attrs, attrs: item_attrs,
vis: vis.clone(), vis: vis.clone(),
struct_token: *struct_token, struct_token: *struct_token,
@ -476,8 +491,8 @@ impl ToTokens for ParsedBundle {
generics: generics.into(), generics: generics.into(),
fields: Fields::Named(fields.clone().into()), fields: Fields::Named(fields.clone().into()),
semi_token: None, semi_token: None,
} };
.to_tokens(tokens); type_struct.to_tokens(tokens);
let (impl_generics, type_generics, where_clause) = generics.split_for_impl(); let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
if let (MaybeParsed::Parsed(generics), MaybeParsed::Parsed(fields), None) = if let (MaybeParsed::Parsed(generics), MaybeParsed::Parsed(fields), None) =
(generics, fields, no_runtime_generics) (generics, fields, no_runtime_generics)
@ -503,6 +518,9 @@ impl ToTokens for ParsedBundle {
} }
let mut wrapped_in_const = WrappedInConst::new(tokens, span); let mut wrapped_in_const = WrappedInConst::new(tokens, span);
let tokens = wrapped_in_const.inner(); let tokens = wrapped_in_const.inner();
if custom_debug_type.is_none() {
create_struct_debug_impl(&type_struct, &struct_name, None).to_tokens(tokens);
}
let builder = Builder { let builder = Builder {
vis: vis.clone(), vis: vis.clone(),
struct_token: *struct_token, struct_token: *struct_token,
@ -530,9 +548,9 @@ impl ToTokens for ParsedBundle {
mask_type_builder.to_tokens(tokens); mask_type_builder.to_tokens(tokens);
let unfilled_mask_type_builder_ty = let unfilled_mask_type_builder_ty =
mask_type_builder.builder_struct_ty(|_| BuilderFieldState::Unfilled); mask_type_builder.builder_struct_ty(|_| BuilderFieldState::Unfilled);
ItemStruct { let mask_type_struct = ItemStruct {
attrs: vec![ attrs: vec![
common_derives(span), common_derives(span, false),
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[allow(non_camel_case_types, dead_code)] #[allow(non_camel_case_types, dead_code)]
}, },
@ -543,17 +561,20 @@ impl ToTokens for ParsedBundle {
generics: generics.into(), generics: generics.into(),
fields: Fields::Named(mask_type_fields.clone()), fields: Fields::Named(mask_type_fields.clone()),
semi_token: None, semi_token: None,
};
mask_type_struct.to_tokens(tokens);
if custom_debug_mask_type.is_none() {
create_struct_debug_impl(&mask_type_struct, mask_type_name, None).to_tokens(tokens);
} }
.to_tokens(tokens);
let mut mask_type_match_variant_fields = mask_type_fields.clone(); let mut mask_type_match_variant_fields = mask_type_fields.clone();
for Field { ty, .. } in &mut mask_type_match_variant_fields.named { for Field { ty, .. } in &mut mask_type_match_variant_fields.named {
*ty = parse_quote_spanned! {span=> *ty = parse_quote_spanned! {span=>
::fayalite::expr::Expr<#ty> ::fayalite::expr::Expr<#ty>
}; };
} }
ItemStruct { let mask_type_match_variant_struct = ItemStruct {
attrs: vec![ attrs: vec![
common_derives(span), common_derives(span, false),
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[allow(non_camel_case_types, dead_code)] #[allow(non_camel_case_types, dead_code)]
}, },
@ -564,17 +585,19 @@ impl ToTokens for ParsedBundle {
generics: generics.into(), generics: generics.into(),
fields: Fields::Named(mask_type_match_variant_fields), fields: Fields::Named(mask_type_match_variant_fields),
semi_token: None, semi_token: None,
} };
.to_tokens(tokens); mask_type_match_variant_struct.to_tokens(tokens);
create_struct_debug_impl(&mask_type_match_variant_struct, mask_type_name, None)
.to_tokens(tokens);
let mut match_variant_fields = FieldsNamed::from(fields.clone()); let mut match_variant_fields = FieldsNamed::from(fields.clone());
for Field { ty, .. } in &mut match_variant_fields.named { for Field { ty, .. } in &mut match_variant_fields.named {
*ty = parse_quote_spanned! {span=> *ty = parse_quote_spanned! {span=>
::fayalite::expr::Expr<#ty> ::fayalite::expr::Expr<#ty>
}; };
} }
ItemStruct { let match_variant_struct = ItemStruct {
attrs: vec![ attrs: vec![
common_derives(span), common_derives(span, false),
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[allow(non_camel_case_types, dead_code)] #[allow(non_camel_case_types, dead_code)]
}, },
@ -585,19 +608,19 @@ impl ToTokens for ParsedBundle {
generics: generics.into(), generics: generics.into(),
fields: Fields::Named(match_variant_fields), fields: Fields::Named(match_variant_fields),
semi_token: None, semi_token: None,
} };
.to_tokens(tokens); match_variant_struct.to_tokens(tokens);
create_struct_debug_impl(&match_variant_struct, &struct_name, None).to_tokens(tokens);
let mut mask_type_sim_value_fields = mask_type_fields; let mut mask_type_sim_value_fields = mask_type_fields;
for Field { ty, .. } in &mut mask_type_sim_value_fields.named { for Field { ty, .. } in &mut mask_type_sim_value_fields.named {
*ty = parse_quote_spanned! {span=> *ty = parse_quote_spanned! {span=>
::fayalite::sim::value::SimValue<#ty> ::fayalite::sim::value::SimValue<#ty>
}; };
} }
ItemStruct { let mask_type_sim_value_struct = ItemStruct {
attrs: vec![ attrs: vec![
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[::fayalite::__std::prelude::v1::derive( #[::fayalite::__std::prelude::v1::derive(
::fayalite::__std::fmt::Debug,
::fayalite::__std::clone::Clone, ::fayalite::__std::clone::Clone,
)] )]
}, },
@ -611,19 +634,34 @@ impl ToTokens for ParsedBundle {
generics: generics.into(), generics: generics.into(),
fields: Fields::Named(mask_type_sim_value_fields), fields: Fields::Named(mask_type_sim_value_fields),
semi_token: None, semi_token: None,
};
mask_type_sim_value_struct.to_tokens(tokens);
if custom_debug_mask_sim.is_none() {
create_struct_debug_impl(
&mask_type_struct,
mask_type_name,
Some(CustomDebugTrait {
trait_path: &parse_quote_spanned! {span=>
::fayalite::ty::SimValueDebug
},
fn_name: &format_ident!("sim_value_debug", span = span),
this_arg: &parse_quote_spanned! {span=>
value: &<Self as ::fayalite::ty::Type>::SimValue
},
}),
)
.to_tokens(tokens);
} }
.to_tokens(tokens);
let mut sim_value_fields = FieldsNamed::from(fields.clone()); let mut sim_value_fields = FieldsNamed::from(fields.clone());
for Field { ty, .. } in &mut sim_value_fields.named { for Field { ty, .. } in &mut sim_value_fields.named {
*ty = parse_quote_spanned! {span=> *ty = parse_quote_spanned! {span=>
::fayalite::sim::value::SimValue<#ty> ::fayalite::sim::value::SimValue<#ty>
}; };
} }
ItemStruct { let sim_value_struct = ItemStruct {
attrs: vec![ attrs: vec![
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[::fayalite::__std::prelude::v1::derive( #[::fayalite::__std::prelude::v1::derive(
::fayalite::__std::fmt::Debug,
::fayalite::__std::clone::Clone, ::fayalite::__std::clone::Clone,
)] )]
}, },
@ -637,8 +675,36 @@ impl ToTokens for ParsedBundle {
generics: generics.into(), generics: generics.into(),
fields: Fields::Named(sim_value_fields), fields: Fields::Named(sim_value_fields),
semi_token: None, semi_token: None,
};
sim_value_struct.to_tokens(tokens);
if custom_debug_sim.is_none() {
create_struct_debug_impl(
&type_struct,
&struct_name,
Some(CustomDebugTrait {
trait_path: &parse_quote_spanned! {span=>
::fayalite::ty::SimValueDebug
},
fn_name: &format_ident!("sim_value_debug", span = span),
this_arg: &parse_quote_spanned! {span=>
value: &<Self as ::fayalite::ty::Type>::SimValue
},
}),
)
.to_tokens(tokens);
}
if custom_sim_display.is_some() {
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics ::fayalite::__std::fmt::Display for #sim_value_ident #type_generics
#where_clause
{
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
<#target #type_generics as ::fayalite::ty::SimValueDisplay>::sim_value_display(self, f)
}
}
}.to_tokens(tokens);
} }
.to_tokens(tokens);
let this_token = Ident::new("__this", span); let this_token = Ident::new("__this", span);
let fields_token = Ident::new("__fields", span); let fields_token = Ident::new("__fields", span);
let self_token = Token![self](span); let self_token = Token![self](span);
@ -820,6 +886,14 @@ impl ToTokens for ParsedBundle {
} }
} }
#[automatically_derived] #[automatically_derived]
impl #impl_generics ::fayalite::__std::fmt::Debug for #mask_type_sim_value_ident #type_generics
#where_clause
{
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
<#mask_type_ident #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f)
}
}
#[automatically_derived]
impl #impl_generics ::fayalite::expr::ValueType for #mask_type_sim_value_ident #type_generics impl #impl_generics ::fayalite::expr::ValueType for #mask_type_sim_value_ident #type_generics
#where_clause #where_clause
{ {
@ -980,6 +1054,14 @@ impl ToTokens for ParsedBundle {
} }
} }
#[automatically_derived] #[automatically_derived]
impl #impl_generics ::fayalite::__std::fmt::Debug for #sim_value_ident #type_generics
#where_clause
{
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
<#target #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f)
}
}
#[automatically_derived]
impl #impl_generics ::fayalite::expr::ValueType for #sim_value_ident #type_generics impl #impl_generics ::fayalite::expr::ValueType for #sim_value_ident #type_generics
#where_clause #where_clause
{ {
@ -1141,7 +1223,7 @@ impl ToTokens for ParsedBundle {
valueless_eq_body = quote_spanned! {span=> valueless_eq_body = quote_spanned! {span=>
let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); let __lhs = ::fayalite::expr::ValueType::ty(&__lhs);
let __rhs = ::fayalite::expr::ValueType::ty(&__rhs); let __rhs = ::fayalite::expr::ValueType::ty(&__rhs);
#(#fields_valueless_eq)|* #(#fields_valueless_eq)&*
}; };
valueless_ne_body = quote_spanned! {span=> valueless_ne_body = quote_spanned! {span=>
let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); let __lhs = ::fayalite::expr::ValueType::ty(&__lhs);

View file

@ -3,8 +3,9 @@
use crate::{ use crate::{
Errors, HdlAttr, PairsIterExt, Errors, HdlAttr, PairsIterExt,
hdl_type_common::{ hdl_type_common::{
ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, SplitForImpl, CustomDebugOptions, ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType,
TypesParser, WrappedInConst, common_derives, get_target, SplitForImpl, TypesParser, WrappedInConst, common_derives, create_struct_debug_impl,
get_target,
}, },
kw, kw,
}; };
@ -158,15 +159,32 @@ impl ParsedEnum {
custom_bounds, custom_bounds,
no_static: _, no_static: _,
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq, cmp_eq: _,
ref get, ref get,
custom_debug: _,
custom_sim_display: _,
} = options.body; } = options.body;
if let Some((cmp_eq,)) = cmp_eq {
errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for enums");
}
if let Some((get, ..)) = get { if let Some((get, ..)) = get {
errors.error(get, "#[hdl(get(...))] is not allowed on enums"); errors.error(get, "#[hdl(get(...))] is not allowed on enums");
} }
let CustomDebugOptions {
type_: _,
sim: _,
mask_type,
mask_sim,
} = options.body.custom_debug();
if let Some((mask_type,)) = mask_type {
errors.error(
mask_type,
"#[hdl(custom_debug(mask_type)] is not allowed on enums",
);
}
if let Some((mask_sim,)) = mask_sim {
errors.error(
mask_sim,
"#[hdl(custom_debug(mask_sim)] 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");
@ -228,12 +246,21 @@ impl ToTokens for ParsedEnum {
custom_bounds: _, custom_bounds: _,
no_static, no_static,
no_runtime_generics, no_runtime_generics,
cmp_eq: _, // TODO: implement cmp_eq for enums cmp_eq,
get: _, get: _,
custom_debug: _,
custom_sim_display,
} = &options.body; } = &options.body;
let CustomDebugOptions {
type_: custom_debug_type,
sim: custom_debug_sim,
mask_type: _,
mask_sim: _,
} = options.body.custom_debug();
let target = get_target(target, ident); let target = get_target(target, ident);
let enum_name = ident.to_string();
let mut struct_attrs = attrs.clone(); let mut struct_attrs = attrs.clone();
struct_attrs.push(common_derives(span)); struct_attrs.push(common_derives(span, false));
struct_attrs.push(parse_quote_spanned! {span=> struct_attrs.push(parse_quote_spanned! {span=>
#[allow(non_snake_case)] #[allow(non_snake_case)]
}); });
@ -273,7 +300,7 @@ impl ToTokens for ParsedEnum {
} }
}, },
)); ));
ItemStruct { let type_struct = ItemStruct {
attrs: struct_attrs, attrs: struct_attrs,
vis: vis.clone(), vis: vis.clone(),
struct_token: Token![struct](enum_token.span), struct_token: Token![struct](enum_token.span),
@ -288,8 +315,8 @@ impl ToTokens for ParsedEnum {
}) })
}, },
semi_token: None, semi_token: None,
} };
.to_tokens(tokens); type_struct.to_tokens(tokens);
let (impl_generics, type_generics, where_clause) = generics.split_for_impl(); let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
if let (MaybeParsed::Parsed(generics), None) = (generics, no_runtime_generics) { if let (MaybeParsed::Parsed(generics), None) = (generics, no_runtime_generics) {
generics.make_runtime_generics(tokens, vis, ident, &target, |context| { generics.make_runtime_generics(tokens, vis, ident, &target, |context| {
@ -373,6 +400,9 @@ impl ToTokens for ParsedEnum {
} }
.to_tokens(tokens); .to_tokens(tokens);
} }
if custom_debug_type.is_none() {
create_struct_debug_impl(&type_struct, &enum_name, None).to_tokens(tokens);
}
let mut enum_attrs = attrs.clone(); let mut enum_attrs = attrs.clone();
enum_attrs.push(parse_quote_spanned! {span=> enum_attrs.push(parse_quote_spanned! {span=>
#[allow(dead_code, non_camel_case_types)] #[allow(dead_code, non_camel_case_types)]
@ -453,7 +483,6 @@ impl ToTokens for ParsedEnum {
let mut enum_attrs = attrs.clone(); let mut enum_attrs = attrs.clone();
enum_attrs.push(parse_quote_spanned! {span=> enum_attrs.push(parse_quote_spanned! {span=>
#[::fayalite::__std::prelude::v1::derive( #[::fayalite::__std::prelude::v1::derive(
::fayalite::__std::fmt::Debug,
::fayalite::__std::clone::Clone, ::fayalite::__std::clone::Clone,
)] )]
}); });
@ -838,6 +867,240 @@ impl ToTokens for ParsedEnum {
}, },
)), )),
); );
if custom_debug_sim.is_none() {
let debug_match_arms = Vec::from_iter(
variants
.iter()
.map(
|ParsedVariant {
attrs: _,
options: _,
ident,
field,
}| {
let variant_name = ident.to_string();
if let Some(_) = field {
quote_spanned! {span=>
#sim_value_ident::#ident(field, _) => {
f.debug_tuple(#variant_name).field(field).finish()
}
}
} else {
quote_spanned! {span=>
#sim_value_ident::#ident(_) => {
f.write_str(#variant_name)
}
}
}
},
)
.chain(sim_value_unknown_variant_name.as_ref().map(
|sim_value_unknown_variant_name| {
let sim_value_unknown_variant_name_str =
sim_value_unknown_variant_name.to_string();
quote_spanned! {span=>
#sim_value_ident::#sim_value_unknown_variant_name(_) => {
f.write_str(#sim_value_unknown_variant_name_str)
}
}
},
)),
);
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics ::fayalite::ty::SimValueDebug for #target #type_generics
#where_clause
{
fn sim_value_debug(
value: &<Self as ::fayalite::ty::Type>::SimValue,
f: &mut ::fayalite::__std::fmt::Formatter<'_>,
) -> ::fayalite::__std::fmt::Result {
match value {
#(#debug_match_arms)*
}
}
}
}
.to_tokens(tokens);
}
if custom_sim_display.is_some() {
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics ::fayalite::__std::fmt::Display for #sim_value_ident #type_generics
#where_clause
{
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
<#target #type_generics as ::fayalite::ty::SimValueDisplay>::sim_value_display(self, f)
}
}
}.to_tokens(tokens);
}
if let Some((cmp_eq,)) = cmp_eq {
let mut cmp_eq_where_clause =
Generics::from(generics)
.where_clause
.unwrap_or_else(|| syn::WhereClause {
where_token: Token![where](span),
predicates: Punctuated::new(),
});
let mut variants_value_eq = vec![];
let mut variants_expr_eq = vec![];
let mut fields_valueless_eq = vec![];
for (
variant_index,
ParsedVariant {
attrs: _,
options: variant_options,
ident: variant_ident,
field,
},
) in variants.iter().enumerate()
{
let VariantOptions {} = variant_options.body;
if let Some(ParsedVariantField {
paren_token: _,
attrs: _,
options: field_options,
ty: field_ty,
comma_token: _,
}) = field
{
let FieldOptions {} = field_options.body;
cmp_eq_where_clause
.predicates
.push(parse_quote_spanned! {cmp_eq.span=>
#field_ty: ::fayalite::expr::HdlPartialEqImpl<#field_ty>
});
variants_value_eq.push(quote_spanned! {span=>
(#sim_value_ident::#variant_ident(__lhs_field, _), #sim_value_ident::#variant_ident(__rhs_field, _)) => {
::fayalite::expr::HdlPartialEqImpl::cmp_value_eq(
__lhs.#variant_ident,
::fayalite::__std::borrow::Cow::Borrowed(__lhs_field),
__rhs.#variant_ident,
::fayalite::__std::borrow::Cow::Borrowed(__rhs_field),
)
}
});
variants_expr_eq.push(quote_spanned! {span=>
{
let (#match_variant_ident::#variant_ident(__lhs), __scope) =
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter)
.expect("known to have enough variants"),
)
else {
::fayalite::__std::unreachable!();
};
let (#match_variant_ident::#variant_ident(__rhs), __scope) =
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
::fayalite::__std::iter::Iterator::nth(
&mut ::fayalite::module::match_(__rhs),
#variant_index,
)
.expect("known to have variant"),
)
else {
::fayalite::__std::unreachable!();
};
::fayalite::module::connect(__retval, ::fayalite::expr::HdlPartialEqImpl::cmp_expr_eq(__lhs, __rhs));
}
});
fields_valueless_eq.push(quote_spanned! {span=>
::fayalite::expr::HdlPartialEqImpl::cmp_valueless_eq(
::fayalite::expr::Valueless::new(__lhs.#variant_ident),
::fayalite::expr::Valueless::new(__rhs.#variant_ident),
)
});
} else {
variants_value_eq.push(quote_spanned! {span=>
(#sim_value_ident::#variant_ident(_), #sim_value_ident::#variant_ident(_)) => true,
});
variants_expr_eq.push(quote_spanned! {span=>
{
let (#match_variant_ident::#variant_ident, __scope) =
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter)
.expect("known to have enough variants"),
)
else {
::fayalite::__std::unreachable!();
};
let (#match_variant_ident::#variant_ident, __scope) =
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
::fayalite::__std::iter::Iterator::nth(
&mut ::fayalite::module::match_(__rhs),
#variant_index,
)
.expect("known to have variant"),
)
else {
::fayalite::__std::unreachable!();
};
::fayalite::module::connect(__retval, true);
}
});
}
}
if let Some(sim_value_unknown_variant_name) = &sim_value_unknown_variant_name {
variants_value_eq.push(quote_spanned! {span=>
(#sim_value_ident::#sim_value_unknown_variant_name(__lhs_unknown), #sim_value_ident::#sim_value_unknown_variant_name(__rhs_unknown)) => {
__lhs_unknown == __rhs_unknown
}
});
}
let valueless_eq_body = if fields_valueless_eq.is_empty() {
quote_spanned! {span=>
::fayalite::expr::Valueless::new(::fayalite::int::Bool)
}
} else {
quote_spanned! {span=>
let __lhs = ::fayalite::expr::ValueType::ty(&__lhs);
let __rhs = ::fayalite::expr::ValueType::ty(&__rhs);
#(#fields_valueless_eq)&*
}
};
let cmp_expr_eq_wire_name = format!("{ident}_cmp_eq");
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics ::fayalite::expr::HdlPartialEqImpl<Self> for #target #type_generics
#cmp_eq_where_clause
{
#[track_caller]
fn cmp_value_eq(
__lhs: Self,
__lhs_value: ::fayalite::__std::borrow::Cow<'_, <Self as ::fayalite::ty::Type>::SimValue>,
__rhs: Self,
__rhs_value: ::fayalite::__std::borrow::Cow<'_, <Self as ::fayalite::ty::Type>::SimValue>,
) -> ::fayalite::__std::primitive::bool {
match (&*__lhs_value, &*__rhs_value) {
#(#variants_value_eq)*
_ => false,
}
}
#[track_caller]
fn cmp_expr_eq(
__lhs: ::fayalite::expr::Expr<Self>,
__rhs: ::fayalite::expr::Expr<Self>,
) -> ::fayalite::expr::Expr<::fayalite::int::Bool> {
let __retval = ::fayalite::module::wire(::fayalite::module::ImplicitName(#cmp_expr_eq_wire_name), ::fayalite::int::Bool);
::fayalite::module::connect(__retval, false);
let mut __lhs_match_variant_iter = ::fayalite::module::match_(__lhs);
#(#variants_expr_eq)*
__retval
}
#[track_caller]
fn cmp_valueless_eq(
__lhs: ::fayalite::expr::Valueless<Self>,
__rhs: ::fayalite::expr::Valueless<Self>,
) -> ::fayalite::expr::Valueless<::fayalite::int::Bool> {
#valueless_eq_body
}
}
}
.to_tokens(tokens);
}
let variants_len = variants.len(); let variants_len = variants.len();
quote_spanned! {span=> quote_spanned! {span=>
#[automatically_derived] #[automatically_derived]
@ -888,6 +1151,7 @@ impl ToTokens for ParsedEnum {
#(#sim_value_from_opaque_match_arms)* #(#sim_value_from_opaque_match_arms)*
} }
} }
#[allow(irrefutable_let_patterns)]
fn sim_value_clone_from_opaque( fn sim_value_clone_from_opaque(
&self, &self,
value: &mut <Self as ::fayalite::ty::Type>::SimValue, value: &mut <Self as ::fayalite::ty::Type>::SimValue,
@ -933,6 +1197,14 @@ impl ToTokens for ParsedEnum {
} }
} }
#[automatically_derived] #[automatically_derived]
impl #impl_generics ::fayalite::__std::fmt::Debug for #sim_value_ident #type_generics
#where_clause
{
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
<#target #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f)
}
}
#[automatically_derived]
impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#target #type_generics> impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#target #type_generics>
for #sim_value_ident #type_generics for #sim_value_ident #type_generics
#where_clause #where_clause

View file

@ -215,6 +215,8 @@ impl ParsedTypeAlias {
no_runtime_generics, no_runtime_generics,
cmp_eq, cmp_eq,
get: _, get: _,
ref custom_debug,
custom_sim_display,
} = options.body; } = options.body;
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");
@ -234,6 +236,15 @@ impl ParsedTypeAlias {
if let Some((cmp_eq,)) = cmp_eq { if let Some((cmp_eq,)) = cmp_eq {
errors.error(cmp_eq, "cmp_eq is not valid on type aliases"); errors.error(cmp_eq, "cmp_eq is not valid on type aliases");
} }
if let Some((custom_debug, _, _)) = custom_debug {
errors.error(custom_debug, "custom_debug is not valid on type aliases");
}
if let Some((custom_sim_display,)) = custom_sim_display {
errors.error(
custom_sim_display,
"custom_sim_display is not valid on type aliases",
);
}
if let Some((custom_bounds,)) = custom_bounds { if let Some((custom_bounds,)) = custom_bounds {
errors.error( errors.error(
custom_bounds, custom_bounds,
@ -287,6 +298,8 @@ impl ParsedTypeAlias {
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq, cmp_eq,
ref mut get, ref mut get,
ref custom_debug,
custom_sim_display,
} = options.body; } = options.body;
if let Some(get) = get.take() { if let Some(get) = get.take() {
return Self::parse_phantom_const_accessor( return Self::parse_phantom_const_accessor(
@ -311,6 +324,15 @@ impl ParsedTypeAlias {
if let Some((cmp_eq,)) = cmp_eq { if let Some((cmp_eq,)) = cmp_eq {
errors.error(cmp_eq, "cmp_eq is not valid on type aliases"); errors.error(cmp_eq, "cmp_eq is not valid on type aliases");
} }
if let Some((custom_debug, _, _)) = custom_debug {
errors.error(custom_debug, "custom_debug is not valid on type aliases");
}
if let Some((custom_sim_display,)) = custom_sim_display {
errors.error(
custom_sim_display,
"custom_sim_display is not valid on type aliases",
);
}
let generics = if custom_bounds.is_some() { let generics = if custom_bounds.is_some() {
MaybeParsed::Unrecognized(generics) MaybeParsed::Unrecognized(generics)
} else if let Some(generics) = errors.ok(ParsedGenerics::parse(&mut generics)) { } else if let Some(generics) = errors.ok(ParsedGenerics::parse(&mut generics)) {
@ -356,6 +378,8 @@ impl ToTokens for ParsedTypeAlias {
no_runtime_generics, no_runtime_generics,
cmp_eq: _, cmp_eq: _,
get: _, get: _,
custom_debug: _,
custom_sim_display: _,
} = &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();
@ -402,6 +426,8 @@ impl ToTokens for ParsedTypeAlias {
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq: _, cmp_eq: _,
get: _, get: _,
custom_debug: _,
custom_sim_display: _,
} = &options.body; } = &options.body;
let span = ident.span(); let span = ident.span();
let mut type_attrs = attrs.clone(); let mut type_attrs = attrs.clone();
@ -427,7 +453,7 @@ impl ToTokens for ParsedTypeAlias {
format_ident!("__{}__GenericsAccumulation", ident); format_ident!("__{}__GenericsAccumulation", ident);
ItemStruct { ItemStruct {
attrs: vec![ attrs: vec![
common_derives(span), common_derives(span, true),
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
}, },

View file

@ -7,10 +7,10 @@ use std::{collections::HashMap, fmt, mem};
use syn::{ 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, FnArg, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index,
Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound, Turbofish, ItemStruct, Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound,
Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath, TypeTuple, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath,
Visibility, WhereClause, WherePredicate, TypeTuple, 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},
@ -18,6 +18,17 @@ use syn::{
token::{Brace, Bracket, Paren}, token::{Brace, Bracket, Paren},
}; };
crate::options! {
#[options = CustomDebugOptions]
#[no_ident_fragment]
pub(crate) enum CustomDebugOption {
Type(type_),
Sim(sim),
MaskType(mask_type),
MaskSim(mask_sim),
}
}
crate::options! { crate::options! {
#[options = ItemOptions] #[options = ItemOptions]
pub(crate) enum ItemOption { pub(crate) enum ItemOption {
@ -28,6 +39,8 @@ crate::options! {
NoRuntimeGenerics(no_runtime_generics), NoRuntimeGenerics(no_runtime_generics),
CmpEq(cmp_eq), CmpEq(cmp_eq),
Get(get, Expr), Get(get, Expr),
CustomDebug(custom_debug, CustomDebugOptions),
CustomSimDisplay(custom_sim_display),
} }
} }
@ -41,8 +54,36 @@ impl ItemOptions {
{ {
self.no_static = Some((kw::no_static(custom_bounds.span),)); self.no_static = Some((kw::no_static(custom_bounds.span),));
} }
if let Some((kw, _, custom_debug)) = &mut self.custom_debug {
if let CustomDebugOptions {
type_: None,
sim: None,
mask_type: None,
mask_sim: None,
} = custom_debug
{
*custom_debug = CustomDebugOptions {
type_: Some((kw::type_(kw.span),)),
sim: Some((kw::sim(kw.span),)),
mask_type: None,
mask_sim: None,
};
}
}
Ok(()) Ok(())
} }
pub(crate) fn custom_debug(&self) -> &CustomDebugOptions {
self.custom_debug.as_ref().map(|v| &v.2).unwrap_or(
const {
&CustomDebugOptions {
type_: None,
sim: None,
mask_type: None,
mask_sim: None,
}
},
)
}
} }
pub(crate) struct WrappedInConst<'a> { pub(crate) struct WrappedInConst<'a> {
@ -84,10 +125,17 @@ pub(crate) fn get_target(target: &Option<(kw::target, Paren, Path)>, item_ident:
} }
} }
pub(crate) fn common_derives(span: Span) -> Attribute { pub(crate) fn common_derives(span: Span, include_debug: bool) -> Attribute {
let debug = include_debug
.then(|| {
quote_spanned! {span=>
::fayalite::__std::fmt::Debug
}
})
.into_iter();
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[::fayalite::__std::prelude::v1::derive( #[::fayalite::__std::prelude::v1::derive(
::fayalite::__std::fmt::Debug, #(#debug,)*
::fayalite::__std::cmp::Eq, ::fayalite::__std::cmp::Eq,
::fayalite::__std::cmp::PartialEq, ::fayalite::__std::cmp::PartialEq,
::fayalite::__std::hash::Hash, ::fayalite::__std::hash::Hash,
@ -2975,7 +3023,7 @@ impl ParsedGenerics {
let span = ident.span(); let span = ident.span();
ItemStruct { ItemStruct {
attrs: vec![ attrs: vec![
common_derives(span), common_derives(span, true),
parse_quote_spanned! {span=> parse_quote_spanned! {span=>
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
}, },
@ -4733,3 +4781,109 @@ impl ParsedVisibility {
.map(|ord| if ord.is_lt() { self } else { other }) .map(|ord| if ord.is_lt() { self } else { other })
} }
} }
pub(crate) struct CustomDebugTrait<'a> {
pub(crate) trait_path: &'a Path,
pub(crate) fn_name: &'a Ident,
pub(crate) this_arg: &'a FnArg,
}
#[must_use]
pub(crate) fn create_struct_debug_impl(
item_struct: &ItemStruct,
debug_struct_name: &str,
custom_debug_trait: Option<CustomDebugTrait<'_>>,
) -> TokenStream {
let ident = &item_struct.ident;
let span = ident.span();
let (impl_generics, type_generics, where_clause) = item_struct.generics.split_for_impl();
let trait_path;
let fn_name;
let this_arg;
let CustomDebugTrait {
trait_path,
fn_name,
this_arg,
} = match custom_debug_trait {
Some(v) => v,
None => {
trait_path = parse_quote_spanned! {span=>
::fayalite::__std::fmt::Debug
};
fn_name = parse_quote_spanned! {span=>
fmt
};
this_arg = parse_quote_spanned! {span=>
&self
};
CustomDebugTrait {
trait_path: &trait_path,
fn_name: &fn_name,
this_arg: &this_arg,
}
}
};
let this_arg_name = match this_arg {
FnArg::Receiver(this_arg) => this_arg.self_token.to_token_stream(),
FnArg::Typed(this_arg) => match &*this_arg.pat {
syn::Pat::Ident(pat_ident) => pat_ident.ident.to_token_stream(),
_ => unreachable!(),
},
};
match &item_struct.fields {
Fields::Named(fields) => {
let field_idents = fields
.named
.iter()
.map(|v| v.ident.as_ref().expect("known to have field name"));
let field_names = field_idents.clone().map(|v| v.to_string());
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics #trait_path for #ident #type_generics
#where_clause
{
fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
let _ = #this_arg_name;
f.debug_struct(#debug_struct_name)
#(.field(#field_names, &#this_arg_name.#field_idents))*
.finish()
}
}
}
}
Fields::Unnamed(fields) => {
let field_members = fields
.unnamed
.iter()
.enumerate()
.map(|(index, _)| syn::Index {
index: index as _,
span,
});
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics #trait_path for #ident #type_generics
#where_clause
{
fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
let _ = #this_arg_name;
f.debug_tuple(#debug_struct_name)
#(.field(&#this_arg_name.#field_members))*
.finish()
}
}
}
}
Fields::Unit => quote_spanned! {ident.span()=>
#[automatically_derived]
impl #impl_generics #trait_path for #ident #type_generics
#where_clause
{
fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
let _ = #this_arg_name;
f.write_str(#debug_struct_name)
}
}
},
}
}

View file

@ -42,6 +42,7 @@ pub(crate) trait CustomToken:
mod kw { mod kw {
pub(crate) use syn::token::Extern as extern_; pub(crate) use syn::token::Extern as extern_;
pub(crate) use syn::token::Type as type_;
macro_rules! custom_keyword { macro_rules! custom_keyword {
($kw:ident) => { ($kw:ident) => {
@ -75,6 +76,8 @@ mod kw {
custom_keyword!(cmp_eq); custom_keyword!(cmp_eq);
custom_keyword!(connect_inexact); custom_keyword!(connect_inexact);
custom_keyword!(custom_bounds); custom_keyword!(custom_bounds);
custom_keyword!(custom_debug);
custom_keyword!(custom_sim_display);
custom_keyword!(flip); custom_keyword!(flip);
custom_keyword!(get); custom_keyword!(get);
custom_keyword!(hdl); custom_keyword!(hdl);
@ -83,6 +86,8 @@ mod kw {
custom_keyword!(input); custom_keyword!(input);
custom_keyword!(instance); custom_keyword!(instance);
custom_keyword!(m); custom_keyword!(m);
custom_keyword!(mask_sim);
custom_keyword!(mask_type);
custom_keyword!(memory); custom_keyword!(memory);
custom_keyword!(memory_array); custom_keyword!(memory_array);
custom_keyword!(memory_with_init); custom_keyword!(memory_with_init);

View file

@ -1096,11 +1096,9 @@ impl Visitor<'_> {
let (#(#bindings,)*) = { let (#(#bindings,)*) = {
type __MatchTy<T> = <T as ::fayalite::ty::Type>::SimValue; type __MatchTy<T> = <T as ::fayalite::ty::Type>::SimValue;
let __match_value = #expr; let __match_value = #expr;
let __match_value = { // use method syntax to deduce what type to convert to
use ::fayalite::sim::value::match_sim_value::*; let __match_value = ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value)
// use method syntax to deduce the correct trait to call .__fayalite_match_sim_value();
::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value).__fayalite_match_sim_value()
};
#let_token #pat #eq_token __match_value #semi_token #let_token #pat #eq_token __match_value #semi_token
(#(#bindings_idents,)*) (#(#bindings_idents,)*)
}; };
@ -1172,11 +1170,9 @@ impl Visitor<'_> {
{ {
type __MatchTy<T> = <T as ::fayalite::ty::Type>::SimValue; type __MatchTy<T> = <T as ::fayalite::ty::Type>::SimValue;
let __match_value = #expr; let __match_value = #expr;
let __match_value = { // use method syntax to deduce what type to convert to
use ::fayalite::sim::value::match_sim_value::*; let __match_value = ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value)
// use method syntax to deduce the correct trait to call .__fayalite_match_sim_value();
::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value).__fayalite_match_sim_value()
};
#match_token __match_value { #match_token __match_value {
#(#arms)* #(#arms)*
} }

View file

@ -26,10 +26,12 @@ hashbrown.workspace = true
jobslot.workspace = true jobslot.workspace = true
num-bigint.workspace = true num-bigint.workspace = true
num-traits.workspace = true num-traits.workspace = true
once_cell.workspace = true
ordered-float.workspace = true ordered-float.workspace = true
petgraph.workspace = true petgraph.workspace = true
serde_json.workspace = true serde_json.workspace = true
serde.workspace = true serde.workspace = true
sha2.workspace = true
tempfile.workspace = true tempfile.workspace = true
vec_map.workspace = true vec_map.workspace = true
which.workspace = true which.workspace = true

View file

@ -95,7 +95,23 @@
//! } //! }
//! //!
//! #[hdl] //! #[hdl]
//! fn destructure_to_sim_value<'a, T: Type>(v: impl ToSimValue<Type = MyStruct<T>>) { //! fn destructure_inner<T: Type>(v: <MyStruct<T> as Type>::SimValue) {
//! #[hdl(sim)]
//! let MyStruct::<T> {
//! a,
//! mut b,
//! c,
//! } = v;
//!
//! // that gives these types:
//! let _: SimValue<UInt<8>> = a;
//! let _: SimValue<Bool> = b;
//! let _: SimValue<T> = c;
//! *b = false; // can modify b since mut was used
//! }
//!
//! #[hdl]
//! fn destructure_inner_ref<'a, T: Type>(v: &'a <MyStruct<T> as Type>::SimValue) {
//! #[hdl(sim)] //! #[hdl(sim)]
//! let MyStruct::<T> { //! let MyStruct::<T> {
//! a, //! a,
@ -104,8 +120,25 @@
//! } = v; //! } = v;
//! //!
//! // that gives these types: //! // that gives these types:
//! let _: SimValue<UInt<8>> = a; //! let _: &'a SimValue<UInt<8>> = a;
//! let _: SimValue<Bool> = b; //! let _: &'a SimValue<Bool> = b;
//! let _: SimValue<T> = c; //! let _: &'a SimValue<T> = c;
//! }
//!
//! #[hdl]
//! fn destructure_inner_mut<'a, T: Type>(v: &'a mut <MyStruct<T> as Type>::SimValue) {
//! #[hdl(sim)]
//! let MyStruct::<T> {
//! a,
//! b,
//! c,
//! } = v;
//!
//! **b = true; // you can modify v by modifying b which borrows from it
//!
//! // that gives these types:
//! let _: &'a mut SimValue<UInt<8>> = a;
//! let _: &'a mut SimValue<Bool> = b;
//! let _: &'a mut SimValue<T> = c;
//! } //! }
//! ``` //! ```

View file

@ -72,15 +72,47 @@
//! } //! }
//! //!
//! #[hdl] //! #[hdl]
//! fn match_to_sim_value<'a, T: Type>(v: impl ToSimValue<Type = MyEnum<T>>) { //! fn match_inner_move<T: Type>(v: <MyEnum<T> as Type>::SimValue) -> String {
//! #[hdl(sim)] //! #[hdl(sim)]
//! match v { //! match v {
//! MyEnum::<T>::A => println!("got A"), //! MyEnum::<T>::A => String::from("got A"),
//! MyEnum::<T>::B(b) => { //! MyEnum::<T>::B(mut b) => {
//! let _: SimValue<Bool> = b; // b has this type //! let _: SimValue<Bool> = b; // b has this type
//! println!("got B({b})"); //! let text = format!("got B({b})");
//! *b = true; // can modify b since mut was used
//! text
//! } //! }
//! _ => println!("something else"), //! _ => String::from("something else"),
//! }
//! }
//!
//! #[hdl]
//! fn match_inner_ref<'a, T: Type>(v: &'a <MyEnum<T> as Type>::SimValue) -> u32 {
//! #[hdl(sim)]
//! match v {
//! MyEnum::<T>::A => 1,
//! MyEnum::<T>::B(b) => {
//! let _: &'a SimValue<Bool> = b; // b has this type
//! println!("got B({b})");
//! 5
//! }
//! _ => 42,
//! }
//! }
//!
//! #[hdl]
//! fn match_inner_mut<'a, T: Type>(v: &'a mut <MyEnum<T> as Type>::SimValue) -> Option<&'a mut SimValue<T>> {
//! #[hdl(sim)]
//! match v {
//! MyEnum::<T>::A => None,
//! MyEnum::<T>::B(b) => {
//! println!("got B({b})");
//! **b = true; // you can modify v by modifying b which borrows from it
//! let _: &'a mut SimValue<Bool> = b; // b has this type
//! None
//! }
//! MyEnum::<T>::C(v) => Some(v), // you can return matched values
//! _ => None, // HDL enums can have invalid discriminants, so we need this extra match arm
//! } //! }
//! } //! }
//! ``` //! ```

View file

@ -13,13 +13,13 @@ use crate::{
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, MatchVariantWithoutScope, OpaqueSimValueSlice, OpaqueSimValueWriter, CanonicalType, MatchVariantWithoutScope, OpaqueSimValueSlice, OpaqueSimValueWriter,
OpaqueSimValueWritten, StaticType, Type, TypeProperties, TypeWithDeref, OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties, TypeWithDeref,
serde_impls::SerdeCanonicalType, serde_impls::SerdeCanonicalType,
}, },
util::ConstUsize, util::ConstUsize,
}; };
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error}; use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
use std::{borrow::Cow, iter::FusedIterator, ops::Index}; use std::{borrow::Cow, fmt, iter::FusedIterator, ops::Index};
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ArrayType<T: Type = CanonicalType, Len: Size = DynSize> { pub struct ArrayType<T: Type = CanonicalType, Len: Size = DynSize> {
@ -28,8 +28,8 @@ pub struct ArrayType<T: Type = CanonicalType, Len: Size = DynSize> {
type_properties: TypeProperties, type_properties: TypeProperties,
} }
impl<T: Type, Len: Size> std::fmt::Debug for ArrayType<T, Len> { impl<T: Type, Len: Size> fmt::Debug for ArrayType<T, Len> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Array<{:?}, {}>", self.element, self.len()) write!(f, "Array<{:?}, {}>", self.element, self.len())
} }
} }
@ -109,14 +109,42 @@ impl<T: StaticType, Len: KnownSize> Default for ArrayType<T, Len> {
} }
} }
struct MakeType<T: StaticType>(Interned<T>);
impl<T: StaticType> From<MakeType<T>> for Interned<T> {
fn from(value: MakeType<T>) -> Self {
value.0
}
}
impl<T: StaticType> Default for MakeType<T> {
fn default() -> Self {
Self(T::TYPE.intern_sized())
}
}
struct MakeMaskType<T: StaticType>(Interned<T::MaskType>);
impl<T: StaticType> From<MakeMaskType<T>> for Interned<T::MaskType> {
fn from(value: MakeMaskType<T>) -> Self {
value.0
}
}
impl<T: StaticType> Default for MakeMaskType<T> {
fn default() -> Self {
Self(T::MASK_TYPE.intern_sized())
}
}
impl<T: StaticType, Len: KnownSize> StaticType for ArrayType<T, Len> { impl<T: StaticType, Len: KnownSize> StaticType for ArrayType<T, Len> {
const TYPE: Self = Self { const TYPE: Self = Self {
element: LazyInterned::new_lazy(&|| T::TYPE.intern_sized()), element: LazyInterned::new_const::<MakeType<T>>(),
len: Len::SIZE, len: Len::SIZE,
type_properties: Self::TYPE_PROPERTIES, type_properties: Self::TYPE_PROPERTIES,
}; };
const MASK_TYPE: Self::MaskType = ArrayType::<T::MaskType, Len> { const MASK_TYPE: Self::MaskType = ArrayType::<T::MaskType, Len> {
element: LazyInterned::new_lazy(&|| T::MASK_TYPE.intern_sized()), element: LazyInterned::new_const::<MakeMaskType<T>>(),
len: Len::SIZE, len: Len::SIZE,
type_properties: Self::MASK_TYPE_PROPERTIES, type_properties: Self::MASK_TYPE_PROPERTIES,
}; };
@ -154,6 +182,15 @@ impl<T: Type + Visit<State>, Len: Size, State: Visitor + ?Sized> Visit<State>
} }
} }
impl<T: Type, Len: Size> SimValueDebug for ArrayType<T, Len> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<T: Type, Len: Size> Type for ArrayType<T, Len> { impl<T: Type, Len: Size> Type for ArrayType<T, Len> {
type BaseType = Array; type BaseType = Array;
type MaskType = ArrayType<T::MaskType, Len>; type MaskType = ArrayType<T::MaskType, Len>;

View file

@ -14,8 +14,8 @@ use crate::{
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, MatchVariantWithoutScope, OpaqueSimValue, OpaqueSimValueSize, CanonicalType, MatchVariantWithoutScope, OpaqueSimValue, OpaqueSimValueSize,
OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug,
TypeProperties, TypeWithDeref, impl_match_variant_as_self, StaticType, Type, TypeProperties, TypeWithDeref, impl_match_variant_as_self,
}, },
util::HashMap, util::HashMap,
}; };
@ -271,6 +271,15 @@ impl Type for Bundle {
} }
} }
impl SimValueDebug for Bundle {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
pub trait BundleType: Type<BaseType = Bundle> { pub trait BundleType: Type<BaseType = Bundle> {
type Builder: Default; type Builder: Default;
fn fields(&self) -> Interned<[BundleField]>; fn fields(&self) -> Interned<[BundleField]>;
@ -471,6 +480,14 @@ macro_rules! impl_tuples {
#[var($var)] #[var($var)]
})*] })*]
} }
impl<$($T: Type,)*> SimValueDebug for ($($T,)*) {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<$($T: Type,)*> Type for ($($T,)*) { impl<$($T: Type,)*> Type for ($($T,)*) {
type BaseType = Bundle; type BaseType = Bundle;
type MaskType = ($($T::MaskType,)*); type MaskType = ($($T::MaskType,)*);
@ -773,6 +790,15 @@ impl_tuples! {
] ]
} }
impl<T: ?Sized + Send + Sync + 'static> SimValueDebug for PhantomData<T> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> { impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
type BaseType = Bundle; type BaseType = Bundle;
type MaskType = (); type MaskType = ();

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
expr::{Expr, ValueType}, expr::{Expr, ValueType},
hdl, hdl,
@ -9,10 +10,12 @@ use crate::{
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter, CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter,
OpaqueSimValueWritten, StaticType, Type, TypeProperties, impl_match_variant_as_self, OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties,
impl_match_variant_as_self,
}, },
}; };
use bitvec::{bits, order::Lsb0}; use bitvec::{bits, order::Lsb0};
use std::fmt;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct Clock; pub struct Clock;
@ -69,6 +72,15 @@ impl Type for Clock {
} }
} }
impl SimValueDebug for Clock {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl Clock { impl Clock {
pub fn type_properties(self) -> TypeProperties { pub fn type_properties(self) -> TypeProperties {
Self::TYPE_PROPERTIES Self::TYPE_PROPERTIES

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
expr::{Expr, HdlPartialEq, HdlPartialEqImpl, ToExpr, ValueType, ops::VariantAccess}, expr::{Expr, ToExpr, ValueType, ops::VariantAccess},
hdl, hdl,
int::{Bool, UIntValue}, int::{Bool, UIntValue},
intern::{Intern, Interned}, intern::{Intern, Interned},
@ -10,18 +10,18 @@ use crate::{
EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope, connect, EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope, connect,
enum_match_variants_helper, incomplete_wire, wire, enum_match_variants_helper, incomplete_wire, wire,
}, },
sim::value::SimValue, sim::value::{SimValue, ToSimValue, ToSimValueWithType},
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, OpaqueSimValueSize, CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, OpaqueSimValueSize,
OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug,
TypeProperties, StaticType, Type, TypeProperties,
}, },
util::HashMap, util::HashMap,
}; };
use bitvec::{order::Lsb0, slice::BitSlice, view::BitView}; use bitvec::{order::Lsb0, slice::BitSlice, view::BitView};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{borrow::Cow, convert::Infallible, fmt, iter::FusedIterator, sync::Arc}; use std::{convert::Infallible, fmt, iter::FusedIterator, sync::Arc};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct EnumVariant { pub struct EnumVariant {
@ -410,6 +410,15 @@ impl Type for Enum {
} }
} }
impl SimValueDebug for Enum {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)] #[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
pub struct EnumPaddingSimValue { pub struct EnumPaddingSimValue {
bits: Option<UIntValue>, bits: Option<UIntValue>,
@ -723,95 +732,12 @@ pub fn enum_type_to_sim_builder<T: EnumType>(v: T) -> T::SimBuilder {
v.into() v.into()
} }
#[hdl] #[hdl(cmp_eq)]
pub enum HdlOption<T: Type> { pub enum HdlOption<T: Type> {
HdlNone, HdlNone,
HdlSome(T), HdlSome(T),
} }
impl<Lhs: Type + HdlPartialEqImpl<Rhs>, Rhs: Type> HdlPartialEqImpl<HdlOption<Rhs>>
for HdlOption<Lhs>
{
fn cmp_value_eq(
lhs: Self,
lhs_value: Cow<'_, Self::SimValue>,
rhs: HdlOption<Rhs>,
rhs_value: Cow<'_, <HdlOption<Rhs> as Type>::SimValue>,
) -> bool {
type SimValueMatch<T> = <T as Type>::SimValue;
match (&*lhs_value, &*rhs_value) {
(SimValueMatch::<Self>::HdlNone(_), SimValueMatch::<HdlOption<Rhs>>::HdlNone(_)) => {
true
}
(SimValueMatch::<Self>::HdlSome(..), SimValueMatch::<HdlOption<Rhs>>::HdlNone(_))
| (SimValueMatch::<Self>::HdlNone(_), SimValueMatch::<HdlOption<Rhs>>::HdlSome(..)) => {
false
}
(
SimValueMatch::<Self>::HdlSome(l, _),
SimValueMatch::<HdlOption<Rhs>>::HdlSome(r, _),
) => HdlPartialEqImpl::cmp_value_eq(
lhs.HdlSome,
Cow::Borrowed(&**l),
rhs.HdlSome,
Cow::Borrowed(&**r),
),
}
}
#[hdl]
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<HdlOption<Rhs>>) -> Expr<Bool> {
#[hdl]
let cmp_eq = wire();
#[hdl]
match lhs {
HdlSome(lhs) =>
{
#[hdl]
match rhs {
HdlSome(rhs) => connect(cmp_eq, lhs.cmp_eq(rhs)),
HdlNone => connect(cmp_eq, false),
}
}
HdlNone =>
{
#[hdl]
match rhs {
HdlSome(_) => connect(cmp_eq, false),
HdlNone => connect(cmp_eq, true),
}
}
}
cmp_eq
}
#[hdl]
fn cmp_expr_ne(lhs: Expr<Self>, rhs: Expr<HdlOption<Rhs>>) -> Expr<Bool> {
#[hdl]
let cmp_ne = wire();
#[hdl]
match lhs {
HdlSome(lhs) =>
{
#[hdl]
match rhs {
HdlSome(rhs) => connect(cmp_ne, lhs.cmp_ne(rhs)),
HdlNone => connect(cmp_ne, true),
}
}
HdlNone =>
{
#[hdl]
match rhs {
HdlSome(_) => connect(cmp_ne, true),
HdlNone => connect(cmp_ne, false),
}
}
}
cmp_ne
}
}
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn HdlNone<T: StaticType>() -> Expr<HdlOption<T>> { pub fn HdlNone<T: StaticType>() -> Expr<HdlOption<T>> {
HdlOption[T::TYPE].HdlNone() HdlOption[T::TYPE].HdlNone()
@ -823,6 +749,123 @@ pub fn HdlSome<T: Type>(value: impl ToExpr<Type = T>) -> Expr<HdlOption<T>> {
HdlOption[value.ty()].HdlSome(value) HdlOption[value.ty()].HdlSome(value)
} }
impl<T: Type> From<SimValue<HdlOption<T>>> for Option<SimValue<T>> {
#[hdl]
fn from(value: SimValue<HdlOption<T>>) -> Self {
#[hdl(sim)]
match value {
HdlSome(v) => Some(v),
HdlNone => None,
}
}
}
impl<'a, T: Type> From<&'a SimValue<HdlOption<T>>> for Option<&'a SimValue<T>> {
#[hdl]
fn from(value: &'a SimValue<HdlOption<T>>) -> Self {
#[hdl(sim)]
match value {
HdlSome(v) => Some(v),
HdlNone => None,
}
}
}
impl<'a, T: Type> From<&'a mut SimValue<HdlOption<T>>> for Option<&'a mut SimValue<T>> {
#[hdl]
fn from(value: &'a mut SimValue<HdlOption<T>>) -> Self {
#[hdl(sim)]
match value {
HdlSome(v) => Some(v),
HdlNone => None,
}
}
}
impl<T: ValueType<Type: StaticType<MaskType: StaticType>>> ValueType for Option<T> {
type Type = HdlOption<T::Type>;
type ValueCategory = T::ValueCategory;
fn ty(&self) -> Self::Type {
StaticType::TYPE
}
}
impl<T: Type, V: ToSimValueWithType<T>> ToSimValueWithType<HdlOption<T>> for Option<V> {
#[hdl]
fn to_sim_value_with_type(&self, ty: HdlOption<T>) -> SimValue<HdlOption<T>> {
match self {
Some(v) =>
{
#[hdl(sim)]
ty.HdlSome(v)
}
None =>
{
#[hdl(sim)]
ty.HdlNone()
}
}
}
#[hdl]
fn into_sim_value_with_type(self, ty: HdlOption<T>) -> SimValue<HdlOption<T>> {
match self {
Some(v) =>
{
#[hdl(sim)]
ty.HdlSome(v)
}
None =>
{
#[hdl(sim)]
ty.HdlNone()
}
}
}
}
impl<T: ToSimValue<Type: StaticType<MaskType: StaticType>>> ToSimValue for Option<T> {
#[hdl]
fn to_sim_value(&self) -> SimValue<Self::Type> {
match self {
Some(v) =>
{
#[hdl(sim)]
HdlSome(v)
}
None =>
{
#[hdl(sim)]
HdlNone()
}
}
}
#[hdl]
fn into_sim_value(self) -> SimValue<Self::Type> {
match self {
Some(v) =>
{
#[hdl(sim)]
HdlSome(v)
}
None =>
{
#[hdl(sim)]
HdlNone()
}
}
}
}
impl<T: ToExpr<Type: StaticType<MaskType: StaticType>>> ToExpr for Option<T> {
fn to_expr(&self) -> Expr<Self::Type> {
match self {
Some(v) => HdlSome(v),
None => HdlNone(),
}
}
}
impl<T: Type> HdlOption<T> { impl<T: Type> HdlOption<T> {
#[track_caller] #[track_caller]
pub fn try_map<R: Type, E>( pub fn try_map<R: Type, E>(

View file

@ -579,6 +579,8 @@ macro_rules! make_impls {
(#[kind(i64)] $($rest:tt)*) => {make_impls! { #[type([][] (i64))] $($rest)* }}; (#[kind(i64)] $($rest:tt)*) => {make_impls! { #[type([][] (i64))] $($rest)* }};
(#[kind(i128)] $($rest:tt)*) => {make_impls! { #[type([][] (i128))] $($rest)* }}; (#[kind(i128)] $($rest:tt)*) => {make_impls! { #[type([][] (i128))] $($rest)* }};
} }
#[cfg(test)]
pub(crate) use make_impls; pub(crate) use make_impls;
#[cfg(test)] #[cfg(test)]

View file

@ -10,13 +10,13 @@ use crate::{
value_category::ValueCategoryValue, value_category::ValueCategoryValue,
}, },
hdl, hdl,
intern::{Intern, Interned, Memoize}, intern::{Intern, Interned, Memoize, OnceInterned},
sim::value::{SimValue, ToSimValueWithType}, sim::value::{SimValue, ToSimValueWithType},
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, FillInDefaultedGenerics, OpaqueSimValueSize, OpaqueSimValueSlice, CanonicalType, FillInDefaultedGenerics, OpaqueSimValueSize, OpaqueSimValueSlice,
OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type, TypeProperties, OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug, SimValueDisplay, StaticType,
impl_match_variant_as_self, Type, TypeProperties, impl_match_variant_as_self,
}, },
util::{ConstBool, ConstUsize, GenericConstBool, GenericConstUsize, interned_bit, slice_range}, util::{ConstBool, ConstUsize, GenericConstBool, GenericConstUsize, interned_bit, slice_range},
}; };
@ -65,14 +65,21 @@ pub type DynSize = ConstUsize<DYN_SIZE>;
trait KnownSizeBaseSealed {} trait KnownSizeBaseSealed {}
impl<const N: usize> KnownSizeBaseSealed for [(); N] {} impl<const N: usize> KnownSizeBaseSealed for ConstUsize<N> {}
#[expect(private_bounds)] #[expect(private_bounds)]
pub trait KnownSizeBase: KnownSizeBaseSealed {} pub trait KnownSizeBase: KnownSizeBaseSealed + GetInternedIntCaches {}
macro_rules! impl_known_size_base { macro_rules! impl_known_size_base {
($($size:literal),* $(,)?) => { ($($size:literal),* $(,)?) => {
$(impl KnownSizeBase for [(); $size] {})* $(impl KnownSizeBase for ConstUsize<$size> {})*
$(impl GetInternedIntCaches for ConstUsize<$size> {
#[inline(always)]
fn get_interned_int_caches() -> &'static InternedIntCaches<Self> {
static CACHES: InternedIntCaches<ConstUsize<$size>> = InternedIntCaches::new();
&CACHES
}
})*
}; };
} }
@ -113,12 +120,34 @@ impl_known_size_base! {
0x200, 0x200,
} }
trait GetInternedIntCaches {
fn get_interned_int_caches() -> &'static InternedIntCaches<Self>
where
Self: KnownSize;
}
struct InternedIntCaches<Width: KnownSize> {
uint: OnceInterned<UIntType<Width>>,
sint: OnceInterned<SIntType<Width>>,
}
impl<Width: KnownSize> InternedIntCaches<Width> {
const fn new() -> Self {
Self {
uint: OnceInterned::new(),
sint: OnceInterned::new(),
}
}
}
#[expect(private_bounds)]
pub trait KnownSize: pub trait KnownSize:
GenericConstUsize GenericConstUsize
+ sealed::SizeTypeSealed + sealed::SizeTypeSealed
+ sealed::SizeSealed + sealed::SizeSealed
+ Default + Default
+ FillInDefaultedGenerics<Type = Self> + FillInDefaultedGenerics<Type = Self>
+ GetInternedIntCaches
{ {
const SIZE: Self; const SIZE: Self;
type ArrayMatch<Element: Type>: AsRef<[Expr<Element>]> type ArrayMatch<Element: Type>: AsRef<[Expr<Element>]>
@ -148,7 +177,7 @@ pub trait KnownSize:
impl<const N: usize> KnownSize for ConstUsize<N> impl<const N: usize> KnownSize for ConstUsize<N>
where where
[(); N]: KnownSizeBase, ConstUsize<N>: KnownSizeBase,
{ {
const SIZE: Self = Self; const SIZE: Self = Self;
type ArrayMatch<Element: Type> = [Expr<Element>; N]; type ArrayMatch<Element: Type> = [Expr<Element>; N];
@ -221,6 +250,10 @@ pub trait Size:
fn from_usize(v: usize) -> Self::SizeType { fn from_usize(v: usize) -> Self::SizeType {
Self::try_from_usize(v).expect("wrong size") Self::try_from_usize(v).expect("wrong size")
} }
#[doc(hidden)]
fn interned_uint(size_type: Self::SizeType) -> Interned<UIntType<Self>>;
#[doc(hidden)]
fn interned_sint(size_type: Self::SizeType) -> Interned<SIntType<Self>>;
} }
impl sealed::SizeTypeSealed for usize {} impl sealed::SizeTypeSealed for usize {}
@ -229,6 +262,8 @@ impl SizeType for usize {
type Size = DynSize; type Size = DynSize;
} }
const MAX_CACHED_INT_WIDTH: usize = 1 << 10;
impl Size for DynSize { impl Size for DynSize {
type ArrayMatch<Element: Type> = Box<[Expr<Element>]>; type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
type ArraySimValue<Element: Type> = Box<[SimValue<Element>]>; type ArraySimValue<Element: Type> = Box<[SimValue<Element>]>;
@ -242,6 +277,36 @@ impl Size for DynSize {
fn try_from_usize(v: usize) -> Option<Self::SizeType> { fn try_from_usize(v: usize) -> Option<Self::SizeType> {
Some(v) Some(v)
} }
#[doc(hidden)]
fn interned_uint(size_type: Self::SizeType) -> Interned<UIntType<Self>> {
static CACHED: [OnceInterned<UInt>; MAX_CACHED_INT_WIDTH] =
[const { OnceInterned::new() }; _];
#[cold]
fn intern_cold(width: usize) -> Interned<UInt> {
Intern::intern_sized(UInt::new(width))
}
if let Some(cached) = CACHED.get(size_type) {
cached.get_or_init(|| intern_cold(size_type))
} else {
intern_cold(size_type)
}
}
#[doc(hidden)]
fn interned_sint(size_type: Self::SizeType) -> Interned<SIntType<Self>> {
static CACHED: [OnceInterned<SInt>; MAX_CACHED_INT_WIDTH] =
[const { OnceInterned::new() }; _];
#[cold]
fn intern_cold(width: usize) -> Interned<SInt> {
Intern::intern_sized(SInt::new(width))
}
if let Some(cached) = CACHED.get(size_type) {
cached.get_or_init(|| intern_cold(size_type))
} else {
intern_cold(size_type)
}
}
} }
impl<const VALUE: usize> sealed::SizeSealed for ConstUsize<VALUE> {} impl<const VALUE: usize> sealed::SizeSealed for ConstUsize<VALUE> {}
@ -267,6 +332,20 @@ impl<T: KnownSize> Size for T {
fn try_from_usize(v: usize) -> Option<Self::SizeType> { fn try_from_usize(v: usize) -> Option<Self::SizeType> {
if v == T::VALUE { Some(T::SIZE) } else { None } if v == T::VALUE { Some(T::SIZE) } else { None }
} }
#[doc(hidden)]
fn interned_uint(_size_type: Self::SizeType) -> Interned<UIntType<Self>> {
T::get_interned_int_caches()
.uint
.get_or_init(|| UIntType::new_static().intern_sized())
}
#[doc(hidden)]
fn interned_sint(_size_type: Self::SizeType) -> Interned<SIntType<Self>> {
T::get_interned_int_caches()
.sint
.get_or_init(|| SIntType::new_static().intern_sized())
}
} }
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
@ -586,7 +665,7 @@ macro_rules! impl_valueless_op_forward {
} }
macro_rules! impl_int { macro_rules! impl_int {
($pretty_name:ident, $name:ident, $generic_name:ident, $value:ident, $SIGNED:literal) => { ($pretty_name:ident, $name:ident, $generic_name:ident, $value:ident, $SIGNED:literal, $interned_int:ident) => {
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[repr(transparent)] #[repr(transparent)]
pub struct $name<Width: Size = DynSize> { pub struct $name<Width: Size = DynSize> {
@ -940,6 +1019,24 @@ macro_rules! impl_int {
} }
} }
impl<Width: Size> SimValueDebug for $name<Width> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<Width: Size> SimValueDisplay for $name<Width> {
fn sim_value_display(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Display::fmt(value, f)
}
}
impl<Width: KnownSize> Default for $name<Width> { impl<Width: KnownSize> Default for $name<Width> {
fn default() -> Self { fn default() -> Self {
Self::TYPE Self::TYPE
@ -1003,7 +1100,7 @@ macro_rules! impl_int {
type Output = $name<Width::Size>; type Output = $name<Width::Size>;
fn index(&self, width: Width) -> &Self::Output { fn index(&self, width: Width) -> &Self::Output {
Interned::into_inner(Intern::intern_sized($name::new(width))) Interned::into_inner(Width::Size::$interned_int(width))
} }
} }
@ -1184,8 +1281,22 @@ macro_rules! impl_int {
}; };
} }
impl_int!(UInt, UIntType, UIntWithoutGenerics, UIntValue, false); impl_int!(
impl_int!(SInt, SIntType, SIntWithoutGenerics, SIntValue, true); UInt,
UIntType,
UIntWithoutGenerics,
UIntValue,
false,
interned_uint
);
impl_int!(
SInt,
SIntType,
SIntWithoutGenerics,
SIntValue,
true,
interned_sint
);
impl UInt { impl UInt {
/// gets the smallest `UInt` that fits `v` losslessly /// gets the smallest `UInt` that fits `v` losslessly
@ -1806,6 +1917,15 @@ impl Type for Bool {
} }
} }
impl SimValueDebug for Bool {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl StaticType for Bool { impl StaticType for Bool {
const TYPE: Self = Bool; const TYPE: Self = Bool;
const MASK_TYPE: Self::MaskType = Bool; const MASK_TYPE: Self::MaskType = Bool;

View file

@ -14,7 +14,7 @@ use crate::{
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten,
StaticType, Type, TypeProperties, impl_match_variant_as_self, SimValueDebug, StaticType, Type, TypeProperties, impl_match_variant_as_self,
}, },
}; };
use bitvec::{order::Lsb0, view::BitView}; use bitvec::{order::Lsb0, view::BitView};
@ -94,6 +94,15 @@ impl Type for UIntInRangeMaskType {
} }
} }
impl SimValueDebug for UIntInRangeMaskType {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl BundleType for UIntInRangeMaskType { impl BundleType for UIntInRangeMaskType {
type Builder = NoBuilder; type Builder = NoBuilder;
@ -339,6 +348,15 @@ macro_rules! define_uint_in_range_type {
} }
} }
impl<Start: Size, End: Size> SimValueDebug for $UIntInRangeType<Start, End> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<Start: Size, End: Size> fmt::Debug for $UIntInRangeType<Start, End> { impl<Start: Size, End: Size> fmt::Debug for $UIntInRangeType<Start, End> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { value, range } = self; let Self { value, range } = self;

View file

@ -4,68 +4,191 @@
use crate::{intern::type_map::TypeIdMap, util::DefaultBuildHasher}; use crate::{intern::type_map::TypeIdMap, util::DefaultBuildHasher};
use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec}; use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec};
use hashbrown::HashTable; use hashbrown::HashTable;
use once_cell::race::OnceRef;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
borrow::{Borrow, Cow}, borrow::{Borrow, Cow},
cell::RefCell,
cmp::Ordering, cmp::Ordering,
ffi::{OsStr, OsString}, ffi::{OsStr, OsString},
fmt, fmt,
hash::{BuildHasher, Hash, Hasher}, hash::{BuildHasher, Hash, Hasher},
iter::FusedIterator, iter::FusedIterator,
marker::PhantomData,
ops::Deref, ops::Deref,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{Mutex, RwLock}, sync::RwLock,
}; };
mod interner;
mod type_map; mod type_map;
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any { /// invariant: T must be zero-sized, `type_id` is unique for every possible T value.
fn get(&self) -> Interned<T>; struct LazyInternedLazyInner<T: ?Sized + 'static> {
type_id: TypeId,
value: T,
} }
impl<T: ?Sized + Send + Sync + 'static, F: ?Sized + Fn() -> Interned<T> + Send + Sync + Any> impl<T: ?Sized + 'static> Hash for LazyInternedLazyInner<T> {
LazyInternedTrait<T> for F fn hash<H: Hasher>(&self, state: &mut H) {
{ let Self { type_id, value: _ } = self;
fn get(&self) -> Interned<T> { type_id.hash(state);
self()
} }
} }
#[repr(transparent)] impl<T: ?Sized + 'static> PartialEq for LazyInternedLazyInner<T> {
pub struct LazyInternedFn<T: ?Sized + Send + Sync + 'static>(pub &'static dyn LazyInternedTrait<T>); fn eq(&self, other: &Self) -> bool {
let Self { type_id, value: _ } = self;
*type_id == other.type_id
}
}
impl<T: ?Sized + Send + Sync + 'static> Copy for LazyInternedFn<T> {} impl<T: ?Sized + 'static> Eq for LazyInternedLazyInner<T> {}
impl<T: ?Sized + Send + Sync + 'static> Clone for LazyInternedFn<T> { impl<T: ?Sized + 'static> fmt::Debug for LazyInternedLazyInner<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LazyInternedLazyInner")
.finish_non_exhaustive()
}
}
impl<T: ?Sized + 'static> LazyInternedLazyInner<T> {
const fn new(value: T) -> Self
where
T: Sized,
{
const { assert!(size_of::<T>() == 0) };
Self {
type_id: TypeId::of::<T>(),
value,
}
}
}
pub struct LazyInternedLazy<T: ?Sized + Send + Sync + 'static>(
&'static LazyInternedLazyInner<dyn Fn() -> Interned<T> + Send + Sync>,
);
impl<T: ?Sized + Send + Sync + 'static> LazyInternedLazy<T> {
pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
Self(&const { LazyInternedLazyInner::new(|| V::default().into()) })
}
pub const fn new_const_default() -> Self
where
Interned<T>: Default,
{
Self::new_const::<Interned<T>>()
}
pub fn interned(self) -> Interned<T> {
struct Map(hashbrown::HashTable<(TypeId, &'static (dyn Any + Send + Sync))>);
impl Map {
const EMPTY: Self = Self(hashbrown::HashTable::new());
fn get<T: ?Sized + Send + Sync + 'static>(
&self,
lazy_interned_lazy: LazyInternedLazy<T>,
hash: u64,
) -> Option<&'static Interned<T>> {
let &(_, v) = self.0.find(hash, |v| v.0 == lazy_interned_lazy.0.type_id)?;
let Some(retval) = v.downcast_ref::<Interned<T>>() else {
unreachable!();
};
Some(retval)
}
fn get_or_insert<T: ?Sized + Send + Sync + 'static>(
&mut self,
lazy_interned_lazy: LazyInternedLazy<T>,
hash: u64,
v: &'static Interned<T>,
) -> &'static Interned<T> {
let entry = self
.0
.entry(
hash,
|&(k, _)| k == lazy_interned_lazy.0.type_id,
|&(k, _)| type_map::TypeIdBuildHasher.hash_one(k),
)
.or_insert_with(|| (lazy_interned_lazy.0.type_id, v));
let &(_, v) = entry.get();
let Some(retval) = v.downcast_ref::<Interned<T>>() else {
unreachable!();
};
retval
}
}
static GLOBAL_CACHE: RwLock<Map> = RwLock::new(Map::EMPTY);
#[cold]
fn insert_in_thread_local_cache<T: ?Sized + Send + Sync + 'static>(
cache: &RefCell<Map>,
this: LazyInternedLazy<T>,
hash: u64,
) -> Interned<T> {
let read_lock = GLOBAL_CACHE.read().unwrap();
let v = read_lock.get(this, hash);
drop(read_lock);
let v = v.unwrap_or_else(|| {
let v = Box::leak(Box::new((this.0.value)()));
GLOBAL_CACHE.write().unwrap().get_or_insert(this, hash, v)
});
*cache.borrow_mut().get_or_insert(this, hash, v)
}
thread_local! {
static THREAD_LOCAL_CACHE: RefCell<Map> = const { RefCell::new(Map::EMPTY) };
}
let hash = type_map::TypeIdBuildHasher.hash_one(self.0.type_id);
THREAD_LOCAL_CACHE.with(|cache| {
let borrow = cache.borrow();
if let Some(v) = borrow.get(self, hash) {
*v
} else {
drop(borrow);
insert_in_thread_local_cache(cache, self, hash)
}
})
}
}
impl<T: ?Sized + Send + Sync + 'static> Copy for LazyInternedLazy<T> {}
impl<T: ?Sized + Send + Sync + 'static> Clone for LazyInternedLazy<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<T: ?Sized + Send + Sync + 'static> Hash for LazyInternedFn<T> { impl<T: ?Sized + Send + Sync + 'static> Hash for LazyInternedLazy<T> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.0.get_ptr_eq_with_type_id().hash(state); self.0.hash(state);
} }
} }
impl<T: ?Sized + Send + Sync + 'static> Eq for LazyInternedFn<T> {} impl<T: ?Sized + Send + Sync + 'static> Eq for LazyInternedLazy<T> {}
impl<T: ?Sized + Send + Sync + 'static> PartialEq for LazyInternedFn<T> { impl<T: ?Sized + Send + Sync + 'static> PartialEq for LazyInternedLazy<T> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.0.get_ptr_eq_with_type_id() == other.0.get_ptr_eq_with_type_id() self.0 == other.0
} }
} }
pub enum LazyInterned<T: ?Sized + Send + Sync + 'static> { pub enum LazyInterned<T: ?Sized + Send + Sync + 'static> {
Interned(Interned<T>), Interned(Interned<T>),
Lazy(LazyInternedFn<T>), Lazy(LazyInternedLazy<T>),
} }
impl<T: ?Sized + Send + Sync + 'static> LazyInterned<T> { impl<T: ?Sized + Send + Sync + 'static> LazyInterned<T> {
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self { pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
Self::Lazy(LazyInternedFn(v)) Self::Lazy(LazyInternedLazy::new_const::<V>())
}
pub const fn new_const_default() -> Self
where
Interned<T>: Default,
{
Self::new_const::<Interned<T>>()
}
pub fn interned(self) -> Interned<T> {
match self {
Self::Interned(retval) => retval,
Self::Lazy(retval) => retval.interned(),
}
} }
} }
@ -77,7 +200,7 @@ impl<T: ?Sized + Sync + Send + 'static> Clone for LazyInterned<T> {
impl<T: ?Sized + Sync + Send + 'static> Copy for LazyInterned<T> {} impl<T: ?Sized + Sync + Send + 'static> Copy for LazyInterned<T> {}
impl<T: ?Sized + Sync + Send + 'static + Intern> Deref for LazyInterned<T> { impl<T: ?Sized + Sync + Send + 'static> Deref for LazyInterned<T> {
type Target = T; type Target = T;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -85,9 +208,9 @@ impl<T: ?Sized + Sync + Send + 'static + Intern> Deref for LazyInterned<T> {
} }
} }
impl<T: ?Sized + Sync + Send + 'static + Intern> Eq for LazyInterned<T> where Interned<T>: Eq {} impl<T: ?Sized + Sync + Send + 'static> Eq for LazyInterned<T> where Interned<T>: Eq {}
impl<T: ?Sized + Sync + Send + 'static + Intern> PartialEq for LazyInterned<T> impl<T: ?Sized + Sync + Send + 'static> PartialEq for LazyInterned<T>
where where
Interned<T>: PartialEq, Interned<T>: PartialEq,
{ {
@ -96,7 +219,7 @@ where
} }
} }
impl<T: ?Sized + Sync + Send + 'static + Intern> Ord for LazyInterned<T> impl<T: ?Sized + Sync + Send + 'static> Ord for LazyInterned<T>
where where
Interned<T>: Ord, Interned<T>: Ord,
{ {
@ -105,7 +228,7 @@ where
} }
} }
impl<T: ?Sized + Sync + Send + 'static + Intern> PartialOrd for LazyInterned<T> impl<T: ?Sized + Sync + Send + 'static> PartialOrd for LazyInterned<T>
where where
Interned<T>: PartialOrd, Interned<T>: PartialOrd,
{ {
@ -114,7 +237,7 @@ where
} }
} }
impl<T: ?Sized + Sync + Send + 'static + Intern> Hash for LazyInterned<T> impl<T: ?Sized + Sync + Send + 'static> Hash for LazyInterned<T>
where where
Interned<T>: Hash, Interned<T>: Hash,
{ {
@ -123,77 +246,6 @@ where
} }
} }
impl<T: ?Sized + Sync + Send + 'static> LazyInterned<T> {
pub fn interned(self) -> Interned<T>
where
T: Intern,
{
struct MemoizeInterned<T: ?Sized + Intern>(PhantomData<T>);
impl<T: ?Sized + Intern> Hash for MemoizeInterned<T> {
fn hash<H: Hasher>(&self, _state: &mut H) {}
}
impl<T: ?Sized + Intern> PartialEq for MemoizeInterned<T> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl<T: ?Sized + Intern> Eq for MemoizeInterned<T> {}
impl<T: ?Sized + Intern> Clone for MemoizeInterned<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: ?Sized + Intern> Copy for MemoizeInterned<T> {}
impl<T: ?Sized + Intern> MemoizeGeneric for MemoizeInterned<T> {
type InputRef<'a> = LazyInternedFn<T>;
type InputOwned = LazyInternedFn<T>;
type InputCow<'a> = LazyInternedFn<T>;
type Output = Interned<T>;
fn input_eq(a: Self::InputRef<'_>, b: Self::InputRef<'_>) -> bool {
a == b
}
fn input_borrow(input: &Self::InputOwned) -> Self::InputRef<'_> {
*input
}
fn input_cow_into_owned(input: Self::InputCow<'_>) -> Self::InputOwned {
input
}
fn input_cow_borrow<'a>(input: &'a Self::InputCow<'_>) -> Self::InputRef<'a> {
*input
}
fn input_cow_from_owned<'a>(input: Self::InputOwned) -> Self::InputCow<'a> {
input
}
fn input_cow_from_ref(input: Self::InputRef<'_>) -> Self::InputCow<'_> {
input
}
fn inner(self, input: Self::InputRef<'_>) -> Self::Output {
input.0.get()
}
}
match self {
Self::Interned(retval) => retval,
Self::Lazy(retval) => MemoizeInterned(PhantomData).get(retval),
}
}
}
pub trait InternedCompare { pub trait InternedCompare {
type InternedCompareKey: Ord + Hash; type InternedCompareKey: Ord + Hash;
fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey; fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey;
@ -593,71 +645,6 @@ impl<T: ?Sized + 'static + Send + Sync + ToOwned> From<Interned<T>> for Cow<'_,
} }
} }
struct InternerState<T: ?Sized + 'static + Send + Sync> {
table: HashTable<&'static T>,
hasher: DefaultBuildHasher,
}
pub struct Interner<T: ?Sized + 'static + Send + Sync> {
state: Mutex<InternerState<T>>,
}
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
fn get() -> &'static Interner<T> {
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
TYPE_ID_MAP.get_or_insert_default()
}
}
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
fn default() -> Self {
Self {
state: Mutex::new(InternerState {
table: HashTable::new(),
hasher: Default::default(),
}),
}
}
}
impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
fn intern<F: FnOnce(Cow<'_, T>) -> &'static T>(
&self,
alloc: F,
value: Cow<'_, T>,
) -> Interned<T> {
let mut state = self.state.lock().unwrap();
let InternerState { table, hasher } = &mut *state;
let inner = *table
.entry(
hasher.hash_one(&*value),
|k| **k == *value,
|k| hasher.hash_one(&**k),
)
.or_insert_with(|| alloc(value))
.get();
Interned { inner }
}
}
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<T> {
fn intern_sized(&self, value: Cow<'_, T>) -> Interned<T> {
self.intern(|value| Box::leak(Box::new(value.into_owned())), value)
}
}
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<[T]> {
fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> {
self.intern(|value| value.into_owned().leak(), value)
}
}
impl Interner<BitSlice> {
fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned<BitSlice> {
self.intern(|value| value.into_owned().leak(), value)
}
}
pub struct Interned<T: ?Sized + 'static + Send + Sync> { pub struct Interned<T: ?Sized + 'static + Send + Sync> {
inner: &'static T, inner: &'static T,
} }
@ -977,7 +964,7 @@ impl<T: Clone + Send + Sync + 'static + Hash + Eq> Intern for T {
where where
Self: ToOwned, Self: ToOwned,
{ {
Interner::get().intern_sized(this) interner::Interner::get().intern_sized(this)
} }
} }
@ -997,7 +984,7 @@ impl<T: Clone + Send + Sync + 'static + Hash + Eq> Intern for [T] {
where where
Self: ToOwned, Self: ToOwned,
{ {
Interner::get().intern_slice(this) interner::Interner::get().intern_slice(this)
} }
} }
@ -1017,7 +1004,7 @@ impl Intern for BitSlice {
where where
Self: ToOwned, Self: ToOwned,
{ {
Interner::get().intern_bit_slice(this) interner::Interner::get().intern_bit_slice(this)
} }
} }
@ -1035,10 +1022,17 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy {
fn inner(self, input: Self::InputRef<'_>) -> Self::Output; fn inner(self, input: Self::InputRef<'_>) -> Self::Output;
fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output { fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new(); static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
thread_local! {
static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() };
}
let map: &RwLock<( let map: &RwLock<(
DefaultBuildHasher, DefaultBuildHasher,
HashTable<(Self, Self::InputOwned, Self::Output)>, HashTable<(Self, Self::InputOwned, Self::Output)>,
)> = TYPE_ID_MAP.get_or_insert_default(); )> = TYPE_ID_MAP_CACHE.with(|cache| {
cache.get_or_insert_with(|| {
TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default()))
})
});
fn hash_eq_key<'a, 'b, T: MemoizeGeneric>( fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
this: &'a T, this: &'a T,
input: T::InputRef<'b>, input: T::InputRef<'b>,
@ -1140,3 +1134,35 @@ pub trait Memoize: 'static + Send + Sync + Hash + Eq + Copy {
self.get_cow(Cow::Borrowed(input)) self.get_cow(Cow::Borrowed(input))
} }
} }
/// like `once_cell::race::OnceBox` but for `Interned<T>` instead of `Box<T>`
pub struct OnceInterned<T: 'static + Send + Sync>(OnceRef<'static, T>);
impl<T: 'static + Send + Sync + fmt::Debug> fmt::Debug for OnceInterned<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("OnceInterned").field(&self.get()).finish()
}
}
impl<T: 'static + Send + Sync> Default for OnceInterned<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: 'static + Send + Sync> OnceInterned<T> {
pub const fn new() -> Self {
Self(OnceRef::new())
}
pub fn set(&self, v: Interned<T>) -> Result<(), ()> {
self.0.set(v.inner)
}
pub fn get(&self) -> Option<Interned<T>> {
self.0.get().map(|inner| Interned { inner })
}
pub fn get_or_init<F: FnOnce() -> Interned<T>>(&self, f: F) -> Interned<T> {
Interned {
inner: self.0.get_or_init(|| f().inner),
}
}
}

View file

@ -0,0 +1,117 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
intern::{Interned, type_map::TypeIdMap},
util::DefaultBuildHasher,
};
use bitvec::slice::BitSlice;
use hashbrown::HashTable;
use std::{
borrow::Cow,
hash::{BuildHasher, Hash},
sync::RwLock,
};
struct InternerShard<T: ?Sized + 'static + Send + Sync> {
table: HashTable<&'static T>,
}
const LOG2_SHARD_COUNT: u32 = 6;
fn shard_index_from_hash(hash: u64) -> usize {
// number of bits used for hashbrown's Tag
const HASH_BROWN_TAG_BITS: u32 = 7;
// try to extract bits of the hash that hashbrown isn't using,
// while accounting for some hash functions only returning `usize` bits.
const SHARD_INDEX_START: u32 = usize::BITS
.saturating_sub(HASH_BROWN_TAG_BITS)
.saturating_sub(LOG2_SHARD_COUNT);
let mut shard_index = hash >> SHARD_INDEX_START;
shard_index %= 1 << LOG2_SHARD_COUNT;
shard_index as usize
}
pub(crate) struct Interner<T: ?Sized + 'static + Send + Sync> {
shards: [RwLock<InternerShard<T>>; 1 << LOG2_SHARD_COUNT],
hasher: DefaultBuildHasher,
}
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
pub(crate) fn get() -> &'static Interner<T> {
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
thread_local! {
static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() };
}
TYPE_ID_MAP_CACHE.with(|cache| {
cache.get_or_insert_with(|| {
TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default()))
})
})
}
}
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
fn default() -> Self {
Self {
shards: [const {
RwLock::new(InternerShard {
table: HashTable::new(),
})
}; _],
hasher: Default::default(),
}
}
}
impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
fn intern<F: FnOnce(Cow<'_, T>) -> &'static T>(
&self,
alloc: F,
value: Cow<'_, T>,
) -> Interned<T> {
let hash = self.hasher.hash_one(&*value);
let shard_index = shard_index_from_hash(hash);
let shard = &self.shards[shard_index];
let shard_read = shard.read().unwrap();
let Some(&inner) = shard_read.table.find(hash, |k| **k == *value) else {
drop(shard_read);
return self.intern_cold(alloc, value, hash, shard);
};
Interned { inner }
}
#[cold]
fn intern_cold<F: FnOnce(Cow<'_, T>) -> &'static T>(
&self,
alloc: F,
value: Cow<'_, T>,
hash: u64,
shard: &RwLock<InternerShard<T>>,
) -> Interned<T> {
let mut shard = shard.write().unwrap();
let inner = *shard
.table
.entry(hash, |k| **k == *value, |k| self.hasher.hash_one(&**k))
.or_insert_with(|| alloc(value))
.get();
Interned { inner }
}
}
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<T> {
pub(crate) fn intern_sized(&self, value: Cow<'_, T>) -> Interned<T> {
self.intern(|value| Box::leak(Box::new(value.into_owned())), value)
}
}
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<[T]> {
pub(crate) fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> {
self.intern(|value| value.into_owned().leak(), value)
}
}
impl Interner<BitSlice> {
pub(crate) fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned<BitSlice> {
self.intern(|value| value.into_owned().leak(), value)
}
}

View file

@ -6,7 +6,7 @@ use std::{
sync::RwLock, sync::RwLock,
}; };
struct TypeIdHasher(u64); pub(crate) struct TypeIdHasher(u64);
// assumes TypeId has at least 64 bits that is a good hash // assumes TypeId has at least 64 bits that is a good hash
impl Hasher for TypeIdHasher { impl Hasher for TypeIdHasher {
@ -63,7 +63,7 @@ impl Hasher for TypeIdHasher {
} }
} }
struct TypeIdBuildHasher; pub(crate) struct TypeIdBuildHasher;
impl BuildHasher for TypeIdBuildHasher { impl BuildHasher for TypeIdBuildHasher {
type Hasher = TypeIdHasher; type Hasher = TypeIdHasher;
@ -87,20 +87,23 @@ impl TypeIdMap {
fn insert_slow( fn insert_slow(
&self, &self,
type_id: TypeId, type_id: TypeId,
make: fn() -> Box<dyn Any + Sync + Send>, make: impl FnOnce() -> &'static (dyn Any + Sync + Send),
) -> &'static (dyn Any + Sync + Send) { ) -> &'static (dyn Any + Sync + Send) {
let value = Box::leak(make()); let value = make();
let mut write_guard = self.0.write().unwrap(); let mut write_guard = self.0.write().unwrap();
*write_guard.entry(type_id).or_insert(value) *write_guard.entry(type_id).or_insert(value)
} }
pub(crate) fn get_or_insert_default<T: Sized + Any + Send + Sync + Default>(&self) -> &T { pub(crate) fn get_or_insert_with<T: Sized + Any + Send + Sync>(
&self,
make: impl FnOnce() -> &'static T,
) -> &'static T {
let type_id = TypeId::of::<T>(); let type_id = TypeId::of::<T>();
let read_guard = self.0.read().unwrap(); let read_guard = self.0.read().unwrap();
let retval = read_guard.get(&type_id).map(|v| *v); let retval = read_guard.get(&type_id).map(|v| *v);
drop(read_guard); drop(read_guard);
let retval = match retval { let retval = match retval {
Some(retval) => retval, Some(retval) => retval,
None => self.insert_slow(type_id, move || Box::new(T::default())), None => self.insert_slow(type_id, move || make()),
}; };
retval.downcast_ref().expect("known to have correct TypeId") retval.downcast_ref().expect("known to have correct TypeId")
} }

View file

@ -2396,13 +2396,16 @@ impl ModuleBuilder {
#[track_caller] #[track_caller]
pub fn extern_module_simulation_fn< pub fn extern_module_simulation_fn<
Args: fmt::Debug + Clone + Hash + Eq + Send + Sync + 'static, Args: fmt::Debug + Clone + Hash + Eq + Send + Sync + 'static,
F: Copy + Fn(Args, crate::sim::ExternModuleSimulationState) -> Fut + Send + Sync + 'static,
Fut: IntoFuture<Output = ()> + 'static, Fut: IntoFuture<Output = ()> + 'static,
>( >(
&self, &self,
args: Args, args: Args,
f: fn(Args, crate::sim::ExternModuleSimulationState) -> Fut, f: F,
) { ) {
self.extern_module_simulation(crate::sim::SimGeneratorFn { args, f }); // use for compile-time side-effect
let _ = crate::sim::SimGeneratorFn::<Args, F, Fut>::ASSERT_F_IS_ZERO_SIZED;
self.extern_module_simulation(crate::sim::SimGeneratorFn::new(args, f));
} }
} }

View file

@ -4,12 +4,12 @@
use crate::{ use crate::{
expr::{Expr, HdlPartialEqImpl, HdlPartialOrdImpl, ToExpr, ValueType}, expr::{Expr, HdlPartialEqImpl, HdlPartialOrdImpl, ToExpr, ValueType},
int::Bool, int::Bool,
intern::{Intern, Interned, InternedCompare, LazyInterned, LazyInternedTrait, Memoize}, intern::{Intern, Interned, InternedCompare, LazyInterned, Memoize},
sim::value::{SimValue, ToSimValue, ToSimValueWithType}, sim::value::{SimValue, ToSimValue, ToSimValueWithType},
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten,
StaticType, Type, TypeProperties, impl_match_variant_as_self, SimValueDebug, StaticType, Type, TypeProperties, impl_match_variant_as_self,
serde_impls::{SerdeCanonicalType, SerdePhantomConst}, serde_impls::{SerdeCanonicalType, SerdePhantomConst},
}, },
}; };
@ -240,11 +240,17 @@ impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
{ {
Self::new_interned(value.intern_deref()) Self::new_interned(value.intern_deref())
} }
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self { pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
Self { Self {
value: LazyInterned::new_lazy(v), value: LazyInterned::new_const::<V>(),
} }
} }
pub const fn new_const_default() -> Self
where
Interned<T>: Default,
{
Self::new_const::<Interned<T>>()
}
pub fn get(self) -> Interned<T> { pub fn get(self) -> Interned<T> {
self.value.interned() self.value.interned()
} }
@ -321,6 +327,15 @@ impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
} }
} }
impl<T: ?Sized + PhantomConstValue> SimValueDebug for PhantomConst<T> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<T: ?Sized + PhantomConstValue> Default for PhantomConst<T> impl<T: ?Sized + PhantomConstValue> Default for PhantomConst<T>
where where
Interned<T>: Default, Interned<T>: Default,
@ -334,9 +349,7 @@ impl<T: ?Sized + PhantomConstValue> StaticType for PhantomConst<T>
where where
Interned<T>: Default, Interned<T>: Default,
{ {
const TYPE: Self = PhantomConst { const TYPE: Self = Self::new_const_default();
value: LazyInterned::new_lazy(&Interned::<T>::default),
};
const MASK_TYPE: Self::MaskType = (); const MASK_TYPE: Self::MaskType = ();
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES; const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES; const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
clock::Clock, clock::Clock,
expr::{CastToImpl, Expr, ValueType}, expr::{CastToImpl, Expr, ValueType},
@ -8,11 +9,13 @@ use crate::{
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter, CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter,
OpaqueSimValueWritten, StaticType, Type, TypeProperties, impl_match_variant_as_self, OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties,
impl_match_variant_as_self,
}, },
util::ConstUsize, util::ConstUsize,
}; };
use bitvec::{bits, order::Lsb0}; use bitvec::{bits, order::Lsb0};
use std::fmt;
mod sealed { mod sealed {
pub trait ResetTypeSealed {} pub trait ResetTypeSealed {}
@ -100,6 +103,15 @@ macro_rules! reset_type {
} }
} }
impl SimValueDebug for $name {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl $name { impl $name {
pub fn type_properties(self) -> TypeProperties { pub fn type_properties(self) -> TypeProperties {
Self::TYPE_PROPERTIES Self::TYPE_PROPERTIES

View file

@ -40,7 +40,7 @@ use crate::{
OpaqueSimValue, OpaqueSimValueSize, OpaqueSimValueSizeRange, OpaqueSimValueSlice, OpaqueSimValue, OpaqueSimValueSize, OpaqueSimValueSizeRange, OpaqueSimValueSlice,
OpaqueSimValueWriter, OpaqueSimValueWriter,
}, },
util::{BitSliceWriteWithBase, DebugAsDisplay, HashMap, HashSet}, util::{BitSliceWriteWithBase, DebugAsDisplay, HashMap, HashSet, copy_le_bytes_to_bitslice},
}; };
use bitvec::{bits, order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView}; use bitvec::{bits, order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView};
use num_bigint::BigInt; use num_bigint::BigInt;
@ -54,7 +54,6 @@ use std::{
hash::Hash, hash::Hash,
mem, mem,
pin::{Pin, pin}, pin::{Pin, pin},
ptr,
rc::Rc, rc::Rc,
sync::{Arc, Mutex, MutexGuard}, sync::{Arc, Mutex, MutexGuard},
task::Poll, task::Poll,
@ -829,6 +828,7 @@ where
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct SimTrace<K, S> { pub(crate) struct SimTrace<K, S> {
kind: K, kind: K,
maybe_changed: bool,
state: S, state: S,
last_state: S, last_state: S,
} }
@ -849,12 +849,14 @@ impl<K: fmt::Debug> SimTraceDebug<TraceScalarId> for SimTrace<K, ()> {
fn fmt(&self, id: TraceScalarId, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, id: TraceScalarId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
kind, kind,
maybe_changed,
state, state,
last_state, last_state,
} = self; } = self;
f.debug_struct("SimTrace") f.debug_struct("SimTrace")
.field("id", &id) .field("id", &id)
.field("kind", kind) .field("kind", kind)
.field("maybe_changed", maybe_changed)
.field("state", state) .field("state", state)
.field("last_state", last_state) .field("last_state", last_state)
.finish() .finish()
@ -865,12 +867,14 @@ impl<K: fmt::Debug> SimTraceDebug<TraceScalarId> for SimTrace<K, SimTraceState>
fn fmt(&self, id: TraceScalarId, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, id: TraceScalarId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
kind, kind,
maybe_changed,
state, state,
last_state, last_state,
} = self; } = self;
f.debug_struct("SimTrace") f.debug_struct("SimTrace")
.field("id", &id) .field("id", &id)
.field("kind", kind) .field("kind", kind)
.field("maybe_changed", maybe_changed)
.field("state", state) .field("state", state)
.field("last_state", last_state) .field("last_state", last_state)
.finish() .finish()
@ -1296,10 +1300,16 @@ impl SimulationModuleState {
if !self.uninitialized_ios.is_empty() { if !self.uninitialized_ios.is_empty() {
match which_module { match which_module {
WhichModule::Main => { WhichModule::Main => {
panic!("can't read from an output before initializing all inputs"); panic!(
"can't read from an output before initializing all inputs\nuninitialized_ios={:#?}",
SortedSetDebug(&self.uninitialized_ios),
);
} }
WhichModule::Extern { .. } => { WhichModule::Extern { .. } => {
panic!("can't read from an input before initializing all outputs"); panic!(
"can't read from an input before initializing all outputs\nuninitialized_ios={:#?}",
SortedSetDebug(&self.uninitialized_ios),
);
} }
} }
} }
@ -2073,10 +2083,12 @@ impl SimulationImpl {
traces: SimTraces(Box::from_iter(compiled.traces.0.iter().map( traces: SimTraces(Box::from_iter(compiled.traces.0.iter().map(
|&SimTrace { |&SimTrace {
kind, kind,
maybe_changed: _,
state: _, state: _,
last_state: _, last_state: _,
}| SimTrace { }| SimTrace {
kind, kind,
maybe_changed: true,
state: kind.make_state(), state: kind.make_state(),
last_state: kind.make_state(), last_state: kind.make_state(),
}, },
@ -2121,13 +2133,16 @@ impl SimulationImpl {
id, id,
&SimTrace { &SimTrace {
kind, kind,
maybe_changed,
ref state, ref state,
ref last_state, ref last_state,
}, },
) in self.traces.0.iter().enumerate() ) in self.traces.0.iter().enumerate()
{ {
if ONLY_IF_CHANGED && state == last_state { if ONLY_IF_CHANGED {
continue; if !(maybe_changed && state != last_state) {
continue;
}
} }
let id = TraceScalarId(id); let id = TraceScalarId(id);
match kind { match kind {
@ -2188,10 +2203,45 @@ impl SimulationImpl {
fn read_traces<const IS_INITIAL_STEP: bool>(&mut self) { fn read_traces<const IS_INITIAL_STEP: bool>(&mut self) {
for &mut SimTrace { for &mut SimTrace {
kind, kind,
ref mut maybe_changed,
ref mut state, ref mut state,
ref mut last_state, ref mut last_state,
} in &mut self.traces.0 } in &mut self.traces.0
{ {
let new_maybe_changed = match kind {
SimTraceKind::BigUInt { index, ty: _ }
| SimTraceKind::BigSInt { index, ty: _ }
| SimTraceKind::BigBool { index }
| SimTraceKind::BigAsyncReset { index }
| SimTraceKind::BigSyncReset { index }
| SimTraceKind::BigClock { index } => self
.state
.big_slots
.state_index_fetch_and_clear_maybe_modified_flag(index),
SimTraceKind::SmallUInt { index, ty: _ }
| SimTraceKind::SmallSInt { index, ty: _ }
| SimTraceKind::SmallBool { index }
| SimTraceKind::SmallAsyncReset { index }
| SimTraceKind::SmallSyncReset { index }
| SimTraceKind::SmallClock { index }
| SimTraceKind::EnumDiscriminant { index, ty: _ } => self
.state
.small_slots
.state_index_fetch_and_clear_maybe_modified_flag(index),
SimTraceKind::SimOnly { index, ty: _ } => self
.state
.sim_only_slots
.state_index_fetch_and_clear_maybe_modified_flag(index),
SimTraceKind::PhantomConst { ty: _ } => IS_INITIAL_STEP,
};
if !new_maybe_changed && !IS_INITIAL_STEP {
if *maybe_changed {
last_state.clone_from(state);
}
*maybe_changed = false;
continue;
}
*maybe_changed = new_maybe_changed;
if !IS_INITIAL_STEP { if !IS_INITIAL_STEP {
mem::swap(state, last_state); mem::swap(state, last_state);
} }
@ -2199,14 +2249,11 @@ impl SimulationImpl {
SimTraceKind::BigUInt { index, ty: _ } | SimTraceKind::BigSInt { index, ty: _ } => { SimTraceKind::BigUInt { index, ty: _ } | SimTraceKind::BigSInt { index, ty: _ } => {
let state = state.unwrap_bits_mut(); let state = state.unwrap_bits_mut();
let bigint = &self.state.big_slots[index]; let bigint = &self.state.big_slots[index];
let mut bytes = bigint.to_signed_bytes_le(); copy_le_bytes_to_bitslice(
bytes.resize( state,
state.len().div_ceil(8), &bigint.to_signed_bytes_le(),
if bigint.is_negative() { 0xFF } else { 0 }, bigint.is_negative(),
); );
let bitslice = BitSlice::<u8, Lsb0>::from_slice(&bytes);
let bitslice = &bitslice[..state.len()];
state.clone_from_bitslice(bitslice);
} }
SimTraceKind::BigBool { index } SimTraceKind::BigBool { index }
| SimTraceKind::BigAsyncReset { index } | SimTraceKind::BigAsyncReset { index }
@ -4065,13 +4112,48 @@ pub trait ExternModuleSimGenerator: Clone + Eq + Hash + Any + Send + Sync + fmt:
fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture<Output = ()> + 'a; fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture<Output = ()> + 'a;
} }
pub struct SimGeneratorFn<Args, Fut> { /// Type requirements: `F` must be zero-sized, this guarantees that the function called
pub args: Args, /// by `F` is entirely determined by the type `F` and not by its value, allowing us to
pub f: fn(Args, ExternModuleSimulationState) -> Fut, /// correctly leave `F` out of the stuff used for `Hash` and `Eq`.
///
/// Note we can't just use function pointers instead -- comparing them is non-deterministic
/// since Rust will duplicate and/or merge functions, even if those functions happen to have
/// different UB but just happen to compile to the same assembly language:
/// <https://github.com/rust-lang/unsafe-code-guidelines/issues/589#issuecomment-3515424930>
pub struct SimGeneratorFn<Args, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> {
args: Args,
f: F,
} }
impl<Args: fmt::Debug, Fut> fmt::Debug for SimGeneratorFn<Args, Fut> { impl<Args, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut>
SimGeneratorFn<Args, F, Fut>
{
pub const ASSERT_F_IS_ZERO_SIZED: () = {
if size_of::<F>() != 0 {
panic!(
"F must be zero-sized -- so it must be a closure with no captures or a function item, it can't be a function pointer"
);
}
};
pub const fn new(args: Args, f: F) -> Self {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
Self { args, f }
}
pub const fn args(&self) -> &Args {
&self.args
}
pub const fn f(&self) -> F {
self.f
}
}
impl<Args: fmt::Debug, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> fmt::Debug
for SimGeneratorFn<Args, F, Fut>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
let Self { args, f: _ } = self; let Self { args, f: _ } = self;
f.debug_struct("SimGeneratorFn") f.debug_struct("SimGeneratorFn")
.field("args", args) .field("args", args)
@ -4080,25 +4162,39 @@ impl<Args: fmt::Debug, Fut> fmt::Debug for SimGeneratorFn<Args, Fut> {
} }
} }
impl<Args: Hash, Fut> Hash for SimGeneratorFn<Args, Fut> { impl<Args: Hash, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Hash
for SimGeneratorFn<Args, F, Fut>
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let Self { args, f } = self; // use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
let Self { args, f: _ } = self;
args.hash(state); args.hash(state);
f.hash(state);
} }
} }
impl<Args: Eq, Fut> Eq for SimGeneratorFn<Args, Fut> {} impl<Args: Eq, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Eq
for SimGeneratorFn<Args, F, Fut>
{
}
impl<Args: PartialEq, Fut> PartialEq for SimGeneratorFn<Args, Fut> { impl<Args: PartialEq, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> PartialEq
for SimGeneratorFn<Args, F, Fut>
{
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
let Self { args, f } = self; // use for compile-time side-effect
*args == other.args && ptr::fn_addr_eq(*f, other.f) let _ = Self::ASSERT_F_IS_ZERO_SIZED;
let Self { args, f: _ } = self;
*args == other.args
} }
} }
impl<Args: Clone, Fut> Clone for SimGeneratorFn<Args, Fut> { impl<Args: Clone, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Clone
for SimGeneratorFn<Args, F, Fut>
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
Self { Self {
args: self.args.clone(), args: self.args.clone(),
f: self.f, f: self.f,
@ -4106,14 +4202,20 @@ impl<Args: Clone, Fut> Clone for SimGeneratorFn<Args, Fut> {
} }
} }
impl<Args: Copy, Fut> Copy for SimGeneratorFn<Args, Fut> {} impl<Args: Copy, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Copy
for SimGeneratorFn<Args, F, Fut>
{
}
impl< impl<
T: fmt::Debug + Clone + Eq + Hash + Send + Sync + 'static, Args: fmt::Debug + Clone + Eq + Hash + Send + Sync + 'static,
F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut + Send + Sync + 'static,
Fut: IntoFuture<Output = ()> + 'static, Fut: IntoFuture<Output = ()> + 'static,
> ExternModuleSimGenerator for SimGeneratorFn<T, Fut> > ExternModuleSimGenerator for SimGeneratorFn<Args, F, Fut>
{ {
fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture<Output = ()> + 'a { fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture<Output = ()> + 'a {
// use for compile-time side-effect
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
(self.f)(self.args.clone(), sim) (self.f)(self.args.clone(), sim)
} }
} }

View file

@ -2234,6 +2234,7 @@ impl Compiler {
let id = TraceScalarId(self.traces.0.len()); let id = TraceScalarId(self.traces.0.len());
self.traces.0.push(SimTrace { self.traces.0.push(SimTrace {
kind, kind,
maybe_changed: true,
state: (), state: (),
last_state: (), last_state: (),
}); });
@ -4087,6 +4088,15 @@ impl Compiler {
let init = self.compiled_expr_to_value(init, reg.source_location()); let init = self.compiled_expr_to_value(init, reg.source_location());
(reg.clock_domain().rst, init) (reg.clock_domain().rst, init)
}); });
// next value defaults to current value
self.compile_simple_connect(
[].intern_slice(),
value.into(),
value,
reg.source_location(),
);
self.compile_reg( self.compile_reg(
clk, clk,
reset_and_init, reset_and_init,

View file

@ -17,12 +17,11 @@ use bitvec::slice::BitSlice;
use num_bigint::BigInt; use num_bigint::BigInt;
use num_traits::{One, Signed, ToPrimitive, Zero}; use num_traits::{One, Signed, ToPrimitive, Zero};
use std::{ use std::{
borrow::BorrowMut,
convert::Infallible, convert::Infallible,
fmt::{self, Write}, fmt::{self, Write},
hash::Hash, hash::Hash,
marker::PhantomData, marker::PhantomData,
ops::{ControlFlow, Deref, DerefMut, Index, IndexMut}, ops::{ControlFlow, Deref, Index, IndexMut},
}; };
use vec_map::VecMap; use vec_map::VecMap;
@ -915,6 +914,12 @@ impl<K: StatePartKind> StatePart<K> {
value: K::borrow_state(&mut self.value), value: K::borrow_state(&mut self.value),
} }
} }
pub(crate) fn state_index_fetch_and_clear_maybe_modified_flag(
&mut self,
part_index: StatePartIndex<K>,
) -> bool {
K::state_index_fetch_and_clear_maybe_modified_flag(&mut self.value, part_index)
}
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
@ -922,56 +927,38 @@ pub(crate) struct BorrowedStatePart<'a, K: StatePartKind> {
pub(crate) value: K::BorrowedState<'a>, pub(crate) value: K::BorrowedState<'a>,
} }
impl< impl<K: StatePartKind> BorrowedStatePart<'_, K> {
'a,
K: StatePartKind<
BorrowedState<'a>: DerefMut<Target: IndexMut<usize, Output = T> + BorrowMut<[T]>>,
>,
T,
> BorrowedStatePart<'a, K>
{
pub(crate) fn get_disjoint_mut<const N: usize>( pub(crate) fn get_disjoint_mut<const N: usize>(
&mut self, &mut self,
indexes: [StatePartIndex<K>; N], indexes: [StatePartIndex<K>; N],
) -> [&mut T; N] { ) -> [&mut K::StateElement; N] {
(*self.value) K::borrowed_state_get_disjoint_mut(&mut self.value, indexes)
.borrow_mut()
.get_disjoint_mut(indexes.map(|v| v.value as usize))
.expect("indexes are disjoint")
} }
} }
impl<K: StatePartKind<State: Deref<Target: Index<usize, Output = T>>>, T> Index<StatePartIndex<K>> impl<K: StatePartKind> Index<StatePartIndex<K>> for StatePart<K> {
for StatePart<K> type Output = K::StateElement;
{
type Output = T;
fn index(&self, index: StatePartIndex<K>) -> &Self::Output { fn index(&self, index: StatePartIndex<K>) -> &Self::Output {
&self.value[index.value as usize] K::state_index(&self.value, index)
} }
} }
impl<K: StatePartKind<State: DerefMut<Target: IndexMut<usize, Output = T>>>, T> impl<K: StatePartKind> IndexMut<StatePartIndex<K>> for StatePart<K> {
IndexMut<StatePartIndex<K>> for StatePart<K>
{
fn index_mut(&mut self, index: StatePartIndex<K>) -> &mut Self::Output { fn index_mut(&mut self, index: StatePartIndex<K>) -> &mut Self::Output {
&mut self.value[index.value as usize] K::state_index_mut(&mut self.value, index)
} }
} }
impl<'a, K: StatePartKind<BorrowedState<'a>: Deref<Target: Index<usize, Output = T>>>, T> impl<K: StatePartKind> Index<StatePartIndex<K>> for BorrowedStatePart<'_, K> {
Index<StatePartIndex<K>> for BorrowedStatePart<'a, K> type Output = K::StateElement;
{
type Output = T;
fn index(&self, index: StatePartIndex<K>) -> &Self::Output { fn index(&self, index: StatePartIndex<K>) -> &Self::Output {
&self.value[index.value as usize] K::borrowed_state_index(&self.value, index)
} }
} }
impl<'a, K: StatePartKind<BorrowedState<'a>: DerefMut<Target: IndexMut<usize, Output = T>>>, T> impl<K: StatePartKind> IndexMut<StatePartIndex<K>> for BorrowedStatePart<'_, K> {
IndexMut<StatePartIndex<K>> for BorrowedStatePart<'a, K>
{
fn index_mut(&mut self, index: StatePartIndex<K>) -> &mut Self::Output { fn index_mut(&mut self, index: StatePartIndex<K>) -> &mut Self::Output {
&mut self.value[index.value as usize] K::borrowed_state_index_mut(&mut self.value, index)
} }
} }

View file

@ -236,6 +236,7 @@ pub(crate) trait StatePartKind:
type LayoutData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy; type LayoutData: Send + Sync + Eq + Hash + fmt::Debug + 'static + Copy;
type State: fmt::Debug + 'static + Clone; type State: fmt::Debug + 'static + Clone;
type BorrowedState<'a>: 'a; type BorrowedState<'a>: 'a;
type StateElement;
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State; fn new_state(layout_data: &[Self::LayoutData]) -> Self::State;
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a>; fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a>;
fn part_debug_data<BK: InsnsBuildingKind>( fn part_debug_data<BK: InsnsBuildingKind>(
@ -247,6 +248,30 @@ pub(crate) trait StatePartKind:
index: StatePartIndex<Self>, index: StatePartIndex<Self>,
f: &mut impl fmt::Write, f: &mut impl fmt::Write,
) -> fmt::Result; ) -> fmt::Result;
fn state_index<'a>(
state: &'a Self::State,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement;
fn state_index_mut<'a>(
state: &'a mut Self::State,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement;
fn state_index_fetch_and_clear_maybe_modified_flag(
state: &mut Self::State,
part_index: StatePartIndex<Self>,
) -> bool;
fn borrowed_state_index<'a, 'b>(
state: &'a Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement;
fn borrowed_state_index_mut<'a, 'b>(
state: &'a mut Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement;
fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>(
state: &'a mut Self::BorrowedState<'b>,
part_indexes: [StatePartIndex<Self>; N],
) -> [&'a mut Self::StateElement; N];
} }
macro_rules! make_state_part_kinds { macro_rules! make_state_part_kinds {
@ -272,6 +297,7 @@ impl StatePartKind for StatePartKindMemories {
type LayoutData = MemoryData<Interned<BitSlice>>; type LayoutData = MemoryData<Interned<BitSlice>>;
type State = Box<[MemoryData<BitBox>]>; type State = Box<[MemoryData<BitBox>]>;
type BorrowedState<'a> = &'a mut [MemoryData<BitBox>]; type BorrowedState<'a> = &'a mut [MemoryData<BitBox>];
type StateElement = MemoryData<BitBox>;
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
layout_data layout_data
.iter() .iter()
@ -297,19 +323,88 @@ impl StatePartKind for StatePartKindMemories {
) -> fmt::Result { ) -> fmt::Result {
write!(f, "{:#?}", &state.memories[index]) write!(f, "{:#?}", &state.memories[index])
} }
fn state_index<'a>(
state: &'a Self::State,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state[part_index.as_usize()]
}
fn state_index_mut<'a>(
state: &'a mut Self::State,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
&mut state[part_index.as_usize()]
}
fn state_index_fetch_and_clear_maybe_modified_flag(
_state: &mut Self::State,
_part_index: StatePartIndex<Self>,
) -> bool {
true
}
fn borrowed_state_index<'a, 'b>(
state: &'a Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state[part_index.as_usize()]
}
fn borrowed_state_index_mut<'a, 'b>(
state: &'a mut Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
&mut state[part_index.as_usize()]
}
fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>(
state: &'a mut Self::BorrowedState<'b>,
part_indexes: [StatePartIndex<Self>; N],
) -> [&'a mut Self::StateElement; N] {
state
.get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize))
.expect("indexes are disjoint")
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
pub(crate) struct StateAndModified<T, M> {
pub(crate) state: T,
pub(crate) modified: M,
}
impl<T: Deref<Target = [E]>, M: Deref<Target = [bool]>, E: fmt::Debug> fmt::Debug
for StateAndModified<T, M>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.state.iter().zip(self.modified.iter().copied()).map(
|(state, modified)| {
fmt::from_fn(move |f| {
state.fmt(f)?;
if modified {
f.write_str(" (modified)")?;
}
Ok(())
})
},
))
.finish()
}
} }
impl StatePartKind for StatePartKindSmallSlots { impl StatePartKind for StatePartKindSmallSlots {
const NAME: &'static str = "SmallSlots"; const NAME: &'static str = "SmallSlots";
type DebugData = SlotDebugData; type DebugData = SlotDebugData;
type LayoutData = (); type LayoutData = ();
type State = Box<[SmallUInt]>; type State = StateAndModified<Box<[Self::StateElement]>, Box<[bool]>>;
type BorrowedState<'a> = &'a mut [SmallUInt]; type BorrowedState<'a> = StateAndModified<&'a mut [Self::StateElement], &'a mut [bool]>;
type StateElement = SmallUInt;
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
vec![0; layout_data.len()].into_boxed_slice() StateAndModified {
state: vec![0; layout_data.len()].into_boxed_slice(),
modified: vec![false; layout_data.len()].into_boxed_slice(),
}
} }
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state let StateAndModified { state, modified } = state;
StateAndModified { state, modified }
} }
fn part_debug_data<BK: InsnsBuildingKind>( fn part_debug_data<BK: InsnsBuildingKind>(
state_layout: &StateLayout<BK>, state_layout: &StateLayout<BK>,
@ -330,19 +425,69 @@ impl StatePartKind for StatePartKindSmallSlots {
write!(f, "{value:#x} {}", value as SmallSInt)?; write!(f, "{value:#x} {}", value as SmallSInt)?;
Ok(()) Ok(())
} }
fn state_index<'a>(
state: &'a Self::State,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state.state[part_index.as_usize()]
}
fn state_index_mut<'a>(
state: &'a mut Self::State,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
state.modified[part_index.as_usize()] = true;
&mut state.state[part_index.as_usize()]
}
fn state_index_fetch_and_clear_maybe_modified_flag(
state: &mut Self::State,
part_index: StatePartIndex<Self>,
) -> bool {
std::mem::replace(&mut state.modified[part_index.as_usize()], false)
}
fn borrowed_state_index<'a, 'b>(
state: &'a Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state.state[part_index.as_usize()]
}
fn borrowed_state_index_mut<'a, 'b>(
state: &'a mut Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
state.modified[part_index.as_usize()] = true;
&mut state.state[part_index.as_usize()]
}
fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>(
state: &'a mut Self::BorrowedState<'b>,
part_indexes: [StatePartIndex<Self>; N],
) -> [&'a mut Self::StateElement; N] {
for part_index in part_indexes {
state.modified[part_index.as_usize()] = true;
}
state
.state
.get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize))
.expect("indexes are disjoint")
}
} }
impl StatePartKind for StatePartKindBigSlots { impl StatePartKind for StatePartKindBigSlots {
const NAME: &'static str = "BigSlots"; const NAME: &'static str = "BigSlots";
type DebugData = SlotDebugData; type DebugData = SlotDebugData;
type LayoutData = (); type LayoutData = ();
type State = Box<[BigInt]>; type State = StateAndModified<Box<[Self::StateElement]>, Box<[bool]>>;
type BorrowedState<'a> = &'a mut [BigInt]; type BorrowedState<'a> = StateAndModified<&'a mut [Self::StateElement], &'a mut [bool]>;
type StateElement = BigInt;
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
layout_data.iter().map(|_| BigInt::default()).collect() let state: Box<[_]> = layout_data.iter().map(|_| BigInt::default()).collect();
StateAndModified {
modified: vec![false; state.len()].into_boxed_slice(),
state,
}
} }
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state let StateAndModified { state, modified } = state;
StateAndModified { state, modified }
} }
fn part_debug_data<BK: InsnsBuildingKind>( fn part_debug_data<BK: InsnsBuildingKind>(
state_layout: &StateLayout<BK>, state_layout: &StateLayout<BK>,
@ -361,19 +506,69 @@ impl StatePartKind for StatePartKindBigSlots {
) -> fmt::Result { ) -> fmt::Result {
write!(f, "{:#x}", state.big_slots[index]) write!(f, "{:#x}", state.big_slots[index])
} }
fn state_index<'a>(
state: &'a Self::State,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state.state[part_index.as_usize()]
}
fn state_index_mut<'a>(
state: &'a mut Self::State,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
state.modified[part_index.as_usize()] = true;
&mut state.state[part_index.as_usize()]
}
fn state_index_fetch_and_clear_maybe_modified_flag(
state: &mut Self::State,
part_index: StatePartIndex<Self>,
) -> bool {
std::mem::replace(&mut state.modified[part_index.as_usize()], false)
}
fn borrowed_state_index<'a, 'b>(
state: &'a Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state.state[part_index.as_usize()]
}
fn borrowed_state_index_mut<'a, 'b>(
state: &'a mut Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
state.modified[part_index.as_usize()] = true;
&mut state.state[part_index.as_usize()]
}
fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>(
state: &'a mut Self::BorrowedState<'b>,
part_indexes: [StatePartIndex<Self>; N],
) -> [&'a mut Self::StateElement; N] {
for part_index in part_indexes {
state.modified[part_index.as_usize()] = true;
}
state
.state
.get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize))
.expect("indexes are disjoint")
}
} }
impl StatePartKind for StatePartKindSimOnlySlots { impl StatePartKind for StatePartKindSimOnlySlots {
const NAME: &'static str = "SimOnlySlots"; const NAME: &'static str = "SimOnlySlots";
type DebugData = SlotDebugData; type DebugData = SlotDebugData;
type LayoutData = DynSimOnly; type LayoutData = DynSimOnly;
type State = Box<[DynSimOnlyValue]>; type State = StateAndModified<Box<[Self::StateElement]>, Box<[bool]>>;
type BorrowedState<'a> = &'a mut [DynSimOnlyValue]; type BorrowedState<'a> = StateAndModified<&'a mut [Self::StateElement], &'a mut [bool]>;
type StateElement = DynSimOnlyValue;
fn new_state(layout_data: &[Self::LayoutData]) -> Self::State { fn new_state(layout_data: &[Self::LayoutData]) -> Self::State {
layout_data.iter().map(|ty| ty.default_value()).collect() let state: Box<[_]> = layout_data.iter().map(|ty| ty.default_value()).collect();
StateAndModified {
modified: vec![false; state.len()].into_boxed_slice(),
state,
}
} }
fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> { fn borrow_state<'a>(state: &'a mut Self::State) -> Self::BorrowedState<'a> {
state let StateAndModified { state, modified } = state;
StateAndModified { state, modified }
} }
fn part_debug_data<BK: InsnsBuildingKind>( fn part_debug_data<BK: InsnsBuildingKind>(
state_layout: &StateLayout<BK>, state_layout: &StateLayout<BK>,
@ -392,6 +587,50 @@ impl StatePartKind for StatePartKindSimOnlySlots {
) -> fmt::Result { ) -> fmt::Result {
write!(f, "{:?}", state.sim_only_slots[index]) write!(f, "{:?}", state.sim_only_slots[index])
} }
fn state_index<'a>(
state: &'a Self::State,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state.state[part_index.as_usize()]
}
fn state_index_mut<'a>(
state: &'a mut Self::State,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
state.modified[part_index.as_usize()] = true;
&mut state.state[part_index.as_usize()]
}
fn state_index_fetch_and_clear_maybe_modified_flag(
state: &mut Self::State,
part_index: StatePartIndex<Self>,
) -> bool {
std::mem::replace(&mut state.modified[part_index.as_usize()], false)
}
fn borrowed_state_index<'a, 'b>(
state: &'a Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a Self::StateElement {
&state.state[part_index.as_usize()]
}
fn borrowed_state_index_mut<'a, 'b>(
state: &'a mut Self::BorrowedState<'b>,
part_index: StatePartIndex<Self>,
) -> &'a mut Self::StateElement {
state.modified[part_index.as_usize()] = true;
&mut state.state[part_index.as_usize()]
}
fn borrowed_state_get_disjoint_mut<'a, 'b, const N: usize>(
state: &'a mut Self::BorrowedState<'b>,
part_indexes: [StatePartIndex<Self>; N],
) -> [&'a mut Self::StateElement; N] {
for part_index in part_indexes {
state.modified[part_index.as_usize()] = true;
}
state
.state
.get_disjoint_mut(part_indexes.map(StatePartIndex::as_usize))
.expect("indexes are disjoint")
}
} }
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]

View file

@ -15,7 +15,8 @@ use crate::{
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
CanonicalType, OpaqueSimValue, OpaqueSimValueSize, OpaqueSimValueSlice, CanonicalType, OpaqueSimValue, OpaqueSimValueSize, OpaqueSimValueSlice,
OpaqueSimValueWriter, StaticType, Type, TypeProperties, impl_match_variant_as_self, OpaqueSimValueWriter, SimValueDebug, StaticType, Type, TypeProperties,
impl_match_variant_as_self,
}, },
util::{ util::{
ConstUsize, HashMap, ConstUsize, HashMap,
@ -551,113 +552,119 @@ impl_sim_value_cmp_as_bool!(AsyncReset);
#[doc(hidden)] #[doc(hidden)]
pub mod match_sim_value { pub mod match_sim_value {
use crate::{ use crate::{sim::value::SimValue, ty::Type};
sim::value::{SimValue, ToSimValue}, use std::ops::{Deref, DerefMut};
ty::Type,
}; macro_rules! wrapper {
(
$(pub struct $wrapper:ident<$T:ident>($inner:ty);)*
) => {
$(#[doc(hidden)]
pub struct $wrapper<$T>($inner);
impl<$T> $wrapper<$T> {
#[inline(always)]
pub fn new(value: $T) -> Self {
Self(<$inner>::new(value))
}
}
impl<$T> Deref for $wrapper<$T> {
type Target = $inner;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<$T> DerefMut for $wrapper<$T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
})*
};
}
wrapper! {
pub struct MatchSimValueHelperCheckSimValue<T>(MatchSimValueHelperCheckMutSimValue<T>);
pub struct MatchSimValueHelperCheckMutSimValue<T>(MatchSimValueHelperCheckRefSimValue<T>);
pub struct MatchSimValueHelperCheckRefSimValue<T>(MatchSimValueHelperCheckRefRefSimValue<T>);
pub struct MatchSimValueHelperCheckRefRefSimValue<T>(MatchSimValueHelperCheckRefMutSimValue<T>);
pub struct MatchSimValueHelperCheckRefMutSimValue<T>(MatchSimValueHelperCheckMutRefSimValue<T>);
pub struct MatchSimValueHelperCheckMutRefSimValue<T>(MatchSimValueHelperCheckMutMutSimValue<T>);
pub struct MatchSimValueHelperCheckMutMutSimValue<T>(MatchSimValueHelperIdentity<T>);
}
impl<T: Type> MatchSimValueHelperCheckSimValue<SimValue<T>> {
#[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> T::SimValue {
SimValue::into_value(self.take())
}
}
impl<'a, T: Type> MatchSimValueHelperCheckMutSimValue<&'a mut SimValue<T>> {
#[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> &'a mut T::SimValue {
self.take()
}
}
impl<'a, T: Type> MatchSimValueHelperCheckRefSimValue<&'a SimValue<T>> {
#[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> &'a T::SimValue {
self.take()
}
}
impl<'a, 'b, T: Type> MatchSimValueHelperCheckRefRefSimValue<&'a &'b SimValue<T>> {
#[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> &'b T::SimValue {
self.take()
}
}
impl<'a, 'b, T: Type> MatchSimValueHelperCheckRefMutSimValue<&'a &'b mut SimValue<T>> {
#[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> &'a T::SimValue {
self.take()
}
}
impl<'a, 'b, T: Type> MatchSimValueHelperCheckMutRefSimValue<&'a mut &'b SimValue<T>> {
#[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> &'b T::SimValue {
self.take()
}
}
impl<'a, 'b, T: Type> MatchSimValueHelperCheckMutMutSimValue<&'a mut &'b mut SimValue<T>> {
#[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> &'a mut T::SimValue {
self.take()
}
}
#[doc(hidden)] #[doc(hidden)]
pub struct MatchSimValueHelper<T>(Option<T>); pub struct MatchSimValueHelperIdentity<T>(Option<T>);
impl<T> MatchSimValueHelper<T> { impl<T> MatchSimValueHelperIdentity<T> {
pub fn new(v: T) -> Self { fn new(v: T) -> Self {
Self(Some(v)) Self(Some(v))
} }
} #[inline(always)]
fn take(&mut self) -> T {
#[doc(hidden)] self.0.take().expect("known to be Some")
pub trait MatchSimValue {
type MatchValue;
/// use `self` so it comes first in the method resolution order
fn __fayalite_match_sim_value(self) -> Self::MatchValue
where
Self: Sized;
}
impl<T: Type> MatchSimValue for MatchSimValueHelper<SimValue<T>> {
type MatchValue = T::SimValue;
fn __fayalite_match_sim_value(self) -> Self::MatchValue {
SimValue::into_value(self.0.expect("should be Some"))
} }
} #[inline(always)]
pub fn __fayalite_match_sim_value(&mut self) -> T {
impl<'a, T: Type> MatchSimValue for MatchSimValueHelper<&'a SimValue<T>> { self.take()
type MatchValue = &'a T::SimValue;
fn __fayalite_match_sim_value(self) -> Self::MatchValue {
SimValue::value(self.0.expect("should be Some"))
}
}
impl<'a, T: Type> MatchSimValue for MatchSimValueHelper<&'a mut SimValue<T>> {
type MatchValue = &'a mut T::SimValue;
fn __fayalite_match_sim_value(self) -> Self::MatchValue {
SimValue::value_mut(self.0.expect("should be Some"))
}
}
impl<'a, T> MatchSimValue for MatchSimValueHelper<&'_ &'a T>
where
MatchSimValueHelper<&'a T>: MatchSimValue,
{
type MatchValue = <MatchSimValueHelper<&'a T> as MatchSimValue>::MatchValue;
fn __fayalite_match_sim_value(self) -> Self::MatchValue {
MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| *v)))
}
}
impl<'a, T> MatchSimValue for MatchSimValueHelper<&'_ mut &'a T>
where
MatchSimValueHelper<&'a T>: MatchSimValue,
{
type MatchValue = <MatchSimValueHelper<&'a T> as MatchSimValue>::MatchValue;
fn __fayalite_match_sim_value(self) -> Self::MatchValue {
MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| *v)))
}
}
impl<'a, T> MatchSimValue for MatchSimValueHelper<&'a &'_ mut T>
where
MatchSimValueHelper<&'a T>: MatchSimValue,
{
type MatchValue = <MatchSimValueHelper<&'a T> as MatchSimValue>::MatchValue;
fn __fayalite_match_sim_value(self) -> Self::MatchValue {
MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| &**v)))
}
}
impl<'a, T> MatchSimValue for MatchSimValueHelper<&'a mut &'_ mut T>
where
MatchSimValueHelper<&'a mut T>: MatchSimValue,
{
type MatchValue = <MatchSimValueHelper<&'a mut T> as MatchSimValue>::MatchValue;
fn __fayalite_match_sim_value(self) -> Self::MatchValue {
MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| &mut **v)))
} }
} }
#[doc(hidden)] #[doc(hidden)]
pub trait MatchSimValueFallback { pub type MatchSimValueHelper<T> = MatchSimValueHelperCheckSimValue<T>;
type MatchValue;
/// use `&mut self` so it comes later in the method resolution order than MatchSimValue
fn __fayalite_match_sim_value(&mut self) -> Self::MatchValue;
}
impl<T: ToSimValue> MatchSimValueFallback for MatchSimValueHelper<T> {
type MatchValue = <T::Type as Type>::SimValue;
fn __fayalite_match_sim_value(&mut self) -> Self::MatchValue {
SimValue::into_value(self.0.take().expect("should be Some").into_sim_value())
}
}
} }
pub trait ToSimValue: ToSimValueWithType<<Self as ValueType>::Type> + ValueType { pub trait ToSimValue: ToSimValueWithType<<Self as ValueType>::Type> + ValueType {
@ -1394,6 +1401,15 @@ impl Type for DynSimOnly {
} }
} }
impl SimValueDebug for DynSimOnly {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<T: SimOnlyValueTrait> Type for SimOnly<T> { impl<T: SimOnlyValueTrait> Type for SimOnly<T> {
type BaseType = DynSimOnly; type BaseType = DynSimOnly;
type MaskType = Bool; type MaskType = Bool;
@ -1459,6 +1475,15 @@ impl<T: SimOnlyValueTrait> Type for SimOnly<T> {
} }
} }
impl<T: SimOnlyValueTrait> SimValueDebug for SimOnly<T> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<T: SimOnlyValueTrait> StaticType for SimOnly<T> { impl<T: SimOnlyValueTrait> StaticType for SimOnly<T> {
const TYPE: Self = Self::new(); const TYPE: Self = Self::new();

View file

@ -21,14 +21,31 @@ use crate::{
}; };
use bitvec::{order::Lsb0, slice::BitSlice}; use bitvec::{order::Lsb0, slice::BitSlice};
use hashbrown::hash_map::Entry; use hashbrown::hash_map::Entry;
use sha2::{Digest, Sha256};
use std::{ use std::{
collections::BTreeMap,
fmt::{self, Write as _}, fmt::{self, Write as _},
io, mem, io, mem,
num::NonZeroU64,
}; };
#[derive(Default)] #[derive(Default, Clone)]
struct PathHash(Sha256);
impl PathHash {
fn joined(mut self, segment: impl AsRef<[u8]>) -> Self {
let segment = segment.as_ref();
self.0.update(u32::to_le_bytes(
segment.len().try_into().expect("path segment is too big"),
));
self.0.update(segment);
self
}
}
struct Scope { struct Scope {
last_inserted: HashMap<Interned<str>, usize>, last_inserted: HashMap<Interned<str>, usize>,
path_hash: PathHash,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -61,6 +78,13 @@ impl fmt::Display for VerilogIdentifier {
} }
impl Scope { impl Scope {
fn new(path_hash: PathHash) -> Self {
Self {
last_inserted: Default::default(),
path_hash,
}
}
fn new_identifier(&mut self, unescaped_name: Interned<str>) -> VerilogIdentifier { fn new_identifier(&mut self, unescaped_name: Interned<str>) -> VerilogIdentifier {
let next_disambiguator = match self.last_inserted.entry(unescaped_name) { let next_disambiguator = match self.last_inserted.entry(unescaped_name) {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
@ -163,6 +187,26 @@ impl<W: io::Write> fmt::Debug for VcdWriterDecls<W> {
} }
} }
/// pass in scope to ensure it's not available in child scope
fn try_write_vcd_scope<W: io::Write, R>(
writer: &mut W,
scope_type: &str,
scope_name: Interned<str>,
scope: Option<&mut Scope>,
f: impl FnOnce(&mut W, Option<&mut Scope>) -> io::Result<R>,
) -> io::Result<R> {
let Some(scope) = scope else {
return f(writer, None);
};
write_vcd_scope(
writer,
scope_type,
scope_name,
scope,
move |writer, scope| f(writer, Some(scope)),
)
}
/// pass in scope to ensure it's not available in child scope /// pass in scope to ensure it's not available in child scope
fn write_vcd_scope<W: io::Write, R>( fn write_vcd_scope<W: io::Write, R>(
writer: &mut W, writer: &mut W,
@ -171,12 +215,10 @@ fn write_vcd_scope<W: io::Write, R>(
scope: &mut Scope, scope: &mut Scope,
f: impl FnOnce(&mut W, &mut Scope) -> io::Result<R>, f: impl FnOnce(&mut W, &mut Scope) -> io::Result<R>,
) -> io::Result<R> { ) -> io::Result<R> {
writeln!( let path_hash = scope.path_hash.clone().joined(scope_name);
writer, let scope_name = scope.new_identifier(scope_name);
"$scope {scope_type} {} $end", writeln!(writer, "$scope {scope_type} {scope_name} $end")?;
scope.new_identifier(scope_name), let retval = f(writer, &mut Scope::new(path_hash))?;
)?;
let retval = f(writer, &mut Scope::default())?;
writeln!(writer, "$upscope $end")?; writeln!(writer, "$upscope $end")?;
Ok(retval) Ok(retval)
} }
@ -216,6 +258,7 @@ trait_arg! {
struct ArgModule<'a> { struct ArgModule<'a> {
properties: &'a mut VcdWriterProperties, properties: &'a mut VcdWriterProperties,
scope: &'a mut Scope, scope: &'a mut Scope,
instance_name: Option<Interned<str>>,
} }
impl<'a> ArgModule<'a> { impl<'a> ArgModule<'a> {
@ -223,6 +266,7 @@ impl<'a> ArgModule<'a> {
ArgModule { ArgModule {
properties: self.properties, properties: self.properties,
scope: self.scope, scope: self.scope,
instance_name: self.instance_name,
} }
} }
} }
@ -246,7 +290,7 @@ struct ArgInType<'a> {
sink_var_type: &'static str, sink_var_type: &'static str,
duplex_var_type: &'static str, duplex_var_type: &'static str,
properties: &'a mut VcdWriterProperties, properties: &'a mut VcdWriterProperties,
scope: &'a mut Scope, scope: Option<&'a mut Scope>,
} }
impl<'a> ArgInType<'a> { impl<'a> ArgInType<'a> {
@ -256,7 +300,7 @@ impl<'a> ArgInType<'a> {
sink_var_type: self.sink_var_type, sink_var_type: self.sink_var_type,
duplex_var_type: self.duplex_var_type, duplex_var_type: self.duplex_var_type,
properties: self.properties, properties: self.properties,
scope: self.scope, scope: self.scope.as_deref_mut(),
} }
} }
} }
@ -291,19 +335,78 @@ impl WriteTrace for TraceScalar {
} }
} }
fn write_vcd_id<W: io::Write>(writer: &mut W, mut id: usize) -> io::Result<()> { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
let min_char = b'!'; #[repr(transparent)]
let max_char = b'~'; struct VcdId(NonZeroU64);
let base = (max_char - min_char + 1) as usize;
loop { impl VcdId {
let digit = (id % base) as u8 + min_char; const CHAR_RANGE: std::ops::RangeInclusive<u8> = b'!'..=b'~';
id /= base; const BASE: u8 = *Self::CHAR_RANGE.end() - *Self::CHAR_RANGE.start() + 1;
writer.write_all(&[digit])?; const LOW_HALF_CHARS: u32 = 5;
if id == 0 { const LOW_HALF_MODULUS: u64 = (Self::BASE as u64).pow(Self::LOW_HALF_CHARS);
break;
const fn from_str(s: &str) -> Option<Self> {
if s.is_empty() {
return None;
} }
let mut retval = 0u64;
let mut bytes = s.as_bytes();
while let [ref rest @ .., digit] = *bytes {
bytes = rest;
let Some(digit) = digit.checked_sub(*Self::CHAR_RANGE.start()) else {
return None;
};
if digit >= Self::BASE {
return None;
}
let Some(v) = retval.checked_mul(Self::BASE as _) else {
return None;
};
let Some(v) = v.checked_add(digit as _) else {
return None;
};
retval = v;
}
let Some(retval) = NonZeroU64::new(retval) else {
return None;
};
Some(Self(retval))
} }
Ok(()) #[must_use]
const fn write(self, out: &mut [u8]) -> usize {
let mut id = self.0.get();
let mut len = 0;
loop {
let digit = (id % Self::BASE as u64) as u8 + *Self::CHAR_RANGE.start();
id /= Self::BASE as u64;
if len < out.len() {
out[len] = digit;
}
len += 1;
if id == 0 {
break;
}
}
len
}
const MAX_ID_LEN: usize = Self(NonZeroU64::MAX).write(&mut []);
}
/// check that VcdId properly round-trips
const _: () = {
let s = "RoundTrip";
let Some(id) = VcdId::from_str(s) else {
unreachable!();
};
let mut buf = [0u8; VcdId::MAX_ID_LEN];
let len = id.write(&mut buf);
assert!(crate::util::const_bytes_cmp(buf.split_at(len).0, s.as_bytes()).is_eq());
};
fn write_vcd_id<W: io::Write>(writer: &mut W, id: VcdId) -> io::Result<()> {
let mut buf = [0u8; VcdId::MAX_ID_LEN];
let len = id.write(&mut buf);
writer.write_all(&buf[..len])
} }
struct Escaped<T: fmt::Display>(T); struct Escaped<T: fmt::Display>(T);
@ -346,12 +449,13 @@ impl<T: fmt::Display> fmt::Display for Escaped<T> {
fn write_vcd_var<W: io::Write>( fn write_vcd_var<W: io::Write>(
properties: &mut VcdWriterProperties, properties: &mut VcdWriterProperties,
scope: Option<&mut Scope>,
memory_element_part_body: MemoryElementPartBody, memory_element_part_body: MemoryElementPartBody,
writer: &mut W, writer: &mut W,
var_type: &str, var_type: &str,
size: usize, size: usize,
location: TraceLocation, location: TraceLocation,
name: VerilogIdentifier, name: Interned<str>,
) -> io::Result<()> { ) -> io::Result<()> {
let id = match location { let id = match location {
TraceLocation::Scalar(id) => id.as_usize(), TraceLocation::Scalar(id) => id.as_usize(),
@ -384,9 +488,21 @@ fn write_vcd_var<W: io::Write>(
first_id + *element_index first_id + *element_index
} }
}; };
write!(writer, "$var {var_type} {size} ")?; if let Some(scope) = scope {
write_vcd_id(writer, id)?; let path_hash = scope.path_hash.clone().joined(name);
writeln!(writer, " {name} $end") let name = scope.new_identifier(name);
let id = properties
.scalar_id_to_vcd_id_map
.builder_get_or_insert(id, &path_hash);
write!(writer, "$var {var_type} {size} ")?;
write_vcd_id(writer, id)?;
writeln!(writer, " {name} $end")
} else {
properties
.scalar_id_to_vcd_id_map
.builder_unused_scalar_id(id);
Ok(())
}
} }
impl WriteTrace for TraceUInt { impl WriteTrace for TraceUInt {
@ -414,12 +530,13 @@ impl WriteTrace for TraceUInt {
} }
write_vcd_var( write_vcd_var(
properties, properties,
scope,
MemoryElementPartBody::Scalar, MemoryElementPartBody::Scalar,
writer, writer,
var_type, var_type,
ty.width(), ty.width(),
location, location,
scope.new_identifier(name), name,
) )
} }
} }
@ -494,12 +611,13 @@ impl WriteTrace for TraceEnumDiscriminant {
} = self; } = self;
write_vcd_var( write_vcd_var(
properties, properties,
scope,
MemoryElementPartBody::EnumDiscriminant { ty }, MemoryElementPartBody::EnumDiscriminant { ty },
writer, writer,
"string", "string",
1, 1,
location, location,
scope.new_identifier(name), name,
) )
} }
} }
@ -569,12 +687,13 @@ impl WriteTrace for TracePhantomConst {
} = self; } = self;
write_vcd_var( write_vcd_var(
properties, properties,
scope,
MemoryElementPartBody::Scalar, MemoryElementPartBody::Scalar,
writer, writer,
"string", "string",
1, 1,
location, location,
scope.new_identifier(name), name,
) )
} }
} }
@ -596,12 +715,13 @@ impl WriteTrace for TraceSimOnly {
} = self; } = self;
write_vcd_var( write_vcd_var(
properties, properties,
scope,
MemoryElementPartBody::Scalar, MemoryElementPartBody::Scalar,
writer, writer,
"string", "string",
1, 1,
location, location,
scope.new_identifier(name), name,
) )
} }
} }
@ -625,14 +745,24 @@ impl WriteTrace for TraceScope {
impl WriteTrace for TraceModule { impl WriteTrace for TraceModule {
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> { fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
let ArgModule { properties, scope } = arg.module(); let ArgModule {
properties,
scope,
instance_name,
} = arg.module();
let Self { name, children } = self; let Self { name, children } = self;
write_vcd_scope(writer, "module", name, scope, |writer, scope| { write_vcd_scope(
for child in children { writer,
child.write_trace(writer, ArgModuleBody { properties, scope })?; "module",
} instance_name.unwrap_or(name),
Ok(()) scope,
}) |writer, scope| {
for child in children {
child.write_trace(writer, ArgModuleBody { properties, scope })?;
}
Ok(())
},
)
} }
} }
@ -640,7 +770,7 @@ impl WriteTrace for TraceInstance {
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> { fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
let ArgModuleBody { properties, scope } = arg.module_body(); let ArgModuleBody { properties, scope } = arg.module_body();
let Self { let Self {
name: _, name,
instance_io, instance_io,
module, module,
ty: _, ty: _,
@ -652,10 +782,17 @@ impl WriteTrace for TraceInstance {
sink_var_type: "wire", sink_var_type: "wire",
duplex_var_type: "wire", duplex_var_type: "wire",
properties, properties,
scope, scope: None,
}, },
)?; )?;
module.write_trace(writer, ArgModule { properties, scope }) module.write_trace(
writer,
ArgModule {
properties,
scope,
instance_name: Some(name),
},
)
} }
} }
@ -694,7 +831,7 @@ impl WriteTrace for TraceMem {
sink_var_type: "reg", sink_var_type: "reg",
duplex_var_type: "reg", duplex_var_type: "reg",
properties, properties,
scope, scope: Some(scope),
}, },
) )
}, },
@ -726,7 +863,7 @@ impl WriteTrace for TraceMemPort {
sink_var_type: "wire", sink_var_type: "wire",
duplex_var_type: "wire", duplex_var_type: "wire",
properties, properties,
scope, scope: Some(scope),
}, },
) )
} }
@ -747,7 +884,7 @@ impl WriteTrace for TraceWire {
sink_var_type: "wire", sink_var_type: "wire",
duplex_var_type: "wire", duplex_var_type: "wire",
properties, properties,
scope, scope: Some(scope),
}, },
) )
} }
@ -768,7 +905,7 @@ impl WriteTrace for TraceReg {
sink_var_type: "reg", sink_var_type: "reg",
duplex_var_type: "reg", duplex_var_type: "reg",
properties, properties,
scope, scope: Some(scope),
}, },
) )
} }
@ -790,7 +927,7 @@ impl WriteTrace for TraceModuleIO {
sink_var_type: "wire", sink_var_type: "wire",
duplex_var_type: "wire", duplex_var_type: "wire",
properties, properties,
scope, scope: Some(scope),
}, },
) )
} }
@ -811,7 +948,7 @@ impl WriteTrace for TraceBundle {
ty: _, ty: _,
flow: _, flow: _,
} = self; } = self;
write_vcd_scope(writer, "struct", name, scope, |writer, scope| { try_write_vcd_scope(writer, "struct", name, scope, |writer, mut scope| {
for field in fields { for field in fields {
field.write_trace( field.write_trace(
writer, writer,
@ -820,7 +957,7 @@ impl WriteTrace for TraceBundle {
sink_var_type, sink_var_type,
duplex_var_type, duplex_var_type,
properties, properties,
scope, scope: scope.as_deref_mut(),
}, },
)?; )?;
} }
@ -844,7 +981,7 @@ impl WriteTrace for TraceArray {
ty: _, ty: _,
flow: _, flow: _,
} = self; } = self;
write_vcd_scope(writer, "struct", name, scope, |writer, scope| { try_write_vcd_scope(writer, "struct", name, scope, |writer, mut scope| {
for element in elements { for element in elements {
element.write_trace( element.write_trace(
writer, writer,
@ -853,7 +990,7 @@ impl WriteTrace for TraceArray {
sink_var_type, sink_var_type,
duplex_var_type, duplex_var_type,
properties, properties,
scope, scope: scope.as_deref_mut(),
}, },
)?; )?;
} }
@ -878,7 +1015,7 @@ impl WriteTrace for TraceEnumWithFields {
ty: _, ty: _,
flow: _, flow: _,
} = self; } = self;
write_vcd_scope(writer, "struct", name, scope, |writer, scope| { try_write_vcd_scope(writer, "struct", name, scope, |writer, mut scope| {
discriminant.write_trace( discriminant.write_trace(
writer, writer,
ArgInType { ArgInType {
@ -886,7 +1023,7 @@ impl WriteTrace for TraceEnumWithFields {
sink_var_type, sink_var_type,
duplex_var_type, duplex_var_type,
properties, properties,
scope, scope: scope.as_deref_mut(),
}, },
)?; )?;
for field in non_empty_fields { for field in non_empty_fields {
@ -897,7 +1034,7 @@ impl WriteTrace for TraceEnumWithFields {
sink_var_type, sink_var_type,
duplex_var_type, duplex_var_type,
properties, properties,
scope, scope: scope.as_deref_mut(),
}, },
)?; )?;
} }
@ -923,6 +1060,9 @@ impl<W: io::Write> TraceWriterDecls for VcdWriterDecls<W> {
writeln!(writer, "$timescale {} $end", vcd_timescale(timescale))?; writeln!(writer, "$timescale {} $end", vcd_timescale(timescale))?;
let mut properties = VcdWriterProperties { let mut properties = VcdWriterProperties {
next_scalar_id: trace_scalar_id_count, next_scalar_id: trace_scalar_id_count,
scalar_id_to_vcd_id_map: ScalarIdToVcdIdMapOrBuilder::Builder(
ScalarIdToVcdIdMapBuilder::default(),
),
memory_properties: (0..trace_memory_id_count) memory_properties: (0..trace_memory_id_count)
.map(|_| MemoryProperties { .map(|_| MemoryProperties {
element_parts: Vec::with_capacity(8), element_parts: Vec::with_capacity(8),
@ -935,9 +1075,17 @@ impl<W: io::Write> TraceWriterDecls for VcdWriterDecls<W> {
&mut writer, &mut writer,
ArgModule { ArgModule {
properties: &mut properties, properties: &mut properties,
scope: &mut Scope::default(), scope: &mut Scope::new(PathHash::default()),
instance_name: None,
}, },
)?; )?;
let ScalarIdToVcdIdMapOrBuilder::Builder(scalar_id_to_vcd_id_map_builder) =
properties.scalar_id_to_vcd_id_map
else {
unreachable!();
};
properties.scalar_id_to_vcd_id_map =
ScalarIdToVcdIdMapOrBuilder::Built(scalar_id_to_vcd_id_map_builder.build());
writeln!(writer, "$enddefinitions $end")?; writeln!(writer, "$enddefinitions $end")?;
writeln!(writer, "$dumpvars")?; writeln!(writer, "$dumpvars")?;
Ok(VcdWriter { Ok(VcdWriter {
@ -967,8 +1115,100 @@ struct MemoryProperties {
element_index: usize, element_index: usize,
} }
struct ScalarIdToVcdIdMap {
scalar_id_to_vcd_id_map: Box<[Option<VcdId>]>,
}
#[derive(Default)]
struct ScalarIdToVcdIdMapBuilder {
scalar_id_to_vcd_id_map: BTreeMap<usize, Option<VcdId>>,
lower_half_to_next_upper_half_map: HashMap<u64, u64>,
}
impl ScalarIdToVcdIdMapBuilder {
fn unused_scalar_id(&mut self, scalar_id: usize) {
self.scalar_id_to_vcd_id_map
.entry(scalar_id)
.or_insert(None);
}
/// `VcdId`s are based off of `path_hash` (and not `scalar_id`) since the hash doesn't change
/// when unrelated variables are added/removed, making the generated VCD more friendly for git diff.
fn get_or_insert(&mut self, scalar_id: usize, path_hash: &PathHash) -> VcdId {
*self
.scalar_id_to_vcd_id_map
.entry(scalar_id)
.or_insert(None)
.get_or_insert_with(|| {
let hash = u128::from_le_bytes(
*path_hash
.0
.clone()
.finalize()
.first_chunk()
.expect("known to be bigger than u128"),
);
let lower_half = (hash % VcdId::LOW_HALF_MODULUS as u128) as u64;
let next_upper_half = self
.lower_half_to_next_upper_half_map
.entry(lower_half)
.or_insert(if lower_half == 0 { 1 } else { 0 });
let upper_half = *next_upper_half;
*next_upper_half += 1;
let Some(id) = upper_half
.checked_mul(VcdId::LOW_HALF_MODULUS)
.and_then(|v| v.checked_add(lower_half))
else {
panic!("too many VcdIds");
};
VcdId(NonZeroU64::new(id).expect("known to not be zero"))
})
}
fn build(self) -> ScalarIdToVcdIdMap {
ScalarIdToVcdIdMap {
scalar_id_to_vcd_id_map: self
.scalar_id_to_vcd_id_map
.into_iter()
.enumerate()
.map(|(index, (scalar_id, vcd_id))| {
if index != scalar_id {
panic!("missing scalar id {index}");
}
vcd_id
})
.collect(),
}
}
}
enum ScalarIdToVcdIdMapOrBuilder {
Builder(ScalarIdToVcdIdMapBuilder),
Built(ScalarIdToVcdIdMap),
}
impl ScalarIdToVcdIdMapOrBuilder {
fn built_scalar_id_to_vcd_id(&self, scalar_id: usize) -> Option<VcdId> {
let Self::Built(v) = self else {
panic!("ScalarIdToVcdIdMap isn't built yet");
};
v.scalar_id_to_vcd_id_map[scalar_id]
}
fn builder_get_or_insert(&mut self, scalar_id: usize, path_hash: &PathHash) -> VcdId {
let Self::Builder(v) = self else {
panic!("ScalarIdToVcdIdMap is already built");
};
v.get_or_insert(scalar_id, path_hash)
}
fn builder_unused_scalar_id(&mut self, scalar_id: usize) {
let Self::Builder(v) = self else {
panic!("ScalarIdToVcdIdMap is already built");
};
v.unused_scalar_id(scalar_id)
}
}
struct VcdWriterProperties { struct VcdWriterProperties {
next_scalar_id: usize, next_scalar_id: usize,
scalar_id_to_vcd_id_map: ScalarIdToVcdIdMapOrBuilder,
memory_properties: Box<[MemoryProperties]>, memory_properties: Box<[MemoryProperties]>,
} }
@ -988,8 +1228,11 @@ impl<W: io::Write + 'static> VcdWriter<W> {
fn write_string_value_change( fn write_string_value_change(
writer: &mut impl io::Write, writer: &mut impl io::Write,
value: impl fmt::Display, value: impl fmt::Display,
id: usize, id: Option<VcdId>,
) -> io::Result<()> { ) -> io::Result<()> {
let Some(id) = id else {
return Ok(());
};
write!(writer, "s{} ", Escaped(value))?; write!(writer, "s{} ", Escaped(value))?;
write_vcd_id(writer, id)?; write_vcd_id(writer, id)?;
writer.write_all(b"\n") writer.write_all(b"\n")
@ -998,8 +1241,11 @@ fn write_string_value_change(
fn write_bits_value_change( fn write_bits_value_change(
writer: &mut impl io::Write, writer: &mut impl io::Write,
value: &BitSlice, value: &BitSlice,
id: usize, id: Option<VcdId>,
) -> io::Result<()> { ) -> io::Result<()> {
let Some(id) = id else {
return Ok(());
};
match value.len() { match value.len() {
0 => writer.write_all(b"s0 ")?, 0 => writer.write_all(b"s0 ")?,
1 => writer.write_all(if value[0] { b"1" } else { b"0" })?, 1 => writer.write_all(if value[0] { b"1" } else { b"0" })?,
@ -1028,7 +1274,7 @@ fn write_enum_discriminant_value_change(
writer: &mut impl io::Write, writer: &mut impl io::Write,
variant_index: usize, variant_index: usize,
ty: Enum, ty: Enum,
id: usize, id: Option<VcdId>,
) -> io::Result<()> { ) -> io::Result<()> {
write_string_value_change( write_string_value_change(
writer, writer,
@ -1063,7 +1309,9 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
MemoryElementPartBody::Scalar => write_bits_value_change( MemoryElementPartBody::Scalar => write_bits_value_change(
&mut self.writer, &mut self.writer,
&element_data[start..start + len], &element_data[start..start + len],
first_id + element_index, self.properties
.scalar_id_to_vcd_id_map
.built_scalar_id_to_vcd_id(first_id + element_index),
)?, )?,
MemoryElementPartBody::EnumDiscriminant { ty } => { MemoryElementPartBody::EnumDiscriminant { ty } => {
let mut variant_index = 0; let mut variant_index = 0;
@ -1073,7 +1321,9 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
&mut self.writer, &mut self.writer,
variant_index, variant_index,
*ty, *ty,
first_id + element_index, self.properties
.scalar_id_to_vcd_id_map
.built_scalar_id_to_vcd_id(first_id + element_index),
)? )?
} }
} }
@ -1082,11 +1332,23 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
} }
fn set_signal_uint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> { fn set_signal_uint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
write_bits_value_change(&mut self.writer, value, id.as_usize()) write_bits_value_change(
&mut self.writer,
value,
self.properties
.scalar_id_to_vcd_id_map
.built_scalar_id_to_vcd_id(id.as_usize()),
)
} }
fn set_signal_sint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> { fn set_signal_sint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
write_bits_value_change(&mut self.writer, value, id.as_usize()) write_bits_value_change(
&mut self.writer,
value,
self.properties
.scalar_id_to_vcd_id_map
.built_scalar_id_to_vcd_id(id.as_usize()),
)
} }
fn finish_init(&mut self) -> Result<(), Self::Error> { fn finish_init(&mut self) -> Result<(), Self::Error> {
@ -1118,7 +1380,14 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
variant_index: usize, variant_index: usize,
ty: Enum, ty: Enum,
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
write_enum_discriminant_value_change(&mut self.writer, variant_index, ty, id.as_usize()) write_enum_discriminant_value_change(
&mut self.writer,
variant_index,
ty,
self.properties
.scalar_id_to_vcd_id_map
.built_scalar_id_to_vcd_id(id.as_usize()),
)
} }
fn set_signal_phantom_const( fn set_signal_phantom_const(
@ -1128,7 +1397,13 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
// avoid multi-line strings because GTKWave can't display them properly: // avoid multi-line strings because GTKWave can't display them properly:
// https://github.com/gtkwave/gtkwave/issues/460 // https://github.com/gtkwave/gtkwave/issues/460
write_string_value_change(&mut self.writer, format_args!("{ty:?}"), id.as_usize()) write_string_value_change(
&mut self.writer,
format_args!("{ty:?}"),
self.properties
.scalar_id_to_vcd_id_map
.built_scalar_id_to_vcd_id(id.as_usize()),
)
} }
fn set_signal_sim_only_value( fn set_signal_sim_only_value(
@ -1136,7 +1411,13 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
id: TraceScalarId, id: TraceScalarId,
value: &DynSimOnlyValue, value: &DynSimOnlyValue,
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
write_string_value_change(&mut self.writer, format_args!("{value:?}"), id.as_usize()) write_string_value_change(
&mut self.writer,
format_args!("{value:?}"),
self.properties
.scalar_id_to_vcd_id_map
.built_scalar_id_to_vcd_id(id.as_usize()),
)
} }
} }
@ -1161,7 +1442,7 @@ mod tests {
#[test] #[test]
fn test_scope() { fn test_scope() {
let mut scope = Scope::default(); let mut scope = Scope::new(PathHash::default());
assert_eq!(&*scope.new_identifier("foo".intern()).unescaped_name, "foo"); assert_eq!(&*scope.new_identifier("foo".intern()).unescaped_name, "foo");
assert_eq!( assert_eq!(
&*scope.new_identifier("foo_0".intern()).unescaped_name, &*scope.new_identifier("foo_0".intern()).unescaped_name,

View file

@ -367,7 +367,15 @@ impl<D: Type> TypeOrDefault<D> for crate::__ {
} }
pub trait Type: pub trait Type:
Copy + Hash + Eq + fmt::Debug + Send + Sync + 'static + FillInDefaultedGenerics<Type = Self> Copy
+ Hash
+ Eq
+ fmt::Debug
+ Send
+ Sync
+ 'static
+ FillInDefaultedGenerics<Type = Self>
+ SimValueDebug
{ {
type BaseType: BaseType; type BaseType: BaseType;
type MaskType: Type<MaskType = Self::MaskType>; type MaskType: Type<MaskType = Self::MaskType>;
@ -402,6 +410,16 @@ pub trait Type:
) -> OpaqueSimValueWritten<'w>; ) -> OpaqueSimValueWritten<'w>;
} }
pub trait SimValueDebug {
fn sim_value_debug(value: &<Self as Type>::SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result
where
Self: Type;
}
pub trait SimValueDisplay: Type {
fn sim_value_display(value: &Self::SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}
pub trait BaseType: pub trait BaseType:
Type< Type<
BaseType = Self, BaseType = Self,
@ -490,6 +508,15 @@ impl Type for CanonicalType {
} }
} }
impl SimValueDebug for CanonicalType {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Default)] #[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Default)]
#[non_exhaustive] #[non_exhaustive]
pub struct OpaqueSimValueSizeRange { pub struct OpaqueSimValueSizeRange {

View file

@ -41,7 +41,7 @@ pub use misc::{
os_str_strip_suffix, serialize_to_json_ascii, serialize_to_json_ascii_pretty, os_str_strip_suffix, serialize_to_json_ascii, serialize_to_json_ascii_pretty,
serialize_to_json_ascii_pretty_with_indent, slice_range, try_slice_range, serialize_to_json_ascii_pretty_with_indent, slice_range, try_slice_range,
}; };
pub(crate) use misc::{InternedStrCompareAsStr, chain}; pub(crate) use misc::{InternedStrCompareAsStr, chain, copy_le_bytes_to_bitslice};
pub mod job_server; pub mod job_server;
pub mod prefix_sum; pub mod prefix_sum;

View file

@ -612,3 +612,43 @@ impl std::borrow::Borrow<str> for InternedStrCompareAsStr {
&self.0 &self.0
} }
} }
pub(crate) fn copy_le_bytes_to_bitslice(
dest: &mut BitSlice<usize, Lsb0>,
bytes: &[u8],
msb_fill: bool,
) {
let (chunks, remainder) = bytes.as_chunks();
let mut filled_to = 0;
for (i, chunk) in chunks.iter().enumerate() {
if let Some(start_bit_index) = i.checked_mul(usize::BITS as usize)
&& start_bit_index < dest.len()
{
let end_bit_index = start_bit_index
.saturating_add(usize::BITS as usize)
.min(dest.len());
let bit_len = end_bit_index - start_bit_index;
let chunk = usize::from_le_bytes(*chunk);
dest[start_bit_index..end_bit_index].copy_from_bitslice(&chunk.view_bits()[..bit_len]);
filled_to = end_bit_index;
} else {
break;
}
}
if !remainder.is_empty() {
if let Some(start_bit_index) = chunks.len().checked_mul(usize::BITS as usize)
&& start_bit_index < dest.len()
{
let end_bit_index = start_bit_index
.saturating_add(usize::BITS as usize)
.min(dest.len());
let bit_len = end_bit_index - start_bit_index;
let mut chunk = [if msb_fill { !0 } else { 0 }; _];
chunk[..remainder.len()].copy_from_slice(remainder);
let chunk = usize::from_le_bytes(chunk);
dest[start_bit_index..end_bit_index].copy_from_bitslice(&chunk.view_bits()[..bit_len]);
filled_to = end_bit_index;
}
}
dest[filled_to..].fill(msb_fill);
}

View file

@ -244,3 +244,13 @@ pub struct MyTypeWithPrivateMembersWithArg<T> {
pub(crate) b: MyPubCrateTypeWithArg<T>, pub(crate) b: MyPubCrateTypeWithArg<T>,
pub c: T, pub c: T,
} }
#[hdl(outline_generated)]
pub enum EnumWithOnlyOneVariant {
A,
}
#[hdl(outline_generated)]
pub enum EnumWithOnlyOneVariant2<T> {
A(T),
}

View file

@ -0,0 +1,166 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use fayalite::{prelude::*, ty::SimValueDebug};
use std::fmt;
#[hdl(outline_generated)]
struct MyStruct0<T, S: Size> {
v: T,
a: ArrayType<UInt<8>, S>,
}
#[hdl]
#[test]
fn check_my_struct0() {
let ty = MyStruct0[UInt[8]][3];
assert_eq!(
format!("{ty:?}"),
"MyStruct0 { v: UInt<8>, a: Array<UInt<8>, 3> }",
);
assert_eq!(
format!("{:?}", ty.mask_type()),
"MaskType<MyStruct0> { v: Bool, a: Array<Bool, 3> }",
);
let v = #[hdl(sim)]
MyStruct0::<_, _> {
v: 0x23u8,
a: [1u8, 2, 3],
};
assert_eq!(
format!("{v:?}"),
"MyStruct0 { v: 0x23_u8, a: [0x1_u8, 0x2_u8, 0x3_u8] }",
);
}
#[hdl(outline_generated, custom_debug())]
struct MyStruct1<T, S: Size> {
v: T,
a: ArrayType<UInt<8>, S>,
}
impl<T: Type, S: Size> fmt::Debug for MyStruct1<T, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { v, a } = self;
f.debug_struct("Custom<MyStruct1>")
.field("v", v)
.field("a", a)
.finish()
}
}
impl<T: Type, S: Size> SimValueDebug for MyStruct1<T, S> {
#[hdl]
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
#[hdl(sim)]
let Self { v, a } = value;
f.debug_struct("Custom<MyStruct1>")
.field("v", &v)
.field("a", &a)
.finish()
}
}
#[hdl]
#[test]
fn check_my_struct1() {
let ty = MyStruct1[UInt[8]][3];
assert_eq!(
format!("{ty:?}"),
"Custom<MyStruct1> { v: UInt<8>, a: Array<UInt<8>, 3> }",
);
assert_eq!(
format!("{:?}", ty.mask_type()),
"MaskType<MyStruct1> { v: Bool, a: Array<Bool, 3> }",
);
let v = #[hdl(sim)]
MyStruct1::<_, _> {
v: 0x23u8,
a: [1u8, 2, 3],
};
assert_eq!(
format!("{v:?}"),
"Custom<MyStruct1> { v: 0x23_u8, a: [0x1_u8, 0x2_u8, 0x3_u8] }",
);
}
#[hdl(outline_generated)]
enum MyEnum0<T, S: Size> {
Unit,
V(T),
A(ArrayType<UInt<8>, S>),
}
#[hdl]
#[test]
fn check_my_enum0() {
let ty = MyEnum0[UInt[8]][3];
assert_eq!(
format!("{ty:?}"),
"MyEnum0 { Unit: (), V: UInt<8>, A: Array<UInt<8>, 3> }",
);
let v = #[hdl(sim)]
ty.Unit();
assert_eq!(format!("{v:?}"), "Unit");
let v = #[hdl(sim)]
ty.V(0x23u8);
assert_eq!(format!("{v:?}"), "V(0x23_u8)");
let v = #[hdl(sim)]
ty.A([1u8, 2, 3]);
assert_eq!(format!("{v:?}"), "A([0x1_u8, 0x2_u8, 0x3_u8])");
}
#[hdl(outline_generated, custom_debug())]
enum MyEnum1<T, S: Size> {
Unit,
V(T),
A(ArrayType<UInt<8>, S>),
}
impl<T: Type, S: Size> fmt::Debug for MyEnum1<T, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { Unit, V, A } = self;
f.debug_struct("Custom<MyEnum1>")
.field("Unit", Unit)
.field("V", V)
.field("A", A)
.finish()
}
}
impl<T: Type, S: Size> SimValueDebug for MyEnum1<T, S> {
#[hdl]
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
type SimValueT<T> = <T as Type>::SimValue;
match value {
SimValueT::<Self>::Unit(_) => f.write_str("MyEnum1::Unit"),
SimValueT::<Self>::V(v, _) => f.debug_tuple("MyEnum1::V").field(v).finish(),
SimValueT::<Self>::A(a, _) => f.debug_tuple("MyEnum1::A").field(a).finish(),
SimValueT::<Self>::Unknown(_) => f.write_str("MyEnum1::Unknown"),
}
}
}
#[hdl]
#[test]
fn check_my_enum1() {
let ty = MyEnum1[UInt[8]][3];
assert_eq!(
format!("{ty:?}"),
"Custom<MyEnum1> { Unit: (), V: UInt<8>, A: Array<UInt<8>, 3> }",
);
let v = #[hdl(sim)]
ty.Unit();
assert_eq!(format!("{v:?}"), "MyEnum1::Unit");
let v = #[hdl(sim)]
ty.V(0x23u8);
assert_eq!(format!("{v:?}"), "MyEnum1::V(0x23_u8)");
let v = #[hdl(sim)]
ty.A([1u8, 2, 3]);
assert_eq!(format!("{v:?}"), "MyEnum1::A([0x1_u8, 0x2_u8, 0x3_u8])");
}

View file

@ -13,7 +13,7 @@ use fayalite::{
}; };
use serde_json::json; use serde_json::json;
#[hdl(outline_generated)] #[hdl(outline_generated, cmp_eq)]
pub enum TestEnum { pub enum TestEnum {
A, A,
B(UInt<8>), B(UInt<8>),
@ -679,6 +679,366 @@ circuit check_enum_literals:
}; };
} }
#[hdl_module(outline_generated)]
pub fn check_enum_cmp_eq() {
#[hdl]
let lhs: TestEnum = m.input();
#[hdl]
let rhs: TestEnum = m.input();
#[hdl]
let eq: Bool = m.output();
connect(eq, lhs.cmp_eq(rhs));
}
#[test]
fn test_enum_cmp_eq() {
let _n = SourceLocation::normalize_files_for_tests();
let m = check_enum_cmp_eq();
dbg!(m);
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
options: ExportOptions {
simplify_enums: None,
..ExportOptions::default()
},
"/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0
circuit check_enum_cmp_eq:
type Ty0 = {|A, B: UInt<8>, C: UInt<1>[3]|}
module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1]
input lhs: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input rhs: Ty0 @[module-XXXXXXXXXX.rs 3:1]
output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1]
wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1]
match lhs: @[module-XXXXXXXXXX.rs 5:1]
A:
match rhs: @[module-XXXXXXXXXX.rs 5:1]
A:
connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1]
B(_match_arm_value):
skip
C(_match_arm_value_1):
skip
B(_match_arm_value_2):
match rhs: @[module-XXXXXXXXXX.rs 5:1]
A:
skip
B(_match_arm_value_3):
connect TestEnum_cmp_eq, eq(_match_arm_value_2, _match_arm_value_3) @[module-XXXXXXXXXX.rs 5:1]
C(_match_arm_value_4):
skip
C(_match_arm_value_5):
match rhs: @[module-XXXXXXXXXX.rs 5:1]
A:
skip
B(_match_arm_value_6):
skip
C(_match_arm_value_7):
wire _array_literal_expr: UInt<1>[3]
connect _array_literal_expr[0], eq(_match_arm_value_5[0], _match_arm_value_7[0])
connect _array_literal_expr[1], eq(_match_arm_value_5[1], _match_arm_value_7[1])
connect _array_literal_expr[2], eq(_match_arm_value_5[2], _match_arm_value_7[2])
wire _cast_array_to_bits_expr: UInt<1>[3]
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
connect _cast_array_to_bits_expr[2], _array_literal_expr[2]
wire _cast_to_bits_expr: UInt<3>
connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0]))
connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1]
connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1]
",
};
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
options: ExportOptions {
simplify_enums: Some(SimplifyEnumsKind::SimplifyToEnumsWithNoBody),
..ExportOptions::default()
},
"/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0
circuit check_enum_cmp_eq:
type Ty0 = {|A, B, C|}
type Ty1 = {tag: Ty0, body: UInt<8>}
module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1]
input lhs: Ty1 @[module-XXXXXXXXXX.rs 2:1]
input rhs: Ty1 @[module-XXXXXXXXXX.rs 3:1]
output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1]
wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1]
match lhs.tag: @[module-XXXXXXXXXX.rs 5:1]
A:
match rhs.tag: @[module-XXXXXXXXXX.rs 5:1]
A:
connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1]
B:
skip
C:
skip
B:
match rhs.tag: @[module-XXXXXXXXXX.rs 5:1]
A:
skip
B:
connect TestEnum_cmp_eq, eq(bits(lhs.body, 7, 0), bits(rhs.body, 7, 0)) @[module-XXXXXXXXXX.rs 5:1]
C:
skip
C:
match rhs.tag: @[module-XXXXXXXXXX.rs 5:1]
A:
skip
B:
skip
C:
wire _array_literal_expr: UInt<1>[3]
wire _cast_bits_to_array_expr: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened[0], bits(bits(lhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0]
connect _cast_bits_to_array_expr_flattened[1], bits(bits(lhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1]
connect _cast_bits_to_array_expr_flattened[2], bits(bits(lhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2]
wire _cast_bits_to_array_expr_1: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(rhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0]
connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(rhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1]
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
wire _cast_bits_to_array_expr_2: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0]
connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1]
connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2]
wire _cast_bits_to_array_expr_3: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0]
connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1]
connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2]
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1])
wire _cast_bits_to_array_expr_4: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0]
connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1]
connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2]
wire _cast_bits_to_array_expr_5: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0]
connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1]
connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2]
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2])
wire _cast_array_to_bits_expr: UInt<1>[3]
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
connect _cast_array_to_bits_expr[2], _array_literal_expr[2]
wire _cast_to_bits_expr: UInt<3>
connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0]))
connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1]
connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1]
",
};
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
options: ExportOptions {
simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
..ExportOptions::default()
},
"/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0
circuit check_enum_cmp_eq:
type Ty0 = {tag: UInt<2>, body: UInt<8>}
module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1]
input lhs: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input rhs: Ty0 @[module-XXXXXXXXXX.rs 3:1]
output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1]
wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1]
when eq(lhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1]
else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
skip
else when eq(lhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
skip
else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, eq(bits(lhs.body, 7, 0), bits(rhs.body, 7, 0)) @[module-XXXXXXXXXX.rs 5:1]
else when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
skip
else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
skip
else:
wire _array_literal_expr: UInt<1>[3]
wire _cast_bits_to_array_expr: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened[0], bits(bits(lhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0]
connect _cast_bits_to_array_expr_flattened[1], bits(bits(lhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1]
connect _cast_bits_to_array_expr_flattened[2], bits(bits(lhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2]
wire _cast_bits_to_array_expr_1: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(rhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0]
connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(rhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1]
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
wire _cast_bits_to_array_expr_2: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0]
connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1]
connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2]
wire _cast_bits_to_array_expr_3: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0]
connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1]
connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2]
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1])
wire _cast_bits_to_array_expr_4: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0]
connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1]
connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2]
wire _cast_bits_to_array_expr_5: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0)
connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0]
connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1)
connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1]
connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2)
connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2]
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2])
wire _cast_array_to_bits_expr: UInt<1>[3]
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
connect _cast_array_to_bits_expr[2], _array_literal_expr[2]
wire _cast_to_bits_expr: UInt<3>
connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0]))
connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1]
connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1]
",
};
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
options: ExportOptions {
simplify_enums: Some(SimplifyEnumsKind::ReplaceWithUInt),
..ExportOptions::default()
},
"/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0
circuit check_enum_cmp_eq:
module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1]
input lhs: UInt<10> @[module-XXXXXXXXXX.rs 2:1]
input rhs: UInt<10> @[module-XXXXXXXXXX.rs 3:1]
output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1]
wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1]
when eq(bits(lhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1]
else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
skip
else when eq(bits(lhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
skip
else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
connect TestEnum_cmp_eq, eq(bits(bits(lhs, 9, 2), 7, 0), bits(bits(rhs, 9, 2), 7, 0)) @[module-XXXXXXXXXX.rs 5:1]
else when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1]
skip
else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1]
skip
else:
wire _array_literal_expr: UInt<1>[3]
wire _cast_bits_to_array_expr: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0)
connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0]
connect _cast_bits_to_array_expr_flattened[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1)
connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1]
connect _cast_bits_to_array_expr_flattened[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2)
connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2]
wire _cast_bits_to_array_expr_1: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0)
connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0]
connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1)
connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1]
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2)
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
wire _cast_bits_to_array_expr_2: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0)
connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0]
connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1)
connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1]
connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2)
connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2]
wire _cast_bits_to_array_expr_3: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0)
connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0]
connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1)
connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1]
connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2)
connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2]
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1])
wire _cast_bits_to_array_expr_4: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0)
connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0]
connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1)
connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1]
connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2)
connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2]
wire _cast_bits_to_array_expr_5: UInt<1>[3]
wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3]
connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0)
connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0]
connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1)
connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1]
connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2)
connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2]
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2])
wire _cast_array_to_bits_expr: UInt<1>[3]
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
connect _cast_array_to_bits_expr[2], _array_literal_expr[2]
wire _cast_to_bits_expr: UInt<3>
connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0]))
connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1]
connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1]
",
};
}
#[hdl_module(outline_generated)] #[hdl_module(outline_generated)]
pub fn check_struct_enum_match() { pub fn check_struct_enum_match() {
#[hdl] #[hdl]

View file

@ -7,7 +7,7 @@ use fayalite::{
prelude::*, prelude::*,
reset::ResetType, reset::ResetType,
sim::vcd::VcdWriterDecls, sim::vcd::VcdWriterDecls,
util::RcWriter, util::{RcWriter, ready_valid::queue},
}; };
use std::{collections::BTreeMap, num::NonZeroUsize, rc::Rc}; use std::{collections::BTreeMap, num::NonZeroUsize, rc::Rc};
@ -2495,3 +2495,349 @@ fn test_sim_read_past() {
panic!(); panic!();
} }
} }
#[hdl_module(outline_generated)]
pub fn last_connect() {
#[hdl]
let inp: HdlOption<Array<Bool, 4>> = m.input();
#[hdl]
let out: HdlOption<UInt<8>> = m.output();
connect(out, HdlNone());
#[hdl]
if let HdlSome(v) = inp {
#[hdl]
let w = wire();
connect(out, HdlSome(w));
connect(w, v.len() as u8);
for (i, v) in v.into_iter().enumerate() {
#[hdl]
if v {
connect(w, i as u8);
}
}
}
}
#[hdl]
#[test]
fn test_last_connect() {
let _n = SourceLocation::normalize_files_for_tests();
let mut sim = Simulation::new(last_connect());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
let bools = [false, true];
sim.write(sim.io().inp, HdlNone());
sim.advance_time(SimDuration::from_micros(1));
let expected: SimValue<HdlOption<UInt<8>>> = #[hdl(sim)]
HdlNone();
assert_eq!(sim.read(sim.io().out), expected);
for a in bools {
for b in bools {
for c in bools {
for d in bools {
let inp = [a, b, c, d];
sim.write(sim.io().inp, HdlSome(inp));
sim.advance_time(SimDuration::from_micros(1));
let mut expected = inp.len() as u8;
for (i, v) in inp.into_iter().enumerate() {
if v {
expected = i as u8;
}
}
let expected: SimValue<HdlOption<UInt<8>>> = #[hdl(sim)]
HdlSome(expected);
let out = sim.read(sim.io().out);
println!("expected={expected:?} out={out:?} inp={inp:?}");
assert_eq!(expected, out);
}
}
}
}
sim.flush_traces().unwrap();
let vcd = String::from_utf8(writer.take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
if vcd != include_str!("sim/expected/last_connect.vcd") {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != include_str!("sim/expected/last_connect.txt") {
panic!();
}
}
#[track_caller]
#[hdl]
fn test_queue_helper(
capacity: usize,
inp_ready_is_comb: bool,
out_valid_is_comb: bool,
expected_vcd: &str,
expected_sim_debug: &str,
) {
let _n = SourceLocation::normalize_files_for_tests();
let mut sim = Simulation::new(queue(
UInt::<8>::new_static(),
NonZeroUsize::new(capacity).expect("capacity should be non-zero"),
inp_ready_is_comb,
out_valid_is_comb,
));
let writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
struct DumpVcdOnDrop {
writer: Option<RcWriter>,
}
impl Drop for DumpVcdOnDrop {
fn drop(&mut self) {
if let Some(mut writer) = self.writer.take() {
let vcd = String::from_utf8(writer.take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
}
}
}
let mut writer = DumpVcdOnDrop {
writer: Some(writer),
};
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
let mut input_value = 0u8;
let mut expected_output_value = 0u8;
/// deterministic random numbers
fn rand(mut v: u32) -> bool {
// random 32-bit primes
v = v.wrapping_mul(0xF807B7EF).rotate_left(16);
v ^= 0xA1E24BBA; // random 32-bit constant
v = v.wrapping_mul(0xE9D30017).rotate_left(16);
v = v.wrapping_mul(0x3895AFFB).rotate_left(16);
v & 1 != 0
}
for cycle in 0..100u32 {
println!("cycle: {cycle}");
sim.write(
sim.io().inp.data,
if rand(cycle) {
#[hdl(sim)]
HdlSome(input_value)
} else {
#[hdl(sim)]
HdlNone()
},
);
sim.write_bool(sim.io().out.ready, rand(u32::MAX / 2 + cycle));
sim.advance_time(SimDuration::from_nanos(500));
if !sim.read_reset(sim.io().cd.rst) {
let inp_ready = sim.read_bool(sim.io().inp.ready);
if inp_ready {
#[hdl(sim)]
if let HdlSome(v) = sim.read(sim.io().inp.data) {
println!("enqueued {v}, expected {input_value:#x}");
assert_eq!(v.as_int(), input_value);
input_value = input_value.wrapping_add(1);
}
}
let out_valid = #[hdl(sim)]
if let HdlSome(v) = sim.read(sim.io().out.data) {
if sim.read_bool(sim.io().out.ready) {
println!("dequeued {v}, expected {expected_output_value:#x}");
assert_eq!(v.as_int(), expected_output_value);
expected_output_value = expected_output_value.wrapping_add(1);
}
true
} else {
false
};
assert!(inp_ready || out_valid, "queue isn't making progress");
}
sim.write_clock(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, false);
}
sim.flush_traces().unwrap();
let vcd = String::from_utf8(writer.writer.take().unwrap().take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
if vcd != expected_vcd {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != expected_sim_debug {
panic!();
}
}
#[test]
fn test_queue_1_false_false() {
test_queue_helper(
1,
false,
false,
include_str!("sim/expected/queue_1_false_false.vcd"),
include_str!("sim/expected/queue_1_false_false.txt"),
);
}
#[test]
fn test_queue_1_false_true() {
test_queue_helper(
1,
false,
true,
include_str!("sim/expected/queue_1_false_true.vcd"),
include_str!("sim/expected/queue_1_false_true.txt"),
);
}
#[test]
fn test_queue_1_true_false() {
test_queue_helper(
1,
true,
false,
include_str!("sim/expected/queue_1_true_false.vcd"),
include_str!("sim/expected/queue_1_true_false.txt"),
);
}
#[test]
fn test_queue_1_true_true() {
test_queue_helper(
1,
true,
true,
include_str!("sim/expected/queue_1_true_true.vcd"),
include_str!("sim/expected/queue_1_true_true.txt"),
);
}
#[test]
fn test_queue_2_false_false() {
test_queue_helper(
2,
false,
false,
include_str!("sim/expected/queue_2_false_false.vcd"),
include_str!("sim/expected/queue_2_false_false.txt"),
);
}
#[test]
fn test_queue_2_false_true() {
test_queue_helper(
2,
false,
true,
include_str!("sim/expected/queue_2_false_true.vcd"),
include_str!("sim/expected/queue_2_false_true.txt"),
);
}
#[test]
fn test_queue_2_true_false() {
test_queue_helper(
2,
true,
false,
include_str!("sim/expected/queue_2_true_false.vcd"),
include_str!("sim/expected/queue_2_true_false.txt"),
);
}
#[test]
fn test_queue_2_true_true() {
test_queue_helper(
2,
true,
true,
include_str!("sim/expected/queue_2_true_true.vcd"),
include_str!("sim/expected/queue_2_true_true.txt"),
);
}
#[test]
fn test_queue_3_false_false() {
test_queue_helper(
3,
false,
false,
include_str!("sim/expected/queue_3_false_false.vcd"),
include_str!("sim/expected/queue_3_false_false.txt"),
);
}
#[test]
fn test_queue_3_false_true() {
test_queue_helper(
3,
false,
true,
include_str!("sim/expected/queue_3_false_true.vcd"),
include_str!("sim/expected/queue_3_false_true.txt"),
);
}
#[test]
fn test_queue_3_true_false() {
test_queue_helper(
3,
true,
false,
include_str!("sim/expected/queue_3_true_false.vcd"),
include_str!("sim/expected/queue_3_true_false.txt"),
);
}
#[test]
fn test_queue_3_true_true() {
test_queue_helper(
3,
true,
true,
include_str!("sim/expected/queue_3_true_true.vcd"),
include_str!("sim/expected/queue_3_true_true.txt"),
);
}
#[test]
fn test_queue_4_false_false() {
test_queue_helper(
4,
false,
false,
include_str!("sim/expected/queue_4_false_false.vcd"),
include_str!("sim/expected/queue_4_false_false.txt"),
);
}
#[test]
fn test_queue_4_false_true() {
test_queue_helper(
4,
false,
true,
include_str!("sim/expected/queue_4_false_true.vcd"),
include_str!("sim/expected/queue_4_false_true.txt"),
);
}
#[test]
fn test_queue_4_true_false() {
test_queue_helper(
4,
true,
false,
include_str!("sim/expected/queue_4_true_false.vcd"),
include_str!("sim/expected/queue_4_true_false.txt"),
);
}
#[test]
fn test_queue_4_true_true() {
test_queue_helper(
4,
true,
true,
include_str!("sim/expected/queue_4_true_true.vcd"),
include_str!("sim/expected/queue_4_true_true.txt"),
);
}

View file

@ -424,8 +424,8 @@ Simulation {
}, },
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
16, 16 (modified),
0, 0 (modified),
], ],
}, },
big_slots: StatePart { big_slots: StatePart {
@ -483,7 +483,7 @@ Simulation {
248, 248,
252, 252,
254, 254,
255, 255 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -1218,6 +1218,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xff, state: 0xff,
last_state: 0xff, last_state: 0xff,
}, },
@ -1227,6 +1228,7 @@ Simulation {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x7f, state: 0x7f,
last_state: 0x7f, last_state: 0x7f,
}, },
@ -1236,6 +1238,7 @@ Simulation {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x3f, state: 0x3f,
last_state: 0x3f, last_state: 0x3f,
}, },
@ -1245,6 +1248,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x1f, state: 0x1f,
last_state: 0x1f, last_state: 0x1f,
}, },
@ -1254,6 +1258,7 @@ Simulation {
index: StatePartIndex<BigSlots>(4), index: StatePartIndex<BigSlots>(4),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x0f, state: 0x0f,
last_state: 0x0f, last_state: 0x0f,
}, },
@ -1263,6 +1268,7 @@ Simulation {
index: StatePartIndex<BigSlots>(5), index: StatePartIndex<BigSlots>(5),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x07, state: 0x07,
last_state: 0x07, last_state: 0x07,
}, },
@ -1272,6 +1278,7 @@ Simulation {
index: StatePartIndex<BigSlots>(6), index: StatePartIndex<BigSlots>(6),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x03, state: 0x03,
last_state: 0x03, last_state: 0x03,
}, },
@ -1281,6 +1288,7 @@ Simulation {
index: StatePartIndex<BigSlots>(7), index: StatePartIndex<BigSlots>(7),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x01, state: 0x01,
last_state: 0x01, last_state: 0x01,
}, },
@ -1290,6 +1298,7 @@ Simulation {
index: StatePartIndex<BigSlots>(8), index: StatePartIndex<BigSlots>(8),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -1299,6 +1308,7 @@ Simulation {
index: StatePartIndex<BigSlots>(9), index: StatePartIndex<BigSlots>(9),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x80, state: 0x80,
last_state: 0x80, last_state: 0x80,
}, },
@ -1308,6 +1318,7 @@ Simulation {
index: StatePartIndex<BigSlots>(10), index: StatePartIndex<BigSlots>(10),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xc0, state: 0xc0,
last_state: 0xc0, last_state: 0xc0,
}, },
@ -1317,6 +1328,7 @@ Simulation {
index: StatePartIndex<BigSlots>(11), index: StatePartIndex<BigSlots>(11),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xe0, state: 0xe0,
last_state: 0xe0, last_state: 0xe0,
}, },
@ -1326,6 +1338,7 @@ Simulation {
index: StatePartIndex<BigSlots>(12), index: StatePartIndex<BigSlots>(12),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xf0, state: 0xf0,
last_state: 0xf0, last_state: 0xf0,
}, },
@ -1335,6 +1348,7 @@ Simulation {
index: StatePartIndex<BigSlots>(13), index: StatePartIndex<BigSlots>(13),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xf8, state: 0xf8,
last_state: 0xf8, last_state: 0xf8,
}, },
@ -1344,6 +1358,7 @@ Simulation {
index: StatePartIndex<BigSlots>(14), index: StatePartIndex<BigSlots>(14),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xfc, state: 0xfc,
last_state: 0xfc, last_state: 0xfc,
}, },
@ -1353,6 +1368,7 @@ Simulation {
index: StatePartIndex<BigSlots>(15), index: StatePartIndex<BigSlots>(15),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xfe, state: 0xfe,
last_state: 0xfe, last_state: 0xfe,
}, },
@ -1362,6 +1378,7 @@ Simulation {
index: StatePartIndex<BigSlots>(16), index: StatePartIndex<BigSlots>(16),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xff, state: 0xff,
last_state: 0xff, last_state: 0xff,
}, },
@ -1371,6 +1388,7 @@ Simulation {
index: StatePartIndex<BigSlots>(17), index: StatePartIndex<BigSlots>(17),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x7f, state: 0x7f,
last_state: 0x7f, last_state: 0x7f,
}, },
@ -1380,6 +1398,7 @@ Simulation {
index: StatePartIndex<BigSlots>(18), index: StatePartIndex<BigSlots>(18),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x3f, state: 0x3f,
last_state: 0x3f, last_state: 0x3f,
}, },
@ -1389,6 +1408,7 @@ Simulation {
index: StatePartIndex<BigSlots>(19), index: StatePartIndex<BigSlots>(19),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x1f, state: 0x1f,
last_state: 0x1f, last_state: 0x1f,
}, },
@ -1398,6 +1418,7 @@ Simulation {
index: StatePartIndex<BigSlots>(20), index: StatePartIndex<BigSlots>(20),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x0f, state: 0x0f,
last_state: 0x0f, last_state: 0x0f,
}, },
@ -1407,6 +1428,7 @@ Simulation {
index: StatePartIndex<BigSlots>(21), index: StatePartIndex<BigSlots>(21),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x07, state: 0x07,
last_state: 0x07, last_state: 0x07,
}, },
@ -1416,6 +1438,7 @@ Simulation {
index: StatePartIndex<BigSlots>(22), index: StatePartIndex<BigSlots>(22),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x03, state: 0x03,
last_state: 0x03, last_state: 0x03,
}, },
@ -1425,6 +1448,7 @@ Simulation {
index: StatePartIndex<BigSlots>(23), index: StatePartIndex<BigSlots>(23),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x01, state: 0x01,
last_state: 0x01, last_state: 0x01,
}, },
@ -1434,6 +1458,7 @@ Simulation {
index: StatePartIndex<BigSlots>(24), index: StatePartIndex<BigSlots>(24),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -1443,6 +1468,7 @@ Simulation {
index: StatePartIndex<BigSlots>(25), index: StatePartIndex<BigSlots>(25),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x80, state: 0x80,
last_state: 0x80, last_state: 0x80,
}, },
@ -1452,6 +1478,7 @@ Simulation {
index: StatePartIndex<BigSlots>(26), index: StatePartIndex<BigSlots>(26),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xc0, state: 0xc0,
last_state: 0xc0, last_state: 0xc0,
}, },
@ -1461,6 +1488,7 @@ Simulation {
index: StatePartIndex<BigSlots>(27), index: StatePartIndex<BigSlots>(27),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xe0, state: 0xe0,
last_state: 0xe0, last_state: 0xe0,
}, },
@ -1470,6 +1498,7 @@ Simulation {
index: StatePartIndex<BigSlots>(28), index: StatePartIndex<BigSlots>(28),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xf0, state: 0xf0,
last_state: 0xf0, last_state: 0xf0,
}, },
@ -1479,6 +1508,7 @@ Simulation {
index: StatePartIndex<BigSlots>(29), index: StatePartIndex<BigSlots>(29),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xf8, state: 0xf8,
last_state: 0xf8, last_state: 0xf8,
}, },
@ -1488,6 +1518,7 @@ Simulation {
index: StatePartIndex<BigSlots>(30), index: StatePartIndex<BigSlots>(30),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xfc, state: 0xfc,
last_state: 0xfc, last_state: 0xfc,
}, },
@ -1497,6 +1528,7 @@ Simulation {
index: StatePartIndex<BigSlots>(31), index: StatePartIndex<BigSlots>(31),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xfe, state: 0xfe,
last_state: 0xe1, last_state: 0xe1,
}, },
@ -1506,6 +1538,7 @@ Simulation {
index: StatePartIndex<BigSlots>(32), index: StatePartIndex<BigSlots>(32),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -1515,6 +1548,7 @@ Simulation {
index: StatePartIndex<BigSlots>(33), index: StatePartIndex<BigSlots>(33),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xff, state: 0xff,
last_state: 0xff, last_state: 0xff,
}, },
@ -1524,6 +1558,7 @@ Simulation {
index: StatePartIndex<BigSlots>(34), index: StatePartIndex<BigSlots>(34),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x10, state: 0x10,
last_state: 0x0f, last_state: 0x0f,
}, },
@ -1533,6 +1568,7 @@ Simulation {
index: StatePartIndex<BigSlots>(35), index: StatePartIndex<BigSlots>(35),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0xe1, last_state: 0xe1,
}, },
@ -1541,6 +1577,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(36), index: StatePartIndex<BigSlots>(36),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1550,6 +1587,7 @@ Simulation {
index: StatePartIndex<BigSlots>(37), index: StatePartIndex<BigSlots>(37),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xff, state: 0xff,
last_state: 0xff, last_state: 0xff,
}, },
@ -1559,6 +1597,7 @@ Simulation {
index: StatePartIndex<BigSlots>(38), index: StatePartIndex<BigSlots>(38),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x7f, state: 0x7f,
last_state: 0x7f, last_state: 0x7f,
}, },
@ -1568,6 +1607,7 @@ Simulation {
index: StatePartIndex<BigSlots>(39), index: StatePartIndex<BigSlots>(39),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x3f, state: 0x3f,
last_state: 0x3f, last_state: 0x3f,
}, },
@ -1577,6 +1617,7 @@ Simulation {
index: StatePartIndex<BigSlots>(40), index: StatePartIndex<BigSlots>(40),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x1f, state: 0x1f,
last_state: 0x1f, last_state: 0x1f,
}, },
@ -1586,6 +1627,7 @@ Simulation {
index: StatePartIndex<BigSlots>(41), index: StatePartIndex<BigSlots>(41),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x0f, state: 0x0f,
last_state: 0x0f, last_state: 0x0f,
}, },
@ -1595,6 +1637,7 @@ Simulation {
index: StatePartIndex<BigSlots>(42), index: StatePartIndex<BigSlots>(42),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x07, state: 0x07,
last_state: 0x07, last_state: 0x07,
}, },
@ -1604,6 +1647,7 @@ Simulation {
index: StatePartIndex<BigSlots>(43), index: StatePartIndex<BigSlots>(43),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x03, state: 0x03,
last_state: 0x03, last_state: 0x03,
}, },
@ -1613,6 +1657,7 @@ Simulation {
index: StatePartIndex<BigSlots>(44), index: StatePartIndex<BigSlots>(44),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x01, state: 0x01,
last_state: 0x01, last_state: 0x01,
}, },
@ -1622,6 +1667,7 @@ Simulation {
index: StatePartIndex<BigSlots>(45), index: StatePartIndex<BigSlots>(45),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -1631,6 +1677,7 @@ Simulation {
index: StatePartIndex<BigSlots>(46), index: StatePartIndex<BigSlots>(46),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x80, state: 0x80,
last_state: 0x80, last_state: 0x80,
}, },
@ -1640,6 +1687,7 @@ Simulation {
index: StatePartIndex<BigSlots>(47), index: StatePartIndex<BigSlots>(47),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xc0, state: 0xc0,
last_state: 0xc0, last_state: 0xc0,
}, },
@ -1649,6 +1697,7 @@ Simulation {
index: StatePartIndex<BigSlots>(48), index: StatePartIndex<BigSlots>(48),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xe0, state: 0xe0,
last_state: 0xe0, last_state: 0xe0,
}, },
@ -1658,6 +1707,7 @@ Simulation {
index: StatePartIndex<BigSlots>(49), index: StatePartIndex<BigSlots>(49),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xf0, state: 0xf0,
last_state: 0xf0, last_state: 0xf0,
}, },
@ -1667,6 +1717,7 @@ Simulation {
index: StatePartIndex<BigSlots>(50), index: StatePartIndex<BigSlots>(50),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xf8, state: 0xf8,
last_state: 0xf8, last_state: 0xf8,
}, },
@ -1676,6 +1727,7 @@ Simulation {
index: StatePartIndex<BigSlots>(51), index: StatePartIndex<BigSlots>(51),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xfc, state: 0xfc,
last_state: 0xfc, last_state: 0xfc,
}, },
@ -1685,6 +1737,7 @@ Simulation {
index: StatePartIndex<BigSlots>(52), index: StatePartIndex<BigSlots>(52),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xfe, state: 0xfe,
last_state: 0xe1, last_state: 0xe1,
}, },

View file

@ -1,283 +1,283 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module array_rw $end $scope module array_rw $end
$scope struct array_in $end $scope struct array_in $end
$var wire 8 ! \[0] $end $var wire 8 Yvfu^ \[0] $end
$var wire 8 " \[1] $end $var wire 8 |Cs`W \[1] $end
$var wire 8 # \[2] $end $var wire 8 M!nsb \[2] $end
$var wire 8 $ \[3] $end $var wire 8 59L{w \[3] $end
$var wire 8 % \[4] $end $var wire 8 o2+|F \[4] $end
$var wire 8 & \[5] $end $var wire 8 ikzV5 \[5] $end
$var wire 8 ' \[6] $end $var wire 8 [E$Z* \[6] $end
$var wire 8 ( \[7] $end $var wire 8 ?"~01 \[7] $end
$var wire 8 ) \[8] $end $var wire 8 /kghT \[8] $end
$var wire 8 * \[9] $end $var wire 8 +}(9) \[9] $end
$var wire 8 + \[10] $end $var wire 8 iMP}= \[10] $end
$var wire 8 , \[11] $end $var wire 8 2M0tL \[11] $end
$var wire 8 - \[12] $end $var wire 8 :AjkA \[12] $end
$var wire 8 . \[13] $end $var wire 8 VM_:8 \[13] $end
$var wire 8 / \[14] $end $var wire 8 UveL2 \[14] $end
$var wire 8 0 \[15] $end $var wire 8 A)9Z6 \[15] $end
$upscope $end $upscope $end
$scope struct array_out $end $scope struct array_out $end
$var wire 8 1 \[0] $end $var wire 8 2zdj1 \[0] $end
$var wire 8 2 \[1] $end $var wire 8 =;m_[ \[1] $end
$var wire 8 3 \[2] $end $var wire 8 @9Hd \[2] $end
$var wire 8 4 \[3] $end $var wire 8 C:="| \[3] $end
$var wire 8 5 \[4] $end $var wire 8 IDk7# \[4] $end
$var wire 8 6 \[5] $end $var wire 8 i]E1i \[5] $end
$var wire 8 7 \[6] $end $var wire 8 tK,M] \[6] $end
$var wire 8 8 \[7] $end $var wire 8 tGp!\ \[7] $end
$var wire 8 9 \[8] $end $var wire 8 ."qjK \[8] $end
$var wire 8 : \[9] $end $var wire 8 AUO:R \[9] $end
$var wire 8 ; \[10] $end $var wire 8 'kx`n \[10] $end
$var wire 8 < \[11] $end $var wire 8 U&(K\ \[11] $end
$var wire 8 = \[12] $end $var wire 8 q<O41 \[12] $end
$var wire 8 > \[13] $end $var wire 8 zvj)] \[13] $end
$var wire 8 ? \[14] $end $var wire 8 >0H<( \[14] $end
$var wire 8 @ \[15] $end $var wire 8 ARhXJ \[15] $end
$upscope $end $upscope $end
$var wire 8 A read_index $end $var wire 8 -n:7@ read_index $end
$var wire 8 B read_data $end $var wire 8 >h<=Z read_data $end
$var wire 8 C write_index $end $var wire 8 [xld3 write_index $end
$var wire 8 D write_data $end $var wire 8 J+DYh write_data $end
$var wire 1 E write_en $end $var wire 1 z,@WW write_en $end
$scope struct array_wire $end $scope struct array_wire $end
$var wire 8 F \[0] $end $var wire 8 B{KJS \[0] $end
$var wire 8 G \[1] $end $var wire 8 V'K*& \[1] $end
$var wire 8 H \[2] $end $var wire 8 4zI$O \[2] $end
$var wire 8 I \[3] $end $var wire 8 %TTk[ \[3] $end
$var wire 8 J \[4] $end $var wire 8 IgSeY \[4] $end
$var wire 8 K \[5] $end $var wire 8 &&1T" \[5] $end
$var wire 8 L \[6] $end $var wire 8 5)-l\ \[6] $end
$var wire 8 M \[7] $end $var wire 8 0RsLb \[7] $end
$var wire 8 N \[8] $end $var wire 8 T>:}D \[8] $end
$var wire 8 O \[9] $end $var wire 8 DPpZ* \[9] $end
$var wire 8 P \[10] $end $var wire 8 %E(nf \[10] $end
$var wire 8 Q \[11] $end $var wire 8 2'pba \[11] $end
$var wire 8 R \[12] $end $var wire 8 e/c1: \[12] $end
$var wire 8 S \[13] $end $var wire 8 ;w.C7 \[13] $end
$var wire 8 T \[14] $end $var wire 8 fwdfu \[14] $end
$var wire 8 U \[15] $end $var wire 8 *R\vx \[15] $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
b11111111 ! b11111111 Yvfu^
b1111111 " b1111111 |Cs`W
b111111 # b111111 M!nsb
b11111 $ b11111 59L{w
b1111 % b1111 o2+|F
b111 & b111 ikzV5
b11 ' b11 [E$Z*
b1 ( b1 ?"~01
b0 ) b0 /kghT
b10000000 * b10000000 +}(9)
b11000000 + b11000000 iMP}=
b11100000 , b11100000 2M0tL
b11110000 - b11110000 :AjkA
b11111000 . b11111000 VM_:8
b11111100 / b11111100 UveL2
b11111110 0 b11111110 A)9Z6
b11111111 1 b11111111 2zdj1
b1111111 2 b1111111 =;m_[
b111111 3 b111111 @9Hd
b11111 4 b11111 C:="|
b1111 5 b1111 IDk7#
b111 6 b111 i]E1i
b11 7 b11 tK,M]
b1 8 b1 tGp!\
b0 9 b0 ."qjK
b10000000 : b10000000 AUO:R
b11000000 ; b11000000 'kx`n
b11100000 < b11100000 U&(K\
b11110000 = b11110000 q<O41
b11111000 > b11111000 zvj)]
b11111100 ? b11111100 >0H<(
b11111110 @ b11111110 ARhXJ
b0 A b0 -n:7@
b11111111 B b11111111 >h<=Z
b0 C b0 [xld3
b0 D b0 J+DYh
0E 0z,@WW
b11111111 F b11111111 B{KJS
b1111111 G b1111111 V'K*&
b111111 H b111111 4zI$O
b11111 I b11111 %TTk[
b1111 J b1111 IgSeY
b111 K b111 &&1T"
b11 L b11 5)-l\
b1 M b1 0RsLb
b0 N b0 T>:}D
b10000000 O b10000000 DPpZ*
b11000000 P b11000000 %E(nf
b11100000 Q b11100000 2'pba
b11110000 R b11110000 e/c1:
b11111000 S b11111000 ;w.C7
b11111100 T b11111100 fwdfu
b11111110 U b11111110 *R\vx
$end $end
#1000000 #1000000
b1 A b1 -n:7@
b1111111 B b1111111 >h<=Z
#2000000 #2000000
b10 A b10 -n:7@
b111111 B b111111 >h<=Z
#3000000 #3000000
b11 A b11 -n:7@
b11111 B b11111 >h<=Z
#4000000 #4000000
b100 A b100 -n:7@
b1111 B b1111 >h<=Z
#5000000 #5000000
b101 A b101 -n:7@
b111 B b111 >h<=Z
#6000000 #6000000
b110 A b110 -n:7@
b11 B b11 >h<=Z
#7000000 #7000000
b111 A b111 -n:7@
b1 B b1 >h<=Z
#8000000 #8000000
b1000 A b1000 -n:7@
b0 B b0 >h<=Z
#9000000 #9000000
b1001 A b1001 -n:7@
b10000000 B b10000000 >h<=Z
#10000000 #10000000
b1010 A b1010 -n:7@
b11000000 B b11000000 >h<=Z
#11000000 #11000000
b1011 A b1011 -n:7@
b11100000 B b11100000 >h<=Z
#12000000 #12000000
b1100 A b1100 -n:7@
b11110000 B b11110000 >h<=Z
#13000000 #13000000
b1101 A b1101 -n:7@
b11111000 B b11111000 >h<=Z
#14000000 #14000000
b1110 A b1110 -n:7@
b11111100 B b11111100 >h<=Z
#15000000 #15000000
b1111 A b1111 -n:7@
b11111110 B b11111110 >h<=Z
#16000000 #16000000
b10000 A b10000 -n:7@
b0 B b0 >h<=Z
#17000000 #17000000
b0 1 b0 2zdj1
b0 A b0 -n:7@
1E 1z,@WW
b0 F b0 B{KJS
#18000000 #18000000
b11111111 1 b11111111 2zdj1
b1 2 b1 =;m_[
b11111111 B b11111111 >h<=Z
b1 C b1 [xld3
b1 D b1 J+DYh
b11111111 F b11111111 B{KJS
b1 G b1 V'K*&
#19000000 #19000000
b1111111 2 b1111111 =;m_[
b100 3 b100 @9Hd
b10 C b10 [xld3
b100 D b100 J+DYh
b1111111 G b1111111 V'K*&
b100 H b100 4zI$O
#20000000 #20000000
b111111 3 b111111 @9Hd
b1001 4 b1001 C:="|
b11 C b11 [xld3
b1001 D b1001 J+DYh
b111111 H b111111 4zI$O
b1001 I b1001 %TTk[
#21000000 #21000000
b11111 4 b11111 C:="|
b10000 5 b10000 IDk7#
b100 C b100 [xld3
b10000 D b10000 J+DYh
b11111 I b11111 %TTk[
b10000 J b10000 IgSeY
#22000000 #22000000
b1111 5 b1111 IDk7#
b11001 6 b11001 i]E1i
b101 C b101 [xld3
b11001 D b11001 J+DYh
b1111 J b1111 IgSeY
b11001 K b11001 &&1T"
#23000000 #23000000
b111 6 b111 i]E1i
b100100 7 b100100 tK,M]
b110 C b110 [xld3
b100100 D b100100 J+DYh
b111 K b111 &&1T"
b100100 L b100100 5)-l\
#24000000 #24000000
b11 7 b11 tK,M]
b110001 8 b110001 tGp!\
b111 C b111 [xld3
b110001 D b110001 J+DYh
b11 L b11 5)-l\
b110001 M b110001 0RsLb
#25000000 #25000000
b1 8 b1 tGp!\
b1000000 9 b1000000 ."qjK
b1000 C b1000 [xld3
b1000000 D b1000000 J+DYh
b1 M b1 0RsLb
b1000000 N b1000000 T>:}D
#26000000 #26000000
b0 9 b0 ."qjK
b1010001 : b1010001 AUO:R
b1001 C b1001 [xld3
b1010001 D b1010001 J+DYh
b0 N b0 T>:}D
b1010001 O b1010001 DPpZ*
#27000000 #27000000
b10000000 : b10000000 AUO:R
b1100100 ; b1100100 'kx`n
b1010 C b1010 [xld3
b1100100 D b1100100 J+DYh
b10000000 O b10000000 DPpZ*
b1100100 P b1100100 %E(nf
#28000000 #28000000
b11000000 ; b11000000 'kx`n
b1111001 < b1111001 U&(K\
b1011 C b1011 [xld3
b1111001 D b1111001 J+DYh
b11000000 P b11000000 %E(nf
b1111001 Q b1111001 2'pba
#29000000 #29000000
b11100000 < b11100000 U&(K\
b10010000 = b10010000 q<O41
b1100 C b1100 [xld3
b10010000 D b10010000 J+DYh
b11100000 Q b11100000 2'pba
b10010000 R b10010000 e/c1:
#30000000 #30000000
b11110000 = b11110000 q<O41
b10101001 > b10101001 zvj)]
b1101 C b1101 [xld3
b10101001 D b10101001 J+DYh
b11110000 R b11110000 e/c1:
b10101001 S b10101001 ;w.C7
#31000000 #31000000
b11111000 > b11111000 zvj)]
b11000100 ? b11000100 >0H<(
b1110 C b1110 [xld3
b11000100 D b11000100 J+DYh
b11111000 S b11111000 ;w.C7
b11000100 T b11000100 fwdfu
#32000000 #32000000
b11111100 ? b11111100 >0H<(
b11100001 @ b11100001 ARhXJ
b1111 C b1111 [xld3
b11100001 D b11100001 J+DYh
b11111100 T b11111100 fwdfu
b11100001 U b11100001 *R\vx
#33000000 #33000000
b11111110 @ b11111110 ARhXJ
b10000 C b10000 [xld3
b0 D b0 J+DYh
b11111110 U b11111110 *R\vx
#34000000 #34000000

View file

@ -86,8 +86,8 @@ Simulation {
value: [ value: [
1, 1,
0, 0,
1, 1 (modified),
0, 0 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -155,6 +155,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x0, last_state: 0x0,
}, },
@ -163,6 +164,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },

View file

@ -1,14 +1,14 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module conditional_assignment_last $end $scope module conditional_assignment_last $end
$var wire 1 ! i $end $var wire 1 xt~(W i $end
$var wire 1 " w $end $var wire 1 6:7im w $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
0! 0xt~(W
1" 16:7im
$end $end
#1000000 #1000000
1! 1xt~(W
0" 06:7im
#2000000 #2000000

View file

@ -63,7 +63,7 @@ Simulation {
big_slots: StatePart { big_slots: StatePart {
value: [ value: [
5, 5,
5, 5 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -124,6 +124,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x05, state: 0x05,
last_state: 0x05, last_state: 0x05,
}, },

View file

@ -90,9 +90,9 @@ Simulation {
value: [ value: [
1, 1,
1, 1,
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -175,6 +175,7 @@ Simulation {
kind: BigAsyncReset { kind: BigAsyncReset {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -183,6 +184,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },

View file

@ -1,11 +1,11 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module connect_const_reset $end $scope module connect_const_reset $end
$var wire 1 ! reset_out $end $var wire 1 8ke|= reset_out $end
$var wire 1 " bit_out $end $var wire 1 {"c@= bit_out $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
1! 18ke|=
1" 1{"c@=
$end $end
#1000000 #1000000

View file

@ -123,68 +123,72 @@ Simulation {
dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
src: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> }, src: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
}, },
8: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
src: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
8: Add { 9: Add {
dest: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<5> }, dest: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
lhs: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> }, lhs: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
rhs: StatePartIndex<BigSlots>(7), // (0x1) SlotDebugData { name: "", ty: UInt<1> }, rhs: StatePartIndex<BigSlots>(7), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
}, },
9: CastToUInt { 10: CastToUInt {
dest: StatePartIndex<BigSlots>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
src: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<5> }, src: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
dest_width: 4, dest_width: 4,
}, },
// at: module-XXXXXXXXXX.rs:4:1 // at: module-XXXXXXXXXX.rs:4:1
10: Copy { 11: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
src: StatePartIndex<BigSlots>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> }, src: StatePartIndex<BigSlots>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
}, },
// at: module-XXXXXXXXXX.rs:6:1 // at: module-XXXXXXXXXX.rs:6:1
11: Copy { 12: Copy {
dest: StatePartIndex<BigSlots>(2), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(2), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count", ty: UInt<4> },
src: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> }, src: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
}, },
// at: module-XXXXXXXXXX.rs:3:1 // at: module-XXXXXXXXXX.rs:3:1
12: BranchIfSmallNonZero { 13: BranchIfSmallNonZero {
target: 16, target: 17,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
13: BranchIfSmallZero { 14: BranchIfSmallZero {
target: 17, target: 18,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
14: Copy { 15: Copy {
dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
src: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> }, src: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
}, },
15: Branch { 16: Branch {
target: 17, target: 18,
}, },
16: Copy { 17: Copy {
dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
src: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> }, src: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
}, },
17: XorSmallImmediate { 18: XorSmallImmediate {
dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: 0x1, rhs: 0x1,
}, },
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
18: Return, 19: Return,
], ],
.. ..
}, },
pc: 18, pc: 19,
memory_write_log: [], memory_write_log: [],
memories: StatePart { memories: StatePart {
value: [], value: [],
}, },
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
0, 0 (modified),
0, 0 (modified),
1, 1 (modified),
0, 0 (modified),
], ],
}, },
big_slots: StatePart { big_slots: StatePart {
@ -193,12 +197,12 @@ Simulation {
0, 0,
3, 3,
3, 3,
4, 4 (modified),
3, 3 (modified),
0, 0 (modified),
1, 1 (modified),
4, 4 (modified),
4, 4 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -328,6 +332,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x0, last_state: 0x0,
}, },
@ -336,6 +341,7 @@ Simulation {
kind: BigAsyncReset { kind: BigAsyncReset {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -345,6 +351,7 @@ Simulation {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x3, state: 0x3,
last_state: 0x2, last_state: 0x2,
}, },
@ -354,6 +361,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x3, state: 0x3,
last_state: 0x2, last_state: 0x2,
}, },

View file

@ -1,217 +1,217 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module counter $end $scope module counter $end
$scope struct cd $end $scope struct cd $end
$var wire 1 ! clk $end $var wire 1 `[J;" clk $end
$var wire 1 " rst $end $var wire 1 4pZx7 rst $end
$upscope $end $upscope $end
$var wire 4 # count $end $var wire 4 rPs;{ count $end
$var reg 4 $ count_reg $end $var reg 4 6_+(g count_reg $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
0! 0`[J;"
0" 04pZx7
b0 # b0 rPs;{
b0 $ b0 6_+(g
$end $end
#500000 #500000
1" 14pZx7
b11 # b11 rPs;{
b11 $ b11 6_+(g
#1000000 #1000000
1! 1`[J;"
#1500000 #1500000
0" 04pZx7
#2000000 #2000000
0! 0`[J;"
#3000000 #3000000
1! 1`[J;"
b100 # b100 rPs;{
b100 $ b100 6_+(g
#4000000 #4000000
0! 0`[J;"
#5000000 #5000000
1! 1`[J;"
b101 # b101 rPs;{
b101 $ b101 6_+(g
#6000000 #6000000
0! 0`[J;"
#7000000 #7000000
1! 1`[J;"
b110 # b110 rPs;{
b110 $ b110 6_+(g
#8000000 #8000000
0! 0`[J;"
#9000000 #9000000
1! 1`[J;"
b111 # b111 rPs;{
b111 $ b111 6_+(g
#10000000 #10000000
0! 0`[J;"
#11000000 #11000000
1! 1`[J;"
b1000 # b1000 rPs;{
b1000 $ b1000 6_+(g
#12000000 #12000000
0! 0`[J;"
#13000000 #13000000
1! 1`[J;"
b1001 # b1001 rPs;{
b1001 $ b1001 6_+(g
#14000000 #14000000
0! 0`[J;"
#15000000 #15000000
1! 1`[J;"
b1010 # b1010 rPs;{
b1010 $ b1010 6_+(g
#16000000 #16000000
0! 0`[J;"
#17000000 #17000000
1! 1`[J;"
b1011 # b1011 rPs;{
b1011 $ b1011 6_+(g
#18000000 #18000000
0! 0`[J;"
#19000000 #19000000
1! 1`[J;"
b1100 # b1100 rPs;{
b1100 $ b1100 6_+(g
#20000000 #20000000
0! 0`[J;"
#21000000 #21000000
1! 1`[J;"
b1101 # b1101 rPs;{
b1101 $ b1101 6_+(g
#22000000 #22000000
0! 0`[J;"
#23000000 #23000000
1! 1`[J;"
b1110 # b1110 rPs;{
b1110 $ b1110 6_+(g
#24000000 #24000000
0! 0`[J;"
#25000000 #25000000
1! 1`[J;"
b1111 # b1111 rPs;{
b1111 $ b1111 6_+(g
#26000000 #26000000
0! 0`[J;"
#27000000 #27000000
1! 1`[J;"
b0 # b0 rPs;{
b0 $ b0 6_+(g
#28000000 #28000000
0! 0`[J;"
#29000000 #29000000
1! 1`[J;"
b1 # b1 rPs;{
b1 $ b1 6_+(g
#30000000 #30000000
0! 0`[J;"
#31000000 #31000000
1! 1`[J;"
b10 # b10 rPs;{
b10 $ b10 6_+(g
#32000000 #32000000
0! 0`[J;"
#33000000 #33000000
1! 1`[J;"
b11 # b11 rPs;{
b11 $ b11 6_+(g
#34000000 #34000000
0! 0`[J;"
#35000000 #35000000
1! 1`[J;"
b100 # b100 rPs;{
b100 $ b100 6_+(g
#36000000 #36000000
0! 0`[J;"
#37000000 #37000000
1! 1`[J;"
b101 # b101 rPs;{
b101 $ b101 6_+(g
#38000000 #38000000
0! 0`[J;"
#39000000 #39000000
1! 1`[J;"
b110 # b110 rPs;{
b110 $ b110 6_+(g
#40000000 #40000000
0! 0`[J;"
#41000000 #41000000
1! 1`[J;"
b111 # b111 rPs;{
b111 $ b111 6_+(g
#42000000 #42000000
0! 0`[J;"
#43000000 #43000000
1! 1`[J;"
b1000 # b1000 rPs;{
b1000 $ b1000 6_+(g
#44000000 #44000000
0! 0`[J;"
#45000000 #45000000
1! 1`[J;"
b1001 # b1001 rPs;{
b1001 $ b1001 6_+(g
#46000000 #46000000
0! 0`[J;"
#47000000 #47000000
1! 1`[J;"
b1010 # b1010 rPs;{
b1010 $ b1010 6_+(g
#48000000 #48000000
0! 0`[J;"
#49000000 #49000000
1! 1`[J;"
b1011 # b1011 rPs;{
b1011 $ b1011 6_+(g
#50000000 #50000000
0! 0`[J;"
#51000000 #51000000
1! 1`[J;"
b1100 # b1100 rPs;{
b1100 $ b1100 6_+(g
#52000000 #52000000
0! 0`[J;"
#53000000 #53000000
1! 1`[J;"
b1101 # b1101 rPs;{
b1101 $ b1101 6_+(g
#54000000 #54000000
0! 0`[J;"
#55000000 #55000000
1! 1`[J;"
b1110 # b1110 rPs;{
b1110 $ b1110 6_+(g
#56000000 #56000000
0! 0`[J;"
#57000000 #57000000
1! 1`[J;"
b1111 # b1111 rPs;{
b1111 $ b1111 6_+(g
#58000000 #58000000
0! 0`[J;"
#59000000 #59000000
1! 1`[J;"
b0 # b0 rPs;{
b0 $ b0 6_+(g
#60000000 #60000000
0! 0`[J;"
#61000000 #61000000
1! 1`[J;"
b1 # b1 rPs;{
b1 $ b1 6_+(g
#62000000 #62000000
0! 0`[J;"
#63000000 #63000000
1! 1`[J;"
b10 # b10 rPs;{
b10 $ b10 6_+(g
#64000000 #64000000
0! 0`[J;"
#65000000 #65000000
1! 1`[J;"
b11 # b11 rPs;{
b11 $ b11 6_+(g
#66000000 #66000000

View file

@ -102,71 +102,75 @@ Simulation {
src: StatePartIndex<BigSlots>(7), // (0x4) SlotDebugData { name: "", ty: UInt<5> }, src: StatePartIndex<BigSlots>(7), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
dest_width: 4, dest_width: 4,
}, },
// at: module-XXXXXXXXXX.rs:4:1
4: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
src: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:3:1 // at: module-XXXXXXXXXX.rs:3:1
5: IsNonZeroDestIsSmall { 4: IsNonZeroDestIsSmall {
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.rst", ty: SyncReset }, src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.rst", ty: SyncReset },
}, },
6: IsNonZeroDestIsSmall { 5: IsNonZeroDestIsSmall {
dest: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.clk", ty: Clock }, src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.clk", ty: Clock },
}, },
7: AndSmall { 6: AndSmall {
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool }, rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
7: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
src: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:4:1
8: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
src: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
8: Const { 9: Const {
dest: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
value: 0x3, value: 0x3,
}, },
// at: module-XXXXXXXXXX.rs:3:1 // at: module-XXXXXXXXXX.rs:3:1
9: BranchIfSmallZero { 10: BranchIfSmallZero {
target: 14, target: 15,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
10: BranchIfSmallNonZero { 11: BranchIfSmallNonZero {
target: 13, target: 14,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
11: Copy { 12: Copy {
dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
src: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> }, src: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
}, },
12: Branch { 13: Branch {
target: 14, target: 15,
}, },
13: Copy { 14: Copy {
dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> }, dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
src: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> }, src: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
}, },
14: XorSmallImmediate { 15: XorSmallImmediate {
dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool }, lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: 0x1, rhs: 0x1,
}, },
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
15: Return, 16: Return,
], ],
.. ..
}, },
pc: 15, pc: 16,
memory_write_log: [], memory_write_log: [],
memories: StatePart { memories: StatePart {
value: [], value: [],
}, },
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
0, 0 (modified),
0, 0 (modified),
1, 1 (modified),
0, 0 (modified),
], ],
}, },
big_slots: StatePart { big_slots: StatePart {
@ -175,11 +179,11 @@ Simulation {
0, 0,
3, 3,
3, 3,
4, 4 (modified),
3, 3 (modified),
1, 1 (modified),
4, 4 (modified),
4, 4 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -309,6 +313,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x0, last_state: 0x0,
}, },
@ -317,6 +322,7 @@ Simulation {
kind: BigSyncReset { kind: BigSyncReset {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: false,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -326,6 +332,7 @@ Simulation {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x3, state: 0x3,
last_state: 0x2, last_state: 0x2,
}, },
@ -335,6 +342,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x3, state: 0x3,
last_state: 0x2, last_state: 0x2,
}, },

View file

@ -1,214 +1,214 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module counter $end $scope module counter $end
$scope struct cd $end $scope struct cd $end
$var wire 1 ! clk $end $var wire 1 `[J;" clk $end
$var wire 1 " rst $end $var wire 1 4pZx7 rst $end
$upscope $end $upscope $end
$var wire 4 # count $end $var wire 4 rPs;{ count $end
$var reg 4 $ count_reg $end $var reg 4 6_+(g count_reg $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
0! 0`[J;"
1" 14pZx7
b0 # b0 rPs;{
b0 $ b0 6_+(g
$end $end
#1000000 #1000000
1! 1`[J;"
b11 # b11 rPs;{
b11 $ b11 6_+(g
0" 04pZx7
#2000000 #2000000
0! 0`[J;"
#3000000 #3000000
1! 1`[J;"
b100 # b100 rPs;{
b100 $ b100 6_+(g
#4000000 #4000000
0! 0`[J;"
#5000000 #5000000
1! 1`[J;"
b101 # b101 rPs;{
b101 $ b101 6_+(g
#6000000 #6000000
0! 0`[J;"
#7000000 #7000000
1! 1`[J;"
b110 # b110 rPs;{
b110 $ b110 6_+(g
#8000000 #8000000
0! 0`[J;"
#9000000 #9000000
1! 1`[J;"
b111 # b111 rPs;{
b111 $ b111 6_+(g
#10000000 #10000000
0! 0`[J;"
#11000000 #11000000
1! 1`[J;"
b1000 # b1000 rPs;{
b1000 $ b1000 6_+(g
#12000000 #12000000
0! 0`[J;"
#13000000 #13000000
1! 1`[J;"
b1001 # b1001 rPs;{
b1001 $ b1001 6_+(g
#14000000 #14000000
0! 0`[J;"
#15000000 #15000000
1! 1`[J;"
b1010 # b1010 rPs;{
b1010 $ b1010 6_+(g
#16000000 #16000000
0! 0`[J;"
#17000000 #17000000
1! 1`[J;"
b1011 # b1011 rPs;{
b1011 $ b1011 6_+(g
#18000000 #18000000
0! 0`[J;"
#19000000 #19000000
1! 1`[J;"
b1100 # b1100 rPs;{
b1100 $ b1100 6_+(g
#20000000 #20000000
0! 0`[J;"
#21000000 #21000000
1! 1`[J;"
b1101 # b1101 rPs;{
b1101 $ b1101 6_+(g
#22000000 #22000000
0! 0`[J;"
#23000000 #23000000
1! 1`[J;"
b1110 # b1110 rPs;{
b1110 $ b1110 6_+(g
#24000000 #24000000
0! 0`[J;"
#25000000 #25000000
1! 1`[J;"
b1111 # b1111 rPs;{
b1111 $ b1111 6_+(g
#26000000 #26000000
0! 0`[J;"
#27000000 #27000000
1! 1`[J;"
b0 # b0 rPs;{
b0 $ b0 6_+(g
#28000000 #28000000
0! 0`[J;"
#29000000 #29000000
1! 1`[J;"
b1 # b1 rPs;{
b1 $ b1 6_+(g
#30000000 #30000000
0! 0`[J;"
#31000000 #31000000
1! 1`[J;"
b10 # b10 rPs;{
b10 $ b10 6_+(g
#32000000 #32000000
0! 0`[J;"
#33000000 #33000000
1! 1`[J;"
b11 # b11 rPs;{
b11 $ b11 6_+(g
#34000000 #34000000
0! 0`[J;"
#35000000 #35000000
1! 1`[J;"
b100 # b100 rPs;{
b100 $ b100 6_+(g
#36000000 #36000000
0! 0`[J;"
#37000000 #37000000
1! 1`[J;"
b101 # b101 rPs;{
b101 $ b101 6_+(g
#38000000 #38000000
0! 0`[J;"
#39000000 #39000000
1! 1`[J;"
b110 # b110 rPs;{
b110 $ b110 6_+(g
#40000000 #40000000
0! 0`[J;"
#41000000 #41000000
1! 1`[J;"
b111 # b111 rPs;{
b111 $ b111 6_+(g
#42000000 #42000000
0! 0`[J;"
#43000000 #43000000
1! 1`[J;"
b1000 # b1000 rPs;{
b1000 $ b1000 6_+(g
#44000000 #44000000
0! 0`[J;"
#45000000 #45000000
1! 1`[J;"
b1001 # b1001 rPs;{
b1001 $ b1001 6_+(g
#46000000 #46000000
0! 0`[J;"
#47000000 #47000000
1! 1`[J;"
b1010 # b1010 rPs;{
b1010 $ b1010 6_+(g
#48000000 #48000000
0! 0`[J;"
#49000000 #49000000
1! 1`[J;"
b1011 # b1011 rPs;{
b1011 $ b1011 6_+(g
#50000000 #50000000
0! 0`[J;"
#51000000 #51000000
1! 1`[J;"
b1100 # b1100 rPs;{
b1100 $ b1100 6_+(g
#52000000 #52000000
0! 0`[J;"
#53000000 #53000000
1! 1`[J;"
b1101 # b1101 rPs;{
b1101 $ b1101 6_+(g
#54000000 #54000000
0! 0`[J;"
#55000000 #55000000
1! 1`[J;"
b1110 # b1110 rPs;{
b1110 $ b1110 6_+(g
#56000000 #56000000
0! 0`[J;"
#57000000 #57000000
1! 1`[J;"
b1111 # b1111 rPs;{
b1111 $ b1111 6_+(g
#58000000 #58000000
0! 0`[J;"
#59000000 #59000000
1! 1`[J;"
b0 # b0 rPs;{
b0 $ b0 6_+(g
#60000000 #60000000
0! 0`[J;"
#61000000 #61000000
1! 1`[J;"
b1 # b1 rPs;{
b1 $ b1 6_+(g
#62000000 #62000000
0! 0`[J;"
#63000000 #63000000
1! 1`[J;"
b10 # b10 rPs;{
b10 $ b10 6_+(g
#64000000 #64000000
0! 0`[J;"
#65000000 #65000000
1! 1`[J;"
b11 # b11 rPs;{
b11 $ b11 6_+(g
#66000000 #66000000

View file

@ -81,9 +81,9 @@ Simulation {
big_slots: StatePart { big_slots: StatePart {
value: [ value: [
5, 5,
5, 5 (modified),
6,
6, 6,
6 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -137,6 +137,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x05, state: 0x05,
last_state: 0x05, last_state: 0x05,
}, },
@ -146,6 +147,7 @@ Simulation {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x06, state: 0x06,
last_state: 0x06, last_state: 0x06,
}, },

View file

@ -1,11 +1,11 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module duplicate_names $end $scope module duplicate_names $end
$var wire 8 ! w $end $var wire 8 7[_7. w $end
$var wire 8 " w_2 $end $var wire 8 7[_7." w_2 $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
b101 ! b101 7[_7.
b110 " b110 7[_7."
$end $end
#1000000 #1000000

View file

@ -1012,173 +1012,177 @@ Simulation {
lhs: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool }, lhs: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool }, rhs: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
99: Copy {
dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
src: StatePartIndex<BigSlots>(23), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
},
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
99: Const { 100: Const {
dest: StatePartIndex<BigSlots>(25), // (0x0) SlotDebugData { name: "", ty: UInt<6> }, dest: StatePartIndex<BigSlots>(25), // (0x0) SlotDebugData { name: "", ty: UInt<6> },
value: 0x0, value: 0x0,
}, },
100: Copy { 101: Copy {
dest: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, dest: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
src: StatePartIndex<BigSlots>(25), // (0x0) SlotDebugData { name: "", ty: UInt<6> }, src: StatePartIndex<BigSlots>(25), // (0x0) SlotDebugData { name: "", ty: UInt<6> },
}, },
// at: module-XXXXXXXXXX.rs:12:1 // at: module-XXXXXXXXXX.rs:12:1
101: BranchIfZero { 102: BranchIfZero {
target: 109, target: 110,
value: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::en", ty: Bool }, value: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::en", ty: Bool },
}, },
// at: module-XXXXXXXXXX.rs:13:1 // at: module-XXXXXXXXXX.rs:13:1
102: BranchIfZero { 103: BranchIfZero {
target: 104, target: 105,
value: StatePartIndex<BigSlots>(46), // (0x0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<BigSlots>(46), // (0x0) SlotDebugData { name: "", ty: Bool },
}, },
// at: module-XXXXXXXXXX.rs:14:1 // at: module-XXXXXXXXXX.rs:14:1
103: Copy { 104: Copy {
dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
src: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, src: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
}, },
// at: module-XXXXXXXXXX.rs:13:1 // at: module-XXXXXXXXXX.rs:13:1
104: BranchIfNonZero { 105: BranchIfNonZero {
target: 109, target: 110,
value: StatePartIndex<BigSlots>(46), // (0x0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<BigSlots>(46), // (0x0) SlotDebugData { name: "", ty: Bool },
}, },
// at: module-XXXXXXXXXX.rs:15:1 // at: module-XXXXXXXXXX.rs:15:1
105: BranchIfZero { 106: BranchIfZero {
target: 107, target: 108,
value: StatePartIndex<BigSlots>(48), // (0x0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<BigSlots>(48), // (0x0) SlotDebugData { name: "", ty: Bool },
}, },
// at: module-XXXXXXXXXX.rs:16:1 // at: module-XXXXXXXXXX.rs:16:1
106: Copy { 107: Copy {
dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
src: StatePartIndex<BigSlots>(65), // (0xd) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, src: StatePartIndex<BigSlots>(65), // (0xd) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
}, },
// at: module-XXXXXXXXXX.rs:15:1 // at: module-XXXXXXXXXX.rs:15:1
107: BranchIfNonZero { 108: BranchIfNonZero {
target: 109, target: 110,
value: StatePartIndex<BigSlots>(48), // (0x0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<BigSlots>(48), // (0x0) SlotDebugData { name: "", ty: Bool },
}, },
// at: module-XXXXXXXXXX.rs:17:1 // at: module-XXXXXXXXXX.rs:17:1
108: Copy { 109: Copy {
dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
src: StatePartIndex<BigSlots>(87), // (0x3e) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, src: StatePartIndex<BigSlots>(87), // (0x3e) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
}, },
// at: module-XXXXXXXXXX.rs:10:1 // at: module-XXXXXXXXXX.rs:10:1
109: Copy { 110: Copy {
dest: StatePartIndex<BigSlots>(15), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b2_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} }, dest: StatePartIndex<BigSlots>(15), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b2_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} },
src: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} }, src: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} },
}, },
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
110: Copy { 111: Copy {
dest: StatePartIndex<BigSlots>(18), // (0x0) SlotDebugData { name: "", ty: UInt<3> }, dest: StatePartIndex<BigSlots>(18), // (0x0) SlotDebugData { name: "", ty: UInt<3> },
src: StatePartIndex<BigSlots>(15), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b2_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} }, src: StatePartIndex<BigSlots>(15), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b2_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} },
}, },
111: SliceInt { 112: SliceInt {
dest: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, dest: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
src: StatePartIndex<BigSlots>(18), // (0x0) SlotDebugData { name: "", ty: UInt<3> }, src: StatePartIndex<BigSlots>(18), // (0x0) SlotDebugData { name: "", ty: UInt<3> },
start: 1, start: 1,
len: 2, len: 2,
}, },
112: SliceInt { 113: SliceInt {
dest: StatePartIndex<BigSlots>(20), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, dest: StatePartIndex<BigSlots>(20), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, src: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
start: 0, start: 0,
len: 1, len: 1,
}, },
113: SliceInt { 114: SliceInt {
dest: StatePartIndex<BigSlots>(21), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, dest: StatePartIndex<BigSlots>(21), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, src: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
start: 1, start: 1,
len: 1, len: 1,
}, },
114: Copy { 115: Copy {
dest: StatePartIndex<BigSlots>(22), // (0x0) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<BigSlots>(22), // (0x0) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(21), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, src: StatePartIndex<BigSlots>(21), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
}, },
115: Copy { 116: Copy {
dest: StatePartIndex<BigSlots>(16), // (0x0) SlotDebugData { name: ".0", ty: UInt<1> }, dest: StatePartIndex<BigSlots>(16), // (0x0) SlotDebugData { name: ".0", ty: UInt<1> },
src: StatePartIndex<BigSlots>(20), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, src: StatePartIndex<BigSlots>(20), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
}, },
116: Copy { 117: Copy {
dest: StatePartIndex<BigSlots>(17), // (0x0) SlotDebugData { name: ".1", ty: Bool }, dest: StatePartIndex<BigSlots>(17), // (0x0) SlotDebugData { name: ".1", ty: Bool },
src: StatePartIndex<BigSlots>(22), // (0x0) SlotDebugData { name: "", ty: Bool }, src: StatePartIndex<BigSlots>(22), // (0x0) SlotDebugData { name: "", ty: Bool },
}, },
// at: module-XXXXXXXXXX.rs:9:1 // at: module-XXXXXXXXXX.rs:9:1
117: AndBigWithSmallImmediate { 118: AndBigWithSmallImmediate {
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome} }, dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome} },
lhs: StatePartIndex<BigSlots>(15), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b2_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} }, lhs: StatePartIndex<BigSlots>(15), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b2_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} },
rhs: 0x1, rhs: 0x1,
}, },
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
118: Copy { 119: Copy {
dest: StatePartIndex<BigSlots>(10), // (0x0) SlotDebugData { name: "", ty: UInt<3> }, dest: StatePartIndex<BigSlots>(10), // (0x0) SlotDebugData { name: "", ty: UInt<3> },
src: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} }, src: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} },
}, },
119: SliceInt { 120: SliceInt {
dest: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, dest: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
src: StatePartIndex<BigSlots>(10), // (0x0) SlotDebugData { name: "", ty: UInt<3> }, src: StatePartIndex<BigSlots>(10), // (0x0) SlotDebugData { name: "", ty: UInt<3> },
start: 1, start: 1,
len: 2, len: 2,
}, },
120: SliceInt { 121: SliceInt {
dest: StatePartIndex<BigSlots>(12), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, dest: StatePartIndex<BigSlots>(12), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, src: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
start: 0, start: 0,
len: 1, len: 1,
}, },
121: SliceInt { 122: SliceInt {
dest: StatePartIndex<BigSlots>(13), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, dest: StatePartIndex<BigSlots>(13), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> }, src: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
start: 1, start: 1,
len: 1, len: 1,
}, },
122: Copy { 123: Copy {
dest: StatePartIndex<BigSlots>(14), // (0x0) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<BigSlots>(14), // (0x0) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(13), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, src: StatePartIndex<BigSlots>(13), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
}, },
123: Copy { 124: Copy {
dest: StatePartIndex<BigSlots>(8), // (0x0) SlotDebugData { name: ".0", ty: UInt<1> }, dest: StatePartIndex<BigSlots>(8), // (0x0) SlotDebugData { name: ".0", ty: UInt<1> },
src: StatePartIndex<BigSlots>(12), // (0x0) SlotDebugData { name: "", ty: UInt<1> }, src: StatePartIndex<BigSlots>(12), // (0x0) SlotDebugData { name: "", ty: UInt<1> },
}, },
124: Copy { 125: Copy {
dest: StatePartIndex<BigSlots>(9), // (0x0) SlotDebugData { name: ".1", ty: Bool }, dest: StatePartIndex<BigSlots>(9), // (0x0) SlotDebugData { name: ".1", ty: Bool },
src: StatePartIndex<BigSlots>(14), // (0x0) SlotDebugData { name: "", ty: Bool }, src: StatePartIndex<BigSlots>(14), // (0x0) SlotDebugData { name: "", ty: Bool },
}, },
// at: module-XXXXXXXXXX.rs:8:1 // at: module-XXXXXXXXXX.rs:8:1
125: AndBigWithSmallImmediate { 126: AndBigWithSmallImmediate {
dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome} }, dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome} },
lhs: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} }, lhs: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} },
rhs: 0x1, rhs: 0x1,
}, },
// at: module-XXXXXXXXXX.rs:11:1 // at: module-XXXXXXXXXX.rs:11:1
126: BranchIfSmallZero { 127: BranchIfSmallZero {
target: 131, target: 132,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
127: BranchIfSmallNonZero { 128: BranchIfSmallNonZero {
target: 130, target: 131,
value: StatePartIndex<SmallSlots>(5), // (0x0 0) SlotDebugData { name: "", ty: Bool }, value: StatePartIndex<SmallSlots>(5), // (0x0 0) SlotDebugData { name: "", ty: Bool },
}, },
128: Copy { 129: Copy {
dest: StatePartIndex<BigSlots>(23), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, dest: StatePartIndex<BigSlots>(23), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
src: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, src: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
}, },
129: Branch { 130: Branch {
target: 131, target: 132,
}, },
130: Copy { 131: Copy {
dest: StatePartIndex<BigSlots>(23), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, dest: StatePartIndex<BigSlots>(23), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
src: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} }, src: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
}, },
131: XorSmallImmediate { 132: XorSmallImmediate {
dest: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool }, dest: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool }, lhs: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: 0x1, rhs: 0x1,
}, },
// at: module-XXXXXXXXXX.rs:1:1 // at: module-XXXXXXXXXX.rs:1:1
132: Return, 133: Return,
], ],
.. ..
}, },
pc: 132, pc: 133,
memory_write_log: [], memory_write_log: [],
memories: StatePart { memories: StatePart {
value: [], value: [],
@ -1187,10 +1191,10 @@ Simulation {
value: [ value: [
0, 0,
0, 0,
0, 0 (modified),
0, 0 (modified),
1, 1 (modified),
0, 0 (modified),
2, 2,
], ],
}, },
@ -1203,110 +1207,110 @@ Simulation {
15, 15,
2, 2,
15, 15,
0 (modified),
0, 0,
0, 0,
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0, 0,
0, 0,
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 62 (modified),
0, 62 (modified),
0, 0 (modified),
0, 0 (modified),
0,
0,
0,
62,
62,
0,
0,
1,
1,
62,
3,
1,
1, 1,
1, 1,
62 (modified),
3 (modified),
1 (modified),
1 (modified),
1 (modified),
1, 1,
1, 1,
-1, -1,
1, 1 (modified),
1, 1 (modified),
15, 15 (modified),
3, 3 (modified),
1, 1 (modified),
1, 1 (modified),
3, 3 (modified),
-1, -1 (modified),
0, 0 (modified),
0, 0 (modified),
1, 1 (modified),
0, 0 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
2, 2 (modified),
3, 3 (modified),
12, 12 (modified),
13, 13 (modified),
13, 13 (modified),
13, 13 (modified),
2, 2 (modified),
1, 1 (modified),
1, 1 (modified),
-1, -1 (modified),
2, 2 (modified),
1, 1 (modified),
1, 1 (modified),
-1, -1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
3, 3 (modified),
-1, -1 (modified),
2, 2 (modified),
3, 3 (modified),
3, 3 (modified),
12, 12 (modified),
15, 15 (modified),
60, 60 (modified),
62, 62 (modified),
62, 62 (modified),
62, 62 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
1, 1 (modified),
2, 2 (modified),
3, 3 (modified),
3, 3 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
1, 1 (modified),
2, 2 (modified),
3, 3 (modified),
6, 6 (modified),
7, 7 (modified),
7, 7 (modified),
7, 7 (modified),
2, 2 (modified),
3, 3 (modified),
3, 3 (modified),
12, 12 (modified),
15, 15 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -1742,6 +1746,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x0, last_state: 0x0,
}, },
@ -1750,6 +1755,7 @@ Simulation {
kind: BigSyncReset { kind: BigSyncReset {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: false,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1758,6 +1764,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
}, },
maybe_changed: false,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1767,6 +1774,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<2>, ty: UInt<2>,
}, },
maybe_changed: false,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -1776,6 +1784,7 @@ Simulation {
index: StatePartIndex<BigSlots>(4), index: StatePartIndex<BigSlots>(4),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: false,
state: 0xf, state: 0xf,
last_state: 0xf, last_state: 0xf,
}, },
@ -1785,6 +1794,7 @@ Simulation {
index: StatePartIndex<BigSlots>(5), index: StatePartIndex<BigSlots>(5),
ty: UInt<2>, ty: UInt<2>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -1794,6 +1804,7 @@ Simulation {
index: StatePartIndex<BigSlots>(6), index: StatePartIndex<BigSlots>(6),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0xf, state: 0xf,
last_state: 0xf, last_state: 0xf,
}, },
@ -1806,6 +1817,7 @@ Simulation {
HdlSome(Bundle {0: UInt<1>, 1: Bool}), HdlSome(Bundle {0: UInt<1>, 1: Bool}),
}, },
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1815,6 +1827,7 @@ Simulation {
index: StatePartIndex<BigSlots>(8), index: StatePartIndex<BigSlots>(8),
ty: UInt<1>, ty: UInt<1>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1823,6 +1836,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(9), index: StatePartIndex<BigSlots>(9),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1835,6 +1849,7 @@ Simulation {
HdlSome(Bundle {0: UInt<1>, 1: Bool}), HdlSome(Bundle {0: UInt<1>, 1: Bool}),
}, },
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1844,6 +1859,7 @@ Simulation {
index: StatePartIndex<BigSlots>(16), index: StatePartIndex<BigSlots>(16),
ty: UInt<1>, ty: UInt<1>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1852,6 +1868,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(17), index: StatePartIndex<BigSlots>(17),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1865,6 +1882,7 @@ Simulation {
C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>}),
}, },
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -1874,6 +1892,7 @@ Simulation {
index: StatePartIndex<BigSlots>(27), index: StatePartIndex<BigSlots>(27),
ty: UInt<1>, ty: UInt<1>,
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1882,6 +1901,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(28), index: StatePartIndex<BigSlots>(28),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1891,6 +1911,7 @@ Simulation {
index: StatePartIndex<BigSlots>(34), index: StatePartIndex<BigSlots>(34),
ty: UInt<1>, ty: UInt<1>,
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1900,6 +1921,7 @@ Simulation {
index: StatePartIndex<BigSlots>(35), index: StatePartIndex<BigSlots>(35),
ty: UInt<1>, ty: UInt<1>,
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1909,6 +1931,7 @@ Simulation {
index: StatePartIndex<BigSlots>(36), index: StatePartIndex<BigSlots>(36),
ty: SInt<2>, ty: SInt<2>,
}, },
maybe_changed: true,
state: 0x3, state: 0x3,
last_state: 0x3, last_state: 0x3,
}, },

View file

@ -1,126 +1,126 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module enums $end $scope module enums $end
$scope struct cd $end $scope struct cd $end
$var wire 1 ! clk $end $var wire 1 0n\U< clk $end
$var wire 1 " rst $end $var wire 1 a?A!) rst $end
$upscope $end $upscope $end
$var wire 1 # en $end $var wire 1 #ZQY# en $end
$var wire 2 $ which_in $end $var wire 2 8?II+ which_in $end
$var wire 4 % data_in $end $var wire 4 OO,N+ data_in $end
$var wire 2 & which_out $end $var wire 2 yr2gr which_out $end
$var wire 4 ' data_out $end $var wire 4 q_O;Y data_out $end
$scope struct b_out $end $scope struct b_out $end
$var string 1 ( \$tag $end $var string 1 7L1gf \$tag $end
$scope struct HdlSome $end $scope struct HdlSome $end
$var wire 1 ) \0 $end $var wire 1 EO?Ju \0 $end
$var wire 1 * \1 $end $var wire 1 cGtNN \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct b2_out $end $scope struct b2_out $end
$var string 1 + \$tag $end $var string 1 dqd@B \$tag $end
$scope struct HdlSome $end $scope struct HdlSome $end
$var wire 1 , \0 $end $var wire 1 (FG:I \0 $end
$var wire 1 - \1 $end $var wire 1 dzy-= \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct the_reg $end $scope struct the_reg $end
$var string 1 . \$tag $end $var string 1 J#9uO \$tag $end
$scope struct B $end $scope struct B $end
$var reg 1 / \0 $end $var reg 1 ca2Gh \0 $end
$var reg 1 0 \1 $end $var reg 1 f)r)? \1 $end
$upscope $end $upscope $end
$scope struct C $end $scope struct C $end
$scope struct a $end $scope struct a $end
$var reg 1 1 \[0] $end $var reg 1 ;BepJ \[0] $end
$var reg 1 2 \[1] $end $var reg 1 J~2;e \[1] $end
$upscope $end $upscope $end
$var reg 2 3 b $end $var reg 2 w\b)K b $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
0! 00n\U<
1" 1a?A!)
0# 0#ZQY#
b0 $ b0 8?II+
b0 % b0 OO,N+
b0 & b0 yr2gr
b0 ' b0 q_O;Y
sHdlNone\x20(0) ( sHdlNone\x20(0) 7L1gf
0) 0EO?Ju
0* 0cGtNN
sHdlNone\x20(0) + sHdlNone\x20(0) dqd@B
0, 0(FG:I
0- 0dzy-=
sA\x20(0) . sA\x20(0) J#9uO
0/ 0ca2Gh
00 0f)r)?
01 0;BepJ
02 0J~2;e
b0 3 b0 w\b)K
$end $end
#1000000 #1000000
1! 10n\U<
#1100000 #1100000
0" 0a?A!)
#2000000 #2000000
0! 00n\U<
#3000000 #3000000
1! 10n\U<
#4000000 #4000000
1# 1#ZQY#
b1 $ b1 8?II+
0! 00n\U<
#5000000 #5000000
1! 10n\U<
b1 & b1 yr2gr
sHdlSome\x20(1) ( sHdlSome\x20(1) 7L1gf
sHdlSome\x20(1) + sHdlSome\x20(1) dqd@B
sB\x20(1) . sB\x20(1) J#9uO
#6000000 #6000000
0# 0#ZQY#
b0 $ b0 8?II+
0! 00n\U<
#7000000 #7000000
1! 10n\U<
#8000000 #8000000
1# 1#ZQY#
b1 $ b1 8?II+
b1111 % b1111 OO,N+
0! 00n\U<
#9000000 #9000000
1! 10n\U<
b11 ' b11 q_O;Y
1) 1EO?Ju
1* 1cGtNN
1, 1(FG:I
1- 1dzy-=
1/ 1ca2Gh
10 1f)r)?
11 1;BepJ
12 1J~2;e
#10000000 #10000000
0! 00n\U<
#11000000 #11000000
1! 10n\U<
#12000000 #12000000
b10 $ b10 8?II+
0! 00n\U<
#13000000 #13000000
1! 10n\U<
b10 & b10 yr2gr
b1111 ' b1111 q_O;Y
sHdlNone\x20(0) ( sHdlNone\x20(0) 7L1gf
0) 0EO?Ju
0* 0cGtNN
sHdlNone\x20(0) + sHdlNone\x20(0) dqd@B
0, 0(FG:I
0- 0dzy-=
sC\x20(2) . sC\x20(2) J#9uO
b11 3 b11 w\b)K
#14000000 #14000000
0! 00n\U<
#15000000 #15000000
1! 10n\U<
#16000000 #16000000

View file

@ -221,6 +221,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
maybe_changed: false,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -229,6 +230,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x0, last_state: 0x0,
}, },

View file

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

View file

@ -57,7 +57,7 @@ Simulation {
big_slots: StatePart { big_slots: StatePart {
value: [ value: [
0, 0,
1, 1 (modified),
101, 101,
], ],
}, },
@ -280,6 +280,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
}, },
maybe_changed: false,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -288,6 +289,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -297,6 +299,7 @@ Simulation {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: false,
state: 0x65, state: 0x65,
last_state: 0x65, last_state: 0x65,
}, },

View file

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

View file

@ -0,0 +1,709 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "",
ty: Enum {
HdlNone,
HdlSome,
},
},
SlotDebugData {
name: "",
ty: Enum {
HdlNone,
HdlSome,
},
},
],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 33,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(last_connect: last_connect).last_connect::inp",
ty: Enum {
HdlNone,
HdlSome(Array<Bool, 4>),
},
},
SlotDebugData {
name: "[0]",
ty: Bool,
},
SlotDebugData {
name: "[1]",
ty: Bool,
},
SlotDebugData {
name: "[2]",
ty: Bool,
},
SlotDebugData {
name: "[3]",
ty: Bool,
},
SlotDebugData {
name: "",
ty: UInt<5>,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: UInt<1>,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: UInt<1>,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: UInt<1>,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: UInt<1>,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(last_connect: last_connect).last_connect::out",
ty: Enum {
HdlNone,
HdlSome(UInt<8>),
},
},
SlotDebugData {
name: "",
ty: UInt<9>,
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<9>,
},
SlotDebugData {
name: "",
ty: Enum {
HdlNone,
HdlSome(UInt<8>),
},
},
SlotDebugData {
name: "InstantiatedModule(last_connect: last_connect).last_connect::w",
ty: UInt<8>,
},
SlotDebugData {
name: ".0",
ty: UInt<1>,
},
SlotDebugData {
name: ".1",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<1>,
},
SlotDebugData {
name: "",
ty: UInt<9>,
},
SlotDebugData {
name: "",
ty: UInt<9>,
},
SlotDebugData {
name: "",
ty: UInt<9>,
},
SlotDebugData {
name: "",
ty: Enum {
HdlNone,
HdlSome(UInt<8>),
},
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
SlotDebugData {
name: "",
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: Const {
dest: StatePartIndex<BigSlots>(32), // (0x3) SlotDebugData { name: "", ty: UInt<8> },
value: 0x3,
},
1: Const {
dest: StatePartIndex<BigSlots>(31), // (0x2) SlotDebugData { name: "", ty: UInt<8> },
value: 0x2,
},
2: Const {
dest: StatePartIndex<BigSlots>(30), // (0x1) SlotDebugData { name: "", ty: UInt<8> },
value: 0x1,
},
3: Const {
dest: StatePartIndex<BigSlots>(29), // (0x0) SlotDebugData { name: "", ty: UInt<8> },
value: 0x0,
},
4: Const {
dest: StatePartIndex<BigSlots>(28), // (0x4) SlotDebugData { name: "", ty: UInt<8> },
value: 0x4,
},
// at: module-XXXXXXXXXX.rs:8:1
5: Copy {
dest: StatePartIndex<BigSlots>(20), // (0x3) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::w", ty: UInt<8> },
src: StatePartIndex<BigSlots>(28), // (0x4) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:1:1
6: Const {
dest: StatePartIndex<BigSlots>(23), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
value: 0x1,
},
7: Const {
dest: StatePartIndex<BigSlots>(18), // (0x0) SlotDebugData { name: "", ty: UInt<9> },
value: 0x0,
},
8: Copy {
dest: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
src: StatePartIndex<BigSlots>(18), // (0x0) SlotDebugData { name: "", ty: UInt<9> },
},
// at: module-XXXXXXXXXX.rs:4:1
9: Copy {
dest: StatePartIndex<BigSlots>(15), // (0x7) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::out", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
src: StatePartIndex<BigSlots>(19), // (0x0) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
},
// at: module-XXXXXXXXXX.rs:1:1
10: Copy {
dest: StatePartIndex<BigSlots>(5), // (0x1f) SlotDebugData { name: "", ty: UInt<5> },
src: StatePartIndex<BigSlots>(0), // (0x1f) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::inp", ty: Enum {HdlNone, HdlSome(Array<Bool, 4>)} },
},
11: SliceInt {
dest: StatePartIndex<BigSlots>(6), // (0xf) SlotDebugData { name: "", ty: UInt<4> },
src: StatePartIndex<BigSlots>(5), // (0x1f) SlotDebugData { name: "", ty: UInt<5> },
start: 1,
len: 4,
},
12: SliceInt {
dest: StatePartIndex<BigSlots>(7), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(6), // (0xf) SlotDebugData { name: "", ty: UInt<4> },
start: 0,
len: 1,
},
13: Copy {
dest: StatePartIndex<BigSlots>(8), // (0x1) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(7), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
},
14: SliceInt {
dest: StatePartIndex<BigSlots>(9), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(6), // (0xf) SlotDebugData { name: "", ty: UInt<4> },
start: 1,
len: 1,
},
15: Copy {
dest: StatePartIndex<BigSlots>(10), // (0x1) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(9), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
},
16: SliceInt {
dest: StatePartIndex<BigSlots>(11), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(6), // (0xf) SlotDebugData { name: "", ty: UInt<4> },
start: 2,
len: 1,
},
17: Copy {
dest: StatePartIndex<BigSlots>(12), // (0x1) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(11), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
},
18: SliceInt {
dest: StatePartIndex<BigSlots>(13), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
src: StatePartIndex<BigSlots>(6), // (0xf) SlotDebugData { name: "", ty: UInt<4> },
start: 3,
len: 1,
},
19: Copy {
dest: StatePartIndex<BigSlots>(14), // (0x1) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(13), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
},
20: Copy {
dest: StatePartIndex<BigSlots>(1), // (0x1) SlotDebugData { name: "[0]", ty: Bool },
src: StatePartIndex<BigSlots>(8), // (0x1) SlotDebugData { name: "", ty: Bool },
},
21: Copy {
dest: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "[1]", ty: Bool },
src: StatePartIndex<BigSlots>(10), // (0x1) SlotDebugData { name: "", ty: Bool },
},
22: Copy {
dest: StatePartIndex<BigSlots>(3), // (0x1) SlotDebugData { name: "[2]", ty: Bool },
src: StatePartIndex<BigSlots>(12), // (0x1) SlotDebugData { name: "", ty: Bool },
},
23: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x1) SlotDebugData { name: "[3]", ty: Bool },
src: StatePartIndex<BigSlots>(14), // (0x1) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:9:1
24: BranchIfZero {
target: 26,
value: StatePartIndex<BigSlots>(1), // (0x1) SlotDebugData { name: "[0]", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:10:1
25: Copy {
dest: StatePartIndex<BigSlots>(20), // (0x3) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::w", ty: UInt<8> },
src: StatePartIndex<BigSlots>(29), // (0x0) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:9:1
26: BranchIfZero {
target: 28,
value: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "[1]", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:10:1
27: Copy {
dest: StatePartIndex<BigSlots>(20), // (0x3) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::w", ty: UInt<8> },
src: StatePartIndex<BigSlots>(30), // (0x1) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:9:1
28: BranchIfZero {
target: 30,
value: StatePartIndex<BigSlots>(3), // (0x1) SlotDebugData { name: "[2]", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:10:1
29: Copy {
dest: StatePartIndex<BigSlots>(20), // (0x3) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::w", ty: UInt<8> },
src: StatePartIndex<BigSlots>(31), // (0x2) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:9:1
30: BranchIfZero {
target: 32,
value: StatePartIndex<BigSlots>(4), // (0x1) SlotDebugData { name: "[3]", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:10:1
31: Copy {
dest: StatePartIndex<BigSlots>(20), // (0x3) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::w", ty: UInt<8> },
src: StatePartIndex<BigSlots>(32), // (0x3) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:1:1
32: Copy {
dest: StatePartIndex<BigSlots>(21), // (0x1) SlotDebugData { name: ".0", ty: UInt<1> },
src: StatePartIndex<BigSlots>(23), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
},
33: Copy {
dest: StatePartIndex<BigSlots>(22), // (0x3) SlotDebugData { name: ".1", ty: UInt<8> },
src: StatePartIndex<BigSlots>(20), // (0x3) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::w", ty: UInt<8> },
},
34: Shl {
dest: StatePartIndex<BigSlots>(24), // (0x6) SlotDebugData { name: "", ty: UInt<9> },
lhs: StatePartIndex<BigSlots>(22), // (0x3) SlotDebugData { name: ".1", ty: UInt<8> },
rhs: 1,
},
35: Or {
dest: StatePartIndex<BigSlots>(25), // (0x7) SlotDebugData { name: "", ty: UInt<9> },
lhs: StatePartIndex<BigSlots>(21), // (0x1) SlotDebugData { name: ".0", ty: UInt<1> },
rhs: StatePartIndex<BigSlots>(24), // (0x6) SlotDebugData { name: "", ty: UInt<9> },
},
36: CastToUInt {
dest: StatePartIndex<BigSlots>(26), // (0x7) SlotDebugData { name: "", ty: UInt<9> },
src: StatePartIndex<BigSlots>(25), // (0x7) SlotDebugData { name: "", ty: UInt<9> },
dest_width: 9,
},
37: Copy {
dest: StatePartIndex<BigSlots>(27), // (0x7) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
src: StatePartIndex<BigSlots>(26), // (0x7) SlotDebugData { name: "", ty: UInt<9> },
},
// at: module-XXXXXXXXXX.rs:2:1
38: AndBigWithSmallImmediate {
dest: StatePartIndex<SmallSlots>(0), // (0x1 1) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome} },
lhs: StatePartIndex<BigSlots>(0), // (0x1f) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::inp", ty: Enum {HdlNone, HdlSome(Array<Bool, 4>)} },
rhs: 0x1,
},
// at: module-XXXXXXXXXX.rs:5:1
39: BranchIfSmallNeImmediate {
target: 41,
lhs: StatePartIndex<SmallSlots>(0), // (0x1 1) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome} },
rhs: 0x1,
},
// at: module-XXXXXXXXXX.rs:7:1
40: Copy {
dest: StatePartIndex<BigSlots>(15), // (0x7) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::out", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
src: StatePartIndex<BigSlots>(27), // (0x7) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
},
// at: module-XXXXXXXXXX.rs:3:1
41: AndBigWithSmallImmediate {
dest: StatePartIndex<SmallSlots>(1), // (0x1 1) SlotDebugData { name: "", ty: Enum {HdlNone, HdlSome} },
lhs: StatePartIndex<BigSlots>(15), // (0x7) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::out", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
rhs: 0x1,
},
// at: module-XXXXXXXXXX.rs:1:1
42: Copy {
dest: StatePartIndex<BigSlots>(16), // (0x7) SlotDebugData { name: "", ty: UInt<9> },
src: StatePartIndex<BigSlots>(15), // (0x7) SlotDebugData { name: "InstantiatedModule(last_connect: last_connect).last_connect::out", ty: Enum {HdlNone, HdlSome(UInt<8>)} },
},
43: SliceInt {
dest: StatePartIndex<BigSlots>(17), // (0x3) SlotDebugData { name: "", ty: UInt<8> },
src: StatePartIndex<BigSlots>(16), // (0x7) SlotDebugData { name: "", ty: UInt<9> },
start: 1,
len: 8,
},
44: Return,
],
..
},
pc: 44,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [
1,
1,
],
},
big_slots: StatePart {
value: [
31 (modified),
1,
1,
1,
1,
31 (modified),
15 (modified),
1 (modified),
1 (modified),
1 (modified),
1 (modified),
1 (modified),
1 (modified),
1 (modified),
1 (modified),
7 (modified),
7 (modified),
3,
0 (modified),
0 (modified),
3,
1 (modified),
3 (modified),
1 (modified),
6 (modified),
7 (modified),
7 (modified),
7 (modified),
4 (modified),
0 (modified),
1 (modified),
2 (modified),
3 (modified),
],
},
sim_only_slots: StatePart {
value: [],
},
},
io: Instance {
name: <simulator>::last_connect,
instantiated: Module {
name: last_connect,
..
},
},
main_module: SimulationModuleState {
base_targets: [
Instance {
name: <simulator>::last_connect,
instantiated: Module {
name: last_connect,
..
},
}.inp,
Instance {
name: <simulator>::last_connect,
instantiated: Module {
name: last_connect,
..
},
}.out,
],
uninitialized_ios: {},
io_targets: {
Instance {
name: <simulator>::last_connect,
instantiated: Module {
name: last_connect,
..
},
}.inp,
Instance {
name: <simulator>::last_connect,
instantiated: Module {
name: last_connect,
..
},
}.out,
},
did_initial_settle: true,
clocks_for_past: {},
},
extern_modules: [],
trace_decls: TraceModule {
name: "last_connect",
children: [
TraceModuleIO {
name: "inp",
child: TraceEnumWithFields {
name: "inp",
discriminant: TraceEnumDiscriminant {
location: TraceScalarId(0),
name: "$tag",
ty: Enum {
HdlNone,
HdlSome(Array<Bool, 4>),
},
flow: Source,
},
non_empty_fields: [
TraceArray {
name: "HdlSome",
elements: [
TraceBool {
location: TraceScalarId(1),
name: "[0]",
flow: Source,
},
TraceBool {
location: TraceScalarId(2),
name: "[1]",
flow: Source,
},
TraceBool {
location: TraceScalarId(3),
name: "[2]",
flow: Source,
},
TraceBool {
location: TraceScalarId(4),
name: "[3]",
flow: Source,
},
],
ty: Array<Bool, 4>,
flow: Source,
},
],
ty: Enum {
HdlNone,
HdlSome(Array<Bool, 4>),
},
flow: Source,
},
ty: Enum {
HdlNone,
HdlSome(Array<Bool, 4>),
},
flow: Source,
},
TraceModuleIO {
name: "out",
child: TraceEnumWithFields {
name: "out",
discriminant: TraceEnumDiscriminant {
location: TraceScalarId(5),
name: "$tag",
ty: Enum {
HdlNone,
HdlSome(UInt<8>),
},
flow: Sink,
},
non_empty_fields: [
TraceUInt {
location: TraceScalarId(6),
name: "HdlSome",
ty: UInt<8>,
flow: Source,
},
],
ty: Enum {
HdlNone,
HdlSome(UInt<8>),
},
flow: Sink,
},
ty: Enum {
HdlNone,
HdlSome(UInt<8>),
},
flow: Sink,
},
TraceWire {
name: "w",
child: TraceUInt {
location: TraceScalarId(7),
name: "w",
ty: UInt<8>,
flow: Duplex,
},
ty: UInt<8>,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: EnumDiscriminant {
index: StatePartIndex<SmallSlots>(0),
ty: Enum {
HdlNone,
HdlSome(Array<Bool, 4>),
},
},
maybe_changed: true,
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(1),
kind: BigBool {
index: StatePartIndex<BigSlots>(1),
},
maybe_changed: true,
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(2),
kind: BigBool {
index: StatePartIndex<BigSlots>(2),
},
maybe_changed: true,
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(3),
kind: BigBool {
index: StatePartIndex<BigSlots>(3),
},
maybe_changed: true,
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(4),
kind: BigBool {
index: StatePartIndex<BigSlots>(4),
},
maybe_changed: true,
state: 0x1,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(5),
kind: EnumDiscriminant {
index: StatePartIndex<SmallSlots>(1),
ty: Enum {
HdlNone,
HdlSome(UInt<8>),
},
},
maybe_changed: true,
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(6),
kind: BigUInt {
index: StatePartIndex<BigSlots>(17),
ty: UInt<8>,
},
maybe_changed: true,
state: 0x03,
last_state: 0x02,
},
SimTrace {
id: TraceScalarId(7),
kind: BigUInt {
index: StatePartIndex<BigSlots>(20),
ty: UInt<8>,
},
maybe_changed: true,
state: 0x03,
last_state: 0x02,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
clocks_triggered: [],
event_queue: EventQueue(EventQueueData {
instant: 17 μs,
events: {},
}),
waiting_sensitivity_sets_by_address: {},
waiting_sensitivity_sets_by_compiled_value: {},
..
}

View file

@ -0,0 +1,104 @@
$timescale 1 ps $end
$scope module last_connect $end
$scope struct inp $end
$var string 1 !C&}* \$tag $end
$scope struct HdlSome $end
$var wire 1 D_viZ \[0] $end
$var wire 1 b5gFK \[1] $end
$var wire 1 xUBRH \[2] $end
$var wire 1 Gp7Xm \[3] $end
$upscope $end
$upscope $end
$scope struct out $end
$var string 1 ^Z_p3 \$tag $end
$var wire 8 rz~), HdlSome $end
$upscope $end
$var wire 8 dlea> w $end
$upscope $end
$enddefinitions $end
$dumpvars
sHdlNone\x20(0) !C&}*
0D_viZ
0b5gFK
0xUBRH
0Gp7Xm
sHdlNone\x20(0) ^Z_p3
b0 rz~),
b100 dlea>
$end
#1000000
sHdlSome\x20(1) !C&}*
sHdlSome\x20(1) ^Z_p3
b100 rz~),
#2000000
1Gp7Xm
b11 rz~),
b11 dlea>
#3000000
1xUBRH
0Gp7Xm
b10 rz~),
b10 dlea>
#4000000
1Gp7Xm
b11 rz~),
b11 dlea>
#5000000
1b5gFK
0xUBRH
0Gp7Xm
b1 rz~),
b1 dlea>
#6000000
1Gp7Xm
b11 rz~),
b11 dlea>
#7000000
1xUBRH
0Gp7Xm
b10 rz~),
b10 dlea>
#8000000
1Gp7Xm
b11 rz~),
b11 dlea>
#9000000
1D_viZ
0b5gFK
0xUBRH
0Gp7Xm
b0 rz~),
b0 dlea>
#10000000
1Gp7Xm
b11 rz~),
b11 dlea>
#11000000
1xUBRH
0Gp7Xm
b10 rz~),
b10 dlea>
#12000000
1Gp7Xm
b11 rz~),
b11 dlea>
#13000000
1b5gFK
0xUBRH
0Gp7Xm
b1 rz~),
b1 dlea>
#14000000
1Gp7Xm
b11 rz~),
b11 dlea>
#15000000
1xUBRH
0Gp7Xm
b10 rz~),
b10 dlea>
#16000000
1Gp7Xm
b11 rz~),
b11 dlea>
#17000000

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -522,18 +522,18 @@ Simulation {
}, },
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
1, 1 (modified),
0, 0 (modified),
0, 0 (modified),
1, 1 (modified),
2, 2 (modified),
1, 1 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
2, 2 (modified),
2, 2 (modified),
0, 0 (modified),
], ],
}, },
big_slots: StatePart { big_slots: StatePart {
@ -562,10 +562,10 @@ Simulation {
-32, -32,
1, 1,
1, 1,
208, 208 (modified),
-32, -32 (modified),
1, 1 (modified),
1, 1 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -1168,6 +1168,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -1176,6 +1177,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1184,6 +1186,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -1193,6 +1196,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xb0, state: 0xb0,
last_state: 0xb0, last_state: 0xb0,
}, },
@ -1202,6 +1206,7 @@ Simulation {
index: StatePartIndex<BigSlots>(4), index: StatePartIndex<BigSlots>(4),
ty: SInt<8>, ty: SInt<8>,
}, },
maybe_changed: true,
state: 0xc0, state: 0xc0,
last_state: 0xc0, last_state: 0xc0,
}, },
@ -1211,6 +1216,7 @@ Simulation {
index: StatePartIndex<BigSlots>(5), index: StatePartIndex<BigSlots>(5),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -1219,6 +1225,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(6), index: StatePartIndex<BigSlots>(6),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1227,6 +1234,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(7), index: StatePartIndex<BigSlots>(7),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -1236,6 +1244,7 @@ Simulation {
index: StatePartIndex<BigSlots>(8), index: StatePartIndex<BigSlots>(8),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xd0, state: 0xd0,
last_state: 0xd0, last_state: 0xd0,
}, },
@ -1245,6 +1254,7 @@ Simulation {
index: StatePartIndex<BigSlots>(9), index: StatePartIndex<BigSlots>(9),
ty: SInt<8>, ty: SInt<8>,
}, },
maybe_changed: true,
state: 0xe0, state: 0xe0,
last_state: 0xe0, last_state: 0xe0,
}, },
@ -1253,6 +1263,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(10), index: StatePartIndex<BigSlots>(10),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1261,6 +1272,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(11), index: StatePartIndex<BigSlots>(11),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1270,6 +1282,7 @@ Simulation {
index: StatePartIndex<BigSlots>(12), index: StatePartIndex<BigSlots>(12),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -1278,6 +1291,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(13), index: StatePartIndex<BigSlots>(13),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1286,6 +1300,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(14), index: StatePartIndex<BigSlots>(14),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -1295,6 +1310,7 @@ Simulation {
index: StatePartIndex<BigSlots>(15), index: StatePartIndex<BigSlots>(15),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xb0, state: 0xb0,
last_state: 0xb0, last_state: 0xb0,
}, },
@ -1304,6 +1320,7 @@ Simulation {
index: StatePartIndex<BigSlots>(16), index: StatePartIndex<BigSlots>(16),
ty: SInt<8>, ty: SInt<8>,
}, },
maybe_changed: true,
state: 0xc0, state: 0xc0,
last_state: 0xc0, last_state: 0xc0,
}, },
@ -1313,6 +1330,7 @@ Simulation {
index: StatePartIndex<BigSlots>(17), index: StatePartIndex<BigSlots>(17),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -1321,6 +1339,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(18), index: StatePartIndex<BigSlots>(18),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1329,6 +1348,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(19), index: StatePartIndex<BigSlots>(19),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -1338,6 +1358,7 @@ Simulation {
index: StatePartIndex<BigSlots>(20), index: StatePartIndex<BigSlots>(20),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0xd0, state: 0xd0,
last_state: 0xd0, last_state: 0xd0,
}, },
@ -1347,6 +1368,7 @@ Simulation {
index: StatePartIndex<BigSlots>(21), index: StatePartIndex<BigSlots>(21),
ty: SInt<8>, ty: SInt<8>,
}, },
maybe_changed: true,
state: 0xe0, state: 0xe0,
last_state: 0xe0, last_state: 0xe0,
}, },
@ -1355,6 +1377,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(22), index: StatePartIndex<BigSlots>(22),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },
@ -1363,6 +1386,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(23), index: StatePartIndex<BigSlots>(23),
}, },
maybe_changed: true,
state: 0x1, state: 0x1,
last_state: 0x1, last_state: 0x1,
}, },

View file

@ -1,408 +1,408 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module memories $end $scope module memories $end
$scope struct r $end $scope struct r $end
$var wire 4 ! addr $end $var wire 4 z&0Qk addr $end
$var wire 1 " en $end $var wire 1 o.T)# en $end
$var wire 1 # clk $end $var wire 1 :XNoK clk $end
$scope struct data $end $scope struct data $end
$var wire 8 $ \0 $end $var wire 8 Cq]A% \0 $end
$var wire 8 % \1 $end $var wire 8 avKNj \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct w $end $scope struct w $end
$var wire 4 & addr $end $var wire 4 p<O.M addr $end
$var wire 1 ' en $end $var wire 1 #9)l8 en $end
$var wire 1 ( clk $end $var wire 1 QX!^| clk $end
$scope struct data $end $scope struct data $end
$var wire 8 ) \0 $end $var wire 8 G"IXQ \0 $end
$var wire 8 * \1 $end $var wire 8 h\t:E \1 $end
$upscope $end $upscope $end
$scope struct mask $end $scope struct mask $end
$var wire 1 + \0 $end $var wire 1 FCuNz \0 $end
$var wire 1 , \1 $end $var wire 1 /Y7%J \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct mem $end $scope struct mem $end
$scope struct contents $end $scope struct contents $end
$scope struct \[0] $end $scope struct \[0] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 9 \0 $end $var reg 8 4d[cL \0 $end
$var reg 8 I \1 $end $var reg 8 {qEUV \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[1] $end $scope struct \[1] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 : \0 $end $var reg 8 c`NPR \0 $end
$var reg 8 J \1 $end $var reg 8 vK:33 \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[2] $end $scope struct \[2] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 ; \0 $end $var reg 8 ihYp_ \0 $end
$var reg 8 K \1 $end $var reg 8 QZb%P \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[3] $end $scope struct \[3] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 < \0 $end $var reg 8 ,O%<$ \0 $end
$var reg 8 L \1 $end $var reg 8 @?uSf \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[4] $end $scope struct \[4] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 = \0 $end $var reg 8 N[IF& \0 $end
$var reg 8 M \1 $end $var reg 8 Zf9lw \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[5] $end $scope struct \[5] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 > \0 $end $var reg 8 dr6lq \0 $end
$var reg 8 N \1 $end $var reg 8 fc"UR \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[6] $end $scope struct \[6] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 ? \0 $end $var reg 8 xpw5\ \0 $end
$var reg 8 O \1 $end $var reg 8 dd$?K \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[7] $end $scope struct \[7] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 @ \0 $end $var reg 8 vH;}2 \0 $end
$var reg 8 P \1 $end $var reg 8 ILB?4 \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[8] $end $scope struct \[8] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 A \0 $end $var reg 8 /X4v> \0 $end
$var reg 8 Q \1 $end $var reg 8 &V*EE \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[9] $end $scope struct \[9] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 B \0 $end $var reg 8 IczZe \0 $end
$var reg 8 R \1 $end $var reg 8 unX>R \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[10] $end $scope struct \[10] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 C \0 $end $var reg 8 0hTyY \0 $end
$var reg 8 S \1 $end $var reg 8 9K_w) \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[11] $end $scope struct \[11] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 D \0 $end $var reg 8 +C/Sz \0 $end
$var reg 8 T \1 $end $var reg 8 }Y{:o \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[12] $end $scope struct \[12] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 E \0 $end $var reg 8 S6-5u \0 $end
$var reg 8 U \1 $end $var reg 8 9q6)w \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[13] $end $scope struct \[13] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 F \0 $end $var reg 8 !c<w* \0 $end
$var reg 8 V \1 $end $var reg 8 Ve@)M \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[14] $end $scope struct \[14] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 G \0 $end $var reg 8 OiF9* \0 $end
$var reg 8 W \1 $end $var reg 8 Ylyz~ \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[15] $end $scope struct \[15] $end
$scope struct mem $end $scope struct mem $end
$var reg 8 H \0 $end $var reg 8 ?+m9D \0 $end
$var reg 8 X \1 $end $var reg 8 A6sb~ \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct r0 $end $scope struct r0 $end
$var wire 4 - addr $end $var wire 4 ="2wN addr $end
$var wire 1 . en $end $var wire 1 jy78F en $end
$var wire 1 / clk $end $var wire 1 \o>8T clk $end
$scope struct data $end $scope struct data $end
$var wire 8 0 \0 $end $var wire 8 \k#l \0 $end
$var wire 8 1 \1 $end $var wire 8 olx7O \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct w1 $end $scope struct w1 $end
$var wire 4 2 addr $end $var wire 4 H,W!J addr $end
$var wire 1 3 en $end $var wire 1 "7?3I en $end
$var wire 1 4 clk $end $var wire 1 DC/;" clk $end
$scope struct data $end $scope struct data $end
$var wire 8 5 \0 $end $var wire 8 0DrV' \0 $end
$var wire 8 6 \1 $end $var wire 8 wa!Cx \1 $end
$upscope $end $upscope $end
$scope struct mask $end $scope struct mask $end
$var wire 1 7 \0 $end $var wire 1 u^b&R \0 $end
$var wire 1 8 \1 $end $var wire 1 Ic\|v \1 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
b1 9 b1 4d[cL
b100011 I b100011 {qEUV
b1 : b1 c`NPR
b100011 J b100011 vK:33
b1 ; b1 ihYp_
b100011 K b100011 QZb%P
b1 < b1 ,O%<$
b100011 L b100011 @?uSf
b1 = b1 N[IF&
b100011 M b100011 Zf9lw
b1 > b1 dr6lq
b100011 N b100011 fc"UR
b1 ? b1 xpw5\
b100011 O b100011 dd$?K
b1 @ b1 vH;}2
b100011 P b100011 ILB?4
b1 A b1 /X4v>
b100011 Q b100011 &V*EE
b1 B b1 IczZe
b100011 R b100011 unX>R
b1 C b1 0hTyY
b100011 S b100011 9K_w)
b1 D b1 +C/Sz
b100011 T b100011 }Y{:o
b1 E b1 S6-5u
b100011 U b100011 9q6)w
b1 F b1 !c<w*
b100011 V b100011 Ve@)M
b1 G b1 OiF9*
b100011 W b100011 Ylyz~
b1 H b1 ?+m9D
b100011 X b100011 A6sb~
b0 ! b0 z&0Qk
0" 0o.T)#
0# 0:XNoK
b0 $ b0 Cq]A%
b0 % b0 avKNj
b0 & b0 p<O.M
0' 0#9)l8
0( 0QX!^|
b0 ) b0 G"IXQ
b0 * b0 h\t:E
0+ 0FCuNz
0, 0/Y7%J
b0 - b0 ="2wN
0. 0jy78F
0/ 0\o>8T
b0 0 b0 \k#l
b0 1 b0 olx7O
b0 2 b0 H,W!J
03 0"7?3I
04 0DC/;"
b0 5 b0 0DrV'
b0 6 b0 wa!Cx
07 0u^b&R
08 0Ic\|v
$end $end
#1000000 #1000000
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#2000000 #2000000
1" 1o.T)#
0# 0:XNoK
b1 $ b1 Cq]A%
b100011 % b100011 avKNj
1' 1#9)l8
0( 0QX!^|
b10000 ) b10000 G"IXQ
b100000 * b100000 h\t:E
1+ 1FCuNz
1, 1/Y7%J
1. 1jy78F
0/ 0\o>8T
b1 0 b1 \k#l
b100011 1 b100011 olx7O
13 1"7?3I
04 0DC/;"
b10000 5 b10000 0DrV'
b100000 6 b100000 wa!Cx
17 1u^b&R
18 1Ic\|v
#3000000 #3000000
b10000 9 b10000 4d[cL
b100000 I b100000 {qEUV
1# 1:XNoK
b10000 $ b10000 Cq]A%
b100000 % b100000 avKNj
1( 1QX!^|
1/ 1\o>8T
b10000 0 b10000 \k#l
b100000 1 b100000 olx7O
14 1DC/;"
#4000000 #4000000
0# 0:XNoK
0( 0QX!^|
b110000 ) b110000 G"IXQ
b1000000 * b1000000 h\t:E
0+ 0FCuNz
0/ 0\o>8T
04 0DC/;"
b110000 5 b110000 0DrV'
b1000000 6 b1000000 wa!Cx
07 0u^b&R
#5000000 #5000000
b10000 9 b10000 4d[cL
b1000000 I b1000000 {qEUV
1# 1:XNoK
b1000000 % b1000000 avKNj
1( 1QX!^|
1/ 1\o>8T
b1000000 1 b1000000 olx7O
14 1DC/;"
#6000000 #6000000
0# 0:XNoK
0( 0QX!^|
b1010000 ) b1010000 G"IXQ
b1100000 * b1100000 h\t:E
1+ 1FCuNz
0, 0/Y7%J
0/ 0\o>8T
04 0DC/;"
b1010000 5 b1010000 0DrV'
b1100000 6 b1100000 wa!Cx
17 1u^b&R
08 0Ic\|v
#7000000 #7000000
b1010000 9 b1010000 4d[cL
b1000000 I b1000000 {qEUV
1# 1:XNoK
b1010000 $ b1010000 Cq]A%
1( 1QX!^|
1/ 1\o>8T
b1010000 0 b1010000 \k#l
14 1DC/;"
#8000000 #8000000
0# 0:XNoK
0( 0QX!^|
b1110000 ) b1110000 G"IXQ
b10000000 * b10000000 h\t:E
0+ 0FCuNz
0/ 0\o>8T
04 0DC/;"
b1110000 5 b1110000 0DrV'
b10000000 6 b10000000 wa!Cx
07 0u^b&R
#9000000 #9000000
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#10000000 #10000000
0# 0:XNoK
0' 0#9)l8
0( 0QX!^|
b10010000 ) b10010000 G"IXQ
b10100000 * b10100000 h\t:E
0/ 0\o>8T
03 0"7?3I
04 0DC/;"
b10010000 5 b10010000 0DrV'
b10100000 6 b10100000 wa!Cx
#11000000 #11000000
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#12000000 #12000000
0# 0:XNoK
b1 & b1 p<O.M
1' 1#9)l8
0( 0QX!^|
1+ 1FCuNz
1, 1/Y7%J
0/ 0\o>8T
b1 2 b1 H,W!J
13 1"7?3I
04 0DC/;"
17 1u^b&R
18 1Ic\|v
#13000000 #13000000
b10010000 : b10010000 c`NPR
b10100000 J b10100000 vK:33
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#14000000 #14000000
0# 0:XNoK
b10 & b10 p<O.M
0( 0QX!^|
b10110000 ) b10110000 G"IXQ
b11000000 * b11000000 h\t:E
0/ 0\o>8T
b10 2 b10 H,W!J
04 0DC/;"
b10110000 5 b10110000 0DrV'
b11000000 6 b11000000 wa!Cx
#15000000 #15000000
b10110000 ; b10110000 ihYp_
b11000000 K b11000000 QZb%P
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#16000000 #16000000
0# 0:XNoK
0' 0#9)l8
0( 0QX!^|
b11010000 ) b11010000 G"IXQ
b11100000 * b11100000 h\t:E
0/ 0\o>8T
03 0"7?3I
04 0DC/;"
b11010000 5 b11010000 0DrV'
b11100000 6 b11100000 wa!Cx
#17000000 #17000000
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#18000000 #18000000
b1 ! b1 z&0Qk
0# 0:XNoK
b10010000 $ b10010000 Cq]A%
b10100000 % b10100000 avKNj
0( 0QX!^|
b1 - b1 ="2wN
0/ 0\o>8T
b10010000 0 b10010000 \k#l
b10100000 1 b10100000 olx7O
04 0DC/;"
#19000000 #19000000
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#20000000 #20000000
b10 ! b10 z&0Qk
0# 0:XNoK
b10110000 $ b10110000 Cq]A%
b11000000 % b11000000 avKNj
0( 0QX!^|
b10 - b10 ="2wN
0/ 0\o>8T
b10110000 0 b10110000 \k#l
b11000000 1 b11000000 olx7O
04 0DC/;"
#21000000 #21000000
1# 1:XNoK
1( 1QX!^|
1/ 1\o>8T
14 1DC/;"
#22000000 #22000000
0# 0:XNoK
0( 0QX!^|
0/ 0\o>8T
04 0DC/;"

View file

@ -545,15 +545,15 @@ Simulation {
value: [ value: [
0, 0,
0, 0,
1, 1 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
], ],
}, },
big_slots: StatePart { big_slots: StatePart {
@ -568,32 +568,32 @@ Simulation {
0, 0,
0, 0,
0, 0,
0 (modified),
0, 0,
0 (modified),
0, 0,
0 (modified),
0 (modified),
0, 0,
0 (modified),
0 (modified),
0, 0,
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 1 (modified),
0, 0 (modified),
0, 1 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
1, 0 (modified),
0, 1 (modified),
1, 1 (modified),
0, 1 (modified),
0,
0,
0,
1,
1,
1,
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -943,6 +943,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<3>, ty: UInt<3>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -951,6 +952,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -959,6 +961,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -968,6 +971,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<2>, ty: UInt<2>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -976,6 +980,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(4), index: StatePartIndex<BigSlots>(4),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -985,6 +990,7 @@ Simulation {
index: StatePartIndex<BigSlots>(5), index: StatePartIndex<BigSlots>(5),
ty: UInt<2>, ty: UInt<2>,
}, },
maybe_changed: false,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -993,6 +999,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(6), index: StatePartIndex<BigSlots>(6),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1002,6 +1009,7 @@ Simulation {
index: StatePartIndex<BigSlots>(7), index: StatePartIndex<BigSlots>(7),
ty: UInt<3>, ty: UInt<3>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1010,6 +1018,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(8), index: StatePartIndex<BigSlots>(8),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1018,6 +1027,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(9), index: StatePartIndex<BigSlots>(9),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -1030,6 +1040,7 @@ Simulation {
HdlSome(Bool), HdlSome(Bool),
}, },
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1038,6 +1049,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(16), index: StatePartIndex<BigSlots>(16),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1046,6 +1058,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(11), index: StatePartIndex<BigSlots>(11),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1058,6 +1071,7 @@ Simulation {
HdlSome(Bool), HdlSome(Bool),
}, },
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1066,6 +1080,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(19), index: StatePartIndex<BigSlots>(19),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -1074,6 +1089,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(13), index: StatePartIndex<BigSlots>(13),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },

View file

@ -1,363 +1,363 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module memories2 $end $scope module memories2 $end
$scope struct rw $end $scope struct rw $end
$var wire 3 ! addr $end $var wire 3 xkkG> addr $end
$var wire 1 " en $end $var wire 1 HoA{1 en $end
$var wire 1 # clk $end $var wire 1 C*2BQ clk $end
$var wire 2 $ rdata $end $var wire 2 ueF!x rdata $end
$var wire 1 % wmode $end $var wire 1 m\l/p wmode $end
$var wire 2 & wdata $end $var wire 2 WmjEh wdata $end
$var wire 1 ' wmask $end $var wire 1 +3E@H wmask $end
$upscope $end $upscope $end
$scope struct mem $end $scope struct mem $end
$scope struct contents $end $scope struct contents $end
$scope struct \[0] $end $scope struct \[0] $end
$scope struct mem $end $scope struct mem $end
$var string 1 1 \$tag $end $var string 1 ujd9u \$tag $end
$var reg 1 6 HdlSome $end $var reg 1 *5lV# HdlSome $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[1] $end $scope struct \[1] $end
$scope struct mem $end $scope struct mem $end
$var string 1 2 \$tag $end $var string 1 *qL|n \$tag $end
$var reg 1 7 HdlSome $end $var reg 1 ^/FDC HdlSome $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[2] $end $scope struct \[2] $end
$scope struct mem $end $scope struct mem $end
$var string 1 3 \$tag $end $var string 1 r*7|@ \$tag $end
$var reg 1 8 HdlSome $end $var reg 1 YMY"3 HdlSome $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[3] $end $scope struct \[3] $end
$scope struct mem $end $scope struct mem $end
$var string 1 4 \$tag $end $var string 1 jj/6F \$tag $end
$var reg 1 9 HdlSome $end $var reg 1 S+Uy} HdlSome $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct \[4] $end $scope struct \[4] $end
$scope struct mem $end $scope struct mem $end
$var string 1 5 \$tag $end $var string 1 H72IP \$tag $end
$var reg 1 : HdlSome $end $var reg 1 vH{({ HdlSome $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct rw0 $end $scope struct rw0 $end
$var wire 3 ( addr $end $var wire 3 uabMI addr $end
$var wire 1 ) en $end $var wire 1 LEn[l en $end
$var wire 1 * clk $end $var wire 1 OpH)U clk $end
$scope struct rdata $end $scope struct rdata $end
$var string 1 + \$tag $end $var string 1 [}rcZ \$tag $end
$var wire 1 , HdlSome $end $var wire 1 5f=Y~ HdlSome $end
$upscope $end $upscope $end
$var wire 1 - wmode $end $var wire 1 6c_9_ wmode $end
$scope struct wdata $end $scope struct wdata $end
$var string 1 . \$tag $end $var string 1 $hfRN \$tag $end
$var wire 1 / HdlSome $end $var wire 1 rop,b HdlSome $end
$upscope $end $upscope $end
$var wire 1 0 wmask $end $var wire 1 Ly=US wmask $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
sHdlSome\x20(1) 1 sHdlSome\x20(1) ujd9u
16 1*5lV#
sHdlSome\x20(1) 2 sHdlSome\x20(1) *qL|n
17 1^/FDC
sHdlSome\x20(1) 3 sHdlSome\x20(1) r*7|@
18 1YMY"3
sHdlSome\x20(1) 4 sHdlSome\x20(1) jj/6F
19 1S+Uy}
sHdlSome\x20(1) 5 sHdlSome\x20(1) H72IP
1: 1vH{({
b0 ! b0 xkkG>
0" 0HoA{1
0# 0C*2BQ
b0 $ b0 ueF!x
0% 0m\l/p
b0 & b0 WmjEh
0' 0+3E@H
b0 ( b0 uabMI
0) 0LEn[l
0* 0OpH)U
sHdlNone\x20(0) + sHdlNone\x20(0) [}rcZ
0, 05f=Y~
0- 06c_9_
sHdlNone\x20(0) . sHdlNone\x20(0) $hfRN
0/ 0rop,b
00 0Ly=US
$end $end
#250000 #250000
1# 1C*2BQ
1* 1OpH)U
#500000 #500000
#750000 #750000
0# 0C*2BQ
0* 0OpH)U
#1000000 #1000000
1" 1HoA{1
1) 1LEn[l
#1250000 #1250000
1# 1C*2BQ
b11 $ b11 ueF!x
1* 1OpH)U
sHdlSome\x20(1) + sHdlSome\x20(1) [}rcZ
1, 15f=Y~
#1500000 #1500000
#1750000 #1750000
0# 0C*2BQ
0* 0OpH)U
#2000000 #2000000
0" 0HoA{1
0) 0LEn[l
#2250000 #2250000
1# 1C*2BQ
b0 $ b0 ueF!x
1* 1OpH)U
sHdlNone\x20(0) + sHdlNone\x20(0) [}rcZ
0, 05f=Y~
#2500000 #2500000
#2750000 #2750000
0# 0C*2BQ
0* 0OpH)U
#3000000 #3000000
1" 1HoA{1
1% 1m\l/p
1' 1+3E@H
1) 1LEn[l
1- 16c_9_
10 1Ly=US
#3250000 #3250000
sHdlNone\x20(0) 1 sHdlNone\x20(0) ujd9u
06 0*5lV#
1# 1C*2BQ
1* 1OpH)U
#3500000 #3500000
#3750000 #3750000
0# 0C*2BQ
0* 0OpH)U
#4000000 #4000000
0% 0m\l/p
0' 0+3E@H
0- 06c_9_
00 0Ly=US
#4250000 #4250000
1# 1C*2BQ
1* 1OpH)U
#4500000 #4500000
#4750000 #4750000
0# 0C*2BQ
0* 0OpH)U
#5000000 #5000000
1% 1m\l/p
b11 & b11 WmjEh
1- 16c_9_
sHdlSome\x20(1) . sHdlSome\x20(1) $hfRN
1/ 1rop,b
#5250000 #5250000
1# 1C*2BQ
1* 1OpH)U
#5500000 #5500000
#5750000 #5750000
0# 0C*2BQ
0* 0OpH)U
#6000000 #6000000
b1 ! b1 xkkG>
b1 & b1 WmjEh
1' 1+3E@H
b1 ( b1 uabMI
0/ 0rop,b
10 1Ly=US
#6250000 #6250000
sHdlSome\x20(1) 2 sHdlSome\x20(1) *qL|n
07 0^/FDC
1# 1C*2BQ
1* 1OpH)U
#6500000 #6500000
#6750000 #6750000
0# 0C*2BQ
0* 0OpH)U
#7000000 #7000000
b10 ! b10 xkkG>
b10 & b10 WmjEh
b10 ( b10 uabMI
sHdlNone\x20(0) . sHdlNone\x20(0) $hfRN
#7250000 #7250000
sHdlNone\x20(0) 3 sHdlNone\x20(0) r*7|@
08 0YMY"3
1# 1C*2BQ
1* 1OpH)U
#7500000 #7500000
#7750000 #7750000
0# 0C*2BQ
0* 0OpH)U
#8000000 #8000000
b11 ! b11 xkkG>
b11 & b11 WmjEh
b11 ( b11 uabMI
sHdlSome\x20(1) . sHdlSome\x20(1) $hfRN
1/ 1rop,b
#8250000 #8250000
sHdlSome\x20(1) 4 sHdlSome\x20(1) jj/6F
19 1S+Uy}
1# 1C*2BQ
1* 1OpH)U
#8500000 #8500000
#8750000 #8750000
0# 0C*2BQ
0* 0OpH)U
#9000000 #9000000
b100 ! b100 xkkG>
b10 & b10 WmjEh
b100 ( b100 uabMI
sHdlNone\x20(0) . sHdlNone\x20(0) $hfRN
0/ 0rop,b
#9250000 #9250000
sHdlNone\x20(0) 5 sHdlNone\x20(0) H72IP
0: 0vH{({
1# 1C*2BQ
1* 1OpH)U
#9500000 #9500000
#9750000 #9750000
0# 0C*2BQ
0* 0OpH)U
#10000000 #10000000
b101 ! b101 xkkG>
b1 & b1 WmjEh
b101 ( b101 uabMI
sHdlSome\x20(1) . sHdlSome\x20(1) $hfRN
#10250000 #10250000
1# 1C*2BQ
1* 1OpH)U
#10500000 #10500000
#10750000 #10750000
0# 0C*2BQ
0* 0OpH)U
#11000000 #11000000
b110 ! b110 xkkG>
b110 ( b110 uabMI
#11250000 #11250000
1# 1C*2BQ
1* 1OpH)U
#11500000 #11500000
#11750000 #11750000
0# 0C*2BQ
0* 0OpH)U
#12000000 #12000000
b111 ! b111 xkkG>
b111 ( b111 uabMI
#12250000 #12250000
1# 1C*2BQ
1* 1OpH)U
#12500000 #12500000
#12750000 #12750000
0# 0C*2BQ
0* 0OpH)U
#13000000 #13000000
0% 0m\l/p
b0 & b0 WmjEh
0' 0+3E@H
0- 06c_9_
sHdlNone\x20(0) . sHdlNone\x20(0) $hfRN
00 0Ly=US
#13250000 #13250000
1# 1C*2BQ
1* 1OpH)U
#13500000 #13500000
#13750000 #13750000
0# 0C*2BQ
0* 0OpH)U
#14000000 #14000000
b110 ! b110 xkkG>
b110 ( b110 uabMI
#14250000 #14250000
1# 1C*2BQ
1* 1OpH)U
#14500000 #14500000
#14750000 #14750000
0# 0C*2BQ
0* 0OpH)U
#15000000 #15000000
b101 ! b101 xkkG>
b101 ( b101 uabMI
#15250000 #15250000
1# 1C*2BQ
1* 1OpH)U
#15500000 #15500000
#15750000 #15750000
0# 0C*2BQ
0* 0OpH)U
#16000000 #16000000
b100 ! b100 xkkG>
b100 ( b100 uabMI
#16250000 #16250000
1# 1C*2BQ
1* 1OpH)U
#16500000 #16500000
#16750000 #16750000
0# 0C*2BQ
0* 0OpH)U
#17000000 #17000000
b11 ! b11 xkkG>
b11 ( b11 uabMI
#17250000 #17250000
1# 1C*2BQ
b11 $ b11 ueF!x
1* 1OpH)U
sHdlSome\x20(1) + sHdlSome\x20(1) [}rcZ
1, 15f=Y~
#17500000 #17500000
#17750000 #17750000
0# 0C*2BQ
0* 0OpH)U
#18000000 #18000000
b10 ! b10 xkkG>
b10 ( b10 uabMI
#18250000 #18250000
1# 1C*2BQ
b0 $ b0 ueF!x
1* 1OpH)U
sHdlNone\x20(0) + sHdlNone\x20(0) [}rcZ
0, 05f=Y~
#18500000 #18500000
#18750000 #18750000
0# 0C*2BQ
0* 0OpH)U
#19000000 #19000000
b0 ! b0 xkkG>
b0 ( b0 uabMI
#19250000 #19250000
1# 1C*2BQ
1* 1OpH)U
#19500000 #19500000
#19750000 #19750000
0# 0C*2BQ
0* 0OpH)U
#20000000 #20000000
b1 ! b1 xkkG>
b1 ( b1 uabMI
#20250000 #20250000
1# 1C*2BQ
b1 $ b1 ueF!x
1* 1OpH)U
sHdlSome\x20(1) + sHdlSome\x20(1) [}rcZ
#20500000 #20500000
#20750000 #20750000
0# 0C*2BQ
0* 0OpH)U
#21000000 #21000000
b0 ! b0 xkkG>
0" 0HoA{1
b0 ( b0 uabMI
0) 0LEn[l
#21250000 #21250000
1# 1C*2BQ
b0 $ b0 ueF!x
1* 1OpH)U
sHdlNone\x20(0) + sHdlNone\x20(0) [}rcZ
#21500000 #21500000
#21750000 #21750000
0# 0C*2BQ
0* 0OpH)U
#22000000 #22000000

View file

@ -1356,20 +1356,20 @@ Simulation {
}, },
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
1, 1 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
1, 1 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
], ],
}, },
big_slots: StatePart { big_slots: StatePart {
@ -1415,6 +1415,22 @@ Simulation {
0, 0,
0, 0,
0, 0,
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0 (modified),
0, 0,
0, 0,
0, 0,
@ -1434,54 +1450,38 @@ Simulation {
0, 0,
0, 0,
0, 0,
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -2391,6 +2391,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<3>, ty: UInt<3>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2399,6 +2400,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2407,6 +2409,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -2416,6 +2419,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2425,6 +2429,7 @@ Simulation {
index: StatePartIndex<BigSlots>(4), index: StatePartIndex<BigSlots>(4),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2434,6 +2439,7 @@ Simulation {
index: StatePartIndex<BigSlots>(5), index: StatePartIndex<BigSlots>(5),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2443,6 +2449,7 @@ Simulation {
index: StatePartIndex<BigSlots>(6), index: StatePartIndex<BigSlots>(6),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2452,6 +2459,7 @@ Simulation {
index: StatePartIndex<BigSlots>(7), index: StatePartIndex<BigSlots>(7),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2461,6 +2469,7 @@ Simulation {
index: StatePartIndex<BigSlots>(8), index: StatePartIndex<BigSlots>(8),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2470,6 +2479,7 @@ Simulation {
index: StatePartIndex<BigSlots>(9), index: StatePartIndex<BigSlots>(9),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2479,6 +2489,7 @@ Simulation {
index: StatePartIndex<BigSlots>(10), index: StatePartIndex<BigSlots>(10),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2488,6 +2499,7 @@ Simulation {
index: StatePartIndex<BigSlots>(11), index: StatePartIndex<BigSlots>(11),
ty: UInt<3>, ty: UInt<3>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2496,6 +2508,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(12), index: StatePartIndex<BigSlots>(12),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2504,6 +2517,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(13), index: StatePartIndex<BigSlots>(13),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -2513,6 +2527,7 @@ Simulation {
index: StatePartIndex<BigSlots>(14), index: StatePartIndex<BigSlots>(14),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2522,6 +2537,7 @@ Simulation {
index: StatePartIndex<BigSlots>(15), index: StatePartIndex<BigSlots>(15),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2531,6 +2547,7 @@ Simulation {
index: StatePartIndex<BigSlots>(16), index: StatePartIndex<BigSlots>(16),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2540,6 +2557,7 @@ Simulation {
index: StatePartIndex<BigSlots>(17), index: StatePartIndex<BigSlots>(17),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2549,6 +2567,7 @@ Simulation {
index: StatePartIndex<BigSlots>(18), index: StatePartIndex<BigSlots>(18),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2558,6 +2577,7 @@ Simulation {
index: StatePartIndex<BigSlots>(19), index: StatePartIndex<BigSlots>(19),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2567,6 +2587,7 @@ Simulation {
index: StatePartIndex<BigSlots>(20), index: StatePartIndex<BigSlots>(20),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2576,6 +2597,7 @@ Simulation {
index: StatePartIndex<BigSlots>(21), index: StatePartIndex<BigSlots>(21),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2584,6 +2606,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(22), index: StatePartIndex<BigSlots>(22),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2592,6 +2615,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(23), index: StatePartIndex<BigSlots>(23),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2600,6 +2624,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(24), index: StatePartIndex<BigSlots>(24),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2608,6 +2633,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(25), index: StatePartIndex<BigSlots>(25),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2616,6 +2642,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(26), index: StatePartIndex<BigSlots>(26),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2624,6 +2651,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(27), index: StatePartIndex<BigSlots>(27),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2632,6 +2660,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(28), index: StatePartIndex<BigSlots>(28),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2640,6 +2669,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(29), index: StatePartIndex<BigSlots>(29),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2649,6 +2679,7 @@ Simulation {
index: StatePartIndex<BigSlots>(30), index: StatePartIndex<BigSlots>(30),
ty: UInt<3>, ty: UInt<3>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2657,6 +2688,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(31), index: StatePartIndex<BigSlots>(31),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2665,6 +2697,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(32), index: StatePartIndex<BigSlots>(32),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -2674,6 +2707,7 @@ Simulation {
index: StatePartIndex<BigSlots>(33), index: StatePartIndex<BigSlots>(33),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2683,6 +2717,7 @@ Simulation {
index: StatePartIndex<BigSlots>(34), index: StatePartIndex<BigSlots>(34),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2692,6 +2727,7 @@ Simulation {
index: StatePartIndex<BigSlots>(35), index: StatePartIndex<BigSlots>(35),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2701,6 +2737,7 @@ Simulation {
index: StatePartIndex<BigSlots>(36), index: StatePartIndex<BigSlots>(36),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2710,6 +2747,7 @@ Simulation {
index: StatePartIndex<BigSlots>(37), index: StatePartIndex<BigSlots>(37),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2719,6 +2757,7 @@ Simulation {
index: StatePartIndex<BigSlots>(38), index: StatePartIndex<BigSlots>(38),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2728,6 +2767,7 @@ Simulation {
index: StatePartIndex<BigSlots>(39), index: StatePartIndex<BigSlots>(39),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2737,6 +2777,7 @@ Simulation {
index: StatePartIndex<BigSlots>(40), index: StatePartIndex<BigSlots>(40),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2746,6 +2787,7 @@ Simulation {
index: StatePartIndex<BigSlots>(57), index: StatePartIndex<BigSlots>(57),
ty: UInt<3>, ty: UInt<3>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2754,6 +2796,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(58), index: StatePartIndex<BigSlots>(58),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2762,6 +2805,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(59), index: StatePartIndex<BigSlots>(59),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x1, last_state: 0x1,
}, },
@ -2771,6 +2815,7 @@ Simulation {
index: StatePartIndex<BigSlots>(60), index: StatePartIndex<BigSlots>(60),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2780,6 +2825,7 @@ Simulation {
index: StatePartIndex<BigSlots>(61), index: StatePartIndex<BigSlots>(61),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2789,6 +2835,7 @@ Simulation {
index: StatePartIndex<BigSlots>(62), index: StatePartIndex<BigSlots>(62),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2798,6 +2845,7 @@ Simulation {
index: StatePartIndex<BigSlots>(63), index: StatePartIndex<BigSlots>(63),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2807,6 +2855,7 @@ Simulation {
index: StatePartIndex<BigSlots>(64), index: StatePartIndex<BigSlots>(64),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2816,6 +2865,7 @@ Simulation {
index: StatePartIndex<BigSlots>(65), index: StatePartIndex<BigSlots>(65),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2825,6 +2875,7 @@ Simulation {
index: StatePartIndex<BigSlots>(66), index: StatePartIndex<BigSlots>(66),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2834,6 +2885,7 @@ Simulation {
index: StatePartIndex<BigSlots>(67), index: StatePartIndex<BigSlots>(67),
ty: UInt<8>, ty: UInt<8>,
}, },
maybe_changed: true,
state: 0x00, state: 0x00,
last_state: 0x00, last_state: 0x00,
}, },
@ -2842,6 +2894,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(68), index: StatePartIndex<BigSlots>(68),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2850,6 +2903,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(69), index: StatePartIndex<BigSlots>(69),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2858,6 +2912,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(70), index: StatePartIndex<BigSlots>(70),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2866,6 +2921,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(71), index: StatePartIndex<BigSlots>(71),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2874,6 +2930,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(72), index: StatePartIndex<BigSlots>(72),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2882,6 +2939,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(73), index: StatePartIndex<BigSlots>(73),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2890,6 +2948,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(74), index: StatePartIndex<BigSlots>(74),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -2898,6 +2957,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(75), index: StatePartIndex<BigSlots>(75),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },

File diff suppressed because it is too large Load diff

View file

@ -207,11 +207,11 @@ Simulation {
-2, -2,
-2, -2,
15, 15,
-2, -2 (modified),
14, 14 (modified),
5, 5 (modified),
1, 1 (modified),
15, 15 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -445,6 +445,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0xa, state: 0xa,
last_state: 0x3, last_state: 0x3,
}, },
@ -454,6 +455,7 @@ Simulation {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
ty: SInt<2>, ty: SInt<2>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x3, last_state: 0x3,
}, },
@ -463,6 +465,7 @@ Simulation {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
ty: SInt<2>, ty: SInt<2>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -472,6 +475,7 @@ Simulation {
index: StatePartIndex<BigSlots>(3), index: StatePartIndex<BigSlots>(3),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0xf, state: 0xf,
last_state: 0xe, last_state: 0xe,
}, },
@ -481,6 +485,7 @@ Simulation {
index: StatePartIndex<BigSlots>(8), index: StatePartIndex<BigSlots>(8),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0xa, state: 0xa,
last_state: 0x3, last_state: 0x3,
}, },
@ -490,6 +495,7 @@ Simulation {
index: StatePartIndex<BigSlots>(9), index: StatePartIndex<BigSlots>(9),
ty: SInt<2>, ty: SInt<2>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x3, last_state: 0x3,
}, },
@ -499,6 +505,7 @@ Simulation {
index: StatePartIndex<BigSlots>(10), index: StatePartIndex<BigSlots>(10),
ty: SInt<2>, ty: SInt<2>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -508,6 +515,7 @@ Simulation {
index: StatePartIndex<BigSlots>(11), index: StatePartIndex<BigSlots>(11),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0xf, state: 0xf,
last_state: 0xe, last_state: 0xe,
}, },
@ -517,6 +525,7 @@ Simulation {
index: StatePartIndex<BigSlots>(4), index: StatePartIndex<BigSlots>(4),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0xa, state: 0xa,
last_state: 0x3, last_state: 0x3,
}, },
@ -526,6 +535,7 @@ Simulation {
index: StatePartIndex<BigSlots>(5), index: StatePartIndex<BigSlots>(5),
ty: SInt<2>, ty: SInt<2>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x3, last_state: 0x3,
}, },
@ -535,6 +545,7 @@ Simulation {
index: StatePartIndex<BigSlots>(6), index: StatePartIndex<BigSlots>(6),
ty: SInt<2>, ty: SInt<2>,
}, },
maybe_changed: true,
state: 0x2, state: 0x2,
last_state: 0x2, last_state: 0x2,
}, },
@ -544,6 +555,7 @@ Simulation {
index: StatePartIndex<BigSlots>(7), index: StatePartIndex<BigSlots>(7),
ty: UInt<4>, ty: UInt<4>,
}, },
maybe_changed: true,
state: 0xf, state: 0xf,
last_state: 0xe, last_state: 0xe,
}, },

View file

@ -1,47 +1,34 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module mod1 $end $scope module mod1 $end
$scope struct o $end $scope struct o $end
$var wire 4 ! i $end $var wire 4 avK(^ i $end
$var wire 2 " o $end $var wire 2 Q2~aG o $end
$var wire 2 # i2 $end $var wire 2 DXK'| i2 $end
$var wire 4 $ o2 $end $var wire 4 cPuix o2 $end
$upscope $end $upscope $end
$scope struct child $end $scope module child $end
$var wire 4 ) i $end $var wire 4 ($5K7 i $end
$var wire 2 * o $end $var wire 2 %6Wv" o $end
$var wire 2 + i2 $end $var wire 2 +|-AU i2 $end
$var wire 4 , o2 $end $var wire 4 Hw?%j o2 $end
$upscope $end
$scope module mod1_child $end
$var wire 4 % i $end
$var wire 2 & o $end
$var wire 2 ' i2 $end
$var wire 4 ( o2 $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
b11 ! b11 avK(^
b11 " b11 Q2~aG
b10 # b10 DXK'|
b1110 $ b1110 cPuix
b11 % b11 ($5K7
b11 & b11 %6Wv"
b10 ' b10 +|-AU
b1110 ( b1110 Hw?%j
b11 )
b11 *
b10 +
b1110 ,
$end $end
#1000000 #1000000
b1010 ! b1010 avK(^
b10 " b10 Q2~aG
b1111 $ b1111 cPuix
b1010 % b1010 ($5K7
b10 & b10 %6Wv"
b1111 ( b1111 Hw?%j
b1010 )
b10 *
b1111 ,
#2000000 #2000000

View file

@ -185,11 +185,11 @@ Simulation {
}, },
small_slots: StatePart { small_slots: StatePart {
value: [ value: [
1, 1 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
], ],
}, },
big_slots: StatePart { big_slots: StatePart {
@ -197,11 +197,11 @@ Simulation {
0, 0,
0, 0,
0, 0,
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
0, 0 (modified),
], ],
}, },
sim_only_slots: StatePart { sim_only_slots: StatePart {
@ -373,6 +373,7 @@ Simulation {
["a","b"], ["a","b"],
), ),
}, },
maybe_changed: true,
state: PhantomConst, state: PhantomConst,
last_state: PhantomConst, last_state: PhantomConst,
}, },
@ -383,6 +384,7 @@ Simulation {
["a","b"], ["a","b"],
), ),
}, },
maybe_changed: true,
state: PhantomConst, state: PhantomConst,
last_state: PhantomConst, last_state: PhantomConst,
}, },
@ -392,6 +394,7 @@ Simulation {
index: StatePartIndex<BigSlots>(0), index: StatePartIndex<BigSlots>(0),
ty: UInt<0>, ty: UInt<0>,
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -400,6 +403,7 @@ Simulation {
kind: BigBool { kind: BigBool {
index: StatePartIndex<BigSlots>(1), index: StatePartIndex<BigSlots>(1),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -408,6 +412,7 @@ Simulation {
kind: BigClock { kind: BigClock {
index: StatePartIndex<BigSlots>(2), index: StatePartIndex<BigSlots>(2),
}, },
maybe_changed: true,
state: 0x0, state: 0x0,
last_state: 0x0, last_state: 0x0,
}, },
@ -418,6 +423,7 @@ Simulation {
"mem_element", "mem_element",
), ),
}, },
maybe_changed: true,
state: PhantomConst, state: PhantomConst,
last_state: PhantomConst, last_state: PhantomConst,
}, },

View file

@ -1,31 +1,31 @@
$timescale 1 ps $end $timescale 1 ps $end
$scope module phantom_const $end $scope module phantom_const $end
$scope struct out $end $scope struct out $end
$var string 1 ! \[0] $end $var string 1 Ru)8A \[0] $end
$var string 1 " \[1] $end $var string 1 y&ssi \[1] $end
$upscope $end $upscope $end
$scope struct mem $end $scope struct mem $end
$scope struct contents $end $scope struct contents $end
$scope struct \[0] $end $scope struct \[0] $end
$var string 1 ' mem $end $var string 1 =+olp mem $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$scope struct r0 $end $scope struct r0 $end
$var string 0 # addr $end $var string 0 U5SS1 addr $end
$var wire 1 $ en $end $var wire 1 rx@_T en $end
$var wire 1 % clk $end $var wire 1 o[(us clk $end
$var string 1 & data $end $var string 1 %Bg(6 data $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$upscope $end $upscope $end
$enddefinitions $end $enddefinitions $end
$dumpvars $dumpvars
s0 ' s0 =+olp
sPhantomConst([\"a\",\"b\"]) ! sPhantomConst([\"a\",\"b\"]) Ru)8A
sPhantomConst([\"a\",\"b\"]) " sPhantomConst([\"a\",\"b\"]) y&ssi
s0 # s0 U5SS1
0$ 0rx@_T
0% 0o[(us
sPhantomConst(\"mem_element\") & sPhantomConst(\"mem_element\") %Bg(6
$end $end
#1000000 #1000000

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more