Compare commits

..

No commits in common. "master" and "formal_memories" have entirely different histories.

71 changed files with 293 additions and 41235 deletions

View file

@ -38,7 +38,7 @@ jobs:
z3 \ z3 \
zlib1g-dev zlib1g-dev
- run: | - run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.82.0 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.80.1
source "$HOME/.cargo/env" source "$HOME/.cargo/env"
echo "$PATH" >> "$GITHUB_PATH" echo "$PATH" >> "$GITHUB_PATH"
- uses: https://code.forgejo.org/actions/cache/restore@v3 - uses: https://code.forgejo.org/actions/cache/restore@v3
@ -57,5 +57,4 @@ jobs:
save-if: ${{ github.ref == 'refs/heads/master' }} save-if: ${{ github.ref == 'refs/heads/master' }}
- 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 doc --features=unstable-doc - run: cargo doc --features=unstable-doc

48
Cargo.lock generated
View file

@ -301,7 +301,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]] [[package]]
name = "fayalite" name = "fayalite"
version = "0.3.0" version = "0.2.1"
dependencies = [ dependencies = [
"bitvec", "bitvec",
"blake3", "blake3",
@ -315,25 +315,23 @@ dependencies = [
"num-bigint", "num-bigint",
"num-traits", "num-traits",
"os_pipe", "os_pipe",
"petgraph",
"serde", "serde",
"serde_json", "serde_json",
"tempfile", "tempfile",
"trybuild", "trybuild",
"vec_map",
"which", "which",
] ]
[[package]] [[package]]
name = "fayalite-proc-macros" name = "fayalite-proc-macros"
version = "0.3.0" version = "0.2.1"
dependencies = [ dependencies = [
"fayalite-proc-macros-impl", "fayalite-proc-macros-impl",
] ]
[[package]] [[package]]
name = "fayalite-proc-macros-impl" name = "fayalite-proc-macros-impl"
version = "0.3.0" version = "0.2.1"
dependencies = [ dependencies = [
"base16ct", "base16ct",
"num-bigint", "num-bigint",
@ -347,7 +345,7 @@ dependencies = [
[[package]] [[package]]
name = "fayalite-visit-gen" name = "fayalite-visit-gen"
version = "0.3.0" version = "0.2.1"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"prettyplease", "prettyplease",
@ -359,12 +357,6 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "fixedbitset"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]] [[package]]
name = "funty" name = "funty"
version = "2.0.0" version = "2.0.0"
@ -431,9 +423,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.5.0" version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
@ -480,10 +472,11 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.6" version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [ dependencies = [
"autocfg",
"num-integer", "num-integer",
"num-traits", "num-traits",
] ]
@ -522,15 +515,6 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "petgraph"
version = "0.6.5"
source = "git+https://github.com/programmerjake/petgraph.git?rev=258ea8071209a924b73fe96f9f87a3b7b45cbc9f#258ea8071209a924b73fe96f9f87a3b7b45cbc9f"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]] [[package]]
name = "prettyplease" name = "prettyplease"
version = "0.2.20" version = "0.2.20"
@ -543,9 +527,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.92" version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -647,9 +631,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.93" version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -736,12 +720,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"

View file

@ -5,18 +5,18 @@ resolver = "2"
members = ["crates/*"] members = ["crates/*"]
[workspace.package] [workspace.package]
version = "0.3.0" version = "0.2.1"
license = "LGPL-3.0-or-later" license = "LGPL-3.0-or-later"
edition = "2021" edition = "2021"
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.82.0" rust-version = "1.80.1"
[workspace.dependencies] [workspace.dependencies]
fayalite-proc-macros = { version = "=0.3.0", path = "crates/fayalite-proc-macros" } fayalite-proc-macros = { version = "=0.2.1", path = "crates/fayalite-proc-macros" }
fayalite-proc-macros-impl = { version = "=0.3.0", path = "crates/fayalite-proc-macros-impl" } fayalite-proc-macros-impl = { version = "=0.2.1", path = "crates/fayalite-proc-macros-impl" }
fayalite-visit-gen = { version = "=0.3.0", path = "crates/fayalite-visit-gen" } fayalite-visit-gen = { version = "=0.2.1", path = "crates/fayalite-visit-gen" }
base16ct = "0.2.0" base16ct = "0.2.0"
bitvec = { version = "1.0.1", features = ["serde"] } bitvec = { version = "1.0.1", features = ["serde"] }
blake3 = { version = "1.5.4", features = ["serde"] } blake3 = { version = "1.5.4", features = ["serde"] }
@ -24,22 +24,19 @@ clap = { version = "4.5.9", features = ["derive", "env", "string"] }
ctor = "0.2.8" ctor = "0.2.8"
eyre = "0.6.12" eyre = "0.6.12"
hashbrown = "0.14.3" hashbrown = "0.14.3"
indexmap = { version = "2.5.0", features = ["serde"] } indexmap = { version = "2.2.6", features = ["serde"] }
jobslot = "0.2.19" jobslot = "0.2.19"
num-bigint = "0.4.6" num-bigint = "0.4.4"
num-traits = "0.2.16" num-traits = "0.2.16"
os_pipe = "1.2.1" os_pipe = "1.2.1"
# TODO: switch back to crates.io once petgraph accepts PR #684 and releases a new version
petgraph = { git = "https://github.com/programmerjake/petgraph.git", rev = "258ea8071209a924b73fe96f9f87a3b7b45cbc9f" }
prettyplease = "0.2.20" prettyplease = "0.2.20"
proc-macro2 = "1.0.83" proc-macro2 = "1.0.83"
quote = "1.0.36" quote = "1.0.36"
serde = { version = "1.0.202", features = ["derive"] } serde = { version = "1.0.202", features = ["derive"] }
serde_json = { version = "1.0.117", features = ["preserve_order"] } serde_json = { version = "1.0.117", features = ["preserve_order"] }
sha2 = "0.10.8" sha2 = "0.10.8"
syn = { version = "2.0.93", features = ["full", "fold", "visit", "extra-traits"] } syn = { version = "2.0.66", features = ["full", "fold", "visit", "extra-traits"] }
tempfile = "3.10.1" tempfile = "3.10.1"
thiserror = "1.0.61" thiserror = "1.0.61"
trybuild = "1.0" trybuild = "1.0"
vec_map = "0.8.2"
which = "6.0.1" which = "6.0.1"

View file

@ -83,7 +83,6 @@ impl ParsedBundle {
custom_bounds, custom_bounds,
no_static: _, no_static: _,
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq: _,
} = options.body; } = options.body;
let mut fields = match fields { let mut fields = match fields {
syn::Fields::Named(fields) => fields, syn::Fields::Named(fields) => fields,
@ -438,7 +437,6 @@ impl ToTokens for ParsedBundle {
custom_bounds: _, custom_bounds: _,
no_static, no_static,
no_runtime_generics, no_runtime_generics,
cmp_eq,
} = &options.body; } = &options.body;
let target = get_target(target, ident); let target = get_target(target, ident);
let mut item_attrs = attrs.clone(); let mut item_attrs = attrs.clone();
@ -767,69 +765,6 @@ impl ToTokens for ParsedBundle {
} }
} }
.to_tokens(tokens); .to_tokens(tokens);
if let Some((cmp_eq,)) = cmp_eq {
let mut where_clause =
Generics::from(generics)
.where_clause
.unwrap_or_else(|| syn::WhereClause {
where_token: Token![where](span),
predicates: Punctuated::new(),
});
let mut fields_cmp_eq = vec![];
let mut fields_cmp_ne = vec![];
for field in fields.named() {
let field_ident = field.ident();
let field_ty = field.ty();
where_clause
.predicates
.push(parse_quote_spanned! {cmp_eq.span=>
#field_ty: ::fayalite::expr::ops::ExprPartialEq<#field_ty>
});
fields_cmp_eq.push(quote_spanned! {span=>
::fayalite::expr::ops::ExprPartialEq::cmp_eq(__lhs.#field_ident, __rhs.#field_ident)
});
fields_cmp_ne.push(quote_spanned! {span=>
::fayalite::expr::ops::ExprPartialEq::cmp_ne(__lhs.#field_ident, __rhs.#field_ident)
});
}
let cmp_eq_body;
let cmp_ne_body;
if fields_len == 0 {
cmp_eq_body = quote_spanned! {span=>
::fayalite::expr::ToExpr::to_expr(&true)
};
cmp_ne_body = quote_spanned! {span=>
::fayalite::expr::ToExpr::to_expr(&false)
};
} else {
cmp_eq_body = quote_spanned! {span=>
#(#fields_cmp_eq)&*
};
cmp_ne_body = quote_spanned! {span=>
#(#fields_cmp_ne)|*
};
};
quote_spanned! {span=>
#[automatically_derived]
impl #impl_generics ::fayalite::expr::ops::ExprPartialEq<Self> for #target #type_generics
#where_clause
{
fn cmp_eq(
__lhs: ::fayalite::expr::Expr<Self>,
__rhs: ::fayalite::expr::Expr<Self>,
) -> ::fayalite::expr::Expr<::fayalite::int::Bool> {
#cmp_eq_body
}
fn cmp_ne(
__lhs: ::fayalite::expr::Expr<Self>,
__rhs: ::fayalite::expr::Expr<Self>,
) -> ::fayalite::expr::Expr<::fayalite::int::Bool> {
#cmp_ne_body
}
}
}
.to_tokens(tokens);
}
if let (None, MaybeParsed::Parsed(generics)) = (no_static, &self.generics) { if let (None, MaybeParsed::Parsed(generics)) = (no_static, &self.generics) {
let static_generics = generics.clone().for_static_type(); let static_generics = generics.clone().for_static_type();
let (static_impl_generics, static_type_generics, static_where_clause) = let (static_impl_generics, static_type_generics, static_where_clause) =

View file

@ -155,11 +155,7 @@ impl ParsedEnum {
custom_bounds, custom_bounds,
no_static: _, no_static: _,
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq,
} = options.body; } = options.body;
if let Some((cmp_eq,)) = cmp_eq {
errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for 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");
@ -215,7 +211,6 @@ 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
} = &options.body; } = &options.body;
let target = get_target(target, ident); let target = get_target(target, ident);
let mut struct_attrs = attrs.clone(); let mut struct_attrs = attrs.clone();

View file

@ -49,14 +49,10 @@ impl ParsedTypeAlias {
custom_bounds, custom_bounds,
no_static, no_static,
no_runtime_generics: _, no_runtime_generics: _,
cmp_eq,
} = 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");
} }
if let Some((cmp_eq,)) = cmp_eq {
errors.error(cmp_eq, "cmp_eq 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)) {
@ -99,7 +95,6 @@ impl ToTokens for ParsedTypeAlias {
custom_bounds: _, custom_bounds: _,
no_static: _, no_static: _,
no_runtime_generics, no_runtime_generics,
cmp_eq: _,
} = &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();

View file

@ -26,7 +26,6 @@ crate::options! {
CustomBounds(custom_bounds), CustomBounds(custom_bounds),
NoStatic(no_static), NoStatic(no_static),
NoRuntimeGenerics(no_runtime_generics), NoRuntimeGenerics(no_runtime_generics),
CmpEq(cmp_eq),
} }
} }
@ -2045,7 +2044,6 @@ pub(crate) mod known_items {
impl_known_item!(::fayalite::int::Size); impl_known_item!(::fayalite::int::Size);
impl_known_item!(::fayalite::int::UInt); impl_known_item!(::fayalite::int::UInt);
impl_known_item!(::fayalite::int::UIntType); impl_known_item!(::fayalite::int::UIntType);
impl_known_item!(::fayalite::reset::ResetType);
impl_known_item!(::fayalite::ty::CanonicalType); impl_known_item!(::fayalite::ty::CanonicalType);
impl_known_item!(::fayalite::ty::StaticType); impl_known_item!(::fayalite::ty::StaticType);
impl_known_item!(::fayalite::ty::Type); impl_known_item!(::fayalite::ty::Type);
@ -2070,16 +2068,11 @@ macro_rules! impl_bounds {
$( $(
$Variant:ident, $Variant:ident,
)* )*
$(
#[unknown]
$Unknown:ident,
)?
} }
) => { ) => {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
$vis enum $enum_type { $vis enum $enum_type {
$($Variant(known_items::$Variant),)* $($Variant(known_items::$Variant),)*
$($Unknown(syn::TypeParamBound),)?
} }
$(impl From<known_items::$Variant> for $enum_type { $(impl From<known_items::$Variant> for $enum_type {
@ -2092,54 +2085,28 @@ macro_rules! impl_bounds {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
match self { match self {
$(Self::$Variant(v) => v.to_tokens(tokens),)* $(Self::$Variant(v) => v.to_tokens(tokens),)*
$(Self::$Unknown(v) => v.to_tokens(tokens),)?
} }
} }
} }
impl $enum_type { impl $enum_type {
$vis fn parse_path(path: Path) -> Result<Self, Path> { $vis fn parse_path(path: Path) -> Result<Self, Path> {
#![allow(unreachable_code)]
$(let path = match known_items::$Variant::parse_path(path) { $(let path = match known_items::$Variant::parse_path(path) {
Ok(v) => return Ok(Self::$Variant(v)), Ok(v) => return Ok(Self::$Variant(v)),
Err(path) => path, Err(path) => path,
};)* };)*
$(return Ok(Self::$Unknown(syn::TraitBound {
paren_token: None,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path,
}.into()));)?
Err(path) Err(path)
} }
$vis fn parse_type_param_bound(mut type_param_bound: syn::TypeParamBound) -> Result<Self, syn::TypeParamBound> {
#![allow(unreachable_code)]
if let syn::TypeParamBound::Trait(mut trait_bound) = type_param_bound {
if let syn::TraitBound {
paren_token: _,
modifier: syn::TraitBoundModifier::None,
lifetimes: None,
path: _,
} = trait_bound {
match Self::parse_path(trait_bound.path) {
Ok(retval) => return Ok(retval),
Err(path) => trait_bound.path = path,
}
}
type_param_bound = trait_bound.into();
}
$(return Ok(Self::$Unknown(type_param_bound));)?
Err(type_param_bound)
}
} }
impl Parse for $enum_type { impl Parse for $enum_type {
fn parse(input: ParseStream) -> syn::Result<Self> { fn parse(input: ParseStream) -> syn::Result<Self> {
Self::parse_type_param_bound(input.parse()?) Self::parse_path(Path::parse_mod_style(input)?).map_err(|path| {
.map_err(|type_param_bound| syn::Error::new_spanned( syn::Error::new_spanned(
type_param_bound, path,
format_args!("expected one of: {}", [$(stringify!($Variant)),*].join(", ")), format_args!("expected one of: {}", [$(stringify!($Variant)),*].join(", ")),
)) )
})
} }
} }
@ -2147,7 +2114,6 @@ macro_rules! impl_bounds {
#[allow(non_snake_case)] #[allow(non_snake_case)]
$vis struct $struct_type { $vis struct $struct_type {
$($vis $Variant: Option<known_items::$Variant>,)* $($vis $Variant: Option<known_items::$Variant>,)*
$($vis $Unknown: Vec<syn::TypeParamBound>,)?
} }
impl ToTokens for $struct_type { impl ToTokens for $struct_type {
@ -2159,63 +2125,42 @@ macro_rules! impl_bounds {
separator = Some(<Token![+]>::default()); separator = Some(<Token![+]>::default());
v.to_tokens(tokens); v.to_tokens(tokens);
})* })*
$(for v in &self.$Unknown {
separator.to_tokens(tokens);
separator = Some(<Token![+]>::default());
v.to_tokens(tokens);
})*
} }
} }
const _: () = { const _: () = {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[allow(non_snake_case)] $vis struct Iter($vis $struct_type);
$vis struct Iter {
$($Variant: Option<known_items::$Variant>,)*
$($Unknown: std::vec::IntoIter<syn::TypeParamBound>,)?
}
impl IntoIterator for $struct_type { impl IntoIterator for $struct_type {
type Item = $enum_type; type Item = $enum_type;
type IntoIter = Iter; type IntoIter = Iter;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
Iter { Iter(self)
$($Variant: self.$Variant,)*
$($Unknown: self.$Unknown.into_iter(),)?
}
} }
} }
impl Iterator for Iter { impl Iterator for Iter {
type Item = $enum_type; type Item = $enum_type;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
$( $(
if let Some(value) = self.$Variant.take() { if let Some(value) = self.0.$Variant.take() {
return Some($enum_type::$Variant(value)); return Some($enum_type::$Variant(value));
} }
)* )*
$(
if let Some(value) = self.$Unknown.next() {
return Some($enum_type::$Unknown(value));
}
)?
None None
} }
#[allow(unused_mut, unused_variables)] #[allow(unused_mut, unused_variables)]
fn fold<B, F: FnMut(B, Self::Item) -> B>(mut self, mut init: B, mut f: F) -> B { fn fold<B, F: FnMut(B, Self::Item) -> B>(mut self, mut init: B, mut f: F) -> B {
$( $(
if let Some(value) = self.$Variant.take() { if let Some(value) = self.0.$Variant.take() {
init = f(init, $enum_type::$Variant(value)); init = f(init, $enum_type::$Variant(value));
} }
)* )*
$(
if let Some(value) = self.$Unknown.next() {
init = f(init, $enum_type::$Unknown(value));
}
)?
init init
} }
} }
@ -2227,9 +2172,6 @@ macro_rules! impl_bounds {
$($enum_type::$Variant(v) => { $($enum_type::$Variant(v) => {
self.$Variant = Some(v); self.$Variant = Some(v);
})* })*
$($enum_type::$Unknown(v) => {
self.$Unknown.push(v);
})?
}); });
} }
} }
@ -2248,7 +2190,6 @@ macro_rules! impl_bounds {
$(if let Some(v) = v.$Variant { $(if let Some(v) = v.$Variant {
self.$Variant = Some(v); self.$Variant = Some(v);
})* })*
$(self.$Unknown.extend(v.$Unknown);)*
}); });
} }
} }
@ -2298,12 +2239,9 @@ impl_bounds! {
EnumType, EnumType,
IntType, IntType,
KnownSize, KnownSize,
ResetType,
Size, Size,
StaticType, StaticType,
Type, Type,
#[unknown]
Unknown,
} }
} }
@ -2314,11 +2252,8 @@ impl_bounds! {
BundleType, BundleType,
EnumType, EnumType,
IntType, IntType,
ResetType,
StaticType, StaticType,
Type, Type,
#[unknown]
Unknown,
} }
} }
@ -2329,10 +2264,8 @@ impl From<ParsedTypeBound> for ParsedBound {
ParsedTypeBound::BundleType(v) => ParsedBound::BundleType(v), ParsedTypeBound::BundleType(v) => ParsedBound::BundleType(v),
ParsedTypeBound::EnumType(v) => ParsedBound::EnumType(v), ParsedTypeBound::EnumType(v) => ParsedBound::EnumType(v),
ParsedTypeBound::IntType(v) => ParsedBound::IntType(v), ParsedTypeBound::IntType(v) => ParsedBound::IntType(v),
ParsedTypeBound::ResetType(v) => ParsedBound::ResetType(v),
ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v), ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v),
ParsedTypeBound::Type(v) => ParsedBound::Type(v), ParsedTypeBound::Type(v) => ParsedBound::Type(v),
ParsedTypeBound::Unknown(v) => ParsedBound::Unknown(v),
} }
} }
} }
@ -2344,10 +2277,8 @@ impl From<ParsedTypeBounds> for ParsedBounds {
BundleType, BundleType,
EnumType, EnumType,
IntType, IntType,
ResetType,
StaticType, StaticType,
Type, Type,
Unknown,
} = value; } = value;
Self { Self {
BoolOrIntType, BoolOrIntType,
@ -2355,11 +2286,9 @@ impl From<ParsedTypeBounds> for ParsedBounds {
EnumType, EnumType,
IntType, IntType,
KnownSize: None, KnownSize: None,
ResetType,
Size: None, Size: None,
StaticType, StaticType,
Type, Type,
Unknown,
} }
} }
} }
@ -2385,17 +2314,11 @@ impl ParsedTypeBound {
ParsedTypeBound::BoolOrIntType(known_items::BoolOrIntType(span)), ParsedTypeBound::BoolOrIntType(known_items::BoolOrIntType(span)),
ParsedTypeBound::Type(known_items::Type(span)), ParsedTypeBound::Type(known_items::Type(span)),
]), ]),
Self::ResetType(v) => ParsedTypeBounds::from_iter([
ParsedTypeBound::from(v),
ParsedTypeBound::StaticType(known_items::StaticType(span)),
ParsedTypeBound::Type(known_items::Type(span)),
]),
Self::StaticType(v) => ParsedTypeBounds::from_iter([ Self::StaticType(v) => ParsedTypeBounds::from_iter([
ParsedTypeBound::from(v), ParsedTypeBound::from(v),
ParsedTypeBound::Type(known_items::Type(span)), ParsedTypeBound::Type(known_items::Type(span)),
]), ]),
Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]), Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]),
Self::Unknown(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::Unknown(v)]),
} }
} }
} }
@ -2426,11 +2349,9 @@ impl From<ParsedSizeTypeBounds> for ParsedBounds {
EnumType: None, EnumType: None,
IntType: None, IntType: None,
KnownSize, KnownSize,
ResetType: None,
Size, Size,
StaticType: None, StaticType: None,
Type: None, Type: None,
Unknown: vec![],
} }
} }
} }
@ -2458,7 +2379,6 @@ impl ParsedBounds {
fn categorize(self, errors: &mut Errors, span: Span) -> ParsedBoundsCategory { fn categorize(self, errors: &mut Errors, span: Span) -> ParsedBoundsCategory {
let mut type_bounds = None; let mut type_bounds = None;
let mut size_type_bounds = None; let mut size_type_bounds = None;
let mut unknown_bounds = vec![];
self.into_iter().for_each(|bound| match bound.categorize() { self.into_iter().for_each(|bound| match bound.categorize() {
ParsedBoundCategory::Type(bound) => { ParsedBoundCategory::Type(bound) => {
type_bounds type_bounds
@ -2470,37 +2390,15 @@ impl ParsedBounds {
.get_or_insert_with(ParsedSizeTypeBounds::default) .get_or_insert_with(ParsedSizeTypeBounds::default)
.extend([bound]); .extend([bound]);
} }
ParsedBoundCategory::Unknown(bound) => unknown_bounds.push(bound),
}); });
match (type_bounds, size_type_bounds, unknown_bounds.is_empty()) { match (type_bounds, size_type_bounds) {
(None, None, true) => ParsedBoundsCategory::Type(ParsedTypeBounds { (None, None) => ParsedBoundsCategory::Type(ParsedTypeBounds {
Type: Some(known_items::Type(span)), Type: Some(known_items::Type(span)),
..Default::default() ..Default::default()
}), }),
(None, None, false) => { (None, Some(bounds)) => ParsedBoundsCategory::SizeType(bounds),
errors.error( (Some(bounds), None) => ParsedBoundsCategory::Type(bounds),
unknown_bounds.remove(0), (Some(type_bounds), Some(size_type_bounds)) => {
"unknown bounds: must use at least one known bound (such as `Type`) with any unknown bounds",
);
ParsedBoundsCategory::Type(ParsedTypeBounds {
Unknown: unknown_bounds,
..Default::default()
})
}
(None, Some(bounds), true) => ParsedBoundsCategory::SizeType(bounds),
(None, Some(bounds), false) => {
// TODO: implement
errors.error(
unknown_bounds.remove(0),
"unknown bounds with `Size` bounds are not implemented",
);
ParsedBoundsCategory::SizeType(bounds)
}
(Some(bounds), None, _) => ParsedBoundsCategory::Type(ParsedTypeBounds {
Unknown: unknown_bounds,
..bounds
}),
(Some(type_bounds), Some(size_type_bounds), _) => {
errors.error( errors.error(
size_type_bounds size_type_bounds
.Size .Size
@ -2517,7 +2415,6 @@ impl ParsedBounds {
pub(crate) enum ParsedBoundCategory { pub(crate) enum ParsedBoundCategory {
Type(ParsedTypeBound), Type(ParsedTypeBound),
SizeType(ParsedSizeTypeBound), SizeType(ParsedSizeTypeBound),
Unknown(syn::TypeParamBound),
} }
impl ParsedBound { impl ParsedBound {
@ -2528,18 +2425,15 @@ impl ParsedBound {
Self::EnumType(v) => ParsedBoundCategory::Type(ParsedTypeBound::EnumType(v)), Self::EnumType(v) => ParsedBoundCategory::Type(ParsedTypeBound::EnumType(v)),
Self::IntType(v) => ParsedBoundCategory::Type(ParsedTypeBound::IntType(v)), Self::IntType(v) => ParsedBoundCategory::Type(ParsedTypeBound::IntType(v)),
Self::KnownSize(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::KnownSize(v)), Self::KnownSize(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::KnownSize(v)),
Self::ResetType(v) => ParsedBoundCategory::Type(ParsedTypeBound::ResetType(v)),
Self::Size(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::Size(v)), Self::Size(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::Size(v)),
Self::StaticType(v) => ParsedBoundCategory::Type(ParsedTypeBound::StaticType(v)), Self::StaticType(v) => ParsedBoundCategory::Type(ParsedTypeBound::StaticType(v)),
Self::Type(v) => ParsedBoundCategory::Type(ParsedTypeBound::Type(v)), Self::Type(v) => ParsedBoundCategory::Type(ParsedTypeBound::Type(v)),
Self::Unknown(v) => ParsedBoundCategory::Unknown(v),
} }
} }
fn implied_bounds(self) -> ParsedBounds { fn implied_bounds(self) -> ParsedBounds {
match self.categorize() { match self.categorize() {
ParsedBoundCategory::Type(v) => v.implied_bounds().into(), ParsedBoundCategory::Type(v) => v.implied_bounds().into(),
ParsedBoundCategory::SizeType(v) => v.implied_bounds().into(), ParsedBoundCategory::SizeType(v) => v.implied_bounds().into(),
ParsedBoundCategory::Unknown(v) => ParsedBounds::from_iter([ParsedBound::Unknown(v)]),
} }
} }
} }
@ -3416,9 +3310,8 @@ impl ParsedGenerics {
ParsedTypeBound::BoolOrIntType(_) ParsedTypeBound::BoolOrIntType(_)
| ParsedTypeBound::BundleType(_) | ParsedTypeBound::BundleType(_)
| ParsedTypeBound::EnumType(_) | ParsedTypeBound::EnumType(_)
| ParsedTypeBound::IntType(_) | ParsedTypeBound::IntType(_) => {
| ParsedTypeBound::ResetType(_) => { errors.error(bound, "bound on mask type not implemented");
errors.error(bound, "bounds on mask types are not implemented");
} }
ParsedTypeBound::StaticType(bound) => { ParsedTypeBound::StaticType(bound) => {
if bounds.StaticType.is_none() { if bounds.StaticType.is_none() {
@ -3430,12 +3323,6 @@ impl ParsedGenerics {
} }
} }
ParsedTypeBound::Type(_) => {} ParsedTypeBound::Type(_) => {}
ParsedTypeBound::Unknown(_) => {
errors.error(
bound,
"unknown bounds on mask types are not implemented",
);
}
} }
} }
bounds.add_implied_bounds(); bounds.add_implied_bounds();

View file

@ -3,20 +3,14 @@
#![cfg_attr(test, recursion_limit = "512")] #![cfg_attr(test, recursion_limit = "512")]
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens}; use quote::{quote, ToTokens};
use std::{ use std::io::{ErrorKind, Write};
collections::{hash_map::Entry, HashMap},
io::{ErrorKind, Write},
};
use syn::{ use syn::{
bracketed, bracketed, parenthesized,
ext::IdentExt,
parenthesized,
parse::{Parse, ParseStream, Parser}, parse::{Parse, ParseStream, Parser},
parse_quote, parse_quote,
punctuated::{Pair, Punctuated}, punctuated::Pair,
spanned::Spanned, spanned::Spanned,
token::{Bracket, Paren}, AttrStyle, Attribute, Error, Item, ItemFn, Token,
AttrStyle, Attribute, Error, Ident, Item, ItemFn, LitBool, LitStr, Meta, Token,
}; };
mod fold; mod fold;
@ -25,7 +19,6 @@ mod hdl_enum;
mod hdl_type_alias; mod hdl_type_alias;
mod hdl_type_common; mod hdl_type_common;
mod module; mod module;
mod process_cfg;
pub(crate) trait CustomToken: pub(crate) trait CustomToken:
Copy Copy
@ -66,20 +59,14 @@ mod kw {
}; };
} }
custom_keyword!(__evaluated_cfgs);
custom_keyword!(all);
custom_keyword!(any);
custom_keyword!(cfg);
custom_keyword!(cfg_attr);
custom_keyword!(clock_domain); custom_keyword!(clock_domain);
custom_keyword!(cmp_eq);
custom_keyword!(connect_inexact); custom_keyword!(connect_inexact);
custom_keyword!(custom_bounds); custom_keyword!(custom_bounds);
custom_keyword!(flip); custom_keyword!(flip);
custom_keyword!(hdl); custom_keyword!(hdl);
custom_keyword!(hdl_module); custom_keyword!(hdl_module);
custom_keyword!(incomplete_wire);
custom_keyword!(input); custom_keyword!(input);
custom_keyword!(incomplete_wire);
custom_keyword!(instance); custom_keyword!(instance);
custom_keyword!(m); custom_keyword!(m);
custom_keyword!(memory); custom_keyword!(memory);
@ -88,7 +75,6 @@ mod kw {
custom_keyword!(no_reset); custom_keyword!(no_reset);
custom_keyword!(no_runtime_generics); custom_keyword!(no_runtime_generics);
custom_keyword!(no_static); custom_keyword!(no_static);
custom_keyword!(not);
custom_keyword!(outline_generated); custom_keyword!(outline_generated);
custom_keyword!(output); custom_keyword!(output);
custom_keyword!(reg_builder); custom_keyword!(reg_builder);
@ -915,346 +901,15 @@ fn hdl_module_impl(item: ItemFn) -> syn::Result<TokenStream> {
Ok(contents) Ok(contents)
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug)] pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
pub(crate) enum CfgExpr { let kw = kw::hdl_module::default();
Option { hdl_module_impl(syn::parse2(quote! { #[#kw(#attr)] #item })?)
ident: Ident,
value: Option<(Token![=], LitStr)>,
},
All {
all: kw::all,
paren: Paren,
exprs: Punctuated<CfgExpr, Token![,]>,
},
Any {
any: kw::any,
paren: Paren,
exprs: Punctuated<CfgExpr, Token![,]>,
},
Not {
not: kw::not,
paren: Paren,
expr: Box<CfgExpr>,
trailing_comma: Option<Token![,]>,
},
} }
impl Parse for CfgExpr { pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
fn parse(input: ParseStream) -> syn::Result<Self> { let kw = kw::hdl::default();
match input.cursor().ident() { let item = quote! { #[#kw(#attr)] #item };
Some((_, cursor)) if cursor.eof() => { let item = syn::parse2::<Item>(item)?;
return Ok(CfgExpr::Option {
ident: input.call(Ident::parse_any)?,
value: None,
});
}
_ => {}
}
if input.peek(Ident::peek_any) && input.peek2(Token![=]) {
return Ok(CfgExpr::Option {
ident: input.call(Ident::parse_any)?,
value: Some((input.parse()?, input.parse()?)),
});
}
let contents;
if input.peek(kw::all) {
Ok(CfgExpr::All {
all: input.parse()?,
paren: parenthesized!(contents in input),
exprs: contents.call(Punctuated::parse_terminated)?,
})
} else if input.peek(kw::any) {
Ok(CfgExpr::Any {
any: input.parse()?,
paren: parenthesized!(contents in input),
exprs: contents.call(Punctuated::parse_terminated)?,
})
} else if input.peek(kw::not) {
Ok(CfgExpr::Not {
not: input.parse()?,
paren: parenthesized!(contents in input),
expr: contents.parse()?,
trailing_comma: contents.parse()?,
})
} else {
Err(input.error("expected cfg-pattern"))
}
}
}
impl ToTokens for CfgExpr {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
CfgExpr::Option { ident, value } => {
ident.to_tokens(tokens);
if let Some((eq, value)) = value {
eq.to_tokens(tokens);
value.to_tokens(tokens);
}
}
CfgExpr::All { all, paren, exprs } => {
all.to_tokens(tokens);
paren.surround(tokens, |tokens| exprs.to_tokens(tokens));
}
CfgExpr::Any { any, paren, exprs } => {
any.to_tokens(tokens);
paren.surround(tokens, |tokens| exprs.to_tokens(tokens));
}
CfgExpr::Not {
not,
paren,
expr,
trailing_comma,
} => {
not.to_tokens(tokens);
paren.surround(tokens, |tokens| {
expr.to_tokens(tokens);
trailing_comma.to_tokens(tokens);
});
}
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct Cfg {
cfg: kw::cfg,
paren: Paren,
expr: CfgExpr,
trailing_comma: Option<Token![,]>,
}
impl Cfg {
fn parse_meta(meta: &Meta) -> syn::Result<Self> {
syn::parse2(meta.to_token_stream())
}
}
impl ToTokens for Cfg {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self {
cfg,
paren,
expr,
trailing_comma,
} = self;
cfg.to_tokens(tokens);
paren.surround(tokens, |tokens| {
expr.to_tokens(tokens);
trailing_comma.to_tokens(tokens);
});
}
}
impl Parse for Cfg {
fn parse(input: ParseStream) -> syn::Result<Self> {
let contents;
Ok(Self {
cfg: input.parse()?,
paren: parenthesized!(contents in input),
expr: contents.parse()?,
trailing_comma: contents.parse()?,
})
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct CfgAttr {
cfg_attr: kw::cfg_attr,
paren: Paren,
expr: CfgExpr,
comma: Token![,],
attrs: Punctuated<Meta, Token![,]>,
}
impl CfgAttr {
pub(crate) fn to_cfg(&self) -> Cfg {
Cfg {
cfg: kw::cfg(self.cfg_attr.span),
paren: self.paren,
expr: self.expr.clone(),
trailing_comma: None,
}
}
fn parse_meta(meta: &Meta) -> syn::Result<Self> {
syn::parse2(meta.to_token_stream())
}
}
impl Parse for CfgAttr {
fn parse(input: ParseStream) -> syn::Result<Self> {
let contents;
Ok(Self {
cfg_attr: input.parse()?,
paren: parenthesized!(contents in input),
expr: contents.parse()?,
comma: contents.parse()?,
attrs: contents.call(Punctuated::parse_terminated)?,
})
}
}
pub(crate) struct CfgAndValue {
cfg: Cfg,
eq_token: Token![=],
value: LitBool,
}
impl Parse for CfgAndValue {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Self {
cfg: input.parse()?,
eq_token: input.parse()?,
value: input.parse()?,
})
}
}
pub(crate) struct Cfgs<T> {
pub(crate) bracket: Bracket,
pub(crate) cfgs_map: HashMap<Cfg, T>,
pub(crate) cfgs_list: Vec<Cfg>,
}
impl<T> Default for Cfgs<T> {
fn default() -> Self {
Self {
bracket: Default::default(),
cfgs_map: Default::default(),
cfgs_list: Default::default(),
}
}
}
impl<T> Cfgs<T> {
fn insert_cfg(&mut self, cfg: Cfg, value: T) {
match self.cfgs_map.entry(cfg) {
Entry::Occupied(_) => {}
Entry::Vacant(entry) => {
self.cfgs_list.push(entry.key().clone());
entry.insert(value);
}
}
}
}
impl Parse for Cfgs<bool> {
fn parse(input: ParseStream) -> syn::Result<Self> {
let contents;
let bracket = bracketed!(contents in input);
let mut cfgs_map = HashMap::new();
let mut cfgs_list = Vec::new();
for CfgAndValue {
cfg,
eq_token,
value,
} in contents.call(Punctuated::<CfgAndValue, Token![,]>::parse_terminated)?
{
let _ = eq_token;
match cfgs_map.entry(cfg) {
Entry::Occupied(_) => {}
Entry::Vacant(entry) => {
cfgs_list.push(entry.key().clone());
entry.insert(value.value);
}
}
}
Ok(Self {
bracket,
cfgs_map,
cfgs_list,
})
}
}
impl Parse for Cfgs<()> {
fn parse(input: ParseStream) -> syn::Result<Self> {
let contents;
let bracket = bracketed!(contents in input);
let mut cfgs_map = HashMap::new();
let mut cfgs_list = Vec::new();
for cfg in contents.call(Punctuated::<Cfg, Token![,]>::parse_terminated)? {
match cfgs_map.entry(cfg) {
Entry::Occupied(_) => {}
Entry::Vacant(entry) => {
cfgs_list.push(entry.key().clone());
entry.insert(());
}
}
}
Ok(Self {
bracket,
cfgs_map,
cfgs_list,
})
}
}
impl ToTokens for Cfgs<()> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self {
bracket,
cfgs_map: _,
cfgs_list,
} = self;
bracket.surround(tokens, |tokens| {
for cfg in cfgs_list {
cfg.to_tokens(tokens);
<Token![,]>::default().to_tokens(tokens);
}
});
}
}
fn hdl_main(
kw: impl CustomToken,
attr: TokenStream,
item: TokenStream,
) -> syn::Result<TokenStream> {
fn parse_evaluated_cfgs_attr<R>(
input: ParseStream,
parse_inner: impl FnOnce(ParseStream) -> syn::Result<R>,
) -> syn::Result<R> {
let _: Token![#] = input.parse()?;
let bracket_content;
bracketed!(bracket_content in input);
let _: kw::__evaluated_cfgs = bracket_content.parse()?;
let paren_content;
parenthesized!(paren_content in bracket_content);
parse_inner(&paren_content)
}
let (evaluated_cfgs, item): (_, TokenStream) = Parser::parse2(
|input: ParseStream| {
let peek = input.fork();
if parse_evaluated_cfgs_attr(&peek, |_| Ok(())).is_ok() {
let evaluated_cfgs = parse_evaluated_cfgs_attr(input, Cfgs::<bool>::parse)?;
Ok((Some(evaluated_cfgs), input.parse()?))
} else {
Ok((None, input.parse()?))
}
},
item,
)?;
let cfgs = if let Some(cfgs) = evaluated_cfgs {
cfgs
} else {
let cfgs = process_cfg::collect_cfgs(syn::parse2(item.clone())?)?;
if cfgs.cfgs_list.is_empty() {
Cfgs::default()
} else {
return Ok(quote! {
::fayalite::__cfg_expansion_helper! {
[]
#cfgs
{#[::fayalite::#kw(#attr)]} { #item }
}
});
}
};
let item = syn::parse2(quote! { #[#kw(#attr)] #item })?;
let Some(item) = process_cfg::process_cfgs(item, cfgs)? else {
return Ok(TokenStream::new());
};
match item { match item {
Item::Enum(item) => hdl_enum::hdl_enum(item), Item::Enum(item) => hdl_enum::hdl_enum(item),
Item::Struct(item) => hdl_bundle::hdl_bundle(item), Item::Struct(item) => hdl_bundle::hdl_bundle(item),
@ -1266,11 +921,3 @@ fn hdl_main(
)), )),
} }
} }
pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
hdl_main(kw::hdl_module::default(), attr, item)
}
pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
hdl_main(kw::hdl::default(), attr, item)
}

View file

@ -1109,7 +1109,7 @@ fn parse_quote_let_pat<T, R: ToTokens, C: Borrow<Token![:]>>(
} }
} }
pub(crate) fn wrap_ty_with_expr(ty: impl ToTokens) -> Type { fn wrap_ty_with_expr(ty: impl ToTokens) -> Type {
parse_quote_spanned! {ty.span()=> parse_quote_spanned! {ty.span()=>
::fayalite::expr::Expr<#ty> ::fayalite::expr::Expr<#ty>
} }
@ -1586,7 +1586,7 @@ impl Visitor<'_> {
} }
} }
pub(crate) fn empty_let() -> Local { fn empty_let() -> Local {
Local { Local {
attrs: vec![], attrs: vec![],
let_token: Default::default(), let_token: Default::default(),
@ -1672,7 +1672,7 @@ impl Fold for Visitor<'_> {
} }
} }
fn fold_local(&mut self, mut let_stmt: Local) -> Local { fn fold_local(&mut self, let_stmt: Local) -> Local {
match self match self
.errors .errors
.ok(HdlAttr::<Nothing, kw::hdl>::parse_and_leave_attr( .ok(HdlAttr::<Nothing, kw::hdl>::parse_and_leave_attr(
@ -1682,25 +1682,6 @@ impl Fold for Visitor<'_> {
Some(None) => return fold_local(self, let_stmt), Some(None) => return fold_local(self, let_stmt),
Some(Some(HdlAttr { .. })) => {} Some(Some(HdlAttr { .. })) => {}
}; };
let mut pat = &let_stmt.pat;
if let Pat::Type(pat_type) = pat {
pat = &pat_type.pat;
}
let Pat::Ident(syn::PatIdent {
attrs: _,
by_ref: None,
mutability: _,
ident: _,
subpat: None,
}) = pat
else {
let hdl_attr = HdlAttr::<Nothing, kw::hdl>::parse_and_take_attr(&mut let_stmt.attrs)
.ok()
.flatten()
.expect("already checked above");
let let_stmt = fold_local(self, let_stmt);
return self.process_hdl_let_pat(hdl_attr, let_stmt);
};
let hdl_let = syn::parse2::<HdlLet<HdlLetKind<Type>>>(let_stmt.into_token_stream()); let hdl_let = syn::parse2::<HdlLet<HdlLetKind<Type>>>(let_stmt.into_token_stream());
let Some(hdl_let) = self.errors.ok(hdl_let) else { let Some(hdl_let) = self.errors.ok(hdl_let) else {
return empty_let(); return empty_let();

View file

@ -3,111 +3,22 @@
use crate::{ use crate::{
fold::{impl_fold, DoFold}, fold::{impl_fold, DoFold},
kw, kw,
module::transform_body::{empty_let, with_debug_clone_and_fold, wrap_ty_with_expr, Visitor}, module::transform_body::{with_debug_clone_and_fold, Visitor},
Errors, HdlAttr, PairsIterExt, Errors, HdlAttr, PairsIterExt,
}; };
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt}; use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt};
use std::collections::BTreeSet;
use syn::{ use syn::{
fold::{fold_arm, fold_expr_match, fold_local, fold_pat, Fold}, fold::{fold_arm, fold_expr_match, fold_pat, Fold},
parse::Nothing, parse::Nothing,
parse_quote_spanned, parse_quote_spanned,
punctuated::Punctuated, punctuated::Punctuated,
spanned::Spanned, spanned::Spanned,
token::{Brace, Paren}, token::{Brace, Paren},
Arm, Attribute, Expr, ExprMatch, FieldPat, Ident, Local, Member, Pat, PatIdent, PatOr, Arm, Attribute, Expr, ExprMatch, FieldPat, Ident, Member, Pat, PatIdent, PatOr, PatParen,
PatParen, PatPath, PatRest, PatStruct, PatTuple, PatTupleStruct, PatWild, Path, PathSegment, PatPath, PatRest, PatStruct, PatTupleStruct, PatWild, Path, PathSegment, Token, TypePath,
Token, TypePath,
}; };
macro_rules! visit_trait {
(
$($vis:vis fn $fn:ident($state:ident: _, $value:ident: &$Value:ty) $block:block)*
) => {
trait VisitMatchPat<'a> {
$(fn $fn(&mut self, $value: &'a $Value) {
$fn(self, $value);
})*
}
$($vis fn $fn<'a>($state: &mut (impl ?Sized + VisitMatchPat<'a>), $value: &'a $Value) $block)*
};
}
visit_trait! {
fn visit_match_pat_binding(_state: _, v: &MatchPatBinding) {
let MatchPatBinding { ident: _ } = v;
}
fn visit_match_pat_wild(_state: _, v: &MatchPatWild) {
let MatchPatWild { underscore_token: _ } = v;
}
fn visit_match_pat_rest(_state: _, v: &MatchPatRest) {
let MatchPatRest { dot2_token: _ } = v;
}
fn visit_match_pat_paren(state: _, v: &MatchPatParen<MatchPat>) {
let MatchPatParen { paren_token: _, pat } = v;
state.visit_match_pat(pat);
}
fn visit_match_pat_paren_simple(state: _, v: &MatchPatParen<MatchPatSimple>) {
let MatchPatParen { paren_token: _, pat } = v;
state.visit_match_pat_simple(pat);
}
fn visit_match_pat_or(state: _, v: &MatchPatOr<MatchPat>) {
let MatchPatOr { leading_vert: _, cases } = v;
for v in cases {
state.visit_match_pat(v);
}
}
fn visit_match_pat_or_simple(state: _, v: &MatchPatOr<MatchPatSimple>) {
let MatchPatOr { leading_vert: _, cases } = v;
for v in cases {
state.visit_match_pat_simple(v);
}
}
fn visit_match_pat_struct_field(state: _, v: &MatchPatStructField) {
let MatchPatStructField { field_name: _, colon_token: _, pat } = v;
state.visit_match_pat_simple(pat);
}
fn visit_match_pat_struct(state: _, v: &MatchPatStruct) {
let MatchPatStruct { match_span: _, path: _, brace_token: _, fields, rest: _ } = v;
for v in fields {
state.visit_match_pat_struct_field(v);
}
}
fn visit_match_pat_tuple(state: _, v: &MatchPatTuple) {
let MatchPatTuple { paren_token: _, fields } = v;
for v in fields {
state.visit_match_pat_simple(v);
}
}
fn visit_match_pat_enum_variant(state: _, v: &MatchPatEnumVariant) {
let MatchPatEnumVariant {match_span:_, variant_path: _, enum_path: _, variant_name: _, field } = v;
if let Some((_, v)) = field {
state.visit_match_pat_simple(v);
}
}
fn visit_match_pat_simple(state: _, v: &MatchPatSimple) {
match v {
MatchPatSimple::Paren(v) => state.visit_match_pat_paren_simple(v),
MatchPatSimple::Or(v) => state.visit_match_pat_or_simple(v),
MatchPatSimple::Binding(v) => state.visit_match_pat_binding(v),
MatchPatSimple::Wild(v) => state.visit_match_pat_wild(v),
MatchPatSimple::Rest(v) => state.visit_match_pat_rest(v),
}
}
fn visit_match_pat(state: _, v: &MatchPat) {
match v {
MatchPat::Simple(v) => state.visit_match_pat_simple(v),
MatchPat::Or(v) => state.visit_match_pat_or(v),
MatchPat::Paren(v) => state.visit_match_pat_paren(v),
MatchPat::Struct(v) => state.visit_match_pat_struct(v),
MatchPat::Tuple(v) => state.visit_match_pat_tuple(v),
MatchPat::EnumVariant(v) => state.visit_match_pat_enum_variant(v),
}
}
}
with_debug_clone_and_fold! { with_debug_clone_and_fold! {
struct MatchPatBinding<> { struct MatchPatBinding<> {
ident: Ident, ident: Ident,
@ -142,15 +53,6 @@ with_debug_clone_and_fold! {
} }
} }
impl<P> MatchPatOr<P> {
/// returns the first `|` between two patterns
fn first_inner_vert(&self) -> Option<Token![|]> {
let mut pairs = self.cases.pairs();
pairs.next_back();
pairs.next().and_then(|v| v.into_tuple().1.copied())
}
}
impl<P: ToTokens> ToTokens for MatchPatOr<P> { impl<P: ToTokens> ToTokens for MatchPatOr<P> {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let Self { let Self {
@ -175,19 +77,6 @@ impl ToTokens for MatchPatWild {
} }
} }
with_debug_clone_and_fold! {
struct MatchPatRest<> {
dot2_token: Token![..],
}
}
impl ToTokens for MatchPatRest {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self { dot2_token } = self;
dot2_token.to_tokens(tokens);
}
}
with_debug_clone_and_fold! { with_debug_clone_and_fold! {
struct MatchPatStructField<> { struct MatchPatStructField<> {
field_name: Ident, field_name: Ident,
@ -270,25 +159,6 @@ impl ToTokens for MatchPatStruct {
} }
} }
with_debug_clone_and_fold! {
struct MatchPatTuple<> {
paren_token: Paren,
fields: Punctuated<MatchPatSimple, Token![,]>,
}
}
impl ToTokens for MatchPatTuple {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self {
paren_token,
fields,
} = self;
paren_token.surround(tokens, |tokens| {
fields.to_tokens(tokens);
})
}
}
with_debug_clone_and_fold! { with_debug_clone_and_fold! {
struct MatchPatEnumVariant<> { struct MatchPatEnumVariant<> {
match_span: Span, match_span: Span,
@ -324,7 +194,6 @@ enum MatchPatSimple {
Or(MatchPatOr<MatchPatSimple>), Or(MatchPatOr<MatchPatSimple>),
Binding(MatchPatBinding), Binding(MatchPatBinding),
Wild(MatchPatWild), Wild(MatchPatWild),
Rest(MatchPatRest),
} }
impl_fold! { impl_fold! {
@ -333,7 +202,6 @@ impl_fold! {
Or(MatchPatOr<MatchPatSimple>), Or(MatchPatOr<MatchPatSimple>),
Binding(MatchPatBinding), Binding(MatchPatBinding),
Wild(MatchPatWild), Wild(MatchPatWild),
Rest(MatchPatRest),
} }
} }
@ -344,7 +212,6 @@ impl ToTokens for MatchPatSimple {
Self::Paren(v) => v.to_tokens(tokens), Self::Paren(v) => v.to_tokens(tokens),
Self::Binding(v) => v.to_tokens(tokens), Self::Binding(v) => v.to_tokens(tokens),
Self::Wild(v) => v.to_tokens(tokens), Self::Wild(v) => v.to_tokens(tokens),
Self::Rest(v) => v.to_tokens(tokens),
} }
} }
} }
@ -411,7 +278,6 @@ trait ParseMatchPat: Sized {
fn or(v: MatchPatOr<Self>) -> Self; fn or(v: MatchPatOr<Self>) -> Self;
fn paren(v: MatchPatParen<Self>) -> Self; fn paren(v: MatchPatParen<Self>) -> Self;
fn struct_(state: &mut HdlMatchParseState<'_>, v: MatchPatStruct) -> Result<Self, ()>; fn struct_(state: &mut HdlMatchParseState<'_>, v: MatchPatStruct) -> Result<Self, ()>;
fn tuple(state: &mut HdlMatchParseState<'_>, v: MatchPatTuple) -> Result<Self, ()>;
fn enum_variant(state: &mut HdlMatchParseState<'_>, v: MatchPatEnumVariant) fn enum_variant(state: &mut HdlMatchParseState<'_>, v: MatchPatEnumVariant)
-> Result<Self, ()>; -> Result<Self, ()>;
fn parse(state: &mut HdlMatchParseState<'_>, pat: Pat) -> Result<Self, ()> { fn parse(state: &mut HdlMatchParseState<'_>, pat: Pat) -> Result<Self, ()> {
@ -596,34 +462,7 @@ trait ParseMatchPat: Sized {
}) => Ok(Self::simple(MatchPatSimple::Wild(MatchPatWild { }) => Ok(Self::simple(MatchPatSimple::Wild(MatchPatWild {
underscore_token, underscore_token,
}))), }))),
Pat::Tuple(PatTuple { Pat::Tuple(_) | Pat::Slice(_) | Pat::Const(_) | Pat::Lit(_) | Pat::Range(_) => {
attrs: _,
paren_token,
elems,
}) => {
let fields = elems
.into_pairs()
.filter_map_pair_value(|field_pat| {
if let Pat::Rest(PatRest {
attrs: _,
dot2_token,
}) = field_pat
{
Some(MatchPatSimple::Rest(MatchPatRest { dot2_token }))
} else {
MatchPatSimple::parse(state, field_pat).ok()
}
})
.collect();
Self::tuple(
state,
MatchPatTuple {
paren_token,
fields,
},
)
}
Pat::Slice(_) | Pat::Const(_) | Pat::Lit(_) | Pat::Range(_) => {
state state
.errors .errors
.error(pat, "not yet implemented in #[hdl] patterns"); .error(pat, "not yet implemented in #[hdl] patterns");
@ -658,14 +497,6 @@ impl ParseMatchPat for MatchPatSimple {
Err(()) Err(())
} }
fn tuple(state: &mut HdlMatchParseState<'_>, v: MatchPatTuple) -> Result<Self, ()> {
state.errors.push(syn::Error::new(
v.paren_token.span.open(),
"matching tuples is not yet implemented inside structs/enums in #[hdl] patterns",
));
Err(())
}
fn enum_variant( fn enum_variant(
state: &mut HdlMatchParseState<'_>, state: &mut HdlMatchParseState<'_>,
v: MatchPatEnumVariant, v: MatchPatEnumVariant,
@ -684,7 +515,6 @@ enum MatchPat {
Or(MatchPatOr<MatchPat>), Or(MatchPatOr<MatchPat>),
Paren(MatchPatParen<MatchPat>), Paren(MatchPatParen<MatchPat>),
Struct(MatchPatStruct), Struct(MatchPatStruct),
Tuple(MatchPatTuple),
EnumVariant(MatchPatEnumVariant), EnumVariant(MatchPatEnumVariant),
} }
@ -694,7 +524,6 @@ impl_fold! {
Or(MatchPatOr<MatchPat>), Or(MatchPatOr<MatchPat>),
Paren(MatchPatParen<MatchPat>), Paren(MatchPatParen<MatchPat>),
Struct(MatchPatStruct), Struct(MatchPatStruct),
Tuple(MatchPatTuple),
EnumVariant(MatchPatEnumVariant), EnumVariant(MatchPatEnumVariant),
} }
} }
@ -716,10 +545,6 @@ impl ParseMatchPat for MatchPat {
Ok(Self::Struct(v)) Ok(Self::Struct(v))
} }
fn tuple(_state: &mut HdlMatchParseState<'_>, v: MatchPatTuple) -> Result<Self, ()> {
Ok(Self::Tuple(v))
}
fn enum_variant( fn enum_variant(
_state: &mut HdlMatchParseState<'_>, _state: &mut HdlMatchParseState<'_>,
v: MatchPatEnumVariant, v: MatchPatEnumVariant,
@ -735,7 +560,6 @@ impl ToTokens for MatchPat {
Self::Or(v) => v.to_tokens(tokens), Self::Or(v) => v.to_tokens(tokens),
Self::Paren(v) => v.to_tokens(tokens), Self::Paren(v) => v.to_tokens(tokens),
Self::Struct(v) => v.to_tokens(tokens), Self::Struct(v) => v.to_tokens(tokens),
Self::Tuple(v) => v.to_tokens(tokens),
Self::EnumVariant(v) => v.to_tokens(tokens), Self::EnumVariant(v) => v.to_tokens(tokens),
} }
} }
@ -798,6 +622,10 @@ struct RewriteAsCheckMatch {
} }
impl Fold for RewriteAsCheckMatch { impl Fold for RewriteAsCheckMatch {
fn fold_field_pat(&mut self, mut i: FieldPat) -> FieldPat {
i.colon_token = Some(Token![:](i.member.span()));
i
}
fn fold_pat(&mut self, pat: Pat) -> Pat { fn fold_pat(&mut self, pat: Pat) -> Pat {
match pat { match pat {
Pat::Ident(mut pat_ident) => match parse_enum_ident(pat_ident.ident) { Pat::Ident(mut pat_ident) => match parse_enum_ident(pat_ident.ident) {
@ -912,30 +740,6 @@ impl Fold for RewriteAsCheckMatch {
// don't recurse into expressions // don't recurse into expressions
i i
} }
fn fold_local(&mut self, mut let_stmt: Local) -> Local {
if let Some(syn::LocalInit {
eq_token,
expr: _,
diverge,
}) = let_stmt.init.take()
{
let_stmt.init = Some(syn::LocalInit {
eq_token,
expr: parse_quote_spanned! {self.span=>
__match_value
},
diverge: diverge.map(|(else_, _expr)| {
(
else_,
parse_quote_spanned! {self.span=>
match __infallible {}
},
)
}),
});
}
fold_local(self, let_stmt)
}
} }
struct HdlMatchParseState<'a> { struct HdlMatchParseState<'a> {
@ -943,123 +747,7 @@ struct HdlMatchParseState<'a> {
errors: &'a mut Errors, errors: &'a mut Errors,
} }
struct HdlLetPatVisitState<'a> {
errors: &'a mut Errors,
bindings: BTreeSet<&'a Ident>,
}
impl<'a> VisitMatchPat<'a> for HdlLetPatVisitState<'a> {
fn visit_match_pat_binding(&mut self, v: &'a MatchPatBinding) {
self.bindings.insert(&v.ident);
}
fn visit_match_pat_or(&mut self, v: &'a MatchPatOr<MatchPat>) {
if let Some(first_inner_vert) = v.first_inner_vert() {
self.errors.error(
first_inner_vert,
"or-patterns are not supported in let statements",
);
}
visit_match_pat_or(self, v);
}
fn visit_match_pat_or_simple(&mut self, v: &'a MatchPatOr<MatchPatSimple>) {
if let Some(first_inner_vert) = v.first_inner_vert() {
self.errors.error(
first_inner_vert,
"or-patterns are not supported in let statements",
);
}
visit_match_pat_or_simple(self, v);
}
fn visit_match_pat_enum_variant(&mut self, v: &'a MatchPatEnumVariant) {
self.errors.error(v, "refutable pattern in let statement");
}
}
impl Visitor<'_> { impl Visitor<'_> {
pub(crate) fn process_hdl_let_pat(
&mut self,
_hdl_attr: HdlAttr<Nothing, kw::hdl>,
mut let_stmt: Local,
) -> Local {
let span = let_stmt.let_token.span();
if let Pat::Type(pat) = &mut let_stmt.pat {
*pat.ty = wrap_ty_with_expr((*pat.ty).clone());
}
let check_let_stmt = RewriteAsCheckMatch { span }.fold_local(let_stmt.clone());
let Local {
attrs: _,
let_token,
pat,
init,
semi_token,
} = let_stmt;
self.require_normal_module_or_fn(let_token);
let Some(syn::LocalInit {
eq_token,
expr,
diverge,
}) = init
else {
self.errors
.error(let_token, "#[hdl] let must be assigned a value");
return empty_let();
};
if let Some((else_, _)) = diverge {
// TODO: implement let-else
self.errors
.error(else_, "#[hdl] let ... else { ... } is not implemented");
return empty_let();
}
let Ok(pat) = MatchPat::parse(
&mut HdlMatchParseState {
match_span: span,
errors: &mut self.errors,
},
pat,
) else {
return empty_let();
};
let mut state = HdlLetPatVisitState {
errors: &mut self.errors,
bindings: BTreeSet::new(),
};
state.visit_match_pat(&pat);
let HdlLetPatVisitState {
errors: _,
bindings,
} = state;
let retval = parse_quote_spanned! {span=>
let (#(#bindings,)* __scope,) = {
type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant;
let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(#expr));
::fayalite::expr::check_match_expr(__match_expr, |__match_value, __infallible| {
#[allow(unused_variables)]
#check_let_stmt
match __infallible {}
});
let mut __match_iter = ::fayalite::module::match_(__match_expr);
let ::fayalite::__std::option::Option::Some(__match_variant) = ::fayalite::__std::iter::Iterator::next(&mut __match_iter) else {
::fayalite::__std::unreachable!("#[hdl] let with uninhabited type");
};
let ::fayalite::__std::option::Option::None = ::fayalite::__std::iter::Iterator::next(&mut __match_iter) else {
::fayalite::__std::unreachable!("#[hdl] let with refutable pattern");
};
let (__match_variant, __scope) =
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
__match_variant,
);
#let_token #pat #eq_token __match_variant #semi_token
(#(#bindings,)* __scope,)
};
};
match retval {
syn::Stmt::Local(retval) => retval,
_ => unreachable!(),
}
}
pub(crate) fn process_hdl_match( pub(crate) fn process_hdl_match(
&mut self, &mut self,
_hdl_attr: HdlAttr<Nothing, kw::hdl>, _hdl_attr: HdlAttr<Nothing, kw::hdl>,

File diff suppressed because it is too large Load diff

View file

@ -25,11 +25,9 @@ jobslot.workspace = true
num-bigint.workspace = true num-bigint.workspace = true
num-traits.workspace = true num-traits.workspace = true
os_pipe.workspace = true os_pipe.workspace = true
petgraph.workspace = true
serde_json.workspace = true serde_json.workspace = true
serde.workspace = true serde.workspace = true
tempfile.workspace = true tempfile.workspace = true
vec_map.workspace = true
which.workspace = true which.workspace = true
[dev-dependencies] [dev-dependencies]

View file

@ -5,9 +5,6 @@ use std::{env, fs, path::Path};
fn main() { fn main() {
println!("cargo::rustc-check-cfg=cfg(todo)"); println!("cargo::rustc-check-cfg=cfg(todo)");
println!("cargo::rustc-check-cfg=cfg(cfg_false_for_tests)");
println!("cargo::rustc-check-cfg=cfg(cfg_true_for_tests)");
println!("cargo::rustc-cfg=cfg_true_for_tests");
let path = "visit_types.json"; let path = "visit_types.json";
println!("cargo::rerun-if-changed={path}"); println!("cargo::rerun-if-changed={path}");
println!("cargo::rerun-if-changed=build.rs"); println!("cargo::rerun-if-changed=build.rs");

View file

@ -2,7 +2,6 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
//! ## `#[hdl] let` statements //! ## `#[hdl] let` statements
pub mod destructuring;
pub mod inputs_outputs; pub mod inputs_outputs;
pub mod instances; pub mod instances;
pub mod memories; pub mod memories;

View file

@ -1,33 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
//! ### Destructuring Let
//!
//! You can use `#[hdl] let` to destructure types, similarly to Rust `let` statements with non-trivial patterns.
//!
//! `#[hdl] let` statements can only match one level of struct/tuple pattern for now,
//! e.g. you can match with the pattern `MyStruct { a, b }`, but not `MyStruct { a, b: Struct2 { v } }`.
//!
//! ```
//! # use fayalite::prelude::*;
//! #[hdl]
//! struct MyStruct {
//! a: UInt<8>,
//! b: Bool,
//! }
//!
//! #[hdl_module]
//! fn my_module() {
//! #[hdl]
//! let my_input: MyStruct = m.input();
//! #[hdl]
//! let my_output: UInt<8> = m.input();
//! #[hdl]
//! let MyStruct { a, b } = my_input;
//! #[hdl]
//! if b {
//! connect(my_output, a);
//! } else {
//! connect(my_output, 0_hdl_u8);
//! }
//! }
//! ```

View file

@ -7,5 +7,5 @@
//! //!
//! `#[hdl] match` statements' bodies must evaluate to type `()` for now. //! `#[hdl] match` statements' bodies must evaluate to type `()` for now.
//! //!
//! `#[hdl] match` statements can only match one level of struct/tuple/enum pattern for now, //! `#[hdl] match` statements can only match one level of struct/enum pattern for now,
//! e.g. you can match with the pattern `HdlSome(v)`, but not `HdlSome(HdlSome(_))`. //! e.g. you can match with the pattern `HdlSome(v)`, but not `HdlSome(HdlSome(_))`.

View file

@ -2,11 +2,8 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
expr::{ expr::{ops::ArrayIndex, Expr, ToExpr},
ops::{ArrayIndex, ArrayLiteral, ExprPartialEq}, int::{DynSize, KnownSize, Size, SizeType, DYN_SIZE},
CastToBits, Expr, HdlPartialEq, ReduceBits, ToExpr,
},
int::{Bool, DynSize, KnownSize, Size, SizeType, DYN_SIZE},
intern::{Intern, Interned, LazyInterned}, intern::{Intern, Interned, LazyInterned},
module::transform::visit::{Fold, Folder, Visit, Visitor}, module::transform::visit::{Fold, Folder, Visit, Visitor},
source_location::SourceLocation, source_location::SourceLocation,
@ -221,36 +218,3 @@ impl<T: Type, L: SizeType> Index<L> for ArrayWithoutLen<T> {
Interned::into_inner(Intern::intern_sized(ArrayType::new(self.element, len))) Interned::into_inner(Intern::intern_sized(ArrayType::new(self.element, len)))
} }
} }
impl<Lhs: Type, Rhs: Type, Len: Size> ExprPartialEq<ArrayType<Rhs, Len>> for ArrayType<Lhs, Len>
where
Lhs: ExprPartialEq<Rhs>,
{
fn cmp_eq(lhs: Expr<Self>, rhs: Expr<ArrayType<Rhs, Len>>) -> Expr<Bool> {
let lhs_ty = Expr::ty(lhs);
let rhs_ty = Expr::ty(rhs);
assert_eq!(lhs_ty.len(), rhs_ty.len());
ArrayLiteral::<Bool, DynSize>::new(
Bool,
(0..lhs_ty.len())
.map(|i| Expr::canonical(lhs[i].cmp_eq(rhs[i])))
.collect(),
)
.cast_to_bits()
.all_one_bits()
}
fn cmp_ne(lhs: Expr<Self>, rhs: Expr<ArrayType<Rhs, Len>>) -> Expr<Bool> {
let lhs_ty = Expr::ty(lhs);
let rhs_ty = Expr::ty(rhs);
assert_eq!(lhs_ty.len(), rhs_ty.len());
ArrayLiteral::<Bool, DynSize>::new(
Bool,
(0..lhs_ty.len())
.map(|i| Expr::canonical(lhs[i].cmp_ne(rhs[i])))
.collect(),
)
.cast_to_bits()
.any_one_bits()
}
}

View file

@ -2,20 +2,14 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
expr::{ expr::{ops::BundleLiteral, Expr, ToExpr},
ops::{ArrayLiteral, BundleLiteral, ExprPartialEq},
CastToBits, Expr, ReduceBits, ToExpr,
},
int::{Bool, DynSize},
intern::{Intern, Interned}, intern::{Intern, Interned},
sim::{SimValue, ToSimValue},
source_location::SourceLocation, source_location::SourceLocation,
ty::{ ty::{
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, StaticType, Type, impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, StaticType, Type,
TypeProperties, TypeWithDeref, TypeProperties, TypeWithDeref,
}, },
}; };
use bitvec::vec::BitVec;
use hashbrown::HashMap; use hashbrown::HashMap;
use std::{fmt, marker::PhantomData}; use std::{fmt, marker::PhantomData};
@ -329,19 +323,7 @@ macro_rules! impl_tuple_builder_fields {
} }
macro_rules! impl_tuples { macro_rules! impl_tuples {
( ([$({#[num = $num:literal, field = $field:ident] $var:ident: $T:ident})*] []) => {
[$({
#[
num = $num:tt,
field = $field:ident,
ty = $ty_var:ident: $Ty:ident,
lhs = $lhs_var:ident: $Lhs:ident,
rhs = $rhs_var:ident: $Rhs:ident
]
$var:ident: $T:ident
})*]
[]
) => {
impl_tuple_builder_fields! { impl_tuple_builder_fields! {
{} {}
[$({ [$({
@ -441,102 +423,6 @@ macro_rules! impl_tuples {
BundleLiteral::new(ty, field_values[..].intern()).to_expr() BundleLiteral::new(ty, field_values[..].intern()).to_expr()
} }
} }
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<CanonicalType> for ($($T,)*) {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
ToSimValue::<Bundle>::to_sim_value(self, Bundle::from_canonical(ty)).into_canonical()
}
#[track_caller]
fn into_sim_value(self, ty: CanonicalType) -> SimValue<CanonicalType>
{
ToSimValue::<Bundle>::into_sim_value(self, Bundle::from_canonical(ty)).into_canonical()
}
#[track_caller]
fn box_into_sim_value(self: Box<Self>, ty: CanonicalType) -> SimValue<CanonicalType> {
ToSimValue::<Bundle>::box_into_sim_value(self, Bundle::from_canonical(ty)).into_canonical()
}
}
impl<$($T: ToSimValue<CanonicalType>,)*> ToSimValue<Bundle> for ($($T,)*) {
#[track_caller]
fn to_sim_value(&self, ty: Bundle) -> SimValue<Bundle> {
let ($($var,)*) = self;
let [$($ty_var,)*] = *ty.fields() else {
panic!("bundle has wrong number of fields");
};
$(let $var = $var.to_sim_value($ty_var.ty);)*
ToSimValue::into_sim_value(($($var,)*), ty)
}
#[track_caller]
fn into_sim_value(self, ty: Bundle) -> SimValue<Bundle> {
#![allow(unused_mut)]
#![allow(clippy::unused_unit)]
let ($($var,)*) = self;
let [$($ty_var,)*] = *ty.fields() else {
panic!("bundle has wrong number of fields");
};
let mut bits: Option<BitVec> = None;
$(let $var = $var.into_sim_value($ty_var.ty);
assert_eq!($var.ty(), $ty_var.ty);
if !$var.bits().is_empty() {
if let Some(bits) = &mut bits {
bits.extend_from_bitslice($var.bits());
} else {
let mut $var = $var.into_bits();
$var.reserve(ty.type_properties().bit_width - $var.len());
bits = Some($var);
}
}
)*
bits.unwrap_or_else(BitVec::new).into_sim_value(ty)
}
#[track_caller]
fn box_into_sim_value(self: Box<Self>, ty: Bundle) -> SimValue<Bundle> {
Self::into_sim_value(*self, ty)
}
}
impl<$($T: ToSimValue<$Ty>, $Ty: Type,)*> ToSimValue<($($Ty,)*)> for ($($T,)*) {
#[track_caller]
fn to_sim_value(&self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
let ($($var,)*) = self;
let ($($ty_var,)*) = ty;
$(let $var = $var.to_sim_value($ty_var).into_canonical();)*
SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical()))
}
#[track_caller]
fn into_sim_value(self, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
let ($($var,)*) = self;
let ($($ty_var,)*) = ty;
$(let $var = $var.into_sim_value($ty_var).into_canonical();)*
SimValue::from_canonical(ToSimValue::into_sim_value(($($var,)*), ty.canonical()))
}
#[track_caller]
fn box_into_sim_value(self: Box<Self>, ty: ($($Ty,)*)) -> SimValue<($($Ty,)*)> {
Self::into_sim_value(*self, ty)
}
}
impl<$($Lhs: Type + ExprPartialEq<$Rhs>, $Rhs: Type,)*> ExprPartialEq<($($Rhs,)*)> for ($($Lhs,)*) {
fn cmp_eq(lhs: Expr<Self>, rhs: Expr<($($Rhs,)*)>) -> Expr<Bool> {
let ($($lhs_var,)*) = *lhs;
let ($($rhs_var,)*) = *rhs;
ArrayLiteral::<Bool, DynSize>::new(
Bool,
FromIterator::from_iter([$(Expr::canonical(ExprPartialEq::cmp_eq($lhs_var, $rhs_var)),)*]),
)
.cast_to_bits()
.all_one_bits()
}
fn cmp_ne(lhs: Expr<Self>, rhs: Expr<($($Rhs,)*)>) -> Expr<Bool> {
let ($($lhs_var,)*) = *lhs;
let ($($rhs_var,)*) = *rhs;
ArrayLiteral::<Bool, DynSize>::new(
Bool,
FromIterator::from_iter([$(Expr::canonical(ExprPartialEq::cmp_ne($lhs_var, $rhs_var)),)*]),
)
.cast_to_bits()
.any_one_bits()
}
}
}; };
([$($lhs:tt)*] [$rhs_first:tt $($rhs:tt)*]) => { ([$($lhs:tt)*] [$rhs_first:tt $($rhs:tt)*]) => {
impl_tuples!([$($lhs)*] []); impl_tuples!([$($lhs)*] []);
@ -546,18 +432,18 @@ macro_rules! impl_tuples {
impl_tuples! { impl_tuples! {
[] [ [] [
{#[num = 0, field = field_0, ty = ty0: Ty0, lhs = lhs0: Lhs0, rhs = rhs0: Rhs0] v0: T0} {#[num = 0, field = field_0] v0: T0}
{#[num = 1, field = field_1, ty = ty1: Ty1, lhs = lhs1: Lhs1, rhs = rhs1: Rhs1] v1: T1} {#[num = 1, field = field_1] v1: T1}
{#[num = 2, field = field_2, ty = ty2: Ty2, lhs = lhs2: Lhs2, rhs = rhs2: Rhs2] v2: T2} {#[num = 2, field = field_2] v2: T2}
{#[num = 3, field = field_3, ty = ty3: Ty3, lhs = lhs3: Lhs3, rhs = rhs3: Rhs3] v3: T3} {#[num = 3, field = field_3] v3: T3}
{#[num = 4, field = field_4, ty = ty4: Ty4, lhs = lhs4: Lhs4, rhs = rhs4: Rhs4] v4: T4} {#[num = 4, field = field_4] v4: T4}
{#[num = 5, field = field_5, ty = ty5: Ty5, lhs = lhs5: Lhs5, rhs = rhs5: Rhs5] v5: T5} {#[num = 5, field = field_5] v5: T5}
{#[num = 6, field = field_6, ty = ty6: Ty6, lhs = lhs6: Lhs6, rhs = rhs6: Rhs6] v6: T6} {#[num = 6, field = field_6] v6: T6}
{#[num = 7, field = field_7, ty = ty7: Ty7, lhs = lhs7: Lhs7, rhs = rhs7: Rhs7] v7: T7} {#[num = 7, field = field_7] v7: T7}
{#[num = 8, field = field_8, ty = ty8: Ty8, lhs = lhs8: Lhs8, rhs = rhs8: Rhs8] v8: T8} {#[num = 8, field = field_8] v8: T8}
{#[num = 9, field = field_9, ty = ty9: Ty9, lhs = lhs9: Lhs9, rhs = rhs9: Rhs9] v9: T9} {#[num = 9, field = field_9] v9: T9}
{#[num = 10, field = field_10, ty = ty10: Ty10, lhs = lhs10: Lhs10, rhs = rhs10: Rhs10] v10: T10} {#[num = 10, field = field_10] v10: T10}
{#[num = 11, field = field_11, ty = ty11: Ty11, lhs = lhs11: Lhs11, rhs = rhs11: Rhs11] v11: T11} {#[num = 11, field = field_11] v11: T11}
] ]
} }
@ -642,27 +528,3 @@ impl<T: ?Sized + Send + Sync + 'static> ToExpr for PhantomData<T> {
BundleLiteral::new(PhantomData, Interned::default()).to_expr() BundleLiteral::new(PhantomData, Interned::default()).to_expr()
} }
} }
impl<T: ?Sized + Send + Sync + 'static> ToSimValue<Self> for PhantomData<T> {
#[track_caller]
fn to_sim_value(&self, ty: Self) -> SimValue<Self> {
ToSimValue::into_sim_value(BitVec::new(), ty)
}
}
impl<T: ?Sized> ToSimValue<Bundle> for PhantomData<T> {
#[track_caller]
fn to_sim_value(&self, ty: Bundle) -> SimValue<Bundle> {
assert!(ty.fields().is_empty());
ToSimValue::into_sim_value(BitVec::new(), ty)
}
}
impl<T: ?Sized> ToSimValue<CanonicalType> for PhantomData<T> {
#[track_caller]
fn to_sim_value(&self, ty: CanonicalType) -> SimValue<CanonicalType> {
let ty = Bundle::from_canonical(ty);
assert!(ty.fields().is_empty());
ToSimValue::into_sim_value(BitVec::new(), ty).into_canonical()
}
}

View file

@ -4,7 +4,7 @@ use crate::{
expr::{Expr, ToExpr}, expr::{Expr, ToExpr},
hdl, hdl,
int::Bool, int::Bool,
reset::{Reset, ResetType}, reset::Reset,
source_location::SourceLocation, source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties}, ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
}; };
@ -88,9 +88,9 @@ impl ToClock for Expr<Clock> {
} }
#[hdl] #[hdl]
pub struct ClockDomain<R: ResetType = Reset> { pub struct ClockDomain {
pub clk: Clock, pub clk: Clock,
pub rst: R, pub rst: Reset,
} }
impl ToClock for bool { impl ToClock for bool {

View file

@ -2,10 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
expr::{ expr::{ops::VariantAccess, Expr, ToExpr},
ops::{ExprPartialEq, VariantAccess},
Expr, ToExpr,
},
hdl, hdl,
int::Bool, int::Bool,
intern::{Intern, Interned}, intern::{Intern, Interned},
@ -363,60 +360,6 @@ pub enum HdlOption<T: Type> {
HdlSome(T), HdlSome(T),
} }
impl<Lhs: Type + ExprPartialEq<Rhs>, Rhs: Type> ExprPartialEq<HdlOption<Rhs>> for HdlOption<Lhs> {
#[hdl]
fn cmp_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, ExprPartialEq::cmp_eq(lhs, 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_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, ExprPartialEq::cmp_ne(lhs, 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()

View file

@ -17,7 +17,6 @@ use crate::{
Instance, ModuleIO, Instance, ModuleIO,
}, },
reg::Reg, reg::Reg,
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
ty::{CanonicalType, StaticType, Type, TypeWithDeref}, ty::{CanonicalType, StaticType, Type, TypeWithDeref},
wire::Wire, wire::Wire,
}; };
@ -210,9 +209,7 @@ expr_enum! {
ModuleIO(ModuleIO<CanonicalType>), ModuleIO(ModuleIO<CanonicalType>),
Instance(Instance<Bundle>), Instance(Instance<Bundle>),
Wire(Wire<CanonicalType>), Wire(Wire<CanonicalType>),
Reg(Reg<CanonicalType, Reset>), Reg(Reg<CanonicalType>),
RegSync(Reg<CanonicalType, SyncReset>),
RegAsync(Reg<CanonicalType, AsyncReset>),
MemPort(MemPort<DynPortType>), MemPort(MemPort<DynPortType>),
} }
} }
@ -596,42 +593,25 @@ impl<T: Type> GetTarget for Wire<T> {
} }
} }
impl<T: Type, R: ResetType> ToExpr for Reg<T, R> { impl<T: Type> ToExpr for Reg<T> {
type Type = T; type Type = T;
fn to_expr(&self) -> Expr<Self::Type> { fn to_expr(&self) -> Expr<Self::Type> {
struct Dispatch;
impl ResetTypeDispatch for Dispatch {
type Input<T: ResetType> = Reg<CanonicalType, T>;
type Output<T: ResetType> = ExprEnum;
fn reset(self, input: Self::Input<Reset>) -> Self::Output<Reset> {
ExprEnum::Reg(input)
}
fn sync_reset(self, input: Self::Input<SyncReset>) -> Self::Output<SyncReset> {
ExprEnum::RegSync(input)
}
fn async_reset(self, input: Self::Input<AsyncReset>) -> Self::Output<AsyncReset> {
ExprEnum::RegAsync(input)
}
}
Expr { Expr {
__enum: R::dispatch(self.canonical(), Dispatch).intern_sized(), __enum: ExprEnum::Reg(self.canonical()).intern_sized(),
__ty: self.ty(), __ty: self.ty(),
__flow: self.flow(), __flow: self.flow(),
} }
} }
} }
impl<T: Type, R: ResetType> ToLiteralBits for Reg<T, R> { impl<T: Type> ToLiteralBits for Reg<T> {
fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> { fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> {
Err(NotALiteralExpr) Err(NotALiteralExpr)
} }
} }
impl<T: Type, R: ResetType> GetTarget for Reg<T, R> { impl<T: Type> GetTarget for Reg<T> {
fn target(&self) -> Option<Interned<Target>> { fn target(&self) -> Option<Interned<Target>> {
Some(Intern::intern_sized(self.canonical().into())) Some(Intern::intern_sized(self.canonical().into()))
} }

View file

@ -19,10 +19,7 @@ use crate::{
UIntType, UIntValue, UIntType, UIntValue,
}, },
intern::{Intern, Interned}, intern::{Intern, Interned},
reset::{ reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset},
AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset, ToAsyncReset, ToReset,
ToSyncReset,
},
ty::{CanonicalType, StaticType, Type}, ty::{CanonicalType, StaticType, Type},
util::ConstUsize, util::ConstUsize,
}; };
@ -265,7 +262,7 @@ impl Neg {
}; };
let result_ty = retval.ty(); let result_ty = retval.ty();
retval.literal_bits = arg.to_literal_bits().map(|bits| { retval.literal_bits = arg.to_literal_bits().map(|bits| {
Intern::intern_owned(result_ty.bits_from_bigint_wrapping(&-SInt::bits_to_bigint(&bits))) Intern::intern_owned(result_ty.bits_from_bigint_wrapping(-SInt::bits_to_bigint(&bits)))
}); });
retval retval
} }
@ -372,7 +369,7 @@ fn binary_op_literal_bits<ResultTy: BoolOrIntType, Lhs: BoolOrIntType, Rhs: Bool
let rhs = Rhs::bits_to_bigint(&rhs); let rhs = Rhs::bits_to_bigint(&rhs);
let result = f(lhs, rhs)?; let result = f(lhs, rhs)?;
Ok(Intern::intern_owned( Ok(Intern::intern_owned(
result_ty.bits_from_bigint_wrapping(&result), result_ty.bits_from_bigint_wrapping(result),
)) ))
} }
@ -1347,7 +1344,7 @@ macro_rules! binary_op_fixed_shift {
literal_bits: Err(NotALiteralExpr), literal_bits: Err(NotALiteralExpr),
}; };
retval.literal_bits = lhs.to_literal_bits().map(|bits| { retval.literal_bits = lhs.to_literal_bits().map(|bits| {
Intern::intern_owned(retval.ty().bits_from_bigint_wrapping(&$Trait::$method( Intern::intern_owned(retval.ty().bits_from_bigint_wrapping($Trait::$method(
$ty::bits_to_bigint(&bits), $ty::bits_to_bigint(&bits),
rhs, rhs,
))) )))
@ -1624,7 +1621,7 @@ macro_rules! impl_cast_int_op {
ty, ty,
literal_bits: arg.to_literal_bits().map(|bits| { literal_bits: arg.to_literal_bits().map(|bits| {
Intern::intern_owned( Intern::intern_owned(
ty.bits_from_bigint_wrapping(&$from::bits_to_bigint(&bits)), ty.bits_from_bigint_wrapping($from::bits_to_bigint(&bits)),
) )
}), }),
} }
@ -1776,11 +1773,11 @@ impl_cast_bit_op!(CastSIntToAsyncReset, SInt<1>, #[dyn] SInt, AsyncReset, #[trai
impl_cast_bit_op!(CastSyncResetToBool, SyncReset, Bool); impl_cast_bit_op!(CastSyncResetToBool, SyncReset, Bool);
impl_cast_bit_op!(CastSyncResetToUInt, SyncReset, UInt<1>, #[dyn] UInt); impl_cast_bit_op!(CastSyncResetToUInt, SyncReset, UInt<1>, #[dyn] UInt);
impl_cast_bit_op!(CastSyncResetToSInt, SyncReset, SInt<1>, #[dyn] SInt); impl_cast_bit_op!(CastSyncResetToSInt, SyncReset, SInt<1>, #[dyn] SInt);
impl_cast_bit_op!(CastSyncResetToReset, SyncReset, Reset); impl_cast_bit_op!(CastSyncResetToReset, SyncReset, Reset, #[trait] ToReset::to_reset);
impl_cast_bit_op!(CastAsyncResetToBool, AsyncReset, Bool); impl_cast_bit_op!(CastAsyncResetToBool, AsyncReset, Bool);
impl_cast_bit_op!(CastAsyncResetToUInt, AsyncReset, UInt<1>, #[dyn] UInt); impl_cast_bit_op!(CastAsyncResetToUInt, AsyncReset, UInt<1>, #[dyn] UInt);
impl_cast_bit_op!(CastAsyncResetToSInt, AsyncReset, SInt<1>, #[dyn] SInt); impl_cast_bit_op!(CastAsyncResetToSInt, AsyncReset, SInt<1>, #[dyn] SInt);
impl_cast_bit_op!(CastAsyncResetToReset, AsyncReset, Reset); impl_cast_bit_op!(CastAsyncResetToReset, AsyncReset, Reset, #[trait] ToReset::to_reset);
impl_cast_bit_op!(CastResetToBool, Reset, Bool); impl_cast_bit_op!(CastResetToBool, Reset, Bool);
impl_cast_bit_op!(CastResetToUInt, Reset, UInt<1>, #[dyn] UInt); impl_cast_bit_op!(CastResetToUInt, Reset, UInt<1>, #[dyn] UInt);
impl_cast_bit_op!(CastResetToSInt, Reset, SInt<1>, #[dyn] SInt); impl_cast_bit_op!(CastResetToSInt, Reset, SInt<1>, #[dyn] SInt);
@ -1791,107 +1788,6 @@ impl_cast_bit_op!(CastClockToBool, Clock, Bool);
impl_cast_bit_op!(CastClockToUInt, Clock, UInt<1>, #[dyn] UInt); impl_cast_bit_op!(CastClockToUInt, Clock, UInt<1>, #[dyn] UInt);
impl_cast_bit_op!(CastClockToSInt, Clock, SInt<1>, #[dyn] SInt); impl_cast_bit_op!(CastClockToSInt, Clock, SInt<1>, #[dyn] SInt);
impl<T: ResetType> ToReset for Expr<T> {
fn to_reset(&self) -> Expr<Reset> {
struct Dispatch;
impl ResetTypeDispatch for Dispatch {
type Input<T: ResetType> = Expr<T>;
type Output<T: ResetType> = Expr<Reset>;
fn reset(self, input: Self::Input<Reset>) -> Self::Output<Reset> {
input
}
fn sync_reset(self, input: Self::Input<SyncReset>) -> Self::Output<SyncReset> {
input.cast_to_static()
}
fn async_reset(self, input: Self::Input<AsyncReset>) -> Self::Output<AsyncReset> {
input.cast_to_static()
}
}
T::dispatch(*self, Dispatch)
}
}
impl ExprCastTo<AsyncReset> for AsyncReset {
fn cast_to(src: Expr<Self>, _to_type: AsyncReset) -> Expr<AsyncReset> {
src
}
}
impl ExprCastTo<SyncReset> for AsyncReset {
fn cast_to(src: Expr<Self>, to_type: SyncReset) -> Expr<SyncReset> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<Clock> for AsyncReset {
fn cast_to(src: Expr<Self>, to_type: Clock) -> Expr<Clock> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<AsyncReset> for SyncReset {
fn cast_to(src: Expr<Self>, to_type: AsyncReset) -> Expr<AsyncReset> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<SyncReset> for SyncReset {
fn cast_to(src: Expr<Self>, _to_type: SyncReset) -> Expr<SyncReset> {
src
}
}
impl ExprCastTo<Clock> for SyncReset {
fn cast_to(src: Expr<Self>, to_type: Clock) -> Expr<Clock> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<AsyncReset> for Reset {
fn cast_to(src: Expr<Self>, to_type: AsyncReset) -> Expr<AsyncReset> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<SyncReset> for Reset {
fn cast_to(src: Expr<Self>, to_type: SyncReset) -> Expr<SyncReset> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<Reset> for Reset {
fn cast_to(src: Expr<Self>, _to_type: Reset) -> Expr<Reset> {
src
}
}
impl ExprCastTo<Clock> for Reset {
fn cast_to(src: Expr<Self>, to_type: Clock) -> Expr<Clock> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<AsyncReset> for Clock {
fn cast_to(src: Expr<Self>, to_type: AsyncReset) -> Expr<AsyncReset> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<SyncReset> for Clock {
fn cast_to(src: Expr<Self>, to_type: SyncReset) -> Expr<SyncReset> {
src.cast_to(Bool).cast_to(to_type)
}
}
impl ExprCastTo<Clock> for Clock {
fn cast_to(src: Expr<Self>, _to_type: Clock) -> Expr<Clock> {
src
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct FieldAccess<FieldType: Type = CanonicalType> { pub struct FieldAccess<FieldType: Type = CanonicalType> {
base: Expr<Bundle>, base: Expr<Bundle>,

View file

@ -3,19 +3,18 @@
use crate::{ use crate::{
array::Array, array::Array,
bundle::{Bundle, BundleField}, bundle::{Bundle, BundleField},
expr::{Expr, Flow, ToExpr}, expr::Flow,
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},
source_location::SourceLocation, source_location::SourceLocation,
ty::{CanonicalType, Type}, ty::{CanonicalType, Type},
wire::Wire, wire::Wire,
}; };
use std::fmt; use std::fmt;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TargetPathBundleField { pub struct TargetPathBundleField {
pub name: Interned<str>, pub name: Interned<str>,
} }
@ -26,7 +25,7 @@ impl fmt::Display for TargetPathBundleField {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TargetPathArrayElement { pub struct TargetPathArrayElement {
pub index: usize, pub index: usize,
} }
@ -37,7 +36,7 @@ impl fmt::Display for TargetPathArrayElement {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TargetPathDynArrayElement {} pub struct TargetPathDynArrayElement {}
impl fmt::Display for TargetPathDynArrayElement { impl fmt::Display for TargetPathDynArrayElement {
@ -46,7 +45,7 @@ impl fmt::Display for TargetPathDynArrayElement {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TargetPathElement { pub enum TargetPathElement {
BundleField(TargetPathBundleField), BundleField(TargetPathBundleField),
ArrayElement(TargetPathArrayElement), ArrayElement(TargetPathArrayElement),
@ -128,7 +127,6 @@ macro_rules! impl_target_base {
$(#[$enum_meta:meta])* $(#[$enum_meta:meta])*
$enum_vis:vis enum $TargetBase:ident { $enum_vis:vis enum $TargetBase:ident {
$( $(
$(#[from = $from:ident])?
#[is = $is_fn:ident] #[is = $is_fn:ident]
#[to = $to_fn:ident] #[to = $to_fn:ident]
$(#[$variant_meta:meta])* $(#[$variant_meta:meta])*
@ -152,19 +150,19 @@ macro_rules! impl_target_base {
} }
} }
$($( $(
impl From<$VariantTy> for $TargetBase { impl From<$VariantTy> for $TargetBase {
fn $from(value: $VariantTy) -> Self { fn from(value: $VariantTy) -> Self {
Self::$Variant(value) Self::$Variant(value)
} }
} }
impl From<$VariantTy> for Target { impl From<$VariantTy> for Target {
fn $from(value: $VariantTy) -> Self { fn from(value: $VariantTy) -> Self {
$TargetBase::$Variant(value).into() $TargetBase::$Variant(value).into()
} }
} }
)*)? )*
impl $TargetBase { impl $TargetBase {
$( $(
@ -195,79 +193,30 @@ macro_rules! impl_target_base {
} }
} }
} }
impl ToExpr for $TargetBase {
type Type = CanonicalType;
fn to_expr(&self) -> Expr<Self::Type> {
match self {
$(Self::$Variant(v) => Expr::canonical(v.to_expr()),)*
}
}
}
}; };
} }
impl_target_base! { impl_target_base! {
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub enum TargetBase { pub enum TargetBase {
#[from = from]
#[is = is_module_io] #[is = is_module_io]
#[to = module_io] #[to = module_io]
ModuleIO(ModuleIO<CanonicalType>), ModuleIO(ModuleIO<CanonicalType>),
#[from = from]
#[is = is_mem_port] #[is = is_mem_port]
#[to = mem_port] #[to = mem_port]
MemPort(MemPort<DynPortType>), MemPort(MemPort<DynPortType>),
#[is = is_reg] #[is = is_reg]
#[to = reg] #[to = reg]
Reg(Reg<CanonicalType, Reset>), Reg(Reg<CanonicalType>),
#[is = is_reg_sync]
#[to = reg_sync]
RegSync(Reg<CanonicalType, SyncReset>),
#[is = is_reg_async]
#[to = reg_async]
RegAsync(Reg<CanonicalType, AsyncReset>),
#[from = from]
#[is = is_wire] #[is = is_wire]
#[to = wire] #[to = wire]
Wire(Wire<CanonicalType>), Wire(Wire<CanonicalType>),
#[from = from]
#[is = is_instance] #[is = is_instance]
#[to = instance] #[to = instance]
Instance(Instance<Bundle>), Instance(Instance<Bundle>),
} }
} }
impl<R: ResetType> From<Reg<CanonicalType, R>> for TargetBase {
fn from(value: Reg<CanonicalType, R>) -> Self {
struct Dispatch;
impl ResetTypeDispatch for Dispatch {
type Input<T: ResetType> = Reg<CanonicalType, T>;
type Output<T: ResetType> = TargetBase;
fn reset(self, input: Self::Input<Reset>) -> Self::Output<Reset> {
TargetBase::Reg(input)
}
fn sync_reset(self, input: Self::Input<SyncReset>) -> Self::Output<SyncReset> {
TargetBase::RegSync(input)
}
fn async_reset(self, input: Self::Input<AsyncReset>) -> Self::Output<AsyncReset> {
TargetBase::RegAsync(input)
}
}
R::dispatch(value, Dispatch)
}
}
impl<R: ResetType> From<Reg<CanonicalType, R>> for Target {
fn from(value: Reg<CanonicalType, R>) -> Self {
TargetBase::from(value).into()
}
}
impl fmt::Display for TargetBase { impl fmt::Display for TargetBase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.target_name()) write!(f, "{:?}", self.target_name())
@ -280,8 +229,6 @@ impl TargetBase {
TargetBase::ModuleIO(v) => TargetName(v.scoped_name(), None), TargetBase::ModuleIO(v) => TargetName(v.scoped_name(), None),
TargetBase::MemPort(v) => TargetName(v.mem_name(), Some(v.port_name())), TargetBase::MemPort(v) => TargetName(v.mem_name(), Some(v.port_name())),
TargetBase::Reg(v) => TargetName(v.scoped_name(), None), TargetBase::Reg(v) => TargetName(v.scoped_name(), None),
TargetBase::RegSync(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),
} }
@ -291,8 +238,6 @@ impl TargetBase {
TargetBase::ModuleIO(v) => v.ty(), TargetBase::ModuleIO(v) => v.ty(),
TargetBase::MemPort(v) => v.ty().canonical(), TargetBase::MemPort(v) => v.ty().canonical(),
TargetBase::Reg(v) => v.ty(), TargetBase::Reg(v) => v.ty(),
TargetBase::RegSync(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(),
} }
@ -368,7 +313,7 @@ impl TargetChild {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub enum Target { pub enum Target {
Base(Interned<TargetBase>), Base(Interned<TargetBase>),
Child(TargetChild), Child(TargetChild),

View file

@ -31,7 +31,7 @@ use crate::{
StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg,
StmtWire, StmtWire,
}, },
reset::{AsyncReset, Reset, ResetType, SyncReset}, reset::{AsyncReset, Reset, SyncReset},
source_location::SourceLocation, source_location::SourceLocation,
ty::{CanonicalType, Type}, ty::{CanonicalType, Type},
util::{ util::{
@ -1739,14 +1739,6 @@ impl<'a> Exporter<'a> {
assert!(!const_ty, "not a constant"); assert!(!const_ty, "not a constant");
self.module.ns.get(expr.scoped_name().1).to_string() self.module.ns.get(expr.scoped_name().1).to_string()
} }
ExprEnum::RegSync(expr) => {
assert!(!const_ty, "not a constant");
self.module.ns.get(expr.scoped_name().1).to_string()
}
ExprEnum::RegAsync(expr) => {
assert!(!const_ty, "not a constant");
self.module.ns.get(expr.scoped_name().1).to_string()
}
ExprEnum::MemPort(expr) => { ExprEnum::MemPort(expr) => {
assert!(!const_ty, "not a constant"); assert!(!const_ty, "not a constant");
let mem_name = self.module.ns.get(expr.mem_name().1); let mem_name = self.module.ns.get(expr.mem_name().1);
@ -1856,8 +1848,6 @@ impl<'a> Exporter<'a> {
self.module.ns.get(v.mem_name().1) self.module.ns.get(v.mem_name().1)
} }
TargetBase::Reg(v) => self.module.ns.get(v.name_id()), TargetBase::Reg(v) => self.module.ns.get(v.name_id()),
TargetBase::RegSync(v) => self.module.ns.get(v.name_id()),
TargetBase::RegAsync(v) => self.module.ns.get(v.name_id()),
TargetBase::Wire(v) => self.module.ns.get(v.name_id()), TargetBase::Wire(v) => self.module.ns.get(v.name_id()),
TargetBase::Instance(v) => self.module.ns.get(v.name_id()), TargetBase::Instance(v) => self.module.ns.get(v.name_id()),
}; };
@ -1966,37 +1956,6 @@ impl<'a> Exporter<'a> {
drop(memory_indent); drop(memory_indent);
Ok(body) Ok(body)
} }
fn stmt_reg<R: ResetType>(
&mut self,
stmt_reg: StmtReg<R>,
module_name: Ident,
definitions: &RcDefinitions,
body: &mut String,
) {
let StmtReg { annotations, reg } = stmt_reg;
let indent = self.indent;
self.targeted_annotations(module_name, vec![], &annotations);
let name = self.module.ns.get(reg.name_id());
let ty = self.type_state.ty(reg.ty());
let clk = self.expr(Expr::canonical(reg.clock_domain().clk), definitions, false);
if let Some(init) = reg.init() {
let rst = self.expr(Expr::canonical(reg.clock_domain().rst), definitions, false);
let init = self.expr(init, definitions, false);
writeln!(
body,
"{indent}regreset {name}: {ty}, {clk}, {rst}, {init}{}",
FileInfo::new(reg.source_location()),
)
.unwrap();
} else {
writeln!(
body,
"{indent}reg {name}: {ty}, {clk}{}",
FileInfo::new(reg.source_location()),
)
.unwrap();
}
}
fn block( fn block(
&mut self, &mut self,
module: Interned<Module<Bundle>>, module: Interned<Module<Bundle>>,
@ -2167,14 +2126,30 @@ impl<'a> Exporter<'a> {
) )
.unwrap(); .unwrap();
} }
Stmt::Declaration(StmtDeclaration::Reg(stmt_reg)) => { Stmt::Declaration(StmtDeclaration::Reg(StmtReg { annotations, reg })) => {
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body); self.targeted_annotations(module_name, vec![], &annotations);
let name = self.module.ns.get(reg.name_id());
let ty = self.type_state.ty(reg.ty());
let clk =
self.expr(Expr::canonical(reg.clock_domain().clk), &definitions, false);
if let Some(init) = reg.init() {
let rst =
self.expr(Expr::canonical(reg.clock_domain().rst), &definitions, false);
let init = self.expr(init, &definitions, false);
writeln!(
body,
"{indent}regreset {name}: {ty}, {clk}, {rst}, {init}{}",
FileInfo::new(reg.source_location()),
)
.unwrap();
} else {
writeln!(
body,
"{indent}reg {name}: {ty}, {clk}{}",
FileInfo::new(reg.source_location()),
)
.unwrap();
} }
Stmt::Declaration(StmtDeclaration::RegSync(stmt_reg)) => {
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body);
}
Stmt::Declaration(StmtDeclaration::RegAsync(stmt_reg)) => {
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body);
} }
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance { Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
annotations, annotations,

View file

@ -202,17 +202,17 @@ macro_rules! impl_int {
bit_width: self.width(), bit_width: self.width(),
} }
} }
pub fn bits_from_bigint_wrapping(self, v: &BigInt) -> BitVec { pub fn bits_from_bigint_wrapping(self, v: BigInt) -> BitVec {
BoolOrIntType::bits_from_bigint_wrapping(self, v) BoolOrIntType::bits_from_bigint_wrapping(self, v)
} }
pub fn from_bigint_wrapping(self, v: &BigInt) -> $value<Width> { pub fn from_bigint_wrapping(self, v: BigInt) -> $value<Width> {
$value { $value {
bits: Arc::new(self.bits_from_bigint_wrapping(v)), bits: Arc::new(self.bits_from_bigint_wrapping(v)),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
pub fn from_int_wrapping(self, v: impl Into<BigInt>) -> $value<Width> { pub fn from_int_wrapping(self, v: impl Into<BigInt>) -> $value<Width> {
self.from_bigint_wrapping(&v.into()) self.from_bigint_wrapping(v.into())
} }
pub fn zero(self) -> $value<Width> { pub fn zero(self) -> $value<Width> {
self.from_int_wrapping(0u8) self.from_int_wrapping(0u8)
@ -227,29 +227,12 @@ macro_rules! impl_int {
impl<Width: Size> BoolOrIntType for $name<Width> { impl<Width: Size> BoolOrIntType for $name<Width> {
type Width = Width; type Width = Width;
type Signed = ConstBool<$SIGNED>; type Signed = ConstBool<$SIGNED>;
type Value = $value<Width>;
fn width(self) -> usize { fn width(self) -> usize {
$name::width(self) $name::width(self)
} }
fn new(width: Width::SizeType) -> Self { fn new(width: Width::SizeType) -> Self {
$name { width } $name { width }
} }
fn value_from_bigint_wrapping(self, v: &BigInt) -> Self::Value {
$value::<Width>::from_bigint_wrapping(self, v)
}
fn bits_to_value(bits: Cow<'_, BitSlice>) -> Self::Value {
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
struct MemoizeBitsToValue;
impl Memoize for MemoizeBitsToValue {
type Input = BitSlice;
type InputOwned = BitVec;
type Output = Arc<BitVec>;
fn inner(self, input: &Self::Input) -> Self::Output {
Arc::new(input.to_bitvec())
}
}
$value::new(MemoizeBitsToValue.get_cow(bits))
}
fn bits_to_expr(bits: Cow<'_, BitSlice>) -> Expr<Self> { fn bits_to_expr(bits: Cow<'_, BitSlice>) -> Expr<Self> {
#[derive(Copy, Clone, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Eq, PartialEq, Hash)]
struct MemoizeBitsToExpr; struct MemoizeBitsToExpr;
@ -351,24 +334,6 @@ macro_rules! impl_int {
} }
} }
impl<Width: Size> PartialOrd for $value<Width> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<Width: Size> Ord for $value<Width> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.to_bigint().cmp(&other.to_bigint())
}
}
impl<Width: Size> From<$value<Width>> for BigInt {
fn from(v: $value<Width>) -> BigInt {
v.to_bigint()
}
}
impl<Width: Size> $value<Width> { impl<Width: Size> $value<Width> {
pub fn width(&self) -> usize { pub fn width(&self) -> usize {
if let Some(retval) = Width::KNOWN_VALUE { if let Some(retval) = Width::KNOWN_VALUE {
@ -378,7 +343,7 @@ macro_rules! impl_int {
self.bits.len() self.bits.len()
} }
} }
pub fn from_bigint_wrapping(ty: $name<Width>, v: &BigInt) -> $value<Width> { pub fn from_bigint_wrapping(ty: $name<Width>, v: BigInt) -> $value<Width> {
ty.from_bigint_wrapping(v) ty.from_bigint_wrapping(v)
} }
pub fn to_bigint(&self) -> BigInt { pub fn to_bigint(&self) -> BigInt {
@ -520,19 +485,6 @@ macro_rules! impl_prim_int {
$(#[$meta:meta])* $(#[$meta:meta])*
$prim_int:ident, $ty:ty $prim_int:ident, $ty:ty
) => { ) => {
impl From<$prim_int> for <$ty as BoolOrIntType>::Value {
fn from(v: $prim_int) -> Self {
<$ty>::le_bytes_to_value_wrapping(
&v.to_le_bytes(),
<$ty as BoolOrIntType>::Width::VALUE,
)
}
}
impl From<NonZero<$prim_int>> for <$ty as BoolOrIntType>::Value {
fn from(v: NonZero<$prim_int>) -> Self {
v.get().into()
}
}
$(#[$meta])* $(#[$meta])*
impl ToExpr for $prim_int { impl ToExpr for $prim_int {
type Type = $ty; type Type = $ty;
@ -549,7 +501,10 @@ macro_rules! impl_prim_int {
type Type = $ty; type Type = $ty;
fn to_expr(&self) -> Expr<Self::Type> { fn to_expr(&self) -> Expr<Self::Type> {
self.get().to_expr() <$ty>::le_bytes_to_expr_wrapping(
&self.get().to_le_bytes(),
<$ty as BoolOrIntType>::Width::VALUE,
)
} }
} }
}; };
@ -567,27 +522,18 @@ impl_prim_int!(i64, SInt<64>);
impl_prim_int!(i128, SInt<128>); impl_prim_int!(i128, SInt<128>);
impl_prim_int!( impl_prim_int!(
/// for portability reasons, [`usize`] always translates to [`UInt<64>`][type@UInt] /// for portability reasons, [`usize`] always translates to [`UInt<64>`]
usize, UInt<64> usize, UInt<64>
); );
impl_prim_int!( impl_prim_int!(
/// for portability reasons, [`isize`] always translates to [`SInt<64>`][type@SInt] /// for portability reasons, [`isize`] always translates to [`SInt<64>`]
isize, SInt<64> isize, SInt<64>
); );
pub trait BoolOrIntType: Type + sealed::BoolOrIntTypeSealed { pub trait BoolOrIntType: Type + sealed::BoolOrIntTypeSealed {
type Width: Size; type Width: Size;
type Signed: GenericConstBool; type Signed: GenericConstBool;
type Value: Clone
+ Ord
+ std::hash::Hash
+ fmt::Debug
+ Send
+ Sync
+ 'static
+ ToExpr<Type = Self>
+ Into<BigInt>;
fn width(self) -> usize; fn width(self) -> usize;
fn new(width: <Self::Width as Size>::SizeType) -> Self; fn new(width: <Self::Width as Size>::SizeType) -> Self;
fn new_static() -> Self fn new_static() -> Self
@ -602,24 +548,17 @@ pub trait BoolOrIntType: Type + sealed::BoolOrIntTypeSealed {
fn as_same_width_uint(self) -> UIntType<Self::Width> { fn as_same_width_uint(self) -> UIntType<Self::Width> {
UIntType::new(Self::Width::from_usize(self.width())) UIntType::new(Self::Width::from_usize(self.width()))
} }
fn value_from_int_wrapping(self, v: impl Into<BigInt>) -> Self::Value { fn bits_from_bigint_wrapping(self, v: BigInt) -> BitVec {
self.value_from_bigint_wrapping(&v.into()) let width = self.width();
}
fn value_from_bigint_wrapping(self, v: &BigInt) -> Self::Value;
fn bits_from_bigint_wrapping(self, v: &BigInt) -> BitVec {
let mut bits = BitVec::repeat(false, self.width());
Self::copy_bits_from_bigint_wrapping(v, &mut bits);
bits
}
fn copy_bits_from_bigint_wrapping(v: &BigInt, bits: &mut BitSlice) {
let width = bits.len();
let mut bytes = v.to_signed_bytes_le(); let mut bytes = v.to_signed_bytes_le();
bytes.resize( bytes.resize(
width.div_ceil(u8::BITS as usize), width.div_ceil(u8::BITS as usize),
if v.is_negative() { 0xFF } else { 0 }, if v.is_negative() { 0xFF } else { 0 },
); );
let bitslice = &BitSlice::<u8, Lsb0>::from_slice(&bytes)[..width]; let bitslice = &BitSlice::<u8, Lsb0>::from_slice(&bytes)[..width];
bits.clone_from_bitslice(bitslice); let mut bits = BitVec::new();
bits.extend_from_bitslice(bitslice);
bits
} }
fn bits_to_bigint(bits: &BitSlice) -> BigInt { fn bits_to_bigint(bits: &BitSlice) -> BigInt {
let sign_byte = if Self::Signed::VALUE && bits.last().as_deref().copied().unwrap_or(false) { let sign_byte = if Self::Signed::VALUE && bits.last().as_deref().copied().unwrap_or(false) {
@ -631,9 +570,8 @@ pub trait BoolOrIntType: Type + sealed::BoolOrIntTypeSealed {
BitSlice::<u8, Lsb0>::from_slice_mut(&mut bytes)[..bits.len()].clone_from_bitslice(bits); BitSlice::<u8, Lsb0>::from_slice_mut(&mut bytes)[..bits.len()].clone_from_bitslice(bits);
BigInt::from_signed_bytes_le(&bytes) BigInt::from_signed_bytes_le(&bytes)
} }
fn bits_to_value(bits: Cow<'_, BitSlice>) -> Self::Value;
fn bits_to_expr(bits: Cow<'_, BitSlice>) -> Expr<Self>; fn bits_to_expr(bits: Cow<'_, BitSlice>) -> Expr<Self>;
fn le_bytes_to_bits_wrapping(bytes: &[u8], bit_width: usize) -> BitVec { fn le_bytes_to_expr_wrapping(bytes: &[u8], bit_width: usize) -> Expr<Self> {
let bitslice = BitSlice::<u8, Lsb0>::from_slice(bytes); let bitslice = BitSlice::<u8, Lsb0>::from_slice(bytes);
let bitslice = &bitslice[..bit_width.min(bitslice.len())]; let bitslice = &bitslice[..bit_width.min(bitslice.len())];
let mut bits = BitVec::new(); let mut bits = BitVec::new();
@ -642,17 +580,7 @@ pub trait BoolOrIntType: Type + sealed::BoolOrIntTypeSealed {
bit_width, bit_width,
Self::Signed::VALUE && bits.last().as_deref().copied().unwrap_or(false), Self::Signed::VALUE && bits.last().as_deref().copied().unwrap_or(false),
); );
bits Self::bits_to_expr(Cow::Owned(bits))
}
fn le_bytes_to_expr_wrapping(bytes: &[u8], bit_width: usize) -> Expr<Self> {
Self::bits_to_expr(Cow::Owned(Self::le_bytes_to_bits_wrapping(
bytes, bit_width,
)))
}
fn le_bytes_to_value_wrapping(bytes: &[u8], bit_width: usize) -> Self::Value {
Self::bits_to_value(Cow::Owned(Self::le_bytes_to_bits_wrapping(
bytes, bit_width,
)))
} }
} }
@ -704,7 +632,6 @@ impl sealed::BoolOrIntTypeSealed for Bool {}
impl BoolOrIntType for Bool { impl BoolOrIntType for Bool {
type Width = ConstUsize<1>; type Width = ConstUsize<1>;
type Signed = ConstBool<false>; type Signed = ConstBool<false>;
type Value = bool;
fn width(self) -> usize { fn width(self) -> usize {
1 1
@ -715,19 +642,10 @@ impl BoolOrIntType for Bool {
Bool Bool
} }
fn value_from_bigint_wrapping(self, v: &BigInt) -> Self::Value {
v.bit(0)
}
fn bits_to_expr(bits: Cow<'_, BitSlice>) -> Expr<Self> { fn bits_to_expr(bits: Cow<'_, BitSlice>) -> Expr<Self> {
assert_eq!(bits.len(), 1); assert_eq!(bits.len(), 1);
bits[0].to_expr() bits[0].to_expr()
} }
fn bits_to_value(bits: Cow<'_, BitSlice>) -> Self::Value {
assert_eq!(bits.len(), 1);
bits[0]
}
} }
impl Bool { impl Bool {

View file

@ -11,59 +11,6 @@ extern crate self as fayalite;
#[doc(hidden)] #[doc(hidden)]
pub use std as __std; pub use std as __std;
#[doc(hidden)]
#[macro_export]
macro_rules! __cfg_expansion_helper {
(
[
$($evaluated_cfgs:ident($($evaluated_exprs:tt)*) = $evaluated_results:ident,)*
]
[
$cfg:ident($($expr:tt)*),
$($unevaluated_cfgs:ident($($unevaluated_exprs:tt)*),)*
]
// pass as tt so we get right span for attribute
$after_evaluation_attr:tt $after_evaluation_body:tt
) => {
#[$cfg($($expr)*)]
$crate::__cfg_expansion_helper! {
[
$($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)*
$cfg($($expr)*) = true,
]
[
$($unevaluated_cfgs($($unevaluated_exprs)*),)*
]
$after_evaluation_attr $after_evaluation_body
}
#[$cfg(not($($expr)*))]
$crate::__cfg_expansion_helper! {
[
$($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)*
$cfg($($expr)*) = false,
]
[
$($unevaluated_cfgs($($unevaluated_exprs)*),)*
]
$after_evaluation_attr $after_evaluation_body
}
};
(
[
$($evaluated_cfgs:ident($($evaluated_exprs:tt)*) = $evaluated_results:ident,)*
]
[]
// don't use #[...] so we get right span for `#` and `[]` of attribute
{$($after_evaluation_attr:tt)*} {$($after_evaluation_body:tt)*}
) => {
$($after_evaluation_attr)*
#[__evaluated_cfgs([
$($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)*
])]
$($after_evaluation_body)*
};
}
#[doc(inline)] #[doc(inline)]
/// The `#[hdl_module]` attribute is applied to a Rust function so that that function creates /// The `#[hdl_module]` attribute is applied to a Rust function so that that function creates
/// a [`Module`][`::fayalite::module::Module`] when called. /// a [`Module`][`::fayalite::module::Module`] when called.
@ -99,7 +46,6 @@ pub mod module;
pub mod prelude; pub mod prelude;
pub mod reg; pub mod reg;
pub mod reset; pub mod reset;
pub mod sim;
pub mod source_location; pub mod source_location;
pub mod testing; pub mod testing;
pub mod ty; pub mod ty;

View file

@ -22,7 +22,7 @@ use std::{
fmt, fmt,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
marker::PhantomData, marker::PhantomData,
num::NonZeroUsize, num::NonZeroU32,
rc::Rc, rc::Rc,
}; };
@ -478,7 +478,7 @@ struct MemImpl<Element: Type, Len: Size, P> {
initial_value: Option<Interned<BitSlice>>, initial_value: Option<Interned<BitSlice>>,
ports: P, ports: P,
read_latency: usize, read_latency: usize,
write_latency: NonZeroUsize, write_latency: NonZeroU32,
read_under_write: ReadUnderWrite, read_under_write: ReadUnderWrite,
port_annotations: Interned<[TargetedAnnotation]>, port_annotations: Interned<[TargetedAnnotation]>,
mem_annotations: Interned<[Annotation]>, mem_annotations: Interned<[Annotation]>,
@ -519,12 +519,7 @@ impl<Element: Type, Len: Size> fmt::Debug for Mem<Element, Len> {
f.debug_struct("Mem") f.debug_struct("Mem")
.field("name", scoped_name) .field("name", scoped_name)
.field("array_type", array_type) .field("array_type", array_type)
.field( .field("initial_value", initial_value)
"initial_value",
&initial_value.as_ref().map(|initial_value| {
DebugMemoryData::from_bit_slice(*array_type, initial_value)
}),
)
.field("read_latency", read_latency) .field("read_latency", read_latency)
.field("write_latency", write_latency) .field("write_latency", write_latency)
.field("read_under_write", read_under_write) .field("read_under_write", read_under_write)
@ -567,7 +562,7 @@ impl<Element: Type, Len: Size> Mem<Element, Len> {
initial_value: Option<Interned<BitSlice>>, initial_value: Option<Interned<BitSlice>>,
ports: Interned<[MemPort<DynPortType>]>, ports: Interned<[MemPort<DynPortType>]>,
read_latency: usize, read_latency: usize,
write_latency: NonZeroUsize, write_latency: NonZeroU32,
read_under_write: ReadUnderWrite, read_under_write: ReadUnderWrite,
port_annotations: Interned<[TargetedAnnotation]>, port_annotations: Interned<[TargetedAnnotation]>,
mem_annotations: Interned<[Annotation]>, mem_annotations: Interned<[Annotation]>,
@ -650,7 +645,7 @@ impl<Element: Type, Len: Size> Mem<Element, Len> {
pub fn read_latency(self) -> usize { pub fn read_latency(self) -> usize {
self.0.read_latency self.0.read_latency
} }
pub fn write_latency(self) -> NonZeroUsize { pub fn write_latency(self) -> NonZeroU32 {
self.0.write_latency self.0.write_latency
} }
pub fn read_under_write(self) -> ReadUnderWrite { pub fn read_under_write(self) -> ReadUnderWrite {
@ -712,7 +707,7 @@ pub(crate) struct MemBuilderTarget {
pub(crate) initial_value: Option<Interned<BitSlice>>, pub(crate) initial_value: Option<Interned<BitSlice>>,
pub(crate) ports: Vec<MemPort<DynPortType>>, pub(crate) ports: Vec<MemPort<DynPortType>>,
pub(crate) read_latency: usize, pub(crate) read_latency: usize,
pub(crate) write_latency: NonZeroUsize, pub(crate) write_latency: NonZeroU32,
pub(crate) read_under_write: ReadUnderWrite, pub(crate) read_under_write: ReadUnderWrite,
pub(crate) port_annotations: Vec<TargetedAnnotation>, pub(crate) port_annotations: Vec<TargetedAnnotation>,
pub(crate) mem_annotations: Vec<Annotation>, pub(crate) mem_annotations: Vec<Annotation>,
@ -872,7 +867,7 @@ impl<Element: Type, Len: Size> MemBuilder<Element, Len> {
initial_value: None, initial_value: None,
ports: vec![], ports: vec![],
read_latency: 0, read_latency: 0,
write_latency: NonZeroUsize::new(1).unwrap(), write_latency: NonZeroU32::new(1).unwrap(),
read_under_write: ReadUnderWrite::Old, read_under_write: ReadUnderWrite::Old,
port_annotations: vec![], port_annotations: vec![],
mem_annotations: vec![], mem_annotations: vec![],
@ -1035,10 +1030,10 @@ impl<Element: Type, Len: Size> MemBuilder<Element, Len> {
pub fn read_latency(&mut self, read_latency: usize) { pub fn read_latency(&mut self, read_latency: usize) {
self.target.borrow_mut().read_latency = read_latency; self.target.borrow_mut().read_latency = read_latency;
} }
pub fn get_write_latency(&self) -> NonZeroUsize { pub fn get_write_latency(&self) -> NonZeroU32 {
self.target.borrow().write_latency self.target.borrow().write_latency
} }
pub fn write_latency(&mut self, write_latency: NonZeroUsize) { pub fn write_latency(&mut self, write_latency: NonZeroU32) {
self.target.borrow_mut().write_latency = write_latency; self.target.borrow_mut().write_latency = write_latency;
} }
pub fn get_read_under_write(&self) -> ReadUnderWrite { pub fn get_read_under_write(&self) -> ReadUnderWrite {
@ -1084,61 +1079,3 @@ pub fn splat_mask<T: Type>(ty: T, value: Expr<Bool>) -> Expr<AsMask<T>> {
)), )),
} }
} }
pub trait DebugMemoryDataGetElement {
fn get_element(&self, element_index: usize, array_type: Array) -> &BitSlice;
}
impl<'a, F: ?Sized + Fn(usize, Array) -> &'a BitSlice> DebugMemoryDataGetElement for &'a F {
fn get_element(&self, element_index: usize, array_type: Array) -> &BitSlice {
self(element_index, array_type)
}
}
#[derive(Clone)]
pub struct DebugMemoryData<GetElement: DebugMemoryDataGetElement> {
pub array_type: Array,
pub get_element: GetElement,
}
impl DebugMemoryDataGetElement for &'_ BitSlice {
fn get_element(&self, element_index: usize, array_type: Array) -> &BitSlice {
assert!(element_index < array_type.len());
let stride = array_type.element().bit_width();
let start = element_index
.checked_mul(stride)
.expect("memory is too big");
let end = start.checked_add(stride).expect("memory is too big");
&self[start..end]
}
}
impl<'a> DebugMemoryData<&'a BitSlice> {
pub fn from_bit_slice<T: Type, Depth: Size>(
array_type: ArrayType<T, Depth>,
bit_slice: &'a BitSlice,
) -> Self {
let array_type = array_type.as_dyn_array();
assert_eq!(bit_slice.len(), array_type.type_properties().bit_width);
Self {
array_type,
get_element: bit_slice,
}
}
}
impl<GetElement: DebugMemoryDataGetElement> fmt::Debug for DebugMemoryData<GetElement> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.array_type.len() == 0 {
return f.write_str("[]");
}
writeln!(f, "[\n // len = {:#x}", self.array_type.len())?;
for element_index in 0..self.array_type.len() {
let element = crate::util::BitSliceWriteWithBase(
self.get_element.get_element(element_index, self.array_type),
);
writeln!(f, " [{element_index:#x}]: {element:#x},")?;
}
f.write_str("]")
}
}

View file

@ -20,7 +20,6 @@ use crate::{
intern::{Intern, Interned}, intern::{Intern, Interned},
memory::{Mem, MemBuilder, MemBuilderTarget, PortName}, memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
reg::Reg, reg::Reg,
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
source_location::SourceLocation, source_location::SourceLocation,
ty::{CanonicalType, Type}, ty::{CanonicalType, Type},
util::ScopedRef, util::ScopedRef,
@ -181,7 +180,7 @@ impl Block {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub struct StmtConnect { pub struct StmtConnect {
pub lhs: Expr<CanonicalType>, pub lhs: Expr<CanonicalType>,
pub rhs: Expr<CanonicalType>, pub rhs: Expr<CanonicalType>,
@ -236,7 +235,7 @@ impl fmt::Debug for StmtConnect {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub struct StmtFormal { pub struct StmtFormal {
pub kind: FormalKind, pub kind: FormalKind,
pub clk: Expr<Clock>, pub clk: Expr<Clock>,
@ -285,8 +284,6 @@ pub struct StmtIf<S: ModuleBuildingStatus = ModuleBuilt> {
pub blocks: [S::Block; 2], pub blocks: [S::Block; 2],
} }
impl Copy for StmtIf {}
impl<S: ModuleBuildingStatus> StmtIf<S> { impl<S: ModuleBuildingStatus> StmtIf<S> {
pub fn then_block(&self) -> S::Block { pub fn then_block(&self) -> S::Block {
self.blocks[0] self.blocks[0]
@ -318,8 +315,6 @@ pub struct StmtMatch<S: ModuleBuildingStatus = ModuleBuilt> {
pub blocks: Interned<[S::Block]>, pub blocks: Interned<[S::Block]>,
} }
impl Copy for StmtMatch {}
impl StmtMatch { impl StmtMatch {
#[track_caller] #[track_caller]
fn assert_validity(&self) { fn assert_validity(&self) {
@ -351,7 +346,7 @@ macro_rules! wrapper_enum {
$(#[$enum_meta:meta])* $(#[$enum_meta:meta])*
$vis:vis enum $enum_name:ident<$T_enum:ident: $T_bound:ident = $T_enum_default:ident> { $vis:vis enum $enum_name:ident<$T_enum:ident: $T_bound:ident = $T_enum_default:ident> {
$( $(
#[is = $is_fn:ident, as_ref = $as_ref_fn:ident $(, from = $from:ident)?] #[is = $is_fn:ident, as_ref = $as_ref_fn:ident]
$(#[$variant_meta:meta])* $(#[$variant_meta:meta])*
$Variant:ident($VariantTy:ty), $Variant:ident($VariantTy:ty),
)* )*
@ -363,7 +358,7 @@ macro_rules! wrapper_enum {
$(#[$enum_meta])* $(#[$enum_meta])*
$vis enum $enum_name<$T_enum: $T_bound = $T_enum_default> { $vis enum $enum_name<$T_enum: $T_bound = $T_enum_default> {
$( $(
#[is = $is_fn, as_ref = $as_ref_fn $(, from = $from)?] #[is = $is_fn, as_ref = $as_ref_fn]
$(#[$variant_meta])* $(#[$variant_meta])*
$Variant($VariantTy), $Variant($VariantTy),
)* )*
@ -390,7 +385,7 @@ macro_rules! wrapper_enum {
$(#[$enum_meta:meta])* $(#[$enum_meta:meta])*
$vis:vis enum $enum_name:ident<$T_enum:ident: $T_bound:ident = $T_enum_default:ident> { $vis:vis enum $enum_name:ident<$T_enum:ident: $T_bound:ident = $T_enum_default:ident> {
$( $(
#[is = $is_fn:ident, as_ref = $as_ref_fn:ident $(, from = $from:ident)?] #[is = $is_fn:ident, as_ref = $as_ref_fn:ident]
$(#[$variant_meta:meta])* $(#[$variant_meta:meta])*
$Variant:ident($VariantTy:ty), $Variant:ident($VariantTy:ty),
)* )*
@ -402,22 +397,22 @@ macro_rules! wrapper_enum {
$(#[$enum_meta])* $(#[$enum_meta])*
$vis enum $enum_name<$T_enum: $T_bound = $T_enum_default> { $vis enum $enum_name<$T_enum: $T_bound = $T_enum_default> {
$( $(
#[is = $is_fn, as_ref = $as_ref_fn $(, from = $from)?] #[is = $is_fn, as_ref = $as_ref_fn]
$(#[$variant_meta])* $(#[$variant_meta])*
$Variant($VariantTy), $Variant($VariantTy),
)* )*
} }
} }
$($( $(
wrapper_enum! { wrapper_enum! {
impl $T_to From<$VariantTy> for $to_type { impl $T_to From<$VariantTy> for $to_type {
fn $from(value: $VariantTy) -> Self { fn from(value: $VariantTy) -> Self {
$enum_name::$Variant(value).into() $enum_name::$Variant(value).into()
} }
} }
} }
)?)* )*
}; };
( (
#[impl()] #[impl()]
@ -425,7 +420,7 @@ macro_rules! wrapper_enum {
$(#[$enum_meta:meta])* $(#[$enum_meta:meta])*
$vis:vis enum $enum_name:ident<$T_enum:ident: $T_bound:ident = $T_enum_default:ident> { $vis:vis enum $enum_name:ident<$T_enum:ident: $T_bound:ident = $T_enum_default:ident> {
$( $(
#[is = $is_fn:ident, as_ref = $as_ref_fn:ident $(, from = $from:ident)?] #[is = $is_fn:ident, as_ref = $as_ref_fn:ident]
$(#[$variant_meta:meta])* $(#[$variant_meta:meta])*
$Variant:ident($VariantTy:ty), $Variant:ident($VariantTy:ty),
)* )*
@ -464,15 +459,13 @@ pub struct StmtWire<S: ModuleBuildingStatus = ModuleBuilt> {
pub wire: Wire<CanonicalType>, pub wire: Wire<CanonicalType>,
} }
impl Copy for StmtWire {}
#[derive(Hash, Clone, PartialEq, Eq, Debug)] #[derive(Hash, Clone, PartialEq, Eq, Debug)]
pub struct StmtReg<R: ResetType, S: ModuleBuildingStatus = ModuleBuilt> { pub struct StmtReg<S: ModuleBuildingStatus = ModuleBuilt> {
pub annotations: S::StmtAnnotations, pub annotations: S::StmtAnnotations,
pub reg: Reg<CanonicalType, R>, pub reg: Reg<CanonicalType>,
} }
impl<R: ResetType> Copy for StmtReg<R> {} impl Copy for StmtReg {}
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct StmtInstance<S: ModuleBuildingStatus = ModuleBuilt> { pub struct StmtInstance<S: ModuleBuildingStatus = ModuleBuilt> {
@ -480,8 +473,6 @@ pub struct StmtInstance<S: ModuleBuildingStatus = ModuleBuilt> {
pub instance: Instance<Bundle>, pub instance: Instance<Bundle>,
} }
impl Copy for StmtInstance {}
wrapper_enum! { wrapper_enum! {
#[impl( #[impl(
(<S: ModuleBuildingStatus>) self: StmtDeclaration<S> = self, (<S: ModuleBuildingStatus>) self: StmtDeclaration<S> = self,
@ -490,57 +481,20 @@ wrapper_enum! {
#[to((<S: ModuleBuildingStatus>) StmtDeclaration<S>, (<S: ModuleBuildingStatus>) Stmt<S>)] #[to((<S: ModuleBuildingStatus>) StmtDeclaration<S>, (<S: ModuleBuildingStatus>) Stmt<S>)]
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub enum StmtDeclaration<S: ModuleBuildingStatus = ModuleBuilt> { pub enum StmtDeclaration<S: ModuleBuildingStatus = ModuleBuilt> {
#[is = is_wire, as_ref = wire, from = from] #[is = is_wire, as_ref = wire]
Wire(StmtWire<S>), Wire(StmtWire<S>),
#[is = is_reg, as_ref = reg] #[is = is_reg, as_ref = reg]
Reg(StmtReg<Reset, S>), Reg(StmtReg<S>),
#[is = is_reg_sync, as_ref = reg_sync] #[is = is_instance, as_ref = instance]
RegSync(StmtReg<SyncReset, S>),
#[is = is_reg_async, as_ref = reg_async]
RegAsync(StmtReg<AsyncReset, S>),
#[is = is_instance, as_ref = instance, from = from]
Instance(StmtInstance<S>), Instance(StmtInstance<S>),
} }
} }
impl Copy for StmtDeclaration {}
impl<S: ModuleBuildingStatus, R: ResetType> From<StmtReg<R, S>> for Stmt<S> {
fn from(value: StmtReg<R, S>) -> Self {
StmtDeclaration::from(value).into()
}
}
impl<S: ModuleBuildingStatus, R: ResetType> From<StmtReg<R, S>> for StmtDeclaration<S> {
fn from(value: StmtReg<R, S>) -> Self {
struct Dispatch<S>(PhantomData<S>);
impl<S: ModuleBuildingStatus> ResetTypeDispatch for Dispatch<S> {
type Input<T: ResetType> = StmtReg<T, S>;
type Output<T: ResetType> = StmtDeclaration<S>;
fn reset(self, input: Self::Input<Reset>) -> Self::Output<Reset> {
StmtDeclaration::Reg(input)
}
fn sync_reset(self, input: Self::Input<SyncReset>) -> Self::Output<SyncReset> {
StmtDeclaration::RegSync(input)
}
fn async_reset(self, input: Self::Input<AsyncReset>) -> Self::Output<AsyncReset> {
StmtDeclaration::RegAsync(input)
}
}
R::dispatch(value, Dispatch(PhantomData))
}
}
impl<S: ModuleBuildingStatus> StmtDeclaration<S> { impl<S: ModuleBuildingStatus> StmtDeclaration<S> {
pub fn annotations(&self) -> S::StmtAnnotations { pub fn annotations(&self) -> S::StmtAnnotations {
match self { match self {
StmtDeclaration::Wire(v) => v.annotations, StmtDeclaration::Wire(v) => v.annotations,
StmtDeclaration::Reg(v) => v.annotations, StmtDeclaration::Reg(v) => v.annotations,
StmtDeclaration::RegSync(v) => v.annotations,
StmtDeclaration::RegAsync(v) => v.annotations,
StmtDeclaration::Instance(v) => v.annotations, StmtDeclaration::Instance(v) => v.annotations,
} }
} }
@ -548,8 +502,6 @@ impl<S: ModuleBuildingStatus> StmtDeclaration<S> {
match self { match self {
StmtDeclaration::Wire(v) => v.wire.source_location(), StmtDeclaration::Wire(v) => v.wire.source_location(),
StmtDeclaration::Reg(v) => v.reg.source_location(), StmtDeclaration::Reg(v) => v.reg.source_location(),
StmtDeclaration::RegSync(v) => v.reg.source_location(),
StmtDeclaration::RegAsync(v) => v.reg.source_location(),
StmtDeclaration::Instance(v) => v.instance.source_location(), StmtDeclaration::Instance(v) => v.instance.source_location(),
} }
} }
@ -557,26 +509,20 @@ impl<S: ModuleBuildingStatus> StmtDeclaration<S> {
match self { match self {
StmtDeclaration::Wire(v) => v.wire.scoped_name(), StmtDeclaration::Wire(v) => v.wire.scoped_name(),
StmtDeclaration::Reg(v) => v.reg.scoped_name(), StmtDeclaration::Reg(v) => v.reg.scoped_name(),
StmtDeclaration::RegSync(v) => v.reg.scoped_name(),
StmtDeclaration::RegAsync(v) => v.reg.scoped_name(),
StmtDeclaration::Instance(v) => v.instance.scoped_name(), StmtDeclaration::Instance(v) => v.instance.scoped_name(),
} }
} }
pub fn sub_stmt_blocks(&self) -> &[S::Block] { pub fn sub_stmt_blocks(&self) -> &[S::Block] {
match self { match self {
StmtDeclaration::Wire(_) StmtDeclaration::Wire(_) | StmtDeclaration::Reg(_) | StmtDeclaration::Instance(_) => {
| StmtDeclaration::Reg(_) &[]
| StmtDeclaration::RegSync(_) }
| StmtDeclaration::RegAsync(_)
| StmtDeclaration::Instance(_) => &[],
} }
} }
pub fn canonical_ty(&self) -> CanonicalType { pub fn canonical_ty(&self) -> CanonicalType {
match self { match self {
StmtDeclaration::Wire(v) => v.wire.ty(), StmtDeclaration::Wire(v) => v.wire.ty(),
StmtDeclaration::Reg(v) => v.reg.ty(), StmtDeclaration::Reg(v) => v.reg.ty(),
StmtDeclaration::RegSync(v) => v.reg.ty(),
StmtDeclaration::RegAsync(v) => v.reg.ty(),
StmtDeclaration::Instance(v) => CanonicalType::Bundle(v.instance.ty()), StmtDeclaration::Instance(v) => CanonicalType::Bundle(v.instance.ty()),
} }
} }
@ -587,21 +533,19 @@ wrapper_enum! {
#[to((<S: ModuleBuildingStatus>) Stmt<S>)] #[to((<S: ModuleBuildingStatus>) Stmt<S>)]
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub enum Stmt<S: ModuleBuildingStatus = ModuleBuilt> { pub enum Stmt<S: ModuleBuildingStatus = ModuleBuilt> {
#[is = is_connect, as_ref = connect, from = from] #[is = is_connect, as_ref = connect]
Connect(StmtConnect), Connect(StmtConnect),
#[is = is_formal, as_ref = formal, from = from] #[is = is_formal, as_ref = formal]
Formal(StmtFormal), Formal(StmtFormal),
#[is = is_if, as_ref = if_, from = from] #[is = is_if, as_ref = if_]
If(StmtIf<S>), If(StmtIf<S>),
#[is = is_match, as_ref = match_, from = from] #[is = is_match, as_ref = match_]
Match(StmtMatch<S>), Match(StmtMatch<S>),
#[is = is_declaration, as_ref = declaration, from = from] #[is = is_declaration, as_ref = declaration]
Declaration(StmtDeclaration<S>), Declaration(StmtDeclaration<S>),
} }
} }
impl Copy for Stmt {}
impl<S: ModuleBuildingStatus> Stmt<S> { impl<S: ModuleBuildingStatus> Stmt<S> {
pub fn sub_stmt_blocks(&self) -> &[S::Block] { pub fn sub_stmt_blocks(&self) -> &[S::Block] {
match self { match self {
@ -770,18 +714,6 @@ impl<T: BundleType> Instance<T> {
source_location, source_location,
} }
} }
pub fn from_canonical(v: Instance<Bundle>) -> Self {
let Instance {
scoped_name,
instantiated,
source_location,
} = v;
Self {
scoped_name,
instantiated: Module::from_canonical(*instantiated).intern_sized(),
source_location,
}
}
pub fn containing_module_name(self) -> Interned<str> { pub fn containing_module_name(self) -> Interned<str> {
self.containing_module_name_id().0 self.containing_module_name_id().0
} }
@ -1026,14 +958,6 @@ impl From<NormalModuleBody<ModuleBuilding>> for NormalModuleBody {
annotations: (), annotations: (),
reg, reg,
}) => StmtReg { annotations, reg }.into(), }) => StmtReg { annotations, reg }.into(),
StmtDeclaration::RegSync(StmtReg {
annotations: (),
reg,
}) => StmtReg { annotations, reg }.into(),
StmtDeclaration::RegAsync(StmtReg {
annotations: (),
reg,
}) => StmtReg { annotations, reg }.into(),
StmtDeclaration::Instance(StmtInstance { StmtDeclaration::Instance(StmtInstance {
annotations: (), annotations: (),
instance, instance,
@ -1737,14 +1661,6 @@ impl AssertValidityState {
annotations: _, annotations: _,
reg, reg,
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block), })) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
Stmt::Declaration(StmtDeclaration::RegSync(StmtReg {
annotations: _,
reg,
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
Stmt::Declaration(StmtDeclaration::RegAsync(StmtReg {
annotations: _,
reg,
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance { Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
annotations: _, annotations: _,
instance, instance,
@ -1926,10 +1842,10 @@ impl<CD> RegBuilder<CD, (), ()> {
} }
impl<I, T: Type> RegBuilder<(), I, T> { impl<I, T: Type> RegBuilder<(), I, T> {
pub fn clock_domain<R: ResetType>( pub fn clock_domain(
self, self,
clock_domain: impl ToExpr<Type = ClockDomain<R>>, clock_domain: impl ToExpr<Type = ClockDomain>,
) -> RegBuilder<Expr<ClockDomain<R>>, I, T> { ) -> RegBuilder<Expr<ClockDomain>, I, T> {
let Self { let Self {
name, name,
source_location, source_location,
@ -1947,7 +1863,7 @@ impl<I, T: Type> RegBuilder<(), I, T> {
} }
} }
impl<T: Type, R: ResetType> RegBuilder<Expr<ClockDomain<R>>, Option<Expr<T>>, T> { impl<T: Type> RegBuilder<Expr<ClockDomain>, Option<Expr<T>>, T> {
#[track_caller] #[track_caller]
pub fn build(self) -> Expr<T> { pub fn build(self) -> Expr<T> {
let Self { let Self {
@ -2272,16 +2188,6 @@ pub fn annotate<T: Type>(target: Expr<T>, annotations: impl IntoAnnotations) {
reg, reg,
} }
.into(), .into(),
TargetBase::RegSync(reg) => StmtReg {
annotations: (),
reg,
}
.into(),
TargetBase::RegAsync(reg) => StmtReg {
annotations: (),
reg,
}
.into(),
TargetBase::Wire(wire) => StmtWire { TargetBase::Wire(wire) => StmtWire {
annotations: (), annotations: (),
wire, wire,
@ -2723,50 +2629,3 @@ impl<T: Type> ModuleIO<T> {
self.ty self.ty
} }
} }
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
pub enum InstantiatedModule {
Base(Interned<Module<Bundle>>),
Child {
parent: Interned<InstantiatedModule>,
instance: Interned<Instance<Bundle>>,
},
}
impl InstantiatedModule {
pub fn leaf_module(self) -> Interned<Module<Bundle>> {
match self {
InstantiatedModule::Base(base) => base,
InstantiatedModule::Child { instance, .. } => instance.instantiated(),
}
}
fn write_path(self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InstantiatedModule::Base(base) => fmt::Debug::fmt(&base.name_id(), f),
InstantiatedModule::Child { parent, instance } => {
parent.write_path(f)?;
write!(f, ".{}", instance.name_id())
}
}
}
}
impl fmt::Debug for InstantiatedModule {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "InstantiatedModule(")?;
self.write_path(f)?;
write!(f, ": {})", self.leaf_module().name_id())
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct TargetInInstantiatedModule {
pub instantiated_module: InstantiatedModule,
pub target: Target,
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct ExprInInstantiatedModule<T: Type> {
pub instantiated_module: InstantiatedModule,
pub expr: Expr<T>,
}

View file

@ -1,6 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information // See Notices.txt for copyright information
pub mod deduce_resets;
pub mod simplify_enums; pub mod simplify_enums;
pub mod simplify_memories; pub mod simplify_memories;
pub mod visit; pub mod visit;

File diff suppressed because it is too large Load diff

View file

@ -764,9 +764,7 @@ impl Folder for State {
| ExprEnum::ModuleIO(_) | ExprEnum::ModuleIO(_)
| ExprEnum::Instance(_) | ExprEnum::Instance(_)
| ExprEnum::Wire(_) | ExprEnum::Wire(_)
| ExprEnum::Reg(_) | ExprEnum::Reg(_) => op.default_fold(self),
| ExprEnum::RegSync(_)
| ExprEnum::RegAsync(_) => op.default_fold(self),
} }
} }

View file

@ -29,7 +29,7 @@ use crate::{
StmtInstance, StmtMatch, StmtReg, StmtWire, StmtInstance, StmtMatch, StmtReg, StmtWire,
}, },
reg::Reg, reg::Reg,
reset::{AsyncReset, Reset, ResetType, SyncReset}, reset::{AsyncReset, Reset, SyncReset},
source_location::SourceLocation, source_location::SourceLocation,
ty::{CanonicalType, Type}, ty::{CanonicalType, Type},
wire::Wire, wire::Wire,

View file

@ -5,22 +5,21 @@ use crate::{
expr::{Expr, Flow}, expr::{Expr, Flow},
intern::Interned, intern::Interned,
module::{NameId, ScopedNameId}, module::{NameId, ScopedNameId},
reset::{Reset, ResetType},
source_location::SourceLocation, source_location::SourceLocation,
ty::{CanonicalType, Type}, ty::{CanonicalType, Type},
}; };
use std::fmt; use std::fmt;
#[derive(Copy, Clone, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Reg<T: Type, R: ResetType = Reset> { pub struct Reg<T: Type> {
name: ScopedNameId, name: ScopedNameId,
source_location: SourceLocation, source_location: SourceLocation,
ty: T, ty: T,
clock_domain: Expr<ClockDomain<R>>, clock_domain: Expr<ClockDomain>,
init: Option<Expr<T>>, init: Option<Expr<T>>,
} }
impl<T: Type + fmt::Debug, R: ResetType> fmt::Debug for Reg<T, R> { impl<T: Type + fmt::Debug> fmt::Debug for Reg<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
name, name,
@ -38,8 +37,8 @@ impl<T: Type + fmt::Debug, R: ResetType> fmt::Debug for Reg<T, R> {
} }
} }
impl<T: Type, R: ResetType> Reg<T, R> { impl<T: Type> Reg<T> {
pub fn canonical(&self) -> Reg<CanonicalType, R> { pub fn canonical(&self) -> Reg<CanonicalType> {
let Self { let Self {
name, name,
source_location, source_location,
@ -60,7 +59,7 @@ impl<T: Type, R: ResetType> Reg<T, R> {
scoped_name: ScopedNameId, scoped_name: ScopedNameId,
source_location: SourceLocation, source_location: SourceLocation,
ty: T, ty: T,
clock_domain: Expr<ClockDomain<R>>, clock_domain: Expr<ClockDomain>,
init: Option<Expr<T>>, init: Option<Expr<T>>,
) -> Self { ) -> Self {
assert!( assert!(
@ -99,7 +98,7 @@ impl<T: Type, R: ResetType> Reg<T, R> {
pub fn scoped_name(&self) -> ScopedNameId { pub fn scoped_name(&self) -> ScopedNameId {
self.name self.name
} }
pub fn clock_domain(&self) -> Expr<ClockDomain<R>> { pub fn clock_domain(&self) -> Expr<ClockDomain> {
self.clock_domain self.clock_domain
} }
pub fn init(&self) -> Option<Expr<T>> { pub fn init(&self) -> Option<Expr<T>> {

View file

@ -1,9 +1,8 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
clock::Clock, expr::{Expr, ToExpr},
expr::{ops, Expr, ToExpr}, int::Bool,
int::{Bool, SInt, UInt},
source_location::SourceLocation, source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties}, ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
}; };
@ -12,33 +11,10 @@ mod sealed {
pub trait ResetTypeSealed {} pub trait ResetTypeSealed {}
} }
pub trait ResetType: pub trait ResetType: StaticType<MaskType = Bool> + sealed::ResetTypeSealed {}
StaticType<MaskType = Bool>
+ sealed::ResetTypeSealed
+ ops::ExprCastTo<Bool>
+ ops::ExprCastTo<Reset>
+ ops::ExprCastTo<SyncReset>
+ ops::ExprCastTo<AsyncReset>
+ ops::ExprCastTo<Clock>
+ ops::ExprCastTo<UInt<1>>
+ ops::ExprCastTo<SInt<1>>
+ ops::ExprCastTo<UInt>
+ ops::ExprCastTo<SInt>
{
fn dispatch<D: ResetTypeDispatch>(input: D::Input<Self>, dispatch: D) -> D::Output<Self>;
}
pub trait ResetTypeDispatch: Sized {
type Input<T: ResetType>;
type Output<T: ResetType>;
fn reset(self, input: Self::Input<Reset>) -> Self::Output<Reset>;
fn sync_reset(self, input: Self::Input<SyncReset>) -> Self::Output<SyncReset>;
fn async_reset(self, input: Self::Input<AsyncReset>) -> Self::Output<AsyncReset>;
}
macro_rules! reset_type { macro_rules! reset_type {
($name:ident, $(#[$impl_trait:ident])? $Trait:ident::$trait_fn:ident, $is_castable_from_bits:literal, $dispatch_fn:ident) => { ($name:ident, $Trait:ident::$trait_fn:ident, $is_castable_from_bits:literal) => {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct $name; pub struct $name;
@ -91,14 +67,7 @@ macro_rules! reset_type {
impl sealed::ResetTypeSealed for $name {} impl sealed::ResetTypeSealed for $name {}
impl ResetType for $name { impl ResetType for $name {}
fn dispatch<D: ResetTypeDispatch>(
input: D::Input<Self>,
dispatch: D,
) -> D::Output<Self> {
dispatch.$dispatch_fn(input)
}
}
pub trait $Trait { pub trait $Trait {
fn $trait_fn(&self) -> Expr<$name>; fn $trait_fn(&self) -> Expr<$name>;
@ -122,21 +91,20 @@ macro_rules! reset_type {
} }
} }
$($impl_trait $Trait for Expr<$name> { impl $Trait for Expr<$name> {
fn $trait_fn(&self) -> Expr<$name> { fn $trait_fn(&self) -> Expr<$name> {
*self *self
} }
})? }
}; };
} }
reset_type!(AsyncReset, #[impl] ToAsyncReset::to_async_reset, true, async_reset); reset_type!(AsyncReset, ToAsyncReset::to_async_reset, true);
reset_type!(SyncReset, #[impl] ToSyncReset::to_sync_reset, true, sync_reset); reset_type!(SyncReset, ToSyncReset::to_sync_reset, true);
reset_type!( reset_type!(
Reset, Reset,
ToReset::to_reset, ToReset::to_reset,
false, // Reset is not castable from bits because we don't know if it's async or sync false // Reset is not castable from bits because we don't know if it's async or sync
reset
); );
impl ToSyncReset for bool { impl ToSyncReset for bool {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,397 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use std::{
fmt,
ops::{Add, AddAssign, Sub, SubAssign},
time::Duration,
};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct SimInstant {
time_since_start: SimDuration,
}
impl SimInstant {
pub const fn checked_add(self, duration: SimDuration) -> Option<Self> {
let Some(time_since_start) = self.time_since_start.checked_add(duration) else {
return None;
};
Some(SimInstant { time_since_start })
}
pub const fn checked_duration_since(self, earlier: Self) -> Option<SimDuration> {
self.time_since_start.checked_sub(earlier.time_since_start)
}
pub const fn checked_sub(self, duration: SimDuration) -> Option<Self> {
let Some(time_since_start) = self.time_since_start.checked_sub(duration) else {
return None;
};
Some(SimInstant { time_since_start })
}
#[track_caller]
pub const fn duration_since(self, earlier: Self) -> SimDuration {
let Some(retval) = self.checked_duration_since(earlier) else {
panic!(
"tried to compute the duration since a later time -- durations can't be negative"
);
};
retval
}
pub const fn saturating_duration_since(self, earlier: Self) -> SimDuration {
let Some(retval) = self.checked_duration_since(earlier) else {
return SimDuration::ZERO;
};
retval
}
}
impl Add<SimDuration> for SimInstant {
type Output = SimInstant;
#[track_caller]
fn add(mut self, rhs: SimDuration) -> Self::Output {
self += rhs;
self
}
}
impl AddAssign<SimDuration> for SimInstant {
#[track_caller]
fn add_assign(&mut self, rhs: SimDuration) {
self.time_since_start += rhs;
}
}
impl Add<SimInstant> for SimDuration {
type Output = SimInstant;
#[track_caller]
fn add(self, rhs: SimInstant) -> Self::Output {
rhs.add(self)
}
}
impl Sub for SimInstant {
type Output = SimDuration;
#[track_caller]
fn sub(self, rhs: SimInstant) -> Self::Output {
self.duration_since(rhs)
}
}
impl Sub<SimDuration> for SimInstant {
type Output = SimInstant;
#[track_caller]
fn sub(self, rhs: SimDuration) -> Self::Output {
let Some(retval) = self.checked_sub(rhs) else {
panic!("SimInstant underflow");
};
retval
}
}
impl SubAssign<SimDuration> for SimInstant {
#[track_caller]
fn sub_assign(&mut self, rhs: SimDuration) {
*self = *self - rhs;
}
}
impl SimInstant {
pub const START: SimInstant = SimInstant {
time_since_start: SimDuration::ZERO,
};
}
impl fmt::Debug for SimInstant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.time_since_start.fmt(f)
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct SimDuration {
attos: u128,
}
impl AddAssign for SimDuration {
#[track_caller]
fn add_assign(&mut self, rhs: SimDuration) {
*self = *self + rhs;
}
}
impl Add for SimDuration {
type Output = SimDuration;
#[track_caller]
fn add(self, rhs: SimDuration) -> Self::Output {
SimDuration {
attos: self
.attos
.checked_add(rhs.attos)
.expect("overflow adding durations"),
}
}
}
impl Sub for SimDuration {
type Output = Self;
#[track_caller]
fn sub(self, rhs: Self) -> Self::Output {
SimDuration {
attos: self
.attos
.checked_add(rhs.attos)
.expect("underflow subtracting durations -- durations can't be negative"),
}
}
}
impl SubAssign for SimDuration {
#[track_caller]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
pub struct SimDurationParts {
pub attos: u16,
pub femtos: u16,
pub picos: u16,
pub nanos: u16,
pub micros: u16,
pub millis: u16,
pub secs: u128,
}
macro_rules! impl_duration_units {
(
$(
#[unit_const = $UNIT:ident, from_units = $from_units:ident, as_units = $as_units:ident, units = $units:ident, suffix = $suffix:literal]
const $log10_units_per_sec:ident: u32 = $log10_units_per_sec_value:expr;
)*
) => {
impl SimDuration {
$(
const $log10_units_per_sec: u32 = $log10_units_per_sec_value;
pub const fn $from_units($units: u128) -> Self {
Self::from_units_helper::<{ Self::$log10_units_per_sec }>($units)
}
pub const fn $as_units(self) -> u128 {
self.attos / const { 10u128.pow(Self::LOG10_ATTOS_PER_SEC - Self::$log10_units_per_sec) }
}
)*
pub const fn to_parts(mut self) -> SimDurationParts {
$(
let $units = self.attos / const { 10u128.pow(Self::LOG10_ATTOS_PER_SEC - Self::$log10_units_per_sec) };
self.attos %= const { 10u128.pow(Self::LOG10_ATTOS_PER_SEC - Self::$log10_units_per_sec) };
)*
SimDurationParts {
$($units: $units as _,)*
}
}
pub const fn from_parts_checked(parts: SimDurationParts) -> Option<Self> {
let attos = 0u128;
$(
let Some(product) = const { 10u128.pow(Self::LOG10_ATTOS_PER_SEC - Self::$log10_units_per_sec) }.checked_mul(parts.$units as u128) else {
return None;
};
let Some(attos) = attos.checked_add(product) else {
return None;
};
)*
Some(Self {
attos,
})
}
}
impl fmt::Debug for SimDuration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ilog10_attos = match self.attos.checked_ilog10() {
Some(v) => v,
None => Self::LOG10_ATTOS_PER_SEC,
};
let (suffix, int, fraction, fraction_digits) =
match Self::LOG10_ATTOS_PER_SEC.saturating_sub(ilog10_attos) {
$(
..=Self::$log10_units_per_sec => {
let divisor = const { 10u128.pow(Self::LOG10_ATTOS_PER_SEC - Self::$log10_units_per_sec) };
(
$suffix,
self.attos / divisor,
self.attos % divisor,
(Self::LOG10_ATTOS_PER_SEC - Self::$log10_units_per_sec) as usize,
)
},
)*
_ => unreachable!(),
};
write!(f, "{int}")?;
if fraction != 0 {
write!(f, ".{fraction:0fraction_digits$}")?;
}
write!(f, " {suffix}")
}
}
#[cfg(test)]
#[test]
fn test_duration_debug() {
$(
assert_eq!(
format!("{:?}", SimDuration::$from_units(123)),
concat!("123 ", $suffix)
);
assert_eq!(
format!("{:?}", SimDuration::$from_units(1)),
concat!("1 ", $suffix),
);
let mut v = SimDuration::$from_units(1);
if v.attos < 1 << 53 {
v.attos += 1;
assert_eq!(
format!("{v:?}"),
format!("{} {}", v.attos as f64 / 10.0f64.powf((SimDuration::LOG10_ATTOS_PER_SEC - SimDuration::$log10_units_per_sec) as f64), $suffix),
"1 {} + 1 as == {} as", $suffix, v.attos,
);
}
)*
}
};
}
impl_duration_units! {
#[unit_const = SECOND, from_units = from_secs, as_units = as_secs, units = secs, suffix = "s"]
const LOG10_SECS_PER_SEC: u32 = 0;
#[unit_const = MILLISECOND, from_units = from_millis, as_units = as_millis, units = millis, suffix = "ms"]
const LOG10_MILLIS_PER_SEC: u32 = 3;
#[unit_const = MICROSECOND, from_units = from_micros, as_units = as_micros, units = micros, suffix = "μs"]
const LOG10_MICROS_PER_SEC: u32 = 6;
#[unit_const = NANOSECOND, from_units = from_nanos, as_units = as_nanos, units = nanos, suffix = "ns"]
const LOG10_NANOS_PER_SEC: u32 = 9;
#[unit_const = PICOSECOND, from_units = from_picos, as_units = as_picos, units = picos, suffix = "ps"]
const LOG10_PICOS_PER_SEC: u32 = 12;
#[unit_const = FEMTOSECOND, from_units = from_femtos, as_units = as_femtos, units = femtos, suffix = "fs"]
const LOG10_FEMTOS_PER_SEC: u32 = 15;
#[unit_const = ATTOSECOND, from_units = from_attos, as_units = as_attos, units = attos, suffix = "as"]
const LOG10_ATTOS_PER_SEC: u32 = 18;
}
impl SimDuration {
const fn from_units_helper<const UNITS_PER_SEC: u32>(units: u128) -> Self {
let Some(attos) =
units.checked_mul(const { 10u128.pow(Self::LOG10_ATTOS_PER_SEC - UNITS_PER_SEC) })
else {
panic!("duration too big");
};
Self { attos }
}
pub const ZERO: SimDuration = SimDuration::from_secs(0);
pub const fn from_parts(parts: SimDurationParts) -> Self {
match Self::from_parts_checked(parts) {
Some(v) => v,
None => panic!("duration too big"),
}
}
pub const fn abs_diff(self, other: Self) -> Self {
Self {
attos: self.attos.abs_diff(other.attos),
}
}
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
let Some(attos) = self.attos.checked_add(rhs.attos) else {
return None;
};
Some(Self { attos })
}
pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
let Some(attos) = self.attos.checked_sub(rhs.attos) else {
return None;
};
Some(Self { attos })
}
pub const fn is_zero(self) -> bool {
self.attos == 0
}
pub const fn saturating_add(self, rhs: Self) -> Self {
Self {
attos: self.attos.saturating_add(rhs.attos),
}
}
pub const fn saturating_sub(self, rhs: Self) -> Self {
Self {
attos: self.attos.saturating_sub(rhs.attos),
}
}
pub const fn checked_ilog10(self) -> Option<i32> {
let Some(ilog10_attos) = self.attos.checked_ilog10() else {
return None;
};
Some(ilog10_attos as i32 - Self::LOG10_ATTOS_PER_SEC as i32)
}
#[track_caller]
pub const fn ilog10(self) -> i32 {
let Some(retval) = self.checked_ilog10() else {
panic!("tried to take the ilog10 of 0");
};
retval
}
pub const fn checked_pow10(log10: i32, underflow_is_zero: bool) -> Option<Self> {
let Some(log10) = Self::LOG10_ATTOS_PER_SEC.checked_add_signed(log10) else {
return if log10 < 0 && underflow_is_zero {
Some(Self::ZERO)
} else {
None
};
};
let Some(attos) = 10u128.checked_pow(log10) else {
return None;
};
Some(Self { attos })
}
#[track_caller]
pub const fn pow10(log10: i32) -> Self {
let Some(retval) = Self::checked_pow10(log10, true) else {
panic!("pow10 overflowed");
};
retval
}
pub const fn is_power_of_ten(self) -> bool {
const TEN: u128 = 10;
const NUMBER_OF_POWERS_OF_TEN: usize = {
let mut n = 0;
while let Some(_) = TEN.checked_pow(n as u32) {
n += 1;
}
n
};
const POWERS_OF_TEN: [u128; NUMBER_OF_POWERS_OF_TEN] = {
let mut retval = [0; NUMBER_OF_POWERS_OF_TEN];
let mut i = 0;
while i < NUMBER_OF_POWERS_OF_TEN {
retval[i] = TEN.pow(i as u32);
i += 1;
}
retval
};
let mut i = 0;
while i < NUMBER_OF_POWERS_OF_TEN {
if self.attos == POWERS_OF_TEN[i] {
return true;
}
i += 1;
}
false
}
}
impl From<Duration> for SimDuration {
fn from(duration: Duration) -> Self {
Self::from_nanos(duration.as_nanos())
}
}

File diff suppressed because it is too large Load diff

View file

@ -24,8 +24,7 @@ pub use scoped_ref::ScopedRef;
#[doc(inline)] #[doc(inline)]
pub use misc::{ pub use misc::{
get_many_mut, interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, DebugAsRawString, MakeMutSlice,
DebugAsRawString, MakeMutSlice, RcWriter,
}; };
pub mod job_server; pub mod job_server;

View file

@ -3,7 +3,6 @@
use crate::intern::{Intern, Interned}; use crate::intern::{Intern, Interned};
use bitvec::{bits, order::Lsb0, slice::BitSlice, view::BitView}; use bitvec::{bits, order::Lsb0, slice::BitSlice, view::BitView};
use std::{ use std::{
cell::Cell,
fmt::{self, Debug, Write}, fmt::{self, Debug, Write},
rc::Rc, rc::Rc,
sync::{Arc, OnceLock}, sync::{Arc, OnceLock},
@ -95,15 +94,9 @@ pub fn interned_bit(v: bool) -> Interned<BitSlice> {
RETVAL.get_or_init(|| [bits![0; 1].intern(), bits![1; 1].intern()])[v as usize] RETVAL.get_or_init(|| [bits![0; 1].intern(), bits![1; 1].intern()])[v as usize]
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone, Debug)]
pub struct BitSliceWriteWithBase<'a>(pub &'a BitSlice); pub struct BitSliceWriteWithBase<'a>(pub &'a BitSlice);
impl<'a> Debug for BitSliceWriteWithBase<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:#x}")
}
}
impl BitSliceWriteWithBase<'_> { impl BitSliceWriteWithBase<'_> {
fn fmt_with_base<const BITS_PER_DIGIT: usize, const UPPER_CASE: bool>( fn fmt_with_base<const BITS_PER_DIGIT: usize, const UPPER_CASE: bool>(
self, self,
@ -162,66 +155,3 @@ impl fmt::UpperHex for BitSliceWriteWithBase<'_> {
self.fmt_with_base::<4, true>(f) self.fmt_with_base::<4, true>(f)
} }
} }
#[inline]
#[track_caller]
pub fn get_many_mut<T, const N: usize>(slice: &mut [T], indexes: [usize; N]) -> [&mut T; N] {
for i in 0..N {
for j in 0..i {
assert!(indexes[i] != indexes[j], "duplicate index");
}
assert!(indexes[i] < slice.len(), "index out of bounds");
}
// Safety: checked that no indexes are duplicates and no indexes are out of bounds
unsafe {
let base = slice.as_mut_ptr(); // convert to a raw pointer before loop to avoid aliasing with &mut [T]
std::array::from_fn(|i| &mut *base.add(indexes[i]))
}
}
#[derive(Clone, Default)]
pub struct RcWriter(Rc<Cell<Vec<u8>>>);
impl Debug for RcWriter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.borrow_impl(|buf| {
f.debug_tuple("RcWriter")
.field(&DebugAsDisplay(format_args!("b\"{}\"", buf.escape_ascii())))
.finish()
})
}
}
impl RcWriter {
fn borrow_impl<R>(&self, f: impl FnOnce(&mut Vec<u8>) -> R) -> R {
let buf = Cell::take(&self.0);
struct PutBackOnDrop<'a> {
buf: Vec<u8>,
this: &'a RcWriter,
}
impl Drop for PutBackOnDrop<'_> {
fn drop(&mut self) {
self.this.0.set(std::mem::take(&mut self.buf));
}
}
let mut buf = PutBackOnDrop { buf, this: self };
f(&mut buf.buf)
}
pub fn borrow<R>(&mut self, f: impl FnOnce(&mut Vec<u8>) -> R) -> R {
self.borrow_impl(f)
}
pub fn take(&mut self) -> Vec<u8> {
Cell::take(&self.0)
}
}
impl std::io::Write for RcWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.borrow(|v| v.extend_from_slice(buf));
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}

View file

@ -49,18 +49,6 @@ impl<T: Type> ReadyValid<T> {
} }
} }
/// This debug port is only meant to assist the formal proof of the queue.
#[cfg(test)]
#[doc(hidden)]
#[hdl]
pub struct QueueDebugPort<Element, Index> {
#[hdl(flip)]
index_to_check: Index,
stored: Element,
inp_index: Index,
out_index: Index,
}
#[hdl_module] #[hdl_module]
pub fn queue<T: Type>( pub fn queue<T: Type>(
ty: T, ty: T,
@ -190,22 +178,6 @@ pub fn queue<T: Type>(
} }
} }
} }
// These debug ports expose some internal state during the Induction phase
// of Formal Verification. They are not present in normal use.
#[cfg(test)]
{
#[hdl]
let dbg: QueueDebugPort<T, UInt> = m.output(QueueDebugPort[ty][index_ty]);
// read the memory word currently stored at some fixed index
let debug_port = mem.new_read_port();
connect(debug_port.addr, dbg.index_to_check);
connect(debug_port.en, true);
connect(debug_port.clk, cd.clk);
connect(dbg.stored, debug_port.data);
// also expose the current read and write indices
connect(dbg.inp_index, inp_index_reg);
connect(dbg.out_index, out_index_reg);
}
} }
#[cfg(test)] #[cfg(test)]
@ -224,23 +196,13 @@ mod tests {
format_args!("test_queue_{capacity}_{inp_ready_is_comb}_{out_valid_is_comb}"), format_args!("test_queue_{capacity}_{inp_ready_is_comb}_{out_valid_is_comb}"),
queue_test(capacity, inp_ready_is_comb, out_valid_is_comb), queue_test(capacity, inp_ready_is_comb, out_valid_is_comb),
FormalMode::Prove, FormalMode::Prove,
2, 14,
None, None,
ExportOptions { ExportOptions {
simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts), simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
..ExportOptions::default() ..ExportOptions::default()
}, },
); );
/// Formal verification of the FIFO queue
///
/// The strategy derives from the observation that, if we filter its
/// input and output streams to consider just one in every N reads and
/// writes (where N is the FIFO capacity), then the FIFO effectively
/// behaves as a one-entry FIFO.
///
/// In particular, any counterexample of the full FIFO behaving badly
/// will also be caught by one of the filtered versions (one which
/// 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] #[hdl]
@ -255,8 +217,6 @@ mod tests {
rst: formal_reset().to_reset(), rst: formal_reset().to_reset(),
}, },
); );
// random input data
#[hdl] #[hdl]
let inp_data: HdlOption<UInt<8>> = wire(); let inp_data: HdlOption<UInt<8>> = wire();
#[hdl] #[hdl]
@ -265,26 +225,16 @@ mod tests {
} else { } else {
connect(inp_data, HdlNone()); connect(inp_data, HdlNone());
} }
// assert output ready at random
#[hdl] #[hdl]
let out_ready: Bool = wire(); let out_ready: Bool = wire();
connect(out_ready, any_seq(Bool)); connect(out_ready, any_seq(Bool));
let index_ty: UInt<32> = UInt::TYPE;
// The current number of elements in the FIFO ranges from zero to
// maximum capacity, inclusive.
let count_ty = UInt::range_inclusive(0..=capacity.get());
// type for counters that wrap around at the FIFO capacity
let index_ty = UInt::range(0..capacity.get());
// among all entries of the FIFO internal circular memory, choose
// one at random to check
#[hdl] #[hdl]
let index_to_check = wire(index_ty); let index_to_check = wire();
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()), ""); let index_max = !index_ty.zero();
// we saturate at index_max, so only check indexes where we properly maintain position
// instantiate and connect the queue hdl_assume(clk, index_to_check.cmp_ne(index_max), "");
#[hdl] #[hdl]
let dut = instance(queue( let dut = instance(queue(
UInt[ConstUsize::<8>], UInt[ConstUsize::<8>],
@ -295,172 +245,109 @@ mod tests {
connect(dut.cd, cd); connect(dut.cd, cd);
connect(dut.inp.data, inp_data); connect(dut.inp.data, inp_data);
connect(dut.out.ready, out_ready); connect(dut.out.ready, out_ready);
hdl_assume(
clk,
index_to_check.cmp_ne(!Expr::ty(index_to_check).zero()),
"",
);
// Keep an independent count of words in the FIFO. Ensure that
// it's always correct, and never overflows.
#[hdl] #[hdl]
let expected_count_reg = reg_builder().clock_domain(cd).reset(count_ty.zero()); let expected_count_reg = reg_builder().clock_domain(cd).reset(0u32);
#[hdl]
let next_expected_count = wire();
connect(next_expected_count, expected_count_reg);
connect(expected_count_reg, next_expected_count);
#[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()), ""); connect_any(next_expected_count, 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()), ""); connect_any(next_expected_count, 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), "");
#[hdl]
let prev_out_ready_reg = reg_builder().clock_domain(cd).reset(!0_hdl_u3);
connect_any(
prev_out_ready_reg,
(prev_out_ready_reg << 1) | out_ready.cast_to(UInt[1]),
);
#[hdl]
let prev_inp_valid_reg = reg_builder().clock_domain(cd).reset(!0_hdl_u3);
connect_any(
prev_inp_valid_reg,
(prev_inp_valid_reg << 1) | HdlOption::is_some(inp_data).cast_to(UInt[1]),
);
hdl_assume(
clk,
(prev_out_ready_reg & prev_inp_valid_reg).cmp_ne(0u8),
"",
);
// keep an independent write index into the FIFO's circular buffer
#[hdl] #[hdl]
let inp_index_reg = reg_builder().clock_domain(cd).reset(index_ty.zero()); let inp_index_reg = reg_builder().clock_domain(cd).reset(index_ty.zero());
#[hdl] #[hdl]
if ReadyValid::firing(dut.inp) { let stored_inp_data_reg = reg_builder().clock_domain(cd).reset(0u8);
#[hdl] #[hdl]
if inp_index_reg.cmp_ne(capacity.get() - 1) { if let HdlSome(data) = ReadyValid::firing_data(dut.inp) {
#[hdl]
if inp_index_reg.cmp_lt(index_max) {
connect_any(inp_index_reg, inp_index_reg + 1u8); connect_any(inp_index_reg, inp_index_reg + 1u8);
} else { #[hdl]
connect_any(inp_index_reg, 0_hdl_u0); if inp_index_reg.cmp_eq(index_to_check) {
connect(stored_inp_data_reg, data);
}
} }
} }
// keep an independent read index into the FIFO's circular buffer #[hdl]
if inp_index_reg.cmp_lt(index_to_check) {
hdl_assert(clk, stored_inp_data_reg.cmp_eq(0u8), "");
}
#[hdl] #[hdl]
let out_index_reg = reg_builder().clock_domain(cd).reset(index_ty.zero()); let out_index_reg = reg_builder().clock_domain(cd).reset(index_ty.zero());
#[hdl] #[hdl]
if ReadyValid::firing(dut.out) { let stored_out_data_reg = reg_builder().clock_domain(cd).reset(0u8);
#[hdl] #[hdl]
if out_index_reg.cmp_ne(capacity.get() - 1) { if let HdlSome(data) = ReadyValid::firing_data(dut.out) {
#[hdl]
if out_index_reg.cmp_lt(index_max) {
connect_any(out_index_reg, out_index_reg + 1u8); connect_any(out_index_reg, out_index_reg + 1u8);
} else {
connect_any(out_index_reg, 0_hdl_u0);
}
}
// filter the input data stream, predicated by the read index
// matching the chosen position in the FIFO's circular buffer
#[hdl] #[hdl]
let inp_index_matches = wire(); if out_index_reg.cmp_eq(index_to_check) {
connect(inp_index_matches, inp_index_reg.cmp_eq(index_to_check)); connect(stored_out_data_reg, data);
#[hdl]
let inp_firing_data = wire();
connect(inp_firing_data, HdlNone());
#[hdl]
if inp_index_matches {
connect(inp_firing_data, ReadyValid::firing_data(dut.inp));
}
// filter the output data stream, predicated by the write index
// matching the chosen position in the FIFO's circular buffer
#[hdl]
let out_index_matches = wire();
connect(out_index_matches, out_index_reg.cmp_eq(index_to_check));
#[hdl]
let out_firing_data = wire();
connect(out_firing_data, HdlNone());
#[hdl]
if out_index_matches {
connect(out_firing_data, ReadyValid::firing_data(dut.out));
}
// Implement a one-entry FIFO and ensure its equivalence to the
// filtered FIFO.
//
// the holding register for our one-entry FIFO
#[hdl]
let stored_reg = reg_builder().clock_domain(cd).reset(HdlNone());
#[hdl]
match stored_reg {
// If the holding register is empty...
HdlNone => {
#[hdl]
match inp_firing_data {
// ... and we are not receiving data, then we must not
// transmit any data.
HdlNone => hdl_assert(clk, HdlOption::is_none(out_firing_data), ""),
// If we are indeed receiving some data...
HdlSome(data_in) => {
#[hdl]
match out_firing_data {
// ... and transmitting at the same time, we
// must be transmitting the input data itself,
// since the holding register is empty.
HdlSome(data_out) => hdl_assert(clk, data_out.cmp_eq(data_in), ""),
// If we are receiving, but not transmitting,
// store the received data in the holding
// register.
HdlNone => connect(stored_reg, HdlSome(data_in)),
}
}
}
}
// If there is some value stored in the holding register...
HdlSome(stored) => {
#[hdl]
match out_firing_data {
// ... and we are not transmitting it, we cannot
// receive any more data.
HdlNone => hdl_assert(clk, HdlOption::is_none(inp_firing_data), ""),
// If we are transmitting a previously stored value...
HdlSome(data_out) => {
// ... it must be the same data we stored earlier.
hdl_assert(clk, data_out.cmp_eq(stored), "");
// Also, accept new data, if any. Otherwise,
// let the holding register become empty.
connect(stored_reg, inp_firing_data);
}
} }
} }
} }
// from now on, some extra assertions in order to pass induction
// sync the holding register, when it's occupied, to the
// corresponding entry in the FIFO's circular buffer
connect(dut.dbg.index_to_check, index_to_check);
#[hdl] #[hdl]
if let HdlSome(stored) = stored_reg { if out_index_reg.cmp_lt(index_to_check) {
hdl_assert(clk, stored.cmp_eq(dut.dbg.stored), ""); hdl_assert(clk, stored_out_data_reg.cmp_eq(0u8), "");
} }
// sync the read and write indices hdl_assert(clk, inp_index_reg.cmp_ge(out_index_reg), "");
hdl_assert(clk, inp_index_reg.cmp_eq(dut.dbg.inp_index), "");
hdl_assert(clk, out_index_reg.cmp_eq(dut.dbg.out_index), "");
// the indices should never go past the capacity, but induction
// doesn't know that...
hdl_assert(clk, inp_index_reg.cmp_lt(capacity.get()), "");
hdl_assert(clk, out_index_reg.cmp_lt(capacity.get()), "");
// strongly constrain the state of the holding register
//
// The holding register is full if and only if the corresponding
// FIFO entry was written to and not yet read. In other words, if
// the number of pending reads until the chosen entry is read out
// is greater than the current FIFO count, then the entry couldn't
// be in the FIFO in the first place.
#[hdl] #[hdl]
let pending_reads: UInt = wire(index_ty); if inp_index_reg.cmp_lt(index_max) & out_index_reg.cmp_lt(index_max) {
// take care of wrap-around when subtracting indices, add the
// capacity amount to keep the result positive if necessary
#[hdl]
if index_to_check.cmp_ge(out_index_reg) {
connect(pending_reads, index_to_check - out_index_reg);
} else {
connect(
pending_reads,
index_to_check + capacity.get() - out_index_reg,
);
}
// check whether the chosen entry is in the FIFO
#[hdl]
let expected_stored: Bool = wire();
connect(expected_stored, pending_reads.cmp_lt(dut.count));
// sync with the state of the holding register
hdl_assert( hdl_assert(
clk, clk,
expected_stored.cmp_eq(HdlOption::is_some(stored_reg)), expected_count_reg.cmp_eq(inp_index_reg - out_index_reg),
"", "",
); );
} else {
hdl_assert(
clk,
expected_count_reg.cmp_ge(inp_index_reg - out_index_reg),
"",
);
}
#[hdl]
if inp_index_reg.cmp_gt(index_to_check) & out_index_reg.cmp_gt(index_to_check) {
hdl_assert(clk, stored_inp_data_reg.cmp_eq(stored_out_data_reg), "");
}
} }
} }
@ -543,24 +430,4 @@ mod tests {
fn test_4_true_true() { fn test_4_true_true() {
test_queue(NonZero::new(4).unwrap(), true, true); test_queue(NonZero::new(4).unwrap(), true, true);
} }
#[test]
fn test_many_false_false() {
test_queue(NonZero::new((2 << 16) - 5).unwrap(), false, false);
}
#[test]
fn test_many_false_true() {
test_queue(NonZero::new((2 << 16) - 5).unwrap(), false, true);
}
#[test]
fn test_many_true_false() {
test_queue(NonZero::new((2 << 16) - 5).unwrap(), true, false);
}
#[test]
fn test_many_true_true() {
test_queue(NonZero::new((2 << 16) - 5).unwrap(), true, true);
}
} }

View file

@ -37,18 +37,6 @@ impl<T: Type> Wire<T> {
ty: ty.canonical(), ty: ty.canonical(),
} }
} }
pub fn from_canonical(v: Wire<CanonicalType>) -> Self {
let Wire {
name,
source_location,
ty,
} = v;
Self {
name,
source_location,
ty: T::from_canonical(ty),
}
}
pub fn ty(&self) -> T { pub fn ty(&self) -> T {
self.ty self.ty
} }

View file

@ -2,8 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use fayalite::{ use fayalite::{
assert_export_firrtl, firrtl::ExportOptions, intern::Intern, assert_export_firrtl, firrtl::ExportOptions, intern::Intern,
module::transform::simplify_enums::SimplifyEnumsKind, prelude::*, reset::ResetType, module::transform::simplify_enums::SimplifyEnumsKind, prelude::*, ty::StaticType,
ty::StaticType,
}; };
use serde_json::json; use serde_json::json;
@ -191,14 +190,10 @@ circuit check_array_repeat:
}; };
} }
pub trait UnknownTrait {}
impl<T: ?Sized> UnknownTrait for T {}
#[hdl_module(outline_generated)] #[hdl_module(outline_generated)]
pub fn check_skipped_generics<T, #[hdl(skip)] U, const N: usize, #[hdl(skip)] const M: usize>(v: U) pub fn check_skipped_generics<T, #[hdl(skip)] U, const N: usize, #[hdl(skip)] const M: usize>(v: U)
where where
T: StaticType + UnknownTrait, T: StaticType,
ConstUsize<N>: KnownSize, ConstUsize<N>: KnownSize,
U: std::fmt::Display, U: std::fmt::Display,
{ {
@ -380,18 +375,18 @@ circuit check_written_inside_both_if_else:
}; };
} }
#[hdl(outline_generated, cmp_eq)] #[hdl(outline_generated)]
pub struct TestStruct<T> { pub struct TestStruct<T> {
pub a: T, pub a: T,
pub b: UInt<8>, pub b: UInt<8>,
} }
#[hdl(outline_generated, cmp_eq)] #[hdl(outline_generated)]
pub struct TestStruct2 { pub struct TestStruct2 {
pub v: UInt<8>, pub v: UInt<8>,
} }
#[hdl(outline_generated, cmp_eq)] #[hdl(outline_generated)]
pub struct TestStruct3 {} pub struct TestStruct3 {}
#[hdl_module(outline_generated)] #[hdl_module(outline_generated)]
@ -4031,519 +4026,3 @@ circuit check_enum_connect_any:
", ",
}; };
} }
#[hdl_module(outline_generated)]
pub fn check_deduce_resets<T: ResetType>(ty: T) {
#[hdl]
let cd: ClockDomain<T> = m.input(ClockDomain[ty]);
#[hdl]
let my_reg = reg_builder().reset(0u8).clock_domain(cd);
#[hdl]
let u8_in: UInt<8> = m.input();
connect(my_reg, u8_in);
#[hdl]
let u8_out: UInt<8> = m.output();
connect(u8_out, my_reg);
#[hdl]
let enum_in: OneOfThree<Reset, AsyncReset, SyncReset> = m.input();
#[hdl]
let enum_out: OneOfThree<Reset, AsyncReset, SyncReset> = m.output();
#[hdl]
let reset_out: Reset = m.output();
connect(reset_out, cd.rst.to_reset());
#[hdl]
match enum_in {
OneOfThree::<_, _, _>::A(v) => {
connect(
enum_out,
OneOfThree[Reset][AsyncReset][SyncReset].A(cd.rst.to_reset()),
);
connect(reset_out, v);
}
OneOfThree::<_, _, _>::B(v) => {
connect(enum_out, OneOfThree[Reset][AsyncReset][SyncReset].B(v))
}
OneOfThree::<_, _, _>::C(v) => {
connect(enum_out, OneOfThree[Reset][AsyncReset][SyncReset].C(v))
}
}
}
#[test]
fn test_deduce_resets() {
let _n = SourceLocation::normalize_files_for_tests();
let m = check_deduce_resets(Reset);
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_deduce_resets.fir": r"FIRRTL version 3.2.0
circuit check_deduce_resets:
type Ty0 = {clk: Clock, rst: Reset}
type Ty1 = {|A: Reset, B: AsyncReset, C: UInt<1>|}
module check_deduce_resets: @[module-XXXXXXXXXX.rs 1:1]
input cd: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input u8_in: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
output u8_out: UInt<8> @[module-XXXXXXXXXX.rs 6:1]
input enum_in: Ty1 @[module-XXXXXXXXXX.rs 8:1]
output enum_out: Ty1 @[module-XXXXXXXXXX.rs 9:1]
output reset_out: Reset @[module-XXXXXXXXXX.rs 10:1]
regreset my_reg: UInt<8>, cd.clk, cd.rst, UInt<8>(0h0) @[module-XXXXXXXXXX.rs 3:1]
connect my_reg, u8_in @[module-XXXXXXXXXX.rs 5:1]
connect u8_out, my_reg @[module-XXXXXXXXXX.rs 7:1]
connect reset_out, cd.rst @[module-XXXXXXXXXX.rs 11:1]
match enum_in: @[module-XXXXXXXXXX.rs 12:1]
A(_match_arm_value):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(A, cd.rst) @[module-XXXXXXXXXX.rs 13:1]
connect reset_out, _match_arm_value @[module-XXXXXXXXXX.rs 14:1]
B(_match_arm_value_1):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(B, _match_arm_value_1) @[module-XXXXXXXXXX.rs 15:1]
C(_match_arm_value_2):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(C, _match_arm_value_2) @[module-XXXXXXXXXX.rs 16:1]
",
};
fayalite::module::transform::deduce_resets::deduce_resets(m.canonical().intern_sized(), false)
.unwrap_err();
let m = fayalite::module::transform::deduce_resets::deduce_resets(
m.canonical().intern_sized(),
true,
)
.unwrap();
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_deduce_resets.fir": r"FIRRTL version 3.2.0
circuit check_deduce_resets:
type Ty0 = {clk: Clock, rst: UInt<1>}
type Ty1 = {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}
module check_deduce_resets: @[module-XXXXXXXXXX.rs 1:1]
input cd: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input u8_in: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
output u8_out: UInt<8> @[module-XXXXXXXXXX.rs 6:1]
input enum_in: Ty1 @[module-XXXXXXXXXX.rs 8:1]
output enum_out: Ty1 @[module-XXXXXXXXXX.rs 9:1]
output reset_out: UInt<1> @[module-XXXXXXXXXX.rs 10:1]
regreset my_reg: UInt<8>, cd.clk, cd.rst, UInt<8>(0h0) @[module-XXXXXXXXXX.rs 3:1]
connect my_reg, u8_in @[module-XXXXXXXXXX.rs 5:1]
connect u8_out, my_reg @[module-XXXXXXXXXX.rs 7:1]
connect reset_out, cd.rst @[module-XXXXXXXXXX.rs 11:1]
match enum_in: @[module-XXXXXXXXXX.rs 12:1]
A(_match_arm_value):
connect enum_out, {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}(A, cd.rst) @[module-XXXXXXXXXX.rs 13:1]
connect reset_out, _match_arm_value @[module-XXXXXXXXXX.rs 14:1]
B(_match_arm_value_1):
connect enum_out, {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}(B, _match_arm_value_1) @[module-XXXXXXXXXX.rs 15:1]
C(_match_arm_value_2):
connect enum_out, {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}(C, _match_arm_value_2) @[module-XXXXXXXXXX.rs 16:1]
",
};
let m = check_deduce_resets(SyncReset);
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_deduce_resets.fir": r"FIRRTL version 3.2.0
circuit check_deduce_resets:
type Ty0 = {clk: Clock, rst: UInt<1>}
type Ty1 = {|A: Reset, B: AsyncReset, C: UInt<1>|}
module check_deduce_resets: @[module-XXXXXXXXXX.rs 1:1]
input cd: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input u8_in: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
output u8_out: UInt<8> @[module-XXXXXXXXXX.rs 6:1]
input enum_in: Ty1 @[module-XXXXXXXXXX.rs 8:1]
output enum_out: Ty1 @[module-XXXXXXXXXX.rs 9:1]
output reset_out: Reset @[module-XXXXXXXXXX.rs 10:1]
regreset my_reg: UInt<8>, cd.clk, cd.rst, UInt<8>(0h0) @[module-XXXXXXXXXX.rs 3:1]
connect my_reg, u8_in @[module-XXXXXXXXXX.rs 5:1]
connect u8_out, my_reg @[module-XXXXXXXXXX.rs 7:1]
connect reset_out, cd.rst @[module-XXXXXXXXXX.rs 11:1]
match enum_in: @[module-XXXXXXXXXX.rs 12:1]
A(_match_arm_value):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(A, cd.rst) @[module-XXXXXXXXXX.rs 13:1]
connect reset_out, _match_arm_value @[module-XXXXXXXXXX.rs 14:1]
B(_match_arm_value_1):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(B, _match_arm_value_1) @[module-XXXXXXXXXX.rs 15:1]
C(_match_arm_value_2):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(C, _match_arm_value_2) @[module-XXXXXXXXXX.rs 16:1]
",
};
let m = fayalite::module::transform::deduce_resets::deduce_resets(
m.canonical().intern_sized(),
false,
)
.unwrap();
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_deduce_resets.fir": r"FIRRTL version 3.2.0
circuit check_deduce_resets:
type Ty0 = {clk: Clock, rst: UInt<1>}
type Ty1 = {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}
module check_deduce_resets: @[module-XXXXXXXXXX.rs 1:1]
input cd: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input u8_in: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
output u8_out: UInt<8> @[module-XXXXXXXXXX.rs 6:1]
input enum_in: Ty1 @[module-XXXXXXXXXX.rs 8:1]
output enum_out: Ty1 @[module-XXXXXXXXXX.rs 9:1]
output reset_out: UInt<1> @[module-XXXXXXXXXX.rs 10:1]
regreset my_reg: UInt<8>, cd.clk, cd.rst, UInt<8>(0h0) @[module-XXXXXXXXXX.rs 3:1]
connect my_reg, u8_in @[module-XXXXXXXXXX.rs 5:1]
connect u8_out, my_reg @[module-XXXXXXXXXX.rs 7:1]
connect reset_out, cd.rst @[module-XXXXXXXXXX.rs 11:1]
match enum_in: @[module-XXXXXXXXXX.rs 12:1]
A(_match_arm_value):
connect enum_out, {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}(A, cd.rst) @[module-XXXXXXXXXX.rs 13:1]
connect reset_out, _match_arm_value @[module-XXXXXXXXXX.rs 14:1]
B(_match_arm_value_1):
connect enum_out, {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}(B, _match_arm_value_1) @[module-XXXXXXXXXX.rs 15:1]
C(_match_arm_value_2):
connect enum_out, {|A: UInt<1>, B: AsyncReset, C: UInt<1>|}(C, _match_arm_value_2) @[module-XXXXXXXXXX.rs 16:1]
",
};
let m = check_deduce_resets(AsyncReset);
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_deduce_resets.fir": r"FIRRTL version 3.2.0
circuit check_deduce_resets:
type Ty0 = {clk: Clock, rst: AsyncReset}
type Ty1 = {|A: Reset, B: AsyncReset, C: UInt<1>|}
module check_deduce_resets: @[module-XXXXXXXXXX.rs 1:1]
input cd: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input u8_in: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
output u8_out: UInt<8> @[module-XXXXXXXXXX.rs 6:1]
input enum_in: Ty1 @[module-XXXXXXXXXX.rs 8:1]
output enum_out: Ty1 @[module-XXXXXXXXXX.rs 9:1]
output reset_out: Reset @[module-XXXXXXXXXX.rs 10:1]
regreset my_reg: UInt<8>, cd.clk, cd.rst, UInt<8>(0h0) @[module-XXXXXXXXXX.rs 3:1]
connect my_reg, u8_in @[module-XXXXXXXXXX.rs 5:1]
connect u8_out, my_reg @[module-XXXXXXXXXX.rs 7:1]
connect reset_out, cd.rst @[module-XXXXXXXXXX.rs 11:1]
match enum_in: @[module-XXXXXXXXXX.rs 12:1]
A(_match_arm_value):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(A, cd.rst) @[module-XXXXXXXXXX.rs 13:1]
connect reset_out, _match_arm_value @[module-XXXXXXXXXX.rs 14:1]
B(_match_arm_value_1):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(B, _match_arm_value_1) @[module-XXXXXXXXXX.rs 15:1]
C(_match_arm_value_2):
connect enum_out, {|A: Reset, B: AsyncReset, C: UInt<1>|}(C, _match_arm_value_2) @[module-XXXXXXXXXX.rs 16:1]
",
};
let m = fayalite::module::transform::deduce_resets::deduce_resets(
m.canonical().intern_sized(),
false,
)
.unwrap();
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_deduce_resets.fir": r"FIRRTL version 3.2.0
circuit check_deduce_resets:
type Ty0 = {clk: Clock, rst: AsyncReset}
type Ty1 = {|A: AsyncReset, B: AsyncReset, C: UInt<1>|}
module check_deduce_resets: @[module-XXXXXXXXXX.rs 1:1]
input cd: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input u8_in: UInt<8> @[module-XXXXXXXXXX.rs 4:1]
output u8_out: UInt<8> @[module-XXXXXXXXXX.rs 6:1]
input enum_in: Ty1 @[module-XXXXXXXXXX.rs 8:1]
output enum_out: Ty1 @[module-XXXXXXXXXX.rs 9:1]
output reset_out: AsyncReset @[module-XXXXXXXXXX.rs 10:1]
regreset my_reg: UInt<8>, cd.clk, cd.rst, UInt<8>(0h0) @[module-XXXXXXXXXX.rs 3:1]
connect my_reg, u8_in @[module-XXXXXXXXXX.rs 5:1]
connect u8_out, my_reg @[module-XXXXXXXXXX.rs 7:1]
connect reset_out, cd.rst @[module-XXXXXXXXXX.rs 11:1]
match enum_in: @[module-XXXXXXXXXX.rs 12:1]
A(_match_arm_value):
connect enum_out, {|A: AsyncReset, B: AsyncReset, C: UInt<1>|}(A, cd.rst) @[module-XXXXXXXXXX.rs 13:1]
connect reset_out, _match_arm_value @[module-XXXXXXXXXX.rs 14:1]
B(_match_arm_value_1):
connect enum_out, {|A: AsyncReset, B: AsyncReset, C: UInt<1>|}(B, _match_arm_value_1) @[module-XXXXXXXXXX.rs 15:1]
C(_match_arm_value_2):
connect enum_out, {|A: AsyncReset, B: AsyncReset, C: UInt<1>|}(C, _match_arm_value_2) @[module-XXXXXXXXXX.rs 16:1]
",
};
}
// intentionally not outline_generated to ensure we get correct macro hygiene
#[hdl_module]
pub fn check_cfgs<#[cfg(cfg_false_for_tests)] A: Type, #[cfg(cfg_true_for_tests)] B: Type>(
#[cfg(cfg_false_for_tests)] a: A,
#[cfg(cfg_true_for_tests)] b: B,
) {
#[hdl]
struct S<#[cfg(cfg_false_for_tests)] A, #[cfg(cfg_true_for_tests)] B> {
#[cfg(cfg_false_for_tests)]
a: A,
#[cfg(cfg_true_for_tests)]
b: B,
}
#[hdl]
#[cfg(cfg_false_for_tests)]
let i_a: A = m.input(a);
#[hdl]
#[cfg(cfg_true_for_tests)]
let i_b: B = m.input(b);
#[hdl]
let w: S<UInt<8>> = wire();
#[cfg(cfg_false_for_tests)]
{
#[hdl]
let o_a: A = m.output(a);
connect(o_a, w.a.cast_bits_to(a));
connect_any(w.a, i_a.cast_to_bits());
}
#[cfg(cfg_true_for_tests)]
{
#[hdl]
let o_b: B = m.output(b);
connect(o_b, w.b.cast_bits_to(b));
connect_any(w.b, i_b.cast_to_bits());
}
}
#[test]
fn test_cfgs() {
let _n = SourceLocation::normalize_files_for_tests();
let m = check_cfgs(UInt[8]);
dbg!(m);
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
"/test/check_cfgs.fir": r"FIRRTL version 3.2.0
circuit check_cfgs:
type Ty0 = {b: UInt<8>}
module check_cfgs: @[the_test_file.rs 9962:1]
input i_b: UInt<8> @[the_test_file.rs 9979:20]
output o_b: UInt<8> @[the_test_file.rs 9992:24]
wire w: Ty0 @[the_test_file.rs 9981:25]
connect o_b, w.b @[the_test_file.rs 9993:9]
connect w.b, i_b @[the_test_file.rs 9994:9]
",
};
}
#[hdl_module(outline_generated)]
pub fn check_let_patterns() {
#[hdl]
let tuple_in: (UInt<1>, SInt<1>, Bool) = m.input();
#[hdl]
let (tuple_0, tuple_1, tuple_2) = tuple_in;
#[hdl]
let tuple_0_out: UInt<1> = m.output();
connect(tuple_0_out, tuple_0);
#[hdl]
let tuple_1_out: SInt<1> = m.output();
connect(tuple_1_out, tuple_1);
#[hdl]
let tuple_2_out: Bool = m.output();
connect(tuple_2_out, tuple_2);
#[hdl]
let test_struct_in: TestStruct<SInt<8>> = m.input();
#[hdl]
let TestStruct::<_> { a, b } = test_struct_in;
#[hdl]
let test_struct_a_out: SInt<8> = m.output();
connect(test_struct_a_out, a);
#[hdl]
let test_struct_b_out: UInt<8> = m.output();
connect(test_struct_b_out, b);
#[hdl]
let test_struct_2_in: TestStruct2 = m.input();
#[hdl]
let TestStruct2 { v } = test_struct_2_in;
#[hdl]
let test_struct_2_v_out: UInt<8> = m.output();
connect(test_struct_2_v_out, v);
#[hdl]
let test_struct_3_in: TestStruct3 = m.input();
#[hdl]
let TestStruct3 {} = test_struct_3_in;
}
#[test]
fn test_let_patterns() {
let _n = SourceLocation::normalize_files_for_tests();
let m = check_let_patterns();
dbg!(m);
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
"/test/check_let_patterns.fir": r"FIRRTL version 3.2.0
circuit check_let_patterns:
type Ty0 = {`0`: UInt<1>, `1`: SInt<1>, `2`: UInt<1>}
type Ty1 = {a: SInt<8>, b: UInt<8>}
type Ty2 = {v: UInt<8>}
type Ty3 = {}
module check_let_patterns: @[module-XXXXXXXXXX.rs 1:1]
input tuple_in: Ty0 @[module-XXXXXXXXXX.rs 2:1]
output tuple_0_out: UInt<1> @[module-XXXXXXXXXX.rs 4:1]
output tuple_1_out: SInt<1> @[module-XXXXXXXXXX.rs 6:1]
output tuple_2_out: UInt<1> @[module-XXXXXXXXXX.rs 8:1]
input test_struct_in: Ty1 @[module-XXXXXXXXXX.rs 10:1]
output test_struct_a_out: SInt<8> @[module-XXXXXXXXXX.rs 12:1]
output test_struct_b_out: UInt<8> @[module-XXXXXXXXXX.rs 14:1]
input test_struct_2_in: Ty2 @[module-XXXXXXXXXX.rs 16:1]
output test_struct_2_v_out: UInt<8> @[module-XXXXXXXXXX.rs 18:1]
input test_struct_3_in: Ty3 @[module-XXXXXXXXXX.rs 20:1]
connect tuple_0_out, tuple_in.`0` @[module-XXXXXXXXXX.rs 5:1]
connect tuple_1_out, tuple_in.`1` @[module-XXXXXXXXXX.rs 7:1]
connect tuple_2_out, tuple_in.`2` @[module-XXXXXXXXXX.rs 9:1]
connect test_struct_a_out, test_struct_in.a @[module-XXXXXXXXXX.rs 13:1]
connect test_struct_b_out, test_struct_in.b @[module-XXXXXXXXXX.rs 15:1]
connect test_struct_2_v_out, test_struct_2_in.v @[module-XXXXXXXXXX.rs 19:1]
",
};
}
#[hdl_module(outline_generated)]
pub fn check_struct_cmp_eq() {
#[hdl]
let tuple_lhs: (UInt<1>, SInt<1>, Bool) = m.input();
#[hdl]
let tuple_rhs: (UInt<1>, SInt<1>, Bool) = m.input();
#[hdl]
let tuple_cmp_eq: Bool = m.output();
connect(tuple_cmp_eq, tuple_lhs.cmp_eq(tuple_rhs));
#[hdl]
let tuple_cmp_ne: Bool = m.output();
connect(tuple_cmp_ne, tuple_lhs.cmp_ne(tuple_rhs));
#[hdl]
let test_struct_lhs: TestStruct<SInt<8>> = m.input();
#[hdl]
let test_struct_rhs: TestStruct<SInt<8>> = m.input();
#[hdl]
let test_struct_cmp_eq: Bool = m.output();
connect(test_struct_cmp_eq, test_struct_lhs.cmp_eq(test_struct_rhs));
#[hdl]
let test_struct_cmp_ne: Bool = m.output();
connect(test_struct_cmp_ne, test_struct_lhs.cmp_ne(test_struct_rhs));
#[hdl]
let test_struct_2_lhs: TestStruct2 = m.input();
#[hdl]
let test_struct_2_rhs: TestStruct2 = m.input();
#[hdl]
let test_struct_2_cmp_eq: Bool = m.output();
connect(
test_struct_2_cmp_eq,
test_struct_2_lhs.cmp_eq(test_struct_2_rhs),
);
#[hdl]
let test_struct_2_cmp_ne: Bool = m.output();
connect(
test_struct_2_cmp_ne,
test_struct_2_lhs.cmp_ne(test_struct_2_rhs),
);
#[hdl]
let test_struct_3_lhs: TestStruct3 = m.input();
#[hdl]
let test_struct_3_rhs: TestStruct3 = m.input();
#[hdl]
let test_struct_3_cmp_eq: Bool = m.output();
connect(
test_struct_3_cmp_eq,
test_struct_3_lhs.cmp_eq(test_struct_3_rhs),
);
#[hdl]
let test_struct_3_cmp_ne: Bool = m.output();
connect(
test_struct_3_cmp_ne,
test_struct_3_lhs.cmp_ne(test_struct_3_rhs),
);
}
#[test]
fn test_struct_cmp_eq() {
let _n = SourceLocation::normalize_files_for_tests();
let m = check_struct_cmp_eq();
dbg!(m);
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
assert_export_firrtl! {
m =>
"/test/check_struct_cmp_eq.fir": r"FIRRTL version 3.2.0
circuit check_struct_cmp_eq:
type Ty0 = {`0`: UInt<1>, `1`: SInt<1>, `2`: UInt<1>}
type Ty1 = {a: SInt<8>, b: UInt<8>}
type Ty2 = {v: UInt<8>}
type Ty3 = {}
module check_struct_cmp_eq: @[module-XXXXXXXXXX.rs 1:1]
input tuple_lhs: Ty0 @[module-XXXXXXXXXX.rs 2:1]
input tuple_rhs: Ty0 @[module-XXXXXXXXXX.rs 3:1]
output tuple_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1]
output tuple_cmp_ne: UInt<1> @[module-XXXXXXXXXX.rs 6:1]
input test_struct_lhs: Ty1 @[module-XXXXXXXXXX.rs 8:1]
input test_struct_rhs: Ty1 @[module-XXXXXXXXXX.rs 9:1]
output test_struct_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 10:1]
output test_struct_cmp_ne: UInt<1> @[module-XXXXXXXXXX.rs 12:1]
input test_struct_2_lhs: Ty2 @[module-XXXXXXXXXX.rs 14:1]
input test_struct_2_rhs: Ty2 @[module-XXXXXXXXXX.rs 15:1]
output test_struct_2_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 16:1]
output test_struct_2_cmp_ne: UInt<1> @[module-XXXXXXXXXX.rs 18:1]
input test_struct_3_lhs: Ty3 @[module-XXXXXXXXXX.rs 20:1]
input test_struct_3_rhs: Ty3 @[module-XXXXXXXXXX.rs 21:1]
output test_struct_3_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 22:1]
output test_struct_3_cmp_ne: UInt<1> @[module-XXXXXXXXXX.rs 24:1]
wire _array_literal_expr: UInt<1>[3]
connect _array_literal_expr[0], eq(tuple_lhs.`0`, tuple_rhs.`0`)
connect _array_literal_expr[1], eq(tuple_lhs.`1`, tuple_rhs.`1`)
connect _array_literal_expr[2], eq(tuple_lhs.`2`, tuple_rhs.`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 tuple_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1]
wire _array_literal_expr_1: UInt<1>[3]
connect _array_literal_expr_1[0], neq(tuple_lhs.`0`, tuple_rhs.`0`)
connect _array_literal_expr_1[1], neq(tuple_lhs.`1`, tuple_rhs.`1`)
connect _array_literal_expr_1[2], neq(tuple_lhs.`2`, tuple_rhs.`2`)
wire _cast_array_to_bits_expr_1: UInt<1>[3]
connect _cast_array_to_bits_expr_1[0], _array_literal_expr_1[0]
connect _cast_array_to_bits_expr_1[1], _array_literal_expr_1[1]
connect _cast_array_to_bits_expr_1[2], _array_literal_expr_1[2]
wire _cast_to_bits_expr_1: UInt<3>
connect _cast_to_bits_expr_1, cat(_cast_array_to_bits_expr_1[2], cat(_cast_array_to_bits_expr_1[1], _cast_array_to_bits_expr_1[0]))
connect tuple_cmp_ne, orr(_cast_to_bits_expr_1) @[module-XXXXXXXXXX.rs 7:1]
connect test_struct_cmp_eq, and(eq(test_struct_lhs.a, test_struct_rhs.a), eq(test_struct_lhs.b, test_struct_rhs.b)) @[module-XXXXXXXXXX.rs 11:1]
connect test_struct_cmp_ne, or(neq(test_struct_lhs.a, test_struct_rhs.a), neq(test_struct_lhs.b, test_struct_rhs.b)) @[module-XXXXXXXXXX.rs 13:1]
connect test_struct_2_cmp_eq, eq(test_struct_2_lhs.v, test_struct_2_rhs.v) @[module-XXXXXXXXXX.rs 17:1]
connect test_struct_2_cmp_ne, neq(test_struct_2_lhs.v, test_struct_2_rhs.v) @[module-XXXXXXXXXX.rs 19:1]
connect test_struct_3_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 23:1]
connect test_struct_3_cmp_ne, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 25:1]
",
};
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,283 +0,0 @@
$timescale 1 ps $end
$scope module array_rw $end
$scope struct array_in $end
$var wire 8 ! \[0] $end
$var wire 8 " \[1] $end
$var wire 8 # \[2] $end
$var wire 8 $ \[3] $end
$var wire 8 % \[4] $end
$var wire 8 & \[5] $end
$var wire 8 ' \[6] $end
$var wire 8 ( \[7] $end
$var wire 8 ) \[8] $end
$var wire 8 * \[9] $end
$var wire 8 + \[10] $end
$var wire 8 , \[11] $end
$var wire 8 - \[12] $end
$var wire 8 . \[13] $end
$var wire 8 / \[14] $end
$var wire 8 0 \[15] $end
$upscope $end
$scope struct array_out $end
$var wire 8 1 \[0] $end
$var wire 8 2 \[1] $end
$var wire 8 3 \[2] $end
$var wire 8 4 \[3] $end
$var wire 8 5 \[4] $end
$var wire 8 6 \[5] $end
$var wire 8 7 \[6] $end
$var wire 8 8 \[7] $end
$var wire 8 9 \[8] $end
$var wire 8 : \[9] $end
$var wire 8 ; \[10] $end
$var wire 8 < \[11] $end
$var wire 8 = \[12] $end
$var wire 8 > \[13] $end
$var wire 8 ? \[14] $end
$var wire 8 @ \[15] $end
$upscope $end
$var wire 8 A read_index $end
$var wire 8 B read_data $end
$var wire 8 C write_index $end
$var wire 8 D write_data $end
$var wire 1 E write_en $end
$scope struct array_wire $end
$var wire 8 F \[0] $end
$var wire 8 G \[1] $end
$var wire 8 H \[2] $end
$var wire 8 I \[3] $end
$var wire 8 J \[4] $end
$var wire 8 K \[5] $end
$var wire 8 L \[6] $end
$var wire 8 M \[7] $end
$var wire 8 N \[8] $end
$var wire 8 O \[9] $end
$var wire 8 P \[10] $end
$var wire 8 Q \[11] $end
$var wire 8 R \[12] $end
$var wire 8 S \[13] $end
$var wire 8 T \[14] $end
$var wire 8 U \[15] $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
b11111111 !
b1111111 "
b111111 #
b11111 $
b1111 %
b111 &
b11 '
b1 (
b0 )
b10000000 *
b11000000 +
b11100000 ,
b11110000 -
b11111000 .
b11111100 /
b11111110 0
b11111111 1
b1111111 2
b111111 3
b11111 4
b1111 5
b111 6
b11 7
b1 8
b0 9
b10000000 :
b11000000 ;
b11100000 <
b11110000 =
b11111000 >
b11111100 ?
b11111110 @
b0 A
b11111111 B
b0 C
b0 D
0E
b11111111 F
b1111111 G
b111111 H
b11111 I
b1111 J
b111 K
b11 L
b1 M
b0 N
b10000000 O
b11000000 P
b11100000 Q
b11110000 R
b11111000 S
b11111100 T
b11111110 U
$end
#1000000
b1 A
b1111111 B
#2000000
b10 A
b111111 B
#3000000
b11 A
b11111 B
#4000000
b100 A
b1111 B
#5000000
b101 A
b111 B
#6000000
b110 A
b11 B
#7000000
b111 A
b1 B
#8000000
b1000 A
b0 B
#9000000
b1001 A
b10000000 B
#10000000
b1010 A
b11000000 B
#11000000
b1011 A
b11100000 B
#12000000
b1100 A
b11110000 B
#13000000
b1101 A
b11111000 B
#14000000
b1110 A
b11111100 B
#15000000
b1111 A
b11111110 B
#16000000
b10000 A
b0 B
#17000000
b0 1
b0 A
1E
b0 F
#18000000
b11111111 1
b1 2
b11111111 B
b1 C
b1 D
b11111111 F
b1 G
#19000000
b1111111 2
b100 3
b10 C
b100 D
b1111111 G
b100 H
#20000000
b111111 3
b1001 4
b11 C
b1001 D
b111111 H
b1001 I
#21000000
b11111 4
b10000 5
b100 C
b10000 D
b11111 I
b10000 J
#22000000
b1111 5
b11001 6
b101 C
b11001 D
b1111 J
b11001 K
#23000000
b111 6
b100100 7
b110 C
b100100 D
b111 K
b100100 L
#24000000
b11 7
b110001 8
b111 C
b110001 D
b11 L
b110001 M
#25000000
b1 8
b1000000 9
b1000 C
b1000000 D
b1 M
b1000000 N
#26000000
b0 9
b1010001 :
b1001 C
b1010001 D
b0 N
b1010001 O
#27000000
b10000000 :
b1100100 ;
b1010 C
b1100100 D
b10000000 O
b1100100 P
#28000000
b11000000 ;
b1111001 <
b1011 C
b1111001 D
b11000000 P
b1111001 Q
#29000000
b11100000 <
b10010000 =
b1100 C
b10010000 D
b11100000 Q
b10010000 R
#30000000
b11110000 =
b10101001 >
b1101 C
b10101001 D
b11110000 R
b10101001 S
#31000000
b11111000 >
b11000100 ?
b1110 C
b11000100 D
b11111000 S
b11000100 T
#32000000
b11111100 ?
b11100001 @
b1111 C
b11100001 D
b11111100 T
b11100001 U
#33000000
b11111110 @
b10000 C
b0 D
b11111110 U
#34000000

View file

@ -1,189 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 4,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::i",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::w",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:1:1
0: Const {
dest: StatePartIndex<BigSlots>(3), // (0x0) SlotDebugData { name: "", ty: Bool },
value: 0x0,
},
1: Const {
dest: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "", ty: Bool },
value: 0x1,
},
// at: module-XXXXXXXXXX.rs:4:1
2: Copy {
dest: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::w", ty: Bool },
src: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:5:1
3: BranchIfZero {
target: 5,
value: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::i", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:6:1
4: Copy {
dest: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::w", ty: Bool },
src: StatePartIndex<BigSlots>(3), // (0x0) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:1:1
5: Return,
],
..
},
pc: 5,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [],
},
big_slots: StatePart {
value: [
1,
0,
1,
0,
],
},
},
io: Instance {
name: <simulator>::conditional_assignment_last,
instantiated: Module {
name: conditional_assignment_last,
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::conditional_assignment_last,
instantiated: Module {
name: conditional_assignment_last,
..
},
}.i: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(conditional_assignment_last: conditional_assignment_last).conditional_assignment_last::i",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "conditional_assignment_last",
children: [
TraceModuleIO {
name: "i",
child: TraceBool {
location: TraceScalarId(0),
name: "i",
flow: Source,
},
ty: Bool,
flow: Source,
},
TraceWire {
name: "w",
child: TraceBool {
location: TraceScalarId(1),
name: "w",
flow: Duplex,
},
ty: Bool,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigBool {
index: StatePartIndex<BigSlots>(0),
},
state: 0x1,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(1),
kind: BigBool {
index: StatePartIndex<BigSlots>(1),
},
state: 0x0,
last_state: 0x1,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 2 μs,
clocks_triggered: [],
..
}

View file

@ -1,14 +0,0 @@
$timescale 1 ps $end
$scope module conditional_assignment_last $end
$var wire 1 ! i $end
$var wire 1 " w $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
1"
$end
#1000000
1!
0"
#2000000

View file

@ -1,142 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const: connect_const).connect_const::o",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:1:1
0: Const {
dest: StatePartIndex<BigSlots>(1), // (0x5) SlotDebugData { name: "", ty: UInt<8> },
value: 0x5,
},
// at: module-XXXXXXXXXX.rs:3:1
1: Copy {
dest: StatePartIndex<BigSlots>(0), // (0x5) SlotDebugData { name: "InstantiatedModule(connect_const: connect_const).connect_const::o", ty: UInt<8> },
src: StatePartIndex<BigSlots>(1), // (0x5) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:1:1
2: Return,
],
..
},
pc: 2,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [],
},
big_slots: StatePart {
value: [
5,
5,
],
},
},
io: Instance {
name: <simulator>::connect_const,
instantiated: Module {
name: connect_const,
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::connect_const,
instantiated: Module {
name: connect_const,
..
},
}.o: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<8>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const: connect_const).connect_const::o",
ty: UInt<8>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "connect_const",
children: [
TraceModuleIO {
name: "o",
child: TraceUInt {
location: TraceScalarId(0),
name: "o",
ty: UInt<8>,
flow: Sink,
},
ty: UInt<8>,
flow: Sink,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigUInt {
index: StatePartIndex<BigSlots>(0),
ty: UInt<8>,
},
state: 0x05,
last_state: 0x05,
},
],
trace_memories: {},
trace_writers: [],
instant: 0 s,
clocks_triggered: [],
..
}

View file

@ -1,229 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 5,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out",
ty: AsyncReset,
},
SlotDebugData {
name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::bit_out",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: AsyncReset,
},
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:1:1
0: Const {
dest: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "", ty: Bool },
value: 0x1,
},
1: Copy {
dest: StatePartIndex<BigSlots>(3), // (0x1) SlotDebugData { name: "", ty: AsyncReset },
src: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:4:1
2: Copy {
dest: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out", ty: AsyncReset },
src: StatePartIndex<BigSlots>(3), // (0x1) SlotDebugData { name: "", ty: AsyncReset },
},
// at: module-XXXXXXXXXX.rs:1:1
3: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x1) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out", ty: AsyncReset },
},
// at: module-XXXXXXXXXX.rs:5:1
4: Copy {
dest: StatePartIndex<BigSlots>(1), // (0x1) SlotDebugData { name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::bit_out", ty: Bool },
src: StatePartIndex<BigSlots>(4), // (0x1) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:1:1
5: Return,
],
..
},
pc: 5,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [],
},
big_slots: StatePart {
value: [
1,
1,
1,
1,
1,
],
},
},
io: Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
}.bit_out: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::bit_out",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::connect_const_reset,
instantiated: Module {
name: connect_const_reset,
..
},
}.reset_out: CompiledValue {
layout: CompiledTypeLayout {
ty: AsyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(connect_const_reset: connect_const_reset).connect_const_reset::reset_out",
ty: AsyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "connect_const_reset",
children: [
TraceModuleIO {
name: "reset_out",
child: TraceAsyncReset {
location: TraceScalarId(0),
name: "reset_out",
flow: Sink,
},
ty: AsyncReset,
flow: Sink,
},
TraceModuleIO {
name: "bit_out",
child: TraceBool {
location: TraceScalarId(1),
name: "bit_out",
flow: Sink,
},
ty: Bool,
flow: Sink,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigAsyncReset {
index: StatePartIndex<BigSlots>(0),
},
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(1),
kind: BigBool {
index: StatePartIndex<BigSlots>(1),
},
state: 0x1,
last_state: 0x1,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 1 μs,
clocks_triggered: [],
..
}

View file

@ -1,11 +0,0 @@
$timescale 1 ps $end
$scope module connect_const_reset $end
$var wire 1 ! reset_out $end
$var wire 1 " bit_out $end
$upscope $end
$enddefinitions $end
$dumpvars
1!
1"
$end
#1000000

View file

@ -1,522 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 4,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 10,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.rst",
ty: AsyncReset,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count_reg",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count_reg$next",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: UInt<1>,
},
SlotDebugData {
name: "",
ty: UInt<5>,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:1:1
0: Const {
dest: StatePartIndex<BigSlots>(7), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
value: 0x1,
},
1: Copy {
dest: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.rst", ty: AsyncReset },
},
// at: module-XXXXXXXXXX.rs:3:1
2: IsNonZeroDestIsSmall {
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.rst", ty: AsyncReset },
},
// at: module-XXXXXXXXXX.rs:1:1
3: Const {
dest: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
value: 0x3,
},
// at: module-XXXXXXXXXX.rs:3:1
4: BranchIfZero {
target: 6,
value: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
},
5: Copy {
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> },
},
// at: module-XXXXXXXXXX.rs:1:1
6: Add {
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> },
rhs: StatePartIndex<BigSlots>(7), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
},
7: CastToUInt {
dest: StatePartIndex<BigSlots>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
src: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
dest_width: 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>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:6:1
9: Copy {
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> },
},
// at: module-XXXXXXXXXX.rs:3:1
10: IsNonZeroDestIsSmall {
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 },
},
11: AndSmall {
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
12: BranchIfSmallNonZero {
target: 16,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
13: BranchIfSmallZero {
target: 17,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
14: Copy {
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> },
},
15: Branch {
target: 17,
},
16: Copy {
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> },
},
17: XorSmallImmediate {
dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: 0x1,
},
// at: module-XXXXXXXXXX.rs:1:1
18: Return,
],
..
},
pc: 18,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [
0,
0,
1,
0,
],
},
big_slots: StatePart {
value: [
1,
0,
3,
3,
4,
3,
0,
1,
4,
4,
],
},
},
io: Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: AsyncReset,
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.rst",
ty: AsyncReset,
},
],
..
},
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: AsyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: AsyncReset,
},
],
..
},
},
body: Scalar,
},
},
],
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.rst: CompiledValue {
layout: CompiledTypeLayout {
ty: AsyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: AsyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.count: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "counter",
children: [
TraceModuleIO {
name: "cd",
child: TraceBundle {
name: "cd",
fields: [
TraceClock {
location: TraceScalarId(0),
name: "clk",
flow: Source,
},
TraceAsyncReset {
location: TraceScalarId(1),
name: "rst",
flow: Source,
},
],
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: AsyncReset,
},
flow: Source,
},
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: AsyncReset,
},
flow: Source,
},
TraceModuleIO {
name: "count",
child: TraceUInt {
location: TraceScalarId(2),
name: "count",
ty: UInt<4>,
flow: Sink,
},
ty: UInt<4>,
flow: Sink,
},
TraceReg {
name: "count_reg",
child: TraceUInt {
location: TraceScalarId(3),
name: "count_reg",
ty: UInt<4>,
flow: Duplex,
},
ty: UInt<4>,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigClock {
index: StatePartIndex<BigSlots>(0),
},
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(1),
kind: BigAsyncReset {
index: StatePartIndex<BigSlots>(1),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(2),
kind: BigUInt {
index: StatePartIndex<BigSlots>(2),
ty: UInt<4>,
},
state: 0x3,
last_state: 0x2,
},
SimTrace {
id: TraceScalarId(3),
kind: BigUInt {
index: StatePartIndex<BigSlots>(3),
ty: UInt<4>,
},
state: 0x3,
last_state: 0x3,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 66 μs,
clocks_triggered: [
StatePartIndex<SmallSlots>(1),
],
..
}

View file

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

View file

@ -1,503 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 4,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 9,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.rst",
ty: SyncReset,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count_reg",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count_reg$next",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: UInt<1>,
},
SlotDebugData {
name: "",
ty: UInt<5>,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:6:1
0: Copy {
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> },
},
// at: module-XXXXXXXXXX.rs:1:1
1: Const {
dest: StatePartIndex<BigSlots>(6), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
value: 0x1,
},
2: Add {
dest: StatePartIndex<BigSlots>(7), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
lhs: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
rhs: StatePartIndex<BigSlots>(6), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
},
3: CastToUInt {
dest: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
src: StatePartIndex<BigSlots>(7), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
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
5: IsNonZeroDestIsSmall {
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 },
},
// at: module-XXXXXXXXXX.rs:1:1
6: Const {
dest: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
value: 0x3,
},
// at: module-XXXXXXXXXX.rs:3:1
7: IsNonZeroDestIsSmall {
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 },
},
8: AndSmall {
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
9: BranchIfSmallZero {
target: 14,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
10: BranchIfSmallNonZero {
target: 13,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
11: Copy {
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> },
},
12: Branch {
target: 14,
},
13: Copy {
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> },
},
14: XorSmallImmediate {
dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: 0x1,
},
// at: module-XXXXXXXXXX.rs:1:1
15: Return,
],
..
},
pc: 15,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [
0,
0,
1,
0,
],
},
big_slots: StatePart {
value: [
1,
0,
3,
3,
4,
3,
1,
4,
4,
],
},
},
io: Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::cd.rst",
ty: SyncReset,
},
],
..
},
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
},
],
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.cd.rst: CompiledValue {
layout: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::counter,
instantiated: Module {
name: counter,
..
},
}.count: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(counter: counter).counter::count",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "counter",
children: [
TraceModuleIO {
name: "cd",
child: TraceBundle {
name: "cd",
fields: [
TraceClock {
location: TraceScalarId(0),
name: "clk",
flow: Source,
},
TraceSyncReset {
location: TraceScalarId(1),
name: "rst",
flow: Source,
},
],
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
},
flow: Source,
},
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
},
flow: Source,
},
TraceModuleIO {
name: "count",
child: TraceUInt {
location: TraceScalarId(2),
name: "count",
ty: UInt<4>,
flow: Sink,
},
ty: UInt<4>,
flow: Sink,
},
TraceReg {
name: "count_reg",
child: TraceUInt {
location: TraceScalarId(3),
name: "count_reg",
ty: UInt<4>,
flow: Duplex,
},
ty: UInt<4>,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigClock {
index: StatePartIndex<BigSlots>(0),
},
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(1),
kind: BigSyncReset {
index: StatePartIndex<BigSlots>(1),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(2),
kind: BigUInt {
index: StatePartIndex<BigSlots>(2),
ty: UInt<4>,
},
state: 0x3,
last_state: 0x2,
},
SimTrace {
id: TraceScalarId(3),
kind: BigUInt {
index: StatePartIndex<BigSlots>(3),
ty: UInt<4>,
},
state: 0x3,
last_state: 0x3,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 66 μs,
clocks_triggered: [
StatePartIndex<SmallSlots>(1),
],
..
}

View file

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

View file

@ -1,153 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 4,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(duplicate_names: duplicate_names).duplicate_names::w",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
SlotDebugData {
name: "InstantiatedModule(duplicate_names: duplicate_names).duplicate_names::w",
ty: UInt<8>,
},
SlotDebugData {
name: "",
ty: UInt<8>,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:1:1
0: Const {
dest: StatePartIndex<BigSlots>(3), // (0x6) SlotDebugData { name: "", ty: UInt<8> },
value: 0x6,
},
// at: module-XXXXXXXXXX.rs:5:1
1: Copy {
dest: StatePartIndex<BigSlots>(2), // (0x6) SlotDebugData { name: "InstantiatedModule(duplicate_names: duplicate_names).duplicate_names::w", ty: UInt<8> },
src: StatePartIndex<BigSlots>(3), // (0x6) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:1:1
2: Const {
dest: StatePartIndex<BigSlots>(1), // (0x5) SlotDebugData { name: "", ty: UInt<8> },
value: 0x5,
},
// at: module-XXXXXXXXXX.rs:3:1
3: Copy {
dest: StatePartIndex<BigSlots>(0), // (0x5) SlotDebugData { name: "InstantiatedModule(duplicate_names: duplicate_names).duplicate_names::w", ty: UInt<8> },
src: StatePartIndex<BigSlots>(1), // (0x5) SlotDebugData { name: "", ty: UInt<8> },
},
// at: module-XXXXXXXXXX.rs:1:1
4: Return,
],
..
},
pc: 4,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [],
},
big_slots: StatePart {
value: [
5,
5,
6,
6,
],
},
},
io: Instance {
name: <simulator>::duplicate_names,
instantiated: Module {
name: duplicate_names,
..
},
},
uninitialized_inputs: {},
io_targets: {},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "duplicate_names",
children: [
TraceWire {
name: "w",
child: TraceUInt {
location: TraceScalarId(0),
name: "w",
ty: UInt<8>,
flow: Duplex,
},
ty: UInt<8>,
},
TraceWire {
name: "w",
child: TraceUInt {
location: TraceScalarId(1),
name: "w",
ty: UInt<8>,
flow: Duplex,
},
ty: UInt<8>,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigUInt {
index: StatePartIndex<BigSlots>(0),
ty: UInt<8>,
},
state: 0x05,
last_state: 0x05,
},
SimTrace {
id: TraceScalarId(1),
kind: BigUInt {
index: StatePartIndex<BigSlots>(2),
ty: UInt<8>,
},
state: 0x06,
last_state: 0x06,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 1 μs,
clocks_triggered: [],
..
}

View file

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

File diff suppressed because it is too large Load diff

View file

@ -1,110 +0,0 @@
$timescale 1 ps $end
$scope module enums $end
$scope struct cd $end
$var wire 1 ! clk $end
$var wire 1 " rst $end
$upscope $end
$var wire 1 # en $end
$var wire 2 $ which_in $end
$var wire 4 % data_in $end
$var wire 2 & which_out $end
$var wire 4 ' data_out $end
$scope struct b_out $end
$var string 1 ( \$tag $end
$scope struct HdlSome $end
$var wire 1 ) \0 $end
$var wire 1 * \1 $end
$upscope $end
$upscope $end
$scope struct the_reg $end
$var string 1 + \$tag $end
$scope struct B $end
$var reg 1 , \0 $end
$var reg 1 - \1 $end
$upscope $end
$scope struct C $end
$scope struct a $end
$var reg 1 . \[0] $end
$var reg 1 / \[1] $end
$upscope $end
$var reg 2 0 b $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
1"
0#
b0 $
b0 %
b0 &
b0 '
sHdlNone\x20(0) (
0)
0*
sA\x20(0) +
0,
0-
0.
0/
b0 0
$end
#1000000
1!
#1100000
0"
#2000000
0!
#3000000
1!
#4000000
1#
b1 $
0!
#5000000
1!
b1 &
sHdlSome\x20(1) (
sB\x20(1) +
#6000000
0#
b0 $
0!
#7000000
1!
#8000000
1#
b1 $
b1111 %
0!
#9000000
1!
b11 '
1)
1*
1,
1-
1.
1/
#10000000
0!
#11000000
1!
#12000000
b10 $
0!
#13000000
1!
b10 &
b1111 '
sHdlNone\x20(0) (
0)
0*
sC\x20(2) +
b11 0
#14000000
0!
#15000000
1!
#16000000

File diff suppressed because it is too large Load diff

View file

@ -1,408 +0,0 @@
$timescale 1 ps $end
$scope module memories $end
$scope struct r $end
$var wire 4 ! addr $end
$var wire 1 " en $end
$var wire 1 # clk $end
$scope struct data $end
$var wire 8 $ \0 $end
$var wire 8 % \1 $end
$upscope $end
$upscope $end
$scope struct w $end
$var wire 4 & addr $end
$var wire 1 ' en $end
$var wire 1 ( clk $end
$scope struct data $end
$var wire 8 ) \0 $end
$var wire 8 * \1 $end
$upscope $end
$scope struct mask $end
$var wire 1 + \0 $end
$var wire 1 , \1 $end
$upscope $end
$upscope $end
$scope struct mem $end
$scope struct contents $end
$scope struct \[0] $end
$scope struct mem $end
$var reg 8 9 \0 $end
$var reg 8 I \1 $end
$upscope $end
$upscope $end
$scope struct \[1] $end
$scope struct mem $end
$var reg 8 : \0 $end
$var reg 8 J \1 $end
$upscope $end
$upscope $end
$scope struct \[2] $end
$scope struct mem $end
$var reg 8 ; \0 $end
$var reg 8 K \1 $end
$upscope $end
$upscope $end
$scope struct \[3] $end
$scope struct mem $end
$var reg 8 < \0 $end
$var reg 8 L \1 $end
$upscope $end
$upscope $end
$scope struct \[4] $end
$scope struct mem $end
$var reg 8 = \0 $end
$var reg 8 M \1 $end
$upscope $end
$upscope $end
$scope struct \[5] $end
$scope struct mem $end
$var reg 8 > \0 $end
$var reg 8 N \1 $end
$upscope $end
$upscope $end
$scope struct \[6] $end
$scope struct mem $end
$var reg 8 ? \0 $end
$var reg 8 O \1 $end
$upscope $end
$upscope $end
$scope struct \[7] $end
$scope struct mem $end
$var reg 8 @ \0 $end
$var reg 8 P \1 $end
$upscope $end
$upscope $end
$scope struct \[8] $end
$scope struct mem $end
$var reg 8 A \0 $end
$var reg 8 Q \1 $end
$upscope $end
$upscope $end
$scope struct \[9] $end
$scope struct mem $end
$var reg 8 B \0 $end
$var reg 8 R \1 $end
$upscope $end
$upscope $end
$scope struct \[10] $end
$scope struct mem $end
$var reg 8 C \0 $end
$var reg 8 S \1 $end
$upscope $end
$upscope $end
$scope struct \[11] $end
$scope struct mem $end
$var reg 8 D \0 $end
$var reg 8 T \1 $end
$upscope $end
$upscope $end
$scope struct \[12] $end
$scope struct mem $end
$var reg 8 E \0 $end
$var reg 8 U \1 $end
$upscope $end
$upscope $end
$scope struct \[13] $end
$scope struct mem $end
$var reg 8 F \0 $end
$var reg 8 V \1 $end
$upscope $end
$upscope $end
$scope struct \[14] $end
$scope struct mem $end
$var reg 8 G \0 $end
$var reg 8 W \1 $end
$upscope $end
$upscope $end
$scope struct \[15] $end
$scope struct mem $end
$var reg 8 H \0 $end
$var reg 8 X \1 $end
$upscope $end
$upscope $end
$upscope $end
$scope struct r0 $end
$var wire 4 - addr $end
$var wire 1 . en $end
$var wire 1 / clk $end
$scope struct data $end
$var wire 8 0 \0 $end
$var wire 8 1 \1 $end
$upscope $end
$upscope $end
$scope struct w1 $end
$var wire 4 2 addr $end
$var wire 1 3 en $end
$var wire 1 4 clk $end
$scope struct data $end
$var wire 8 5 \0 $end
$var wire 8 6 \1 $end
$upscope $end
$scope struct mask $end
$var wire 1 7 \0 $end
$var wire 1 8 \1 $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
b1 9
b100011 I
b1 :
b100011 J
b1 ;
b100011 K
b1 <
b100011 L
b1 =
b100011 M
b1 >
b100011 N
b1 ?
b100011 O
b1 @
b100011 P
b1 A
b100011 Q
b1 B
b100011 R
b1 C
b100011 S
b1 D
b100011 T
b1 E
b100011 U
b1 F
b100011 V
b1 G
b100011 W
b1 H
b100011 X
b0 !
0"
0#
b0 $
b0 %
b0 &
0'
0(
b0 )
b0 *
0+
0,
b0 -
0.
0/
b0 0
b0 1
b0 2
03
04
b0 5
b0 6
07
08
$end
#1000000
1#
1(
1/
14
#2000000
1"
0#
b1 $
b100011 %
1'
0(
b10000 )
b100000 *
1+
1,
1.
0/
b1 0
b100011 1
13
04
b10000 5
b100000 6
17
18
#3000000
b10000 9
b100000 I
1#
1(
1/
14
b10000 $
b100000 %
b10000 0
b100000 1
#4000000
0#
0(
b110000 )
b1000000 *
0+
0/
04
b110000 5
b1000000 6
07
#5000000
b10000 9
b1000000 I
1#
1(
1/
14
b1000000 %
b1000000 1
#6000000
0#
0(
b1010000 )
b1100000 *
1+
0,
0/
04
b1010000 5
b1100000 6
17
08
#7000000
b1010000 9
b1000000 I
1#
1(
1/
14
b1010000 $
b1010000 0
#8000000
0#
0(
b1110000 )
b10000000 *
0+
0/
04
b1110000 5
b10000000 6
07
#9000000
1#
1(
1/
14
#10000000
0#
0'
0(
b10010000 )
b10100000 *
0/
03
04
b10010000 5
b10100000 6
#11000000
1#
1(
1/
14
#12000000
0#
b1 &
1'
0(
1+
1,
0/
b1 2
13
04
17
18
#13000000
b10010000 :
b10100000 J
1#
1(
1/
14
#14000000
0#
b10 &
0(
b10110000 )
b11000000 *
0/
b10 2
04
b10110000 5
b11000000 6
#15000000
b10110000 ;
b11000000 K
1#
1(
1/
14
#16000000
0#
0'
0(
b11010000 )
b11100000 *
0/
03
04
b11010000 5
b11100000 6
#17000000
1#
1(
1/
14
#18000000
b1 !
0#
b10010000 $
b10100000 %
0(
b1 -
0/
b10010000 0
b10100000 1
04
#19000000
1#
1(
1/
14
#20000000
b10 !
0#
b10110000 $
b11000000 %
0(
b10 -
0/
b10110000 0
b11000000 1
04
#21000000
1#
1(
1/
14
#22000000
0#
0(
0/
04

File diff suppressed because it is too large Load diff

View file

@ -1,363 +0,0 @@
$timescale 1 ps $end
$scope module memories2 $end
$scope struct rw $end
$var wire 3 ! addr $end
$var wire 1 " en $end
$var wire 1 # clk $end
$var wire 2 $ rdata $end
$var wire 1 % wmode $end
$var wire 2 & wdata $end
$var wire 1 ' wmask $end
$upscope $end
$scope struct mem $end
$scope struct contents $end
$scope struct \[0] $end
$scope struct mem $end
$var string 1 1 \$tag $end
$var reg 1 6 HdlSome $end
$upscope $end
$upscope $end
$scope struct \[1] $end
$scope struct mem $end
$var string 1 2 \$tag $end
$var reg 1 7 HdlSome $end
$upscope $end
$upscope $end
$scope struct \[2] $end
$scope struct mem $end
$var string 1 3 \$tag $end
$var reg 1 8 HdlSome $end
$upscope $end
$upscope $end
$scope struct \[3] $end
$scope struct mem $end
$var string 1 4 \$tag $end
$var reg 1 9 HdlSome $end
$upscope $end
$upscope $end
$scope struct \[4] $end
$scope struct mem $end
$var string 1 5 \$tag $end
$var reg 1 : HdlSome $end
$upscope $end
$upscope $end
$upscope $end
$scope struct rw0 $end
$var wire 3 ( addr $end
$var wire 1 ) en $end
$var wire 1 * clk $end
$scope struct rdata $end
$var string 1 + \$tag $end
$var wire 1 , HdlSome $end
$upscope $end
$var wire 1 - wmode $end
$scope struct wdata $end
$var string 1 . \$tag $end
$var wire 1 / HdlSome $end
$upscope $end
$var wire 1 0 wmask $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
sHdlSome\x20(1) 1
16
sHdlSome\x20(1) 2
17
sHdlSome\x20(1) 3
18
sHdlSome\x20(1) 4
19
sHdlSome\x20(1) 5
1:
b0 !
0"
0#
b0 $
0%
b0 &
0'
b0 (
0)
0*
sHdlNone\x20(0) +
0,
0-
sHdlNone\x20(0) .
0/
00
$end
#250000
1#
1*
#500000
#750000
0#
0*
#1000000
1"
1)
#1250000
1#
1*
b11 $
sHdlSome\x20(1) +
1,
#1500000
#1750000
0#
0*
#2000000
0"
0)
#2250000
1#
1*
b0 $
sHdlNone\x20(0) +
0,
#2500000
#2750000
0#
0*
#3000000
1"
1%
1'
1)
1-
10
#3250000
sHdlNone\x20(0) 1
06
1#
1*
#3500000
#3750000
0#
0*
#4000000
0%
0'
0-
00
#4250000
1#
1*
#4500000
#4750000
0#
0*
#5000000
1%
b11 &
1-
sHdlSome\x20(1) .
1/
#5250000
1#
1*
#5500000
#5750000
0#
0*
#6000000
b1 !
b1 &
1'
b1 (
0/
10
#6250000
sHdlSome\x20(1) 2
07
1#
1*
#6500000
#6750000
0#
0*
#7000000
b10 !
b10 &
b10 (
sHdlNone\x20(0) .
#7250000
sHdlNone\x20(0) 3
08
1#
1*
#7500000
#7750000
0#
0*
#8000000
b11 !
b11 &
b11 (
sHdlSome\x20(1) .
1/
#8250000
sHdlSome\x20(1) 4
19
1#
1*
#8500000
#8750000
0#
0*
#9000000
b100 !
b10 &
b100 (
sHdlNone\x20(0) .
0/
#9250000
sHdlNone\x20(0) 5
0:
1#
1*
#9500000
#9750000
0#
0*
#10000000
b101 !
b1 &
b101 (
sHdlSome\x20(1) .
#10250000
1#
1*
#10500000
#10750000
0#
0*
#11000000
b110 !
b110 (
#11250000
1#
1*
#11500000
#11750000
0#
0*
#12000000
b111 !
b111 (
#12250000
1#
1*
#12500000
#12750000
0#
0*
#13000000
0%
b0 &
0'
0-
sHdlNone\x20(0) .
00
#13250000
1#
1*
#13500000
#13750000
0#
0*
#14000000
b110 !
b110 (
#14250000
1#
1*
#14500000
#14750000
0#
0*
#15000000
b101 !
b101 (
#15250000
1#
1*
#15500000
#15750000
0#
0*
#16000000
b100 !
b100 (
#16250000
1#
1*
#16500000
#16750000
0#
0*
#17000000
b11 !
b11 (
#17250000
1#
1*
b11 $
sHdlSome\x20(1) +
1,
#17500000
#17750000
0#
0*
#18000000
b10 !
b10 (
#18250000
1#
1*
b0 $
sHdlNone\x20(0) +
0,
#18500000
#18750000
0#
0*
#19000000
b0 !
b0 (
#19250000
1#
1*
#19500000
#19750000
0#
0*
#20000000
b1 !
b1 (
#20250000
1#
1*
b1 $
sHdlSome\x20(1) +
#20500000
#20750000
0#
0*
#21000000
b0 !
0"
b0 (
0)
#21250000
1#
1*
b0 $
sHdlNone\x20(0) +
#21500000
#21750000
0#
0*
#22000000

File diff suppressed because it is too large Load diff

View file

@ -1,836 +0,0 @@
$timescale 1 ps $end
$scope module memories3 $end
$scope struct r $end
$var wire 3 ! addr $end
$var wire 1 " en $end
$var wire 1 # clk $end
$scope struct data $end
$var wire 8 $ \[0] $end
$var wire 8 % \[1] $end
$var wire 8 & \[2] $end
$var wire 8 ' \[3] $end
$var wire 8 ( \[4] $end
$var wire 8 ) \[5] $end
$var wire 8 * \[6] $end
$var wire 8 + \[7] $end
$upscope $end
$upscope $end
$scope struct w $end
$var wire 3 , addr $end
$var wire 1 - en $end
$var wire 1 . clk $end
$scope struct data $end
$var wire 8 / \[0] $end
$var wire 8 0 \[1] $end
$var wire 8 1 \[2] $end
$var wire 8 2 \[3] $end
$var wire 8 3 \[4] $end
$var wire 8 4 \[5] $end
$var wire 8 5 \[6] $end
$var wire 8 6 \[7] $end
$upscope $end
$scope struct mask $end
$var wire 1 7 \[0] $end
$var wire 1 8 \[1] $end
$var wire 1 9 \[2] $end
$var wire 1 : \[3] $end
$var wire 1 ; \[4] $end
$var wire 1 < \[5] $end
$var wire 1 = \[6] $end
$var wire 1 > \[7] $end
$upscope $end
$upscope $end
$scope struct mem $end
$scope struct contents $end
$scope struct \[0] $end
$scope struct mem $end
$var reg 8 ] \[0] $end
$var reg 8 e \[1] $end
$var reg 8 m \[2] $end
$var reg 8 u \[3] $end
$var reg 8 } \[4] $end
$var reg 8 '" \[5] $end
$var reg 8 /" \[6] $end
$var reg 8 7" \[7] $end
$upscope $end
$upscope $end
$scope struct \[1] $end
$scope struct mem $end
$var reg 8 ^ \[0] $end
$var reg 8 f \[1] $end
$var reg 8 n \[2] $end
$var reg 8 v \[3] $end
$var reg 8 ~ \[4] $end
$var reg 8 (" \[5] $end
$var reg 8 0" \[6] $end
$var reg 8 8" \[7] $end
$upscope $end
$upscope $end
$scope struct \[2] $end
$scope struct mem $end
$var reg 8 _ \[0] $end
$var reg 8 g \[1] $end
$var reg 8 o \[2] $end
$var reg 8 w \[3] $end
$var reg 8 !" \[4] $end
$var reg 8 )" \[5] $end
$var reg 8 1" \[6] $end
$var reg 8 9" \[7] $end
$upscope $end
$upscope $end
$scope struct \[3] $end
$scope struct mem $end
$var reg 8 ` \[0] $end
$var reg 8 h \[1] $end
$var reg 8 p \[2] $end
$var reg 8 x \[3] $end
$var reg 8 "" \[4] $end
$var reg 8 *" \[5] $end
$var reg 8 2" \[6] $end
$var reg 8 :" \[7] $end
$upscope $end
$upscope $end
$scope struct \[4] $end
$scope struct mem $end
$var reg 8 a \[0] $end
$var reg 8 i \[1] $end
$var reg 8 q \[2] $end
$var reg 8 y \[3] $end
$var reg 8 #" \[4] $end
$var reg 8 +" \[5] $end
$var reg 8 3" \[6] $end
$var reg 8 ;" \[7] $end
$upscope $end
$upscope $end
$scope struct \[5] $end
$scope struct mem $end
$var reg 8 b \[0] $end
$var reg 8 j \[1] $end
$var reg 8 r \[2] $end
$var reg 8 z \[3] $end
$var reg 8 $" \[4] $end
$var reg 8 ," \[5] $end
$var reg 8 4" \[6] $end
$var reg 8 <" \[7] $end
$upscope $end
$upscope $end
$scope struct \[6] $end
$scope struct mem $end
$var reg 8 c \[0] $end
$var reg 8 k \[1] $end
$var reg 8 s \[2] $end
$var reg 8 { \[3] $end
$var reg 8 %" \[4] $end
$var reg 8 -" \[5] $end
$var reg 8 5" \[6] $end
$var reg 8 =" \[7] $end
$upscope $end
$upscope $end
$scope struct \[7] $end
$scope struct mem $end
$var reg 8 d \[0] $end
$var reg 8 l \[1] $end
$var reg 8 t \[2] $end
$var reg 8 | \[3] $end
$var reg 8 &" \[4] $end
$var reg 8 ." \[5] $end
$var reg 8 6" \[6] $end
$var reg 8 >" \[7] $end
$upscope $end
$upscope $end
$upscope $end
$scope struct r0 $end
$var wire 3 ? addr $end
$var wire 1 @ en $end
$var wire 1 A clk $end
$scope struct data $end
$var wire 8 B \[0] $end
$var wire 8 C \[1] $end
$var wire 8 D \[2] $end
$var wire 8 E \[3] $end
$var wire 8 F \[4] $end
$var wire 8 G \[5] $end
$var wire 8 H \[6] $end
$var wire 8 I \[7] $end
$upscope $end
$upscope $end
$scope struct w1 $end
$var wire 3 J addr $end
$var wire 1 K en $end
$var wire 1 L clk $end
$scope struct data $end
$var wire 8 M \[0] $end
$var wire 8 N \[1] $end
$var wire 8 O \[2] $end
$var wire 8 P \[3] $end
$var wire 8 Q \[4] $end
$var wire 8 R \[5] $end
$var wire 8 S \[6] $end
$var wire 8 T \[7] $end
$upscope $end
$scope struct mask $end
$var wire 1 U \[0] $end
$var wire 1 V \[1] $end
$var wire 1 W \[2] $end
$var wire 1 X \[3] $end
$var wire 1 Y \[4] $end
$var wire 1 Z \[5] $end
$var wire 1 [ \[6] $end
$var wire 1 \ \[7] $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
b0 ]
b0 e
b0 m
b0 u
b0 }
b0 '"
b0 /"
b0 7"
b0 ^
b0 f
b0 n
b0 v
b0 ~
b0 ("
b0 0"
b0 8"
b0 _
b0 g
b0 o
b0 w
b0 !"
b0 )"
b0 1"
b0 9"
b0 `
b0 h
b0 p
b0 x
b0 ""
b0 *"
b0 2"
b0 :"
b0 a
b0 i
b0 q
b0 y
b0 #"
b0 +"
b0 3"
b0 ;"
b0 b
b0 j
b0 r
b0 z
b0 $"
b0 ,"
b0 4"
b0 <"
b0 c
b0 k
b0 s
b0 {
b0 %"
b0 -"
b0 5"
b0 ="
b0 d
b0 l
b0 t
b0 |
b0 &"
b0 ."
b0 6"
b0 >"
b0 !
0"
0#
b0 $
b0 %
b0 &
b0 '
b0 (
b0 )
b0 *
b0 +
b0 ,
1-
0.
b10010 /
b110100 0
b1010110 1
b1111000 2
b10011010 3
b10111100 4
b11011110 5
b11110000 6
07
18
09
1:
1;
0<
0=
1>
b0 ?
0@
0A
b0 B
b0 C
b0 D
b0 E
b0 F
b0 G
b0 H
b0 I
b0 J
1K
0L
b10010 M
b110100 N
b1010110 O
b1111000 P
b10011010 Q
b10111100 R
b11011110 S
b11110000 T
0U
1V
0W
1X
1Y
0Z
0[
1\
$end
#250000
1#
1.
1A
1L
#500000
#750000
0#
0.
0A
0L
#1000000
1"
b1 ,
0-
b0 /
b0 0
b0 1
b0 2
b0 3
b0 4
b0 5
b0 6
08
0:
0;
0>
1@
b1 J
0K
b0 M
b0 N
b0 O
b0 P
b0 Q
b0 R
b0 S
b0 T
0V
0X
0Y
0\
#1250000
b0 ]
b110100 e
b0 m
b1111000 u
b10011010 }
b0 '"
b0 /"
b11110000 7"
1#
1.
1A
1L
#1500000
#1750000
0#
0.
0A
0L
#2000000
#2250000
1#
1.
1A
1L
#2500000
#2750000
0#
0.
0A
0L
#3000000
b0 ,
1-
b11111110 /
b11011100 0
b10111010 1
b10011000 2
b1110110 3
b1010100 4
b110010 5
b10000 6
17
18
19
1:
1;
1<
1=
1>
b0 J
1K
b11111110 M
b11011100 N
b10111010 O
b10011000 P
b1110110 Q
b1010100 R
b110010 S
b10000 T
1U
1V
1W
1X
1Y
1Z
1[
1\
#3250000
1#
1.
1A
b110100 C
b1111000 E
b10011010 F
b11110000 I
1L
b110100 %
b1111000 '
b10011010 (
b11110000 +
#3500000
#3750000
0#
0.
0A
0L
#4000000
#4250000
b11111110 ]
b11011100 e
b10111010 m
b10011000 u
b1110110 }
b1010100 '"
b110010 /"
b10000 7"
1#
1.
1A
1L
#4500000
#4750000
0#
0.
0A
0L
#5000000
#5250000
b11111110 ]
b11011100 e
b10111010 m
b10011000 u
b1110110 }
b1010100 '"
b110010 /"
b10000 7"
1#
1.
1A
1L
#5500000
#5750000
0#
0.
0A
0L
#6000000
0"
b1 ,
b10011 /
b1010111 0
b10011011 1
b11011111 2
b10 3
b1000110 4
b10001010 5
b11001110 6
0@
b1 J
b10011 M
b1010111 N
b10011011 O
b11011111 P
b10 Q
b1000110 R
b10001010 S
b11001110 T
#6250000
b11111110 ]
b11011100 e
b10111010 m
b10011000 u
b1110110 }
b1010100 '"
b110010 /"
b10000 7"
1#
1.
1A
b11111110 B
b11011100 C
b10111010 D
b10011000 E
b1110110 F
b1010100 G
b110010 H
b10000 I
1L
b11111110 $
b11011100 %
b10111010 &
b10011000 '
b1110110 (
b1010100 )
b110010 *
b10000 +
#6500000
#6750000
0#
0.
0A
0L
#7000000
b10 ,
b1110100 /
b1100101 0
b1110011 1
b1110100 2
b1101001 3
b1101110 4
b1100111 5
b100001 6
b10 J
b1110100 M
b1100101 N
b1110011 O
b1110100 P
b1101001 Q
b1101110 R
b1100111 S
b100001 T
#7250000
b10011 ^
b1010111 f
b10011011 n
b11011111 v
b10 ~
b1000110 ("
b10001010 0"
b11001110 8"
1#
1.
1A
b0 B
b0 C
b0 D
b0 E
b0 F
b0 G
b0 H
b0 I
1L
b0 $
b0 %
b0 &
b0 '
b0 (
b0 )
b0 *
b0 +
#7500000
#7750000
0#
0.
0A
0L
#8000000
b11 ,
b1101101 /
b1101111 0
b1110010 1
b1100101 2
b100000 3
b1110100 4
b1110011 5
b1110100 6
b11 J
b1101101 M
b1101111 N
b1110010 O
b1100101 P
b100000 Q
b1110100 R
b1110011 S
b1110100 T
#8250000
b1110100 _
b1100101 g
b1110011 o
b1110100 w
b1101001 !"
b1101110 )"
b1100111 1"
b100001 9"
1#
1.
1A
1L
#8500000
#8750000
0#
0.
0A
0L
#9000000
1"
b0 ,
0-
b0 /
b0 0
b0 1
b0 2
b0 3
b0 4
b0 5
b0 6
07
08
09
0:
0;
0<
0=
0>
1@
b0 J
0K
b0 M
b0 N
b0 O
b0 P
b0 Q
b0 R
b0 S
b0 T
0U
0V
0W
0X
0Y
0Z
0[
0\
#9250000
b1101101 `
b1101111 h
b1110010 p
b1100101 x
b100000 ""
b1110100 *"
b1110011 2"
b1110100 :"
1#
1.
1A
1L
#9500000
#9750000
0#
0.
0A
0L
#10000000
b1 !
b1 ?
#10250000
1#
1.
1A
b11111110 B
b11011100 C
b10111010 D
b10011000 E
b1110110 F
b1010100 G
b110010 H
b10000 I
1L
b11111110 $
b11011100 %
b10111010 &
b10011000 '
b1110110 (
b1010100 )
b110010 *
b10000 +
#10500000
#10750000
0#
0.
0A
0L
#11000000
b10 !
b10 ?
#11250000
1#
1.
1A
b10011 B
b1010111 C
b10011011 D
b11011111 E
b10 F
b1000110 G
b10001010 H
b11001110 I
1L
b10011 $
b1010111 %
b10011011 &
b11011111 '
b10 (
b1000110 )
b10001010 *
b11001110 +
#11500000
#11750000
0#
0.
0A
0L
#12000000
b11 !
b11 ?
#12250000
1#
1.
1A
b1110100 B
b1100101 C
b1110011 D
b1110100 E
b1101001 F
b1101110 G
b1100111 H
b100001 I
1L
b1110100 $
b1100101 %
b1110011 &
b1110100 '
b1101001 (
b1101110 )
b1100111 *
b100001 +
#12500000
#12750000
0#
0.
0A
0L
#13000000
b0 !
0"
b0 ?
0@
#13250000
1#
1.
1A
b1101101 B
b1101111 C
b1110010 D
b1100101 E
b100000 F
b1110100 G
b1110011 H
b1110100 I
1L
b1101101 $
b1101111 %
b1110010 &
b1100101 '
b100000 (
b1110100 )
b1110011 *
b1110100 +
#13500000
#13750000
0#
0.
0A
0L
#14000000
#14250000
1#
1.
1A
b0 B
b0 C
b0 D
b0 E
b0 F
b0 G
b0 H
b0 I
1L
b0 $
b0 %
b0 &
b0 '
b0 (
b0 )
b0 *
b0 +
#14500000
#14750000
0#
0.
0A
0L
#15000000

View file

@ -1,810 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 17,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.i",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.o",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.i2",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.o2",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::child.i",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::child.o",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::child.i2",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::child.o2",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::i",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::o",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::i2",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::o2",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: SInt<2>,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:4:1
0: Copy {
dest: StatePartIndex<BigSlots>(6), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.i2", ty: SInt<2> },
src: StatePartIndex<BigSlots>(2), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::o.i2", ty: SInt<2> },
},
1: Copy {
dest: StatePartIndex<BigSlots>(4), // (0xa) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.i", ty: UInt<4> },
src: StatePartIndex<BigSlots>(0), // (0xa) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::o.i", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:2:1
2: Copy {
dest: StatePartIndex<BigSlots>(10), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::i2", ty: SInt<2> },
src: StatePartIndex<BigSlots>(6), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.i2", ty: SInt<2> },
},
3: Copy {
dest: StatePartIndex<BigSlots>(8), // (0xa) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::i", ty: UInt<4> },
src: StatePartIndex<BigSlots>(4), // (0xa) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.i", ty: UInt<4> },
},
// at: module-XXXXXXXXXX-2.rs:1:1
4: Const {
dest: StatePartIndex<BigSlots>(16), // (0xf) SlotDebugData { name: "", ty: UInt<4> },
value: 0xf,
},
5: Const {
dest: StatePartIndex<BigSlots>(14), // (0x5) SlotDebugData { name: "", ty: UInt<4> },
value: 0x5,
},
6: CmpLt {
dest: StatePartIndex<BigSlots>(15), // (0x1) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<BigSlots>(14), // (0x5) SlotDebugData { name: "", ty: UInt<4> },
rhs: StatePartIndex<BigSlots>(8), // (0xa) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::i", ty: UInt<4> },
},
7: CastToUInt {
dest: StatePartIndex<BigSlots>(13), // (0xe) SlotDebugData { name: "", ty: UInt<4> },
src: StatePartIndex<BigSlots>(10), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::i2", ty: SInt<2> },
dest_width: 4,
},
// at: module-XXXXXXXXXX-2.rs:7:1
8: Copy {
dest: StatePartIndex<BigSlots>(11), // (0xf) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::o2", ty: UInt<4> },
src: StatePartIndex<BigSlots>(13), // (0xe) SlotDebugData { name: "", ty: UInt<4> },
},
// at: module-XXXXXXXXXX-2.rs:8:1
9: BranchIfZero {
target: 11,
value: StatePartIndex<BigSlots>(15), // (0x1) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX-2.rs:9:1
10: Copy {
dest: StatePartIndex<BigSlots>(11), // (0xf) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::o2", ty: UInt<4> },
src: StatePartIndex<BigSlots>(16), // (0xf) SlotDebugData { name: "", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:2:1
11: Copy {
dest: StatePartIndex<BigSlots>(7), // (0xf) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.o2", ty: UInt<4> },
src: StatePartIndex<BigSlots>(11), // (0xf) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::o2", ty: UInt<4> },
},
// at: module-XXXXXXXXXX.rs:4:1
12: Copy {
dest: StatePartIndex<BigSlots>(3), // (0xf) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::o.o2", ty: UInt<4> },
src: StatePartIndex<BigSlots>(7), // (0xf) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.o2", ty: UInt<4> },
},
// at: module-XXXXXXXXXX-2.rs:1:1
13: CastToSInt {
dest: StatePartIndex<BigSlots>(12), // (-0x2) SlotDebugData { name: "", ty: SInt<2> },
src: StatePartIndex<BigSlots>(8), // (0xa) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::i", ty: UInt<4> },
dest_width: 2,
},
// at: module-XXXXXXXXXX-2.rs:6:1
14: Copy {
dest: StatePartIndex<BigSlots>(9), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::o", ty: SInt<2> },
src: StatePartIndex<BigSlots>(12), // (-0x2) SlotDebugData { name: "", ty: SInt<2> },
},
// at: module-XXXXXXXXXX.rs:2:1
15: Copy {
dest: StatePartIndex<BigSlots>(5), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.o", ty: SInt<2> },
src: StatePartIndex<BigSlots>(9), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1.child: mod1_child).mod1_child::o", ty: SInt<2> },
},
// at: module-XXXXXXXXXX.rs:4:1
16: Copy {
dest: StatePartIndex<BigSlots>(1), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::o.o", ty: SInt<2> },
src: StatePartIndex<BigSlots>(5), // (-0x2) SlotDebugData { name: "InstantiatedModule(mod1: mod1).mod1::child.o", ty: SInt<2> },
},
// at: module-XXXXXXXXXX.rs:1:1
17: Return,
],
..
},
pc: 17,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [],
},
big_slots: StatePart {
value: [
10,
-2,
-2,
15,
10,
-2,
-2,
15,
10,
-2,
-2,
15,
-2,
14,
5,
1,
15,
],
},
},
io: Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
#[hdl(flip)] /* offset = 0 */
i: UInt<4>,
/* offset = 4 */
o: SInt<2>,
#[hdl(flip)] /* offset = 6 */
i2: SInt<2>,
/* offset = 8 */
o2: UInt<4>,
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 4,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.i",
ty: UInt<4>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.o",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.i2",
ty: SInt<2>,
},
SlotDebugData {
name: "InstantiatedModule(mod1: mod1).mod1::o.o2",
ty: UInt<4>,
},
],
..
},
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(2),
},
ty: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(3),
},
ty: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
},
],
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 4 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.i: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.i2: CompiledValue {
layout: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.o: CompiledValue {
layout: CompiledTypeLayout {
ty: SInt<2>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SInt<2>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::mod1,
instantiated: Module {
name: mod1,
..
},
}.o.o2: CompiledValue {
layout: CompiledTypeLayout {
ty: UInt<4>,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: UInt<4>,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 3, len: 1 },
},
write: None,
},
},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "mod1",
children: [
TraceModuleIO {
name: "o",
child: TraceBundle {
name: "o",
fields: [
TraceUInt {
location: TraceScalarId(0),
name: "i",
ty: UInt<4>,
flow: Source,
},
TraceSInt {
location: TraceScalarId(1),
name: "o",
ty: SInt<2>,
flow: Sink,
},
TraceSInt {
location: TraceScalarId(2),
name: "i2",
ty: SInt<2>,
flow: Source,
},
TraceUInt {
location: TraceScalarId(3),
name: "o2",
ty: UInt<4>,
flow: Sink,
},
],
ty: Bundle {
#[hdl(flip)] /* offset = 0 */
i: UInt<4>,
/* offset = 4 */
o: SInt<2>,
#[hdl(flip)] /* offset = 6 */
i2: SInt<2>,
/* offset = 8 */
o2: UInt<4>,
},
flow: Sink,
},
ty: Bundle {
#[hdl(flip)] /* offset = 0 */
i: UInt<4>,
/* offset = 4 */
o: SInt<2>,
#[hdl(flip)] /* offset = 6 */
i2: SInt<2>,
/* offset = 8 */
o2: UInt<4>,
},
flow: Sink,
},
TraceInstance {
name: "child",
instance_io: TraceBundle {
name: "child",
fields: [
TraceUInt {
location: TraceScalarId(8),
name: "i",
ty: UInt<4>,
flow: Sink,
},
TraceSInt {
location: TraceScalarId(9),
name: "o",
ty: SInt<2>,
flow: Source,
},
TraceSInt {
location: TraceScalarId(10),
name: "i2",
ty: SInt<2>,
flow: Sink,
},
TraceUInt {
location: TraceScalarId(11),
name: "o2",
ty: UInt<4>,
flow: Source,
},
],
ty: Bundle {
#[hdl(flip)] /* offset = 0 */
i: UInt<4>,
/* offset = 4 */
o: SInt<2>,
#[hdl(flip)] /* offset = 6 */
i2: SInt<2>,
/* offset = 8 */
o2: UInt<4>,
},
flow: Source,
},
module: TraceModule {
name: "mod1_child",
children: [
TraceModuleIO {
name: "i",
child: TraceUInt {
location: TraceScalarId(4),
name: "i",
ty: UInt<4>,
flow: Source,
},
ty: UInt<4>,
flow: Source,
},
TraceModuleIO {
name: "o",
child: TraceSInt {
location: TraceScalarId(5),
name: "o",
ty: SInt<2>,
flow: Sink,
},
ty: SInt<2>,
flow: Sink,
},
TraceModuleIO {
name: "i2",
child: TraceSInt {
location: TraceScalarId(6),
name: "i2",
ty: SInt<2>,
flow: Source,
},
ty: SInt<2>,
flow: Source,
},
TraceModuleIO {
name: "o2",
child: TraceUInt {
location: TraceScalarId(7),
name: "o2",
ty: UInt<4>,
flow: Sink,
},
ty: UInt<4>,
flow: Sink,
},
],
},
ty: Bundle {
#[hdl(flip)] /* offset = 0 */
i: UInt<4>,
/* offset = 4 */
o: SInt<2>,
#[hdl(flip)] /* offset = 6 */
i2: SInt<2>,
/* offset = 8 */
o2: UInt<4>,
},
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigUInt {
index: StatePartIndex<BigSlots>(0),
ty: UInt<4>,
},
state: 0xa,
last_state: 0x3,
},
SimTrace {
id: TraceScalarId(1),
kind: BigSInt {
index: StatePartIndex<BigSlots>(1),
ty: SInt<2>,
},
state: 0x2,
last_state: 0x3,
},
SimTrace {
id: TraceScalarId(2),
kind: BigSInt {
index: StatePartIndex<BigSlots>(2),
ty: SInt<2>,
},
state: 0x2,
last_state: 0x2,
},
SimTrace {
id: TraceScalarId(3),
kind: BigUInt {
index: StatePartIndex<BigSlots>(3),
ty: UInt<4>,
},
state: 0xf,
last_state: 0xe,
},
SimTrace {
id: TraceScalarId(4),
kind: BigUInt {
index: StatePartIndex<BigSlots>(8),
ty: UInt<4>,
},
state: 0xa,
last_state: 0x3,
},
SimTrace {
id: TraceScalarId(5),
kind: BigSInt {
index: StatePartIndex<BigSlots>(9),
ty: SInt<2>,
},
state: 0x2,
last_state: 0x3,
},
SimTrace {
id: TraceScalarId(6),
kind: BigSInt {
index: StatePartIndex<BigSlots>(10),
ty: SInt<2>,
},
state: 0x2,
last_state: 0x2,
},
SimTrace {
id: TraceScalarId(7),
kind: BigUInt {
index: StatePartIndex<BigSlots>(11),
ty: UInt<4>,
},
state: 0xf,
last_state: 0xe,
},
SimTrace {
id: TraceScalarId(8),
kind: BigUInt {
index: StatePartIndex<BigSlots>(4),
ty: UInt<4>,
},
state: 0xa,
last_state: 0x3,
},
SimTrace {
id: TraceScalarId(9),
kind: BigSInt {
index: StatePartIndex<BigSlots>(5),
ty: SInt<2>,
},
state: 0x2,
last_state: 0x3,
},
SimTrace {
id: TraceScalarId(10),
kind: BigSInt {
index: StatePartIndex<BigSlots>(6),
ty: SInt<2>,
},
state: 0x2,
last_state: 0x2,
},
SimTrace {
id: TraceScalarId(11),
kind: BigUInt {
index: StatePartIndex<BigSlots>(7),
ty: UInt<4>,
},
state: 0xf,
last_state: 0xe,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 2 μs,
clocks_triggered: [],
..
}

View file

@ -1,47 +0,0 @@
$timescale 1 ps $end
$scope module mod1 $end
$scope struct o $end
$var wire 4 ! i $end
$var wire 2 " o $end
$var wire 2 # i2 $end
$var wire 4 $ o2 $end
$upscope $end
$scope struct child $end
$var wire 4 ) i $end
$var wire 2 * o $end
$var wire 2 + i2 $end
$var wire 4 , 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
$enddefinitions $end
$dumpvars
b11 !
b11 "
b10 #
b1110 $
b11 %
b11 &
b10 '
b1110 (
b11 )
b11 *
b10 +
b1110 ,
$end
#1000000
b1010 !
b10 "
b1111 $
b1010 %
b10 &
b1111 (
b1010 )
b10 *
b1111 ,
#2000000

View file

@ -1,683 +0,0 @@
Simulation {
state: State {
insns: Insns {
state_layout: StateLayout {
ty: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 4,
debug_data: [
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 13,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.rst",
ty: SyncReset,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::d",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::q",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg0",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg0$next",
ty: Bool,
},
SlotDebugData {
name: "",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg1",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg1$next",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg2",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg2$next",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg3",
ty: Bool,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::reg3$next",
ty: Bool,
},
],
..
},
},
memories: StatePartLayout<Memories> {
len: 0,
debug_data: [],
layout_data: [],
..
},
},
insns: [
// at: module-XXXXXXXXXX.rs:13:1
0: Copy {
dest: StatePartIndex<BigSlots>(3), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::q", ty: Bool },
src: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg3", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:12:1
1: Copy {
dest: StatePartIndex<BigSlots>(12), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg3$next", ty: Bool },
src: StatePartIndex<BigSlots>(9), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg2", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:10:1
2: Copy {
dest: StatePartIndex<BigSlots>(10), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg2$next", ty: Bool },
src: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg1", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:8:1
3: Copy {
dest: StatePartIndex<BigSlots>(8), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg1$next", ty: Bool },
src: StatePartIndex<BigSlots>(4), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg0", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:6:1
4: Copy {
dest: StatePartIndex<BigSlots>(5), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg0$next", ty: Bool },
src: StatePartIndex<BigSlots>(2), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::d", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:5:1
5: IsNonZeroDestIsSmall {
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.rst", ty: SyncReset },
},
// at: module-XXXXXXXXXX.rs:1:1
6: Const {
dest: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
value: 0x0,
},
// at: module-XXXXXXXXXX.rs:5:1
7: IsNonZeroDestIsSmall {
dest: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.clk", ty: Clock },
},
8: AndSmall {
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
9: BranchIfSmallZero {
target: 14,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
10: BranchIfSmallNonZero {
target: 13,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
11: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg0", ty: Bool },
src: StatePartIndex<BigSlots>(5), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg0$next", ty: Bool },
},
12: Branch {
target: 14,
},
13: Copy {
dest: StatePartIndex<BigSlots>(4), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg0", ty: Bool },
src: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:7:1
14: BranchIfSmallZero {
target: 19,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
15: BranchIfSmallNonZero {
target: 18,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
16: Copy {
dest: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg1", ty: Bool },
src: StatePartIndex<BigSlots>(8), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg1$next", ty: Bool },
},
17: Branch {
target: 19,
},
18: Copy {
dest: StatePartIndex<BigSlots>(7), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg1", ty: Bool },
src: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:9:1
19: BranchIfSmallZero {
target: 24,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
20: BranchIfSmallNonZero {
target: 23,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
21: Copy {
dest: StatePartIndex<BigSlots>(9), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg2", ty: Bool },
src: StatePartIndex<BigSlots>(10), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg2$next", ty: Bool },
},
22: Branch {
target: 24,
},
23: Copy {
dest: StatePartIndex<BigSlots>(9), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg2", ty: Bool },
src: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:11:1
24: BranchIfSmallZero {
target: 29,
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
25: BranchIfSmallNonZero {
target: 28,
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
},
26: Copy {
dest: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg3", ty: Bool },
src: StatePartIndex<BigSlots>(12), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg3$next", ty: Bool },
},
27: Branch {
target: 29,
},
28: Copy {
dest: StatePartIndex<BigSlots>(11), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::reg3", ty: Bool },
src: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
},
// at: module-XXXXXXXXXX.rs:5:1
29: XorSmallImmediate {
dest: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
rhs: 0x1,
},
// at: module-XXXXXXXXXX.rs:1:1
30: Return,
],
..
},
pc: 30,
memory_write_log: [],
memories: StatePart {
value: [],
},
small_slots: StatePart {
value: [
0,
0,
1,
0,
],
},
big_slots: StatePart {
value: [
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
},
},
io: Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
},
uninitialized_inputs: {},
io_targets: {
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd: CompiledValue {
layout: CompiledTypeLayout {
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
},
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 2,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.clk",
ty: Clock,
},
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.rst",
ty: SyncReset,
},
],
..
},
},
body: Bundle {
fields: [
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(0),
},
ty: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
},
CompiledBundleField {
offset: TypeIndex {
small_slots: StatePartIndex<SmallSlots>(0),
big_slots: StatePartIndex<BigSlots>(1),
},
ty: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
},
],
},
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 2 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd.clk: CompiledValue {
layout: CompiledTypeLayout {
ty: Clock,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: Clock,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 0, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.cd.rst: CompiledValue {
layout: CompiledTypeLayout {
ty: SyncReset,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "",
ty: SyncReset,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.d: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::d",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 2, len: 1 },
},
write: None,
},
Instance {
name: <simulator>::shift_register,
instantiated: Module {
name: shift_register,
..
},
}.q: CompiledValue {
layout: CompiledTypeLayout {
ty: Bool,
layout: TypeLayout {
small_slots: StatePartLayout<SmallSlots> {
len: 0,
debug_data: [],
..
},
big_slots: StatePartLayout<BigSlots> {
len: 1,
debug_data: [
SlotDebugData {
name: "InstantiatedModule(shift_register: shift_register).shift_register::q",
ty: Bool,
},
],
..
},
},
body: Scalar,
},
range: TypeIndexRange {
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
big_slots: StatePartIndexRange<BigSlots> { start: 3, len: 1 },
},
write: None,
},
},
made_initial_step: true,
needs_settle: false,
trace_decls: TraceModule {
name: "shift_register",
children: [
TraceModuleIO {
name: "cd",
child: TraceBundle {
name: "cd",
fields: [
TraceClock {
location: TraceScalarId(0),
name: "clk",
flow: Source,
},
TraceSyncReset {
location: TraceScalarId(1),
name: "rst",
flow: Source,
},
],
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
},
flow: Source,
},
ty: Bundle {
/* offset = 0 */
clk: Clock,
/* offset = 1 */
rst: SyncReset,
},
flow: Source,
},
TraceModuleIO {
name: "d",
child: TraceBool {
location: TraceScalarId(2),
name: "d",
flow: Source,
},
ty: Bool,
flow: Source,
},
TraceModuleIO {
name: "q",
child: TraceBool {
location: TraceScalarId(3),
name: "q",
flow: Sink,
},
ty: Bool,
flow: Sink,
},
TraceReg {
name: "reg0",
child: TraceBool {
location: TraceScalarId(4),
name: "reg0",
flow: Duplex,
},
ty: Bool,
},
TraceReg {
name: "reg1",
child: TraceBool {
location: TraceScalarId(5),
name: "reg1",
flow: Duplex,
},
ty: Bool,
},
TraceReg {
name: "reg2",
child: TraceBool {
location: TraceScalarId(6),
name: "reg2",
flow: Duplex,
},
ty: Bool,
},
TraceReg {
name: "reg3",
child: TraceBool {
location: TraceScalarId(7),
name: "reg3",
flow: Duplex,
},
ty: Bool,
},
],
},
traces: [
SimTrace {
id: TraceScalarId(0),
kind: BigClock {
index: StatePartIndex<BigSlots>(0),
},
state: 0x1,
last_state: 0x1,
},
SimTrace {
id: TraceScalarId(1),
kind: BigSyncReset {
index: StatePartIndex<BigSlots>(1),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(2),
kind: BigBool {
index: StatePartIndex<BigSlots>(2),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(3),
kind: BigBool {
index: StatePartIndex<BigSlots>(3),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(4),
kind: BigBool {
index: StatePartIndex<BigSlots>(4),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(5),
kind: BigBool {
index: StatePartIndex<BigSlots>(7),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(6),
kind: BigBool {
index: StatePartIndex<BigSlots>(9),
},
state: 0x0,
last_state: 0x0,
},
SimTrace {
id: TraceScalarId(7),
kind: BigBool {
index: StatePartIndex<BigSlots>(11),
},
state: 0x0,
last_state: 0x0,
},
],
trace_memories: {},
trace_writers: [
Running(
VcdWriter {
finished_init: true,
timescale: 1 ps,
..
},
),
],
instant: 66 μs,
clocks_triggered: [
StatePartIndex<SmallSlots>(1),
],
..
}

View file

@ -1,193 +0,0 @@
$timescale 1 ps $end
$scope module shift_register $end
$scope struct cd $end
$var wire 1 ! clk $end
$var wire 1 " rst $end
$upscope $end
$var wire 1 # d $end
$var wire 1 $ q $end
$var reg 1 % reg0 $end
$var reg 1 & reg1 $end
$var reg 1 ' reg2 $end
$var reg 1 ( reg3 $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
1"
0#
0$
0%
0&
0'
0(
$end
#1000000
1!
#1100000
0"
#2000000
0!
#3000000
1!
#4000000
0!
1#
#5000000
1!
1%
#6000000
0!
#7000000
1!
1&
#8000000
0!
0#
#9000000
1!
0%
1'
#10000000
0!
#11000000
1!
0&
1(
1$
#12000000
0!
1#
#13000000
1!
1%
0'
#14000000
0!
0#
#15000000
1!
0%
1&
0(
0$
#16000000
0!
1#
#17000000
1!
1%
0&
1'
#18000000
0!
#19000000
1!
1&
0'
1(
1$
#20000000
0!
#21000000
1!
1'
0(
0$
#22000000
0!
#23000000
1!
1(
1$
#24000000
0!
0#
#25000000
1!
0%
#26000000
0!
#27000000
1!
0&
#28000000
0!
#29000000
1!
0'
#30000000
0!
#31000000
1!
0(
0$
#32000000
0!
#33000000
1!
#34000000
0!
#35000000
1!
#36000000
0!
#37000000
1!
#38000000
0!
#39000000
1!
#40000000
0!
#41000000
1!
#42000000
0!
#43000000
1!
#44000000
0!
#45000000
1!
#46000000
0!
#47000000
1!
#48000000
0!
#49000000
1!
#50000000
0!
#51000000
1!
#52000000
0!
#53000000
1!
#54000000
0!
#55000000
1!
#56000000
0!
#57000000
1!
#58000000
0!
#59000000
1!
#60000000
0!
#61000000
1!
#62000000
0!
#63000000
1!
#64000000
0!
#65000000
1!
#66000000

View file

@ -1047,9 +1047,9 @@
"clock_domain()": "Visible", "clock_domain()": "Visible",
"init()": "Visible" "init()": "Visible"
}, },
"generics": "<T: Type, R: ResetType>", "generics": "<T: Type>",
"fold_where": "T: Fold<State>, R: Fold<State>", "fold_where": "T: Fold<State>",
"visit_where": "T: Visit<State>, R: Visit<State>" "visit_where": "T: Visit<State>"
}, },
"Wire": { "Wire": {
"data": { "data": {
@ -1078,8 +1078,6 @@
"$kind": "Enum", "$kind": "Enum",
"Wire": "Visible", "Wire": "Visible",
"Reg": "Visible", "Reg": "Visible",
"RegSync": "Visible",
"RegAsync": "Visible",
"Instance": "Visible" "Instance": "Visible"
} }
}, },
@ -1138,10 +1136,7 @@
"$kind": "Struct", "$kind": "Struct",
"annotations": "Visible", "annotations": "Visible",
"reg": "Visible" "reg": "Visible"
}, }
"generics": "<R: ResetType>",
"fold_where": "R: Fold<State>",
"visit_where": "R: Visit<State>"
}, },
"StmtWire": { "StmtWire": {
"data": { "data": {
@ -1224,8 +1219,6 @@
"ModuleIO": "Visible", "ModuleIO": "Visible",
"MemPort": "Visible", "MemPort": "Visible",
"Reg": "Visible", "Reg": "Visible",
"RegSync": "Visible",
"RegAsync": "Visible",
"Wire": "Visible", "Wire": "Visible",
"Instance": "Visible" "Instance": "Visible"
} }

View file

@ -46,7 +46,7 @@ function main()
*/LICENSE.md|*/Notices.txt) */LICENSE.md|*/Notices.txt)
# copyright file # copyright file
;; ;;
/crates/fayalite/tests/ui/*.stderr|/crates/fayalite/tests/sim/expected/*.vcd|/crates/fayalite/tests/sim/expected/*.txt) /crates/fayalite/tests/ui/*.stderr)
# file that can't contain copyright header # file that can't contain copyright header
;; ;;
/.forgejo/workflows/*.yml|*/.gitignore|*.toml) /.forgejo/workflows/*.yml|*/.gitignore|*.toml)