forked from libre-chip/fayalite
Compare commits
35 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ffca1a279d | |||
| d4d9706798 | |||
| 5d68885eaf | |||
| 31353862ce | |||
| b1116c4a1a | |||
| 6902aea3a6 | |||
| 1880ed682f | |||
| cf3e6cfc6b | |||
| ea183eac87 | |||
| 26224abe1c | |||
| 2266315944 | |||
| 7e9d7739fb | |||
| 7516ec3c24 | |||
| 8e4eeef723 | |||
| 402f457c68 | |||
| 8cff3687f7 | |||
| 80b92c7dd3 | |||
| 2aa41137d4 | |||
| a0b2dc085c | |||
| a8a541b357 | |||
| 52c41bb5db | |||
| a93e66d8ab | |||
| eb3ca59053 | |||
| dbed947408 | |||
| cb4e1f42c0 | |||
| 8c270b0e35 | |||
| c632e5d570 | |||
| 1bc835803b | |||
| 9db3240644 | |||
| caa097db0b | |||
| a96efa9696 | |||
| 4ac1bcbc0a | |||
| 39810043ea | |||
| 26b0dc3fd8 | |||
| 11281a9842 |
158 changed files with 91662 additions and 11426 deletions
|
|
@ -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
6
Cargo.lock
generated
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,7 +585,9 @@ 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,
|
||||||
}
|
};
|
||||||
|
mask_type_match_variant_struct.to_tokens(tokens);
|
||||||
|
create_struct_debug_impl(&mask_type_match_variant_struct, mask_type_name, None)
|
||||||
.to_tokens(tokens);
|
.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 {
|
||||||
|
|
@ -572,9 +595,9 @@ impl ToTokens for ParsedBundle {
|
||||||
::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);
|
.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);
|
||||||
|
}
|
||||||
let this_token = Ident::new("__this", span);
|
let this_token = Ident::new("__this", span);
|
||||||
let fields_token = Ident::new("__fields", span);
|
let fields_token = Ident::new("__fields", span);
|
||||||
let self_token = Token;
|
let self_token = Token;
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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_token: Token,
|
||||||
|
|
@ -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,
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -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)]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)*
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,10 @@ impl TargetedAnnotation {
|
||||||
}
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn assert_valid_target(target: Interned<Target>) {
|
pub fn assert_valid_target(target: Interned<Target>) {
|
||||||
assert!(target.is_static(), "can't annotate non-static targets");
|
assert!(
|
||||||
|
target.is_valid_annotation_target(),
|
||||||
|
"not a valid annotation target: {target:?}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
pub fn target(&self) -> Interned<Target> {
|
pub fn target(&self) -> Interned<Target> {
|
||||||
self.target
|
self.target
|
||||||
|
|
|
||||||
|
|
@ -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>;
|
||||||
|
|
|
||||||
|
|
@ -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 = ();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>(
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
bundle::{Bundle, BundleType},
|
bundle::{Bundle, BundleType},
|
||||||
enum_::{Enum, EnumType},
|
enum_::{Enum, EnumType},
|
||||||
expr::target::{GetTarget, Target},
|
expr::target::{GetTarget, Target},
|
||||||
|
formal::FormalInput,
|
||||||
int::{Bool, DynSize, IntType, SIntValue, Size, SizeType, UInt, UIntType, UIntValue},
|
int::{Bool, DynSize, IntType, SIntValue, Size, SizeType, UInt, UIntType, UIntValue},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{DynPortType, MemPort, PortType},
|
memory::{DynPortType, MemPort, PortType},
|
||||||
|
|
@ -17,7 +18,7 @@ use crate::{
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
||||||
sim::value::{SimValue, ToSimValue, ToSimValueWithType},
|
sim::value::{SimValue, ToSimValue, ToSimValueWithType},
|
||||||
ty::{CanonicalType, OpaqueSimValue, StaticType, Type, TypeWithDeref},
|
ty::{CanonicalType, OpaqueSimValue, StaticType, TraceAsString, Type, TypeWithDeref},
|
||||||
util::{ConstBool, ConstUsize},
|
util::{ConstBool, ConstUsize},
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
};
|
};
|
||||||
|
|
@ -218,6 +219,8 @@ expr_enum! {
|
||||||
SliceSInt(ops::SliceSInt),
|
SliceSInt(ops::SliceSInt),
|
||||||
CastToBits(ops::CastToBits),
|
CastToBits(ops::CastToBits),
|
||||||
CastBitsTo(ops::CastBitsTo),
|
CastBitsTo(ops::CastBitsTo),
|
||||||
|
ToTraceAsString(ops::ToTraceAsString),
|
||||||
|
TraceAsStringAsInner(ops::TraceAsStringAsInner),
|
||||||
ModuleIO(ModuleIO<CanonicalType>),
|
ModuleIO(ModuleIO<CanonicalType>),
|
||||||
Instance(Instance<Bundle>),
|
Instance(Instance<Bundle>),
|
||||||
Wire(Wire<CanonicalType>),
|
Wire(Wire<CanonicalType>),
|
||||||
|
|
@ -225,6 +228,8 @@ expr_enum! {
|
||||||
RegSync(Reg<CanonicalType, SyncReset>),
|
RegSync(Reg<CanonicalType, SyncReset>),
|
||||||
RegAsync(Reg<CanonicalType, AsyncReset>),
|
RegAsync(Reg<CanonicalType, AsyncReset>),
|
||||||
MemPort(MemPort<DynPortType>),
|
MemPort(MemPort<DynPortType>),
|
||||||
|
FormalInput(FormalInput),
|
||||||
|
SimIoForGlobal(ops::SimIoForGlobal),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -389,6 +394,35 @@ impl<T: Type> Expr<T> {
|
||||||
__flow: this.__flow,
|
__flow: this.__flow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn as_trace_as_string(this: Self, ty: TraceAsString<T>) -> Expr<TraceAsString<T>> {
|
||||||
|
assert_eq!(this.ty(), ty.inner_ty());
|
||||||
|
ops::ToTraceAsString::new(Expr::canonical(this), ty).to_expr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Expr<CanonicalType> {
|
||||||
|
pub fn unwrap_transparent_types(mut this: Self) -> Expr<CanonicalType> {
|
||||||
|
loop {
|
||||||
|
match this.ty() {
|
||||||
|
CanonicalType::UInt(_)
|
||||||
|
| CanonicalType::SInt(_)
|
||||||
|
| CanonicalType::Bool(_)
|
||||||
|
| CanonicalType::Array(_)
|
||||||
|
| CanonicalType::Enum(_)
|
||||||
|
| CanonicalType::Bundle(_)
|
||||||
|
| CanonicalType::AsyncReset(_)
|
||||||
|
| CanonicalType::SyncReset(_)
|
||||||
|
| CanonicalType::Reset(_)
|
||||||
|
| CanonicalType::Clock(_)
|
||||||
|
| CanonicalType::PhantomConst(_)
|
||||||
|
| CanonicalType::DynSimOnly(_) => return this,
|
||||||
|
CanonicalType::TraceAsString(_) => {
|
||||||
|
this = *Expr::<TraceAsString>::from_canonical(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Type> ToLiteralBits for Expr<T> {
|
impl<T: Type> ToLiteralBits for Expr<T> {
|
||||||
|
|
@ -1692,3 +1726,204 @@ impl<'a, T: Type> ToSimValueInner<'a> for &'a SimValue<T> {
|
||||||
Cow::Borrowed(&**this)
|
Cow::Borrowed(&**this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ToTraceAsString: ValueType {
|
||||||
|
type Output: ValueType<Type = TraceAsString<Self::Type>, ValueCategory = Self::ValueCategory>;
|
||||||
|
fn to_trace_as_string_with_ty(&self, ty: TraceAsString<Self::Type>) -> Self::Output;
|
||||||
|
fn into_trace_as_string_with_ty(self, ty: TraceAsString<Self::Type>) -> Self::Output
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn to_trace_as_string(&self) -> Self::Output;
|
||||||
|
fn into_trace_as_string(self) -> Self::Output
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
T: ?Sized
|
||||||
|
+ ValueType
|
||||||
|
+ ToTraceAsStringImpl<<Self as ValueType>::Type, <Self as ValueType>::ValueCategory>,
|
||||||
|
> ToTraceAsString for T
|
||||||
|
{
|
||||||
|
type Output = T::ImplOutput;
|
||||||
|
fn to_trace_as_string_with_ty(&self, ty: TraceAsString<Self::Type>) -> Self::Output {
|
||||||
|
Self::to_trace_as_string_with_ty_impl(self, ty)
|
||||||
|
}
|
||||||
|
fn into_trace_as_string_with_ty(self, ty: TraceAsString<Self::Type>) -> Self::Output
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Self::into_trace_as_string_with_ty_impl(self, ty)
|
||||||
|
}
|
||||||
|
fn to_trace_as_string(&self) -> Self::Output {
|
||||||
|
Self::to_trace_as_string_impl(self)
|
||||||
|
}
|
||||||
|
fn into_trace_as_string(self) -> Self::Output
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Self::into_trace_as_string_impl(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ToTraceAsStringImpl<Ty: Type, C: value_category::ValueCategory> {
|
||||||
|
type ImplOutput: ValueType<Type = TraceAsString<Ty>, ValueCategory = C>;
|
||||||
|
fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput;
|
||||||
|
fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn to_trace_as_string_with_ty_impl(this: &Self, ty: TraceAsString<Ty>) -> Self::ImplOutput;
|
||||||
|
fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString<Ty>) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + crate::sim::value::ToSimValue>
|
||||||
|
ToTraceAsStringImpl<T::Type, value_category::ValueCategoryValue> for T
|
||||||
|
{
|
||||||
|
type ImplOutput = crate::ty::TraceAsStringSimValue<T::Type>;
|
||||||
|
|
||||||
|
fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput {
|
||||||
|
crate::ty::TraceAsStringSimValue::new(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
crate::ty::TraceAsStringSimValue::new(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_trace_as_string_with_ty_impl(
|
||||||
|
this: &Self,
|
||||||
|
ty: TraceAsString<T::Type>,
|
||||||
|
) -> Self::ImplOutput {
|
||||||
|
crate::ty::TraceAsStringSimValue::new_with_ty(this, ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString<T::Type>) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
crate::ty::TraceAsStringSimValue::new_with_ty(this, ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + crate::sim::value::ToSimValue>
|
||||||
|
ToTraceAsStringImpl<T::Type, value_category::ValueCategorySimValue> for T
|
||||||
|
{
|
||||||
|
type ImplOutput = SimValue<TraceAsString<T::Type>>;
|
||||||
|
|
||||||
|
fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput {
|
||||||
|
crate::ty::TraceAsStringSimValue::new(this).into_sim_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
crate::ty::TraceAsStringSimValue::new(this).into_sim_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_trace_as_string_with_ty_impl(
|
||||||
|
this: &Self,
|
||||||
|
ty: TraceAsString<T::Type>,
|
||||||
|
) -> Self::ImplOutput {
|
||||||
|
crate::ty::TraceAsStringSimValue::new_with_ty(this, ty).into_sim_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString<T::Type>) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
crate::ty::TraceAsStringSimValue::new_with_ty(this, ty).into_sim_value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + ToExpr> ToTraceAsStringImpl<T::Type, value_category::ValueCategoryExpr> for T {
|
||||||
|
type ImplOutput = Expr<TraceAsString<T::Type>>;
|
||||||
|
|
||||||
|
fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput {
|
||||||
|
let this = this.to_expr();
|
||||||
|
ops::ToTraceAsString::new(Expr::canonical(this), TraceAsString::new(this.ty())).to_expr()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let this = this.to_expr();
|
||||||
|
ops::ToTraceAsString::new(Expr::canonical(this), TraceAsString::new(this.ty())).to_expr()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_trace_as_string_with_ty_impl(
|
||||||
|
this: &Self,
|
||||||
|
ty: TraceAsString<T::Type>,
|
||||||
|
) -> Self::ImplOutput {
|
||||||
|
let this = this.to_expr();
|
||||||
|
ops::ToTraceAsString::new(
|
||||||
|
Expr::canonical(this),
|
||||||
|
ty.with_new_inner_ty(this.ty().intern_sized()),
|
||||||
|
)
|
||||||
|
.to_expr()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString<T::Type>) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let this = this.to_expr();
|
||||||
|
ops::ToTraceAsString::new(
|
||||||
|
Expr::canonical(this),
|
||||||
|
ty.with_new_inner_ty(this.ty().intern_sized()),
|
||||||
|
)
|
||||||
|
.to_expr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + ValueType> ToTraceAsStringImpl<T::Type, value_category::ValueCategoryValueless>
|
||||||
|
for T
|
||||||
|
{
|
||||||
|
type ImplOutput = Valueless<TraceAsString<T::Type>>;
|
||||||
|
|
||||||
|
fn to_trace_as_string_impl(this: &Self) -> Self::ImplOutput {
|
||||||
|
Valueless::new(TraceAsString::new(this.ty()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_impl(this: Self) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Valueless::new(TraceAsString::new(this.ty()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_trace_as_string_with_ty_impl(
|
||||||
|
this: &Self,
|
||||||
|
ty: TraceAsString<T::Type>,
|
||||||
|
) -> Self::ImplOutput {
|
||||||
|
Valueless::new(ty.with_new_inner_ty(this.ty().intern_sized()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_trace_as_string_with_ty_impl(this: Self, ty: TraceAsString<T::Type>) -> Self::ImplOutput
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
Valueless::new(ty.with_new_inner_ty(this.ty().intern_sized()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToLiteralBits for FormalInput {
|
||||||
|
fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> {
|
||||||
|
Err(NotALiteralExpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToExpr for FormalInput {
|
||||||
|
fn to_expr(&self) -> Expr<Self::Type> {
|
||||||
|
Expr {
|
||||||
|
__enum: ExprEnum::FormalInput(*self).intern_sized(),
|
||||||
|
__ty: self.ty(),
|
||||||
|
__flow: self.flow(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ use crate::{
|
||||||
ToExpr, ToLiteralBits, ToSimValueInner, ToValueless, ValueType, Valueless,
|
ToExpr, ToLiteralBits, ToSimValueInner, ToValueless, ValueType, Valueless,
|
||||||
target::{
|
target::{
|
||||||
GetTarget, Target, TargetPathArrayElement, TargetPathBundleField,
|
GetTarget, Target, TargetPathArrayElement, TargetPathBundleField,
|
||||||
TargetPathDynArrayElement, TargetPathElement,
|
TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString,
|
||||||
|
TargetPathTraceAsStringInner,
|
||||||
},
|
},
|
||||||
value_category::ValueCategoryExpr,
|
value_category::ValueCategoryExpr,
|
||||||
},
|
},
|
||||||
|
formal::FormalInput,
|
||||||
int::{
|
int::{
|
||||||
Bool, BoolOrIntType, DynSize, IntType, KnownSize, SInt, SIntType, SIntValue, Size, UInt,
|
Bool, BoolOrIntType, DynSize, IntType, KnownSize, SInt, SIntType, SIntValue, Size, UInt,
|
||||||
UIntType, UIntValue,
|
UIntType, UIntValue,
|
||||||
|
|
@ -27,7 +29,7 @@ use crate::{
|
||||||
ToSyncReset,
|
ToSyncReset,
|
||||||
},
|
},
|
||||||
sim::value::{SimValue, ToSimValue},
|
sim::value::{SimValue, ToSimValue},
|
||||||
ty::{CanonicalType, StaticType, Type},
|
ty::{CanonicalType, StaticType, TraceAsString, Type},
|
||||||
util::ConstUsize,
|
util::ConstUsize,
|
||||||
};
|
};
|
||||||
use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView};
|
use bitvec::{order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView};
|
||||||
|
|
@ -44,6 +46,9 @@ use std::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test_ops_impls;
|
||||||
|
|
||||||
macro_rules! make_impls {
|
macro_rules! make_impls {
|
||||||
(
|
(
|
||||||
$([$($args:tt)*])?
|
$([$($args:tt)*])?
|
||||||
|
|
@ -579,10 +584,9 @@ 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)* }};
|
||||||
}
|
}
|
||||||
pub(crate) use make_impls;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_ops_impls;
|
pub(crate) use make_impls;
|
||||||
|
|
||||||
macro_rules! impl_simple_binary_op_trait {
|
macro_rules! impl_simple_binary_op_trait {
|
||||||
(
|
(
|
||||||
|
|
@ -4692,3 +4696,255 @@ impl<This: ExprFromIterator<A>, A> FromIterator<A> for Expr<This> {
|
||||||
This::expr_from_iter(iter)
|
This::expr_from_iter(iter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ToTraceAsString<T: Type = CanonicalType> {
|
||||||
|
inner: Expr<CanonicalType>,
|
||||||
|
ty: TraceAsString<T>,
|
||||||
|
literal_bits: Result<Interned<BitSlice>, NotALiteralExpr>,
|
||||||
|
target: Option<Interned<Target>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> fmt::Debug for ToTraceAsString<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let Self {
|
||||||
|
inner,
|
||||||
|
ty: _,
|
||||||
|
literal_bits: _,
|
||||||
|
target: _,
|
||||||
|
} = self;
|
||||||
|
f.debug_struct("ToTraceAsString")
|
||||||
|
.field("inner", inner)
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToTraceAsString<T> {
|
||||||
|
pub fn new(inner: Expr<CanonicalType>, ty: TraceAsString<T>) -> Self {
|
||||||
|
assert_eq!(inner.ty(), ty.inner_ty().canonical());
|
||||||
|
let literal_bits = inner.to_literal_bits();
|
||||||
|
let target = inner.target().map(|base| {
|
||||||
|
Intern::intern_sized(
|
||||||
|
base.join(TargetPathElement::intern_sized(
|
||||||
|
TargetPathToTraceAsString {
|
||||||
|
ty: ty.canonical_trace_as_string(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
))
|
||||||
|
.canonicalized(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
Self {
|
||||||
|
inner,
|
||||||
|
ty,
|
||||||
|
literal_bits,
|
||||||
|
target,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn inner(self) -> Expr<CanonicalType> {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> GetTarget for ToTraceAsString<T> {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
self.target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToLiteralBits for ToTraceAsString<T> {
|
||||||
|
fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> {
|
||||||
|
self.literal_bits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ValueType for ToTraceAsString<T> {
|
||||||
|
type Type = TraceAsString<T>;
|
||||||
|
type ValueCategory = ValueCategoryExpr;
|
||||||
|
|
||||||
|
fn ty(&self) -> Self::Type {
|
||||||
|
self.ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToExpr for ToTraceAsString<T> {
|
||||||
|
fn to_expr(&self) -> Expr<Self::Type> {
|
||||||
|
Expr {
|
||||||
|
__enum: ExprEnum::ToTraceAsString(ToTraceAsString {
|
||||||
|
inner: self.inner,
|
||||||
|
ty: self.ty.canonical_trace_as_string(),
|
||||||
|
literal_bits: self.literal_bits,
|
||||||
|
target: self.target,
|
||||||
|
})
|
||||||
|
.intern(),
|
||||||
|
__ty: self.ty,
|
||||||
|
__flow: Expr::flow(self.inner),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct TraceAsStringAsInner<T: Type = CanonicalType> {
|
||||||
|
arg: Expr<TraceAsString<CanonicalType>>,
|
||||||
|
ty: T,
|
||||||
|
literal_bits: Result<Interned<BitSlice>, NotALiteralExpr>,
|
||||||
|
target: Option<Interned<Target>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> fmt::Debug for TraceAsStringAsInner<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let Self {
|
||||||
|
arg,
|
||||||
|
ty: _,
|
||||||
|
literal_bits: _,
|
||||||
|
target: _,
|
||||||
|
} = self;
|
||||||
|
f.debug_struct("TraceAsStringAsInner")
|
||||||
|
.field("arg", arg)
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> TraceAsStringAsInner<T> {
|
||||||
|
pub fn from_arg_and_ty(arg: Expr<TraceAsString<CanonicalType>>, ty: T) -> Self {
|
||||||
|
assert_eq!(arg.ty().inner_ty(), ty.canonical());
|
||||||
|
let literal_bits = arg.to_literal_bits();
|
||||||
|
let target = arg.target().map(|base| {
|
||||||
|
Intern::intern_sized(
|
||||||
|
base.join(TargetPathElement::intern_sized(
|
||||||
|
TargetPathTraceAsStringInner {}.into(),
|
||||||
|
))
|
||||||
|
.canonicalized(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
Self {
|
||||||
|
arg,
|
||||||
|
ty,
|
||||||
|
literal_bits,
|
||||||
|
target,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new(arg: Expr<TraceAsString<T>>) -> Self {
|
||||||
|
Self::from_arg_and_ty(
|
||||||
|
Expr {
|
||||||
|
__enum: arg.__enum,
|
||||||
|
__ty: arg.__ty.canonical_trace_as_string(),
|
||||||
|
__flow: arg.__flow,
|
||||||
|
},
|
||||||
|
arg.ty().inner_ty(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pub fn arg(self) -> Expr<TraceAsString<CanonicalType>> {
|
||||||
|
self.arg
|
||||||
|
}
|
||||||
|
pub fn arg_typed(self) -> Expr<TraceAsString<T>> {
|
||||||
|
Expr {
|
||||||
|
__enum: self.arg.__enum,
|
||||||
|
__ty: TraceAsString::from_canonical_trace_as_string(self.arg.__ty),
|
||||||
|
__flow: self.arg.__flow,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> GetTarget for TraceAsStringAsInner<T> {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
self.target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToLiteralBits for TraceAsStringAsInner<T> {
|
||||||
|
fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> {
|
||||||
|
self.literal_bits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ValueType for TraceAsStringAsInner<T> {
|
||||||
|
type Type = T;
|
||||||
|
type ValueCategory = ValueCategoryExpr;
|
||||||
|
|
||||||
|
fn ty(&self) -> Self::Type {
|
||||||
|
self.ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToExpr for TraceAsStringAsInner<T> {
|
||||||
|
fn to_expr(&self) -> Expr<Self::Type> {
|
||||||
|
Expr {
|
||||||
|
__enum: ExprEnum::TraceAsStringAsInner(TraceAsStringAsInner {
|
||||||
|
arg: self.arg,
|
||||||
|
ty: self.ty.canonical(),
|
||||||
|
literal_bits: self.literal_bits,
|
||||||
|
target: self.target,
|
||||||
|
})
|
||||||
|
.intern(),
|
||||||
|
__ty: self.ty,
|
||||||
|
__flow: Expr::flow(self.arg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
/// The [`Simulation::io()`] equivalent for a global signal, this is a flipped version of a global signal
|
||||||
|
/// that allows you to e.g. use [`Simulation::write()`] to write to [`formal_global_clock()`].
|
||||||
|
///
|
||||||
|
/// [`Simulation::io()`]: crate::sim::Simulation::io
|
||||||
|
/// [`Simulation::write()`]: crate::sim::Simulation::write
|
||||||
|
/// [`formal_global_clock()`]: crate::formal::formal_global_clock
|
||||||
|
pub struct SimIoForGlobal {
|
||||||
|
global: FormalInput,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for SimIoForGlobal {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_tuple("SimIoForGlobal").field(&self.global).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimIoForGlobal {
|
||||||
|
pub fn new(global: FormalInput) -> Self {
|
||||||
|
Self { global }
|
||||||
|
}
|
||||||
|
pub fn global(self) -> FormalInput {
|
||||||
|
self.global
|
||||||
|
}
|
||||||
|
pub(crate) fn must_connect_to(self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
pub fn flow(self) -> Flow {
|
||||||
|
self.global.flow().flip()
|
||||||
|
}
|
||||||
|
pub(crate) fn source_location(self) -> crate::source_location::SourceLocation {
|
||||||
|
self.global.source_location()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetTarget for SimIoForGlobal {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
Some(Target::from(*self).intern_sized())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToLiteralBits for SimIoForGlobal {
|
||||||
|
fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> {
|
||||||
|
Err(NotALiteralExpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValueType for SimIoForGlobal {
|
||||||
|
type Type = CanonicalType;
|
||||||
|
type ValueCategory = ValueCategoryExpr;
|
||||||
|
|
||||||
|
fn ty(&self) -> Self::Type {
|
||||||
|
self.global.ty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToExpr for SimIoForGlobal {
|
||||||
|
fn to_expr(&self) -> Expr<Self::Type> {
|
||||||
|
Expr {
|
||||||
|
__enum: ExprEnum::SimIoForGlobal(*self).intern(),
|
||||||
|
__ty: self.ty(),
|
||||||
|
__flow: self.flow(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@ use crate::{
|
||||||
array::Array,
|
array::Array,
|
||||||
bundle::{Bundle, BundleField},
|
bundle::{Bundle, BundleField},
|
||||||
expr::{Expr, Flow, ToExpr, ValueType, value_category::ValueCategoryExpr},
|
expr::{Expr, Flow, ToExpr, ValueType, value_category::ValueCategoryExpr},
|
||||||
|
formal::FormalInput,
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{DynPortType, MemPort},
|
memory::{DynPortType, MemPort},
|
||||||
module::{Instance, ModuleIO, TargetName},
|
module::{Instance, ModuleIO, TargetName},
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, TraceAsString, Type},
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
};
|
};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
@ -46,11 +47,33 @@ impl fmt::Display for TargetPathDynArrayElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct TargetPathTraceAsStringInner {}
|
||||||
|
|
||||||
|
impl fmt::Display for TargetPathTraceAsStringInner {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, ".<inner>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct TargetPathToTraceAsString {
|
||||||
|
pub ty: TraceAsString<CanonicalType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TargetPathToTraceAsString {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, ".to_trace_as_string(...)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum TargetPathElement {
|
pub enum TargetPathElement {
|
||||||
BundleField(TargetPathBundleField),
|
BundleField(TargetPathBundleField),
|
||||||
ArrayElement(TargetPathArrayElement),
|
ArrayElement(TargetPathArrayElement),
|
||||||
DynArrayElement(TargetPathDynArrayElement),
|
DynArrayElement(TargetPathDynArrayElement),
|
||||||
|
TraceAsStringInner(TargetPathTraceAsStringInner),
|
||||||
|
ToTraceAsString(TargetPathToTraceAsString),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TargetPathBundleField> for TargetPathElement {
|
impl From<TargetPathBundleField> for TargetPathElement {
|
||||||
|
|
@ -71,12 +94,26 @@ impl From<TargetPathDynArrayElement> for TargetPathElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<TargetPathTraceAsStringInner> for TargetPathElement {
|
||||||
|
fn from(value: TargetPathTraceAsStringInner) -> Self {
|
||||||
|
Self::TraceAsStringInner(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TargetPathToTraceAsString> for TargetPathElement {
|
||||||
|
fn from(value: TargetPathToTraceAsString) -> Self {
|
||||||
|
Self::ToTraceAsString(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for TargetPathElement {
|
impl fmt::Display for TargetPathElement {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::BundleField(v) => v.fmt(f),
|
Self::BundleField(v) => v.fmt(f),
|
||||||
Self::ArrayElement(v) => v.fmt(f),
|
Self::ArrayElement(v) => v.fmt(f),
|
||||||
Self::DynArrayElement(v) => v.fmt(f),
|
Self::DynArrayElement(v) => v.fmt(f),
|
||||||
|
Self::TraceAsStringInner(v) => v.fmt(f),
|
||||||
|
Self::ToTraceAsString(v) => v.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -100,6 +137,15 @@ impl TargetPathElement {
|
||||||
let parent_ty = Array::<CanonicalType>::from_canonical(parent.canonical_ty());
|
let parent_ty = Array::<CanonicalType>::from_canonical(parent.canonical_ty());
|
||||||
parent_ty.element()
|
parent_ty.element()
|
||||||
}
|
}
|
||||||
|
Self::TraceAsStringInner(_) => {
|
||||||
|
let parent_ty =
|
||||||
|
TraceAsString::<CanonicalType>::from_canonical(parent.canonical_ty());
|
||||||
|
parent_ty.inner_ty()
|
||||||
|
}
|
||||||
|
&Self::ToTraceAsString(TargetPathToTraceAsString { ty }) => {
|
||||||
|
assert_eq!(parent.canonical_ty(), ty.inner_ty());
|
||||||
|
ty.canonical()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn flow(&self, parent: Interned<Target>) -> Flow {
|
pub fn flow(&self, parent: Interned<Target>) -> Flow {
|
||||||
|
|
@ -111,13 +157,18 @@ impl TargetPathElement {
|
||||||
.expect("field name is known to be a valid field of parent type");
|
.expect("field name is known to be a valid field of parent type");
|
||||||
parent.flow().flip_if(field.flipped)
|
parent.flow().flip_if(field.flipped)
|
||||||
}
|
}
|
||||||
Self::ArrayElement(_) => parent.flow(),
|
Self::ArrayElement(_)
|
||||||
Self::DynArrayElement(_) => parent.flow(),
|
| Self::DynArrayElement(_)
|
||||||
|
| Self::TraceAsStringInner(_)
|
||||||
|
| Self::ToTraceAsString(_) => parent.flow(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn is_static(&self) -> bool {
|
pub fn is_static(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::BundleField(_) | Self::ArrayElement(_) => true,
|
Self::BundleField(_)
|
||||||
|
| Self::ArrayElement(_)
|
||||||
|
| Self::TraceAsStringInner(_)
|
||||||
|
| Self::ToTraceAsString(_) => true,
|
||||||
Self::DynArrayElement(_) => false,
|
Self::DynArrayElement(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -245,6 +296,14 @@ impl_target_base! {
|
||||||
#[is = is_instance]
|
#[is = is_instance]
|
||||||
#[to = instance]
|
#[to = instance]
|
||||||
Instance(Instance<Bundle>),
|
Instance(Instance<Bundle>),
|
||||||
|
#[from = from]
|
||||||
|
#[is = is_formal_input]
|
||||||
|
#[to = formal_input]
|
||||||
|
FormalInput(FormalInput),
|
||||||
|
#[from = from]
|
||||||
|
#[is = is_sim_io_for_global]
|
||||||
|
#[to = sim_io_for_global]
|
||||||
|
SimIoForGlobal(crate::expr::ops::SimIoForGlobal),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,6 +352,8 @@ impl TargetBase {
|
||||||
TargetBase::RegAsync(v) => TargetName(v.scoped_name(), None),
|
TargetBase::RegAsync(v) => TargetName(v.scoped_name(), None),
|
||||||
TargetBase::Wire(v) => TargetName(v.scoped_name(), None),
|
TargetBase::Wire(v) => TargetName(v.scoped_name(), None),
|
||||||
TargetBase::Instance(v) => TargetName(v.scoped_name(), None),
|
TargetBase::Instance(v) => TargetName(v.scoped_name(), None),
|
||||||
|
TargetBase::FormalInput(v) => TargetName(v.scoped_name(), None),
|
||||||
|
TargetBase::SimIoForGlobal(v) => TargetName(v.global().scoped_name(), None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn canonical_ty(&self) -> CanonicalType {
|
pub fn canonical_ty(&self) -> CanonicalType {
|
||||||
|
|
@ -304,6 +365,21 @@ impl TargetBase {
|
||||||
TargetBase::RegAsync(v) => v.ty(),
|
TargetBase::RegAsync(v) => v.ty(),
|
||||||
TargetBase::Wire(v) => v.ty(),
|
TargetBase::Wire(v) => v.ty(),
|
||||||
TargetBase::Instance(v) => v.ty().canonical(),
|
TargetBase::Instance(v) => v.ty().canonical(),
|
||||||
|
TargetBase::FormalInput(v) => v.ty(),
|
||||||
|
TargetBase::SimIoForGlobal(v) => v.ty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn is_valid_annotation_target(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::ModuleIO(_) => true,
|
||||||
|
Self::MemPort(_) => true,
|
||||||
|
Self::Reg(_) => true,
|
||||||
|
Self::RegSync(_) => true,
|
||||||
|
Self::RegAsync(_) => true,
|
||||||
|
Self::Wire(_) => true,
|
||||||
|
Self::Instance(_) => true,
|
||||||
|
Self::FormalInput(_) => false,
|
||||||
|
Self::SimIoForGlobal(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -314,6 +390,7 @@ pub struct TargetChild {
|
||||||
path_element: Interned<TargetPathElement>,
|
path_element: Interned<TargetPathElement>,
|
||||||
canonical_ty: CanonicalType,
|
canonical_ty: CanonicalType,
|
||||||
flow: Flow,
|
flow: Flow,
|
||||||
|
canonicalized_if_different: Option<Interned<Target>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for TargetChild {
|
impl fmt::Debug for TargetChild {
|
||||||
|
|
@ -323,6 +400,7 @@ impl fmt::Debug for TargetChild {
|
||||||
path_element,
|
path_element,
|
||||||
canonical_ty: _,
|
canonical_ty: _,
|
||||||
flow: _,
|
flow: _,
|
||||||
|
canonicalized_if_different: _,
|
||||||
} = self;
|
} = self;
|
||||||
parent.fmt(f)?;
|
parent.fmt(f)?;
|
||||||
fmt::Display::fmt(path_element, f)
|
fmt::Display::fmt(path_element, f)
|
||||||
|
|
@ -336,6 +414,7 @@ impl fmt::Display for TargetChild {
|
||||||
path_element,
|
path_element,
|
||||||
canonical_ty: _,
|
canonical_ty: _,
|
||||||
flow: _,
|
flow: _,
|
||||||
|
canonicalized_if_different: _,
|
||||||
} = self;
|
} = self;
|
||||||
parent.fmt(f)?;
|
parent.fmt(f)?;
|
||||||
path_element.fmt(f)
|
path_element.fmt(f)
|
||||||
|
|
@ -343,14 +422,69 @@ impl fmt::Display for TargetChild {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TargetChild {
|
impl TargetChild {
|
||||||
pub fn new(parent: Interned<Target>, path_element: Interned<TargetPathElement>) -> Self {
|
fn new_helper(
|
||||||
|
parent: Interned<Target>,
|
||||||
|
path_element: Interned<TargetPathElement>,
|
||||||
|
canonicalized_if_different: Option<Interned<Target>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent,
|
parent,
|
||||||
path_element,
|
path_element,
|
||||||
canonical_ty: path_element.canonical_ty(parent),
|
canonical_ty: path_element.canonical_ty(parent),
|
||||||
flow: path_element.flow(parent),
|
flow: path_element.flow(parent),
|
||||||
|
canonicalized_if_different,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn make_canonicalized_if_different(
|
||||||
|
parent: Interned<Target>,
|
||||||
|
path_element: Interned<TargetPathElement>,
|
||||||
|
) -> Option<Interned<Target>> {
|
||||||
|
use TargetPathElement::*;
|
||||||
|
match *path_element {
|
||||||
|
BundleField(_) => {}
|
||||||
|
ArrayElement(_) => {}
|
||||||
|
DynArrayElement(_) => {}
|
||||||
|
TraceAsStringInner(_) => {
|
||||||
|
if let Some(child) = parent.canonicalized().child() {
|
||||||
|
match *child.path_element() {
|
||||||
|
BundleField(_)
|
||||||
|
| ArrayElement(_)
|
||||||
|
| DynArrayElement(_)
|
||||||
|
| TraceAsStringInner(_) => {}
|
||||||
|
ToTraceAsString(_) => return Some(child.parent()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ToTraceAsString(TargetPathToTraceAsString { ty }) => {
|
||||||
|
if let Some(child) = parent.canonicalized().child() {
|
||||||
|
match *child.path_element() {
|
||||||
|
BundleField(_) | ArrayElement(_) | DynArrayElement(_)
|
||||||
|
| ToTraceAsString(_) => {}
|
||||||
|
TraceAsStringInner(_) => {
|
||||||
|
if ty.canonical() == child.parent().canonical_ty() {
|
||||||
|
return Some(child.parent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(
|
||||||
|
Target::Child(Self::new_helper(
|
||||||
|
parent.canonicalized_if_different()?,
|
||||||
|
path_element,
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
.intern_sized(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pub fn new(parent: Interned<Target>, path_element: Interned<TargetPathElement>) -> Self {
|
||||||
|
Self::new_helper(
|
||||||
|
parent,
|
||||||
|
path_element,
|
||||||
|
Self::make_canonicalized_if_different(parent, path_element),
|
||||||
|
)
|
||||||
|
}
|
||||||
pub fn parent(self) -> Interned<Target> {
|
pub fn parent(self) -> Interned<Target> {
|
||||||
self.parent
|
self.parent
|
||||||
}
|
}
|
||||||
|
|
@ -363,6 +497,19 @@ impl TargetChild {
|
||||||
pub fn flow(self) -> Flow {
|
pub fn flow(self) -> Flow {
|
||||||
self.flow
|
self.flow
|
||||||
}
|
}
|
||||||
|
pub fn is_canonicalized(self) -> bool {
|
||||||
|
self.canonicalized_if_different.is_none()
|
||||||
|
}
|
||||||
|
pub fn canonicalized_if_different(self) -> Option<Interned<Target>> {
|
||||||
|
self.canonicalized_if_different
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
pub fn canonicalized(self) -> Target {
|
||||||
|
match self.canonicalized_if_different {
|
||||||
|
Some(v) => *v,
|
||||||
|
None => Target::Child(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn bundle_field(self) -> Option<BundleField> {
|
pub fn bundle_field(self) -> Option<BundleField> {
|
||||||
if let TargetPathElement::BundleField(TargetPathBundleField { name }) = *self.path_element {
|
if let TargetPathElement::BundleField(TargetPathBundleField { name }) = *self.path_element {
|
||||||
let parent_ty = Bundle::from_canonical(self.parent.canonical_ty());
|
let parent_ty = Bundle::from_canonical(self.parent.canonical_ty());
|
||||||
|
|
@ -427,6 +574,16 @@ impl Target {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn is_valid_annotation_target(&self) -> bool {
|
||||||
|
let mut target = self;
|
||||||
|
loop {
|
||||||
|
match target {
|
||||||
|
Self::Base(target_base) => return target_base.is_valid_annotation_target(),
|
||||||
|
Self::Child(v) if !v.path_element().is_static() => return false,
|
||||||
|
Self::Child(v) => target = &v.parent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn join(&self, path_element: Interned<TargetPathElement>) -> Self {
|
pub fn join(&self, path_element: Interned<TargetPathElement>) -> Self {
|
||||||
TargetChild::new(self.intern(), path_element).into()
|
TargetChild::new(self.intern(), path_element).into()
|
||||||
|
|
@ -443,6 +600,82 @@ impl Target {
|
||||||
Target::Child(v) => v.canonical_ty(),
|
Target::Child(v) => v.canonical_ty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn is_canonicalized(self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Base(_) => true,
|
||||||
|
Self::Child(child) => child.is_canonicalized(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn canonicalized_if_different(self) -> Option<Interned<Self>> {
|
||||||
|
match self {
|
||||||
|
Self::Base(_) => None,
|
||||||
|
Self::Child(child) => child.canonicalized_if_different(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
pub fn canonicalized(self) -> Target {
|
||||||
|
match self.canonicalized_if_different() {
|
||||||
|
Some(v) => *v,
|
||||||
|
None => self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
pub fn canonicalized_interned(this: Interned<Target>) -> Interned<Target> {
|
||||||
|
this.canonicalized_if_different().unwrap_or(this)
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
pub fn unwrap_transparent_types(mut self) -> Target {
|
||||||
|
loop {
|
||||||
|
self = self.canonicalized();
|
||||||
|
match self.canonical_ty() {
|
||||||
|
CanonicalType::UInt(_)
|
||||||
|
| CanonicalType::SInt(_)
|
||||||
|
| CanonicalType::Bool(_)
|
||||||
|
| CanonicalType::Array(_)
|
||||||
|
| CanonicalType::Enum(_)
|
||||||
|
| CanonicalType::Bundle(_)
|
||||||
|
| CanonicalType::AsyncReset(_)
|
||||||
|
| CanonicalType::SyncReset(_)
|
||||||
|
| CanonicalType::Reset(_)
|
||||||
|
| CanonicalType::Clock(_)
|
||||||
|
| CanonicalType::PhantomConst(_)
|
||||||
|
| CanonicalType::DynSimOnly(_) => return self,
|
||||||
|
CanonicalType::TraceAsString(_) => {
|
||||||
|
if let Self::Child(child) = self
|
||||||
|
&& let TargetPathElement::ToTraceAsString(_) = *child.path_element()
|
||||||
|
{
|
||||||
|
self = *child.parent();
|
||||||
|
} else {
|
||||||
|
self = self.join(TargetPathElement::intern_sized(
|
||||||
|
TargetPathTraceAsStringInner {}.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
pub fn unwrap_transparent_types_interned(this: Interned<Target>) -> Interned<Target> {
|
||||||
|
let retval = this.unwrap_transparent_types();
|
||||||
|
if retval != *this {
|
||||||
|
retval.intern_sized()
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
pub fn without_trailing_transparent_path_elements(mut self) -> Target {
|
||||||
|
use TargetPathElement::*;
|
||||||
|
loop {
|
||||||
|
match self {
|
||||||
|
Self::Base(_) => return self,
|
||||||
|
Self::Child(child) => match *child.path_element() {
|
||||||
|
BundleField(_) | ArrayElement(_) | DynArrayElement(_) => return self,
|
||||||
|
TraceAsStringInner(_) | ToTraceAsString(_) => self = *child.parent(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Target {
|
impl fmt::Display for Target {
|
||||||
|
|
@ -467,6 +700,18 @@ pub trait GetTarget {
|
||||||
fn target(&self) -> Option<Interned<Target>>;
|
fn target(&self) -> Option<Interned<Target>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GetTarget for Target {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
Some(self.intern())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetTarget for TargetBase {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
Some(Target::Base(self.intern()).intern_sized())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GetTarget for bool {
|
impl GetTarget for bool {
|
||||||
fn target(&self) -> Option<Interned<Target>> {
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
None
|
None
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,11 +1,189 @@
|
||||||
// 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::target::{GetTarget, Target},
|
||||||
int::BoolOrIntType,
|
int::BoolOrIntType,
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned},
|
||||||
|
module::{NameId, NameIdOrGlobal, ScopedNameId},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use std::sync::OnceLock;
|
use std::{fmt, sync::OnceLock};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub enum FormalInputKind {
|
||||||
|
FormalGlobalClock,
|
||||||
|
FormalReset,
|
||||||
|
AnyConst,
|
||||||
|
AnySeq,
|
||||||
|
AllConst,
|
||||||
|
AllSeq,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormalInputKind {
|
||||||
|
pub fn fixed_ty(self) -> Option<CanonicalType> {
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock => Some(Clock.into()),
|
||||||
|
Self::FormalReset => Some(SyncReset.into()),
|
||||||
|
Self::AnyConst => None,
|
||||||
|
Self::AnySeq => None,
|
||||||
|
Self::AllConst => None,
|
||||||
|
Self::AllSeq => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fixed_id(self) -> Option<crate::module::Id> {
|
||||||
|
struct Cache {
|
||||||
|
formal_global_clock: crate::module::Id,
|
||||||
|
formal_reset: crate::module::Id,
|
||||||
|
}
|
||||||
|
static CACHE: OnceLock<Cache> = OnceLock::new();
|
||||||
|
let cache = || {
|
||||||
|
CACHE.get_or_init(
|
||||||
|
#[cold]
|
||||||
|
|| Cache {
|
||||||
|
formal_global_clock: crate::module::Id::new(),
|
||||||
|
formal_reset: crate::module::Id::new(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock => Some(cache().formal_global_clock),
|
||||||
|
Self::FormalReset => Some(cache().formal_reset),
|
||||||
|
Self::AnyConst => None,
|
||||||
|
Self::AnySeq => None,
|
||||||
|
Self::AllConst => None,
|
||||||
|
Self::AllSeq => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fixed_source_location(self) -> Option<SourceLocation> {
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock | Self::FormalReset => Some(SourceLocation::builtin()),
|
||||||
|
Self::AnyConst | Self::AnySeq | Self::AllConst | Self::AllSeq => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn name(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock => "formal_global_clock",
|
||||||
|
Self::FormalReset => "formal_reset",
|
||||||
|
Self::AnyConst => "any_const",
|
||||||
|
Self::AnySeq => "any_seq",
|
||||||
|
Self::AllConst => "all_const",
|
||||||
|
Self::AllSeq => "all_seq",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn interned_name(self) -> Interned<str> {
|
||||||
|
macro_rules! impl_interned_name {
|
||||||
|
($($variant:ident,)*) => {
|
||||||
|
match self {
|
||||||
|
$(Self::$variant => {
|
||||||
|
static CACHE: OnceLock<Interned<str>> = OnceLock::new();
|
||||||
|
*CACHE.get_or_init(|| Self::$variant.name().intern())
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
impl_interned_name! {
|
||||||
|
FormalGlobalClock,
|
||||||
|
FormalReset,
|
||||||
|
AnyConst,
|
||||||
|
AnySeq,
|
||||||
|
AllConst,
|
||||||
|
AllSeq,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct FormalInputData {
|
||||||
|
kind: FormalInputKind,
|
||||||
|
name_id: NameId,
|
||||||
|
ty: CanonicalType,
|
||||||
|
source_location: SourceLocation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct FormalInput(Interned<FormalInputData>);
|
||||||
|
|
||||||
|
impl fmt::Debug for FormalInput {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
if self.kind().fixed_ty().is_some() {
|
||||||
|
f.write_str(&self.name())
|
||||||
|
} else {
|
||||||
|
f.debug_tuple(&self.name()).field(&self.0.ty).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormalInput {
|
||||||
|
#[track_caller]
|
||||||
|
pub fn new(
|
||||||
|
kind: FormalInputKind,
|
||||||
|
name_id: NameId,
|
||||||
|
ty: CanonicalType,
|
||||||
|
source_location: SourceLocation,
|
||||||
|
) -> Self {
|
||||||
|
let NameId(name, id) = name_id;
|
||||||
|
assert_eq!(kind.interned_name(), name);
|
||||||
|
if let Some(fixed_ty) = kind.fixed_ty() {
|
||||||
|
assert_eq!(ty, fixed_ty);
|
||||||
|
} else {
|
||||||
|
assert!(
|
||||||
|
ty.is_castable_from_bits(),
|
||||||
|
"{name} type must be castable from bits. got:\n{ty:#?}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(fixed_source_location) = kind.fixed_source_location() {
|
||||||
|
assert_eq!(source_location, fixed_source_location);
|
||||||
|
}
|
||||||
|
if let Some(fixed_id) = kind.fixed_id() {
|
||||||
|
assert_eq!(id, fixed_id);
|
||||||
|
}
|
||||||
|
Self(
|
||||||
|
FormalInputData {
|
||||||
|
kind,
|
||||||
|
name_id,
|
||||||
|
ty,
|
||||||
|
source_location,
|
||||||
|
}
|
||||||
|
.intern_sized(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pub fn kind(self) -> FormalInputKind {
|
||||||
|
self.0.kind
|
||||||
|
}
|
||||||
|
pub fn name(self) -> Interned<str> {
|
||||||
|
self.0.name_id.0
|
||||||
|
}
|
||||||
|
pub fn name_id(self) -> NameId {
|
||||||
|
self.0.name_id
|
||||||
|
}
|
||||||
|
pub fn scoped_name(self) -> ScopedNameId {
|
||||||
|
ScopedNameId(NameIdOrGlobal::Global, self.name_id())
|
||||||
|
}
|
||||||
|
pub fn source_location(self) -> SourceLocation {
|
||||||
|
self.0.source_location
|
||||||
|
}
|
||||||
|
pub(crate) fn must_connect_to(self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
pub(crate) fn flow(self) -> crate::expr::Flow {
|
||||||
|
crate::expr::Flow::Source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValueType for FormalInput {
|
||||||
|
type Type = CanonicalType;
|
||||||
|
type ValueCategory = crate::expr::value_category::ValueCategoryExpr;
|
||||||
|
|
||||||
|
fn ty(&self) -> Self::Type {
|
||||||
|
self.0.ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetTarget for FormalInput {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
Some(Target::from(*self).intern_sized())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
pub enum FormalKind {
|
pub enum FormalKind {
|
||||||
|
|
@ -138,110 +316,76 @@ make_formal!(
|
||||||
hdl_cover
|
hdl_cover
|
||||||
);
|
);
|
||||||
|
|
||||||
pub trait MakeFormalExpr: Type {}
|
|
||||||
|
|
||||||
impl<T: Type> MakeFormalExpr for T {}
|
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub fn formal_global_clock() -> Expr<Clock> {
|
pub fn formal_global_clock() -> Expr<Clock> {
|
||||||
#[hdl_module(extern)]
|
static CACHE: OnceLock<Expr<Clock>> = OnceLock::new();
|
||||||
fn formal_global_clock() {
|
*CACHE.get_or_init(|| {
|
||||||
#[hdl]
|
let kind = FormalInputKind::FormalGlobalClock;
|
||||||
let clk: Clock = m.output();
|
Expr::from_canonical(
|
||||||
m.annotate_module(BlackBoxInlineAnnotation {
|
FormalInput::new(
|
||||||
path: "fayalite_formal_global_clock.v".intern(),
|
kind,
|
||||||
text: r"module __fayalite_formal_global_clock(output clk);
|
NameId(
|
||||||
(* gclk *)
|
kind.interned_name(),
|
||||||
reg clk;
|
kind.fixed_id().expect("known to have a fixed Id"),
|
||||||
endmodule
|
),
|
||||||
"
|
Clock.into(),
|
||||||
.intern(),
|
kind.fixed_source_location()
|
||||||
});
|
.expect("known to have a fixed SourceLocation"),
|
||||||
m.verilog_name("__fayalite_formal_global_clock");
|
)
|
||||||
}
|
.to_expr(),
|
||||||
#[hdl]
|
)
|
||||||
let formal_global_clock = instance(formal_global_clock());
|
})
|
||||||
formal_global_clock.clk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub fn formal_reset() -> Expr<SyncReset> {
|
pub fn formal_reset() -> Expr<SyncReset> {
|
||||||
#[hdl_module(extern)]
|
static CACHE: OnceLock<Expr<SyncReset>> = OnceLock::new();
|
||||||
fn formal_reset() {
|
*CACHE.get_or_init(|| {
|
||||||
#[hdl]
|
let kind = FormalInputKind::FormalReset;
|
||||||
let rst: SyncReset = m.output();
|
Expr::from_canonical(
|
||||||
m.annotate_module(BlackBoxInlineAnnotation {
|
FormalInput::new(
|
||||||
path: "fayalite_formal_reset.v".intern(),
|
kind,
|
||||||
text: r"module __fayalite_formal_reset(output rst);
|
NameId(
|
||||||
assign rst = $initstate;
|
kind.interned_name(),
|
||||||
endmodule
|
kind.fixed_id().expect("known to have a fixed Id"),
|
||||||
"
|
),
|
||||||
.intern(),
|
SyncReset.into(),
|
||||||
});
|
kind.fixed_source_location()
|
||||||
m.verilog_name("__fayalite_formal_reset");
|
.expect("known to have a fixed SourceLocation"),
|
||||||
}
|
)
|
||||||
static MOD: OnceLock<Interned<Module<formal_reset>>> = OnceLock::new();
|
.to_expr(),
|
||||||
#[hdl]
|
)
|
||||||
let formal_reset = instance(*MOD.get_or_init(formal_reset));
|
})
|
||||||
formal_reset.rst
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! make_any_const_fn {
|
macro_rules! make_any_const_fn {
|
||||||
($ident:ident, $verilog_attribute:literal) => {
|
($ident:ident, $ident_with_loc:ident, $verilog_attribute:literal, $kind:ident) => {
|
||||||
|
#[track_caller]
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub fn $ident<T: BoolOrIntType>(ty: T) -> Expr<T> {
|
pub fn $ident<T: BoolOrIntType>(ty: T) -> Expr<T> {
|
||||||
#[hdl_module(extern)]
|
$ident_with_loc(ty, SourceLocation::caller())
|
||||||
pub(super) fn $ident<T: BoolOrIntType>(ty: T) {
|
}
|
||||||
|
#[track_caller]
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let out: T = m.output(ty);
|
pub fn $ident_with_loc<T: BoolOrIntType>(
|
||||||
let width = ty.width();
|
ty: T,
|
||||||
let verilog_bitslice = if width == 1 {
|
source_location: SourceLocation,
|
||||||
String::new()
|
) -> Expr<T> {
|
||||||
} else {
|
let kind = FormalInputKind::$kind;
|
||||||
format!(" [{}:0]", width - 1)
|
Expr::from_canonical(
|
||||||
};
|
FormalInput::new(
|
||||||
m.annotate_module(BlackBoxInlineAnnotation {
|
kind,
|
||||||
path: Intern::intern_owned(format!(
|
NameId(kind.interned_name(), crate::module::Id::new()),
|
||||||
"fayalite_{}_{width}.v",
|
ty.canonical(),
|
||||||
stringify!($ident),
|
source_location,
|
||||||
)),
|
)
|
||||||
text: Intern::intern_owned(format!(
|
.to_expr(),
|
||||||
r"module __fayalite_{}_{width}(output{verilog_bitslice} out);
|
)
|
||||||
(* {} *)
|
|
||||||
reg{verilog_bitslice} out;
|
|
||||||
endmodule
|
|
||||||
",
|
|
||||||
stringify!($ident),
|
|
||||||
$verilog_attribute,
|
|
||||||
)),
|
|
||||||
});
|
|
||||||
m.verilog_name(format!("__fayalite_{}_{width}", stringify!($ident)));
|
|
||||||
}
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
|
||||||
struct TheMemoize<T>(T);
|
|
||||||
impl<T: BoolOrIntType> Memoize for TheMemoize<T> {
|
|
||||||
type Input = ();
|
|
||||||
type InputOwned = ();
|
|
||||||
type Output = Option<Interned<Module<$ident<T>>>>;
|
|
||||||
fn inner(self, _input: &Self::Input) -> Self::Output {
|
|
||||||
if self.0.width() == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some($ident(self.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let Some(module) = TheMemoize(ty).get_owned(()) else {
|
|
||||||
return 0_hdl_u0.cast_bits_to(ty);
|
|
||||||
};
|
|
||||||
#[hdl]
|
|
||||||
let $ident = instance(module);
|
|
||||||
$ident.out
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
make_any_const_fn!(any_const, "anyconst");
|
make_any_const_fn!(any_const, any_const_with_loc, "anyconst", AnyConst);
|
||||||
make_any_const_fn!(any_seq, "anyseq");
|
make_any_const_fn!(any_seq, any_seq_with_loc, "anyseq", AnySeq);
|
||||||
make_any_const_fn!(all_const, "allconst");
|
make_any_const_fn!(all_const, all_const_with_loc, "allconst", AllConst);
|
||||||
make_any_const_fn!(all_seq, "allseq");
|
make_any_const_fn!(all_seq, all_seq_with_loc, "allseq", AllSeq);
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1180,12 +1277,29 @@ macro_rules! impl_int {
|
||||||
pub fn bitvec_mut(&mut self) -> &mut BitVec {
|
pub fn bitvec_mut(&mut self) -> &mut BitVec {
|
||||||
Arc::make_mut(&mut self.bits)
|
Arc::make_mut(&mut self.bits)
|
||||||
}
|
}
|
||||||
|
pub fn arc_bitvec_mut(&mut self) -> &mut Arc<BitVec> {
|
||||||
|
&mut self.bits
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +1920,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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
type_id.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + 'static> PartialEq for LazyInternedLazyInner<T> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
let Self { type_id, value: _ } = self;
|
||||||
|
*type_id == other.type_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + 'static> Eq for LazyInternedLazyInner<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,
|
||||||
{
|
{
|
||||||
fn get(&self) -> Interned<T> {
|
const { assert!(size_of::<T>() == 0) };
|
||||||
self()
|
Self {
|
||||||
|
type_id: TypeId::of::<T>(),
|
||||||
|
value,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
pub struct LazyInternedLazy<T: ?Sized + Send + Sync + 'static>(
|
||||||
pub struct LazyInternedFn<T: ?Sized + Send + Sync + 'static>(pub &'static dyn LazyInternedTrait<T>);
|
&'static LazyInternedLazyInner<dyn Fn() -> Interned<T> + Send + Sync>,
|
||||||
|
);
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static> Copy for LazyInternedFn<T> {}
|
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> Clone for LazyInternedFn<T> {
|
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,
|
||||||
}
|
}
|
||||||
|
|
@ -695,27 +682,62 @@ impl<T: ?Sized + 'static + Send + Sync + AsRef<U>, U: ?Sized> AsRef<U> for Inter
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct InternedSliceIter<T: Clone + 'static + Send + Sync> {
|
pub struct InternedSliceIter<T: Clone + 'static + Send + Sync> {
|
||||||
slice: Interned<[T]>,
|
iter: std::iter::Cloned<std::slice::Iter<'static, T>>,
|
||||||
index: std::ops::Range<usize>,
|
}
|
||||||
|
|
||||||
|
impl<T: Clone + 'static + Send + Sync> Default for InternedSliceIter<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
iter: [].iter().cloned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + 'static + Send + Sync> Iterator for InternedSliceIter<T> {
|
impl<T: Clone + 'static + Send + Sync> Iterator for InternedSliceIter<T> {
|
||||||
type Item = T;
|
type Item = T;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.index.next().map(|index| self.slice[index].clone())
|
self.iter.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.index.size_hint()
|
self.iter.size_hint()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count(self) -> usize {
|
||||||
|
self.iter.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn last(mut self) -> Option<Self::Item> {
|
||||||
|
self.next_back()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||||
|
self.iter.nth(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold<B, F>(self, init: B, f: F) -> B
|
||||||
|
where
|
||||||
|
F: FnMut(B, Self::Item) -> B,
|
||||||
|
{
|
||||||
|
self.iter.fold(init, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + 'static + Send + Sync> DoubleEndedIterator for InternedSliceIter<T> {
|
impl<T: Clone + 'static + Send + Sync> DoubleEndedIterator for InternedSliceIter<T> {
|
||||||
fn next_back(&mut self) -> Option<Self::Item> {
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
self.index
|
self.iter.next_back()
|
||||||
.next_back()
|
}
|
||||||
.map(|index| self.slice[index].clone())
|
|
||||||
|
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||||
|
self.iter.nth_back(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rfold<B, F>(self, init: B, f: F) -> B
|
||||||
|
where
|
||||||
|
F: FnMut(B, Self::Item) -> B,
|
||||||
|
{
|
||||||
|
self.iter.rfold(init, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -729,8 +751,7 @@ impl<T: Clone + 'static + Send + Sync> IntoIterator for Interned<[T]> {
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
InternedSliceIter {
|
InternedSliceIter {
|
||||||
index: 0..self.len(),
|
iter: Interned::into_inner(self).iter().cloned(),
|
||||||
slice: self,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -977,7 +998,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 +1018,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 +1038,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 +1056,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 +1168,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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
117
crates/fayalite/src/intern/interner.rs
Normal file
117
crates/fayalite/src/intern/interner.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1093,6 +1093,7 @@ pub fn splat_mask<T: Type>(ty: T, value: Expr<Bool>) -> Expr<AsMask<T>> {
|
||||||
.to_expr(),
|
.to_expr(),
|
||||||
)),
|
)),
|
||||||
CanonicalType::PhantomConst(_) => Expr::from_canonical(Expr::canonical(().to_expr())),
|
CanonicalType::PhantomConst(_) => Expr::from_canonical(Expr::canonical(().to_expr())),
|
||||||
|
CanonicalType::TraceAsString(ty) => Expr::from_canonical(splat_mask(ty.inner_ty(), value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
clock::{Clock, ClockDomain},
|
clock::{Clock, ClockDomain},
|
||||||
enum_::{Enum, EnumMatchVariantsIter, EnumType},
|
enum_::{Enum, EnumMatchVariantsIter, EnumType},
|
||||||
expr::{
|
expr::{
|
||||||
Expr, Flow, ToExpr, ValueType,
|
Expr, ExprEnum, Flow, ToExpr, ValueType,
|
||||||
ops::VariantAccess,
|
ops::VariantAccess,
|
||||||
target::{
|
target::{
|
||||||
GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField,
|
GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField,
|
||||||
|
|
@ -20,6 +20,7 @@ use crate::{
|
||||||
int::{Bool, DynSize, Size},
|
int::{Bool, DynSize, Size},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
||||||
|
module::transform::visit::{Visit, Visitor},
|
||||||
platform::PlatformIOBuilder,
|
platform::PlatformIOBuilder,
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
||||||
|
|
@ -726,7 +727,57 @@ impl fmt::Display for NameId {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct ScopedNameId(pub NameId, pub NameId);
|
pub enum NameIdOrGlobal {
|
||||||
|
Global,
|
||||||
|
NameId(NameId),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NameIdOrGlobal {
|
||||||
|
pub fn name_id(self) -> Option<NameId> {
|
||||||
|
match self {
|
||||||
|
Self::Global => None,
|
||||||
|
Self::NameId(v) => Some(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn assert_is_name_id(self) {
|
||||||
|
match self {
|
||||||
|
Self::Global => panic!("expected a NameId, got NameIdOrGlobal::Global"),
|
||||||
|
Self::NameId(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn unwrap_name_id(self) -> NameId {
|
||||||
|
match self {
|
||||||
|
Self::Global => panic!("expected a NameId, got NameIdOrGlobal::Global"),
|
||||||
|
Self::NameId(v) => v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for NameIdOrGlobal {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NameIdOrGlobal {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Global => f.write_str("<<Global>>"),
|
||||||
|
Self::NameId(name_id) => fmt::Display::fmt(name_id, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NameId> for NameIdOrGlobal {
|
||||||
|
fn from(value: NameId) -> Self {
|
||||||
|
Self::NameId(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct ScopedNameId(pub NameIdOrGlobal, pub NameId);
|
||||||
|
|
||||||
impl fmt::Debug for ScopedNameId {
|
impl fmt::Debug for ScopedNameId {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
|
@ -804,7 +855,7 @@ impl<T: BundleType> Instance<T> {
|
||||||
self.containing_module_name_id().0
|
self.containing_module_name_id().0
|
||||||
}
|
}
|
||||||
pub fn containing_module_name_id(self) -> NameId {
|
pub fn containing_module_name_id(self) -> NameId {
|
||||||
self.scoped_name.0
|
self.scoped_name.0.unwrap_name_id()
|
||||||
}
|
}
|
||||||
pub fn name(self) -> Interned<str> {
|
pub fn name(self) -> Interned<str> {
|
||||||
self.name_id().0
|
self.name_id().0
|
||||||
|
|
@ -821,11 +872,13 @@ impl<T: BundleType> Instance<T> {
|
||||||
pub fn source_location(self) -> SourceLocation {
|
pub fn source_location(self) -> SourceLocation {
|
||||||
self.source_location
|
self.source_location
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn new_unchecked(
|
pub fn new_unchecked(
|
||||||
scoped_name: ScopedNameId,
|
scoped_name: ScopedNameId,
|
||||||
instantiated: Interned<Module<T>>,
|
instantiated: Interned<Module<T>>,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
scoped_name.0.assert_is_name_id();
|
||||||
Self {
|
Self {
|
||||||
scoped_name,
|
scoped_name,
|
||||||
instantiated,
|
instantiated,
|
||||||
|
|
@ -1111,7 +1164,10 @@ fn validate_clock_for_past<S: ModuleBuildingStatus>(
|
||||||
let mut target = clock_for_past;
|
let mut target = clock_for_past;
|
||||||
while let Target::Child(child) = target {
|
while let Target::Child(child) = target {
|
||||||
match *child.path_element() {
|
match *child.path_element() {
|
||||||
TargetPathElement::BundleField(_) | TargetPathElement::ArrayElement(_) => {}
|
TargetPathElement::BundleField(_)
|
||||||
|
| TargetPathElement::ArrayElement(_)
|
||||||
|
| TargetPathElement::ToTraceAsString(_)
|
||||||
|
| TargetPathElement::TraceAsStringInner(_) => {}
|
||||||
TargetPathElement::DynArrayElement(_) => {
|
TargetPathElement::DynArrayElement(_) => {
|
||||||
panic!(
|
panic!(
|
||||||
"clock_for_past: clock must be a static target (you can't use `Expr<UInt>` array indexes):\n{clock_for_past:?}"
|
"clock_for_past: clock must be a static target (you can't use `Expr<UInt>` array indexes):\n{clock_for_past:?}"
|
||||||
|
|
@ -1535,6 +1591,7 @@ impl TargetState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn new(target: Interned<Target>, declared_in_block: usize) -> Self {
|
fn new(target: Interned<Target>, declared_in_block: usize) -> Self {
|
||||||
|
let target = Target::unwrap_transparent_types_interned(target);
|
||||||
Self {
|
Self {
|
||||||
target,
|
target,
|
||||||
inner: match target.canonical_ty() {
|
inner: match target.canonical_ty() {
|
||||||
|
|
@ -1586,17 +1643,71 @@ impl TargetState {
|
||||||
declared_in_block,
|
declared_in_block,
|
||||||
written_in_blocks: RefCell::default(),
|
written_in_blocks: RefCell::default(),
|
||||||
},
|
},
|
||||||
|
CanonicalType::TraceAsString(_) => {
|
||||||
|
unreachable!("handled by Target::unwrap_transparent_types_interned")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VisibleExprsStack {
|
||||||
|
buf: Vec<HashSet<ExprEnum>>,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VisibleExprsStack {
|
||||||
|
fn top(&mut self) -> &mut HashSet<ExprEnum> {
|
||||||
|
&mut self.buf[self.len - 1]
|
||||||
|
}
|
||||||
|
fn slice(&self) -> &[HashSet<ExprEnum>] {
|
||||||
|
&self.buf[..self.len]
|
||||||
|
}
|
||||||
|
fn contains(&self, v: &ExprEnum) -> bool {
|
||||||
|
self.slice().iter().any(|i| i.contains(v))
|
||||||
|
}
|
||||||
|
fn push_empty(&mut self) {
|
||||||
|
#[cold]
|
||||||
|
fn push_empty_cold(stack: &mut VisibleExprsStack) {
|
||||||
|
stack.buf.push(HashSet::default());
|
||||||
|
assert_eq!(stack.buf.len(), stack.len)
|
||||||
|
}
|
||||||
|
self.len += 1;
|
||||||
|
if self.len > self.buf.len() {
|
||||||
|
push_empty_cold(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn pop(&mut self) {
|
||||||
|
let Some(new_len) = self.len.checked_sub(1) else {
|
||||||
|
unreachable!("visible exprs stack underflow");
|
||||||
|
};
|
||||||
|
self.buf[new_len].clear();
|
||||||
|
self.len = new_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VisibleExprsStack {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
buf: Vec::new(),
|
||||||
|
len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AssertValidityState {
|
struct AssertValidityState {
|
||||||
module: Module<Bundle>,
|
module: Module<Bundle>,
|
||||||
blocks: Vec<Block>,
|
blocks: Vec<Block>,
|
||||||
|
visible_exprs: VisibleExprsStack,
|
||||||
target_states: HashMap<Interned<TargetBase>, TargetState>,
|
target_states: HashMap<Interned<TargetBase>, TargetState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum GetTargetStatesError {
|
||||||
|
NotFound,
|
||||||
|
IsGlobal,
|
||||||
|
FoundSimIoForGlobal(crate::expr::ops::SimIoForGlobal),
|
||||||
|
}
|
||||||
|
|
||||||
impl AssertValidityState {
|
impl AssertValidityState {
|
||||||
fn make_block_index(&mut self, block: Block) -> usize {
|
fn make_block_index(&mut self, block: Block) -> usize {
|
||||||
let retval = self.blocks.len();
|
let retval = self.blocks.len();
|
||||||
|
|
@ -1605,19 +1716,25 @@ impl AssertValidityState {
|
||||||
}
|
}
|
||||||
fn get_target_states<'a>(
|
fn get_target_states<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
target: &Target,
|
target: Target,
|
||||||
process_target_state: &dyn Fn(&'a TargetState, bool),
|
process_target_state: &dyn Fn(&'a TargetState, bool),
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), GetTargetStatesError> {
|
||||||
match target {
|
let mut target = target.unwrap_transparent_types();
|
||||||
|
loop {
|
||||||
|
break match target {
|
||||||
Target::Base(target_base) => {
|
Target::Base(target_base) => {
|
||||||
let target_state = self.get_base_state(*target_base)?;
|
let target_state = self.get_base_state(target_base)?;
|
||||||
process_target_state(target_state, false);
|
process_target_state(target_state, false);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Target::Child(target_child) => self.get_target_states(
|
Target::Child(target_child) => match *target_child.path_element() {
|
||||||
&target_child.parent(),
|
TargetPathElement::BundleField(_)
|
||||||
|
| TargetPathElement::ArrayElement(_)
|
||||||
|
| TargetPathElement::DynArrayElement(_) => self.get_target_states(
|
||||||
|
*target_child.parent(),
|
||||||
&|target_state, exact_target_unknown| {
|
&|target_state, exact_target_unknown| {
|
||||||
let TargetStateInner::Decomposed { subtargets } = &target_state.inner else {
|
let TargetStateInner::Decomposed { subtargets } = &target_state.inner
|
||||||
|
else {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
"TargetState::new makes TargetState tree match the Target type"
|
"TargetState::new makes TargetState tree match the Target type"
|
||||||
);
|
);
|
||||||
|
|
@ -1640,13 +1757,38 @@ impl AssertValidityState {
|
||||||
process_target_state(target_state, true);
|
process_target_state(target_state, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TargetPathElement::TraceAsStringInner(_)
|
||||||
|
| TargetPathElement::ToTraceAsString(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
TargetPathElement::TraceAsStringInner(_)
|
||||||
|
| TargetPathElement::ToTraceAsString(_) => {
|
||||||
|
target = *target_child.parent();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get_base_state(&self, target_base: Interned<TargetBase>) -> Result<&TargetState, ()> {
|
fn get_base_state(
|
||||||
self.target_states.get(&target_base).ok_or(())
|
&self,
|
||||||
|
target_base: Interned<TargetBase>,
|
||||||
|
) -> Result<&TargetState, GetTargetStatesError> {
|
||||||
|
match *target_base {
|
||||||
|
TargetBase::ModuleIO(_)
|
||||||
|
| TargetBase::MemPort(_)
|
||||||
|
| TargetBase::Reg(_)
|
||||||
|
| TargetBase::RegSync(_)
|
||||||
|
| TargetBase::RegAsync(_)
|
||||||
|
| TargetBase::Wire(_)
|
||||||
|
| TargetBase::Instance(_) => self
|
||||||
|
.target_states
|
||||||
|
.get(&target_base)
|
||||||
|
.ok_or(GetTargetStatesError::NotFound),
|
||||||
|
TargetBase::FormalInput(_) => Err(GetTargetStatesError::IsGlobal),
|
||||||
|
TargetBase::SimIoForGlobal(v) => Err(GetTargetStatesError::FoundSimIoForGlobal(v)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn insert_new_base(&mut self, target_base: Interned<TargetBase>, declared_in_block: usize) {
|
fn insert_new_base(&mut self, target_base: Interned<TargetBase>, declared_in_block: usize) {
|
||||||
|
|
@ -1693,6 +1835,7 @@ impl AssertValidityState {
|
||||||
&TargetPathElement::BundleField(_) => {
|
&TargetPathElement::BundleField(_) => {
|
||||||
let field = sub_target_state
|
let field = sub_target_state
|
||||||
.target
|
.target
|
||||||
|
.without_trailing_transparent_path_elements()
|
||||||
.child()
|
.child()
|
||||||
.expect("known to be a child")
|
.expect("known to be a child")
|
||||||
.bundle_field()
|
.bundle_field()
|
||||||
|
|
@ -1716,6 +1859,8 @@ impl AssertValidityState {
|
||||||
TargetPathElement::DynArrayElement { .. } => {
|
TargetPathElement::DynArrayElement { .. } => {
|
||||||
Self::set_connect_target_written(sub_target_state, is_lhs, block, true);
|
Self::set_connect_target_written(sub_target_state, is_lhs, block, true);
|
||||||
}
|
}
|
||||||
|
TargetPathElement::TraceAsStringInner(_)
|
||||||
|
| TargetPathElement::ToTraceAsString(_) => unreachable!("never added"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1733,19 +1878,33 @@ impl AssertValidityState {
|
||||||
debug_assert!(!is_lhs, "the ModuleBuilder asserts lhs.target().is_some()");
|
debug_assert!(!is_lhs, "the ModuleBuilder asserts lhs.target().is_some()");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let result = self.get_target_states(&target, &|target_state, exact_target_unknown| {
|
let result = self.get_target_states(*target, &|target_state, exact_target_unknown| {
|
||||||
Self::set_connect_target_written(target_state, is_lhs, block, exact_target_unknown);
|
Self::set_connect_target_written(target_state, is_lhs, block, exact_target_unknown);
|
||||||
});
|
});
|
||||||
if result.is_err() {
|
match result {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(GetTargetStatesError::NotFound) => {
|
||||||
if is_lhs {
|
if is_lhs {
|
||||||
panic!("at {source_location}: tried to connect to not-yet-defined item: {target}");
|
panic!(
|
||||||
|
"at {source_location}: tried to connect to not-yet-defined item: {target}"
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"at {source_location}: tried to connect from not-yet-defined item: {target}"
|
"at {source_location}: tried to connect from not-yet-defined item: {target}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(GetTargetStatesError::IsGlobal) => {
|
||||||
|
// no error
|
||||||
}
|
}
|
||||||
|
Err(GetTargetStatesError::FoundSimIoForGlobal(v)) => {
|
||||||
|
panic!(
|
||||||
|
"at {source_location}: fayalite::expr::ops::SimIoForGlobal is not allowed in Modules: {v:?}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
fn process_conditional_sub_blocks(
|
fn process_conditional_sub_blocks(
|
||||||
&mut self,
|
&mut self,
|
||||||
parent_block: usize,
|
parent_block: usize,
|
||||||
|
|
@ -1759,17 +1918,40 @@ impl AssertValidityState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
fn assert_expr_validity<T: Type>(&mut self, expr: Expr<T>, source_location: SourceLocation) {
|
||||||
|
let mut visitor = AssertExprValidity { state: self };
|
||||||
|
match visitor.visit_expr(&expr) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => match e {
|
||||||
|
InvalidExpr::ExprIsNotVisible(expr) => {
|
||||||
|
if let Some(target) = expr.target() {
|
||||||
|
panic!(
|
||||||
|
"at {source_location}: expression isn't visible here, it's defined:\n\
|
||||||
|
at {}: {expr:?}",
|
||||||
|
target.base().source_location(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
panic!("at {source_location}: expression isn't visible here: {expr:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
fn assert_subtree_validity(&mut self, block: usize) {
|
fn assert_subtree_validity(&mut self, block: usize) {
|
||||||
|
self.visible_exprs.push_empty();
|
||||||
let module = self.module;
|
let module = self.module;
|
||||||
if block == 0 {
|
if block == 0 {
|
||||||
for module_io in &*module.module_io {
|
for module_io in &*module.module_io {
|
||||||
self.insert_new_base(TargetBase::intern_sized(module_io.module_io.into()), block);
|
self.insert_new_base(TargetBase::intern_sized(module_io.module_io.into()), block);
|
||||||
|
self.visible_exprs.top().insert(module_io.module_io.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let Block { memories, stmts } = self.blocks[block];
|
let Block { memories, stmts } = self.blocks[block];
|
||||||
for m in memories {
|
for m in memories {
|
||||||
for port in m.ports() {
|
for port in m.ports() {
|
||||||
self.insert_new_base(TargetBase::intern_sized(port.into()), block);
|
self.insert_new_base(TargetBase::intern_sized(port.into()), block);
|
||||||
|
self.visible_exprs.top().insert(port.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
|
|
@ -1783,45 +1965,105 @@ impl AssertValidityState {
|
||||||
} = connect;
|
} = connect;
|
||||||
self.set_connect_side_written(lhs, source_location, true, block);
|
self.set_connect_side_written(lhs, source_location, true, block);
|
||||||
self.set_connect_side_written(rhs, source_location, false, block);
|
self.set_connect_side_written(rhs, source_location, false, block);
|
||||||
|
self.assert_expr_validity(lhs, source_location);
|
||||||
|
self.assert_expr_validity(rhs, source_location);
|
||||||
|
}
|
||||||
|
Stmt::Formal(formal) => {
|
||||||
|
let StmtFormal {
|
||||||
|
kind: _,
|
||||||
|
clk,
|
||||||
|
pred,
|
||||||
|
en,
|
||||||
|
text: _,
|
||||||
|
source_location,
|
||||||
|
} = formal;
|
||||||
|
self.assert_expr_validity(clk, source_location);
|
||||||
|
self.assert_expr_validity(pred, source_location);
|
||||||
|
self.assert_expr_validity(en, source_location);
|
||||||
}
|
}
|
||||||
Stmt::Formal(_) => {}
|
|
||||||
Stmt::If(if_stmt) => {
|
Stmt::If(if_stmt) => {
|
||||||
let sub_blocks = if_stmt.blocks.map(|block| self.make_block_index(block));
|
let StmtIf {
|
||||||
|
cond,
|
||||||
|
source_location,
|
||||||
|
blocks: sub_blocks,
|
||||||
|
} = if_stmt;
|
||||||
|
self.assert_expr_validity(cond, source_location);
|
||||||
|
let sub_blocks = sub_blocks.map(|block| self.make_block_index(block));
|
||||||
self.process_conditional_sub_blocks(block, sub_blocks)
|
self.process_conditional_sub_blocks(block, sub_blocks)
|
||||||
}
|
}
|
||||||
Stmt::Match(match_stmt) => {
|
Stmt::Match(match_stmt) => {
|
||||||
match_stmt.assert_validity();
|
match_stmt.assert_validity();
|
||||||
|
let StmtMatch {
|
||||||
|
expr,
|
||||||
|
source_location,
|
||||||
|
blocks: sub_blocks,
|
||||||
|
} = match_stmt;
|
||||||
|
self.assert_expr_validity(expr, source_location);
|
||||||
let sub_blocks = Vec::from_iter(
|
let sub_blocks = Vec::from_iter(
|
||||||
match_stmt
|
sub_blocks
|
||||||
.blocks
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|block| self.make_block_index(block)),
|
.map(|block| self.make_block_index(block)),
|
||||||
);
|
);
|
||||||
self.process_conditional_sub_blocks(block, sub_blocks.iter().copied())
|
self.visible_exprs.push_empty();
|
||||||
|
let visible_exprs_top = self.visible_exprs.top();
|
||||||
|
for variant_index in 0..expr.ty().variants().len() {
|
||||||
|
visible_exprs_top
|
||||||
|
.insert(<VariantAccess>::new_by_index(expr, variant_index).into());
|
||||||
|
}
|
||||||
|
self.process_conditional_sub_blocks(block, sub_blocks.iter().copied());
|
||||||
|
self.visible_exprs.pop();
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Wire(StmtWire {
|
Stmt::Declaration(StmtDeclaration::Wire(StmtWire {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
wire,
|
wire,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(wire.into()), block),
|
})) => {
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(wire.into()), block);
|
||||||
|
self.visible_exprs.top().insert(wire.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Reg(StmtReg {
|
Stmt::Declaration(StmtDeclaration::Reg(StmtReg {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
reg,
|
reg,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
|
})) => {
|
||||||
|
self.assert_expr_validity(reg.clock_domain(), reg.source_location());
|
||||||
|
if let Some(init) = reg.init() {
|
||||||
|
self.assert_expr_validity(init, reg.source_location());
|
||||||
|
}
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(reg.into()), block);
|
||||||
|
self.visible_exprs.top().insert(reg.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegSync(StmtReg {
|
Stmt::Declaration(StmtDeclaration::RegSync(StmtReg {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
reg,
|
reg,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
|
})) => {
|
||||||
|
self.assert_expr_validity(reg.clock_domain(), reg.source_location());
|
||||||
|
if let Some(init) = reg.init() {
|
||||||
|
self.assert_expr_validity(init, reg.source_location());
|
||||||
|
}
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(reg.into()), block);
|
||||||
|
self.visible_exprs.top().insert(reg.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegAsync(StmtReg {
|
Stmt::Declaration(StmtDeclaration::RegAsync(StmtReg {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
reg,
|
reg,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
|
})) => {
|
||||||
|
self.assert_expr_validity(reg.clock_domain(), reg.source_location());
|
||||||
|
if let Some(init) = reg.init() {
|
||||||
|
self.assert_expr_validity(init, reg.source_location());
|
||||||
|
}
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(reg.into()), block);
|
||||||
|
self.visible_exprs.top().insert(reg.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
instance,
|
instance,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(instance.into()), block),
|
})) => {
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(instance.into()), block);
|
||||||
|
self.visible_exprs.top().insert(instance.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.visible_exprs.pop();
|
||||||
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn assert_validity(&mut self) {
|
fn assert_validity(&mut self) {
|
||||||
match self.module.body {
|
match self.module.body {
|
||||||
|
|
@ -1849,6 +2091,142 @@ impl AssertValidityState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AssertExprValidity<'a> {
|
||||||
|
state: &'a mut AssertValidityState,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InvalidExpr {
|
||||||
|
ExprIsNotVisible(Expr<CanonicalType>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl transform::visit::Visitor for AssertExprValidity<'_> {
|
||||||
|
type Error = InvalidExpr;
|
||||||
|
fn visit_expr_enum(&mut self, v: &ExprEnum) -> Result<(), Self::Error> {
|
||||||
|
match v {
|
||||||
|
ExprEnum::UIntLiteral(_)
|
||||||
|
| ExprEnum::SIntLiteral(_)
|
||||||
|
| ExprEnum::BoolLiteral(_)
|
||||||
|
| ExprEnum::PhantomConst(_)
|
||||||
|
| ExprEnum::BundleLiteral(_)
|
||||||
|
| ExprEnum::ArrayLiteral(_)
|
||||||
|
| ExprEnum::EnumLiteral(_)
|
||||||
|
| ExprEnum::Uninit(_)
|
||||||
|
| ExprEnum::NotU(_)
|
||||||
|
| ExprEnum::NotS(_)
|
||||||
|
| ExprEnum::NotB(_)
|
||||||
|
| ExprEnum::Neg(_)
|
||||||
|
| ExprEnum::BitAndU(_)
|
||||||
|
| ExprEnum::BitAndS(_)
|
||||||
|
| ExprEnum::BitAndB(_)
|
||||||
|
| ExprEnum::BitOrU(_)
|
||||||
|
| ExprEnum::BitOrS(_)
|
||||||
|
| ExprEnum::BitOrB(_)
|
||||||
|
| ExprEnum::BitXorU(_)
|
||||||
|
| ExprEnum::BitXorS(_)
|
||||||
|
| ExprEnum::BitXorB(_)
|
||||||
|
| ExprEnum::AddU(_)
|
||||||
|
| ExprEnum::AddS(_)
|
||||||
|
| ExprEnum::SubU(_)
|
||||||
|
| ExprEnum::SubS(_)
|
||||||
|
| ExprEnum::MulU(_)
|
||||||
|
| ExprEnum::MulS(_)
|
||||||
|
| ExprEnum::DivU(_)
|
||||||
|
| ExprEnum::DivS(_)
|
||||||
|
| ExprEnum::RemU(_)
|
||||||
|
| ExprEnum::RemS(_)
|
||||||
|
| ExprEnum::DynShlU(_)
|
||||||
|
| ExprEnum::DynShlS(_)
|
||||||
|
| ExprEnum::DynShrU(_)
|
||||||
|
| ExprEnum::DynShrS(_)
|
||||||
|
| ExprEnum::FixedShlU(_)
|
||||||
|
| ExprEnum::FixedShlS(_)
|
||||||
|
| ExprEnum::FixedShrU(_)
|
||||||
|
| ExprEnum::FixedShrS(_)
|
||||||
|
| ExprEnum::CmpLtB(_)
|
||||||
|
| ExprEnum::CmpLeB(_)
|
||||||
|
| ExprEnum::CmpGtB(_)
|
||||||
|
| ExprEnum::CmpGeB(_)
|
||||||
|
| ExprEnum::CmpEqB(_)
|
||||||
|
| ExprEnum::CmpNeB(_)
|
||||||
|
| ExprEnum::CmpLtU(_)
|
||||||
|
| ExprEnum::CmpLeU(_)
|
||||||
|
| ExprEnum::CmpGtU(_)
|
||||||
|
| ExprEnum::CmpGeU(_)
|
||||||
|
| ExprEnum::CmpEqU(_)
|
||||||
|
| ExprEnum::CmpNeU(_)
|
||||||
|
| ExprEnum::CmpLtS(_)
|
||||||
|
| ExprEnum::CmpLeS(_)
|
||||||
|
| ExprEnum::CmpGtS(_)
|
||||||
|
| ExprEnum::CmpGeS(_)
|
||||||
|
| ExprEnum::CmpEqS(_)
|
||||||
|
| ExprEnum::CmpNeS(_)
|
||||||
|
| ExprEnum::CastUIntToUInt(_)
|
||||||
|
| ExprEnum::CastUIntToSInt(_)
|
||||||
|
| ExprEnum::CastSIntToUInt(_)
|
||||||
|
| ExprEnum::CastSIntToSInt(_)
|
||||||
|
| ExprEnum::CastBoolToUInt(_)
|
||||||
|
| ExprEnum::CastBoolToSInt(_)
|
||||||
|
| ExprEnum::CastUIntToBool(_)
|
||||||
|
| ExprEnum::CastSIntToBool(_)
|
||||||
|
| ExprEnum::CastBoolToSyncReset(_)
|
||||||
|
| ExprEnum::CastUIntToSyncReset(_)
|
||||||
|
| ExprEnum::CastSIntToSyncReset(_)
|
||||||
|
| ExprEnum::CastBoolToAsyncReset(_)
|
||||||
|
| ExprEnum::CastUIntToAsyncReset(_)
|
||||||
|
| ExprEnum::CastSIntToAsyncReset(_)
|
||||||
|
| ExprEnum::CastSyncResetToBool(_)
|
||||||
|
| ExprEnum::CastSyncResetToUInt(_)
|
||||||
|
| ExprEnum::CastSyncResetToSInt(_)
|
||||||
|
| ExprEnum::CastSyncResetToReset(_)
|
||||||
|
| ExprEnum::CastAsyncResetToBool(_)
|
||||||
|
| ExprEnum::CastAsyncResetToUInt(_)
|
||||||
|
| ExprEnum::CastAsyncResetToSInt(_)
|
||||||
|
| ExprEnum::CastAsyncResetToReset(_)
|
||||||
|
| ExprEnum::CastResetToBool(_)
|
||||||
|
| ExprEnum::CastResetToUInt(_)
|
||||||
|
| ExprEnum::CastResetToSInt(_)
|
||||||
|
| ExprEnum::CastBoolToClock(_)
|
||||||
|
| ExprEnum::CastUIntToClock(_)
|
||||||
|
| ExprEnum::CastSIntToClock(_)
|
||||||
|
| ExprEnum::CastClockToBool(_)
|
||||||
|
| ExprEnum::CastClockToUInt(_)
|
||||||
|
| ExprEnum::CastClockToSInt(_)
|
||||||
|
| ExprEnum::FieldAccess(_)
|
||||||
|
| ExprEnum::ArrayIndex(_)
|
||||||
|
| ExprEnum::DynArrayIndex(_)
|
||||||
|
| ExprEnum::ReduceBitAndU(_)
|
||||||
|
| ExprEnum::ReduceBitAndS(_)
|
||||||
|
| ExprEnum::ReduceBitOrU(_)
|
||||||
|
| ExprEnum::ReduceBitOrS(_)
|
||||||
|
| ExprEnum::ReduceBitXorU(_)
|
||||||
|
| ExprEnum::ReduceBitXorS(_)
|
||||||
|
| ExprEnum::SliceUInt(_)
|
||||||
|
| ExprEnum::SliceSInt(_)
|
||||||
|
| ExprEnum::CastToBits(_)
|
||||||
|
| ExprEnum::CastBitsTo(_)
|
||||||
|
| ExprEnum::ToTraceAsString(_)
|
||||||
|
| ExprEnum::TraceAsStringAsInner(_)
|
||||||
|
| ExprEnum::FormalInput(_) => v.default_visit(self),
|
||||||
|
ExprEnum::VariantAccess(_)
|
||||||
|
| ExprEnum::ModuleIO(_)
|
||||||
|
| ExprEnum::Instance(_)
|
||||||
|
| ExprEnum::Wire(_)
|
||||||
|
| ExprEnum::Reg(_)
|
||||||
|
| ExprEnum::RegSync(_)
|
||||||
|
| ExprEnum::RegAsync(_)
|
||||||
|
| ExprEnum::MemPort(_) => {
|
||||||
|
if self.state.visible_exprs.contains(v) {
|
||||||
|
// no need to visit inner expressions, we already checked them before adding them to visible_exprs
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(InvalidExpr::ExprIsNotVisible(v.to_expr()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExprEnum::SimIoForGlobal(_) => Err(InvalidExpr::ExprIsNotVisible(v.to_expr())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: BundleType> Module<T> {
|
impl<T: BundleType> Module<T> {
|
||||||
/// you generally should use the [`#[hdl_module]`][`crate::hdl_module`] proc-macro and [`ModuleBuilder`] instead
|
/// you generally should use the [`#[hdl_module]`][`crate::hdl_module`] proc-macro and [`ModuleBuilder`] instead
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
|
@ -1974,6 +2352,7 @@ impl<T: BundleType> Module<T> {
|
||||||
AssertValidityState {
|
AssertValidityState {
|
||||||
module: self.canonical(),
|
module: self.canonical(),
|
||||||
blocks: vec![],
|
blocks: vec![],
|
||||||
|
visible_exprs: VisibleExprsStack::default(),
|
||||||
target_states: HashMap::with_capacity_and_hasher(64, Default::default()),
|
target_states: HashMap::with_capacity_and_hasher(64, Default::default()),
|
||||||
}
|
}
|
||||||
.assert_validity();
|
.assert_validity();
|
||||||
|
|
@ -2079,7 +2458,7 @@ impl<T: Type, R: ResetType> RegBuilder<Expr<ClockDomain<R>>, Option<Expr<T>>, T>
|
||||||
ty,
|
ty,
|
||||||
} = self;
|
} = self;
|
||||||
ModuleBuilder::with(|module_builder| {
|
ModuleBuilder::with(|module_builder| {
|
||||||
let scoped_name = ScopedNameId(module_builder.name, NameId(name, Id::new()));
|
let scoped_name = ScopedNameId(module_builder.name.into(), NameId(name, Id::new()));
|
||||||
let reg = Reg::new_unchecked(scoped_name, source_location, ty, clock_domain, init);
|
let reg = Reg::new_unchecked(scoped_name, source_location, ty, clock_domain, init);
|
||||||
let retval = reg.to_expr();
|
let retval = reg.to_expr();
|
||||||
// convert before borrow_mut since ModuleBuilder could be reentered by T::canonical()
|
// convert before borrow_mut since ModuleBuilder could be reentered by T::canonical()
|
||||||
|
|
@ -2475,6 +2854,9 @@ pub fn annotate<T: Type>(target: Expr<T>, annotations: impl IntoAnnotations) {
|
||||||
instance,
|
instance,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
TargetBase::FormalInput(_) | TargetBase::SimIoForGlobal(_) => {
|
||||||
|
unreachable!("not a valid annotation target")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
unwrap!(m.impl_.borrow_mut().body.builder_normal_body_opt())
|
unwrap!(m.impl_.borrow_mut().body.builder_normal_body_opt())
|
||||||
|
|
@ -2489,7 +2871,7 @@ pub fn annotate<T: Type>(target: Expr<T>, annotations: impl IntoAnnotations) {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn wire_with_loc<T: Type>(name: &str, source_location: SourceLocation, ty: T) -> Expr<T> {
|
pub fn wire_with_loc<T: Type>(name: &str, source_location: SourceLocation, ty: T) -> Expr<T> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let wire = Wire::<T>::new_unchecked(scoped_name, source_location, ty);
|
let wire = Wire::<T>::new_unchecked(scoped_name, source_location, ty);
|
||||||
let retval = wire.to_expr();
|
let retval = wire.to_expr();
|
||||||
let canonical_wire = wire.canonical();
|
let canonical_wire = wire.canonical();
|
||||||
|
|
@ -2521,7 +2903,7 @@ fn incomplete_declaration(
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> Rc<RefCell<IncompleteDeclaration>> {
|
) -> Rc<RefCell<IncompleteDeclaration>> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete {
|
let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete {
|
||||||
name: scoped_name,
|
name: scoped_name,
|
||||||
source_location,
|
source_location,
|
||||||
|
|
@ -2697,7 +3079,7 @@ pub fn instance_with_loc<T: BundleType>(
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> Expr<T> {
|
) -> Expr<T> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let instance = Instance::<T> {
|
let instance = Instance::<T> {
|
||||||
scoped_name,
|
scoped_name,
|
||||||
instantiated,
|
instantiated,
|
||||||
|
|
@ -2736,7 +3118,7 @@ fn memory_impl<Element: Type, Len: Size>(
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> MemBuilder<Element, Len> {
|
) -> MemBuilder<Element, Len> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let (retval, target_mem) = MemBuilder::new(scoped_name, source_location, mem_element_type);
|
let (retval, target_mem) = MemBuilder::new(scoped_name, source_location, mem_element_type);
|
||||||
let mut impl_ = m.impl_.borrow_mut();
|
let mut impl_ = m.impl_.borrow_mut();
|
||||||
let body = impl_.body.builder_normal_body();
|
let body = impl_.body.builder_normal_body();
|
||||||
|
|
@ -2891,7 +3273,7 @@ impl<T: Type> ModuleIO<T> {
|
||||||
NameId(self.bundle_field.name, self.id)
|
NameId(self.bundle_field.name, self.id)
|
||||||
}
|
}
|
||||||
pub fn scoped_name(&self) -> ScopedNameId {
|
pub fn scoped_name(&self) -> ScopedNameId {
|
||||||
ScopedNameId(self.containing_module_name, self.name_id())
|
ScopedNameId(self.containing_module_name.into(), self.name_id())
|
||||||
}
|
}
|
||||||
pub fn source_location(&self) -> SourceLocation {
|
pub fn source_location(&self) -> SourceLocation {
|
||||||
self.source_location
|
self.source_location
|
||||||
|
|
@ -2964,10 +3346,102 @@ impl fmt::Debug for InstantiatedModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
pub enum InstantiatedModuleOrGlobal {
|
||||||
|
Global,
|
||||||
|
InstantiatedModule(InstantiatedModule),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstantiatedModuleOrGlobal {
|
||||||
|
pub fn leaf_module_source_location(self) -> SourceLocation {
|
||||||
|
match self {
|
||||||
|
Self::Global => SourceLocation::builtin(),
|
||||||
|
Self::InstantiatedModule(v) => v.leaf_module().source_location(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<InstantiatedModule> for InstantiatedModuleOrGlobal {
|
||||||
|
fn from(value: InstantiatedModule) -> Self {
|
||||||
|
Self::InstantiatedModule(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for InstantiatedModuleOrGlobal {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Global => f.write_str("Global"),
|
||||||
|
Self::InstantiatedModule(v) => v.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
pub struct TargetInInstantiatedModule {
|
pub struct TargetInInstantiatedModuleOrGlobal {
|
||||||
pub instantiated_module: InstantiatedModule,
|
instantiated_module_or_global: InstantiatedModuleOrGlobal,
|
||||||
pub target: Target,
|
target: Target,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TargetInInstantiatedModuleOrGlobal {
|
||||||
|
#[track_caller]
|
||||||
|
pub fn new(instantiated_module_or_global: InstantiatedModuleOrGlobal, target: Target) -> Self {
|
||||||
|
match (
|
||||||
|
instantiated_module_or_global,
|
||||||
|
target.base().target_name().0.0,
|
||||||
|
) {
|
||||||
|
(InstantiatedModuleOrGlobal::Global, NameIdOrGlobal::Global)
|
||||||
|
| (InstantiatedModuleOrGlobal::InstantiatedModule(_), NameIdOrGlobal::NameId(_)) => {
|
||||||
|
Self {
|
||||||
|
instantiated_module_or_global,
|
||||||
|
target,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(InstantiatedModuleOrGlobal::Global, NameIdOrGlobal::NameId(_))
|
||||||
|
| (InstantiatedModuleOrGlobal::InstantiatedModule(_), NameIdOrGlobal::Global) => {
|
||||||
|
panic!(
|
||||||
|
"instantiated_module_or_global doesn't match target.base().target_name().0.0:\n\
|
||||||
|
instantiated_module_or_global: {instantiated_module_or_global:?}\n\
|
||||||
|
target: {target:?}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn from_target(
|
||||||
|
instantiated_module: impl Into<InstantiatedModuleOrGlobal>,
|
||||||
|
target: Target,
|
||||||
|
) -> Self {
|
||||||
|
let instantiated_module = instantiated_module.into();
|
||||||
|
Self {
|
||||||
|
instantiated_module_or_global: match target.base().target_name().0.0 {
|
||||||
|
NameIdOrGlobal::Global => InstantiatedModuleOrGlobal::Global,
|
||||||
|
NameIdOrGlobal::NameId(name_id) => {
|
||||||
|
let InstantiatedModuleOrGlobal::InstantiatedModule(instantiated_module) =
|
||||||
|
instantiated_module
|
||||||
|
else {
|
||||||
|
panic!(
|
||||||
|
"target is in a module, but no InstantiatedModule was provided: {target:#?}"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
name_id,
|
||||||
|
instantiated_module.leaf_module().name_id(),
|
||||||
|
"target isn't contained in module:\n\
|
||||||
|
target: {target:#?}\n\
|
||||||
|
instantiated_module: {instantiated_module:?}",
|
||||||
|
);
|
||||||
|
InstantiatedModuleOrGlobal::InstantiatedModule(instantiated_module)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
target,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn instantiated_module_or_global(self) -> InstantiatedModuleOrGlobal {
|
||||||
|
self.instantiated_module_or_global
|
||||||
|
}
|
||||||
|
pub fn target(self) -> Target {
|
||||||
|
self.target
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ use crate::{
|
||||||
ops::{self, ArrayLiteral},
|
ops::{self, ArrayLiteral},
|
||||||
target::{
|
target::{
|
||||||
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
|
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
|
||||||
TargetPathDynArrayElement, TargetPathElement,
|
TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString,
|
||||||
|
TargetPathTraceAsStringInner,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
formal::FormalKind,
|
formal::FormalKind,
|
||||||
|
|
@ -26,6 +27,7 @@ use crate::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reset::{ResetType, ResetTypeDispatch},
|
reset::{ResetType, ResetTypeDispatch},
|
||||||
sim::ExternModuleSimulation,
|
sim::ExternModuleSimulation,
|
||||||
|
ty::TraceAsString,
|
||||||
util::{HashMap, HashSet},
|
util::{HashMap, HashSet},
|
||||||
};
|
};
|
||||||
use hashbrown::hash_map::Entry;
|
use hashbrown::hash_map::Entry;
|
||||||
|
|
@ -103,6 +105,10 @@ enum ResetsLayout {
|
||||||
element: Interned<ResetsLayout>,
|
element: Interned<ResetsLayout>,
|
||||||
reset_count: usize,
|
reset_count: usize,
|
||||||
},
|
},
|
||||||
|
Transparent {
|
||||||
|
inner: Interned<ResetsLayout>,
|
||||||
|
reset_count: usize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResetsLayout {
|
impl ResetsLayout {
|
||||||
|
|
@ -112,7 +118,8 @@ impl ResetsLayout {
|
||||||
ResetsLayout::Reset | ResetsLayout::SyncReset | ResetsLayout::AsyncReset => 1,
|
ResetsLayout::Reset | ResetsLayout::SyncReset | ResetsLayout::AsyncReset => 1,
|
||||||
ResetsLayout::Bundle { reset_count, .. }
|
ResetsLayout::Bundle { reset_count, .. }
|
||||||
| ResetsLayout::Enum { reset_count, .. }
|
| ResetsLayout::Enum { reset_count, .. }
|
||||||
| ResetsLayout::Array { reset_count, .. } => reset_count,
|
| ResetsLayout::Array { reset_count, .. }
|
||||||
|
| ResetsLayout::Transparent { reset_count, .. } => reset_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn new(ty: CanonicalType) -> Self {
|
fn new(ty: CanonicalType) -> Self {
|
||||||
|
|
@ -166,6 +173,13 @@ impl ResetsLayout {
|
||||||
CanonicalType::Clock(_) => ResetsLayout::NoResets,
|
CanonicalType::Clock(_) => ResetsLayout::NoResets,
|
||||||
CanonicalType::PhantomConst(_) => ResetsLayout::NoResets,
|
CanonicalType::PhantomConst(_) => ResetsLayout::NoResets,
|
||||||
CanonicalType::DynSimOnly(_) => ResetsLayout::NoResets,
|
CanonicalType::DynSimOnly(_) => ResetsLayout::NoResets,
|
||||||
|
CanonicalType::TraceAsString(ty) => {
|
||||||
|
let inner = ResetsLayout::new(ty.inner_ty()).intern_sized();
|
||||||
|
ResetsLayout::Transparent {
|
||||||
|
inner,
|
||||||
|
reset_count: inner.reset_count(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -315,6 +329,12 @@ impl ResetGraph {
|
||||||
} => {
|
} => {
|
||||||
self.append_new_nodes_for_layout(*element, node_indexes, source_location);
|
self.append_new_nodes_for_layout(*element, node_indexes, source_location);
|
||||||
}
|
}
|
||||||
|
ResetsLayout::Transparent {
|
||||||
|
inner,
|
||||||
|
reset_count: _,
|
||||||
|
} => {
|
||||||
|
self.append_new_nodes_for_layout(*inner, node_indexes, source_location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -357,6 +377,21 @@ impl Resets {
|
||||||
node_indexes: self.node_indexes,
|
node_indexes: self.node_indexes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn trace_as_string_inner(self) -> Self {
|
||||||
|
let trace_as_string = TraceAsString::from_canonical(self.ty);
|
||||||
|
let ResetsLayout::Transparent {
|
||||||
|
inner,
|
||||||
|
reset_count: _,
|
||||||
|
} = self.layout
|
||||||
|
else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
ty: trace_as_string.inner_ty(),
|
||||||
|
layout: *inner,
|
||||||
|
node_indexes: self.node_indexes,
|
||||||
|
}
|
||||||
|
}
|
||||||
fn bundle_fields(self) -> impl Iterator<Item = Self> {
|
fn bundle_fields(self) -> impl Iterator<Item = Self> {
|
||||||
let bundle = Bundle::from_canonical(self.ty);
|
let bundle = Bundle::from_canonical(self.ty);
|
||||||
let ResetsLayout::Bundle {
|
let ResetsLayout::Bundle {
|
||||||
|
|
@ -480,6 +515,17 @@ impl Resets {
|
||||||
CanonicalType::SyncReset(SyncReset)
|
CanonicalType::SyncReset(SyncReset)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
CanonicalType::TraceAsString(ty) => Ok(CanonicalType::TraceAsString(
|
||||||
|
ty.with_new_inner_ty(
|
||||||
|
self.array_elements()
|
||||||
|
.substituted_type(
|
||||||
|
reset_graph,
|
||||||
|
fallback_to_sync_reset,
|
||||||
|
fallback_error_source_location,
|
||||||
|
)?
|
||||||
|
.intern_sized(),
|
||||||
|
),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1013,7 +1059,8 @@ fn cast_bit_op<P: Pass, T: Type, A: Type>(
|
||||||
| CanonicalType::Bundle(_)
|
| CanonicalType::Bundle(_)
|
||||||
| CanonicalType::Reset(_)
|
| CanonicalType::Reset(_)
|
||||||
| CanonicalType::PhantomConst(_)
|
| CanonicalType::PhantomConst(_)
|
||||||
| CanonicalType::DynSimOnly(_) => unreachable!(),
|
| CanonicalType::DynSimOnly(_)
|
||||||
|
| CanonicalType::TraceAsString(_) => unreachable!(),
|
||||||
$(CanonicalType::$Variant(ty) => Expr::expr_enum($arg.cast_to(ty)),)*
|
$(CanonicalType::$Variant(ty) => Expr::expr_enum($arg.cast_to(ty)),)*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1024,7 +1071,8 @@ fn cast_bit_op<P: Pass, T: Type, A: Type>(
|
||||||
CanonicalType::Array(_)
|
CanonicalType::Array(_)
|
||||||
| CanonicalType::Enum(_)
|
| CanonicalType::Enum(_)
|
||||||
| CanonicalType::Bundle(_)
|
| CanonicalType::Bundle(_)
|
||||||
| CanonicalType::Reset(_) => unreachable!(),
|
| CanonicalType::Reset(_)
|
||||||
|
| CanonicalType::TraceAsString(_) => unreachable!(),
|
||||||
CanonicalType::PhantomConst(_) |
|
CanonicalType::PhantomConst(_) |
|
||||||
CanonicalType::DynSimOnly(_) => Expr::expr_enum(arg),
|
CanonicalType::DynSimOnly(_) => Expr::expr_enum(arg),
|
||||||
$(CanonicalType::$Variant(_) => {
|
$(CanonicalType::$Variant(_) => {
|
||||||
|
|
@ -1156,6 +1204,10 @@ impl<P: Pass> RunPass<P> for ExprEnum {
|
||||||
ExprEnum::SliceSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::SliceSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::CastToBits(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::CastToBits(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::CastBitsTo(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::CastBitsTo(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
|
ExprEnum::TraceAsStringAsInner(expr) => {
|
||||||
|
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
|
||||||
|
}
|
||||||
|
ExprEnum::ToTraceAsString(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::ModuleIO(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::ModuleIO(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::Instance(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::Instance(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::Wire(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::Wire(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
|
|
@ -1163,6 +1215,10 @@ impl<P: Pass> RunPass<P> for ExprEnum {
|
||||||
ExprEnum::RegSync(expr) => reg_expr_run_pass(expr, pass_args),
|
ExprEnum::RegSync(expr) => reg_expr_run_pass(expr, pass_args),
|
||||||
ExprEnum::RegAsync(expr) => reg_expr_run_pass(expr, pass_args),
|
ExprEnum::RegAsync(expr) => reg_expr_run_pass(expr, pass_args),
|
||||||
ExprEnum::MemPort(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::MemPort(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
|
ExprEnum::FormalInput(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
|
ExprEnum::SimIoForGlobal(_) => {
|
||||||
|
unreachable!("Module is known to not contain SimIoForGlobal from validation")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1536,6 +1592,67 @@ impl RunPassExpr for ops::CastBitsTo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RunPassExpr for ops::TraceAsStringAsInner {
|
||||||
|
type Args<'a> = [Expr<CanonicalType>; 1];
|
||||||
|
|
||||||
|
fn args<'a>(&'a self) -> Self::Args<'a> {
|
||||||
|
[Expr::canonical(self.arg())]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source_location(&self) -> Option<SourceLocation> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn union_parts(
|
||||||
|
&self,
|
||||||
|
resets: Resets,
|
||||||
|
args_resets: Vec<Resets>,
|
||||||
|
mut pass_args: PassArgs<'_, BuildResetGraph>,
|
||||||
|
) -> Result<(), DeduceResetsError> {
|
||||||
|
pass_args.union(resets, args_resets[0].trace_as_string_inner(), None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
|
&self,
|
||||||
|
_ty: CanonicalType,
|
||||||
|
new_args: Vec<Expr<CanonicalType>>,
|
||||||
|
) -> Result<Self, DeduceResetsError> {
|
||||||
|
Ok(Self::new(Expr::from_canonical(new_args[0])))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RunPassExpr for ops::ToTraceAsString {
|
||||||
|
type Args<'a> = [Expr<CanonicalType>; 1];
|
||||||
|
|
||||||
|
fn args<'a>(&'a self) -> Self::Args<'a> {
|
||||||
|
[Expr::canonical(self.inner())]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source_location(&self) -> Option<SourceLocation> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn union_parts(
|
||||||
|
&self,
|
||||||
|
resets: Resets,
|
||||||
|
args_resets: Vec<Resets>,
|
||||||
|
mut pass_args: PassArgs<'_, BuildResetGraph>,
|
||||||
|
) -> Result<(), DeduceResetsError> {
|
||||||
|
pass_args.union(resets.trace_as_string_inner(), args_resets[0], None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
|
&self,
|
||||||
|
_ty: CanonicalType,
|
||||||
|
new_args: Vec<Expr<CanonicalType>>,
|
||||||
|
) -> Result<Self, DeduceResetsError> {
|
||||||
|
Ok(Self::new(
|
||||||
|
new_args[0],
|
||||||
|
self.ty().with_new_inner_ty(new_args[0].ty().intern_sized()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RunPassExpr for ModuleIO<CanonicalType> {
|
impl RunPassExpr for ModuleIO<CanonicalType> {
|
||||||
type Args<'a> = [Expr<CanonicalType>; 0];
|
type Args<'a> = [Expr<CanonicalType>; 0];
|
||||||
|
|
||||||
|
|
@ -1691,7 +1808,8 @@ impl RunPassDispatch for AnyReg {
|
||||||
| CanonicalType::Reset(_)
|
| CanonicalType::Reset(_)
|
||||||
| CanonicalType::Clock(_)
|
| CanonicalType::Clock(_)
|
||||||
| CanonicalType::PhantomConst(_)
|
| CanonicalType::PhantomConst(_)
|
||||||
| CanonicalType::DynSimOnly(_) => unreachable!(),
|
| CanonicalType::DynSimOnly(_)
|
||||||
|
| CanonicalType::TraceAsString(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1818,6 +1936,7 @@ impl_run_pass_copy!([] SVAttributeAnnotation);
|
||||||
impl_run_pass_copy!([] UInt);
|
impl_run_pass_copy!([] UInt);
|
||||||
impl_run_pass_copy!([] usize);
|
impl_run_pass_copy!([] usize);
|
||||||
impl_run_pass_copy!([] FormalKind);
|
impl_run_pass_copy!([] FormalKind);
|
||||||
|
impl_run_pass_copy!([] crate::formal::FormalInput);
|
||||||
impl_run_pass_copy!([] PhantomConst);
|
impl_run_pass_copy!([] PhantomConst);
|
||||||
|
|
||||||
macro_rules! impl_run_pass_for_struct {
|
macro_rules! impl_run_pass_for_struct {
|
||||||
|
|
@ -2134,6 +2253,12 @@ impl<P: Pass> RunPass<P> for TargetBase {
|
||||||
&TargetBase::RegAsync(v) => v.into(),
|
&TargetBase::RegAsync(v) => v.into(),
|
||||||
TargetBase::Wire(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Wire)),
|
TargetBase::Wire(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Wire)),
|
||||||
TargetBase::Instance(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Instance)),
|
TargetBase::Instance(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Instance)),
|
||||||
|
TargetBase::FormalInput(v) => {
|
||||||
|
return Ok(v.run_pass(pass_args)?.map(TargetBase::FormalInput));
|
||||||
|
}
|
||||||
|
TargetBase::SimIoForGlobal(_) => {
|
||||||
|
unreachable!("Module is known to not contain SimIoForGlobal from validation")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(reg.run_pass(pass_args)?.map(|reg| match reg {
|
Ok(reg.run_pass(pass_args)?.map(|reg| match reg {
|
||||||
AnyReg::Reg(reg) => TargetBase::Reg(reg),
|
AnyReg::Reg(reg) => TargetBase::Reg(reg),
|
||||||
|
|
@ -2173,30 +2298,6 @@ impl<P: Pass> RunPass<P> for StmtDeclaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_run_pass_for_struct! {
|
|
||||||
impl[] RunPass for TargetPathBundleField {
|
|
||||||
name: _,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_run_pass_for_struct! {
|
|
||||||
impl[] RunPass for TargetPathArrayElement {
|
|
||||||
index: _,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_run_pass_for_struct! {
|
|
||||||
impl[] RunPass for TargetPathDynArrayElement {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_run_pass_for_enum! {
|
|
||||||
impl[] RunPass for TargetPathElement {
|
|
||||||
BundleField(v),
|
|
||||||
ArrayElement(v),
|
|
||||||
DynArrayElement(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_run_pass_for_enum! {
|
impl_run_pass_for_enum! {
|
||||||
impl[] RunPass for Target {
|
impl[] RunPass for Target {
|
||||||
Base(v),
|
Base(v),
|
||||||
|
|
@ -2204,11 +2305,28 @@ impl_run_pass_for_enum! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_run_pass_for_struct! {
|
impl<P: Pass> RunPass<P> for TargetChild {
|
||||||
#[constructor = TargetChild::new(parent, path_element)]
|
fn run_pass(
|
||||||
impl[] RunPass for TargetChild {
|
&self,
|
||||||
parent(): _,
|
mut pass_args: PassArgs<'_, P>,
|
||||||
path_element(): _,
|
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
|
||||||
|
Ok(self.parent().run_pass(pass_args.as_mut())?.map(|parent| {
|
||||||
|
let path_element = match *self.path_element() {
|
||||||
|
TargetPathElement::BundleField(TargetPathBundleField { name: _ })
|
||||||
|
| TargetPathElement::ArrayElement(TargetPathArrayElement { index: _ })
|
||||||
|
| TargetPathElement::DynArrayElement(TargetPathDynArrayElement {})
|
||||||
|
| TargetPathElement::TraceAsStringInner(TargetPathTraceAsStringInner {}) => {
|
||||||
|
self.path_element()
|
||||||
|
}
|
||||||
|
TargetPathElement::ToTraceAsString(TargetPathToTraceAsString { ty }) => {
|
||||||
|
TargetPathElement::from(TargetPathToTraceAsString {
|
||||||
|
ty: ty.with_new_inner_ty(parent.canonical_ty().intern_sized()),
|
||||||
|
})
|
||||||
|
.intern_sized()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TargetChild::new(parent, path_element)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
||||||
transform::visit::{Fold, Folder},
|
transform::visit::{Fold, Folder},
|
||||||
},
|
},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, TraceAsString, Type},
|
||||||
util::HashMap,
|
util::HashMap,
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
};
|
};
|
||||||
|
|
@ -64,6 +64,7 @@ fn contains_any_enum_types(ty: CanonicalType) -> bool {
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.any(|field| contains_any_enum_types(field.ty)),
|
.any(|field| contains_any_enum_types(field.ty)),
|
||||||
|
CanonicalType::TraceAsString(ty) => contains_any_enum_types(ty.inner_ty()),
|
||||||
CanonicalType::UInt(_)
|
CanonicalType::UInt(_)
|
||||||
| CanonicalType::SInt(_)
|
| CanonicalType::SInt(_)
|
||||||
| CanonicalType::Bool(_)
|
| CanonicalType::Bool(_)
|
||||||
|
|
@ -95,11 +96,12 @@ enum EnumTypeState {
|
||||||
|
|
||||||
struct ModuleState {
|
struct ModuleState {
|
||||||
module_name: NameId,
|
module_name: NameId,
|
||||||
|
expr_cache: HashMap<ExprEnum, ExprEnum>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleState {
|
impl ModuleState {
|
||||||
fn gen_name(&mut self, name: &str) -> ScopedNameId {
|
fn gen_name(&mut self, name: &str) -> ScopedNameId {
|
||||||
ScopedNameId(self.module_name, NameId(name.intern(), Id::new()))
|
ScopedNameId(self.module_name.into(), NameId(name.intern(), Id::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,6 +315,24 @@ impl State {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn handle_stmt_connect_trace_as_string(
|
||||||
|
&mut self,
|
||||||
|
unfolded_lhs_ty: TraceAsString,
|
||||||
|
unfolded_rhs_ty: TraceAsString,
|
||||||
|
folded_lhs: Expr<TraceAsString>,
|
||||||
|
folded_rhs: Expr<TraceAsString>,
|
||||||
|
source_location: SourceLocation,
|
||||||
|
output_stmts: &mut Vec<Stmt>,
|
||||||
|
) -> Result<(), SimplifyEnumsError> {
|
||||||
|
self.handle_stmt_connect(
|
||||||
|
unfolded_lhs_ty.inner_ty(),
|
||||||
|
unfolded_rhs_ty.inner_ty(),
|
||||||
|
ops::TraceAsStringAsInner::new(folded_lhs).to_expr(),
|
||||||
|
ops::TraceAsStringAsInner::new(folded_rhs).to_expr(),
|
||||||
|
source_location,
|
||||||
|
output_stmts,
|
||||||
|
)
|
||||||
|
}
|
||||||
fn handle_stmt_connect_bundle(
|
fn handle_stmt_connect_bundle(
|
||||||
&mut self,
|
&mut self,
|
||||||
unfolded_lhs_ty: Bundle,
|
unfolded_lhs_ty: Bundle,
|
||||||
|
|
@ -509,6 +529,15 @@ impl State {
|
||||||
source_location,
|
source_location,
|
||||||
output_stmts,
|
output_stmts,
|
||||||
),
|
),
|
||||||
|
CanonicalType::TraceAsString(unfolded_lhs_ty) => self
|
||||||
|
.handle_stmt_connect_trace_as_string(
|
||||||
|
unfolded_lhs_ty,
|
||||||
|
TraceAsString::from_canonical(unfolded_rhs_ty),
|
||||||
|
Expr::from_canonical(folded_lhs),
|
||||||
|
Expr::from_canonical(folded_rhs),
|
||||||
|
source_location,
|
||||||
|
output_stmts,
|
||||||
|
),
|
||||||
CanonicalType::UInt(_)
|
CanonicalType::UInt(_)
|
||||||
| CanonicalType::SInt(_)
|
| CanonicalType::SInt(_)
|
||||||
| CanonicalType::Bool(_)
|
| CanonicalType::Bool(_)
|
||||||
|
|
@ -528,6 +557,8 @@ fn connect_port(
|
||||||
rhs: Expr<CanonicalType>,
|
rhs: Expr<CanonicalType>,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) {
|
) {
|
||||||
|
let lhs = Expr::unwrap_transparent_types(lhs);
|
||||||
|
let rhs = Expr::unwrap_transparent_types(rhs);
|
||||||
if lhs.ty() == rhs.ty() {
|
if lhs.ty() == rhs.ty() {
|
||||||
stmts.push(
|
stmts.push(
|
||||||
StmtConnect {
|
StmtConnect {
|
||||||
|
|
@ -573,6 +604,9 @@ fn connect_port(
|
||||||
connect_port(stmts, lhs[index], rhs[index], source_location);
|
connect_port(stmts, lhs[index], rhs[index], source_location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(CanonicalType::TraceAsString(_), CanonicalType::TraceAsString(_)) => {
|
||||||
|
unreachable!("handled by unwrap_transparent_types")
|
||||||
|
}
|
||||||
(CanonicalType::Bundle(_), _)
|
(CanonicalType::Bundle(_), _)
|
||||||
| (CanonicalType::Enum(_), _)
|
| (CanonicalType::Enum(_), _)
|
||||||
| (CanonicalType::Array(_), _)
|
| (CanonicalType::Array(_), _)
|
||||||
|
|
@ -584,7 +618,8 @@ fn connect_port(
|
||||||
| (CanonicalType::SyncReset(_), _)
|
| (CanonicalType::SyncReset(_), _)
|
||||||
| (CanonicalType::Reset(_), _)
|
| (CanonicalType::Reset(_), _)
|
||||||
| (CanonicalType::PhantomConst(_), _)
|
| (CanonicalType::PhantomConst(_), _)
|
||||||
| (CanonicalType::DynSimOnly(_), _) => unreachable!(
|
| (CanonicalType::DynSimOnly(_), _)
|
||||||
|
| (CanonicalType::TraceAsString(_), _) => unreachable!(
|
||||||
"trying to connect memory ports:\n{:?}\n{:?}",
|
"trying to connect memory ports:\n{:?}\n{:?}",
|
||||||
lhs.ty(),
|
lhs.ty(),
|
||||||
rhs.ty(),
|
rhs.ty(),
|
||||||
|
|
@ -641,6 +676,7 @@ impl Folder for State {
|
||||||
fn fold_module<T: BundleType>(&mut self, v: Module<T>) -> Result<Module<T>, Self::Error> {
|
fn fold_module<T: BundleType>(&mut self, v: Module<T>) -> Result<Module<T>, Self::Error> {
|
||||||
self.module_state_stack.push(ModuleState {
|
self.module_state_stack.push(ModuleState {
|
||||||
module_name: v.name_id(),
|
module_name: v.name_id(),
|
||||||
|
expr_cache: HashMap::default(),
|
||||||
});
|
});
|
||||||
let retval = Fold::default_fold(v, self);
|
let retval = Fold::default_fold(v, self);
|
||||||
self.module_state_stack.pop();
|
self.module_state_stack.pop();
|
||||||
|
|
@ -648,30 +684,39 @@ impl Folder for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_expr_enum(&mut self, op: ExprEnum) -> Result<ExprEnum, Self::Error> {
|
fn fold_expr_enum(&mut self, op: ExprEnum) -> Result<ExprEnum, Self::Error> {
|
||||||
match op {
|
if let Some(folded_op) = self
|
||||||
|
.module_state_stack
|
||||||
|
.last()
|
||||||
|
.expect("known to be in module")
|
||||||
|
.expr_cache
|
||||||
|
.get(&op)
|
||||||
|
{
|
||||||
|
return Ok(*folded_op);
|
||||||
|
}
|
||||||
|
let folded_op = match op {
|
||||||
ExprEnum::EnumLiteral(op) => {
|
ExprEnum::EnumLiteral(op) => {
|
||||||
let folded_variant_value = op.variant_value().map(|v| v.fold(self)).transpose()?;
|
let folded_variant_value = op.variant_value().map(|v| v.fold(self)).transpose()?;
|
||||||
Ok(*Expr::expr_enum(self.handle_enum_literal(
|
*Expr::expr_enum(self.handle_enum_literal(
|
||||||
op.ty(),
|
op.ty(),
|
||||||
op.variant_index(),
|
op.variant_index(),
|
||||||
folded_variant_value,
|
folded_variant_value,
|
||||||
)?))
|
)?)
|
||||||
}
|
}
|
||||||
ExprEnum::VariantAccess(op) => {
|
ExprEnum::VariantAccess(op) => {
|
||||||
let folded_base_expr = Expr::canonical(op.base()).fold(self)?;
|
let folded_base_expr = Expr::canonical(op.base()).fold(self)?;
|
||||||
Ok(*Expr::expr_enum(self.handle_variant_access(
|
*Expr::expr_enum(self.handle_variant_access(
|
||||||
op.base().ty(),
|
op.base().ty(),
|
||||||
folded_base_expr,
|
folded_base_expr,
|
||||||
op.variant_index(),
|
op.variant_index(),
|
||||||
)?))
|
)?)
|
||||||
}
|
}
|
||||||
ExprEnum::MemPort(mem_port) => Ok(
|
ExprEnum::MemPort(mem_port) => {
|
||||||
if let Some(&wire) = self.replacement_mem_ports.get(&mem_port) {
|
if let Some(&wire) = self.replacement_mem_ports.get(&mem_port) {
|
||||||
ExprEnum::Wire(wire)
|
ExprEnum::Wire(wire)
|
||||||
} else {
|
} else {
|
||||||
ExprEnum::MemPort(mem_port.fold(self)?)
|
ExprEnum::MemPort(mem_port.fold(self)?)
|
||||||
},
|
}
|
||||||
),
|
}
|
||||||
ExprEnum::UIntLiteral(_)
|
ExprEnum::UIntLiteral(_)
|
||||||
| ExprEnum::SIntLiteral(_)
|
| ExprEnum::SIntLiteral(_)
|
||||||
| ExprEnum::BoolLiteral(_)
|
| ExprEnum::BoolLiteral(_)
|
||||||
|
|
@ -772,13 +817,23 @@ impl Folder for State {
|
||||||
| ExprEnum::SliceSInt(_)
|
| ExprEnum::SliceSInt(_)
|
||||||
| ExprEnum::CastToBits(_)
|
| ExprEnum::CastToBits(_)
|
||||||
| ExprEnum::CastBitsTo(_)
|
| ExprEnum::CastBitsTo(_)
|
||||||
|
| ExprEnum::TraceAsStringAsInner(_)
|
||||||
|
| ExprEnum::ToTraceAsString(_)
|
||||||
| ExprEnum::ModuleIO(_)
|
| ExprEnum::ModuleIO(_)
|
||||||
| ExprEnum::Instance(_)
|
| ExprEnum::Instance(_)
|
||||||
| ExprEnum::Wire(_)
|
| ExprEnum::Wire(_)
|
||||||
| ExprEnum::Reg(_)
|
| ExprEnum::Reg(_)
|
||||||
| ExprEnum::RegSync(_)
|
| ExprEnum::RegSync(_)
|
||||||
| ExprEnum::RegAsync(_) => op.default_fold(self),
|
| ExprEnum::RegAsync(_)
|
||||||
}
|
| ExprEnum::FormalInput(_)
|
||||||
|
| ExprEnum::SimIoForGlobal(_) => op.default_fold(self)?,
|
||||||
|
};
|
||||||
|
self.module_state_stack
|
||||||
|
.last_mut()
|
||||||
|
.expect("known to be in module")
|
||||||
|
.expr_cache
|
||||||
|
.insert(op, folded_op);
|
||||||
|
Ok(folded_op)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_block(&mut self, block: Block) -> Result<Block, Self::Error> {
|
fn fold_block(&mut self, block: Block) -> Result<Block, Self::Error> {
|
||||||
|
|
@ -936,7 +991,8 @@ impl Folder for State {
|
||||||
| CanonicalType::SyncReset(_)
|
| CanonicalType::SyncReset(_)
|
||||||
| CanonicalType::Reset(_)
|
| CanonicalType::Reset(_)
|
||||||
| CanonicalType::PhantomConst(_)
|
| CanonicalType::PhantomConst(_)
|
||||||
| CanonicalType::DynSimOnly(_) => canonical_type.default_fold(self),
|
| CanonicalType::DynSimOnly(_)
|
||||||
|
| CanonicalType::TraceAsString(_) => canonical_type.default_fold(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ impl MemSplit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn new(element_type: CanonicalType) -> Self {
|
fn new(element_type: CanonicalType) -> Self {
|
||||||
match element_type {
|
match element_type.unwrap_transparent_types() {
|
||||||
CanonicalType::Bundle(bundle_ty) => MemSplit::Bundle {
|
CanonicalType::Bundle(bundle_ty) => MemSplit::Bundle {
|
||||||
fields: bundle_ty
|
fields: bundle_ty
|
||||||
.fields()
|
.fields()
|
||||||
|
|
@ -195,6 +195,7 @@ impl MemSplit {
|
||||||
| CanonicalType::SyncReset(_)
|
| CanonicalType::SyncReset(_)
|
||||||
| CanonicalType::Reset(_) => unreachable!("memory element type is a storable type"),
|
| CanonicalType::Reset(_) => unreachable!("memory element type is a storable type"),
|
||||||
CanonicalType::DynSimOnly(_) => todo!("memory containing sim-only values"),
|
CanonicalType::DynSimOnly(_) => todo!("memory containing sim-only values"),
|
||||||
|
CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -306,7 +307,9 @@ impl SplitMemState<'_, '_> {
|
||||||
let outer_mem_name_path_len = self.mem_name_path.len();
|
let outer_mem_name_path_len = self.mem_name_path.len();
|
||||||
match self.split {
|
match self.split {
|
||||||
MemSplit::Bundle { fields } => {
|
MemSplit::Bundle { fields } => {
|
||||||
let CanonicalType::Bundle(bundle_type) = self.element_type else {
|
let CanonicalType::Bundle(bundle_type) =
|
||||||
|
self.element_type.unwrap_transparent_types()
|
||||||
|
else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
for ((field, field_offset), split) in bundle_type
|
for ((field, field_offset), split) in bundle_type
|
||||||
|
|
@ -321,7 +324,10 @@ impl SplitMemState<'_, '_> {
|
||||||
let field_ty_bit_width = field.ty.bit_width();
|
let field_ty_bit_width = field.ty.bit_width();
|
||||||
self.split_state_stack.push_map(
|
self.split_state_stack.push_map(
|
||||||
|e: Expr<CanonicalType>| {
|
|e: Expr<CanonicalType>| {
|
||||||
Expr::field(Expr::<Bundle>::from_canonical(e), &field.name)
|
Expr::field(
|
||||||
|
Expr::<Bundle>::from_canonical(Expr::unwrap_transparent_types(e)),
|
||||||
|
&field.name,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|initial_value_element| {
|
|initial_value_element| {
|
||||||
let Some(field_offset) = field_offset.only_bit_width() else {
|
let Some(field_offset) = field_offset.only_bit_width() else {
|
||||||
|
|
@ -377,8 +383,8 @@ impl SplitMemState<'_, '_> {
|
||||||
};
|
};
|
||||||
self.output_stmts.push(
|
self.output_stmts.push(
|
||||||
StmtConnect {
|
StmtConnect {
|
||||||
lhs: Expr::field(port_expr, name),
|
lhs: Expr::unwrap_transparent_types(Expr::field(port_expr, name)),
|
||||||
rhs: Expr::field(wire_expr, name),
|
rhs: Expr::unwrap_transparent_types(Expr::field(wire_expr, name)),
|
||||||
source_location: port.source_location(),
|
source_location: port.source_location(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
|
@ -389,7 +395,8 @@ impl SplitMemState<'_, '_> {
|
||||||
self.output_mems.push(new_mem);
|
self.output_mems.push(new_mem);
|
||||||
}
|
}
|
||||||
MemSplit::Array { elements } => {
|
MemSplit::Array { elements } => {
|
||||||
let CanonicalType::Array(array_type) = self.element_type else {
|
let CanonicalType::Array(array_type) = self.element_type.unwrap_transparent_types()
|
||||||
|
else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
let element_type = array_type.element();
|
let element_type = array_type.element();
|
||||||
|
|
@ -398,7 +405,7 @@ impl SplitMemState<'_, '_> {
|
||||||
self.mem_name_path.truncate(outer_mem_name_path_len);
|
self.mem_name_path.truncate(outer_mem_name_path_len);
|
||||||
write!(self.mem_name_path, "_{index}").unwrap();
|
write!(self.mem_name_path, "_{index}").unwrap();
|
||||||
self.split_state_stack.push_map(
|
self.split_state_stack.push_map(
|
||||||
|e| Expr::<Array>::from_canonical(e)[index],
|
|e| Expr::<Array>::from_canonical(Expr::unwrap_transparent_types(e))[index],
|
||||||
|initial_value_element| {
|
|initial_value_element| {
|
||||||
&initial_value_element[index * element_bit_width..][..element_bit_width]
|
&initial_value_element[index * element_bit_width..][..element_bit_width]
|
||||||
},
|
},
|
||||||
|
|
@ -464,7 +471,7 @@ impl ModuleState {
|
||||||
assert_eq!(memory_element_array_range_len % input_array_type.len(), 0);
|
assert_eq!(memory_element_array_range_len % input_array_type.len(), 0);
|
||||||
let chunk_size = memory_element_array_range_len / input_array_type.len();
|
let chunk_size = memory_element_array_range_len / input_array_type.len();
|
||||||
for index in 0..input_array_type.len() {
|
for index in 0..input_array_type.len() {
|
||||||
let map = |e| Expr::<Array>::from_canonical(e)[index];
|
let map = |e| Expr::<Array>::from_canonical(Expr::unwrap_transparent_types(e))[index];
|
||||||
let wire_rdata = wire_rdata.map(map);
|
let wire_rdata = wire_rdata.map(map);
|
||||||
let wire_wdata = wire_wdata.map(map);
|
let wire_wdata = wire_wdata.map(map);
|
||||||
let wire_wmask = wire_wmask.map(map);
|
let wire_wmask = wire_wmask.map(map);
|
||||||
|
|
@ -505,8 +512,8 @@ impl ModuleState {
|
||||||
port_read: Expr<CanonicalType>| {
|
port_read: Expr<CanonicalType>| {
|
||||||
output_stmts.push(
|
output_stmts.push(
|
||||||
StmtConnect {
|
StmtConnect {
|
||||||
lhs: wire_read,
|
lhs: Expr::unwrap_transparent_types(wire_read),
|
||||||
rhs: port_read,
|
rhs: Expr::unwrap_transparent_types(port_read),
|
||||||
source_location,
|
source_location,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
|
@ -517,8 +524,8 @@ impl ModuleState {
|
||||||
port_write: Expr<CanonicalType>| {
|
port_write: Expr<CanonicalType>| {
|
||||||
output_stmts.push(
|
output_stmts.push(
|
||||||
StmtConnect {
|
StmtConnect {
|
||||||
lhs: port_write,
|
lhs: Expr::unwrap_transparent_types(port_write),
|
||||||
rhs: wire_write,
|
rhs: Expr::unwrap_transparent_types(wire_write),
|
||||||
source_location,
|
source_location,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
|
@ -530,7 +537,8 @@ impl ModuleState {
|
||||||
connect_read(
|
connect_read(
|
||||||
output_stmts,
|
output_stmts,
|
||||||
wire_read,
|
wire_read,
|
||||||
Expr::<UInt>::from_canonical(port_read).cast_bits_to(wire_read.ty()),
|
Expr::<UInt>::from_canonical(Expr::unwrap_transparent_types(port_read))
|
||||||
|
.cast_bits_to(wire_read.ty()),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let connect_write_enum =
|
let connect_write_enum =
|
||||||
|
|
@ -544,7 +552,7 @@ impl ModuleState {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
match input_element_type {
|
match input_element_type.unwrap_transparent_types() {
|
||||||
CanonicalType::Bundle(_) => {
|
CanonicalType::Bundle(_) => {
|
||||||
unreachable!("bundle types are always split")
|
unreachable!("bundle types are always split")
|
||||||
}
|
}
|
||||||
|
|
@ -625,6 +633,9 @@ impl ModuleState {
|
||||||
| CanonicalType::SyncReset(_)
|
| CanonicalType::SyncReset(_)
|
||||||
| CanonicalType::Reset(_) => unreachable!("memory element type is a storable type"),
|
| CanonicalType::Reset(_) => unreachable!("memory element type is a storable type"),
|
||||||
CanonicalType::DynSimOnly(_) => todo!("memory containing sim-only values"),
|
CanonicalType::DynSimOnly(_) => todo!("memory containing sim-only values"),
|
||||||
|
CanonicalType::TraceAsString(_) => {
|
||||||
|
unreachable!("handled by unwrap_transparent_types")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,17 @@ use crate::{
|
||||||
Expr, ExprEnum, ValueType, ops,
|
Expr, ExprEnum, ValueType, ops,
|
||||||
target::{
|
target::{
|
||||||
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
|
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
|
||||||
TargetPathDynArrayElement, TargetPathElement,
|
TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString,
|
||||||
|
TargetPathTraceAsStringInner,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
formal::FormalKind,
|
formal::{FormalInput, FormalInputKind, FormalKind},
|
||||||
int::{Bool, SIntType, SIntValue, Size, UIntType, UIntValue},
|
int::{Bool, SIntType, SIntValue, Size, UIntType, UIntValue},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{Mem, MemPort, PortKind, PortName, PortType, ReadUnderWrite},
|
memory::{Mem, MemPort, PortKind, PortName, PortType, ReadUnderWrite},
|
||||||
module::{
|
module::{
|
||||||
AnnotatedModuleIO, Block, BlockId, ExternModuleBody, ExternModuleParameter,
|
AnnotatedModuleIO, Block, BlockId, ExternModuleBody, ExternModuleParameter,
|
||||||
ExternModuleParameterValue, Instance, Module, ModuleBody, ModuleIO, NameId,
|
ExternModuleParameterValue, Instance, Module, ModuleBody, ModuleIO, NameId, NameIdOrGlobal,
|
||||||
NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf,
|
NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf,
|
||||||
StmtInstance, StmtMatch, StmtReg, StmtWire,
|
StmtInstance, StmtMatch, StmtReg, StmtWire,
|
||||||
},
|
},
|
||||||
|
|
@ -32,7 +33,7 @@ use crate::{
|
||||||
reset::{AsyncReset, Reset, ResetType, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, SyncReset},
|
||||||
sim::{ExternModuleSimulation, value::DynSimOnly},
|
sim::{ExternModuleSimulation, value::DynSimOnly},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, TraceAsString, Type},
|
||||||
vendor::xilinx::{
|
vendor::xilinx::{
|
||||||
XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, XilinxAnnotation,
|
XdcCreateClockAnnotation, XdcIOStandardAnnotation, XdcLocationAnnotation, XilinxAnnotation,
|
||||||
},
|
},
|
||||||
|
|
@ -481,4 +482,30 @@ impl<T: ?Sized + Visit<State>, State: ?Sized + Visitor> Visit<State> for &'_ mut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<State: ?Sized + Visitor> Visit<State> for NameIdOrGlobal {
|
||||||
|
fn visit(&self, state: &mut State) -> Result<(), <State>::Error> {
|
||||||
|
state.visit_name_id_or_global(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_visit(&self, state: &mut State) -> Result<(), <State>::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Global => Ok(()),
|
||||||
|
Self::NameId(name_id) => name_id.visit(state),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<State: ?Sized + Folder> Fold<State> for NameIdOrGlobal {
|
||||||
|
fn fold(self, state: &mut State) -> Result<Self, <State>::Error> {
|
||||||
|
state.fold_name_id_or_global(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_fold(self, state: &mut State) -> Result<Self, <State>::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Global => Ok(Self::Global),
|
||||||
|
Self::NameId(name_id) => Ok(Self::NameId(name_id.fold(state)?)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/visit.rs"));
|
include!(concat!(env!("OUT_DIR"), "/visit.rs"));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ pub use crate::{
|
||||||
enum_::{Enum, HdlNone, HdlOption, HdlSome},
|
enum_::{Enum, HdlNone, HdlOption, HdlSome},
|
||||||
expr::{
|
expr::{
|
||||||
CastBitsTo, CastTo, CastToBits, Expr, HdlPartialEq, HdlPartialOrd, MakeUninitExpr,
|
CastBitsTo, CastTo, CastToBits, Expr, HdlPartialEq, HdlPartialOrd, MakeUninitExpr,
|
||||||
ReduceBits, ToExpr, ValueType, repeat,
|
ReduceBits, ToExpr, ToTraceAsString, ValueType, repeat,
|
||||||
},
|
},
|
||||||
formal::{
|
formal::{
|
||||||
MakeFormalExpr, all_const, all_seq, any_const, any_seq, formal_global_clock, formal_reset,
|
all_const, all_seq, any_const, any_seq, formal_global_clock, formal_reset, hdl_assert,
|
||||||
hdl_assert, hdl_assert_with_enable, hdl_assume, hdl_assume_with_enable, hdl_cover,
|
hdl_assert_with_enable, hdl_assume, hdl_assume_with_enable, hdl_cover,
|
||||||
hdl_cover_with_enable,
|
hdl_cover_with_enable,
|
||||||
},
|
},
|
||||||
hdl, hdl_module,
|
hdl, hdl_module,
|
||||||
|
|
@ -37,8 +37,8 @@ pub use crate::{
|
||||||
value::{SimOnly, SimOnlyValue, SimValue, ToSimValue, ToSimValueWithType},
|
value::{SimOnly, SimOnlyValue, SimValue, ToSimValue, ToSimValueWithType},
|
||||||
},
|
},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
testing::{FormalMode, assert_formal},
|
testing::{FormalMode, assert_formal, checked_vcd_output},
|
||||||
ty::{AsMask, CanonicalType, Type},
|
ty::{AsMask, CanonicalType, TraceAsString, Type},
|
||||||
util::{ConstUsize, GenericConstUsize},
|
util::{ConstUsize, GenericConstUsize},
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ impl<T: Type, R: ResetType> Reg<T, R> {
|
||||||
if let Some(init) = init {
|
if let Some(init) = init {
|
||||||
assert_eq!(ty, init.ty(), "register's type must match init type");
|
assert_eq!(ty, init.ty(), "register's type must match init type");
|
||||||
}
|
}
|
||||||
|
scoped_name.0.assert_is_name_id();
|
||||||
Self {
|
Self {
|
||||||
name: scoped_name,
|
name: scoped_name,
|
||||||
source_location,
|
source_location,
|
||||||
|
|
@ -94,7 +95,7 @@ impl<T: Type, R: ResetType> Reg<T, R> {
|
||||||
self.containing_module_name_id().0
|
self.containing_module_name_id().0
|
||||||
}
|
}
|
||||||
pub fn containing_module_name_id(&self) -> NameId {
|
pub fn containing_module_name_id(&self) -> NameId {
|
||||||
self.name.0
|
self.name.0.unwrap_name_id()
|
||||||
}
|
}
|
||||||
pub fn name(&self) -> Interned<str> {
|
pub fn name(&self) -> Interned<str> {
|
||||||
self.name_id().0
|
self.name_id().0
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -6,9 +6,9 @@ use crate::{
|
||||||
int::{BoolOrIntType, SInt, UInt},
|
int::{BoolOrIntType, SInt, UInt},
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
sim::interpreter::parts::{
|
sim::interpreter::parts::{
|
||||||
StateLayout, StatePartIndex, StatePartKind, StatePartKindBigSlots, StatePartKindMemories,
|
StateLayout, StatePartIndex, StatePartIndexRange, StatePartKind, StatePartKindBigSlots,
|
||||||
StatePartKindSimOnlySlots, StatePartKindSmallSlots, StatePartLen, TypeIndexRange,
|
StatePartKindMemories, StatePartKindSimOnlySlots, StatePartKindSmallSlots, StatePartLen,
|
||||||
TypeLayout, get_state_part_kinds,
|
TypeIndexRange, TypeLayout, get_state_part_kinds,
|
||||||
},
|
},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
util::{HashMap, HashSet},
|
util::{HashMap, HashSet},
|
||||||
|
|
@ -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,21 @@ 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_maybe_modified_flag(
|
||||||
|
&self,
|
||||||
|
part_index: StatePartIndex<K>,
|
||||||
|
) -> bool {
|
||||||
|
K::state_index_fetch_maybe_modified_flag(&self.value, part_index)
|
||||||
|
}
|
||||||
|
pub(crate) fn state_index_range_fetch_maybe_modified_flags(
|
||||||
|
&self,
|
||||||
|
part_index_range: StatePartIndexRange<K>,
|
||||||
|
) -> bool {
|
||||||
|
K::state_index_range_fetch_maybe_modified_flags(&self.value, part_index_range)
|
||||||
|
}
|
||||||
|
pub(crate) fn clear_all_maybe_modified_flags(&mut self) {
|
||||||
|
K::clear_all_maybe_modified_flags(&mut self.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
|
@ -922,56 +936,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -984,6 +980,7 @@ macro_rules! make_state {
|
||||||
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
||||||
pub(crate) pc: usize,
|
pub(crate) pc: usize,
|
||||||
pub(crate) memory_write_log: Vec<(StatePartIndex<StatePartKindMemories>, usize)>,
|
pub(crate) memory_write_log: Vec<(StatePartIndex<StatePartKindMemories>, usize)>,
|
||||||
|
pub(crate) assert_failed_log: Vec<usize>,
|
||||||
$(pub(crate) $state_plural_field: StatePart<$state_kind>,)*
|
$(pub(crate) $state_plural_field: StatePart<$state_kind>,)*
|
||||||
$(pub(crate) $type_plural_field: StatePart<$type_kind>,)*
|
$(pub(crate) $type_plural_field: StatePart<$type_kind>,)*
|
||||||
}
|
}
|
||||||
|
|
@ -994,6 +991,7 @@ macro_rules! make_state {
|
||||||
insns: _,
|
insns: _,
|
||||||
pc,
|
pc,
|
||||||
memory_write_log,
|
memory_write_log,
|
||||||
|
assert_failed_log,
|
||||||
$($state_plural_field,)*
|
$($state_plural_field,)*
|
||||||
$($type_plural_field,)*
|
$($type_plural_field,)*
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -1001,6 +999,7 @@ macro_rules! make_state {
|
||||||
.field("insns", &InsnsOfState(self))
|
.field("insns", &InsnsOfState(self))
|
||||||
.field("pc", pc)
|
.field("pc", pc)
|
||||||
.field("memory_write_log", memory_write_log)
|
.field("memory_write_log", memory_write_log)
|
||||||
|
.field("assert_failed_log", assert_failed_log)
|
||||||
$(.field(stringify!($state_plural_field), $state_plural_field))*
|
$(.field(stringify!($state_plural_field), $state_plural_field))*
|
||||||
$(.field(stringify!($type_plural_field), $type_plural_field))*
|
$(.field(stringify!($type_plural_field), $type_plural_field))*
|
||||||
.finish()
|
.finish()
|
||||||
|
|
@ -1013,6 +1012,7 @@ macro_rules! make_state {
|
||||||
insns,
|
insns,
|
||||||
pc: 0,
|
pc: 0,
|
||||||
memory_write_log: Vec::with_capacity(32),
|
memory_write_log: Vec::with_capacity(32),
|
||||||
|
assert_failed_log: Vec::new(),
|
||||||
$($state_plural_field: StatePart::new(&insns.state_layout.$state_plural_field.layout_data),)*
|
$($state_plural_field: StatePart::new(&insns.state_layout.$state_plural_field.layout_data),)*
|
||||||
$($type_plural_field: StatePart::new(&insns.state_layout.ty.$type_plural_field.layout_data),)*
|
$($type_plural_field: StatePart::new(&insns.state_layout.ty.$type_plural_field.layout_data),)*
|
||||||
}
|
}
|
||||||
|
|
@ -1024,10 +1024,20 @@ macro_rules! make_state {
|
||||||
pc: self.pc,
|
pc: self.pc,
|
||||||
orig_pc: &mut self.pc,
|
orig_pc: &mut self.pc,
|
||||||
memory_write_log: &mut self.memory_write_log,
|
memory_write_log: &mut self.memory_write_log,
|
||||||
|
assert_failed_log: &mut self.assert_failed_log,
|
||||||
$($state_plural_field: self.$state_plural_field.borrow(),)*
|
$($state_plural_field: self.$state_plural_field.borrow(),)*
|
||||||
$($type_plural_field: self.$type_plural_field.borrow(),)*
|
$($type_plural_field: self.$type_plural_field.borrow(),)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub(crate) fn type_index_range_fetch_maybe_modified_flags(&self, range: TypeIndexRange) -> bool {
|
||||||
|
$(self.$type_plural_field.state_index_range_fetch_maybe_modified_flags(
|
||||||
|
range.$type_plural_field,
|
||||||
|
))||*
|
||||||
|
}
|
||||||
|
pub(crate) fn clear_all_maybe_modified_flags(&mut self) {
|
||||||
|
$(self.$state_plural_field.clear_all_maybe_modified_flags();)*
|
||||||
|
$(self.$type_plural_field.clear_all_maybe_modified_flags();)*
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -1037,6 +1047,7 @@ macro_rules! make_state {
|
||||||
pub(crate) orig_pc: &'a mut usize,
|
pub(crate) orig_pc: &'a mut usize,
|
||||||
pub(crate) pc: usize,
|
pub(crate) pc: usize,
|
||||||
pub(crate) memory_write_log: &'a mut Vec<(StatePartIndex<StatePartKindMemories>, usize)>,
|
pub(crate) memory_write_log: &'a mut Vec<(StatePartIndex<StatePartKindMemories>, usize)>,
|
||||||
|
pub(crate) assert_failed_log: &'a mut Vec<usize>,
|
||||||
$(pub(crate) $state_plural_field: BorrowedStatePart<'a, $state_kind>,)*
|
$(pub(crate) $state_plural_field: BorrowedStatePart<'a, $state_kind>,)*
|
||||||
$(pub(crate) $type_plural_field: BorrowedStatePart<'a, $type_kind>,)*
|
$(pub(crate) $type_plural_field: BorrowedStatePart<'a, $type_kind>,)*
|
||||||
}
|
}
|
||||||
|
|
@ -1294,6 +1305,7 @@ impl State {
|
||||||
insns: _,
|
insns: _,
|
||||||
pc,
|
pc,
|
||||||
memory_write_log: _,
|
memory_write_log: _,
|
||||||
|
assert_failed_log: _,
|
||||||
memories: _,
|
memories: _,
|
||||||
small_slots: _,
|
small_slots: _,
|
||||||
big_slots: _,
|
big_slots: _,
|
||||||
|
|
@ -1333,6 +1345,10 @@ impl BorrowedState<'_> {
|
||||||
self.memory_write_log.push(log_entry);
|
self.memory_write_log.push(log_entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cold]
|
||||||
|
fn assert_failed(&mut self, assert_index: usize) {
|
||||||
|
self.assert_failed_log.push(assert_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bigint_pow2(width: usize) -> Interned<BigInt> {
|
fn bigint_pow2(width: usize) -> Interned<BigInt> {
|
||||||
|
|
@ -2100,6 +2116,19 @@ impl_insns! {
|
||||||
state.log_memory_write(memory, addr);
|
state.log_memory_write(memory, addr);
|
||||||
next!();
|
next!();
|
||||||
}
|
}
|
||||||
|
Assert {
|
||||||
|
#[kind = Input]
|
||||||
|
clk_triggered: StatePartIndex<StatePartKindSmallSlots>,
|
||||||
|
#[kind = Input]
|
||||||
|
pred: StatePartIndex<StatePartKindSmallSlots>,
|
||||||
|
#[kind = Immediate]
|
||||||
|
assert_index: usize,
|
||||||
|
} => {
|
||||||
|
if state.small_slots[clk_triggered] != 0 && state.small_slots[pred] == 0 {
|
||||||
|
state.assert_failed(assert_index);
|
||||||
|
}
|
||||||
|
next!();
|
||||||
|
}
|
||||||
Return => {
|
Return => {
|
||||||
break RunResult::Return(());
|
break RunResult::Return(());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,35 @@ 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_maybe_modified_flag(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index: StatePartIndex<Self>,
|
||||||
|
) -> bool;
|
||||||
|
fn state_index_range_fetch_maybe_modified_flags(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index_range: StatePartIndexRange<Self>,
|
||||||
|
) -> bool;
|
||||||
|
fn clear_all_maybe_modified_flags(state: &mut Self::State);
|
||||||
|
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 +302,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 +328,95 @@ 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_maybe_modified_flag(
|
||||||
|
_state: &Self::State,
|
||||||
|
_part_index: StatePartIndex<Self>,
|
||||||
|
) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn state_index_range_fetch_maybe_modified_flags(
|
||||||
|
_state: &Self::State,
|
||||||
|
part_index_range: StatePartIndexRange<Self>,
|
||||||
|
) -> bool {
|
||||||
|
part_index_range.len.value > 0
|
||||||
|
}
|
||||||
|
fn clear_all_maybe_modified_flags(_state: &mut Self::State) {}
|
||||||
|
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 +437,80 @@ 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_maybe_modified_flag(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index: StatePartIndex<Self>,
|
||||||
|
) -> bool {
|
||||||
|
state.modified[part_index.as_usize()]
|
||||||
|
}
|
||||||
|
fn state_index_range_fetch_maybe_modified_flags(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index_range: StatePartIndexRange<Self>,
|
||||||
|
) -> bool {
|
||||||
|
state.modified[part_index_range.start.as_usize()..]
|
||||||
|
[..part_index_range.len.as_index().as_usize()]
|
||||||
|
.contains(&true)
|
||||||
|
}
|
||||||
|
fn clear_all_maybe_modified_flags(state: &mut Self::State) {
|
||||||
|
state.modified.fill(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 +529,80 @@ 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_maybe_modified_flag(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index: StatePartIndex<Self>,
|
||||||
|
) -> bool {
|
||||||
|
state.modified[part_index.as_usize()]
|
||||||
|
}
|
||||||
|
fn state_index_range_fetch_maybe_modified_flags(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index_range: StatePartIndexRange<Self>,
|
||||||
|
) -> bool {
|
||||||
|
state.modified[part_index_range.start.as_usize()..]
|
||||||
|
[..part_index_range.len.as_index().as_usize()]
|
||||||
|
.contains(&true)
|
||||||
|
}
|
||||||
|
fn clear_all_maybe_modified_flags(state: &mut Self::State) {
|
||||||
|
state.modified.fill(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 +621,61 @@ 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_maybe_modified_flag(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index: StatePartIndex<Self>,
|
||||||
|
) -> bool {
|
||||||
|
state.modified[part_index.as_usize()]
|
||||||
|
}
|
||||||
|
fn state_index_range_fetch_maybe_modified_flags(
|
||||||
|
state: &Self::State,
|
||||||
|
part_index_range: StatePartIndexRange<Self>,
|
||||||
|
) -> bool {
|
||||||
|
state.modified[part_index_range.start.as_usize()..]
|
||||||
|
[..part_index_range.len.as_index().as_usize()]
|
||||||
|
.contains(&true)
|
||||||
|
}
|
||||||
|
fn clear_all_maybe_modified_flags(state: &mut Self::State) {
|
||||||
|
state.modified.fill(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)]
|
||||||
|
|
|
||||||
|
|
@ -15,23 +15,23 @@ 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,
|
||||||
alternating_cell::{AlternatingCell, AlternatingCellMethods},
|
alternating_cell::{AlternatingCell, AlternatingCellMethods},
|
||||||
|
serde_by_id::{SerdeById, SerdeByIdProperties, SerdeByIdTable, SerdeByIdTrait},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bitvec::{slice::BitSlice, vec::BitVec};
|
use bitvec::{slice::BitSlice, vec::BitVec};
|
||||||
use hashbrown::hash_map::Entry;
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _, ser::Error as _};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _, ser::Error as _};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::{Borrow, BorrowMut, Cow},
|
borrow::{Borrow, BorrowMut, Cow},
|
||||||
fmt::{self, Write},
|
fmt,
|
||||||
hash::{BuildHasher, Hash, Hasher, RandomState},
|
|
||||||
num::NonZero,
|
num::NonZero,
|
||||||
ops::{Deref, DerefMut, Index, IndexMut},
|
ops::{Deref, DerefMut, Index, IndexMut},
|
||||||
sync::{Arc, Mutex},
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod sim_only_value_unsafe;
|
pub(crate) mod sim_only_value_unsafe;
|
||||||
|
|
@ -551,113 +551,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 {
|
||||||
|
self.0.take().expect("known to be Some")
|
||||||
}
|
}
|
||||||
|
#[inline(always)]
|
||||||
#[doc(hidden)]
|
pub fn __fayalite_match_sim_value(&mut self) -> T {
|
||||||
pub trait MatchSimValue {
|
self.take()
|
||||||
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"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Type> MatchSimValue for MatchSimValueHelper<&'a SimValue<T>> {
|
|
||||||
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 {
|
||||||
|
|
@ -1091,7 +1097,8 @@ impl ToSimValueWithType<CanonicalType> for bool {
|
||||||
| CanonicalType::Enum(_)
|
| CanonicalType::Enum(_)
|
||||||
| CanonicalType::Bundle(_)
|
| CanonicalType::Bundle(_)
|
||||||
| CanonicalType::PhantomConst(_)
|
| CanonicalType::PhantomConst(_)
|
||||||
| CanonicalType::DynSimOnly(_) => {
|
| CanonicalType::DynSimOnly(_)
|
||||||
|
| CanonicalType::TraceAsString(_) => {
|
||||||
panic!("can't create SimValue from bool: expected value of type: {ty:?}");
|
panic!("can't create SimValue from bool: expected value of type: {ty:?}");
|
||||||
}
|
}
|
||||||
CanonicalType::Bool(_)
|
CanonicalType::Bool(_)
|
||||||
|
|
@ -1220,80 +1227,17 @@ macro_rules! impl_to_sim_value_for_int_value {
|
||||||
impl_to_sim_value_for_int_value!(UIntValue, UInt, UIntType);
|
impl_to_sim_value_for_int_value!(UIntValue, UInt, UIntType);
|
||||||
impl_to_sim_value_for_int_value!(SIntValue, SInt, SIntType);
|
impl_to_sim_value_for_int_value!(SIntValue, SInt, SIntType);
|
||||||
|
|
||||||
#[derive(Default)]
|
impl SerdeByIdTrait for DynSimOnly {
|
||||||
struct DynSimOnlySerdeTableRest {
|
fn serde_by_id_properties(&self) -> SerdeByIdProperties<Self> {
|
||||||
from_serde: HashMap<DynSimOnlySerdeId, DynSimOnly>,
|
self.serde_by_id_properties_inner()
|
||||||
serde_id_random_state: RandomState,
|
|
||||||
buffer: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DynSimOnlySerdeTableRest {
|
fn static_table() -> &'static SerdeByIdTable<Self> {
|
||||||
#[cold]
|
static TABLE: SerdeByIdTable<DynSimOnly> = SerdeByIdTable::new();
|
||||||
fn add_new(&mut self, ty: DynSimOnly) -> DynSimOnlySerdeId {
|
&TABLE
|
||||||
let mut try_number = 0u64;
|
|
||||||
let mut hasher = self.serde_id_random_state.build_hasher();
|
|
||||||
// extract more bits of randomness from TypeId -- its Hash impl only hashes 64-bits
|
|
||||||
write!(self.buffer, "{:?}", ty.type_id()).expect("shouldn't ever fail");
|
|
||||||
self.buffer.hash(&mut hasher);
|
|
||||||
loop {
|
|
||||||
let mut hasher = hasher.clone();
|
|
||||||
try_number.hash(&mut hasher);
|
|
||||||
try_number += 1;
|
|
||||||
let retval = DynSimOnlySerdeId(std::array::from_fn(|i| {
|
|
||||||
let mut hasher = hasher.clone();
|
|
||||||
i.hash(&mut hasher);
|
|
||||||
hasher.finish() as u32
|
|
||||||
}));
|
|
||||||
match self.from_serde.entry(retval) {
|
|
||||||
Entry::Occupied(_) => continue,
|
|
||||||
Entry::Vacant(e) => {
|
|
||||||
e.insert(ty);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
const NAME: &'static str = "DynSimOnly";
|
||||||
struct DynSimOnlySerdeTable {
|
|
||||||
to_serde: HashMap<DynSimOnly, DynSimOnlySerdeId>,
|
|
||||||
rest: DynSimOnlySerdeTableRest,
|
|
||||||
}
|
|
||||||
|
|
||||||
static DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE: Mutex<Option<DynSimOnlySerdeTable>> = Mutex::new(None);
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
|
|
||||||
#[serde(transparent)]
|
|
||||||
struct DynSimOnlySerdeId([u32; 4]);
|
|
||||||
|
|
||||||
impl From<DynSimOnly> for DynSimOnlySerdeId {
|
|
||||||
fn from(ty: DynSimOnly) -> Self {
|
|
||||||
let mut locked = DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE
|
|
||||||
.lock()
|
|
||||||
.expect("shouldn't be poison");
|
|
||||||
let DynSimOnlySerdeTable { to_serde, rest } = locked.get_or_insert_default();
|
|
||||||
match to_serde.entry(ty) {
|
|
||||||
Entry::Occupied(occupied_entry) => *occupied_entry.get(),
|
|
||||||
Entry::Vacant(vacant_entry) => *vacant_entry.insert(rest.add_new(ty)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DynSimOnlySerdeId {
|
|
||||||
fn ty(self) -> Option<DynSimOnly> {
|
|
||||||
let locked = DYN_SIM_ONLY_VALUE_TYPE_SERDE_TABLE
|
|
||||||
.lock()
|
|
||||||
.expect("shouldn't be poison");
|
|
||||||
Some(*locked.as_ref()?.rest.from_serde.get(&self)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
|
|
||||||
struct DynSimOnlySerde<'a> {
|
|
||||||
random_id: DynSimOnlySerdeId,
|
|
||||||
#[serde(borrow)]
|
|
||||||
type_name: Cow<'a, str>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for DynSimOnly {
|
impl Serialize for DynSimOnly {
|
||||||
|
|
@ -1301,11 +1245,7 @@ impl Serialize for DynSimOnly {
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
DynSimOnlySerde {
|
SerdeById { inner: *self }.serialize(serializer)
|
||||||
random_id: (*self).into(),
|
|
||||||
type_name: Cow::Borrowed(self.type_name()),
|
|
||||||
}
|
|
||||||
.serialize(serializer)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1314,16 +1254,7 @@ impl<'de> Deserialize<'de> for DynSimOnly {
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let deserialized = DynSimOnlySerde::deserialize(deserializer)?;
|
Ok(SerdeById::deserialize(deserializer)?.inner)
|
||||||
let retval = deserialized
|
|
||||||
.random_id
|
|
||||||
.ty()
|
|
||||||
.filter(|ty| ty.type_name() == deserialized.type_name);
|
|
||||||
retval.ok_or_else(|| {
|
|
||||||
D::Error::custom(
|
|
||||||
"doesn't match any DynSimOnly that was serialized this time this program was run",
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1394,6 +1325,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 +1399,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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
|
|
||||||
//! `unsafe` parts of [`DynSimOnlyValue`]
|
//! `unsafe` parts of [`DynSimOnlyValue`]
|
||||||
|
|
||||||
use crate::expr::{ValueType, value_category::ValueCategoryValue};
|
use crate::{
|
||||||
|
expr::{ValueType, value_category::ValueCategoryValue},
|
||||||
|
util::serde_by_id::SerdeByIdProperties,
|
||||||
|
};
|
||||||
use serde::{Serialize, de::DeserializeOwned};
|
use serde::{Serialize, de::DeserializeOwned};
|
||||||
use std::{
|
use std::{
|
||||||
any::{self, TypeId},
|
any::{self, TypeId},
|
||||||
|
|
@ -33,6 +36,7 @@ unsafe trait DynSimOnlyTrait: 'static + Send + Sync {
|
||||||
&self,
|
&self,
|
||||||
json_str: &str,
|
json_str: &str,
|
||||||
) -> serde_json::Result<Rc<dyn DynSimOnlyValueTrait>>;
|
) -> serde_json::Result<Rc<dyn DynSimOnlyValueTrait>>;
|
||||||
|
fn serde_by_id_properties_inner(&self) -> SerdeByIdProperties<DynSimOnly>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Safety: `type_id_dyn` is implemented correctly
|
/// Safety: `type_id_dyn` is implemented correctly
|
||||||
|
|
@ -55,6 +59,9 @@ unsafe impl<T: SimOnlyValueTrait> DynSimOnlyTrait for SimOnly<T> {
|
||||||
) -> serde_json::Result<Rc<dyn DynSimOnlyValueTrait>> {
|
) -> serde_json::Result<Rc<dyn DynSimOnlyValueTrait>> {
|
||||||
Ok(Rc::<T>::new(serde_json::from_str(json_str)?))
|
Ok(Rc::<T>::new(serde_json::from_str(json_str)?))
|
||||||
}
|
}
|
||||||
|
fn serde_by_id_properties_inner(&self) -> SerdeByIdProperties<DynSimOnly> {
|
||||||
|
SerdeByIdProperties::of::<T>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Safety:
|
/// Safety:
|
||||||
|
|
@ -151,6 +158,9 @@ impl DynSimOnly {
|
||||||
pub fn default_value(self) -> DynSimOnlyValue {
|
pub fn default_value(self) -> DynSimOnlyValue {
|
||||||
DynSimOnlyValue(self.ty.default_value())
|
DynSimOnlyValue(self.ty.default_value())
|
||||||
}
|
}
|
||||||
|
pub(super) fn serde_by_id_properties_inner(self) -> SerdeByIdProperties<Self> {
|
||||||
|
self.ty.serde_by_id_properties_inner()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for DynSimOnly {
|
impl PartialEq for DynSimOnly {
|
||||||
|
|
|
||||||
|
|
@ -9,26 +9,44 @@ use crate::{
|
||||||
prelude::PhantomConst,
|
prelude::PhantomConst,
|
||||||
sim::{
|
sim::{
|
||||||
TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl,
|
TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl,
|
||||||
TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance,
|
TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceFormalInput,
|
||||||
TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule,
|
TraceInstance, TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation,
|
||||||
TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, TraceScalar, TraceScalarId,
|
TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt, TraceScalar,
|
||||||
TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire, TraceWriter,
|
TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceTraceAsString, TraceUInt,
|
||||||
TraceWriterDecls,
|
TraceWire, TraceWriter, TraceWriterDecls,
|
||||||
time::{SimDuration, SimInstant},
|
time::{SimDuration, SimInstant},
|
||||||
value::DynSimOnlyValue,
|
value::DynSimOnlyValue,
|
||||||
},
|
},
|
||||||
|
ty::{OpaqueSimValueSlice, TraceAsString},
|
||||||
util::HashMap,
|
util::HashMap,
|
||||||
};
|
};
|
||||||
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 +79,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 +188,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 +216,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 +259,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 +267,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 +291,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 +301,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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -287,23 +332,83 @@ impl WriteTrace for TraceScalar {
|
||||||
Self::AsyncReset(v) => v.write_trace(writer, arg),
|
Self::AsyncReset(v) => v.write_trace(writer, arg),
|
||||||
Self::PhantomConst(v) => v.write_trace(writer, arg),
|
Self::PhantomConst(v) => v.write_trace(writer, arg),
|
||||||
Self::SimOnly(v) => v.write_trace(writer, arg),
|
Self::SimOnly(v) => v.write_trace(writer, arg),
|
||||||
|
Self::TraceAsString(v) => v.write_trace(writer, arg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
|
impl VcdId {
|
||||||
|
const CHAR_RANGE: std::ops::RangeInclusive<u8> = b'!'..=b'~';
|
||||||
|
const BASE: u8 = *Self::CHAR_RANGE.end() - *Self::CHAR_RANGE.start() + 1;
|
||||||
|
const LOW_HALF_CHARS: u32 = 5;
|
||||||
|
const LOW_HALF_MODULUS: u64 = (Self::BASE as u64).pow(Self::LOW_HALF_CHARS);
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
const fn write(self, out: &mut [u8]) -> usize {
|
||||||
|
let mut id = self.0.get();
|
||||||
|
let mut len = 0;
|
||||||
loop {
|
loop {
|
||||||
let digit = (id % base) as u8 + min_char;
|
let digit = (id % Self::BASE as u64) as u8 + *Self::CHAR_RANGE.start();
|
||||||
id /= base;
|
id /= Self::BASE as u64;
|
||||||
writer.write_all(&[digit])?;
|
if len < out.len() {
|
||||||
|
out[len] = digit;
|
||||||
|
}
|
||||||
|
len += 1;
|
||||||
if id == 0 {
|
if id == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
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 +451,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 +490,21 @@ fn write_vcd_var<W: io::Write>(
|
||||||
first_id + *element_index
|
first_id + *element_index
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if let Some(scope) = scope {
|
||||||
|
let path_hash = scope.path_hash.clone().joined(name);
|
||||||
|
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!(writer, "$var {var_type} {size} ")?;
|
||||||
write_vcd_id(writer, id)?;
|
write_vcd_id(writer, id)?;
|
||||||
writeln!(writer, " {name} $end")
|
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 +532,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 +613,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 +689,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 +717,41 @@ 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteTrace for TraceTraceAsString {
|
||||||
|
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||||
|
let ArgInType {
|
||||||
|
source_var_type: _,
|
||||||
|
sink_var_type: _,
|
||||||
|
duplex_var_type: _,
|
||||||
|
properties,
|
||||||
|
scope,
|
||||||
|
} = arg.in_type();
|
||||||
|
let Self {
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
flow: _,
|
||||||
|
} = self;
|
||||||
|
write_vcd_var(
|
||||||
|
properties,
|
||||||
|
scope,
|
||||||
|
MemoryElementPartBody::TraceAsString { ty },
|
||||||
|
writer,
|
||||||
|
"string",
|
||||||
|
1,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -616,6 +766,7 @@ impl WriteTrace for TraceScope {
|
||||||
Self::Wire(v) => v.write_trace(writer, arg),
|
Self::Wire(v) => v.write_trace(writer, arg),
|
||||||
Self::Reg(v) => v.write_trace(writer, arg),
|
Self::Reg(v) => v.write_trace(writer, arg),
|
||||||
Self::ModuleIO(v) => v.write_trace(writer, arg),
|
Self::ModuleIO(v) => v.write_trace(writer, arg),
|
||||||
|
Self::FormalInput(v) => v.write_trace(writer, arg),
|
||||||
Self::Bundle(v) => v.write_trace(writer, arg),
|
Self::Bundle(v) => v.write_trace(writer, arg),
|
||||||
Self::Array(v) => v.write_trace(writer, arg),
|
Self::Array(v) => v.write_trace(writer, arg),
|
||||||
Self::EnumWithFields(v) => v.write_trace(writer, arg),
|
Self::EnumWithFields(v) => v.write_trace(writer, arg),
|
||||||
|
|
@ -625,14 +776,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(
|
||||||
|
writer,
|
||||||
|
"module",
|
||||||
|
instance_name.unwrap_or(name),
|
||||||
|
scope,
|
||||||
|
|writer, scope| {
|
||||||
for child in children {
|
for child in children {
|
||||||
child.write_trace(writer, ArgModuleBody { properties, scope })?;
|
child.write_trace(writer, ArgModuleBody { properties, scope })?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -640,7 +801,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 +813,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 +862,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 +894,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 +915,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 +936,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 +958,28 @@ 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),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteTrace for TraceFormalInput {
|
||||||
|
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 Self {
|
||||||
|
name: _,
|
||||||
|
child,
|
||||||
|
formal_input: _,
|
||||||
|
} = self;
|
||||||
|
child.write_trace(
|
||||||
|
writer,
|
||||||
|
ArgInType {
|
||||||
|
source_var_type: "wire",
|
||||||
|
sink_var_type: "wire",
|
||||||
|
duplex_var_type: "wire",
|
||||||
|
properties,
|
||||||
|
scope: Some(scope),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -811,7 +1000,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 +1009,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 +1033,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 +1042,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 +1067,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 +1075,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 +1086,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 +1112,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 +1127,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 {
|
||||||
|
|
@ -945,6 +1145,7 @@ impl<W: io::Write> TraceWriterDecls for VcdWriterDecls<W> {
|
||||||
finished_init: false,
|
finished_init: false,
|
||||||
timescale,
|
timescale,
|
||||||
properties,
|
properties,
|
||||||
|
trace_as_string_buf: String::with_capacity(256),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -952,6 +1153,7 @@ impl<W: io::Write> TraceWriterDecls for VcdWriterDecls<W> {
|
||||||
enum MemoryElementPartBody {
|
enum MemoryElementPartBody {
|
||||||
Scalar,
|
Scalar,
|
||||||
EnumDiscriminant { ty: Enum },
|
EnumDiscriminant { ty: Enum },
|
||||||
|
TraceAsString { ty: TraceAsString },
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MemoryElementPart {
|
struct MemoryElementPart {
|
||||||
|
|
@ -967,8 +1169,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]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -977,6 +1271,7 @@ pub struct VcdWriter<W: io::Write + 'static> {
|
||||||
finished_init: bool,
|
finished_init: bool,
|
||||||
timescale: SimDuration,
|
timescale: SimDuration,
|
||||||
properties: VcdWriterProperties,
|
properties: VcdWriterProperties,
|
||||||
|
trace_as_string_buf: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: io::Write + 'static> VcdWriter<W> {
|
impl<W: io::Write + 'static> VcdWriter<W> {
|
||||||
|
|
@ -988,8 +1283,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 +1296,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 +1329,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 +1364,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,20 +1376,49 @@ 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),
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
|
MemoryElementPartBody::TraceAsString { ty } => {
|
||||||
|
self.trace_as_string_buf.clear();
|
||||||
|
ty.trace_fmt_append_to_string(
|
||||||
|
&mut self.trace_as_string_buf,
|
||||||
|
OpaqueSimValueSlice::from_bitslice(&element_data[start..start + len]),
|
||||||
|
);
|
||||||
|
write_string_value_change(
|
||||||
|
&mut self.writer,
|
||||||
|
&self.trace_as_string_buf,
|
||||||
|
self.properties
|
||||||
|
.scalar_id_to_vcd_id_map
|
||||||
|
.built_scalar_id_to_vcd_id(first_id + element_index),
|
||||||
|
)?;
|
||||||
|
self.trace_as_string_buf.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +1450,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 +1467,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 +1481,23 @@ 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()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_signal_string(&mut self, id: TraceScalarId, value: &str) -> Result<(), Self::Error> {
|
||||||
|
write_string_value_change(
|
||||||
|
&mut self.writer,
|
||||||
|
value,
|
||||||
|
self.properties
|
||||||
|
.scalar_id_to_vcd_id_map
|
||||||
|
.built_scalar_id_to_vcd_id(id.as_usize()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1147,6 +1508,7 @@ impl<W: io::Write> fmt::Debug for VcdWriter<W> {
|
||||||
finished_init,
|
finished_init,
|
||||||
timescale,
|
timescale,
|
||||||
properties: _,
|
properties: _,
|
||||||
|
trace_as_string_buf: _,
|
||||||
} = self;
|
} = self;
|
||||||
f.debug_struct("VcdWriter")
|
f.debug_struct("VcdWriter")
|
||||||
.field("finished_init", finished_init)
|
.field("finished_init", finished_init)
|
||||||
|
|
@ -1161,7 +1523,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,
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,13 @@ use crate::{
|
||||||
bundle::BundleType,
|
bundle::BundleType,
|
||||||
firrtl::ExportOptions,
|
firrtl::ExportOptions,
|
||||||
module::Module,
|
module::Module,
|
||||||
util::HashMap,
|
sim::{Simulation, vcd::VcdWriterDecls},
|
||||||
|
util::{HashMap, RcWriter},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Write},
|
fmt::{self, Write},
|
||||||
|
panic::Location,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::Command,
|
process::Command,
|
||||||
sync::{Mutex, OnceLock},
|
sync::{Mutex, OnceLock},
|
||||||
|
|
@ -222,3 +224,190 @@ pub fn assert_formal<M: AsRef<Module<T>>, T: BundleType>(
|
||||||
)
|
)
|
||||||
.expect("testing::assert_formal() failed");
|
.expect("testing::assert_formal() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CheckedVcdOutput {
|
||||||
|
writer: Option<RcWriter>,
|
||||||
|
expected_path: PathBuf,
|
||||||
|
expected_contents: Result<String, (Option<PathBuf>, std::io::Error)>,
|
||||||
|
location: &'static Location<'static>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CheckedVcdOutput {
|
||||||
|
#[must_use]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn new<T: BundleType>(sim: &mut Simulation<T>, expected_path: PathBuf) -> Self {
|
||||||
|
let writer = RcWriter::default();
|
||||||
|
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||||
|
Self {
|
||||||
|
writer: Some(writer),
|
||||||
|
expected_contents: std::fs::read_to_string(&expected_path).map_err(|e| {
|
||||||
|
eprintln!(
|
||||||
|
"error: failed to read expected VCD from: {}",
|
||||||
|
expected_path.display(),
|
||||||
|
);
|
||||||
|
(std::env::current_dir().ok(), e)
|
||||||
|
}),
|
||||||
|
expected_path,
|
||||||
|
location: Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
#[track_caller]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn __checked_vcd_output_macro_helper<T: BundleType>(
|
||||||
|
sim: &mut Simulation<T>,
|
||||||
|
cargo_manifest_dir: &'static str,
|
||||||
|
path: &'static str,
|
||||||
|
) -> Self {
|
||||||
|
Self::new(sim, Path::new(cargo_manifest_dir).join(path))
|
||||||
|
}
|
||||||
|
pub fn with_vcd_output<R>(&self, f: impl FnOnce(&str) -> R) -> R {
|
||||||
|
let Some(writer) = &self.writer else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
writer.clone().borrow(|output| {
|
||||||
|
let Ok(output) = str::from_utf8(output) else {
|
||||||
|
unreachable!("VcdWriter writes valid UTF-8");
|
||||||
|
};
|
||||||
|
f(output)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn finish(mut self) {
|
||||||
|
let Ok(()) = self.finish_impl(|msg| panic!("{msg}"));
|
||||||
|
}
|
||||||
|
fn finish_impl<E>(
|
||||||
|
&mut self,
|
||||||
|
error: impl FnOnce(std::fmt::Arguments<'_>) -> E,
|
||||||
|
) -> Result<(), E> {
|
||||||
|
let Self {
|
||||||
|
writer: Some(writer),
|
||||||
|
expected_path,
|
||||||
|
expected_contents,
|
||||||
|
location,
|
||||||
|
} = self
|
||||||
|
else {
|
||||||
|
// already finished
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let Ok(vcd) = String::from_utf8(writer.take()) else {
|
||||||
|
unreachable!("VcdWriter writes valid UTF-8");
|
||||||
|
};
|
||||||
|
let expected_path_d = expected_path.display();
|
||||||
|
if expected_contents
|
||||||
|
.as_ref()
|
||||||
|
.is_ok_and(|expected_contents| *expected_contents == vcd)
|
||||||
|
{
|
||||||
|
// avoid written output from being split from threads interleaving writes to stdout
|
||||||
|
let _stdout = std::io::stderr().lock();
|
||||||
|
// use println to get output captured by tests
|
||||||
|
println!("\n{location}: generated VCD matches the expected VCD in {expected_path_d}");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// avoid written output from being split from threads interleaving writes to stderr
|
||||||
|
let _stderr = std::io::stderr().lock();
|
||||||
|
let error = |msg: std::fmt::Arguments<'_>| {
|
||||||
|
// print msg at both beginning and end so it's easier to find when the vcd is huge
|
||||||
|
Err(error(format_args!(
|
||||||
|
"\n{msg}####### VCD:\n{vcd}\n#######\n{msg}"
|
||||||
|
)))
|
||||||
|
};
|
||||||
|
let error = |msg: std::fmt::Arguments<'_>| match &*expected_contents {
|
||||||
|
Ok(_) => error(format_args!(
|
||||||
|
"{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\
|
||||||
|
{msg}",
|
||||||
|
)),
|
||||||
|
Err((Some(current_dir), e)) => error(format_args!(
|
||||||
|
"{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\
|
||||||
|
error: failed to read: {e}\n\
|
||||||
|
current dir: {current_dir}\n\
|
||||||
|
{msg}",
|
||||||
|
current_dir = current_dir.display(),
|
||||||
|
)),
|
||||||
|
Err((None, e)) => error(format_args!(
|
||||||
|
"{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\
|
||||||
|
error: failed to read: {e}\n\
|
||||||
|
{msg}",
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
const OVERWRITE_VAR_NAME: &str = "OVERWRITE_EXPECTED_VCD";
|
||||||
|
const OVERWRITE_VAR_VALUE: &str = "overwrite";
|
||||||
|
match std::env::var_os(OVERWRITE_VAR_NAME) {
|
||||||
|
Some(v) if v == OVERWRITE_VAR_VALUE => match std::fs::write(&expected_path, &vcd) {
|
||||||
|
Ok(()) => error(format_args!(
|
||||||
|
"warning: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- writing the generated VCD to {expected_path_d}\n"
|
||||||
|
)),
|
||||||
|
Err(e) => error(format_args!(
|
||||||
|
"error: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- tried to write the generated VCD to {expected_path_d}\n\
|
||||||
|
error: failed to write: {e}"
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
_ => error(format_args!(
|
||||||
|
"note: rerun the test with the environment variable `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}`\n\
|
||||||
|
to update the expected output to match the generated output.\n"
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for CheckedVcdOutput {
|
||||||
|
#[track_caller]
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let _ = self.finish_impl(|msg| {
|
||||||
|
if std::thread::panicking() {
|
||||||
|
eprintln!("{msg}"); // use eprintln to get output captured by tests
|
||||||
|
} else {
|
||||||
|
panic!("{msg}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
/// Use in tests to check that [`Simulation`] generates the expected VCD traces, by comparing to a `.vcd` file containing the expected traces.
|
||||||
|
///
|
||||||
|
/// Use like so:
|
||||||
|
/// ```
|
||||||
|
/// # use fayalite::prelude::*;
|
||||||
|
/// #
|
||||||
|
/// # #[hdl_module]
|
||||||
|
/// # fn my_module() {
|
||||||
|
/// # #[hdl]
|
||||||
|
/// # let a: UInt<8> = m.input();
|
||||||
|
/// # #[hdl]
|
||||||
|
/// # let b: UInt<8> = m.output();
|
||||||
|
/// # connect(b, 0u8);
|
||||||
|
/// # #[hdl]
|
||||||
|
/// # if a.cmp_eq(100u8) {
|
||||||
|
/// # connect(b, 42u8);
|
||||||
|
/// # }
|
||||||
|
/// # }
|
||||||
|
/// // inside your #[test] fn my_test():
|
||||||
|
///
|
||||||
|
/// // get the module to simulate:
|
||||||
|
/// let m = my_module();
|
||||||
|
/// // create a simulation of the module:
|
||||||
|
/// let mut sim = Simulation::new(m);
|
||||||
|
/// // set up the expected VCD traces, the given .vcd path is relative to env!("CARGO_MANIFEST_DIR")
|
||||||
|
/// let _checked_vcd_output = checked_vcd_output!(
|
||||||
|
/// &mut sim,
|
||||||
|
/// "tests/expected/my_test.vcd",
|
||||||
|
/// );
|
||||||
|
/// // now run the simulation like normal:
|
||||||
|
/// sim.write(sim.io().a, 0u8);
|
||||||
|
/// assert_eq!(sim.read(sim.io().b).as_int(), 0);
|
||||||
|
/// sim.advance_time(SimDuration::from_micros(1));
|
||||||
|
/// sim.write(sim.io().a, 100u8);
|
||||||
|
/// assert_eq!(sim.read(sim.io().b).as_int(), 42);
|
||||||
|
/// ```
|
||||||
|
macro_rules! checked_vcd_output {
|
||||||
|
($sim:expr, $path_relative_to_manifest_dir:expr $(,)?) => {
|
||||||
|
$crate::testing::CheckedVcdOutput::__checked_vcd_output_macro_helper(
|
||||||
|
$sim,
|
||||||
|
$crate::__std::env!("CARGO_MANIFEST_DIR"),
|
||||||
|
$crate::__std::concat!($path_relative_to_manifest_dir),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use checked_vcd_output;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -12,7 +12,8 @@ use crate::{
|
||||||
prelude::PhantomConst,
|
prelude::PhantomConst,
|
||||||
reset::{AsyncReset, Reset, SyncReset},
|
reset::{AsyncReset, Reset, SyncReset},
|
||||||
sim::value::DynSimOnly,
|
sim::value::DynSimOnly,
|
||||||
ty::{BaseType, CanonicalType},
|
ty::{BaseType, CanonicalType, TraceAsString, TraceAsStringTrait},
|
||||||
|
util::serde_by_id::SerdeById,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
|
@ -38,6 +39,7 @@ impl<'de, T: ?Sized + PhantomConstValue> Deserialize<'de> for SerdePhantomConst<
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(rename = "CanonicalType")]
|
#[serde(rename = "CanonicalType")]
|
||||||
|
#[expect(private_interfaces)]
|
||||||
pub(crate) enum SerdeCanonicalType<
|
pub(crate) enum SerdeCanonicalType<
|
||||||
ArrayElement = CanonicalType,
|
ArrayElement = CanonicalType,
|
||||||
ThePhantomConst = SerdePhantomConst<Interned<PhantomConstCanonicalValue>>,
|
ThePhantomConst = SerdePhantomConst<Interned<PhantomConstCanonicalValue>>,
|
||||||
|
|
@ -65,6 +67,10 @@ pub(crate) enum SerdeCanonicalType<
|
||||||
Clock,
|
Clock,
|
||||||
PhantomConst(ThePhantomConst),
|
PhantomConst(ThePhantomConst),
|
||||||
DynSimOnly(DynSimOnly),
|
DynSimOnly(DynSimOnly),
|
||||||
|
TraceAsString {
|
||||||
|
inner_ty: Interned<CanonicalType>,
|
||||||
|
trace_as_string: SerdeById<Interned<dyn TraceAsStringTrait>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ArrayElement, PhantomConstInner> SerdeCanonicalType<ArrayElement, PhantomConstInner> {
|
impl<ArrayElement, PhantomConstInner> SerdeCanonicalType<ArrayElement, PhantomConstInner> {
|
||||||
|
|
@ -82,6 +88,7 @@ impl<ArrayElement, PhantomConstInner> SerdeCanonicalType<ArrayElement, PhantomCo
|
||||||
Self::Clock => "a Clock",
|
Self::Clock => "a Clock",
|
||||||
Self::PhantomConst(_) => "a PhantomConst",
|
Self::PhantomConst(_) => "a PhantomConst",
|
||||||
Self::DynSimOnly(_) => "a SimOnlyValue",
|
Self::DynSimOnly(_) => "a SimOnlyValue",
|
||||||
|
Self::TraceAsString { .. } => "a TraceAsString",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,6 +116,15 @@ impl<T: BaseType> From<T> for SerdeCanonicalType {
|
||||||
CanonicalType::Clock(Clock {}) => Self::Clock,
|
CanonicalType::Clock(Clock {}) => Self::Clock,
|
||||||
CanonicalType::PhantomConst(ty) => Self::PhantomConst(SerdePhantomConst(ty.get())),
|
CanonicalType::PhantomConst(ty) => Self::PhantomConst(SerdePhantomConst(ty.get())),
|
||||||
CanonicalType::DynSimOnly(ty) => Self::DynSimOnly(ty),
|
CanonicalType::DynSimOnly(ty) => Self::DynSimOnly(ty),
|
||||||
|
CanonicalType::TraceAsString(TraceAsString {
|
||||||
|
inner_ty,
|
||||||
|
trace_as_string,
|
||||||
|
}) => Self::TraceAsString {
|
||||||
|
inner_ty: inner_ty.interned(),
|
||||||
|
trace_as_string: SerdeById {
|
||||||
|
inner: trace_as_string.interned(),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -130,6 +146,13 @@ impl From<SerdeCanonicalType> for CanonicalType {
|
||||||
Self::PhantomConst(PhantomConst::new_interned(value.0))
|
Self::PhantomConst(PhantomConst::new_interned(value.0))
|
||||||
}
|
}
|
||||||
SerdeCanonicalType::DynSimOnly(value) => Self::DynSimOnly(value),
|
SerdeCanonicalType::DynSimOnly(value) => Self::DynSimOnly(value),
|
||||||
|
SerdeCanonicalType::TraceAsString {
|
||||||
|
inner_ty,
|
||||||
|
trace_as_string,
|
||||||
|
} => Self::TraceAsString(TraceAsString {
|
||||||
|
inner_ty: crate::intern::LazyInterned::Interned(inner_ty),
|
||||||
|
trace_as_string: crate::intern::LazyInterned::Interned(trace_as_string.inner),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,9 @@ 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;
|
||||||
pub mod ready_valid;
|
pub mod ready_valid;
|
||||||
|
pub(crate) mod serde_by_id;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -241,15 +241,13 @@ mod tests {
|
||||||
/// happens to be in phase with the offending input or output).
|
/// happens to be in phase with the offending input or output).
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
fn queue_test(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) {
|
fn queue_test(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) {
|
||||||
#[hdl]
|
|
||||||
let clk: Clock = m.input();
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let cd = wire();
|
let cd = wire();
|
||||||
connect(
|
connect(
|
||||||
cd,
|
cd,
|
||||||
#[hdl]
|
#[hdl]
|
||||||
ClockDomain {
|
ClockDomain {
|
||||||
clk,
|
clk: formal_global_clock(),
|
||||||
rst: formal_reset().to_reset(),
|
rst: formal_reset().to_reset(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -280,7 +278,7 @@ mod tests {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let index_to_check = wire(index_ty);
|
let index_to_check = wire(index_ty);
|
||||||
connect(index_to_check, any_const(index_ty));
|
connect(index_to_check, any_const(index_ty));
|
||||||
hdl_assume(clk, index_to_check.cmp_lt(capacity.get()), "");
|
hdl_assume(cd.clk, index_to_check.cmp_lt(capacity.get()), "");
|
||||||
|
|
||||||
// instantiate and connect the queue
|
// instantiate and connect the queue
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -300,13 +298,13 @@ mod tests {
|
||||||
let expected_count_reg = reg_builder().clock_domain(cd).reset(count_ty.zero());
|
let expected_count_reg = reg_builder().clock_domain(cd).reset(count_ty.zero());
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if ReadyValid::firing(dut.inp) & !ReadyValid::firing(dut.out) {
|
if ReadyValid::firing(dut.inp) & !ReadyValid::firing(dut.out) {
|
||||||
hdl_assert(clk, expected_count_reg.cmp_ne(capacity.get()), "");
|
hdl_assert(cd.clk, expected_count_reg.cmp_ne(capacity.get()), "");
|
||||||
connect_any(expected_count_reg, expected_count_reg + 1u8);
|
connect_any(expected_count_reg, expected_count_reg + 1u8);
|
||||||
} else if !ReadyValid::firing(dut.inp) & ReadyValid::firing(dut.out) {
|
} else if !ReadyValid::firing(dut.inp) & ReadyValid::firing(dut.out) {
|
||||||
hdl_assert(clk, expected_count_reg.cmp_ne(count_ty.zero()), "");
|
hdl_assert(cd.clk, expected_count_reg.cmp_ne(count_ty.zero()), "");
|
||||||
connect_any(expected_count_reg, expected_count_reg - 1u8);
|
connect_any(expected_count_reg, expected_count_reg - 1u8);
|
||||||
}
|
}
|
||||||
hdl_assert(clk, expected_count_reg.cmp_eq(dut.count), "");
|
hdl_assert(cd.clk, expected_count_reg.cmp_eq(dut.count), "");
|
||||||
|
|
||||||
// keep an independent write index into the FIFO's circular buffer
|
// keep an independent write index into the FIFO's circular buffer
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -374,7 +372,7 @@ mod tests {
|
||||||
match inp_firing_data {
|
match inp_firing_data {
|
||||||
// ... and we are not receiving data, then we must not
|
// ... and we are not receiving data, then we must not
|
||||||
// transmit any data.
|
// transmit any data.
|
||||||
HdlNone => hdl_assert(clk, HdlOption::is_none(out_firing_data), ""),
|
HdlNone => hdl_assert(cd.clk, HdlOption::is_none(out_firing_data), ""),
|
||||||
// If we are indeed receiving some data...
|
// If we are indeed receiving some data...
|
||||||
HdlSome(data_in) => {
|
HdlSome(data_in) => {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -382,7 +380,9 @@ mod tests {
|
||||||
// ... and transmitting at the same time, we
|
// ... and transmitting at the same time, we
|
||||||
// must be transmitting the input data itself,
|
// must be transmitting the input data itself,
|
||||||
// since the holding register is empty.
|
// since the holding register is empty.
|
||||||
HdlSome(data_out) => hdl_assert(clk, data_out.cmp_eq(data_in), ""),
|
HdlSome(data_out) => {
|
||||||
|
hdl_assert(cd.clk, data_out.cmp_eq(data_in), "")
|
||||||
|
}
|
||||||
// If we are receiving, but not transmitting,
|
// If we are receiving, but not transmitting,
|
||||||
// store the received data in the holding
|
// store the received data in the holding
|
||||||
// register.
|
// register.
|
||||||
|
|
@ -397,11 +397,11 @@ mod tests {
|
||||||
match out_firing_data {
|
match out_firing_data {
|
||||||
// ... and we are not transmitting it, we cannot
|
// ... and we are not transmitting it, we cannot
|
||||||
// receive any more data.
|
// receive any more data.
|
||||||
HdlNone => hdl_assert(clk, HdlOption::is_none(inp_firing_data), ""),
|
HdlNone => hdl_assert(cd.clk, HdlOption::is_none(inp_firing_data), ""),
|
||||||
// If we are transmitting a previously stored value...
|
// If we are transmitting a previously stored value...
|
||||||
HdlSome(data_out) => {
|
HdlSome(data_out) => {
|
||||||
// ... it must be the same data we stored earlier.
|
// ... it must be the same data we stored earlier.
|
||||||
hdl_assert(clk, data_out.cmp_eq(stored), "");
|
hdl_assert(cd.clk, data_out.cmp_eq(stored), "");
|
||||||
// Also, accept new data, if any. Otherwise,
|
// Also, accept new data, if any. Otherwise,
|
||||||
// let the holding register become empty.
|
// let the holding register become empty.
|
||||||
connect(stored_reg, inp_firing_data);
|
connect(stored_reg, inp_firing_data);
|
||||||
|
|
@ -417,17 +417,17 @@ mod tests {
|
||||||
connect(dut.dbg.index_to_check, index_to_check);
|
connect(dut.dbg.index_to_check, index_to_check);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if let HdlSome(stored) = stored_reg {
|
if let HdlSome(stored) = stored_reg {
|
||||||
hdl_assert(clk, stored.cmp_eq(dut.dbg.stored), "");
|
hdl_assert(cd.clk, stored.cmp_eq(dut.dbg.stored), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// sync the read and write indices
|
// sync the read and write indices
|
||||||
hdl_assert(clk, inp_index_reg.cmp_eq(dut.dbg.inp_index), "");
|
hdl_assert(cd.clk, inp_index_reg.cmp_eq(dut.dbg.inp_index), "");
|
||||||
hdl_assert(clk, out_index_reg.cmp_eq(dut.dbg.out_index), "");
|
hdl_assert(cd.clk, out_index_reg.cmp_eq(dut.dbg.out_index), "");
|
||||||
|
|
||||||
// the indices should never go past the capacity, but induction
|
// the indices should never go past the capacity, but induction
|
||||||
// doesn't know that...
|
// doesn't know that...
|
||||||
hdl_assert(clk, inp_index_reg.cmp_lt(capacity.get()), "");
|
hdl_assert(cd.clk, inp_index_reg.cmp_lt(capacity.get()), "");
|
||||||
hdl_assert(clk, out_index_reg.cmp_lt(capacity.get()), "");
|
hdl_assert(cd.clk, out_index_reg.cmp_lt(capacity.get()), "");
|
||||||
|
|
||||||
// strongly constrain the state of the holding register
|
// strongly constrain the state of the holding register
|
||||||
//
|
//
|
||||||
|
|
@ -455,7 +455,7 @@ mod tests {
|
||||||
connect(expected_stored, pending_reads.cmp_lt(dut.count));
|
connect(expected_stored, pending_reads.cmp_lt(dut.count));
|
||||||
// sync with the state of the holding register
|
// sync with the state of the holding register
|
||||||
hdl_assert(
|
hdl_assert(
|
||||||
clk,
|
cd.clk,
|
||||||
expected_stored.cmp_eq(HdlOption::is_some(stored_reg)),
|
expected_stored.cmp_eq(HdlOption::is_some(stored_reg)),
|
||||||
"",
|
"",
|
||||||
);
|
);
|
||||||
|
|
|
||||||
234
crates/fayalite/src/util/serde_by_id.rs
Normal file
234
crates/fayalite/src/util/serde_by_id.rs
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use crate::util::HashMap;
|
||||||
|
use hashbrown::hash_map::Entry;
|
||||||
|
use serde::{Deserialize, Serialize, de::Error};
|
||||||
|
use std::{
|
||||||
|
any::TypeId,
|
||||||
|
borrow::Cow,
|
||||||
|
fmt::Write,
|
||||||
|
hash::{BuildHasher, Hash, Hasher},
|
||||||
|
marker::PhantomData,
|
||||||
|
sync::Mutex,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) struct SerdeByIdProperties<T: SerdeByIdTrait> {
|
||||||
|
type_id: TypeId,
|
||||||
|
type_name: &'static str,
|
||||||
|
_phantom: PhantomData<fn(T) -> T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> Clone for SerdeByIdProperties<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> Copy for SerdeByIdProperties<T> {}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> SerdeByIdProperties<T> {
|
||||||
|
pub fn of<U: ?Sized + 'static>() -> Self {
|
||||||
|
Self {
|
||||||
|
type_id: TypeId::of::<U>(),
|
||||||
|
type_name: std::any::type_name::<U>(),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait SerdeByIdTrait: Hash + Eq + Clone + 'static + Send {
|
||||||
|
fn serde_by_id_properties(&self) -> SerdeByIdProperties<Self>;
|
||||||
|
fn static_table() -> &'static SerdeByIdTable<Self>;
|
||||||
|
const NAME: &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct SerdeRandomId([u32; 4]);
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub(crate) struct SerdeId<'a, T: SerdeByIdTrait> {
|
||||||
|
random_id: SerdeRandomId,
|
||||||
|
#[serde(borrow)]
|
||||||
|
type_name: Cow<'a, str>,
|
||||||
|
#[serde(skip)]
|
||||||
|
_phantom: PhantomData<fn(T) -> T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: SerdeByIdTrait> Clone for SerdeId<'a, T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
random_id: self.random_id,
|
||||||
|
type_name: self.type_name.clone(),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: SerdeByIdTrait> Eq for SerdeId<'a, T> {}
|
||||||
|
|
||||||
|
impl<'a, 'b, T: SerdeByIdTrait> PartialEq<SerdeId<'b, T>> for SerdeId<'a, T> {
|
||||||
|
fn eq(&self, other: &SerdeId<'b, T>) -> bool {
|
||||||
|
let Self {
|
||||||
|
random_id,
|
||||||
|
type_name,
|
||||||
|
_phantom: _,
|
||||||
|
} = self;
|
||||||
|
*random_id == other.random_id && *type_name == other.type_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: SerdeByIdTrait> Hash for SerdeId<'a, T> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
let Self {
|
||||||
|
random_id,
|
||||||
|
type_name: _,
|
||||||
|
_phantom: _,
|
||||||
|
} = self;
|
||||||
|
random_id.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SerdeByIdTableRest<T: SerdeByIdTrait> {
|
||||||
|
from_serde: HashMap<SerdeId<'static, T>, T>,
|
||||||
|
serde_id_random_state: std::hash::RandomState,
|
||||||
|
buffer: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> Default for SerdeByIdTableRest<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
from_serde: Default::default(),
|
||||||
|
serde_id_random_state: Default::default(),
|
||||||
|
buffer: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> SerdeByIdTableRest<T> {
|
||||||
|
fn add_new(&mut self, value: T) -> SerdeId<'static, T> {
|
||||||
|
let properties = value.serde_by_id_properties();
|
||||||
|
let mut try_number = 0u64;
|
||||||
|
let mut hasher = self.serde_id_random_state.build_hasher();
|
||||||
|
// extract more bits of randomness from TypeId -- its Hash impl only hashes 64-bits
|
||||||
|
write!(self.buffer, "{:?}", properties.type_id).expect("shouldn't ever fail");
|
||||||
|
self.buffer.hash(&mut hasher);
|
||||||
|
loop {
|
||||||
|
let mut hasher = hasher.clone();
|
||||||
|
try_number.hash(&mut hasher);
|
||||||
|
try_number += 1;
|
||||||
|
let key = SerdeId {
|
||||||
|
random_id: SerdeRandomId(std::array::from_fn(|i| {
|
||||||
|
let mut hasher = hasher.clone();
|
||||||
|
i.hash(&mut hasher);
|
||||||
|
hasher.finish() as u32
|
||||||
|
})),
|
||||||
|
type_name: Cow::Borrowed(properties.type_name),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
|
match self.from_serde.entry(key) {
|
||||||
|
Entry::Occupied(_) => continue,
|
||||||
|
Entry::Vacant(e) => {
|
||||||
|
let key = e.key().clone();
|
||||||
|
e.insert(value);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct SerdeByIdTableMut<T: SerdeByIdTrait> {
|
||||||
|
to_serde: HashMap<T, SerdeId<'static, T>>,
|
||||||
|
rest: SerdeByIdTableRest<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> Default for SerdeByIdTableMut<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
to_serde: Default::default(),
|
||||||
|
rest: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> SerdeByIdTableMut<T> {
|
||||||
|
pub(crate) fn to_serde(&mut self, value: &T) -> SerdeId<'static, T> {
|
||||||
|
if let Some(retval) = self.to_serde.get(value) {
|
||||||
|
return retval.clone();
|
||||||
|
}
|
||||||
|
self.to_serde_insert(value)
|
||||||
|
}
|
||||||
|
#[cold]
|
||||||
|
fn to_serde_insert(&mut self, value: &T) -> SerdeId<'static, T> {
|
||||||
|
let value = value.clone();
|
||||||
|
let retval = self.rest.add_new(value.clone());
|
||||||
|
self.to_serde.insert(value, retval.clone());
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
pub(crate) fn from_serde(&self, id: &SerdeId<'_, T>) -> Option<T> {
|
||||||
|
self.rest.from_serde.get(id).cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct SerdeByIdTable<T: SerdeByIdTrait>(Mutex<Option<SerdeByIdTableMut<T>>>);
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> SerdeByIdTable<T> {
|
||||||
|
pub(crate) const fn new() -> Self {
|
||||||
|
Self(Mutex::new(None))
|
||||||
|
}
|
||||||
|
pub(crate) fn to_serde(&self, value: &T) -> SerdeId<'static, T> {
|
||||||
|
self.0
|
||||||
|
.lock()
|
||||||
|
.expect("shouldn't be poison")
|
||||||
|
.get_or_insert_with(
|
||||||
|
#[cold]
|
||||||
|
|| Default::default(),
|
||||||
|
)
|
||||||
|
.to_serde(value)
|
||||||
|
}
|
||||||
|
pub(crate) fn from_serde(&self, id: &SerdeId<'_, T>) -> Option<T> {
|
||||||
|
self.0
|
||||||
|
.lock()
|
||||||
|
.expect("shouldn't be poison")
|
||||||
|
.get_or_insert_with(
|
||||||
|
#[cold]
|
||||||
|
|| Default::default(),
|
||||||
|
)
|
||||||
|
.from_serde(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, Ord, PartialOrd)]
|
||||||
|
pub(crate) struct SerdeById<T: SerdeByIdTrait> {
|
||||||
|
pub(crate) inner: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, T: SerdeByIdTrait> Deserialize<'de> for SerdeById<T> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let id = SerdeId::deserialize(deserializer)?;
|
||||||
|
let inner = T::static_table().from_serde(&id).ok_or_else(|| {
|
||||||
|
D::Error::custom(format_args!(
|
||||||
|
"doesn't match any {} that was serialized this time this program was run: type_name={:?}",
|
||||||
|
T::NAME,
|
||||||
|
id.type_name,
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
Ok(Self { inner })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: SerdeByIdTrait> Serialize for SerdeById<T> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
T::static_table()
|
||||||
|
.to_serde(&self.inner)
|
||||||
|
.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -546,7 +546,7 @@ impl<W: fmt::Write> Visitor for XdcFileWriter<W> {
|
||||||
base.source_location(),
|
base.source_location(),
|
||||||
)? {},
|
)? {},
|
||||||
}
|
}
|
||||||
match base.canonical_ty() {
|
match base.canonical_ty().unwrap_transparent_types() {
|
||||||
CanonicalType::UInt(_)
|
CanonicalType::UInt(_)
|
||||||
| CanonicalType::SInt(_)
|
| CanonicalType::SInt(_)
|
||||||
| CanonicalType::Bool(_)
|
| CanonicalType::Bool(_)
|
||||||
|
|
@ -563,6 +563,9 @@ impl<W: fmt::Write> Visitor for XdcFileWriter<W> {
|
||||||
v,
|
v,
|
||||||
base.source_location(),
|
base.source_location(),
|
||||||
)? {},
|
)? {},
|
||||||
|
CanonicalType::TraceAsString(_) => {
|
||||||
|
unreachable!("handled by unwrap_transparent_types")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.required_dont_touch_targets.insert(target);
|
self.required_dont_touch_targets.insert(target);
|
||||||
match v {
|
match v {
|
||||||
|
|
@ -592,6 +595,9 @@ impl<W: fmt::Write> Visitor for XdcFileWriter<W> {
|
||||||
v,
|
v,
|
||||||
instance.source_location(),
|
instance.source_location(),
|
||||||
)? {},
|
)? {},
|
||||||
|
TargetBase::FormalInput(_) | TargetBase::SimIoForGlobal(_) => {
|
||||||
|
unreachable!("base.is_valid_annotation_target() is known to be false")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,13 @@ impl<T: Type> Wire<T> {
|
||||||
ty: T::from_canonical(ty),
|
ty: T::from_canonical(ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn new_unchecked(
|
pub fn new_unchecked(
|
||||||
scoped_name: ScopedNameId,
|
scoped_name: ScopedNameId,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
ty: T,
|
ty: T,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
scoped_name.0.assert_is_name_id();
|
||||||
Self {
|
Self {
|
||||||
name: scoped_name,
|
name: scoped_name,
|
||||||
source_location,
|
source_location,
|
||||||
|
|
@ -76,7 +78,7 @@ impl<T: Type> Wire<T> {
|
||||||
self.containing_module_name_id().0
|
self.containing_module_name_id().0
|
||||||
}
|
}
|
||||||
pub fn containing_module_name_id(&self) -> NameId {
|
pub fn containing_module_name_id(&self) -> NameId {
|
||||||
self.name.0
|
self.name.0.unwrap_name_id()
|
||||||
}
|
}
|
||||||
pub fn name(&self) -> Interned<str> {
|
pub fn name(&self) -> Interned<str> {
|
||||||
self.name_id().0
|
self.name_id().0
|
||||||
|
|
|
||||||
6
crates/fayalite/tests/expected/my_test.md
Normal file
6
crates/fayalite/tests/expected/my_test.md
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!--
|
||||||
|
SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
See Notices.txt for copyright information
|
||||||
|
-->
|
||||||
|
|
||||||
|
`my_test.vcd` is used in the doctest of `fayalite::testing::checked_vcd_output`
|
||||||
13
crates/fayalite/tests/expected/my_test.vcd
Normal file
13
crates/fayalite/tests/expected/my_test.vcd
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
$timescale 1 ps $end
|
||||||
|
$scope module my_module $end
|
||||||
|
$var wire 8 gAF7X a $end
|
||||||
|
$var wire 8 QS=a/ b $end
|
||||||
|
$upscope $end
|
||||||
|
$enddefinitions $end
|
||||||
|
$dumpvars
|
||||||
|
b0 gAF7X
|
||||||
|
b0 QS=a/
|
||||||
|
$end
|
||||||
|
#1000000
|
||||||
|
b1100100 gAF7X
|
||||||
|
b101010 QS=a/
|
||||||
|
|
@ -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),
|
||||||
|
}
|
||||||
|
|
|
||||||
166
crates/fayalite/tests/hdl_types_fmt.rs
Normal file
166
crates/fayalite/tests/hdl_types_fmt.rs
Normal 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])");
|
||||||
|
}
|
||||||
|
|
@ -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,270 @@ 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])
|
||||||
|
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1])
|
||||||
|
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[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])
|
||||||
|
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1])
|
||||||
|
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[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])
|
||||||
|
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1])
|
||||||
|
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[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]
|
||||||
|
|
@ -3419,20 +3683,176 @@ circuit check_formal: %[[
|
||||||
input pred1: UInt<1> @[module-XXXXXXXXXX.rs 6:1]
|
input pred1: UInt<1> @[module-XXXXXXXXXX.rs 6:1]
|
||||||
input pred2: UInt<1> @[module-XXXXXXXXXX.rs 7:1]
|
input pred2: UInt<1> @[module-XXXXXXXXXX.rs 7:1]
|
||||||
input pred3: UInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
input pred3: UInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
||||||
inst formal_reset of formal_reset @[formal.rs 185:24]
|
inst formal_reset of formal_reset @[builtin 1:1]
|
||||||
assert(clk, pred1, and(en1, not(formal_reset.rst)), "en check 1") @[module-XXXXXXXXXX.rs 9:1]
|
assert(clk, pred1, and(en1, not(formal_reset.rst)), "en check 1") @[module-XXXXXXXXXX.rs 9:1]
|
||||||
inst formal_reset_1 of formal_reset @[formal.rs 185:24]
|
assume(clk, pred2, and(en2, not(formal_reset.rst)), "en check 2") @[module-XXXXXXXXXX.rs 10:1]
|
||||||
assume(clk, pred2, and(en2, not(formal_reset_1.rst)), "en check 2") @[module-XXXXXXXXXX.rs 10:1]
|
cover(clk, pred3, and(en3, not(formal_reset.rst)), "en check 3") @[module-XXXXXXXXXX.rs 11:1]
|
||||||
inst formal_reset_2 of formal_reset @[formal.rs 185:24]
|
assert(clk, pred1, and(UInt<1>(0h1), not(formal_reset.rst)), "check 1") @[module-XXXXXXXXXX.rs 12:1]
|
||||||
cover(clk, pred3, and(en3, not(formal_reset_2.rst)), "en check 3") @[module-XXXXXXXXXX.rs 11:1]
|
assume(clk, pred2, and(UInt<1>(0h1), not(formal_reset.rst)), "check 2") @[module-XXXXXXXXXX.rs 13:1]
|
||||||
inst formal_reset_3 of formal_reset @[formal.rs 185:24]
|
cover(clk, pred3, and(UInt<1>(0h1), not(formal_reset.rst)), "check 3") @[module-XXXXXXXXXX.rs 14:1]
|
||||||
assert(clk, pred1, and(UInt<1>(0h1), not(formal_reset_3.rst)), "check 1") @[module-XXXXXXXXXX.rs 12:1]
|
extmodule formal_reset: @[builtin 1:1]
|
||||||
inst formal_reset_4 of formal_reset @[formal.rs 185:24]
|
output rst: UInt<1> @[builtin 1:1]
|
||||||
assume(clk, pred2, and(UInt<1>(0h1), not(formal_reset_4.rst)), "check 2") @[module-XXXXXXXXXX.rs 13:1]
|
defname = __fayalite_formal_reset
|
||||||
inst formal_reset_5 of formal_reset @[formal.rs 185:24]
|
"#,
|
||||||
cover(clk, pred3, and(UInt<1>(0h1), not(formal_reset_5.rst)), "check 3") @[module-XXXXXXXXXX.rs 14:1]
|
};
|
||||||
extmodule formal_reset: @[formal.rs 169:5]
|
}
|
||||||
output rst: UInt<1> @[formal.rs 172:32]
|
|
||||||
|
#[hdl_module(outline_generated)]
|
||||||
|
pub fn check_formal_input() {
|
||||||
|
#[hdl]
|
||||||
|
let bool_in: Bool = m.input();
|
||||||
|
#[hdl]
|
||||||
|
let bool_out: Bool = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let any_const_out1: Bool = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let any_const_out2: UInt<16> = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let any_const_out3: SInt<12> = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let any_seq_out: UInt<10> = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let all_const_out: UInt<10> = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let all_seq_out: UInt<10> = m.output();
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
let bool_reg = reg_builder()
|
||||||
|
.clock_domain(
|
||||||
|
#[hdl]
|
||||||
|
ClockDomain {
|
||||||
|
clk: formal_global_clock(),
|
||||||
|
rst: formal_reset(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.reset(false);
|
||||||
|
|
||||||
|
connect(bool_reg, bool_in);
|
||||||
|
connect(bool_out, bool_reg);
|
||||||
|
connect(any_const_out1, any_const(StaticType::TYPE));
|
||||||
|
connect(any_const_out2, any_const(StaticType::TYPE));
|
||||||
|
connect(any_const_out3, any_const(StaticType::TYPE));
|
||||||
|
connect(any_seq_out, any_seq(StaticType::TYPE));
|
||||||
|
connect(all_const_out, all_const(StaticType::TYPE));
|
||||||
|
connect(all_seq_out, all_seq(StaticType::TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_formal_input() {
|
||||||
|
let _n = SourceLocation::normalize_files_for_tests();
|
||||||
|
let m = check_formal_input();
|
||||||
|
dbg!(m);
|
||||||
|
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
|
||||||
|
assert_export_firrtl! {
|
||||||
|
m =>
|
||||||
|
"/test/check_formal_input.fir": r#"FIRRTL version 3.2.0
|
||||||
|
circuit check_formal_input: %[[
|
||||||
|
{
|
||||||
|
"class": "firrtl.AttributeAnnotation",
|
||||||
|
"description": "gclk",
|
||||||
|
"target": "~check_formal_input|check_formal_input>formal_global_clock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.DontTouchAnnotation",
|
||||||
|
"target": "~check_formal_input|check_formal_input>formal_global_clock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.AttributeAnnotation",
|
||||||
|
"description": "anyconst",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_const"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.DontTouchAnnotation",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_const"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.AttributeAnnotation",
|
||||||
|
"description": "anyconst",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_const_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.DontTouchAnnotation",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_const_1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.AttributeAnnotation",
|
||||||
|
"description": "anyconst",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_const_2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.DontTouchAnnotation",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_const_2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.AttributeAnnotation",
|
||||||
|
"description": "anyseq",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_seq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.DontTouchAnnotation",
|
||||||
|
"target": "~check_formal_input|check_formal_input>any_seq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.AttributeAnnotation",
|
||||||
|
"description": "allconst",
|
||||||
|
"target": "~check_formal_input|check_formal_input>all_const"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.DontTouchAnnotation",
|
||||||
|
"target": "~check_formal_input|check_formal_input>all_const"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.AttributeAnnotation",
|
||||||
|
"description": "allseq",
|
||||||
|
"target": "~check_formal_input|check_formal_input>all_seq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.DontTouchAnnotation",
|
||||||
|
"target": "~check_formal_input|check_formal_input>all_seq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class": "firrtl.transforms.BlackBoxInlineAnno",
|
||||||
|
"name": "fayalite_formal_reset.v",
|
||||||
|
"text": "module __fayalite_formal_reset(output rst);\n assign rst = $initstate;\nendmodule\n",
|
||||||
|
"target": "~check_formal_input|formal_reset"
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
type Ty0 = {clk: Clock, rst: UInt<1>}
|
||||||
|
type Ty1 = {rst: UInt<1>}
|
||||||
|
module check_formal_input: @[module-XXXXXXXXXX.rs 1:1]
|
||||||
|
input bool_in: UInt<1> @[module-XXXXXXXXXX.rs 2:1]
|
||||||
|
output bool_out: UInt<1> @[module-XXXXXXXXXX.rs 3:1]
|
||||||
|
output any_const_out1: UInt<1> @[module-XXXXXXXXXX.rs 4:1]
|
||||||
|
output any_const_out2: UInt<16> @[module-XXXXXXXXXX.rs 5:1]
|
||||||
|
output any_const_out3: SInt<12> @[module-XXXXXXXXXX.rs 6:1]
|
||||||
|
output any_seq_out: UInt<10> @[module-XXXXXXXXXX.rs 7:1]
|
||||||
|
output all_const_out: UInt<10> @[module-XXXXXXXXXX.rs 8:1]
|
||||||
|
output all_seq_out: UInt<10> @[module-XXXXXXXXXX.rs 9:1]
|
||||||
|
wire _bundle_literal_expr_1: Ty0
|
||||||
|
connect _bundle_literal_expr_1.clk, asClock(UInt<1>(0h0))
|
||||||
|
connect _bundle_literal_expr_1.rst, UInt<1>(0h0)
|
||||||
|
reg formal_global_clock: UInt<1>, _bundle_literal_expr_1.clk @[builtin 1:1]
|
||||||
|
inst formal_reset of formal_reset @[builtin 1:1]
|
||||||
|
reg any_const: UInt<1>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 13:1]
|
||||||
|
reg any_const_1: UInt<16>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 15:1]
|
||||||
|
reg any_const_2: SInt<12>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 17:1]
|
||||||
|
reg any_seq: UInt<10>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 19:1]
|
||||||
|
reg all_const: UInt<10>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 21:1]
|
||||||
|
reg all_seq: UInt<10>, _bundle_literal_expr_1.clk @[module-XXXXXXXXXX.rs 23:1]
|
||||||
|
wire _bundle_literal_expr: Ty0
|
||||||
|
connect _bundle_literal_expr.clk, asClock(formal_global_clock)
|
||||||
|
connect _bundle_literal_expr.rst, formal_reset.rst
|
||||||
|
regreset bool_reg: UInt<1>, _bundle_literal_expr.clk, _bundle_literal_expr.rst, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 10:1]
|
||||||
|
connect bool_reg, bool_in @[module-XXXXXXXXXX.rs 11:1]
|
||||||
|
connect bool_out, bool_reg @[module-XXXXXXXXXX.rs 12:1]
|
||||||
|
connect any_const_out1, any_const @[module-XXXXXXXXXX.rs 14:1]
|
||||||
|
connect any_const_out2, any_const_1 @[module-XXXXXXXXXX.rs 16:1]
|
||||||
|
connect any_const_out3, any_const_2 @[module-XXXXXXXXXX.rs 18:1]
|
||||||
|
connect any_seq_out, any_seq @[module-XXXXXXXXXX.rs 20:1]
|
||||||
|
connect all_const_out, all_const @[module-XXXXXXXXXX.rs 22:1]
|
||||||
|
connect all_seq_out, all_seq @[module-XXXXXXXXXX.rs 24:1]
|
||||||
|
extmodule formal_reset: @[builtin 1:1]
|
||||||
|
output rst: UInt<1> @[builtin 1:1]
|
||||||
defname = __fayalite_formal_reset
|
defname = __fayalite_formal_reset
|
||||||
"#,
|
"#,
|
||||||
};
|
};
|
||||||
|
|
@ -3565,21 +3985,10 @@ circuit check_enum_connect_any:
|
||||||
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
HdlSome:
|
HdlSome:
|
||||||
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_1: Ty5
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_1: Ty6
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 2, 0), 0, 0)
|
|
||||||
wire _cast_bits_to_enum_expr_1: Ty3
|
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_1.tag, 0)):
|
|
||||||
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlNone)
|
|
||||||
else:
|
|
||||||
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlSome)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_enum_expr_1
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.body, bits(bits(i2.body, 2, 0), 2, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<1>
|
; lhs: SInt<1>
|
||||||
; rhs: SInt<2>
|
; rhs: SInt<2>
|
||||||
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr_1.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_2: Ty4
|
wire _bundle_literal_expr_2: Ty4
|
||||||
connect _bundle_literal_expr_2.tag, {|HdlNone, HdlSome|}(HdlSome)
|
connect _bundle_literal_expr_2.tag, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
||||||
|
|
@ -3601,18 +4010,18 @@ circuit check_enum_connect_any:
|
||||||
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
C:
|
C:
|
||||||
wire __connect_variant_body_3: Ty8 @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_3: Ty8 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_2: Ty8
|
wire _cast_bits_to_bundle_expr_1: Ty8
|
||||||
wire _cast_bits_to_bundle_expr_flattened_2: Ty9
|
wire _cast_bits_to_bundle_expr_flattened_1: Ty9
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
||||||
wire _cast_bits_to_enum_expr_2: Ty3
|
wire _cast_bits_to_enum_expr_1: Ty3
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_2.tag, 0)):
|
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_1.tag, 0)):
|
||||||
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlNone)
|
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
else:
|
else:
|
||||||
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlSome)
|
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_enum_expr_2
|
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_enum_expr_1
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_1.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
||||||
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_2 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_4: Ty1
|
wire _bundle_literal_expr_4: Ty1
|
||||||
connect _bundle_literal_expr_4.tag, {|A, B, C|}(C)
|
connect _bundle_literal_expr_4.tag, {|A, B, C|}(C)
|
||||||
wire _cast_bundle_to_bits_expr_1: Ty9
|
wire _cast_bundle_to_bits_expr_1: Ty9
|
||||||
|
|
@ -3641,18 +4050,18 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
B:
|
B:
|
||||||
wire __connect_variant_body_5: Ty5 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_5: Ty5 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_3: Ty4
|
wire _cast_bits_to_bundle_expr_2: Ty4
|
||||||
wire _cast_bits_to_bundle_expr_flattened_3: Ty7
|
wire _cast_bits_to_bundle_expr_flattened_2: Ty7
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
||||||
wire _cast_bits_to_enum_expr_3: Ty3
|
wire _cast_bits_to_enum_expr_2: Ty3
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_3.tag, 0)):
|
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_2.tag, 0)):
|
||||||
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlNone)
|
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
else:
|
else:
|
||||||
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlSome)
|
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_enum_expr_3
|
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_enum_expr_2
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.body, bits(bits(i1.body, 1, 0), 1, 1)
|
connect _cast_bits_to_bundle_expr_flattened_2.body, bits(bits(i1.body, 1, 0), 1, 1)
|
||||||
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
||||||
match _cast_bits_to_bundle_expr_3.tag: @[module-XXXXXXXXXX.rs 9:1]
|
match _cast_bits_to_bundle_expr_2.tag: @[module-XXXXXXXXXX.rs 9:1]
|
||||||
HdlNone:
|
HdlNone:
|
||||||
wire _bundle_literal_expr_6: Ty5
|
wire _bundle_literal_expr_6: Ty5
|
||||||
connect _bundle_literal_expr_6.tag, {|HdlNone, HdlSome|}(HdlNone)
|
connect _bundle_literal_expr_6.tag, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
|
|
@ -3660,21 +4069,10 @@ circuit check_enum_connect_any:
|
||||||
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
HdlSome:
|
HdlSome:
|
||||||
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_4: Ty4
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_4: Ty7
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
|
||||||
wire _cast_bits_to_enum_expr_4: Ty3
|
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_4.tag, 0)):
|
|
||||||
connect _cast_bits_to_enum_expr_4, {|HdlNone, HdlSome|}(HdlNone)
|
|
||||||
else:
|
|
||||||
connect _cast_bits_to_enum_expr_4, {|HdlNone, HdlSome|}(HdlSome)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.tag, _cast_bits_to_enum_expr_4
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.body, bits(bits(i1.body, 1, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.body, _cast_bits_to_bundle_expr_flattened_4.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<2>
|
; lhs: SInt<2>
|
||||||
; rhs: SInt<1>
|
; rhs: SInt<1>
|
||||||
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_4.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_2.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_7: Ty5
|
wire _bundle_literal_expr_7: Ty5
|
||||||
connect _bundle_literal_expr_7.tag, {|HdlNone, HdlSome|}(HdlSome)
|
connect _bundle_literal_expr_7.tag, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
||||||
|
|
@ -3696,18 +4094,18 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
C:
|
C:
|
||||||
wire __connect_variant_body_7: Ty8 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_7: Ty8 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_5: Ty8
|
wire _cast_bits_to_bundle_expr_3: Ty8
|
||||||
wire _cast_bits_to_bundle_expr_flattened_5: Ty9
|
wire _cast_bits_to_bundle_expr_flattened_3: Ty9
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
||||||
wire _cast_bits_to_enum_expr_5: Ty3
|
wire _cast_bits_to_enum_expr_3: Ty3
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_5.tag, 0)):
|
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_3.tag, 0)):
|
||||||
connect _cast_bits_to_enum_expr_5, {|HdlNone, HdlSome|}(HdlNone)
|
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
else:
|
else:
|
||||||
connect _cast_bits_to_enum_expr_5, {|HdlNone, HdlSome|}(HdlSome)
|
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _cast_bits_to_bundle_expr_5.tag, _cast_bits_to_enum_expr_5
|
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_enum_expr_3
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_3.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_5.body, _cast_bits_to_bundle_expr_flattened_5.body
|
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
||||||
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_3 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_9: Ty2
|
wire _bundle_literal_expr_9: Ty2
|
||||||
connect _bundle_literal_expr_9.tag, {|A, B, C|}(C)
|
connect _bundle_literal_expr_9.tag, {|A, B, C|}(C)
|
||||||
wire _cast_bundle_to_bits_expr_3: Ty9
|
wire _cast_bundle_to_bits_expr_3: Ty9
|
||||||
|
|
@ -3774,16 +4172,10 @@ circuit check_enum_connect_any:
|
||||||
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_1: Ty3
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_1: Ty3
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_bundle_expr_flattened_1.tag
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.body, bits(bits(i2.body, 2, 0), 2, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<1>
|
; lhs: SInt<1>
|
||||||
; rhs: SInt<2>
|
; rhs: SInt<2>
|
||||||
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr_1.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_2: Ty2
|
wire _bundle_literal_expr_2: Ty2
|
||||||
connect _bundle_literal_expr_2.tag, UInt<1>(0h1)
|
connect _bundle_literal_expr_2.tag, UInt<1>(0h1)
|
||||||
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
||||||
|
|
@ -3799,13 +4191,13 @@ circuit check_enum_connect_any:
|
||||||
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_3: Ty4 @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_3: Ty4 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_2: Ty4
|
wire _cast_bits_to_bundle_expr_1: Ty4
|
||||||
wire _cast_bits_to_bundle_expr_flattened_2: Ty4
|
wire _cast_bits_to_bundle_expr_flattened_1: Ty4
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
||||||
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_bundle_expr_flattened_2.tag
|
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_bundle_expr_flattened_1.tag
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_1.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
||||||
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_2 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_4: Ty0
|
wire _bundle_literal_expr_4: Ty0
|
||||||
connect _bundle_literal_expr_4.tag, UInt<2>(0h2)
|
connect _bundle_literal_expr_4.tag, UInt<2>(0h2)
|
||||||
wire _cast_bundle_to_bits_expr_1: Ty4
|
wire _cast_bundle_to_bits_expr_1: Ty4
|
||||||
|
|
@ -3827,29 +4219,23 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
else when eq(i1.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 9:1]
|
else when eq(i1.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire __connect_variant_body_5: Ty3 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_5: Ty3 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_3: Ty2
|
wire _cast_bits_to_bundle_expr_2: Ty2
|
||||||
wire _cast_bits_to_bundle_expr_flattened_3: Ty2
|
wire _cast_bits_to_bundle_expr_flattened_2: Ty2
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
||||||
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_bundle_expr_flattened_3.tag
|
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_bundle_expr_flattened_2.tag
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.body, bits(bits(i1.body, 1, 0), 1, 1)
|
connect _cast_bits_to_bundle_expr_flattened_2.body, bits(bits(i1.body, 1, 0), 1, 1)
|
||||||
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
||||||
when eq(_cast_bits_to_bundle_expr_3.tag, UInt<1>(0h0)): @[module-XXXXXXXXXX.rs 9:1]
|
when eq(_cast_bits_to_bundle_expr_2.tag, UInt<1>(0h0)): @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_6: Ty3
|
wire _bundle_literal_expr_6: Ty3
|
||||||
connect _bundle_literal_expr_6.tag, UInt<1>(0h0)
|
connect _bundle_literal_expr_6.tag, UInt<1>(0h0)
|
||||||
connect _bundle_literal_expr_6.body, UInt<2>(0h0)
|
connect _bundle_literal_expr_6.body, UInt<2>(0h0)
|
||||||
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_4: Ty2
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_4: Ty2
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.tag, _cast_bits_to_bundle_expr_flattened_4.tag
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.body, bits(bits(i1.body, 1, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.body, _cast_bits_to_bundle_expr_flattened_4.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<2>
|
; lhs: SInt<2>
|
||||||
; rhs: SInt<1>
|
; rhs: SInt<1>
|
||||||
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_4.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_2.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_7: Ty3
|
wire _bundle_literal_expr_7: Ty3
|
||||||
connect _bundle_literal_expr_7.tag, UInt<1>(0h1)
|
connect _bundle_literal_expr_7.tag, UInt<1>(0h1)
|
||||||
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
||||||
|
|
@ -3865,13 +4251,13 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_7: Ty4 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_7: Ty4 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_5: Ty4
|
wire _cast_bits_to_bundle_expr_3: Ty4
|
||||||
wire _cast_bits_to_bundle_expr_flattened_5: Ty4
|
wire _cast_bits_to_bundle_expr_flattened_3: Ty4
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
||||||
connect _cast_bits_to_bundle_expr_5.tag, _cast_bits_to_bundle_expr_flattened_5.tag
|
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_bundle_expr_flattened_3.tag
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_3.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_5.body, _cast_bits_to_bundle_expr_flattened_5.body
|
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
||||||
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_3 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_9: Ty1
|
wire _bundle_literal_expr_9: Ty1
|
||||||
connect _bundle_literal_expr_9.tag, UInt<2>(0h2)
|
connect _bundle_literal_expr_9.tag, UInt<2>(0h2)
|
||||||
wire _cast_bundle_to_bits_expr_3: Ty4
|
wire _cast_bundle_to_bits_expr_3: Ty4
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -419,6 +419,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 38,
|
pc: 38,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -497,6 +498,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -1218,6 +1220,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 +1230,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 +1240,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 +1250,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 +1260,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 +1270,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 +1280,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 +1290,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 +1300,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 +1310,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 +1320,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 +1330,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 +1340,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 +1350,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 +1360,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 +1370,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 +1380,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 +1390,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 +1400,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 +1410,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 +1420,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 +1430,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 +1440,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 +1450,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 +1460,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 +1470,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 +1480,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 +1490,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 +1500,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 +1510,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 +1520,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 +1530,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 +1540,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 +1550,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 +1560,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 +1570,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 +1579,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 +1589,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 +1599,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 +1609,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 +1619,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 +1629,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 +1639,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 +1649,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 +1659,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 +1669,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 +1679,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 +1689,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 +1699,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 +1709,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 +1719,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 +1729,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 +1739,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,
|
||||||
},
|
},
|
||||||
|
|
@ -1706,5 +1761,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 5,
|
pc: 5,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -101,6 +102,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -155,6 +157,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 +166,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,
|
||||||
},
|
},
|
||||||
|
|
@ -184,5 +188,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 2,
|
pc: 2,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -77,6 +78,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -124,6 +126,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,
|
||||||
},
|
},
|
||||||
|
|
@ -137,5 +140,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +80,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 5,
|
pc: 5,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -106,6 +107,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -175,6 +177,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 +186,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,
|
||||||
},
|
},
|
||||||
|
|
@ -204,5 +208,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -123,59 +123,64 @@ 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: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -212,6 +217,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -328,6 +334,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 +343,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 +353,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 +363,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,
|
||||||
},
|
},
|
||||||
|
|
@ -377,5 +387,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -102,62 +102,67 @@ 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: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -193,6 +198,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -309,6 +315,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 +324,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 +334,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 +344,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,
|
||||||
},
|
},
|
||||||
|
|
@ -358,5 +368,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 4,
|
pc: 4,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -97,6 +98,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [],
|
base_targets: [],
|
||||||
uninitialized_ios: {},
|
uninitialized_ios: {},
|
||||||
|
|
@ -137,6 +139,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 +149,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,
|
||||||
},
|
},
|
||||||
|
|
@ -167,5 +171,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
752
crates/fayalite/tests/sim/expected/enum_with_simple_body.txt
Normal file
752
crates/fayalite/tests/sim/expected/enum_with_simple_body.txt
Normal file
|
|
@ -0,0 +1,752 @@
|
||||||
|
Simulation {
|
||||||
|
state: State {
|
||||||
|
insns: Insns {
|
||||||
|
state_layout: StateLayout {
|
||||||
|
ty: TypeLayout {
|
||||||
|
small_slots: StatePartLayout<SmallSlots> {
|
||||||
|
len: 1,
|
||||||
|
debug_data: [
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: Enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
..
|
||||||
|
},
|
||||||
|
big_slots: StatePartLayout<BigSlots> {
|
||||||
|
len: 33,
|
||||||
|
debug_data: [
|
||||||
|
SlotDebugData {
|
||||||
|
name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_in",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out",
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(UInt<8>),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: Bool,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: ".0",
|
||||||
|
ty: UInt<2>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: ".1",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<2>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(UInt<8>),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: Bool,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: ".0",
|
||||||
|
ty: UInt<2>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: ".1",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<2>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(UInt<8>),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: ".0",
|
||||||
|
ty: UInt<2>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: ".1",
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<2>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: UInt<10>,
|
||||||
|
},
|
||||||
|
SlotDebugData {
|
||||||
|
name: "",
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(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), // (0x2) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
value: 0x2,
|
||||||
|
},
|
||||||
|
1: Const {
|
||||||
|
dest: StatePartIndex<BigSlots>(27), // (0x2) SlotDebugData { name: "", ty: UInt<2> },
|
||||||
|
value: 0x2,
|
||||||
|
},
|
||||||
|
2: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(25), // (0x2) SlotDebugData { name: ".0", ty: UInt<2> },
|
||||||
|
src: StatePartIndex<BigSlots>(27), // (0x2) SlotDebugData { name: "", ty: UInt<2> },
|
||||||
|
},
|
||||||
|
3: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(26), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(1), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
4: Shl {
|
||||||
|
dest: StatePartIndex<BigSlots>(28), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
lhs: StatePartIndex<BigSlots>(26), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> },
|
||||||
|
rhs: 2,
|
||||||
|
},
|
||||||
|
5: Or {
|
||||||
|
dest: StatePartIndex<BigSlots>(29), // (0x386) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
lhs: StatePartIndex<BigSlots>(25), // (0x2) SlotDebugData { name: ".0", ty: UInt<2> },
|
||||||
|
rhs: StatePartIndex<BigSlots>(28), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
},
|
||||||
|
6: CastToUInt {
|
||||||
|
dest: StatePartIndex<BigSlots>(30), // (0x386) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
src: StatePartIndex<BigSlots>(29), // (0x386) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
dest_width: 10,
|
||||||
|
},
|
||||||
|
7: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(31), // (0x386) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
src: StatePartIndex<BigSlots>(30), // (0x386) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
},
|
||||||
|
8: Const {
|
||||||
|
dest: StatePartIndex<BigSlots>(20), // (0x1) SlotDebugData { name: "", ty: UInt<2> },
|
||||||
|
value: 0x1,
|
||||||
|
},
|
||||||
|
9: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(18), // (0x1) SlotDebugData { name: ".0", ty: UInt<2> },
|
||||||
|
src: StatePartIndex<BigSlots>(20), // (0x1) SlotDebugData { name: "", ty: UInt<2> },
|
||||||
|
},
|
||||||
|
10: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(19), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(1), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
11: Shl {
|
||||||
|
dest: StatePartIndex<BigSlots>(21), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
lhs: StatePartIndex<BigSlots>(19), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> },
|
||||||
|
rhs: 2,
|
||||||
|
},
|
||||||
|
12: Or {
|
||||||
|
dest: StatePartIndex<BigSlots>(22), // (0x385) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
lhs: StatePartIndex<BigSlots>(18), // (0x1) SlotDebugData { name: ".0", ty: UInt<2> },
|
||||||
|
rhs: StatePartIndex<BigSlots>(21), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
},
|
||||||
|
13: CastToUInt {
|
||||||
|
dest: StatePartIndex<BigSlots>(23), // (0x385) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
src: StatePartIndex<BigSlots>(22), // (0x385) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
dest_width: 10,
|
||||||
|
},
|
||||||
|
14: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(24), // (0x385) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
src: StatePartIndex<BigSlots>(23), // (0x385) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
},
|
||||||
|
15: Const {
|
||||||
|
dest: StatePartIndex<BigSlots>(16), // (0x1) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
value: 0x1,
|
||||||
|
},
|
||||||
|
16: CmpEq {
|
||||||
|
dest: StatePartIndex<BigSlots>(17), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
lhs: StatePartIndex<BigSlots>(0), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_in", ty: UInt<8> },
|
||||||
|
rhs: StatePartIndex<BigSlots>(16), // (0x1) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
17: Const {
|
||||||
|
dest: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
|
||||||
|
value: 0x0,
|
||||||
|
},
|
||||||
|
18: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(9), // (0x0) SlotDebugData { name: ".0", ty: UInt<2> },
|
||||||
|
src: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "", ty: UInt<2> },
|
||||||
|
},
|
||||||
|
19: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(10), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(1), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_in", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
20: Shl {
|
||||||
|
dest: StatePartIndex<BigSlots>(12), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
lhs: StatePartIndex<BigSlots>(10), // (0xe1) SlotDebugData { name: ".1", ty: UInt<8> },
|
||||||
|
rhs: 2,
|
||||||
|
},
|
||||||
|
21: Or {
|
||||||
|
dest: StatePartIndex<BigSlots>(13), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
lhs: StatePartIndex<BigSlots>(9), // (0x0) SlotDebugData { name: ".0", ty: UInt<2> },
|
||||||
|
rhs: StatePartIndex<BigSlots>(12), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
},
|
||||||
|
22: CastToUInt {
|
||||||
|
dest: StatePartIndex<BigSlots>(14), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
src: StatePartIndex<BigSlots>(13), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
dest_width: 10,
|
||||||
|
},
|
||||||
|
23: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(15), // (0x384) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
src: StatePartIndex<BigSlots>(14), // (0x384) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
},
|
||||||
|
24: Const {
|
||||||
|
dest: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
value: 0x0,
|
||||||
|
},
|
||||||
|
25: CmpEq {
|
||||||
|
dest: StatePartIndex<BigSlots>(8), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
lhs: StatePartIndex<BigSlots>(0), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_in", ty: UInt<8> },
|
||||||
|
rhs: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:7:1
|
||||||
|
26: BranchIfZero {
|
||||||
|
target: 28,
|
||||||
|
value: StatePartIndex<BigSlots>(8), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:8:1
|
||||||
|
27: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
src: StatePartIndex<BigSlots>(15), // (0x384) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:7:1
|
||||||
|
28: BranchIfNonZero {
|
||||||
|
target: 33,
|
||||||
|
value: StatePartIndex<BigSlots>(8), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:9:1
|
||||||
|
29: BranchIfZero {
|
||||||
|
target: 31,
|
||||||
|
value: StatePartIndex<BigSlots>(17), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:10:1
|
||||||
|
30: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
src: StatePartIndex<BigSlots>(24), // (0x385) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:9:1
|
||||||
|
31: BranchIfNonZero {
|
||||||
|
target: 33,
|
||||||
|
value: StatePartIndex<BigSlots>(17), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:11:1
|
||||||
|
32: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
src: StatePartIndex<BigSlots>(31), // (0x386) SlotDebugData { name: "", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:1:1
|
||||||
|
33: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(5), // (0x386) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
src: StatePartIndex<BigSlots>(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
},
|
||||||
|
34: SliceInt {
|
||||||
|
dest: StatePartIndex<BigSlots>(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(5), // (0x386) SlotDebugData { name: "", ty: UInt<10> },
|
||||||
|
start: 2,
|
||||||
|
len: 8,
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:6:1
|
||||||
|
35: AndBigWithSmallImmediate {
|
||||||
|
dest: StatePartIndex<SmallSlots>(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} },
|
||||||
|
lhs: StatePartIndex<BigSlots>(4), // (0x386) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::enum_out", ty: Enum {A(UInt<8>), B(UInt<8>), C(UInt<8>)} },
|
||||||
|
rhs: 0x3,
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:12:1
|
||||||
|
36: BranchIfSmallNeImmediate {
|
||||||
|
target: 39,
|
||||||
|
lhs: StatePartIndex<SmallSlots>(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} },
|
||||||
|
rhs: 0x0,
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:13:1
|
||||||
|
37: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(2), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:14:1
|
||||||
|
38: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(3), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:12:1
|
||||||
|
39: BranchIfSmallNeImmediate {
|
||||||
|
target: 42,
|
||||||
|
lhs: StatePartIndex<SmallSlots>(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} },
|
||||||
|
rhs: 0x1,
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:15:1
|
||||||
|
40: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(2), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(16), // (0x1) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:16:1
|
||||||
|
41: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(3), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:12:1
|
||||||
|
42: BranchIfSmallNeImmediate {
|
||||||
|
target: 45,
|
||||||
|
lhs: StatePartIndex<SmallSlots>(0), // (0x2 2) SlotDebugData { name: "", ty: Enum {A, B, C} },
|
||||||
|
rhs: 0x2,
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:17:1
|
||||||
|
43: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(2), // (0x2) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::which_out", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(32), // (0x2) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:18:1
|
||||||
|
44: Copy {
|
||||||
|
dest: StatePartIndex<BigSlots>(3), // (0xe1) SlotDebugData { name: "InstantiatedModule(enum_with_simple_body: enum_with_simple_body).enum_with_simple_body::data_out", ty: UInt<8> },
|
||||||
|
src: StatePartIndex<BigSlots>(6), // (0xe1) SlotDebugData { name: "", ty: UInt<8> },
|
||||||
|
},
|
||||||
|
// at: module-XXXXXXXXXX.rs:1:1
|
||||||
|
45: Return,
|
||||||
|
],
|
||||||
|
..
|
||||||
|
},
|
||||||
|
pc: 45,
|
||||||
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
|
memories: StatePart {
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
small_slots: StatePart {
|
||||||
|
value: [
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
big_slots: StatePart {
|
||||||
|
value: [
|
||||||
|
2,
|
||||||
|
225,
|
||||||
|
2 (modified),
|
||||||
|
225 (modified),
|
||||||
|
902,
|
||||||
|
902,
|
||||||
|
225,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
225,
|
||||||
|
0,
|
||||||
|
900,
|
||||||
|
900,
|
||||||
|
900,
|
||||||
|
900,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
225,
|
||||||
|
1,
|
||||||
|
900,
|
||||||
|
901,
|
||||||
|
901,
|
||||||
|
901,
|
||||||
|
2,
|
||||||
|
225,
|
||||||
|
2,
|
||||||
|
900,
|
||||||
|
902,
|
||||||
|
902,
|
||||||
|
902,
|
||||||
|
2,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sim_only_slots: StatePart {
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
io: Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
},
|
||||||
|
global_io: {},
|
||||||
|
main_module: SimulationModuleState {
|
||||||
|
base_targets: [
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.which_in,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.data_in,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.which_out,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.data_out,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.enum_out,
|
||||||
|
],
|
||||||
|
uninitialized_ios: {},
|
||||||
|
io_targets: {
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.data_in,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.data_out,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.enum_out,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.which_in,
|
||||||
|
Instance {
|
||||||
|
name: <simulator>::enum_with_simple_body,
|
||||||
|
instantiated: Module {
|
||||||
|
name: enum_with_simple_body,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
}.which_out,
|
||||||
|
},
|
||||||
|
did_initial_settle: true,
|
||||||
|
clocks_for_past: {},
|
||||||
|
},
|
||||||
|
extern_modules: [],
|
||||||
|
trace_decls: TraceModule {
|
||||||
|
name: "enum_with_simple_body",
|
||||||
|
children: [
|
||||||
|
TraceModuleIO {
|
||||||
|
name: "which_in",
|
||||||
|
child: TraceUInt {
|
||||||
|
location: TraceScalarId(0),
|
||||||
|
name: "which_in",
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Source,
|
||||||
|
},
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Source,
|
||||||
|
},
|
||||||
|
TraceModuleIO {
|
||||||
|
name: "data_in",
|
||||||
|
child: TraceUInt {
|
||||||
|
location: TraceScalarId(1),
|
||||||
|
name: "data_in",
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Source,
|
||||||
|
},
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Source,
|
||||||
|
},
|
||||||
|
TraceModuleIO {
|
||||||
|
name: "which_out",
|
||||||
|
child: TraceUInt {
|
||||||
|
location: TraceScalarId(2),
|
||||||
|
name: "which_out",
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
TraceModuleIO {
|
||||||
|
name: "data_out",
|
||||||
|
child: TraceUInt {
|
||||||
|
location: TraceScalarId(3),
|
||||||
|
name: "data_out",
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
TraceModuleIO {
|
||||||
|
name: "enum_out",
|
||||||
|
child: TraceEnumWithFields {
|
||||||
|
name: "enum_out",
|
||||||
|
discriminant: TraceEnumDiscriminant {
|
||||||
|
location: TraceScalarId(4),
|
||||||
|
name: "$tag",
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(UInt<8>),
|
||||||
|
},
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
non_empty_fields: [
|
||||||
|
TraceUInt {
|
||||||
|
location: TraceScalarId(5),
|
||||||
|
name: "A",
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Source,
|
||||||
|
},
|
||||||
|
TraceUInt {
|
||||||
|
location: TraceScalarId(6),
|
||||||
|
name: "B",
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Source,
|
||||||
|
},
|
||||||
|
TraceUInt {
|
||||||
|
location: TraceScalarId(7),
|
||||||
|
name: "C",
|
||||||
|
ty: UInt<8>,
|
||||||
|
flow: Source,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(UInt<8>),
|
||||||
|
},
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(UInt<8>),
|
||||||
|
},
|
||||||
|
flow: Sink,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
traces: [
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(0),
|
||||||
|
kind: BigUInt {
|
||||||
|
index: StatePartIndex<BigSlots>(0),
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0x02,
|
||||||
|
last_state: 0x02,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(1),
|
||||||
|
kind: BigUInt {
|
||||||
|
index: StatePartIndex<BigSlots>(1),
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0xe1,
|
||||||
|
last_state: 0xb4,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(2),
|
||||||
|
kind: BigUInt {
|
||||||
|
index: StatePartIndex<BigSlots>(2),
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0x02,
|
||||||
|
last_state: 0x02,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(3),
|
||||||
|
kind: BigUInt {
|
||||||
|
index: StatePartIndex<BigSlots>(3),
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0xe1,
|
||||||
|
last_state: 0xb4,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(4),
|
||||||
|
kind: EnumDiscriminant {
|
||||||
|
index: StatePartIndex<SmallSlots>(0),
|
||||||
|
ty: Enum {
|
||||||
|
A(UInt<8>),
|
||||||
|
B(UInt<8>),
|
||||||
|
C(UInt<8>),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0x2,
|
||||||
|
last_state: 0x2,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(5),
|
||||||
|
kind: BigUInt {
|
||||||
|
index: StatePartIndex<BigSlots>(6),
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0xe1,
|
||||||
|
last_state: 0xb4,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(6),
|
||||||
|
kind: BigUInt {
|
||||||
|
index: StatePartIndex<BigSlots>(6),
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0xe1,
|
||||||
|
last_state: 0xb4,
|
||||||
|
},
|
||||||
|
SimTrace {
|
||||||
|
id: TraceScalarId(7),
|
||||||
|
kind: BigUInt {
|
||||||
|
index: StatePartIndex<BigSlots>(6),
|
||||||
|
ty: UInt<8>,
|
||||||
|
},
|
||||||
|
maybe_changed: true,
|
||||||
|
state: 0xe1,
|
||||||
|
last_state: 0xb4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
trace_memories: {},
|
||||||
|
trace_writers: [
|
||||||
|
Running(
|
||||||
|
VcdWriter {
|
||||||
|
finished_init: true,
|
||||||
|
timescale: 1 ps,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
clocks_triggered: [],
|
||||||
|
event_queue: EventQueue(EventQueueData {
|
||||||
|
instant: 18 μs,
|
||||||
|
events: {},
|
||||||
|
}),
|
||||||
|
waiting_sensitivity_sets_by_address: {},
|
||||||
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
|
..
|
||||||
|
}
|
||||||
133
crates/fayalite/tests/sim/expected/enum_with_simple_body.vcd
Normal file
133
crates/fayalite/tests/sim/expected/enum_with_simple_body.vcd
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
$timescale 1 ps $end
|
||||||
|
$scope module enum_with_simple_body $end
|
||||||
|
$var wire 8 J&-ne which_in $end
|
||||||
|
$var wire 8 \7mo/ data_in $end
|
||||||
|
$var wire 8 ,`>ir which_out $end
|
||||||
|
$var wire 8 0_gMP data_out $end
|
||||||
|
$scope struct enum_out $end
|
||||||
|
$var string 1 kFH/w \$tag $end
|
||||||
|
$var wire 8 |EI_= A $end
|
||||||
|
$var wire 8 !pRd4 B $end
|
||||||
|
$var wire 8 &RAbd C $end
|
||||||
|
$upscope $end
|
||||||
|
$upscope $end
|
||||||
|
$enddefinitions $end
|
||||||
|
$dumpvars
|
||||||
|
b0 J&-ne
|
||||||
|
b0 \7mo/
|
||||||
|
b0 ,`>ir
|
||||||
|
b0 0_gMP
|
||||||
|
sA\x20(0) kFH/w
|
||||||
|
b0 |EI_=
|
||||||
|
b0 !pRd4
|
||||||
|
b0 &RAbd
|
||||||
|
$end
|
||||||
|
#1000000
|
||||||
|
b101101 \7mo/
|
||||||
|
b101101 0_gMP
|
||||||
|
b101101 |EI_=
|
||||||
|
b101101 !pRd4
|
||||||
|
b101101 &RAbd
|
||||||
|
#2000000
|
||||||
|
b1011010 \7mo/
|
||||||
|
b1011010 0_gMP
|
||||||
|
b1011010 |EI_=
|
||||||
|
b1011010 !pRd4
|
||||||
|
b1011010 &RAbd
|
||||||
|
#3000000
|
||||||
|
b10000111 \7mo/
|
||||||
|
b10000111 0_gMP
|
||||||
|
b10000111 |EI_=
|
||||||
|
b10000111 !pRd4
|
||||||
|
b10000111 &RAbd
|
||||||
|
#4000000
|
||||||
|
b10110100 \7mo/
|
||||||
|
b10110100 0_gMP
|
||||||
|
b10110100 |EI_=
|
||||||
|
b10110100 !pRd4
|
||||||
|
b10110100 &RAbd
|
||||||
|
#5000000
|
||||||
|
b11100001 \7mo/
|
||||||
|
b11100001 0_gMP
|
||||||
|
b11100001 |EI_=
|
||||||
|
b11100001 !pRd4
|
||||||
|
b11100001 &RAbd
|
||||||
|
#6000000
|
||||||
|
b1 J&-ne
|
||||||
|
b0 \7mo/
|
||||||
|
b1 ,`>ir
|
||||||
|
b0 0_gMP
|
||||||
|
sB\x20(1) kFH/w
|
||||||
|
b0 |EI_=
|
||||||
|
b0 !pRd4
|
||||||
|
b0 &RAbd
|
||||||
|
#7000000
|
||||||
|
b101101 \7mo/
|
||||||
|
b101101 0_gMP
|
||||||
|
b101101 |EI_=
|
||||||
|
b101101 !pRd4
|
||||||
|
b101101 &RAbd
|
||||||
|
#8000000
|
||||||
|
b1011010 \7mo/
|
||||||
|
b1011010 0_gMP
|
||||||
|
b1011010 |EI_=
|
||||||
|
b1011010 !pRd4
|
||||||
|
b1011010 &RAbd
|
||||||
|
#9000000
|
||||||
|
b10000111 \7mo/
|
||||||
|
b10000111 0_gMP
|
||||||
|
b10000111 |EI_=
|
||||||
|
b10000111 !pRd4
|
||||||
|
b10000111 &RAbd
|
||||||
|
#10000000
|
||||||
|
b10110100 \7mo/
|
||||||
|
b10110100 0_gMP
|
||||||
|
b10110100 |EI_=
|
||||||
|
b10110100 !pRd4
|
||||||
|
b10110100 &RAbd
|
||||||
|
#11000000
|
||||||
|
b11100001 \7mo/
|
||||||
|
b11100001 0_gMP
|
||||||
|
b11100001 |EI_=
|
||||||
|
b11100001 !pRd4
|
||||||
|
b11100001 &RAbd
|
||||||
|
#12000000
|
||||||
|
b10 J&-ne
|
||||||
|
b0 \7mo/
|
||||||
|
b10 ,`>ir
|
||||||
|
b0 0_gMP
|
||||||
|
sC\x20(2) kFH/w
|
||||||
|
b0 |EI_=
|
||||||
|
b0 !pRd4
|
||||||
|
b0 &RAbd
|
||||||
|
#13000000
|
||||||
|
b101101 \7mo/
|
||||||
|
b101101 0_gMP
|
||||||
|
b101101 |EI_=
|
||||||
|
b101101 !pRd4
|
||||||
|
b101101 &RAbd
|
||||||
|
#14000000
|
||||||
|
b1011010 \7mo/
|
||||||
|
b1011010 0_gMP
|
||||||
|
b1011010 |EI_=
|
||||||
|
b1011010 !pRd4
|
||||||
|
b1011010 &RAbd
|
||||||
|
#15000000
|
||||||
|
b10000111 \7mo/
|
||||||
|
b10000111 0_gMP
|
||||||
|
b10000111 |EI_=
|
||||||
|
b10000111 !pRd4
|
||||||
|
b10000111 &RAbd
|
||||||
|
#16000000
|
||||||
|
b10110100 \7mo/
|
||||||
|
b10110100 0_gMP
|
||||||
|
b10110100 |EI_=
|
||||||
|
b10110100 !pRd4
|
||||||
|
b10110100 &RAbd
|
||||||
|
#17000000
|
||||||
|
b11100001 \7mo/
|
||||||
|
b11100001 0_gMP
|
||||||
|
b11100001 |EI_=
|
||||||
|
b11100001 !pRd4
|
||||||
|
b11100001 &RAbd
|
||||||
|
#18000000
|
||||||
|
|
@ -1012,174 +1012,179 @@ 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: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -1320,6 +1325,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -1742,6 +1748,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 +1757,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 +1766,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 +1776,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 +1786,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 +1796,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 +1806,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 +1819,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 +1829,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 +1838,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 +1851,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 +1861,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 +1870,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 +1884,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 +1894,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 +1903,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 +1913,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 +1923,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 +1933,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,
|
||||||
},
|
},
|
||||||
|
|
@ -1932,5 +1957,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 0,
|
pc: 0,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -67,6 +68,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -221,6 +223,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 +232,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,
|
||||||
},
|
},
|
||||||
|
|
@ -259,5 +263,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 0,
|
pc: 0,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -57,7 +58,7 @@ Simulation {
|
||||||
big_slots: StatePart {
|
big_slots: StatePart {
|
||||||
value: [
|
value: [
|
||||||
0,
|
0,
|
||||||
1,
|
1 (modified),
|
||||||
101,
|
101,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -72,6 +73,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -280,6 +282,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 +291,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 +301,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,
|
||||||
},
|
},
|
||||||
|
|
@ -413,5 +418,6 @@ Simulation {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
712
crates/fayalite/tests/sim/expected/last_connect.txt
Normal file
712
crates/fayalite/tests/sim/expected/last_connect.txt
Normal file
|
|
@ -0,0 +1,712 @@
|
||||||
|
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: [],
|
||||||
|
assert_failed_log: [],
|
||||||
|
memories: StatePart {
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
small_slots: StatePart {
|
||||||
|
value: [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
big_slots: StatePart {
|
||||||
|
value: [
|
||||||
|
31,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
31,
|
||||||
|
15,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
7 (modified),
|
||||||
|
7,
|
||||||
|
3,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
7,
|
||||||
|
4,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sim_only_slots: StatePart {
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
io: Instance {
|
||||||
|
name: <simulator>::last_connect,
|
||||||
|
instantiated: Module {
|
||||||
|
name: last_connect,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
},
|
||||||
|
global_io: {},
|
||||||
|
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: {},
|
||||||
|
asserts: [],
|
||||||
|
..
|
||||||
|
}
|
||||||
104
crates/fayalite/tests/sim/expected/last_connect.vcd
Normal file
104
crates/fayalite/tests/sim/expected/last_connect.vcd
Normal 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
|
|
@ -494,6 +494,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 41,
|
pc: 41,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [
|
value: [
|
||||||
MemoryData {
|
MemoryData {
|
||||||
|
|
@ -579,6 +580,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -1168,6 +1170,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 +1179,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 +1188,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 +1198,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 +1208,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 +1218,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 +1227,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 +1236,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 +1246,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 +1256,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 +1265,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 +1274,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 +1284,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 +1293,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 +1302,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 +1312,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 +1322,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 +1332,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 +1341,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 +1350,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 +1360,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 +1370,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 +1379,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 +1388,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,
|
||||||
},
|
},
|
||||||
|
|
@ -1626,5 +1652,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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/;"
|
||||||
|
|
|
||||||
|
|
@ -526,6 +526,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 52,
|
pc: 52,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [
|
value: [
|
||||||
MemoryData {
|
MemoryData {
|
||||||
|
|
@ -607,6 +608,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -943,6 +945,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 +954,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 +963,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 +973,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 +982,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 +992,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 +1001,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 +1011,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 +1020,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 +1029,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 +1042,7 @@ Simulation {
|
||||||
HdlSome(Bool),
|
HdlSome(Bool),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
maybe_changed: true,
|
||||||
state: 0x0,
|
state: 0x0,
|
||||||
last_state: 0x0,
|
last_state: 0x0,
|
||||||
},
|
},
|
||||||
|
|
@ -1038,6 +1051,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 +1060,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 +1073,7 @@ Simulation {
|
||||||
HdlSome(Bool),
|
HdlSome(Bool),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
maybe_changed: true,
|
||||||
state: 0x0,
|
state: 0x0,
|
||||||
last_state: 0x0,
|
last_state: 0x0,
|
||||||
},
|
},
|
||||||
|
|
@ -1066,6 +1082,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 +1091,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,
|
||||||
},
|
},
|
||||||
|
|
@ -1269,5 +1287,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1336,6 +1336,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 129,
|
pc: 129,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [
|
value: [
|
||||||
MemoryData {
|
MemoryData {
|
||||||
|
|
@ -1495,6 +1496,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -2391,6 +2393,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 +2402,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 +2411,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 +2421,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 +2431,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 +2441,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 +2451,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 +2461,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 +2471,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 +2481,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 +2491,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 +2501,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 +2510,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 +2519,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 +2529,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 +2539,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 +2549,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 +2559,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 +2569,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 +2579,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 +2589,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 +2599,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 +2608,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 +2617,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 +2626,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 +2635,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 +2644,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 +2653,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 +2662,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 +2671,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 +2681,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 +2690,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 +2699,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 +2709,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 +2719,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 +2729,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 +2739,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 +2749,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 +2759,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 +2769,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 +2779,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 +2789,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 +2798,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 +2807,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 +2817,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 +2827,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 +2837,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 +2847,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 +2857,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 +2867,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 +2877,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 +2887,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 +2896,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 +2905,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 +2914,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 +2923,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 +2932,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 +2941,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 +2950,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 +2959,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,
|
||||||
},
|
},
|
||||||
|
|
@ -3285,5 +3347,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -187,6 +187,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 17,
|
pc: 17,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
|
@ -225,6 +226,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -445,6 +447,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 +457,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 +467,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 +477,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 +487,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 +497,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 +507,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 +517,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 +527,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 +537,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 +547,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 +557,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,
|
||||||
},
|
},
|
||||||
|
|
@ -565,5 +579,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ Simulation {
|
||||||
},
|
},
|
||||||
pc: 16,
|
pc: 16,
|
||||||
memory_write_log: [],
|
memory_write_log: [],
|
||||||
|
assert_failed_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [
|
value: [
|
||||||
MemoryData {
|
MemoryData {
|
||||||
|
|
@ -215,6 +216,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
global_io: {},
|
||||||
main_module: SimulationModuleState {
|
main_module: SimulationModuleState {
|
||||||
base_targets: [
|
base_targets: [
|
||||||
Instance {
|
Instance {
|
||||||
|
|
@ -373,6 +375,7 @@ Simulation {
|
||||||
["a","b"],
|
["a","b"],
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
maybe_changed: true,
|
||||||
state: PhantomConst,
|
state: PhantomConst,
|
||||||
last_state: PhantomConst,
|
last_state: PhantomConst,
|
||||||
},
|
},
|
||||||
|
|
@ -383,6 +386,7 @@ Simulation {
|
||||||
["a","b"],
|
["a","b"],
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
maybe_changed: true,
|
||||||
state: PhantomConst,
|
state: PhantomConst,
|
||||||
last_state: PhantomConst,
|
last_state: PhantomConst,
|
||||||
},
|
},
|
||||||
|
|
@ -392,6 +396,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 +405,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 +414,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 +425,7 @@ Simulation {
|
||||||
"mem_element",
|
"mem_element",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
maybe_changed: true,
|
||||||
state: PhantomConst,
|
state: PhantomConst,
|
||||||
last_state: PhantomConst,
|
last_state: PhantomConst,
|
||||||
},
|
},
|
||||||
|
|
@ -521,5 +529,6 @@ Simulation {
|
||||||
}),
|
}),
|
||||||
waiting_sensitivity_sets_by_address: {},
|
waiting_sensitivity_sets_by_address: {},
|
||||||
waiting_sensitivity_sets_by_compiled_value: {},
|
waiting_sensitivity_sets_by_compiled_value: {},
|
||||||
|
asserts: [],
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
2167
crates/fayalite/tests/sim/expected/queue_1_false_false.txt
Normal file
2167
crates/fayalite/tests/sim/expected/queue_1_false_false.txt
Normal file
File diff suppressed because it is too large
Load diff
1916
crates/fayalite/tests/sim/expected/queue_1_false_false.vcd
Normal file
1916
crates/fayalite/tests/sim/expected/queue_1_false_false.vcd
Normal file
File diff suppressed because it is too large
Load diff
2146
crates/fayalite/tests/sim/expected/queue_1_false_true.txt
Normal file
2146
crates/fayalite/tests/sim/expected/queue_1_false_true.txt
Normal file
File diff suppressed because it is too large
Load diff
1836
crates/fayalite/tests/sim/expected/queue_1_false_true.vcd
Normal file
1836
crates/fayalite/tests/sim/expected/queue_1_false_true.vcd
Normal file
File diff suppressed because it is too large
Load diff
2177
crates/fayalite/tests/sim/expected/queue_1_true_false.txt
Normal file
2177
crates/fayalite/tests/sim/expected/queue_1_true_false.txt
Normal file
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
Loading…
Add table
Add a link
Reference in a new issue