Compare commits

...

2 commits

Author SHA1 Message Date
Jacob Lifshay 6446b71afd
deduce_resets works!
All checks were successful
/ deps (push) Successful in 18s
/ test (push) Successful in 4m56s
/ deps (pull_request) Successful in 13s
/ test (pull_request) Successful in 5m0s
2024-11-27 23:24:11 -08:00
Jacob Lifshay d36cf92d7f
make ToReset generic over the reset type 2024-11-27 23:19:55 -08:00
4 changed files with 1023 additions and 159 deletions

View file

@ -19,7 +19,10 @@ use crate::{
UIntType, UIntValue,
},
intern::{Intern, Interned},
reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset},
reset::{
AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset, ToAsyncReset, ToReset,
ToSyncReset,
},
ty::{CanonicalType, StaticType, Type},
util::ConstUsize,
};
@ -1773,11 +1776,11 @@ impl_cast_bit_op!(CastSIntToAsyncReset, SInt<1>, #[dyn] SInt, AsyncReset, #[trai
impl_cast_bit_op!(CastSyncResetToBool, SyncReset, Bool);
impl_cast_bit_op!(CastSyncResetToUInt, SyncReset, UInt<1>, #[dyn] UInt);
impl_cast_bit_op!(CastSyncResetToSInt, SyncReset, SInt<1>, #[dyn] SInt);
impl_cast_bit_op!(CastSyncResetToReset, SyncReset, Reset, #[trait] ToReset::to_reset);
impl_cast_bit_op!(CastSyncResetToReset, SyncReset, Reset);
impl_cast_bit_op!(CastAsyncResetToBool, AsyncReset, Bool);
impl_cast_bit_op!(CastAsyncResetToUInt, AsyncReset, UInt<1>, #[dyn] UInt);
impl_cast_bit_op!(CastAsyncResetToSInt, AsyncReset, SInt<1>, #[dyn] SInt);
impl_cast_bit_op!(CastAsyncResetToReset, AsyncReset, Reset, #[trait] ToReset::to_reset);
impl_cast_bit_op!(CastAsyncResetToReset, AsyncReset, Reset);
impl_cast_bit_op!(CastResetToBool, Reset, Bool);
impl_cast_bit_op!(CastResetToUInt, Reset, UInt<1>, #[dyn] UInt);
impl_cast_bit_op!(CastResetToSInt, Reset, SInt<1>, #[dyn] SInt);
@ -1788,6 +1791,29 @@ impl_cast_bit_op!(CastClockToBool, Clock, Bool);
impl_cast_bit_op!(CastClockToUInt, Clock, UInt<1>, #[dyn] UInt);
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

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ pub trait ResetTypeDispatch: Sized {
}
macro_rules! reset_type {
($name:ident, $Trait:ident::$trait_fn:ident, $is_castable_from_bits:literal, $dispatch_fn:ident) => {
($name:ident, $(#[$impl_trait:ident])? $Trait:ident::$trait_fn:ident, $is_castable_from_bits:literal, $dispatch_fn:ident) => {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct $name;
@ -109,16 +109,16 @@ macro_rules! reset_type {
}
}
impl $Trait for Expr<$name> {
$($impl_trait $Trait for Expr<$name> {
fn $trait_fn(&self) -> Expr<$name> {
*self
}
}
})?
};
}
reset_type!(AsyncReset, ToAsyncReset::to_async_reset, true, async_reset);
reset_type!(SyncReset, ToSyncReset::to_sync_reset, true, sync_reset);
reset_type!(AsyncReset, #[impl] ToAsyncReset::to_async_reset, true, async_reset);
reset_type!(SyncReset, #[impl] ToSyncReset::to_sync_reset, true, sync_reset);
reset_type!(
Reset,
ToReset::to_reset,

View file

@ -2,7 +2,8 @@
// See Notices.txt for copyright information
use fayalite::{
assert_export_firrtl, firrtl::ExportOptions, intern::Intern,
module::transform::simplify_enums::SimplifyEnumsKind, prelude::*, ty::StaticType,
module::transform::simplify_enums::SimplifyEnumsKind, prelude::*, reset::ResetType,
ty::StaticType,
};
use serde_json::json;
@ -4026,3 +4027,263 @@ 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]
",
};
}