working on simulator
This commit is contained in:
		
							parent
							
								
									41ce9b3474
								
							
						
					
					
						commit
						96b3f1fee4
					
				
					 7 changed files with 1212 additions and 190 deletions
				
			
		
							
								
								
									
										7
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -319,6 +319,7 @@ dependencies = [ | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "tempfile", |  "tempfile", | ||||||
|  "trybuild", |  "trybuild", | ||||||
|  |  "vec_map", | ||||||
|  "which", |  "which", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | @ -720,6 +721,12 @@ version = "0.2.2" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "vec_map" | ||||||
|  | version = "0.8.2" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "version_check" | name = "version_check" | ||||||
| version = "0.9.4" | version = "0.9.4" | ||||||
|  |  | ||||||
|  | @ -39,4 +39,5 @@ syn = { version = "2.0.66", features = ["full", "fold", "visit", "extra-traits"] | ||||||
| tempfile = "3.10.1" | tempfile = "3.10.1" | ||||||
| thiserror = "1.0.61" | thiserror = "1.0.61" | ||||||
| trybuild = "1.0" | trybuild = "1.0" | ||||||
|  | vec_map = "0.8.2" | ||||||
| which = "6.0.1" | which = "6.0.1" | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ os_pipe.workspace = true | ||||||
| serde_json.workspace = true | serde_json.workspace = true | ||||||
| serde.workspace = true | serde.workspace = true | ||||||
| tempfile.workspace = true | tempfile.workspace = true | ||||||
|  | vec_map.workspace = true | ||||||
| which.workspace = true | which.workspace = true | ||||||
| 
 | 
 | ||||||
| [dev-dependencies] | [dev-dependencies] | ||||||
|  |  | ||||||
|  | @ -4,29 +4,28 @@ | ||||||
| //! Fayalite Simulation
 | //! Fayalite Simulation
 | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     bundle::{Bundle, BundleField, BundleType}, |     bundle::{BundleField, BundleType}, | ||||||
|     enum_::Enum, |  | ||||||
|     expr::{ |     expr::{ | ||||||
|         target::{ |         target::{ | ||||||
|             Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement, |             Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement, | ||||||
|         }, |         }, | ||||||
|         Expr, |         ExprEnum, | ||||||
|     }, |     }, | ||||||
|     int::Bool, |  | ||||||
|     intern::{Intern, Interned, Memoize}, |     intern::{Intern, Interned, Memoize}, | ||||||
|     module::{ |     module::{ | ||||||
|         AnnotatedModuleIO, Block, Instance, Module, ModuleBody, NormalModuleBody, Stmt, |         AnnotatedModuleIO, Block, ModuleBody, NormalModuleBody, Stmt, StmtConnect, StmtDeclaration, | ||||||
|         StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, |         StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire, | ||||||
|     }, |     }, | ||||||
|  |     prelude::*, | ||||||
|     sim::interpreter::{ |     sim::interpreter::{ | ||||||
|         Insn, Insns, InsnsBuilding, InsnsBuildingDone, SlotDebugData, StatePartLayout, TypeIndex, |         Insn, Insns, InsnsBuilding, InsnsBuildingDone, SlotDebugData, SmallUInt, StatePartIndex, | ||||||
|         TypeIndexRange, TypeLayout, |         StatePartIndexMap, StatePartKind, StatePartKindBigSlots, StatePartKindSmallSlots, | ||||||
|  |         StatePartLayout, StatePartLen, StatePartsValue, TypeIndex, TypeIndexRange, TypeLayout, | ||||||
|  |         TypeLen, TypeParts, MIN_BITS_FOR_NEEDING_BIG, | ||||||
|     }, |     }, | ||||||
|     source_location::SourceLocation, |  | ||||||
|     ty::CanonicalType, |  | ||||||
| }; | }; | ||||||
| use hashbrown::HashMap; | use hashbrown::HashMap; | ||||||
| use std::fmt; | use std::{fmt, marker::PhantomData, mem}; | ||||||
| 
 | 
 | ||||||
| mod interpreter; | mod interpreter; | ||||||
| 
 | 
 | ||||||
|  | @ -35,17 +34,17 @@ enum CondStack { | ||||||
|     Always, |     Always, | ||||||
|     IfTrue { |     IfTrue { | ||||||
|         parent: Interned<CondStack>, |         parent: Interned<CondStack>, | ||||||
|         cond: Expr<Bool>, |         cond: CompiledExpr<Bool>, | ||||||
|         source_location: SourceLocation, |         source_location: SourceLocation, | ||||||
|     }, |     }, | ||||||
|     IfFalse { |     IfFalse { | ||||||
|         parent: Interned<CondStack>, |         parent: Interned<CondStack>, | ||||||
|         cond: Expr<Bool>, |         cond: CompiledExpr<Bool>, | ||||||
|         source_location: SourceLocation, |         source_location: SourceLocation, | ||||||
|     }, |     }, | ||||||
|     MatchArm { |     MatchArm { | ||||||
|         parent: Interned<CondStack>, |         parent: Interned<CondStack>, | ||||||
|         enum_expr: Expr<Enum>, |         enum_expr: CompiledExpr<Enum>, | ||||||
|         variant_index: usize, |         variant_index: usize, | ||||||
|         source_location: SourceLocation, |         source_location: SourceLocation, | ||||||
|     }, |     }, | ||||||
|  | @ -95,7 +94,7 @@ struct TargetInInstantiatedModule { | ||||||
| #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | ||||||
| struct CompiledBundleField { | struct CompiledBundleField { | ||||||
|     offset: TypeIndex, |     offset: TypeIndex, | ||||||
|     ty: CompiledTypeLayout, |     ty: CompiledTypeLayout<CanonicalType>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | ||||||
|  | @ -103,7 +102,7 @@ enum CompiledTypeLayoutBody { | ||||||
|     Scalar, |     Scalar, | ||||||
|     Array { |     Array { | ||||||
|         /// debug names are ignored, use parent's layout instead
 |         /// debug names are ignored, use parent's layout instead
 | ||||||
|         element: Interned<CompiledTypeLayout>, |         element: Interned<CompiledTypeLayout<CanonicalType>>, | ||||||
|     }, |     }, | ||||||
|     Bundle { |     Bundle { | ||||||
|         /// debug names are ignored, use parent's layout instead
 |         /// debug names are ignored, use parent's layout instead
 | ||||||
|  | @ -112,13 +111,13 @@ enum CompiledTypeLayoutBody { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | ||||||
| struct CompiledTypeLayout { | struct CompiledTypeLayout<T: Type> { | ||||||
|     ty: CanonicalType, |     ty: T, | ||||||
|     layout: TypeLayout<InsnsBuildingDone>, |     layout: TypeLayout<InsnsBuildingDone>, | ||||||
|     body: CompiledTypeLayoutBody, |     body: CompiledTypeLayoutBody, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl CompiledTypeLayout { | impl<T: Type> CompiledTypeLayout<T> { | ||||||
|     fn with_prefixed_debug_names(self, prefix: &str) -> Self { |     fn with_prefixed_debug_names(self, prefix: &str) -> Self { | ||||||
|         let Self { ty, layout, body } = self; |         let Self { ty, layout, body } = self; | ||||||
|         Self { |         Self { | ||||||
|  | @ -127,13 +126,13 @@ impl CompiledTypeLayout { | ||||||
|             body, |             body, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     fn get(ty: CanonicalType) -> Self { |     fn get(ty: T) -> Self { | ||||||
|         #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |         #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | ||||||
|         struct MyMemoize; |         struct MyMemoize; | ||||||
|         impl Memoize for MyMemoize { |         impl Memoize for MyMemoize { | ||||||
|             type Input = CanonicalType; |             type Input = CanonicalType; | ||||||
|             type InputOwned = CanonicalType; |             type InputOwned = CanonicalType; | ||||||
|             type Output = CompiledTypeLayout; |             type Output = CompiledTypeLayout<CanonicalType>; | ||||||
| 
 | 
 | ||||||
|             fn inner(self, input: &Self::Input) -> Self::Output { |             fn inner(self, input: &Self::Input) -> Self::Output { | ||||||
|                 match input { |                 match input { | ||||||
|  | @ -146,8 +145,10 @@ impl CompiledTypeLayout { | ||||||
|                     | CanonicalType::Reset(_) |                     | CanonicalType::Reset(_) | ||||||
|                     | CanonicalType::Clock(_) => { |                     | CanonicalType::Clock(_) => { | ||||||
|                         let mut layout = TypeLayout::empty(); |                         let mut layout = TypeLayout::empty(); | ||||||
|                         let debug_data = SlotDebugData { name: "".intern() }; |                         let debug_data = SlotDebugData { | ||||||
|                         if input.bit_width() > interpreter::SmallUInt::BITS as usize { |                             name: Interned::default(), | ||||||
|  |                         }; | ||||||
|  |                         if input.bit_width() >= interpreter::MIN_BITS_FOR_NEEDING_BIG { | ||||||
|                             layout.big_slots = StatePartLayout::scalar(debug_data); |                             layout.big_slots = StatePartLayout::scalar(debug_data); | ||||||
|                         } else { |                         } else { | ||||||
|                             layout.small_slots = StatePartLayout::scalar(debug_data); |                             layout.small_slots = StatePartLayout::scalar(debug_data); | ||||||
|  | @ -205,24 +206,32 @@ impl CompiledTypeLayout { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         MyMemoize.get_owned(ty) |         let CompiledTypeLayout { | ||||||
|  |             ty: _, | ||||||
|  |             layout, | ||||||
|  |             body, | ||||||
|  |         } = MyMemoize.get_owned(ty.canonical()); | ||||||
|  |         Self { ty, layout, body } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] | ||||||
| struct CompiledValue { | struct CompiledValue<T: Type> { | ||||||
|     layout: CompiledTypeLayout, |     layout: CompiledTypeLayout<T>, | ||||||
|     range: TypeIndexRange, |     range: TypeIndexRange, | ||||||
|     write: Option<(CompiledTypeLayout, TypeIndexRange)>, |     write: Option<(CompiledTypeLayout<T>, TypeIndexRange)>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl CompiledValue { | impl<T: Type> CompiledValue<T> { | ||||||
|     fn map( |     fn map<U: Type>( | ||||||
|         self, |         self, | ||||||
|         mut f: impl FnMut(CompiledTypeLayout, TypeIndexRange) -> (CompiledTypeLayout, TypeIndexRange), |         mut f: impl FnMut( | ||||||
|     ) -> Self { |             CompiledTypeLayout<T>, | ||||||
|  |             TypeIndexRange, | ||||||
|  |         ) -> (CompiledTypeLayout<U>, TypeIndexRange), | ||||||
|  |     ) -> CompiledValue<U> { | ||||||
|         let (layout, range) = f(self.layout, self.range); |         let (layout, range) = f(self.layout, self.range); | ||||||
|         Self { |         CompiledValue { | ||||||
|             layout, |             layout, | ||||||
|             range, |             range, | ||||||
|             write: self.write.map(|(layout, range)| f(layout, range)), |             write: self.write.map(|(layout, range)| f(layout, range)), | ||||||
|  | @ -230,12 +239,98 @@ impl CompiledValue { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] | ||||||
|  | struct CompiledExprDynIndex { | ||||||
|  |     index_slot: StatePartIndex<StatePartKindSmallSlots>, | ||||||
|  |     len: TypeLen, | ||||||
|  |     stride: TypeLen, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] | ||||||
|  | struct CompiledExpr<T: Type> { | ||||||
|  |     static_part: CompiledValue<T>, | ||||||
|  |     dyn_indexes: Interned<[CompiledExprDynIndex]>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T: Type> From<CompiledValue<T>> for CompiledExpr<T> { | ||||||
|  |     fn from(static_part: CompiledValue<T>) -> Self { | ||||||
|  |         Self { | ||||||
|  |             static_part, | ||||||
|  |             dyn_indexes: Interned::default(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T: Type> CompiledExpr<T> { | ||||||
|  |     fn map_ty<U: Type>(self, mut f: impl FnMut(T) -> U) -> CompiledExpr<U> { | ||||||
|  |         let Self { | ||||||
|  |             static_part, | ||||||
|  |             dyn_indexes, | ||||||
|  |         } = self; | ||||||
|  |         CompiledExpr { | ||||||
|  |             static_part: static_part.map(|CompiledTypeLayout { ty, layout, body }, range| { | ||||||
|  |                 ( | ||||||
|  |                     CompiledTypeLayout { | ||||||
|  |                         ty: f(ty), | ||||||
|  |                         layout, | ||||||
|  |                         body, | ||||||
|  |                     }, | ||||||
|  |                     range, | ||||||
|  |                 ) | ||||||
|  |             }), | ||||||
|  |             dyn_indexes, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] | ||||||
|  | struct SlotSet(TypeParts<Self>); | ||||||
|  | 
 | ||||||
|  | impl SlotSet { | ||||||
|  |     fn is_empty(&self) -> bool { | ||||||
|  |         let Self(TypeParts { | ||||||
|  |             small_slots, | ||||||
|  |             big_slots, | ||||||
|  |         }) = self; | ||||||
|  |         small_slots.is_empty() && big_slots.is_empty() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl StatePartsValue for SlotSet { | ||||||
|  |     type Value<K: StatePartKind> = Vec<StatePartIndex<K>>; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct Assignment { | ||||||
|  |     inputs: SlotSet, | ||||||
|  |     insns: Vec<Insn>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Default)] | ||||||
|  | struct StatePartAssignments<K: StatePartKind> { | ||||||
|  |     written_slot_to_assignment_indexes_map: StatePartIndexMap<K, Vec<usize>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Default)] | ||||||
|  | struct SlotAssignments { | ||||||
|  |     assignments: Vec<Assignment>, | ||||||
|  |     parts: TypeParts<Self>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl StatePartsValue for SlotAssignments { | ||||||
|  |     type Value<K: StatePartKind> = StatePartAssignments<K>; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct Compiler { | pub struct Compiler { | ||||||
|     insns: Insns<InsnsBuilding>, |     insns: Insns<InsnsBuilding>, | ||||||
|     base_module: Interned<Module<Bundle>>, |     base_module: Interned<Module<Bundle>>, | ||||||
|     modules: HashMap<InstantiatedModule, CompiledModule>, |     modules: HashMap<InstantiatedModule, CompiledModule>, | ||||||
|     compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue>, |     compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue<CanonicalType>>, | ||||||
|  |     compiled_exprs: HashMap<Expr<CanonicalType>, CompiledExpr<CanonicalType>>, | ||||||
|  |     compiled_exprs_to_values: HashMap<CompiledExpr<CanonicalType>, CompiledValue<CanonicalType>>, | ||||||
|  |     expanded_to_big: HashMap<Expr<CanonicalType>, CompiledValue<CanonicalType>>, | ||||||
|  |     slots_assignments: SlotAssignments, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Compiler { | impl Compiler { | ||||||
|  | @ -245,13 +340,20 @@ impl Compiler { | ||||||
|             base_module, |             base_module, | ||||||
|             modules: HashMap::new(), |             modules: HashMap::new(), | ||||||
|             compiled_values: HashMap::new(), |             compiled_values: HashMap::new(), | ||||||
|  |             compiled_exprs: HashMap::new(), | ||||||
|  |             compiled_exprs_to_values: HashMap::new(), | ||||||
|  |             expanded_to_big: HashMap::new(), | ||||||
|  |             slots_assignments: SlotAssignments::default(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     fn compile_value(&mut self, target: TargetInInstantiatedModule) -> CompiledValue { |     fn compile_value( | ||||||
|  |         &mut self, | ||||||
|  |         target: TargetInInstantiatedModule, | ||||||
|  |     ) -> CompiledValue<CanonicalType> { | ||||||
|         if let Some(&retval) = self.compiled_values.get(&target) { |         if let Some(&retval) = self.compiled_values.get(&target) { | ||||||
|             return retval; |             return retval; | ||||||
|         } |         } | ||||||
|         match target.target { |         let retval = match target.target { | ||||||
|             Target::Base(base) => { |             Target::Base(base) => { | ||||||
|                 let unprefixed_layout = CompiledTypeLayout::get(base.canonical_ty()); |                 let unprefixed_layout = CompiledTypeLayout::get(base.canonical_ty()); | ||||||
|                 let layout = unprefixed_layout.with_prefixed_debug_names(&format!( |                 let layout = unprefixed_layout.with_prefixed_debug_names(&format!( | ||||||
|  | @ -319,7 +421,494 @@ impl Compiler { | ||||||
|                     TargetPathElement::DynArrayElement(_) => unreachable!(), |                     TargetPathElement::DynArrayElement(_) => unreachable!(), | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         }; | ||||||
|  |         self.compiled_values.insert(target, retval); | ||||||
|  |         retval | ||||||
|     } |     } | ||||||
|  |     fn compiled_expr_to_value( | ||||||
|  |         &mut self, | ||||||
|  |         expr: CompiledExpr<CanonicalType>, | ||||||
|  |     ) -> CompiledValue<CanonicalType> { | ||||||
|  |         if let Some(&retval) = self.compiled_exprs_to_values.get(&expr) { | ||||||
|  |             return retval; | ||||||
|  |         } | ||||||
|  |         let CompiledExpr { | ||||||
|  |             static_part: mut retval, | ||||||
|  |             dyn_indexes, | ||||||
|  |         } = expr; | ||||||
|  |         for CompiledExprDynIndex { | ||||||
|  |             index_slot, | ||||||
|  |             len, | ||||||
|  |             stride, | ||||||
|  |         } in dyn_indexes | ||||||
|  |         { | ||||||
|  |             todo!(); | ||||||
|  |         } | ||||||
|  |         self.compiled_exprs_to_values.insert(expr, retval); | ||||||
|  |         retval | ||||||
|  |     } | ||||||
|  |     fn simple_nary_expr<const N: usize>( | ||||||
|  |         &mut self, | ||||||
|  |         dest_ty: CanonicalType, | ||||||
|  |         inputs: [Expr<CanonicalType>; N], | ||||||
|  |         make_insns: impl FnOnce( | ||||||
|  |             &mut Self, | ||||||
|  |             CompiledValue<CanonicalType>, | ||||||
|  |             &mut [CompiledValue<CanonicalType>; N], | ||||||
|  |         ) -> Vec<Insn>, | ||||||
|  |     ) -> CompiledValue<CanonicalType> { | ||||||
|  |         let mut inputs = inputs.map(|input| { | ||||||
|  |             let input = self.compile_expr(input); | ||||||
|  |             self.compiled_expr_to_value(input) | ||||||
|  |         }); | ||||||
|  |         let layout = CompiledTypeLayout::get(dest_ty); | ||||||
|  |         let range = self.insns.allocate_variable(&layout.layout); | ||||||
|  |         let retval = CompiledValue { | ||||||
|  |             layout, | ||||||
|  |             range, | ||||||
|  |             write: None, | ||||||
|  |         }; | ||||||
|  |         let insns = make_insns(self, retval, &mut inputs); | ||||||
|  |         let mut inputs_set = SlotSet::default(); | ||||||
|  |         for input in inputs { | ||||||
|  |             let TypeIndexRange { | ||||||
|  |                 small_slots, | ||||||
|  |                 big_slots, | ||||||
|  |             } = input.range; | ||||||
|  |             inputs_set.0.small_slots.extend(small_slots.iter()); | ||||||
|  |             inputs_set.0.big_slots.extend(big_slots.iter()); | ||||||
|  |         } | ||||||
|  |         let assignment_index = self.slots_assignments.assignments.len(); | ||||||
|  |         self.slots_assignments.assignments.push(Assignment { | ||||||
|  |             inputs: inputs_set, | ||||||
|  |             insns, | ||||||
|  |         }); | ||||||
|  |         let TypeIndexRange { | ||||||
|  |             small_slots, | ||||||
|  |             big_slots, | ||||||
|  |         } = range; | ||||||
|  |         for i in small_slots.iter() { | ||||||
|  |             self.slots_assignments | ||||||
|  |                 .parts | ||||||
|  |                 .small_slots | ||||||
|  |                 .written_slot_to_assignment_indexes_map | ||||||
|  |                 .entry(i) | ||||||
|  |                 .or_insert_with(Vec::new) | ||||||
|  |                 .push(assignment_index); | ||||||
|  |         } | ||||||
|  |         for i in big_slots.iter() { | ||||||
|  |             self.slots_assignments | ||||||
|  |                 .parts | ||||||
|  |                 .big_slots | ||||||
|  |                 .written_slot_to_assignment_indexes_map | ||||||
|  |                 .entry(i) | ||||||
|  |                 .or_insert_with(Vec::new) | ||||||
|  |                 .push(assignment_index); | ||||||
|  |         } | ||||||
|  |         retval | ||||||
|  |     } | ||||||
|  |     fn expand_to_big(&mut self, expr: Expr<CanonicalType>) -> CompiledValue<CanonicalType> { | ||||||
|  |         if let Some(&retval) = self.expanded_to_big.get(&expr) { | ||||||
|  |             return retval; | ||||||
|  |         } | ||||||
|  |         let input = self.compile_expr(expr); | ||||||
|  |         let input = self.compiled_expr_to_value(input); | ||||||
|  |         let retval = match input.range.len() { | ||||||
|  |             TypeLen { | ||||||
|  |                 small_slots: | ||||||
|  |                     StatePartLen { | ||||||
|  |                         value: 0, | ||||||
|  |                         _phantom: _, | ||||||
|  |                     }, | ||||||
|  |                 big_slots: _, | ||||||
|  |             } => input, | ||||||
|  |             len => { | ||||||
|  |                 assert_eq!( | ||||||
|  |                     Some(StatePartLen { | ||||||
|  |                         value: 1, | ||||||
|  |                         _phantom: PhantomData, | ||||||
|  |                     }), | ||||||
|  |                     len.only_small() | ||||||
|  |                 ); | ||||||
|  |                 let signed = match Expr::ty(expr) { | ||||||
|  |                     CanonicalType::UInt(_) => false, | ||||||
|  |                     CanonicalType::SInt(_) => true, | ||||||
|  |                     CanonicalType::Bool(_) => false, | ||||||
|  |                     CanonicalType::Enum(_) => false, | ||||||
|  |                     CanonicalType::Array(_) => unreachable!(), | ||||||
|  |                     CanonicalType::Bundle(_) => unreachable!(), | ||||||
|  |                     CanonicalType::AsyncReset(_) => false, | ||||||
|  |                     CanonicalType::SyncReset(_) => false, | ||||||
|  |                     CanonicalType::Reset(_) => false, | ||||||
|  |                     CanonicalType::Clock(_) => false, | ||||||
|  |                 }; | ||||||
|  |                 self.simple_nary_expr( | ||||||
|  |                     if signed { | ||||||
|  |                         SInt::new_dyn(MIN_BITS_FOR_NEEDING_BIG).canonical() | ||||||
|  |                     } else { | ||||||
|  |                         UInt::new_dyn(MIN_BITS_FOR_NEEDING_BIG).canonical() | ||||||
|  |                     }, | ||||||
|  |                     [expr], | ||||||
|  |                     |_this, dest, [input]| { | ||||||
|  |                         let dest = dest.range.big_slots.start; | ||||||
|  |                         let src = input.range.small_slots.start; | ||||||
|  |                         let unused_bit_count = | ||||||
|  |                             interpreter::SmallUInt::BITS as u8 - Expr::ty(expr).bit_width() as u8; | ||||||
|  |                         if signed { | ||||||
|  |                             vec![Insn::SExtSmallToBig { | ||||||
|  |                                 dest, | ||||||
|  |                                 src, | ||||||
|  |                                 unused_bit_count, | ||||||
|  |                             }] | ||||||
|  |                         } else { | ||||||
|  |                             vec![Insn::ZExtSmallToBig { | ||||||
|  |                                 dest, | ||||||
|  |                                 src, | ||||||
|  |                                 unused_bit_count, | ||||||
|  |                             }] | ||||||
|  |                         } | ||||||
|  |                     }, | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         self.expanded_to_big.insert(expr, retval); | ||||||
|  |         retval | ||||||
|  |     } | ||||||
|  |     fn simple_nary_small_or_big_expr<const N: usize>( | ||||||
|  |         &mut self, | ||||||
|  |         dest_ty: CanonicalType, | ||||||
|  |         inputs: [Expr<CanonicalType>; N], | ||||||
|  |         make_insns_small: impl FnOnce( | ||||||
|  |             StatePartIndex<StatePartKindSmallSlots>, | ||||||
|  |             [StatePartIndex<StatePartKindSmallSlots>; N], | ||||||
|  |         ) -> Vec<Insn>, | ||||||
|  |         make_insns_big: impl FnOnce( | ||||||
|  |             StatePartIndex<StatePartKindBigSlots>, | ||||||
|  |             [StatePartIndex<StatePartKindBigSlots>; N], | ||||||
|  |         ) -> Vec<Insn>, | ||||||
|  |         make_insns_big_to_small: impl FnOnce( | ||||||
|  |             StatePartIndex<StatePartKindSmallSlots>, | ||||||
|  |             [StatePartIndex<StatePartKindBigSlots>; N], | ||||||
|  |         ) -> Vec<Insn>, | ||||||
|  |     ) -> CompiledValue<CanonicalType> { | ||||||
|  |         self.simple_nary_expr(dest_ty, inputs, |this, dest, compiled_inputs| { | ||||||
|  |             let all_inputs_only_small = compiled_inputs | ||||||
|  |                 .iter() | ||||||
|  |                 .all(|input| input.range.len().only_small().is_some()); | ||||||
|  |             if all_inputs_only_small { | ||||||
|  |                 if dest.range.len().only_small().is_some() { | ||||||
|  |                     // all small
 | ||||||
|  |                     assert_eq!(dest.range.len().small_slots.value, 1); | ||||||
|  |                     return make_insns_small( | ||||||
|  |                         dest.range.small_slots.start, | ||||||
|  |                         compiled_inputs.map( | ||||||
|  |                             |CompiledValue { | ||||||
|  |                                  layout, | ||||||
|  |                                  range, | ||||||
|  |                                  write: _, | ||||||
|  |                              }| { | ||||||
|  |                                 assert_eq!(range.small_slots.len().value, 1); | ||||||
|  |                                 range.small_slots.start | ||||||
|  |                             }, | ||||||
|  |                         ), | ||||||
|  |                     ); | ||||||
|  |                 } else { | ||||||
|  |                     // inputs small, dest big -- expand inputs to big
 | ||||||
|  |                     for (&input, compiled_input) in inputs.iter().zip(&mut *compiled_inputs) { | ||||||
|  |                         *compiled_input = this.expand_to_big(input); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             let big_inputs = compiled_inputs.map( | ||||||
|  |                 |CompiledValue { | ||||||
|  |                      layout, | ||||||
|  |                      range: | ||||||
|  |                          TypeIndexRange { | ||||||
|  |                              small_slots, | ||||||
|  |                              big_slots, | ||||||
|  |                          }, | ||||||
|  |                      write: _, | ||||||
|  |                  }| { | ||||||
|  |                     assert_eq!(small_slots.len().value, 0); | ||||||
|  |                     assert_eq!(big_slots.len().value, 1); | ||||||
|  |                     big_slots.start | ||||||
|  |                 }, | ||||||
|  |             ); | ||||||
|  |             if dest.range.len().only_small().is_some() { | ||||||
|  |                 // inputs big, dest small
 | ||||||
|  |                 assert_eq!(dest.range.len().small_slots.value, 1); | ||||||
|  |                 return make_insns_big_to_small(dest.range.small_slots.start, big_inputs); | ||||||
|  |             } | ||||||
|  |             let TypeIndexRange { | ||||||
|  |                 small_slots, | ||||||
|  |                 big_slots, | ||||||
|  |             } = dest.range; | ||||||
|  |             assert_eq!(small_slots.len().value, 0); | ||||||
|  |             assert_eq!(big_slots.len().value, 1); | ||||||
|  |             make_insns_big(big_slots.start, big_inputs) | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |     fn compile_expr(&mut self, expr: Expr<CanonicalType>) -> CompiledExpr<CanonicalType> { | ||||||
|  |         if let Some(&retval) = self.compiled_exprs.get(&expr) { | ||||||
|  |             return retval; | ||||||
|  |         } | ||||||
|  |         let retval: CompiledExpr<_> = match *Expr::expr_enum(expr) { | ||||||
|  |             ExprEnum::UIntLiteral(expr) => self | ||||||
|  |                 .simple_nary_small_or_big_expr( | ||||||
|  |                     Bool.canonical(), | ||||||
|  |                     [], | ||||||
|  |                     |dest, []| { | ||||||
|  |                         vec![Insn::ConstSmall { | ||||||
|  |                             dest, | ||||||
|  |                             value: expr.to_bigint().try_into().expect("const too big"), | ||||||
|  |                         }] | ||||||
|  |                     }, | ||||||
|  |                     |dest, []| { | ||||||
|  |                         vec![Insn::ConstBig { | ||||||
|  |                             dest, | ||||||
|  |                             value: expr.to_bigint().intern_sized(), | ||||||
|  |                         }] | ||||||
|  |                     }, | ||||||
|  |                     |_, _| unreachable!(), | ||||||
|  |                 ) | ||||||
|  |                 .into(), | ||||||
|  |             ExprEnum::SIntLiteral(expr) => self | ||||||
|  |                 .simple_nary_small_or_big_expr( | ||||||
|  |                     Bool.canonical(), | ||||||
|  |                     [], | ||||||
|  |                     |dest, []| { | ||||||
|  |                         vec![Insn::ConstSmall { | ||||||
|  |                             dest, | ||||||
|  |                             value: expr.to_bigint().try_into().expect("const too big"), | ||||||
|  |                         }] | ||||||
|  |                     }, | ||||||
|  |                     |dest, []| { | ||||||
|  |                         vec![Insn::ConstBig { | ||||||
|  |                             dest, | ||||||
|  |                             value: expr.to_bigint().intern_sized(), | ||||||
|  |                         }] | ||||||
|  |                     }, | ||||||
|  |                     |_, _| unreachable!(), | ||||||
|  |                 ) | ||||||
|  |                 .into(), | ||||||
|  |             ExprEnum::BoolLiteral(expr) => self | ||||||
|  |                 .simple_nary_small_or_big_expr( | ||||||
|  |                     Bool.canonical(), | ||||||
|  |                     [], | ||||||
|  |                     |dest, []| { | ||||||
|  |                         vec![Insn::ConstSmall { | ||||||
|  |                             dest, | ||||||
|  |                             value: expr as SmallUInt, | ||||||
|  |                         }] | ||||||
|  |                     }, | ||||||
|  |                     |_, _| unreachable!(), | ||||||
|  |                     |_, _| unreachable!(), | ||||||
|  |                 ) | ||||||
|  |                 .into(), | ||||||
|  |             ExprEnum::BundleLiteral(expr) => todo!(), | ||||||
|  |             ExprEnum::ArrayLiteral(expr) => todo!(), | ||||||
|  |             ExprEnum::EnumLiteral(expr) => todo!(), | ||||||
|  |             ExprEnum::Uninit(expr) => todo!(), | ||||||
|  |             ExprEnum::NotU(expr) => todo!(), | ||||||
|  |             ExprEnum::NotS(expr) => todo!(), | ||||||
|  |             ExprEnum::NotB(expr) => todo!(), | ||||||
|  |             ExprEnum::Neg(expr) => self | ||||||
|  |                 .simple_nary_small_or_big_expr( | ||||||
|  |                     expr.ty().canonical(), | ||||||
|  |                     [Expr::canonical(expr.arg())], | ||||||
|  |                     |dest, [src]| vec![Insn::NegSmall { dest, src }], | ||||||
|  |                     |dest, [src]| vec![Insn::NegBig { dest, src }], | ||||||
|  |                     |_, _| unreachable!(), | ||||||
|  |                 ) | ||||||
|  |                 .into(), | ||||||
|  |             ExprEnum::BitAndU(expr) => todo!(), | ||||||
|  |             ExprEnum::BitAndS(expr) => todo!(), | ||||||
|  |             ExprEnum::BitAndB(expr) => todo!(), | ||||||
|  |             ExprEnum::BitOrU(expr) => todo!(), | ||||||
|  |             ExprEnum::BitOrS(expr) => todo!(), | ||||||
|  |             ExprEnum::BitOrB(expr) => todo!(), | ||||||
|  |             ExprEnum::BitXorU(expr) => todo!(), | ||||||
|  |             ExprEnum::BitXorS(expr) => todo!(), | ||||||
|  |             ExprEnum::BitXorB(expr) => todo!(), | ||||||
|  |             ExprEnum::AddU(expr) => todo!(), | ||||||
|  |             ExprEnum::AddS(expr) => todo!(), | ||||||
|  |             ExprEnum::SubU(expr) => todo!(), | ||||||
|  |             ExprEnum::SubS(expr) => todo!(), | ||||||
|  |             ExprEnum::MulU(expr) => todo!(), | ||||||
|  |             ExprEnum::MulS(expr) => todo!(), | ||||||
|  |             ExprEnum::DivU(expr) => todo!(), | ||||||
|  |             ExprEnum::DivS(expr) => todo!(), | ||||||
|  |             ExprEnum::RemU(expr) => todo!(), | ||||||
|  |             ExprEnum::RemS(expr) => todo!(), | ||||||
|  |             ExprEnum::DynShlU(expr) => todo!(), | ||||||
|  |             ExprEnum::DynShlS(expr) => todo!(), | ||||||
|  |             ExprEnum::DynShrU(expr) => todo!(), | ||||||
|  |             ExprEnum::DynShrS(expr) => todo!(), | ||||||
|  |             ExprEnum::FixedShlU(expr) => todo!(), | ||||||
|  |             ExprEnum::FixedShlS(expr) => todo!(), | ||||||
|  |             ExprEnum::FixedShrU(expr) => todo!(), | ||||||
|  |             ExprEnum::FixedShrS(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpLtB(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpLeB(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpGtB(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpGeB(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpEqB(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpNeB(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpLtU(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpLeU(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpGtU(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpGeU(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpEqU(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpNeU(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpLtS(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpLeS(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpGtS(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpGeS(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpEqS(expr) => todo!(), | ||||||
|  |             ExprEnum::CmpNeS(expr) => todo!(), | ||||||
|  |             ExprEnum::CastUIntToUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastUIntToSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSIntToUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSIntToSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastBoolToUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastBoolToSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastUIntToBool(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSIntToBool(expr) => todo!(), | ||||||
|  |             ExprEnum::CastBoolToSyncReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastUIntToSyncReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSIntToSyncReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastBoolToAsyncReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastUIntToAsyncReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSIntToAsyncReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSyncResetToBool(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSyncResetToUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSyncResetToSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSyncResetToReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastAsyncResetToBool(expr) => todo!(), | ||||||
|  |             ExprEnum::CastAsyncResetToUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastAsyncResetToSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastAsyncResetToReset(expr) => todo!(), | ||||||
|  |             ExprEnum::CastResetToBool(expr) => todo!(), | ||||||
|  |             ExprEnum::CastResetToUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastResetToSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastBoolToClock(expr) => todo!(), | ||||||
|  |             ExprEnum::CastUIntToClock(expr) => todo!(), | ||||||
|  |             ExprEnum::CastSIntToClock(expr) => todo!(), | ||||||
|  |             ExprEnum::CastClockToBool(expr) => todo!(), | ||||||
|  |             ExprEnum::CastClockToUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastClockToSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::FieldAccess(expr) => todo!(), | ||||||
|  |             ExprEnum::VariantAccess(expr) => todo!(), | ||||||
|  |             ExprEnum::ArrayIndex(expr) => todo!(), | ||||||
|  |             ExprEnum::DynArrayIndex(expr) => todo!(), | ||||||
|  |             ExprEnum::ReduceBitAndU(expr) => todo!(), | ||||||
|  |             ExprEnum::ReduceBitAndS(expr) => todo!(), | ||||||
|  |             ExprEnum::ReduceBitOrU(expr) => todo!(), | ||||||
|  |             ExprEnum::ReduceBitOrS(expr) => todo!(), | ||||||
|  |             ExprEnum::ReduceBitXorU(expr) => todo!(), | ||||||
|  |             ExprEnum::ReduceBitXorS(expr) => todo!(), | ||||||
|  |             ExprEnum::SliceUInt(expr) => todo!(), | ||||||
|  |             ExprEnum::SliceSInt(expr) => todo!(), | ||||||
|  |             ExprEnum::CastToBits(expr) => todo!(), | ||||||
|  |             ExprEnum::CastBitsTo(expr) => todo!(), | ||||||
|  |             ExprEnum::ModuleIO(expr) => todo!(), | ||||||
|  |             ExprEnum::Instance(expr) => todo!(), | ||||||
|  |             ExprEnum::Wire(expr) => todo!(), | ||||||
|  |             ExprEnum::Reg(expr) => todo!(), | ||||||
|  |             ExprEnum::MemPort(expr) => todo!(), | ||||||
|  |         }; | ||||||
|  |         self.compiled_exprs.insert(expr, retval); | ||||||
|  |         retval | ||||||
|  |     } | ||||||
|  |     fn compile_connect( | ||||||
|  |         &mut self, | ||||||
|  |         parent_module: Interned<InstantiatedModule>, | ||||||
|  |         cond_stack: Interned<CondStack>, | ||||||
|  |         lhs: Expr<CanonicalType>, | ||||||
|  |         mut rhs: Expr<CanonicalType>, | ||||||
|  |         source_location: SourceLocation, | ||||||
|  |     ) { | ||||||
|  |         if Expr::ty(lhs) != Expr::ty(rhs) || !Expr::ty(lhs).is_passive() { | ||||||
|  |             match Expr::ty(lhs) { | ||||||
|  |                 CanonicalType::UInt(lhs_ty) => { | ||||||
|  |                     rhs = Expr::canonical(Expr::<UInt>::from_canonical(rhs).cast_to(lhs_ty)); | ||||||
|  |                 } | ||||||
|  |                 CanonicalType::SInt(lhs_ty) => { | ||||||
|  |                     rhs = Expr::canonical(Expr::<SInt>::from_canonical(rhs).cast_to(lhs_ty)); | ||||||
|  |                 } | ||||||
|  |                 CanonicalType::Bool(_) => unreachable!(), | ||||||
|  |                 CanonicalType::Array(lhs_ty) => { | ||||||
|  |                     let CanonicalType::Array(rhs_ty) = Expr::ty(rhs) else { | ||||||
|  |                         unreachable!(); | ||||||
|  |                     }; | ||||||
|  |                     assert_eq!(lhs_ty.len(), rhs_ty.len()); | ||||||
|  |                     let lhs = Expr::<Array>::from_canonical(lhs); | ||||||
|  |                     let rhs = Expr::<Array>::from_canonical(rhs); | ||||||
|  |                     for index in 0..lhs_ty.len() { | ||||||
|  |                         self.compile_connect( | ||||||
|  |                             parent_module, | ||||||
|  |                             cond_stack, | ||||||
|  |                             lhs[index], | ||||||
|  |                             rhs[index], | ||||||
|  |                             source_location, | ||||||
|  |                         ); | ||||||
|  |                     } | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 CanonicalType::Enum(lhs_ty) => { | ||||||
|  |                     let CanonicalType::Enum(rhs_ty) = Expr::ty(rhs) else { | ||||||
|  |                         unreachable!(); | ||||||
|  |                     }; | ||||||
|  |                     todo!("handle connect with different enum types"); | ||||||
|  |                 } | ||||||
|  |                 CanonicalType::Bundle(lhs_ty) => { | ||||||
|  |                     let CanonicalType::Bundle(rhs_ty) = Expr::ty(rhs) else { | ||||||
|  |                         unreachable!(); | ||||||
|  |                     }; | ||||||
|  |                     assert_eq!(lhs_ty.fields().len(), rhs_ty.fields().len()); | ||||||
|  |                     let lhs = Expr::<Bundle>::from_canonical(lhs); | ||||||
|  |                     let rhs = Expr::<Bundle>::from_canonical(rhs); | ||||||
|  |                     for ( | ||||||
|  |                         field_index, | ||||||
|  |                         ( | ||||||
|  |                             BundleField { | ||||||
|  |                                 name, | ||||||
|  |                                 flipped, | ||||||
|  |                                 ty: _, | ||||||
|  |                             }, | ||||||
|  |                             rhs_field, | ||||||
|  |                         ), | ||||||
|  |                     ) in lhs_ty.fields().into_iter().zip(rhs_ty.fields()).enumerate() | ||||||
|  |                     { | ||||||
|  |                         assert_eq!(name, rhs_field.name); | ||||||
|  |                         assert_eq!(flipped, rhs_field.flipped); | ||||||
|  |                         let mut lhs_expr = | ||||||
|  |                             crate::expr::ops::FieldAccess::new_by_index(lhs, field_index).to_expr(); | ||||||
|  |                         let mut rhs_expr = | ||||||
|  |                             crate::expr::ops::FieldAccess::new_by_index(rhs, field_index).to_expr(); | ||||||
|  |                         if flipped { | ||||||
|  |                             mem::swap(&mut lhs_expr, &mut rhs_expr); | ||||||
|  |                         } | ||||||
|  |                         self.compile_connect( | ||||||
|  |                             parent_module, | ||||||
|  |                             cond_stack, | ||||||
|  |                             lhs_expr, | ||||||
|  |                             rhs_expr, | ||||||
|  |                             source_location, | ||||||
|  |                         ); | ||||||
|  |                     } | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 CanonicalType::AsyncReset(_) => unreachable!(), | ||||||
|  |                 CanonicalType::SyncReset(_) => unreachable!(), | ||||||
|  |                 CanonicalType::Reset(_) => unreachable!(), | ||||||
|  |                 CanonicalType::Clock(_) => unreachable!(), | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         let lhs = self.compile_expr(lhs); | ||||||
|  |         let rhs = self.compile_expr(rhs); | ||||||
|  |         let rhs = self.compiled_expr_to_value(rhs); | ||||||
|  |         todo!(); | ||||||
|     } |     } | ||||||
|     fn compile_block( |     fn compile_block( | ||||||
|         &mut self, |         &mut self, | ||||||
|  | @ -337,7 +926,7 @@ impl Compiler { | ||||||
|                     lhs, |                     lhs, | ||||||
|                     rhs, |                     rhs, | ||||||
|                     source_location, |                     source_location, | ||||||
|                 }) => todo!(), |                 }) => self.compile_connect(parent_module, cond_stack, lhs, rhs, source_location), | ||||||
|                 Stmt::Formal(StmtFormal { |                 Stmt::Formal(StmtFormal { | ||||||
|                     kind, |                     kind, | ||||||
|                     clk, |                     clk, | ||||||
|  | @ -351,6 +940,9 @@ impl Compiler { | ||||||
|                     source_location, |                     source_location, | ||||||
|                     blocks: [then_block, else_block], |                     blocks: [then_block, else_block], | ||||||
|                 }) => { |                 }) => { | ||||||
|  |                     let cond = self | ||||||
|  |                         .compile_expr(Expr::canonical(cond)) | ||||||
|  |                         .map_ty(Bool::from_canonical); | ||||||
|                     self.compile_block( |                     self.compile_block( | ||||||
|                         parent_module, |                         parent_module, | ||||||
|                         then_block, |                         then_block, | ||||||
|  | @ -377,13 +969,16 @@ impl Compiler { | ||||||
|                     source_location, |                     source_location, | ||||||
|                     blocks, |                     blocks, | ||||||
|                 }) => { |                 }) => { | ||||||
|  |                     let enum_expr = self | ||||||
|  |                         .compile_expr(Expr::canonical(expr)) | ||||||
|  |                         .map_ty(Enum::from_canonical); | ||||||
|                     for (variant_index, block) in blocks.into_iter().enumerate() { |                     for (variant_index, block) in blocks.into_iter().enumerate() { | ||||||
|                         self.compile_block( |                         self.compile_block( | ||||||
|                             parent_module, |                             parent_module, | ||||||
|                             block, |                             block, | ||||||
|                             CondStack::MatchArm { |                             CondStack::MatchArm { | ||||||
|                                 parent: cond_stack, |                                 parent: cond_stack, | ||||||
|                                 enum_expr: expr, |                                 enum_expr, | ||||||
|                                 variant_index, |                                 variant_index, | ||||||
|                                 source_location, |                                 source_location, | ||||||
|                             } |                             } | ||||||
|  | @ -392,19 +987,51 @@ impl Compiler { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 Stmt::Declaration(declaration) => match declaration { |                 Stmt::Declaration(declaration) => match declaration { | ||||||
|                     StmtDeclaration::Wire(wire) => todo!(), |                     StmtDeclaration::Wire(StmtWire { annotations, wire }) => { | ||||||
|                     StmtDeclaration::Reg(reg) => todo!(), |                         self.compile_value(TargetInInstantiatedModule { | ||||||
|  |                             instantiated_module: *parent_module, | ||||||
|  |                             target: wire.into(), | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                     StmtDeclaration::Reg(StmtReg { annotations, reg }) => { | ||||||
|  |                         self.compile_value(TargetInInstantiatedModule { | ||||||
|  |                             instantiated_module: *parent_module, | ||||||
|  |                             target: reg.into(), | ||||||
|  |                         }); | ||||||
|  |                         todo!(); | ||||||
|  |                     } | ||||||
|                     StmtDeclaration::Instance(StmtInstance { |                     StmtDeclaration::Instance(StmtInstance { | ||||||
|                         annotations, |                         annotations, | ||||||
|                         instance, |                         instance, | ||||||
|                     }) => { |                     }) => { | ||||||
|                         self.compile_module( |                         let CompiledValue { | ||||||
|  |                             layout: | ||||||
|  |                                 CompiledTypeLayout { | ||||||
|  |                                     ty: value_ty, | ||||||
|  |                                     layout: ty_layout, | ||||||
|  |                                     body: CompiledTypeLayoutBody::Bundle { fields }, | ||||||
|  |                                 }, | ||||||
|  |                             range: value_range, | ||||||
|  |                             write: None, | ||||||
|  |                         } = self.compile_value(TargetInInstantiatedModule { | ||||||
|  |                             instantiated_module: *parent_module, | ||||||
|  |                             target: instance.into(), | ||||||
|  |                         }) | ||||||
|  |                         else { | ||||||
|  |                             unreachable!(); | ||||||
|  |                         }; | ||||||
|  |                         let CompiledModule { module_io } = *self.compile_module( | ||||||
|                             InstantiatedModule::Child { |                             InstantiatedModule::Child { | ||||||
|                                 parent: parent_module, |                                 parent: parent_module, | ||||||
|                                 instance: instance.intern_sized(), |                                 instance: instance.intern_sized(), | ||||||
|                             } |                             } | ||||||
|                             .intern_sized(), |                             .intern_sized(), | ||||||
|                         ); |                         ); | ||||||
|  |                         for (module_io, CompiledBundleField { offset, ty }) in | ||||||
|  |                             module_io.into_iter().zip(fields) | ||||||
|  |                         { | ||||||
|  |                             todo!(); | ||||||
|  |                         } | ||||||
|                         todo!() |                         todo!() | ||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|  | @ -452,7 +1079,7 @@ impl Compiler { | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| struct CompiledModule { | struct CompiledModule { | ||||||
|     module_io: Interned<[CompiledValue]>, |     module_io: Interned<[CompiledValue<CanonicalType>]>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -24,7 +24,8 @@ pub use scoped_ref::ScopedRef; | ||||||
| 
 | 
 | ||||||
| #[doc(inline)] | #[doc(inline)] | ||||||
| pub use misc::{ | pub use misc::{ | ||||||
|     interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, DebugAsRawString, MakeMutSlice, |     get_many_mut, interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, | ||||||
|  |     DebugAsRawString, MakeMutSlice, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| pub mod job_server; | pub mod job_server; | ||||||
|  |  | ||||||
|  | @ -155,3 +155,19 @@ impl fmt::UpperHex for BitSliceWriteWithBase<'_> { | ||||||
|         self.fmt_with_base::<4, true>(f) |         self.fmt_with_base::<4, true>(f) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #[inline] | ||||||
|  | #[track_caller] | ||||||
|  | pub fn get_many_mut<T, const N: usize>(slice: &mut [T], indexes: [usize; N]) -> [&mut T; N] { | ||||||
|  |     for i in 0..N { | ||||||
|  |         for j in 0..i { | ||||||
|  |             assert!(indexes[i] != indexes[j], "duplicate index"); | ||||||
|  |         } | ||||||
|  |         assert!(indexes[i] < slice.len(), "index out of bounds"); | ||||||
|  |     } | ||||||
|  |     // Safety: checked that no indexes are duplicates and no indexes are out of bounds
 | ||||||
|  |     unsafe { | ||||||
|  |         let base = slice.as_mut_ptr(); // convert to a raw pointer before loop to avoid aliasing with &mut [T]
 | ||||||
|  |         std::array::from_fn(|i| &mut *base.add(indexes[i])) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue