working on deduce_resets
Some checks failed
/ deps (push) Successful in 15s
/ test (push) Has been cancelled
/ deps (pull_request) Successful in 13s
/ test (pull_request) Successful in 5m1s

This commit is contained in:
Jacob Lifshay 2024-11-26 21:26:56 -08:00
parent 9b5f1218fd
commit 546010739a
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ

View file

@ -3,44 +3,41 @@
#![cfg(todo)]
use hashbrown::{hash_map::Entry, HashMap};
use num_bigint::BigInt;
use petgraph::{
graph::{NodeIndex, UnGraph},
unionfind::UnionFind,
};
use crate::{
annotations::{Annotation, TargetedAnnotation},
bundle::{BundleField, BundleType},
enum_::{EnumType, EnumVariant},
expr::{
ops,
target::{
Target, TargetBase, TargetChild, TargetPathArrayElement, TargetPathBundleField,
TargetPathDynArrayElement, TargetPathElement,
},
ExprEnum, Flow,
ExprEnum,
},
int::{SIntValue, UIntValue},
intern::{Intern, Interned, Memoize},
memory::{DynPortType, MemPort},
module::{
transform::visit::{Folder, Visit, Visitor},
AnnotatedModuleIO, Block, ExprInInstantiatedModule, ExternModuleBody,
ExternModuleParameter, ExternModuleParameterValue, InstantiatedModule, ModuleBody,
ModuleIO, NameId, NormalModuleBody, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf,
StmtInstance, StmtMatch, StmtReg, StmtWire,
AnnotatedModuleIO, Block, ExprInInstantiatedModule, ExternModuleBody, InstantiatedModule,
ModuleBody, ModuleIO, NameId, NormalModuleBody,
},
prelude::*,
source_location,
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,
convert::Infallible,
fmt,
hash::{Hash, Hasher},
marker::PhantomData,
mem,
};
#[derive(Debug)]
@ -70,6 +67,25 @@ impl From<DeduceResetsError> for std::io::Error {
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
enum AnyReg {
Reg(Reg<CanonicalType, Reset>),
RegSync(Reg<CanonicalType, SyncReset>),
RegAsync(Reg<CanonicalType, AsyncReset>),
}
macro_rules! match_any_reg {
(
$match_expr:expr, $fn:expr
) => {
match $match_expr {
AnyReg::Reg(reg) => $fn(reg),
AnyReg::RegSync(reg) => $fn(reg),
AnyReg::RegAsync(reg) => $fn(reg),
}
};
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
enum ResetsLayout {
NoResets,
@ -261,6 +277,45 @@ impl ResetGraph {
})
}
}
fn append_new_nodes_for_layout(
&mut self,
layout: ResetsLayout,
node_indexes: &mut Vec<ResetNodeIndex>,
source_location: Option<SourceLocation>,
) {
match layout {
ResetsLayout::NoResets => {}
ResetsLayout::Reset => node_indexes.push(self.new_node(None, source_location)),
ResetsLayout::SyncReset => {
node_indexes.push(self.new_node(Some(false), source_location))
}
ResetsLayout::AsyncReset => {
node_indexes.push(self.new_node(Some(true), source_location))
}
ResetsLayout::Bundle {
fields,
reset_count: _,
} => {
for field in fields {
self.append_new_nodes_for_layout(field, node_indexes, source_location);
}
}
ResetsLayout::Enum {
variants,
reset_count: _,
} => {
for variant in variants {
self.append_new_nodes_for_layout(variant, node_indexes, source_location);
}
}
ResetsLayout::Array {
element,
reset_count: _,
} => {
self.append_new_nodes_for_layout(*element, node_indexes, source_location);
}
}
}
}
#[derive(Debug)]
@ -318,23 +373,164 @@ impl<'a, T: ?Sized + Intern> MaybeInterned<'a, T> {
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
struct Resets<'a> {
struct Resets {
ty: CanonicalType,
layout: ResetsLayout,
node_indexes: MaybeInterned<'a, [ResetNodeIndex]>,
node_indexes: Interned<[ResetNodeIndex]>,
}
impl<'a> Resets<'a> {
fn into_interned(self) -> Resets<'static> {
let Self {
impl Resets {
fn with_new_nodes(
reset_graph: &mut ResetGraph,
ty: CanonicalType,
source_location: Option<SourceLocation>,
) -> Self {
let layout = ResetsLayout::new(ty);
let mut node_indexes = Vec::with_capacity(layout.reset_count());
reset_graph.append_new_nodes_for_layout(layout, &mut node_indexes, source_location);
let node_indexes = Intern::intern_owned(node_indexes);
Self {
ty,
layout,
node_indexes,
} = self;
Resets {
}
}
fn array_elements(self) -> Self {
let array = <Array>::from_canonical(self.ty);
let ResetsLayout::Array {
element,
reset_count: _,
} = self.layout
else {
unreachable!();
};
Self {
ty: array.element(),
layout: *element,
node_indexes: self.node_indexes,
}
}
fn bundle_fields(self) -> impl Iterator<Item = Self> {
let bundle = Bundle::from_canonical(self.ty);
let ResetsLayout::Bundle {
fields,
reset_count: _,
} = self.layout
else {
unreachable!();
};
bundle.fields().into_iter().zip(fields).scan(
0,
move |start_index, (BundleField { ty, .. }, layout)| {
let end_index = *start_index + layout.reset_count();
let node_indexes = self.node_indexes[*start_index..end_index].intern();
*start_index = end_index;
Some(Self {
ty,
layout,
node_indexes: MaybeInterned::Interned(node_indexes.to_interned()),
node_indexes,
})
},
)
}
fn enum_variants(self) -> impl Iterator<Item = Option<Self>> {
let enum_ = Enum::from_canonical(self.ty);
let ResetsLayout::Enum {
variants,
reset_count: _,
} = self.layout
else {
unreachable!();
};
enum_.variants().into_iter().zip(variants).scan(
0,
move |start_index, (EnumVariant { ty, .. }, layout)| {
let end_index = *start_index + layout.reset_count();
let node_indexes = self.node_indexes[*start_index..end_index].intern();
*start_index = end_index;
Some(ty.map(|ty| Self {
ty,
layout,
node_indexes,
}))
},
)
}
fn substituted_type(
self,
reset_graph: &mut ResetGraph,
fallback_to_sync_reset: bool,
fallback_error_source_location: SourceLocation,
) -> Result<CanonicalType, DeduceResetsError> {
if self.layout.reset_count() == 0 {
return Ok(self.ty);
}
match self.ty {
CanonicalType::UInt(_)
| CanonicalType::SInt(_)
| CanonicalType::Bool(_)
| CanonicalType::AsyncReset(_)
| CanonicalType::SyncReset(_)
| CanonicalType::Clock(_) => Ok(self.ty),
CanonicalType::Array(ty) => Ok(CanonicalType::Array(Array::new_dyn(
self.array_elements().substituted_type(
reset_graph,
fallback_to_sync_reset,
fallback_error_source_location,
)?,
ty.len(),
))),
CanonicalType::Enum(ty) => Ok(CanonicalType::Enum(Enum::new(Result::from_iter(
self.enum_variants().zip(ty.variants()).map(
|(resets, EnumVariant { name, ty: _ })| {
Ok(EnumVariant {
name,
ty: resets
.map(|resets| {
resets.substituted_type(
reset_graph,
fallback_to_sync_reset,
fallback_error_source_location,
)
})
.transpose()?,
})
},
),
)?))),
CanonicalType::Bundle(ty) => Ok(CanonicalType::Bundle(Bundle::new(Result::from_iter(
self.bundle_fields().zip(ty.fields()).map(
|(
resets,
BundleField {
name,
flipped,
ty: _,
},
)| {
Ok(BundleField {
name,
flipped,
ty: resets.substituted_type(
reset_graph,
fallback_to_sync_reset,
fallback_error_source_location,
)?,
})
},
),
)?))),
CanonicalType::Reset(_) => Ok(
if reset_graph.is_async(
self.node_indexes[0],
fallback_to_sync_reset,
fallback_error_source_location,
)? {
CanonicalType::AsyncReset(AsyncReset)
} else {
CanonicalType::SyncReset(SyncReset)
},
),
}
}
}
@ -342,11 +538,48 @@ impl<'a> Resets<'a> {
#[derive(Debug)]
struct State {
base_module: Interned<Module<Bundle>>,
expr_resets: HashMap<ExprInInstantiatedModule<CanonicalType>, Resets<'static>>,
expr_resets: HashMap<ExprInInstantiatedModule<CanonicalType>, Resets>,
reset_graph: ResetGraph,
fallback_to_sync_reset: bool,
}
impl State {
fn get_resets(
&self,
instantiated_module: InstantiatedModule,
expr: impl ToExpr,
) -> Option<Resets> {
self.expr_resets
.get(&ExprInInstantiatedModule {
instantiated_module,
expr: Expr::canonical(expr.to_expr()),
})
.copied()
}
fn get_or_make_resets(
&mut self,
instantiated_module: InstantiatedModule,
expr: impl ToExpr,
source_location: Option<SourceLocation>,
) -> (Resets, bool) {
let expr = Expr::canonical(expr.to_expr());
match self.expr_resets.entry(ExprInInstantiatedModule {
instantiated_module,
expr,
}) {
Entry::Occupied(entry) => (*entry.get(), false),
Entry::Vacant(entry) => (
*entry.insert(Resets::with_new_nodes(
&mut self.reset_graph,
Expr::ty(expr),
source_location,
)),
true,
),
}
}
}
struct PassOutput<T, P: Pass>(P::Output<T>);
impl<T, P: Pass> PassOutput<T, P> {
@ -442,6 +675,19 @@ impl<T: FromIterator<A>, P: Pass, A> FromIterator<PassOutput<A, P>> for PassOutp
}
}
trait PassDispatch: Sized {
type Input<P: Pass>;
type Output<P: Pass>;
fn build_reset_graph(
self,
input: Self::Input<BuildResetGraph>,
) -> Self::Output<BuildResetGraph>;
fn substitute_resets(
self,
input: Self::Input<SubstituteResets>,
) -> Self::Output<SubstituteResets>;
}
trait Pass: Sized {
type Output<T>;
fn output_new<T>(v: T) -> PassOutput<T, Self>;
@ -452,6 +698,7 @@ trait Pass: Sized {
) -> PassOutput<T, Self>;
fn map<T, U>(v: PassOutput<T, Self>, f: impl FnOnce(T) -> U) -> PassOutput<U, Self>;
fn zip<T, U>(t: PassOutput<T, Self>, u: PassOutput<U, Self>) -> PassOutput<(T, U), Self>;
fn dispatch<D: PassDispatch>(dispatch: D, input: D::Input<Self>) -> D::Output<Self>;
}
struct BuildResetGraph;
@ -485,6 +732,10 @@ impl Pass for BuildResetGraph {
fn zip<T, U>(_t: PassOutput<T, Self>, _u: PassOutput<U, Self>) -> PassOutput<(T, U), Self> {
PassOutput(())
}
fn dispatch<D: PassDispatch>(dispatch: D, input: D::Input<Self>) -> D::Output<Self> {
dispatch.build_reset_graph(input)
}
}
struct SubstituteResets;
@ -517,6 +768,10 @@ impl Pass for SubstituteResets {
fn zip<T, U>(t: PassOutput<T, Self>, u: PassOutput<U, Self>) -> PassOutput<(T, U), Self> {
PassOutput((t.0, u.0))
}
fn dispatch<D: PassDispatch>(dispatch: D, input: D::Input<Self>) -> D::Output<Self> {
dispatch.substitute_resets(input)
}
}
struct PassArgs<'a, P: Pass> {
@ -560,6 +815,17 @@ impl<'a, P: Pass> PassArgs<'a, P> {
_phantom: PhantomData,
}
}
fn get_resets(&self, expr: impl ToExpr) -> Option<Resets> {
self.state.get_resets(self.instantiated_module, expr)
}
fn get_or_make_resets(
&mut self,
expr: impl ToExpr,
source_location: Option<SourceLocation>,
) -> (Resets, bool) {
self.state
.get_or_make_resets(self.instantiated_module, expr, source_location)
}
}
trait RunPass<P: Pass>: Sized {
@ -569,6 +835,50 @@ trait RunPass<P: Pass>: Sized {
) -> Result<PassOutput<Self, P>, DeduceResetsError>;
}
trait RunPassDispatch: Sized {
fn build_reset_graph(
&self,
pass_args: PassArgs<'_, BuildResetGraph>,
) -> Result<PassOutput<Self, BuildResetGraph>, DeduceResetsError>;
fn substitute_resets(
&self,
pass_args: PassArgs<'_, SubstituteResets>,
) -> Result<PassOutput<Self, SubstituteResets>, DeduceResetsError>;
fn dispatch<P: Pass>(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
struct Dispatch<'a, T>(T, PhantomData<&'a mut ()>);
impl<'a, T: RunPassDispatch> PassDispatch for Dispatch<'a, &'_ T> {
type Input<P: Pass> = PassArgs<'a, P>;
type Output<P: Pass> = Result<PassOutput<T, P>, DeduceResetsError>;
fn build_reset_graph(
self,
input: Self::Input<BuildResetGraph>,
) -> Self::Output<BuildResetGraph> {
self.0.build_reset_graph(input)
}
fn substitute_resets(
self,
input: Self::Input<SubstituteResets>,
) -> Self::Output<SubstituteResets> {
self.0.substitute_resets(input)
}
}
P::dispatch(Dispatch(self, PhantomData), pass_args)
}
}
impl<T: RunPassDispatch, P: Pass> RunPass<P> for T {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
T::dispatch(self, pass_args)
}
}
impl<T: RunPass<P> + Intern + Clone, P: Pass> RunPass<P> for Interned<T> {
fn run_pass(
&self,
@ -590,6 +900,332 @@ where
}
}
impl<T: RunPass<P>, P: Pass> RunPass<P> for Option<T> {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
match self {
Some(v) => Ok(v.run_pass(pass_args)?.map(Some)),
None => Ok(PassOutput::new(None)),
}
}
}
fn reg_expr_run_pass<P: Pass, R: ResetType>(
reg: &Reg<CanonicalType, R>,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<ExprEnum, P>, DeduceResetsError> {
Ok(AnyReg::from(*reg)
.run_pass(pass_args)?
.map(|reg| match_any_reg!(reg, ExprEnum::from)))
}
impl<P: Pass> RunPass<P> for ExprEnum {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
match self {
ExprEnum::UIntLiteral(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::SIntLiteral(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BoolLiteral(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BundleLiteral(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ArrayLiteral(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::EnumLiteral(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::Uninit(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::NotU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::NotS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::NotB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::Neg(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitAndU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitAndS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitAndB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitOrU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitOrS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitOrB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitXorU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitXorS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::BitXorB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::AddU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::AddS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::SubU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::SubS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::MulU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::MulS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::DivU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::DivS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::RemU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::RemS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::DynShlU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::DynShlS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::DynShrU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::DynShrS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::FixedShlU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::FixedShlS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::FixedShrU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::FixedShrS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpLtB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpLeB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpGtB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpGeB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpEqB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpNeB(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpLtU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpLeU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpGtU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpGeU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpEqU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpNeU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpLtS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpLeS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpGtS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpGeS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpEqS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CmpNeS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastUIntToUInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastUIntToSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastSIntToUInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastSIntToSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastBoolToUInt(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::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::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)),
ExprEnum::CastClockToBool(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastClockToUInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastClockToSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::FieldAccess(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::VariantAccess(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ArrayIndex(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::DynArrayIndex(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ReduceBitAndU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ReduceBitAndS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ReduceBitOrU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ReduceBitOrS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ReduceBitXorU(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ReduceBitXorS(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::SliceUInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::SliceSInt(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastToBits(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::CastBitsTo(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::ModuleIO(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::Instance(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::Wire(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
ExprEnum::Reg(expr) => reg_expr_run_pass(expr, pass_args),
ExprEnum::RegSync(expr) => reg_expr_run_pass(expr, pass_args),
ExprEnum::RegAsync(expr) => reg_expr_run_pass(expr, pass_args),
ExprEnum::MemPort(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
}
}
}
impl<P: Pass> RunPass<P> for Expr<CanonicalType> {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
Ok(Expr::expr_enum(*self)
.run_pass(pass_args)?
.map(|expr_enum| expr_enum.to_expr()))
}
}
impl RunPassDispatch for ModuleIO<CanonicalType> {
fn build_reset_graph(
&self,
mut pass_args: PassArgs<'_, BuildResetGraph>,
) -> Result<PassOutput<Self, BuildResetGraph>, DeduceResetsError> {
pass_args.get_or_make_resets(self, Some(self.source_location()));
Ok(PassOutput(()))
}
fn substitute_resets(
&self,
pass_args: PassArgs<'_, SubstituteResets>,
) -> Result<PassOutput<Self, SubstituteResets>, DeduceResetsError> {
let resets = pass_args
.get_resets(self)
.expect("added resets in build_reset_graph");
Ok(PassOutput(Self::new_unchecked(
self.containing_module_name_id(),
self.name_id(),
self.source_location(),
self.is_input(),
resets.substituted_type(
&mut pass_args.state.reset_graph,
pass_args.state.fallback_to_sync_reset,
self.source_location(),
)?,
)))
}
}
impl RunPassDispatch for Wire<CanonicalType> {
fn build_reset_graph(
&self,
mut pass_args: PassArgs<'_, BuildResetGraph>,
) -> Result<PassOutput<Self, BuildResetGraph>, DeduceResetsError> {
pass_args.get_or_make_resets(self, Some(self.source_location()));
Ok(PassOutput(()))
}
fn substitute_resets(
&self,
pass_args: PassArgs<'_, SubstituteResets>,
) -> Result<PassOutput<Self, SubstituteResets>, DeduceResetsError> {
let resets = pass_args
.get_resets(self)
.expect("added resets in build_reset_graph");
Ok(PassOutput(Self::new_unchecked(
self.scoped_name(),
self.source_location(),
resets.substituted_type(
&mut pass_args.state.reset_graph,
pass_args.state.fallback_to_sync_reset,
self.source_location(),
)?,
)))
}
}
impl<T: ResetType> From<Reg<CanonicalType, T>> for AnyReg {
fn from(value: Reg<CanonicalType, T>) -> Self {
struct Dispatch;
impl ResetTypeDispatch for Dispatch {
type Input<T: ResetType> = Reg<CanonicalType, T>;
type Output<T: ResetType> = AnyReg;
fn reset(self, input: Self::Input<Reset>) -> Self::Output<Reset> {
AnyReg::Reg(input)
}
fn sync_reset(self, input: Self::Input<SyncReset>) -> Self::Output<SyncReset> {
AnyReg::RegSync(input)
}
fn async_reset(self, input: Self::Input<AsyncReset>) -> Self::Output<AsyncReset> {
AnyReg::RegAsync(input)
}
}
T::dispatch(value, Dispatch)
}
}
impl RunPassDispatch for AnyReg {
fn build_reset_graph(
&self,
mut pass_args: PassArgs<'_, BuildResetGraph>,
) -> Result<PassOutput<Self, BuildResetGraph>, DeduceResetsError> {
match_any_reg!(self, |reg: &Reg<CanonicalType, _>| {
pass_args
.get_or_make_resets(Expr::canonical(reg.to_expr()), Some(reg.source_location()));
reg.init().run_pass(pass_args.as_mut())?;
Expr::canonical(reg.clock_domain()).run_pass(pass_args)?;
Ok(PassOutput(()))
})
}
fn substitute_resets(
&self,
mut pass_args: PassArgs<'_, SubstituteResets>,
) -> Result<PassOutput<Self, SubstituteResets>, DeduceResetsError> {
match_any_reg!(self, |reg: &Reg<CanonicalType, _>| {
let scoped_name = reg.scoped_name();
let source_location = reg.source_location();
let resets = pass_args
.get_resets(Expr::canonical(reg.to_expr()))
.expect("added resets in build_reset_graph");
let ty = resets.substituted_type(
&mut pass_args.state.reset_graph,
pass_args.state.fallback_to_sync_reset,
source_location,
)?;
let init = reg.init().run_pass(pass_args.as_mut())?.0;
let clock_domain = Expr::<Bundle>::from_canonical(
Expr::canonical(reg.clock_domain()).run_pass(pass_args)?.0,
);
match Expr::ty(clock_domain)
.field_by_name("rst".intern())
.expect("ClockDomain has rst field")
.ty
{
CanonicalType::AsyncReset(_) => {
Ok(PassOutput(AnyReg::RegAsync(Reg::new_unchecked(
scoped_name,
source_location,
ty,
Expr::from_bundle(clock_domain),
init,
))))
}
CanonicalType::SyncReset(_) => Ok(PassOutput(AnyReg::RegSync(Reg::new_unchecked(
scoped_name,
source_location,
ty,
Expr::from_bundle(clock_domain),
init,
)))),
CanonicalType::UInt(_)
| CanonicalType::SInt(_)
| CanonicalType::Bool(_)
| CanonicalType::Array(_)
| CanonicalType::Enum(_)
| CanonicalType::Bundle(_)
| CanonicalType::Reset(_)
| CanonicalType::Clock(_) => unreachable!(),
}
})
}
}
macro_rules! impl_run_pass_copy {
([$($generics:tt)*] $ty:ty) => {
impl<P: Pass, $($generics)*> RunPass<P> for $ty {
@ -616,10 +1252,21 @@ macro_rules! impl_run_pass_clone {
};
}
impl_run_pass_copy!([] Interned<str>);
impl_run_pass_copy!([] usize);
impl_run_pass_copy!([] bool);
impl_run_pass_clone!([] BigInt);
impl_run_pass_clone!([] UIntValue);
impl_run_pass_clone!([] SIntValue);
impl_run_pass_copy!([] BlackBoxInlineAnnotation);
impl_run_pass_copy!([] BlackBoxPathAnnotation);
impl_run_pass_copy!([] bool);
impl_run_pass_copy!([] CustomFirrtlAnnotation);
impl_run_pass_copy!([] DocStringAnnotation);
impl_run_pass_copy!([] DontTouchAnnotation);
impl_run_pass_copy!([] ExternModuleBody);
impl_run_pass_copy!([] Interned<str>);
impl_run_pass_copy!([] NameId);
impl_run_pass_copy!([] SourceLocation);
impl_run_pass_copy!([] SVAttributeAnnotation);
impl_run_pass_copy!([] usize);
macro_rules! impl_run_pass_for_struct {
(
@ -690,25 +1337,28 @@ impl_run_pass_for_struct! {
}
}
impl_run_pass_copy!([] ExternModuleBody);
impl_run_pass_copy!([] NameId);
impl_run_pass_copy!([] SourceLocation);
impl_run_pass_copy!([] DontTouchAnnotation);
impl_run_pass_copy!([] SVAttributeAnnotation);
impl_run_pass_copy!([] BlackBoxInlineAnnotation);
impl_run_pass_copy!([] BlackBoxPathAnnotation);
impl_run_pass_copy!([] DocStringAnnotation);
impl_run_pass_copy!([] CustomFirrtlAnnotation);
impl_run_pass_copy!([] MemPort<DynPortType>); // Mem can't contain any `Reset` types
impl_run_pass_copy!([] Mem); // Mem can't contain any `Reset` types
impl_run_pass_for_enum! {
impl[] RunPass for TargetBase {
ModuleIO(v),
MemPort(v),
Reg(v),
Wire(v),
Instance(v),
impl<P: Pass> RunPass<P> for TargetBase {
fn run_pass(
&self,
pass_args: PassArgs<'_, P>,
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
let reg = match self {
TargetBase::ModuleIO(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::ModuleIO)),
TargetBase::MemPort(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::MemPort)),
&TargetBase::Reg(v) => v.into(),
&TargetBase::RegSync(v) => v.into(),
&TargetBase::RegAsync(v) => v.into(),
TargetBase::Wire(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Wire)),
TargetBase::Instance(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Instance)),
};
Ok(reg.run_pass(pass_args)?.map(|reg| match reg {
AnyReg::Reg(reg) => TargetBase::Reg(reg),
AnyReg::RegSync(reg) => TargetBase::RegSync(reg),
AnyReg::RegAsync(reg) => TargetBase::RegAsync(reg),
}))
}
}