working on deduce_resets
This commit is contained in:
parent
9b5f1218fd
commit
546010739a
|
@ -3,44 +3,41 @@
|
||||||
|
|
||||||
#![cfg(todo)]
|
#![cfg(todo)]
|
||||||
|
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
|
||||||
use num_bigint::BigInt;
|
|
||||||
use petgraph::{
|
|
||||||
graph::{NodeIndex, UnGraph},
|
|
||||||
unionfind::UnionFind,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
annotations::{Annotation, TargetedAnnotation},
|
annotations::{Annotation, TargetedAnnotation},
|
||||||
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,
|
||||||
},
|
},
|
||||||
ExprEnum, Flow,
|
ExprEnum,
|
||||||
},
|
},
|
||||||
|
int::{SIntValue, UIntValue},
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
memory::{DynPortType, MemPort},
|
memory::{DynPortType, MemPort},
|
||||||
module::{
|
module::{
|
||||||
transform::visit::{Folder, Visit, Visitor},
|
AnnotatedModuleIO, Block, ExprInInstantiatedModule, ExternModuleBody, InstantiatedModule,
|
||||||
AnnotatedModuleIO, Block, ExprInInstantiatedModule, ExternModuleBody,
|
ModuleBody, ModuleIO, NameId, NormalModuleBody,
|
||||||
ExternModuleParameter, ExternModuleParameterValue, InstantiatedModule, ModuleBody,
|
|
||||||
ModuleIO, NameId, NormalModuleBody, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf,
|
|
||||||
StmtInstance, StmtMatch, StmtReg, StmtWire,
|
|
||||||
},
|
},
|
||||||
prelude::*,
|
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::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
convert::Infallible,
|
|
||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
enum ResetsLayout {
|
enum ResetsLayout {
|
||||||
NoResets,
|
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)]
|
#[derive(Debug)]
|
||||||
|
@ -318,23 +373,164 @@ impl<'a, T: ?Sized + Intern> MaybeInterned<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
struct Resets<'a> {
|
struct Resets {
|
||||||
ty: CanonicalType,
|
ty: CanonicalType,
|
||||||
layout: ResetsLayout,
|
layout: ResetsLayout,
|
||||||
node_indexes: MaybeInterned<'a, [ResetNodeIndex]>,
|
node_indexes: Interned<[ResetNodeIndex]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Resets<'a> {
|
impl Resets {
|
||||||
fn into_interned(self) -> Resets<'static> {
|
fn with_new_nodes(
|
||||||
let Self {
|
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,
|
ty,
|
||||||
layout,
|
layout,
|
||||||
node_indexes,
|
node_indexes,
|
||||||
} = self;
|
}
|
||||||
Resets {
|
}
|
||||||
ty,
|
fn array_elements(self) -> Self {
|
||||||
layout,
|
let array = <Array>::from_canonical(self.ty);
|
||||||
node_indexes: MaybeInterned::Interned(node_indexes.to_interned()),
|
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,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
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)]
|
#[derive(Debug)]
|
||||||
struct State {
|
struct State {
|
||||||
base_module: Interned<Module<Bundle>>,
|
base_module: Interned<Module<Bundle>>,
|
||||||
expr_resets: HashMap<ExprInInstantiatedModule<CanonicalType>, Resets<'static>>,
|
expr_resets: HashMap<ExprInInstantiatedModule<CanonicalType>, Resets>,
|
||||||
reset_graph: ResetGraph,
|
reset_graph: ResetGraph,
|
||||||
fallback_to_sync_reset: bool,
|
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>);
|
struct PassOutput<T, P: Pass>(P::Output<T>);
|
||||||
|
|
||||||
impl<T, P: Pass> PassOutput<T, P> {
|
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 {
|
trait Pass: Sized {
|
||||||
type Output<T>;
|
type Output<T>;
|
||||||
fn output_new<T>(v: T) -> PassOutput<T, Self>;
|
fn output_new<T>(v: T) -> PassOutput<T, Self>;
|
||||||
|
@ -452,6 +698,7 @@ trait Pass: Sized {
|
||||||
) -> PassOutput<T, Self>;
|
) -> PassOutput<T, Self>;
|
||||||
fn map<T, U>(v: PassOutput<T, Self>, f: impl FnOnce(T) -> U) -> PassOutput<U, 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 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;
|
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> {
|
fn zip<T, U>(_t: PassOutput<T, Self>, _u: PassOutput<U, Self>) -> PassOutput<(T, U), Self> {
|
||||||
PassOutput(())
|
PassOutput(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dispatch<D: PassDispatch>(dispatch: D, input: D::Input<Self>) -> D::Output<Self> {
|
||||||
|
dispatch.build_reset_graph(input)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SubstituteResets;
|
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> {
|
fn zip<T, U>(t: PassOutput<T, Self>, u: PassOutput<U, Self>) -> PassOutput<(T, U), Self> {
|
||||||
PassOutput((t.0, u.0))
|
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> {
|
struct PassArgs<'a, P: Pass> {
|
||||||
|
@ -560,6 +815,17 @@ impl<'a, P: Pass> PassArgs<'a, P> {
|
||||||
_phantom: PhantomData,
|
_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 {
|
trait RunPass<P: Pass>: Sized {
|
||||||
|
@ -569,6 +835,50 @@ trait RunPass<P: Pass>: Sized {
|
||||||
) -> Result<PassOutput<Self, P>, DeduceResetsError>;
|
) -> 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> {
|
impl<T: RunPass<P> + Intern + Clone, P: Pass> RunPass<P> for Interned<T> {
|
||||||
fn run_pass(
|
fn run_pass(
|
||||||
&self,
|
&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 {
|
macro_rules! impl_run_pass_copy {
|
||||||
([$($generics:tt)*] $ty:ty) => {
|
([$($generics:tt)*] $ty:ty) => {
|
||||||
impl<P: Pass, $($generics)*> RunPass<P> for $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!([] 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 {
|
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!([] MemPort<DynPortType>); // Mem can't contain any `Reset` types
|
||||||
impl_run_pass_copy!([] Mem); // 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<P: Pass> RunPass<P> for TargetBase {
|
||||||
impl[] RunPass for TargetBase {
|
fn run_pass(
|
||||||
ModuleIO(v),
|
&self,
|
||||||
MemPort(v),
|
pass_args: PassArgs<'_, P>,
|
||||||
Reg(v),
|
) -> Result<PassOutput<Self, P>, DeduceResetsError> {
|
||||||
Wire(v),
|
let reg = match self {
|
||||||
Instance(v),
|
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),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue