WIP working on implementing deduce_resets pass
This commit is contained in:
parent
913baa37e9
commit
59be3bd645
|
@ -180,7 +180,7 @@ impl Block {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct StmtConnect {
|
||||
pub lhs: Expr<CanonicalType>,
|
||||
pub rhs: Expr<CanonicalType>,
|
||||
|
@ -235,7 +235,7 @@ impl fmt::Debug for StmtConnect {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct StmtFormal {
|
||||
pub kind: FormalKind,
|
||||
pub clk: Expr<Clock>,
|
||||
|
@ -284,6 +284,8 @@ pub struct StmtIf<S: ModuleBuildingStatus = ModuleBuilt> {
|
|||
pub blocks: [S::Block; 2],
|
||||
}
|
||||
|
||||
impl Copy for StmtIf {}
|
||||
|
||||
impl<S: ModuleBuildingStatus> StmtIf<S> {
|
||||
pub fn then_block(&self) -> S::Block {
|
||||
self.blocks[0]
|
||||
|
@ -315,6 +317,8 @@ pub struct StmtMatch<S: ModuleBuildingStatus = ModuleBuilt> {
|
|||
pub blocks: Interned<[S::Block]>,
|
||||
}
|
||||
|
||||
impl Copy for StmtMatch {}
|
||||
|
||||
impl StmtMatch {
|
||||
#[track_caller]
|
||||
fn assert_validity(&self) {
|
||||
|
@ -459,6 +463,8 @@ pub struct StmtWire<S: ModuleBuildingStatus = ModuleBuilt> {
|
|||
pub wire: Wire<CanonicalType>,
|
||||
}
|
||||
|
||||
impl Copy for StmtWire {}
|
||||
|
||||
#[derive(Hash, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct StmtReg<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||
pub annotations: S::StmtAnnotations,
|
||||
|
@ -473,6 +479,8 @@ pub struct StmtInstance<S: ModuleBuildingStatus = ModuleBuilt> {
|
|||
pub instance: Instance<Bundle>,
|
||||
}
|
||||
|
||||
impl Copy for StmtInstance {}
|
||||
|
||||
wrapper_enum! {
|
||||
#[impl(
|
||||
(<S: ModuleBuildingStatus>) self: StmtDeclaration<S> = self,
|
||||
|
@ -490,6 +498,8 @@ wrapper_enum! {
|
|||
}
|
||||
}
|
||||
|
||||
impl Copy for StmtDeclaration {}
|
||||
|
||||
impl<S: ModuleBuildingStatus> StmtDeclaration<S> {
|
||||
pub fn annotations(&self) -> S::StmtAnnotations {
|
||||
match self {
|
||||
|
@ -546,6 +556,8 @@ wrapper_enum! {
|
|||
}
|
||||
}
|
||||
|
||||
impl Copy for Stmt {}
|
||||
|
||||
impl<S: ModuleBuildingStatus> Stmt<S> {
|
||||
pub fn sub_stmt_blocks(&self) -> &[S::Block] {
|
||||
match self {
|
||||
|
|
|
@ -2,20 +2,28 @@
|
|||
// See Notices.txt for copyright information
|
||||
|
||||
use hashbrown::{hash_map::Entry, HashMap};
|
||||
use petgraph::graph::{NodeIndex, UnGraph};
|
||||
use petgraph::{
|
||||
graph::{NodeIndex, UnGraph},
|
||||
unionfind::UnionFind,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
bundle::{BundleField, BundleType},
|
||||
enum_::{EnumType, EnumVariant},
|
||||
expr::target::{TargetPathArrayElement, TargetPathBundleField, TargetPathElement},
|
||||
expr::{
|
||||
ops,
|
||||
target::{TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement},
|
||||
Flow,
|
||||
},
|
||||
intern::{Intern, Interned, Memoize},
|
||||
module::{
|
||||
AnnotatedModuleIO, ExprInInstantiatedModule, ExternModuleBody, InstantiatedModule,
|
||||
ModuleBody, NormalModuleBody, TargetInInstantiatedModule,
|
||||
AnnotatedModuleIO, Block, ExprInInstantiatedModule, ExternModuleBody, InstantiatedModule,
|
||||
ModuleBody, ModuleIO, NormalModuleBody, Stmt, StmtConnect, StmtDeclaration, StmtFormal,
|
||||
StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule,
|
||||
},
|
||||
prelude::*,
|
||||
};
|
||||
use std::fmt;
|
||||
use std::{convert::Infallible, fmt};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DeduceResetsError {
|
||||
|
@ -40,18 +48,132 @@ impl From<DeduceResetsError> for std::io::Error {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
enum ResetTarget {
|
||||
Base {
|
||||
base: Interned<TargetBase>,
|
||||
},
|
||||
BundleField {
|
||||
parent: Interned<ResetTarget>,
|
||||
field_ty: CanonicalType,
|
||||
field_index: usize,
|
||||
},
|
||||
EnumVariant {
|
||||
parent: Interned<ResetTarget>,
|
||||
variant_ty: CanonicalType,
|
||||
variant_index: usize,
|
||||
},
|
||||
/// Array's Elements:
|
||||
/// deduce_resets requires all array elements to deduce to the same pattern of async/sync resets,
|
||||
/// so we don't track individual array elements but instead track all of an array's elements together.
|
||||
ArraysElements {
|
||||
parent: Interned<ResetTarget>,
|
||||
element_ty: CanonicalType,
|
||||
},
|
||||
}
|
||||
|
||||
impl ResetTarget {
|
||||
fn canonical_ty(self) -> CanonicalType {
|
||||
match self {
|
||||
ResetTarget::Base { base } => base.canonical_ty(),
|
||||
ResetTarget::BundleField { field_ty, .. } => field_ty,
|
||||
ResetTarget::EnumVariant { variant_ty, .. } => variant_ty,
|
||||
ResetTarget::ArraysElements { element_ty, .. } => element_ty,
|
||||
}
|
||||
}
|
||||
fn parent(self) -> Option<Interned<ResetTarget>> {
|
||||
match self {
|
||||
ResetTarget::Base { .. } => None,
|
||||
ResetTarget::BundleField { parent, .. }
|
||||
| ResetTarget::EnumVariant { parent, .. }
|
||||
| ResetTarget::ArraysElements { parent, .. } => Some(parent),
|
||||
}
|
||||
}
|
||||
fn base(mut self) -> Interned<TargetBase> {
|
||||
loop {
|
||||
match self {
|
||||
ResetTarget::Base { base } => break base,
|
||||
ResetTarget::BundleField { parent, .. }
|
||||
| ResetTarget::EnumVariant { parent, .. }
|
||||
| ResetTarget::ArraysElements { parent, .. } => self = *parent,
|
||||
}
|
||||
}
|
||||
}
|
||||
fn bundle_field(self, field_index: usize) -> Self {
|
||||
let field_ty = Bundle::from_canonical(self.canonical_ty()).fields()[field_index].ty;
|
||||
Self::BundleField {
|
||||
parent: self.intern_sized(),
|
||||
field_ty,
|
||||
field_index,
|
||||
}
|
||||
}
|
||||
fn enum_variant(self, variant_index: usize) -> Self {
|
||||
let variant_ty = Enum::from_canonical(self.canonical_ty()).variants()[variant_index]
|
||||
.ty
|
||||
.expect("known to have a variant field");
|
||||
Self::EnumVariant {
|
||||
parent: self.intern_sized(),
|
||||
variant_ty,
|
||||
variant_index,
|
||||
}
|
||||
}
|
||||
fn arrays_elements(self) -> Self {
|
||||
let element_ty = <Array>::from_canonical(self.canonical_ty()).element();
|
||||
Self::ArraysElements {
|
||||
parent: self.intern_sized(),
|
||||
element_ty,
|
||||
}
|
||||
}
|
||||
fn for_each_child<E>(self, mut f: impl FnMut(ResetTarget) -> Result<(), E>) -> Result<(), E> {
|
||||
match self.canonical_ty() {
|
||||
CanonicalType::UInt(_)
|
||||
| CanonicalType::SInt(_)
|
||||
| CanonicalType::Bool(_)
|
||||
| CanonicalType::AsyncReset(_)
|
||||
| CanonicalType::SyncReset(_)
|
||||
| CanonicalType::Reset(_)
|
||||
| CanonicalType::Clock(_) => Ok(()),
|
||||
CanonicalType::Array(_) => f(self.arrays_elements()),
|
||||
CanonicalType::Enum(ty) => {
|
||||
for variant_index in 0..ty.variants().len() {
|
||||
f(self.enum_variant(variant_index))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
CanonicalType::Bundle(ty) => {
|
||||
for field_index in 0..ty.fields().len() {
|
||||
f(self.bundle_field(field_index))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<TargetBase>> From<T> for ResetTarget {
|
||||
fn from(base: T) -> Self {
|
||||
ResetTarget::Base {
|
||||
base: TargetBase::intern_sized(base.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
struct ResetTargetInInstantiatedModule {
|
||||
instantiated_module: InstantiatedModule,
|
||||
target: ResetTarget,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Node {
|
||||
target: TargetInInstantiatedModule,
|
||||
target: ResetTargetInInstantiatedModule,
|
||||
deduced_type: Option<CanonicalType>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct State {
|
||||
base_module: Interned<Module<Bundle>>,
|
||||
transformed_exprs:
|
||||
HashMap<ExprInInstantiatedModule<CanonicalType>, ExprInInstantiatedModule<CanonicalType>>,
|
||||
node_ids: HashMap<TargetInInstantiatedModule, NodeIndex<u32>>,
|
||||
node_ids: HashMap<ResetTargetInInstantiatedModule, NodeIndex<u32>>,
|
||||
graph: UnGraph<Node, ()>,
|
||||
fallback_to_sync_reset: bool,
|
||||
}
|
||||
|
@ -89,88 +211,499 @@ fn type_contains_any_undeduced_resets(ty: CanonicalType) -> bool {
|
|||
MyMemoize.get_owned(ty)
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn add_target_to_graph_recursive(
|
||||
&mut self,
|
||||
target: TargetInInstantiatedModule,
|
||||
) -> NodeIndex<u32> {
|
||||
let entry = match self.node_ids.entry(target) {
|
||||
Entry::Vacant(entry) => entry,
|
||||
Entry::Occupied(entry) => {
|
||||
return *entry.get();
|
||||
}
|
||||
trait ProcessStep {
|
||||
type Error;
|
||||
type Processed<T>;
|
||||
fn processed_as_ref<T>(v: &Self::Processed<T>) -> Self::Processed<&T>;
|
||||
fn processed_as_mut<T>(v: &mut Self::Processed<T>) -> Self::Processed<&mut T>;
|
||||
fn processed_zip<T, U>(t: Self::Processed<T>, u: Self::Processed<U>)
|
||||
-> Self::Processed<(T, U)>;
|
||||
fn processed_map<T, U>(v: Self::Processed<T>, f: impl FnOnce(T) -> U) -> Self::Processed<U>;
|
||||
fn processed_make<T>(t: T) -> Self::Processed<T>;
|
||||
fn processed_from_iter<T, O: FromIterator<T>>(
|
||||
iter: impl IntoIterator<Item = Self::Processed<T>>,
|
||||
) -> Self::Processed<O>;
|
||||
}
|
||||
|
||||
macro_rules! impl_process_step_with_empty_processed {
|
||||
() => {
|
||||
type Processed<T> = ();
|
||||
fn processed_as_ref<T>(v: &Self::Processed<T>) -> Self::Processed<&T> {
|
||||
*v
|
||||
}
|
||||
fn processed_as_mut<T>(v: &mut Self::Processed<T>) -> Self::Processed<&mut T> {
|
||||
*v
|
||||
}
|
||||
fn processed_zip<T, U>(
|
||||
t: Self::Processed<T>,
|
||||
u: Self::Processed<U>,
|
||||
) -> Self::Processed<(T, U)> {
|
||||
let _ = t;
|
||||
let _ = u;
|
||||
()
|
||||
}
|
||||
fn processed_map<T, U>(
|
||||
v: Self::Processed<T>,
|
||||
f: impl FnOnce(T) -> U,
|
||||
) -> Self::Processed<U> {
|
||||
let _ = f;
|
||||
v
|
||||
}
|
||||
fn processed_make<T>(t: T) -> Self::Processed<T> {
|
||||
let _ = t;
|
||||
()
|
||||
}
|
||||
fn processed_from_iter<T, O: FromIterator<T>>(
|
||||
iter: impl IntoIterator<Item = Self::Processed<T>>,
|
||||
) -> Self::Processed<O> {
|
||||
FromIterator::from_iter(iter)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct Processed<T, Step: ProcessStep>(Step::Processed<T>);
|
||||
|
||||
impl<T, Step: ProcessStep> Processed<T, Step> {
|
||||
fn as_ref(&self) -> Processed<&T, Step> {
|
||||
Processed(Step::processed_as_ref(&self.0))
|
||||
}
|
||||
fn as_mut(&mut self) -> Processed<&mut T, Step> {
|
||||
Processed(Step::processed_as_mut(&mut self.0))
|
||||
}
|
||||
fn zip<U>(self, u: Processed<U, Step>) -> Processed<(T, U), Step> {
|
||||
Processed(Step::processed_zip(self.0, u.0))
|
||||
}
|
||||
fn new(v: T) -> Self {
|
||||
Processed(Step::processed_make(v))
|
||||
}
|
||||
fn map<U>(self, f: impl FnOnce(T) -> U) -> Processed<U, Step> {
|
||||
Processed(Step::processed_map(self.0, f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: FromIterator<A>, A, Step: ProcessStep> FromIterator<Processed<A, Step>>
|
||||
for Processed<C, Step>
|
||||
{
|
||||
fn from_iter<T: IntoIterator<Item = Processed<A, Step>>>(iter: T) -> Self {
|
||||
Processed(Step::processed_from_iter(iter.into_iter().map(|v| v.0)))
|
||||
}
|
||||
}
|
||||
|
||||
struct AddNodesToGraphStep;
|
||||
|
||||
impl ProcessStep for AddNodesToGraphStep {
|
||||
type Error = Infallible;
|
||||
impl_process_step_with_empty_processed!();
|
||||
}
|
||||
|
||||
struct AddEdgesToGraphStep {
|
||||
union_find: UnionFind<u32>,
|
||||
}
|
||||
|
||||
impl ProcessStep for AddEdgesToGraphStep {
|
||||
type Error = Infallible;
|
||||
impl_process_step_with_empty_processed!();
|
||||
}
|
||||
|
||||
trait RunProcessStep<Step: ProcessStep>: Sized {
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error>;
|
||||
}
|
||||
|
||||
impl RunProcessStep<AddNodesToGraphStep> for ResetTarget {
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut AddNodesToGraphStep,
|
||||
) -> Result<Processed<Self, AddNodesToGraphStep>, Infallible> {
|
||||
let target = ResetTargetInInstantiatedModule {
|
||||
instantiated_module,
|
||||
target: self,
|
||||
};
|
||||
let ty = target.target.canonical_ty();
|
||||
let node_id = self.graph.add_node(Node {
|
||||
let Entry::Vacant(entry) = state.node_ids.entry(target) else {
|
||||
return Ok(Processed(()));
|
||||
};
|
||||
let ty = self.canonical_ty();
|
||||
let node_id = state.graph.add_node(Node {
|
||||
target,
|
||||
deduced_type: type_contains_any_undeduced_resets(ty).then_some(ty),
|
||||
});
|
||||
entry.insert(node_id);
|
||||
match target.target.canonical_ty() {
|
||||
CanonicalType::UInt(_)
|
||||
| CanonicalType::SInt(_)
|
||||
| CanonicalType::Bool(_)
|
||||
| CanonicalType::AsyncReset(_)
|
||||
| CanonicalType::SyncReset(_)
|
||||
| CanonicalType::Clock(_) => {}
|
||||
CanonicalType::Array(ty) => {
|
||||
for index in 0..ty.len() {
|
||||
self.add_target_to_graph_recursive(TargetInInstantiatedModule {
|
||||
instantiated_module: target.instantiated_module,
|
||||
target: target.target.join(
|
||||
TargetPathElement::from(TargetPathArrayElement { index })
|
||||
.intern_sized(),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
CanonicalType::Enum(_) => {}
|
||||
CanonicalType::Bundle(ty) => {
|
||||
for BundleField { name, .. } in ty.fields() {
|
||||
self.add_target_to_graph_recursive(TargetInInstantiatedModule {
|
||||
instantiated_module: target.instantiated_module,
|
||||
target: target.target.join(
|
||||
TargetPathElement::from(TargetPathBundleField { name }).intern_sized(),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
CanonicalType::Reset(_) => {}
|
||||
}
|
||||
node_id
|
||||
self.for_each_child(|target| -> Result<(), Infallible> {
|
||||
target.run_process_step(instantiated_module, state, step)?;
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(Processed(()))
|
||||
}
|
||||
fn build_graph_for_module(&mut self, instantiated_module: Interned<InstantiatedModule>) {
|
||||
let Module {
|
||||
name: _,
|
||||
source_location: _,
|
||||
body,
|
||||
io_ty: _,
|
||||
module_io,
|
||||
module_annotations: _,
|
||||
} = *instantiated_module.leaf_module();
|
||||
for AnnotatedModuleIO {
|
||||
annotations: _,
|
||||
module_io,
|
||||
} in module_io
|
||||
{
|
||||
self.add_target_to_graph_recursive(TargetInInstantiatedModule {
|
||||
instantiated_module: *instantiated_module,
|
||||
target: module_io.into(),
|
||||
});
|
||||
}
|
||||
|
||||
struct ConnectAndLhsInstantiatedModule {
|
||||
lhs_instantiated_module: InstantiatedModule,
|
||||
lhs: Expr<CanonicalType>,
|
||||
rhs: Expr<CanonicalType>,
|
||||
source_location: SourceLocation,
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for ConnectAndLhsInstantiatedModule {
|
||||
fn run_process_step(
|
||||
self,
|
||||
rhs_instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
let Self {
|
||||
lhs_instantiated_module,
|
||||
lhs,
|
||||
rhs,
|
||||
source_location,
|
||||
} = self;
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtConnect {
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
let StmtConnect {
|
||||
lhs,
|
||||
rhs,
|
||||
source_location,
|
||||
} = self;
|
||||
Ok(ConnectAndLhsInstantiatedModule {
|
||||
lhs_instantiated_module: instantiated_module,
|
||||
lhs,
|
||||
rhs,
|
||||
source_location,
|
||||
}
|
||||
match body {
|
||||
ModuleBody::Normal(NormalModuleBody { body }) => todo!(),
|
||||
ModuleBody::Extern(ExternModuleBody {
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(
|
||||
|ConnectAndLhsInstantiatedModule {
|
||||
lhs_instantiated_module: _,
|
||||
lhs,
|
||||
rhs,
|
||||
source_location,
|
||||
}| StmtConnect {
|
||||
lhs,
|
||||
rhs,
|
||||
source_location,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtFormal {
|
||||
fn run_process_step(
|
||||
self,
|
||||
_instantiated_module: InstantiatedModule,
|
||||
_state: &mut State,
|
||||
_step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
// no inputs are Reset
|
||||
Ok(Processed::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtIf {
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtMatch {
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for ModuleIO<CanonicalType>
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
Ok(ResetTarget::from(self)
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(|target| {
|
||||
let ResetTarget::Base { base } = target else {
|
||||
unreachable!();
|
||||
};
|
||||
let TargetBase::ModuleIO(module_io) = *base else {
|
||||
unreachable!();
|
||||
};
|
||||
module_io
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtWire
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
let Self { annotations, wire } = self;
|
||||
Ok(ResetTarget::from(wire)
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(|target| {
|
||||
let ResetTarget::Base { base } = target else {
|
||||
unreachable!();
|
||||
};
|
||||
let TargetBase::Wire(wire) = *base else {
|
||||
unreachable!();
|
||||
};
|
||||
Self { annotations, wire }
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtReg
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
let Self { annotations, reg } = self;
|
||||
Ok(ResetTarget::from(reg)
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(|target| {
|
||||
let ResetTarget::Base { base } = target else {
|
||||
unreachable!();
|
||||
};
|
||||
let TargetBase::Reg(reg) = *base else {
|
||||
unreachable!();
|
||||
};
|
||||
Self { annotations, reg }
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtInstance
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
let Self {
|
||||
annotations,
|
||||
instance,
|
||||
} = self;
|
||||
let child_instantiated_module = InstantiatedModule::Child {
|
||||
parent: instantiated_module.intern_sized(),
|
||||
instance: instance.intern_sized(),
|
||||
};
|
||||
instance
|
||||
.instantiated()
|
||||
.run_process_step(child_instantiated_module, state, step)?;
|
||||
for (field_index, AnnotatedModuleIO { module_io, .. }) in
|
||||
instance.instantiated().module_io().into_iter().enumerate()
|
||||
{
|
||||
let (lhs_instantiated_module, lhs, rhs_instantiated_module, rhs) = match module_io
|
||||
.flow()
|
||||
{
|
||||
Flow::Source => {
|
||||
// connect to submodule's input from instance input
|
||||
(
|
||||
child_instantiated_module,
|
||||
module_io.to_expr(),
|
||||
instantiated_module,
|
||||
ops::FieldAccess::new_by_index(instance.to_expr(), field_index).to_expr(),
|
||||
)
|
||||
}
|
||||
Flow::Sink => {
|
||||
// connect to instance output from submodule's output
|
||||
(
|
||||
instantiated_module,
|
||||
ops::FieldAccess::new_by_index(instance.to_expr(), field_index).to_expr(),
|
||||
child_instantiated_module,
|
||||
module_io.to_expr(),
|
||||
)
|
||||
}
|
||||
Flow::Duplex => unreachable!(),
|
||||
};
|
||||
ConnectAndLhsInstantiatedModule {
|
||||
lhs_instantiated_module,
|
||||
lhs,
|
||||
rhs,
|
||||
source_location: instance.source_location(),
|
||||
}
|
||||
.run_process_step(rhs_instantiated_module, state, step)?;
|
||||
}
|
||||
Ok(ResetTarget::from(instance)
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(|target| {
|
||||
let ResetTarget::Base { base } = target else {
|
||||
unreachable!();
|
||||
};
|
||||
let TargetBase::Instance(instance) = *base else {
|
||||
unreachable!();
|
||||
};
|
||||
Self {
|
||||
annotations,
|
||||
instance,
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for StmtDeclaration
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
Ok(match self {
|
||||
StmtDeclaration::Wire(decl) => decl
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(StmtDeclaration::from),
|
||||
StmtDeclaration::Reg(decl) => decl
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(StmtDeclaration::from),
|
||||
StmtDeclaration::Instance(decl) => decl
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(StmtDeclaration::from),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for Stmt
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
Ok(match self {
|
||||
Stmt::Connect(stmt) => stmt
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(Stmt::from),
|
||||
Stmt::Formal(stmt) => stmt
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(Stmt::from),
|
||||
Stmt::If(stmt) => stmt
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(Stmt::from),
|
||||
Stmt::Match(stmt) => stmt
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(Stmt::from),
|
||||
Stmt::Declaration(stmt) => stmt
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(Stmt::from),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for Block
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
let Block { memories, stmts } = self;
|
||||
// memories and memory ports won't ever contain any Reset values,
|
||||
// so always just use the old `memories` value. we add the ports to the graph anyway to make the other logic easier.
|
||||
for memory in memories {
|
||||
for port in memory.ports() {
|
||||
ResetTarget::from(port).run_process_step(instantiated_module, state, step)?;
|
||||
}
|
||||
}
|
||||
let stmts = Result::<Processed<_, _>, _>::from_iter(
|
||||
stmts
|
||||
.iter()
|
||||
.map(|stmt| stmt.run_process_step(instantiated_module, state, step)),
|
||||
)?;
|
||||
Ok(stmts.map(|stmts| Block { memories, stmts }))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Step: ProcessStep> RunProcessStep<Step> for Module<Bundle>
|
||||
where
|
||||
ResetTarget: RunProcessStep<Step>,
|
||||
{
|
||||
fn run_process_step(
|
||||
self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
state: &mut State,
|
||||
step: &mut Step,
|
||||
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||
let module = *instantiated_module.leaf_module();
|
||||
let module_io =
|
||||
Result::<Processed<Interned<[_]>, _>, _>::from_iter(module.module_io().iter().map(
|
||||
|&AnnotatedModuleIO {
|
||||
annotations,
|
||||
module_io,
|
||||
}| {
|
||||
Ok(module_io
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(|module_io| AnnotatedModuleIO {
|
||||
annotations,
|
||||
module_io,
|
||||
}))
|
||||
},
|
||||
))?;
|
||||
let body = match module.body() {
|
||||
ModuleBody::Normal(NormalModuleBody { body }) => body
|
||||
.run_process_step(instantiated_module, state, step)?
|
||||
.map(|body| ModuleBody::Normal(NormalModuleBody { body })),
|
||||
body @ ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name: _,
|
||||
parameters: _,
|
||||
}) => {}
|
||||
}
|
||||
}
|
||||
fn deduce_types(&mut self) -> Result<(), DeduceResetsError> {
|
||||
todo!()
|
||||
}
|
||||
fn transform_module(&mut self, module: Interned<Module<Bundle>>) -> Interned<Module<Bundle>> {
|
||||
todo!()
|
||||
}) => Processed::new(body),
|
||||
};
|
||||
Ok(module_io.zip(body).map(|(module_io, body)| {
|
||||
Module::new_unchecked(
|
||||
module.name_id(),
|
||||
module.source_location(),
|
||||
body,
|
||||
module_io,
|
||||
module.module_annotations(),
|
||||
)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,12 +713,16 @@ pub fn deduce_resets(
|
|||
) -> Result<Interned<Module<Bundle>>, DeduceResetsError> {
|
||||
let mut state = State {
|
||||
base_module: module,
|
||||
transformed_exprs: HashMap::new(),
|
||||
node_ids: HashMap::new(),
|
||||
graph: UnGraph::new_undirected(),
|
||||
fallback_to_sync_reset,
|
||||
};
|
||||
state.build_graph_for_module(InstantiatedModule::Base(module).intern_sized());
|
||||
state.deduce_types()?;
|
||||
Ok(state.transform_module(module))
|
||||
let Ok(Processed(())) = module.run_process_step(
|
||||
InstantiatedModule::Base(module),
|
||||
&mut state,
|
||||
&mut AddNodesToGraphStep,
|
||||
);
|
||||
todo!("add edges");
|
||||
todo!("deduce types");
|
||||
Ok(todo!("transform module"))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue