forked from libre-chip/fayalite
		
	WIP working on implementing deduce_resets pass
This commit is contained in:
		
							parent
							
								
									913baa37e9
								
							
						
					
					
						commit
						59be3bd645
					
				
					 2 changed files with 637 additions and 88 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue