From 7516ec3c24405e07640db4da52ece6f40acb2bec Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 1 May 2026 18:34:49 -0700 Subject: [PATCH] implement #[hdl(cmp_eq)] for enums --- .../src/hdl_bundle.rs | 2 +- .../fayalite-proc-macros-impl/src/hdl_enum.rs | 173 ++++++++- crates/fayalite/tests/module.rs | 362 +++++++++++++++++- 3 files changed, 530 insertions(+), 7 deletions(-) diff --git a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs index 6847af9..f7ad68d 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs @@ -1223,7 +1223,7 @@ impl ToTokens for ParsedBundle { valueless_eq_body = quote_spanned! {span=> let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); let __rhs = ::fayalite::expr::ValueType::ty(&__rhs); - #(#fields_valueless_eq)|* + #(#fields_valueless_eq)&* }; valueless_ne_body = quote_spanned! {span=> let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); diff --git a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs index e2410bc..e9f013b 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs @@ -159,14 +159,11 @@ impl ParsedEnum { custom_bounds, no_static: _, no_runtime_generics: _, - cmp_eq, + cmp_eq: _, ref get, custom_debug: _, custom_sim_display: _, } = options.body; - if let Some((cmp_eq,)) = cmp_eq { - errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for enums"); - } if let Some((get, ..)) = get { errors.error(get, "#[hdl(get(...))] is not allowed on enums"); } @@ -249,7 +246,7 @@ impl ToTokens for ParsedEnum { custom_bounds: _, no_static, no_runtime_generics, - cmp_eq: _, // TODO: implement cmp_eq for enums + cmp_eq, get: _, custom_debug: _, custom_sim_display, @@ -938,6 +935,172 @@ impl ToTokens for ParsedEnum { } }.to_tokens(tokens); } + if let Some((cmp_eq,)) = cmp_eq { + let mut cmp_eq_where_clause = + Generics::from(generics) + .where_clause + .unwrap_or_else(|| syn::WhereClause { + where_token: Token![where](span), + predicates: Punctuated::new(), + }); + let mut variants_value_eq = vec![]; + let mut variants_expr_eq = vec![]; + let mut fields_valueless_eq = vec![]; + for ( + variant_index, + ParsedVariant { + attrs: _, + options: variant_options, + ident: variant_ident, + field, + }, + ) in variants.iter().enumerate() + { + let VariantOptions {} = variant_options.body; + if let Some(ParsedVariantField { + paren_token: _, + attrs: _, + options: field_options, + ty: field_ty, + comma_token: _, + }) = field + { + let FieldOptions {} = field_options.body; + cmp_eq_where_clause + .predicates + .push(parse_quote_spanned! {cmp_eq.span=> + #field_ty: ::fayalite::expr::HdlPartialEqImpl<#field_ty> + }); + variants_value_eq.push(quote_spanned! {span=> + (#sim_value_ident::#variant_ident(__lhs_field, _), #sim_value_ident::#variant_ident(__rhs_field, _)) => { + ::fayalite::expr::HdlPartialEqImpl::cmp_value_eq( + __lhs.#variant_ident, + ::fayalite::__std::borrow::Cow::Borrowed(__lhs_field), + __rhs.#variant_ident, + ::fayalite::__std::borrow::Cow::Borrowed(__rhs_field), + ) + } + }); + variants_expr_eq.push(quote_spanned! {span=> + { + let (#match_variant_ident::#variant_ident(__lhs), __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter) + .expect("known to have enough variants"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + let (#match_variant_ident::#variant_ident(__rhs), __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::nth( + &mut ::fayalite::module::match_(__rhs), + #variant_index, + ) + .expect("known to have variant"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + ::fayalite::module::connect(__retval, ::fayalite::expr::HdlPartialEqImpl::cmp_expr_eq(__lhs, __rhs)); + } + }); + fields_valueless_eq.push(quote_spanned! {span=> + ::fayalite::expr::HdlPartialEqImpl::cmp_valueless_eq( + ::fayalite::expr::Valueless::new(__lhs.#variant_ident), + ::fayalite::expr::Valueless::new(__rhs.#variant_ident), + ) + }); + } else { + variants_value_eq.push(quote_spanned! {span=> + (#sim_value_ident::#variant_ident(_), #sim_value_ident::#variant_ident(_)) => true, + }); + variants_expr_eq.push(quote_spanned! {span=> + { + let (#match_variant_ident::#variant_ident, __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter) + .expect("known to have enough variants"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + let (#match_variant_ident::#variant_ident, __scope) = + ::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope( + ::fayalite::__std::iter::Iterator::nth( + &mut ::fayalite::module::match_(__rhs), + #variant_index, + ) + .expect("known to have variant"), + ) + else { + ::fayalite::__std::unreachable!(); + }; + ::fayalite::module::connect(__retval, true); + } + }); + } + } + if let Some(sim_value_unknown_variant_name) = &sim_value_unknown_variant_name { + variants_value_eq.push(quote_spanned! {span=> + (#sim_value_ident::#sim_value_unknown_variant_name(__lhs_unknown), #sim_value_ident::#sim_value_unknown_variant_name(__rhs_unknown)) => { + __lhs_unknown == __rhs_unknown + } + }); + } + let valueless_eq_body = if fields_valueless_eq.is_empty() { + quote_spanned! {span=> + ::fayalite::expr::Valueless::new(::fayalite::int::Bool) + } + } else { + quote_spanned! {span=> + let __lhs = ::fayalite::expr::ValueType::ty(&__lhs); + let __rhs = ::fayalite::expr::ValueType::ty(&__rhs); + #(#fields_valueless_eq)&* + } + }; + let cmp_expr_eq_wire_name = format!("{ident}_cmp_eq"); + quote_spanned! {span=> + #[automatically_derived] + impl #impl_generics ::fayalite::expr::HdlPartialEqImpl for #target #type_generics + #cmp_eq_where_clause + { + #[track_caller] + fn cmp_value_eq( + __lhs: Self, + __lhs_value: ::fayalite::__std::borrow::Cow<'_, ::SimValue>, + __rhs: Self, + __rhs_value: ::fayalite::__std::borrow::Cow<'_, ::SimValue>, + ) -> ::fayalite::__std::primitive::bool { + match (&*__lhs_value, &*__rhs_value) { + #(#variants_value_eq)* + _ => false, + } + } + + #[track_caller] + fn cmp_expr_eq( + __lhs: ::fayalite::expr::Expr, + __rhs: ::fayalite::expr::Expr, + ) -> ::fayalite::expr::Expr<::fayalite::int::Bool> { + let __retval = ::fayalite::module::wire(::fayalite::module::ImplicitName(#cmp_expr_eq_wire_name), ::fayalite::int::Bool); + ::fayalite::module::connect(__retval, false); + let mut __lhs_match_variant_iter = ::fayalite::module::match_(__lhs); + #(#variants_expr_eq)* + __retval + } + + #[track_caller] + fn cmp_valueless_eq( + __lhs: ::fayalite::expr::Valueless, + __rhs: ::fayalite::expr::Valueless, + ) -> ::fayalite::expr::Valueless<::fayalite::int::Bool> { + #valueless_eq_body + } + } + } + .to_tokens(tokens); + } let variants_len = variants.len(); quote_spanned! {span=> #[automatically_derived] diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index 2761cba..9dc0107 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -13,7 +13,7 @@ use fayalite::{ }; use serde_json::json; -#[hdl(outline_generated)] +#[hdl(outline_generated, cmp_eq)] pub enum TestEnum { A, B(UInt<8>), @@ -679,6 +679,366 @@ circuit check_enum_literals: }; } +#[hdl_module(outline_generated)] +pub fn check_enum_cmp_eq() { + #[hdl] + let lhs: TestEnum = m.input(); + #[hdl] + let rhs: TestEnum = m.input(); + #[hdl] + let eq: Bool = m.output(); + connect(eq, lhs.cmp_eq(rhs)); +} + +#[test] +fn test_enum_cmp_eq() { + let _n = SourceLocation::normalize_files_for_tests(); + let m = check_enum_cmp_eq(); + dbg!(m); + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: None, + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + type Ty0 = {|A, B: UInt<8>, C: UInt<1>[3]|} + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: Ty0 @[module-XXXXXXXXXX.rs 2:1] + input rhs: Ty0 @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + match lhs: @[module-XXXXXXXXXX.rs 5:1] + A: + match rhs: @[module-XXXXXXXXXX.rs 5:1] + A: + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + B(_match_arm_value): + skip + C(_match_arm_value_1): + skip + B(_match_arm_value_2): + match rhs: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B(_match_arm_value_3): + connect TestEnum_cmp_eq, eq(_match_arm_value_2, _match_arm_value_3) @[module-XXXXXXXXXX.rs 5:1] + C(_match_arm_value_4): + skip + C(_match_arm_value_5): + match rhs: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B(_match_arm_value_6): + skip + C(_match_arm_value_7): + wire _array_literal_expr: UInt<1>[3] + connect _array_literal_expr[0], eq(_match_arm_value_5[0], _match_arm_value_7[0]) + connect _array_literal_expr[1], eq(_match_arm_value_5[1], _match_arm_value_7[1]) + connect _array_literal_expr[2], eq(_match_arm_value_5[2], _match_arm_value_7[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: Some(SimplifyEnumsKind::SimplifyToEnumsWithNoBody), + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + type Ty0 = {|A, B, C|} + type Ty1 = {tag: Ty0, body: UInt<8>} + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: Ty1 @[module-XXXXXXXXXX.rs 2:1] + input rhs: Ty1 @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + match lhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + match rhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + B: + skip + C: + skip + B: + match rhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B: + connect TestEnum_cmp_eq, eq(bits(lhs.body, 7, 0), bits(rhs.body, 7, 0)) @[module-XXXXXXXXXX.rs 5:1] + C: + skip + C: + match rhs.tag: @[module-XXXXXXXXXX.rs 5:1] + A: + skip + B: + skip + C: + wire _array_literal_expr: UInt<1>[3] + wire _cast_bits_to_array_expr: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0] + connect _cast_bits_to_array_expr_flattened[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1] + connect _cast_bits_to_array_expr_flattened[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2] + wire _cast_bits_to_array_expr_1: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0] + connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1] + connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] + connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) + wire _cast_bits_to_array_expr_2: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] + connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] + connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] + wire _cast_bits_to_array_expr_3: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] + connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] + connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) + wire _cast_bits_to_array_expr_4: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] + connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] + connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] + wire _cast_bits_to_array_expr_5: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] + connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] + connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts), + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + type Ty0 = {tag: UInt<2>, body: UInt<8>} + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: Ty0 @[module-XXXXXXXXXX.rs 2:1] + input rhs: Ty0 @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + when eq(lhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(lhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, eq(bits(lhs.body, 7, 0), bits(rhs.body, 7, 0)) @[module-XXXXXXXXXX.rs 5:1] + else when eq(rhs.tag, UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(rhs.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else: + wire _array_literal_expr: UInt<1>[3] + wire _cast_bits_to_array_expr: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0] + connect _cast_bits_to_array_expr_flattened[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1] + connect _cast_bits_to_array_expr_flattened[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2] + wire _cast_bits_to_array_expr_1: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0] + connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1] + connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] + connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) + wire _cast_bits_to_array_expr_2: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] + connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] + connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] + wire _cast_bits_to_array_expr_3: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] + connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] + connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) + wire _cast_bits_to_array_expr_4: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] + connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] + connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] + wire _cast_bits_to_array_expr_5: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0) + connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] + connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1) + connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] + connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2) + connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; + #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161 + assert_export_firrtl! { + m => + options: ExportOptions { + simplify_enums: Some(SimplifyEnumsKind::ReplaceWithUInt), + ..ExportOptions::default() + }, + "/test/check_enum_cmp_eq.fir": r"FIRRTL version 3.2.0 +circuit check_enum_cmp_eq: + module check_enum_cmp_eq: @[module-XXXXXXXXXX.rs 1:1] + input lhs: UInt<10> @[module-XXXXXXXXXX.rs 2:1] + input rhs: UInt<10> @[module-XXXXXXXXXX.rs 3:1] + output eq: UInt<1> @[module-XXXXXXXXXX.rs 4:1] + wire TestEnum_cmp_eq: UInt<1> @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h0) @[module-XXXXXXXXXX.rs 5:1] + when eq(bits(lhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, UInt<1>(0h1) @[module-XXXXXXXXXX.rs 5:1] + else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(bits(lhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + connect TestEnum_cmp_eq, eq(bits(bits(lhs, 9, 2), 7, 0), bits(bits(rhs, 9, 2), 7, 0)) @[module-XXXXXXXXXX.rs 5:1] + else when eq(bits(rhs, 1, 0), UInt<2>(0h0)): @[module-XXXXXXXXXX.rs 5:1] + skip + else when eq(bits(rhs, 1, 0), UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 5:1] + skip + else: + wire _array_literal_expr: UInt<1>[3] + wire _cast_bits_to_array_expr: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr[0], _cast_bits_to_array_expr_flattened[0] + connect _cast_bits_to_array_expr_flattened[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr[1], _cast_bits_to_array_expr_flattened[1] + connect _cast_bits_to_array_expr_flattened[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr[2], _cast_bits_to_array_expr_flattened[2] + wire _cast_bits_to_array_expr_1: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_1: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_1[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_1[0], _cast_bits_to_array_expr_flattened_1[0] + connect _cast_bits_to_array_expr_flattened_1[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_1[1], _cast_bits_to_array_expr_flattened_1[1] + connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2] + connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0]) + wire _cast_bits_to_array_expr_2: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0] + connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1] + connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2] + wire _cast_bits_to_array_expr_3: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0] + connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1] + connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2] + connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1]) + wire _cast_bits_to_array_expr_4: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0] + connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1] + connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2] + wire _cast_bits_to_array_expr_5: UInt<1>[3] + wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3] + connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0) + connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0] + connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1) + connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1] + connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2) + connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2] + connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2]) + wire _cast_array_to_bits_expr: UInt<1>[3] + connect _cast_array_to_bits_expr[0], _array_literal_expr[0] + connect _cast_array_to_bits_expr[1], _array_literal_expr[1] + connect _cast_array_to_bits_expr[2], _array_literal_expr[2] + wire _cast_to_bits_expr: UInt<3> + connect _cast_to_bits_expr, cat(_cast_array_to_bits_expr[2], cat(_cast_array_to_bits_expr[1], _cast_array_to_bits_expr[0])) + connect TestEnum_cmp_eq, andr(_cast_to_bits_expr) @[module-XXXXXXXXXX.rs 5:1] + connect eq, TestEnum_cmp_eq @[module-XXXXXXXXXX.rs 6:1] +", + }; +} + #[hdl_module(outline_generated)] pub fn check_struct_enum_match() { #[hdl]