working on deduce_resets
All checks were successful
/ deps (push) Successful in 16s
/ test (push) Successful in 4m57s
/ deps (pull_request) Successful in 13s
/ test (pull_request) Successful in 5m3s

This commit is contained in:
Jacob Lifshay 2024-11-27 01:31:18 -08:00
parent 358cdd10c8
commit d744d85c66
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ

View file

@ -8,6 +8,7 @@ use crate::{
bundle::{BundleField, BundleType},
enum_::{EnumType, EnumVariant},
expr::{
ops,
target::{
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
TargetPathDynArrayElement, TargetPathElement,
@ -25,14 +26,8 @@ use crate::{
reset::{ResetType, ResetTypeDispatch},
};
use hashbrown::{hash_map::Entry, HashMap};
use hashbrown::{hash_map::Entry, HashMap};
use num_bigint::BigInt;
use num_bigint::BigInt;
use petgraph::unionfind::UnionFind;
use petgraph::{
graph::{NodeIndex, UnGraph},
unionfind::UnionFind,
};
use std::{
borrow::Borrow,
fmt,
@ -921,6 +916,94 @@ fn reg_expr_run_pass<P: Pass, R: ResetType>(
.map(|reg| match_any_reg!(reg, ExprEnum::from)))
}
fn cast_bit_op<P: Pass, T: Type, A: Type>(
expr: impl ToExpr<Type = T>,
arg: Expr<A>,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<ExprEnum, P>, DeduceResetsError> {
struct Dispatch<'a, T: Type, A: Type> {
expr: Expr<T>,
arg: Expr<A>,
_phantom: PhantomData<&'a mut ()>,
}
impl<'a, T: Type, A: Type> PassDispatch for Dispatch<'a, T, A> {
type Input<P: Pass> = PassArgs<'a, P>;
type Output<P: Pass> = Result<PassOutput<ExprEnum, P>, DeduceResetsError>;
fn build_reset_graph(
self,
mut pass_args: Self::Input<BuildResetGraph>,
) -> Self::Output<BuildResetGraph> {
Expr::canonical(self.arg).run_pass(pass_args.as_mut())?;
let (expr_resets, _) = pass_args.get_or_make_resets(self.expr, None);
let (arg_resets, _) = pass_args.get_or_make_resets(self.arg, None);
for (expr_node_index, arg_node_index) in expr_resets
.node_indexes
.into_iter()
.zip(arg_resets.node_indexes)
{
pass_args.state.reset_graph.union(
expr_node_index,
arg_node_index,
pass_args.fallback_error_source_location,
)?;
}
Ok(PassOutput(()))
}
fn substitute_resets(
self,
mut pass_args: Self::Input<SubstituteResets>,
) -> Self::Output<SubstituteResets> {
let resets = pass_args
.get_resets(self.expr)
.expect("added resets in build_reset_graph");
let arg = Expr::canonical(self.arg).run_pass(pass_args.as_mut())?;
let ty = resets.substituted_type(
&mut pass_args.state.reset_graph,
pass_args.state.fallback_to_sync_reset,
pass_args.fallback_error_source_location,
)?;
Ok(arg.map(|arg| {
macro_rules! match_expr_ty {
($arg:ident, $($Variant:ident),*) => {
match ty {
CanonicalType::Array(_)
| CanonicalType::Enum(_)
| CanonicalType::Bundle(_)
| CanonicalType::Reset(_) => unreachable!(),
$(CanonicalType::$Variant(ty) => Expr::expr_enum($arg.cast_to(ty)),)*
}
};
}
macro_rules! match_arg_ty {
($($Variant:ident),*) => {
*match Expr::ty(arg) {
CanonicalType::Array(_)
| CanonicalType::Enum(_)
| CanonicalType::Bundle(_)
| CanonicalType::Reset(_) => unreachable!(),
$(CanonicalType::$Variant(_) => {
let arg = Expr::<$Variant>::from_canonical(arg);
match_expr_ty!(arg, UInt, SInt, Bool, AsyncReset, SyncReset, Clock)
})*
}
};
}
match_arg_ty!(UInt, SInt, Bool, AsyncReset, SyncReset, Clock)
}))
}
}
P::dispatch(
Dispatch {
expr: expr.to_expr(),
arg,
_phantom: PhantomData,
},
pass_args,
)
}
impl<P: Pass> RunPass<P> for ExprEnum {
fn run_pass(
&self,
@ -991,51 +1074,23 @@ impl<P: Pass> RunPass<P> for ExprEnum {
ExprEnum::CastBoolToSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastUIntToBool(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastSIntToBool(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastBoolToSyncReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastUIntToSyncReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastSIntToSyncReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastBoolToAsyncReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastUIntToAsyncReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastSIntToAsyncReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastSyncResetToBool(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastSyncResetToUInt(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastSyncResetToSInt(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastSyncResetToReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastAsyncResetToBool(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastAsyncResetToUInt(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastAsyncResetToSInt(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastAsyncResetToReset(expr) => {
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
}
ExprEnum::CastResetToBool(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastResetToUInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastResetToSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastBoolToSyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastUIntToSyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastSIntToSyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastBoolToAsyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastUIntToAsyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastSIntToAsyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastSyncResetToBool(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastSyncResetToUInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastSyncResetToSInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastSyncResetToReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastAsyncResetToBool(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastAsyncResetToUInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastAsyncResetToSInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastAsyncResetToReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastResetToBool(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastResetToUInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastResetToSInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
ExprEnum::CastBoolToClock(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastUIntToClock(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastSIntToClock(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
@ -1078,6 +1133,50 @@ impl<P: Pass> RunPass<P> for Expr<CanonicalType> {
}
}
impl<P: Pass, Width: Size> RunPass<P> for Expr<UIntType<Width>> {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
Ok(Expr::canonical(*self)
.run_pass(pass_args)?
.map(Expr::from_canonical))
}
}
impl<P: Pass, Width: Size> RunPass<P> for Expr<SIntType<Width>> {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
Ok(Expr::canonical(*self)
.run_pass(pass_args)?
.map(Expr::from_canonical))
}
}
impl<P: Pass> RunPass<P> for Expr<Bool> {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
Ok(Expr::canonical(*self)
.run_pass(pass_args)?
.map(Expr::from_canonical))
}
}
impl<P: Pass> RunPass<P> for Expr<Clock> {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
Ok(Expr::canonical(*self)
.run_pass(pass_args)?
.map(Expr::from_canonical))
}
}
impl RunPassDispatch for ModuleIO<CanonicalType> {
fn build_reset_graph(
&self,
@ -1324,6 +1423,113 @@ macro_rules! impl_run_pass_for_enum {
};
}
macro_rules! impl_run_pass_for_unary_op {
($path:path) => {
impl_run_pass_for_struct! {
#[constructor = <$path>::new(arg)]
impl[] RunPass for $path {
arg(): _,
}
}
};
}
impl_run_pass_for_unary_op!(ops::NotU);
impl_run_pass_for_unary_op!(ops::NotS);
impl_run_pass_for_unary_op!(ops::NotB);
impl_run_pass_for_unary_op!(ops::Neg);
impl_run_pass_for_unary_op!(ops::CastBoolToUInt);
impl_run_pass_for_unary_op!(ops::CastBoolToSInt);
impl_run_pass_for_unary_op!(ops::CastUIntToBool);
impl_run_pass_for_unary_op!(ops::CastSIntToBool);
impl_run_pass_for_unary_op!(ops::CastBoolToClock);
impl_run_pass_for_unary_op!(ops::CastUIntToClock);
impl_run_pass_for_unary_op!(ops::CastSIntToClock);
impl_run_pass_for_unary_op!(ops::CastClockToBool);
impl_run_pass_for_unary_op!(ops::CastClockToUInt);
impl_run_pass_for_unary_op!(ops::CastClockToSInt);
impl_run_pass_for_unary_op!(ops::ReduceBitAndU);
impl_run_pass_for_unary_op!(ops::ReduceBitAndS);
impl_run_pass_for_unary_op!(ops::ReduceBitOrU);
impl_run_pass_for_unary_op!(ops::ReduceBitOrS);
impl_run_pass_for_unary_op!(ops::ReduceBitXorU);
impl_run_pass_for_unary_op!(ops::ReduceBitXorS);
macro_rules! impl_run_pass_for_binary_op {
($path:path) => {
impl_run_pass_for_struct! {
#[constructor = <$path>::new(lhs, rhs)]
impl[] RunPass for $path {
lhs(): _,
rhs(): _,
}
}
};
}
impl_run_pass_for_binary_op!(ops::BitAndU);
impl_run_pass_for_binary_op!(ops::BitAndS);
impl_run_pass_for_binary_op!(ops::BitAndB);
impl_run_pass_for_binary_op!(ops::BitOrU);
impl_run_pass_for_binary_op!(ops::BitOrS);
impl_run_pass_for_binary_op!(ops::BitOrB);
impl_run_pass_for_binary_op!(ops::BitXorU);
impl_run_pass_for_binary_op!(ops::BitXorS);
impl_run_pass_for_binary_op!(ops::BitXorB);
impl_run_pass_for_binary_op!(ops::AddU);
impl_run_pass_for_binary_op!(ops::AddS);
impl_run_pass_for_binary_op!(ops::SubU);
impl_run_pass_for_binary_op!(ops::SubS);
impl_run_pass_for_binary_op!(ops::MulU);
impl_run_pass_for_binary_op!(ops::MulS);
impl_run_pass_for_binary_op!(ops::DivU);
impl_run_pass_for_binary_op!(ops::DivS);
impl_run_pass_for_binary_op!(ops::RemU);
impl_run_pass_for_binary_op!(ops::RemS);
impl_run_pass_for_binary_op!(ops::DynShlU);
impl_run_pass_for_binary_op!(ops::DynShlS);
impl_run_pass_for_binary_op!(ops::DynShrU);
impl_run_pass_for_binary_op!(ops::DynShrS);
impl_run_pass_for_binary_op!(ops::FixedShlU);
impl_run_pass_for_binary_op!(ops::FixedShlS);
impl_run_pass_for_binary_op!(ops::FixedShrU);
impl_run_pass_for_binary_op!(ops::FixedShrS);
impl_run_pass_for_binary_op!(ops::CmpLtB);
impl_run_pass_for_binary_op!(ops::CmpLeB);
impl_run_pass_for_binary_op!(ops::CmpGtB);
impl_run_pass_for_binary_op!(ops::CmpGeB);
impl_run_pass_for_binary_op!(ops::CmpEqB);
impl_run_pass_for_binary_op!(ops::CmpNeB);
impl_run_pass_for_binary_op!(ops::CmpLtU);
impl_run_pass_for_binary_op!(ops::CmpLeU);
impl_run_pass_for_binary_op!(ops::CmpGtU);
impl_run_pass_for_binary_op!(ops::CmpGeU);
impl_run_pass_for_binary_op!(ops::CmpEqU);
impl_run_pass_for_binary_op!(ops::CmpNeU);
impl_run_pass_for_binary_op!(ops::CmpLtS);
impl_run_pass_for_binary_op!(ops::CmpLeS);
impl_run_pass_for_binary_op!(ops::CmpGtS);
impl_run_pass_for_binary_op!(ops::CmpGeS);
impl_run_pass_for_binary_op!(ops::CmpEqS);
impl_run_pass_for_binary_op!(ops::CmpNeS);
macro_rules! impl_run_pass_for_int_cast_op {
($path:path) => {
impl_run_pass_for_struct! {
#[constructor = <$path>::new(arg, ty)]
impl[] RunPass for $path {
arg(): _,
ty(): _,
}
}
};
}
impl_run_pass_for_int_cast_op!(ops::CastUIntToUInt);
impl_run_pass_for_int_cast_op!(ops::CastUIntToSInt);
impl_run_pass_for_int_cast_op!(ops::CastSIntToUInt);
impl_run_pass_for_int_cast_op!(ops::CastSIntToSInt);
impl_run_pass_for_struct! {
impl[] RunPass for Block {
memories: _,