working on deduce_resets
This commit is contained in:
parent
358cdd10c8
commit
d744d85c66
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
bundle::{BundleField, BundleType},
|
bundle::{BundleField, BundleType},
|
||||||
enum_::{EnumType, EnumVariant},
|
enum_::{EnumType, EnumVariant},
|
||||||
expr::{
|
expr::{
|
||||||
|
ops,
|
||||||
target::{
|
target::{
|
||||||
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
|
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
|
||||||
TargetPathDynArrayElement, TargetPathElement,
|
TargetPathDynArrayElement, TargetPathElement,
|
||||||
|
@ -25,14 +26,8 @@ use crate::{
|
||||||
reset::{ResetType, ResetTypeDispatch},
|
reset::{ResetType, ResetTypeDispatch},
|
||||||
};
|
};
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
|
||||||
use num_bigint::BigInt;
|
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use petgraph::unionfind::UnionFind;
|
use petgraph::unionfind::UnionFind;
|
||||||
use petgraph::{
|
|
||||||
graph::{NodeIndex, UnGraph},
|
|
||||||
unionfind::UnionFind,
|
|
||||||
};
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
fmt,
|
fmt,
|
||||||
|
@ -921,6 +916,94 @@ fn reg_expr_run_pass<P: Pass, R: ResetType>(
|
||||||
.map(|reg| match_any_reg!(reg, ExprEnum::from)))
|
.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 {
|
impl<P: Pass> RunPass<P> for ExprEnum {
|
||||||
fn run_pass(
|
fn run_pass(
|
||||||
&self,
|
&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::CastBoolToSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::CastUIntToBool(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::CastSIntToBool(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::CastBoolToSyncReset(expr) => {
|
ExprEnum::CastBoolToSyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
|
ExprEnum::CastUIntToSyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
}
|
ExprEnum::CastSIntToSyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
ExprEnum::CastUIntToSyncReset(expr) => {
|
ExprEnum::CastBoolToAsyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
|
ExprEnum::CastUIntToAsyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
}
|
ExprEnum::CastSIntToAsyncReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
ExprEnum::CastSIntToSyncReset(expr) => {
|
ExprEnum::CastSyncResetToBool(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
|
ExprEnum::CastSyncResetToUInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
}
|
ExprEnum::CastSyncResetToSInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
ExprEnum::CastBoolToAsyncReset(expr) => {
|
ExprEnum::CastSyncResetToReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
|
ExprEnum::CastAsyncResetToBool(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
}
|
ExprEnum::CastAsyncResetToUInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
ExprEnum::CastUIntToAsyncReset(expr) => {
|
ExprEnum::CastAsyncResetToSInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
|
ExprEnum::CastAsyncResetToReset(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
}
|
ExprEnum::CastResetToBool(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
ExprEnum::CastSIntToAsyncReset(expr) => {
|
ExprEnum::CastResetToUInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
Ok(expr.run_pass(pass_args)?.map(ExprEnum::from))
|
ExprEnum::CastResetToSInt(expr) => cast_bit_op(expr, expr.arg(), pass_args),
|
||||||
}
|
|
||||||
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::CastBoolToClock(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
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::CastUIntToClock(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
ExprEnum::CastSIntToClock(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> {
|
impl RunPassDispatch for ModuleIO<CanonicalType> {
|
||||||
fn build_reset_graph(
|
fn build_reset_graph(
|
||||||
&self,
|
&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_run_pass_for_struct! {
|
||||||
impl[] RunPass for Block {
|
impl[] RunPass for Block {
|
||||||
memories: _,
|
memories: _,
|
||||||
|
|
Loading…
Reference in a new issue