WIP implementing simulator
This commit is contained in:
		
							parent
							
								
									6f904148c4
								
							
						
					
					
						commit
						479d59b287
					
				
					 3 changed files with 1104 additions and 248 deletions
				
			
		| 
						 | 
					@ -313,7 +313,7 @@ impl TargetChild {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, PartialEq, Eq, Hash)]
 | 
					#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 | 
				
			||||||
pub enum Target {
 | 
					pub enum Target {
 | 
				
			||||||
    Base(Interned<TargetBase>),
 | 
					    Base(Interned<TargetBase>),
 | 
				
			||||||
    Child(TargetChild),
 | 
					    Child(TargetChild),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,28 +1,32 @@
 | 
				
			||||||
//! Fayalite Simulation
 | 
					//! Fayalite Simulation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    bundle::{Bundle, BundleType},
 | 
					    bundle::{Bundle, BundleField, BundleType},
 | 
				
			||||||
    enum_::Enum,
 | 
					    enum_::Enum,
 | 
				
			||||||
    expr::Expr,
 | 
					    expr::{
 | 
				
			||||||
    int::Bool,
 | 
					        target::{
 | 
				
			||||||
    intern::{Intern, Interned},
 | 
					            Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement,
 | 
				
			||||||
    module::{
 | 
					        },
 | 
				
			||||||
        Block, Module, ModuleBody, NormalModuleBody, Stmt, StmtConnect, StmtFormal, StmtIf,
 | 
					        Expr,
 | 
				
			||||||
        StmtMatch,
 | 
					    },
 | 
				
			||||||
 | 
					    int::Bool,
 | 
				
			||||||
 | 
					    intern::{Intern, Interned, Memoize},
 | 
				
			||||||
 | 
					    module::{
 | 
				
			||||||
 | 
					        AnnotatedModuleIO, Block, Instance, Module, ModuleBody, NormalModuleBody, Stmt,
 | 
				
			||||||
 | 
					        StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    sim::interpreter::{
 | 
				
			||||||
 | 
					        Insn, Insns, InsnsBuilding, InsnsBuildingDone, SlotDebugData, StatePartLayout, TypeIndex,
 | 
				
			||||||
 | 
					        TypeIndexRange, TypeLayout,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    sim::interpreter::{Insn, Insns, InsnsBuilding},
 | 
					 | 
				
			||||||
    source_location::SourceLocation,
 | 
					    source_location::SourceLocation,
 | 
				
			||||||
 | 
					    ty::CanonicalType,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use hashbrown::HashMap;
 | 
					use hashbrown::HashMap;
 | 
				
			||||||
use std::{cell::RefCell, rc::Rc};
 | 
					use std::fmt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod interpreter;
 | 
					mod interpreter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
struct CompilingModule {
 | 
					 | 
				
			||||||
    compiled_module: Option<CompiledModule>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
 | 
					#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
 | 
				
			||||||
enum CondStack {
 | 
					enum CondStack {
 | 
				
			||||||
    Always,
 | 
					    Always,
 | 
				
			||||||
| 
						 | 
					@ -44,32 +48,279 @@ enum CondStack {
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(PartialEq, Eq, Hash, Clone, Copy)]
 | 
				
			||||||
 | 
					enum InstantiatedModule {
 | 
				
			||||||
 | 
					    Base(Interned<Module<Bundle>>),
 | 
				
			||||||
 | 
					    Child {
 | 
				
			||||||
 | 
					        parent: Interned<InstantiatedModule>,
 | 
				
			||||||
 | 
					        instance: Interned<Instance<Bundle>>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl InstantiatedModule {
 | 
				
			||||||
 | 
					    fn leaf_module(self) -> Interned<Module<Bundle>> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            InstantiatedModule::Base(base) => base,
 | 
				
			||||||
 | 
					            InstantiatedModule::Child { instance, .. } => instance.instantiated(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn write_path(self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            InstantiatedModule::Base(base) => fmt::Debug::fmt(&base.name_id(), f),
 | 
				
			||||||
 | 
					            InstantiatedModule::Child { parent, instance } => {
 | 
				
			||||||
 | 
					                parent.write_path(f)?;
 | 
				
			||||||
 | 
					                write!(f, ".{}", instance.name_id())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl fmt::Debug for InstantiatedModule {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
				
			||||||
 | 
					        write!(f, "InstantiatedModule(")?;
 | 
				
			||||||
 | 
					        self.write_path(f)?;
 | 
				
			||||||
 | 
					        write!(f, ": {})", self.leaf_module().name_id())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
 | 
				
			||||||
 | 
					struct TargetInInstantiatedModule {
 | 
				
			||||||
 | 
					    instantiated_module: InstantiatedModule,
 | 
				
			||||||
 | 
					    target: Target,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
 | 
				
			||||||
 | 
					struct CompiledBundleField {
 | 
				
			||||||
 | 
					    offset: TypeIndex,
 | 
				
			||||||
 | 
					    ty: CompiledTypeLayout,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
 | 
				
			||||||
 | 
					enum CompiledTypeLayoutBody {
 | 
				
			||||||
 | 
					    Scalar,
 | 
				
			||||||
 | 
					    Array {
 | 
				
			||||||
 | 
					        /// debug names are ignored, use parent's layout instead
 | 
				
			||||||
 | 
					        element: Interned<CompiledTypeLayout>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    Bundle {
 | 
				
			||||||
 | 
					        /// debug names are ignored, use parent's layout instead
 | 
				
			||||||
 | 
					        fields: Interned<[CompiledBundleField]>,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
 | 
				
			||||||
 | 
					struct CompiledTypeLayout {
 | 
				
			||||||
 | 
					    ty: CanonicalType,
 | 
				
			||||||
 | 
					    layout: TypeLayout<InsnsBuildingDone>,
 | 
				
			||||||
 | 
					    body: CompiledTypeLayoutBody,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl CompiledTypeLayout {
 | 
				
			||||||
 | 
					    fn with_prefixed_debug_names(self, prefix: &str) -> Self {
 | 
				
			||||||
 | 
					        let Self { ty, layout, body } = self;
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            ty,
 | 
				
			||||||
 | 
					            layout: layout.with_prefixed_debug_names(prefix),
 | 
				
			||||||
 | 
					            body,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn get(ty: CanonicalType) -> Self {
 | 
				
			||||||
 | 
					        #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 | 
				
			||||||
 | 
					        struct MyMemoize;
 | 
				
			||||||
 | 
					        impl Memoize for MyMemoize {
 | 
				
			||||||
 | 
					            type Input = CanonicalType;
 | 
				
			||||||
 | 
					            type InputOwned = CanonicalType;
 | 
				
			||||||
 | 
					            type Output = CompiledTypeLayout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fn inner(self, input: &Self::Input) -> Self::Output {
 | 
				
			||||||
 | 
					                match input {
 | 
				
			||||||
 | 
					                    CanonicalType::UInt(_)
 | 
				
			||||||
 | 
					                    | CanonicalType::SInt(_)
 | 
				
			||||||
 | 
					                    | CanonicalType::Bool(_)
 | 
				
			||||||
 | 
					                    | CanonicalType::Enum(_)
 | 
				
			||||||
 | 
					                    | CanonicalType::AsyncReset(_)
 | 
				
			||||||
 | 
					                    | CanonicalType::SyncReset(_)
 | 
				
			||||||
 | 
					                    | CanonicalType::Reset(_)
 | 
				
			||||||
 | 
					                    | CanonicalType::Clock(_) => {
 | 
				
			||||||
 | 
					                        let mut layout = TypeLayout::empty();
 | 
				
			||||||
 | 
					                        let debug_data = SlotDebugData { name: "".intern() };
 | 
				
			||||||
 | 
					                        if input.bit_width() > interpreter::SmallUInt::BITS as usize {
 | 
				
			||||||
 | 
					                            layout.big_slots = StatePartLayout::scalar(debug_data);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            layout.small_slots = StatePartLayout::scalar(debug_data);
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        CompiledTypeLayout {
 | 
				
			||||||
 | 
					                            ty: *input,
 | 
				
			||||||
 | 
					                            layout: layout.into(),
 | 
				
			||||||
 | 
					                            body: CompiledTypeLayoutBody::Scalar,
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    CanonicalType::Array(array) => {
 | 
				
			||||||
 | 
					                        let mut layout = TypeLayout::empty();
 | 
				
			||||||
 | 
					                        let element = CompiledTypeLayout::get(array.element()).intern_sized();
 | 
				
			||||||
 | 
					                        for index in 0..array.len() {
 | 
				
			||||||
 | 
					                            layout.allocate(
 | 
				
			||||||
 | 
					                                &element
 | 
				
			||||||
 | 
					                                    .layout
 | 
				
			||||||
 | 
					                                    .with_prefixed_debug_names(&format!("[{index}]")),
 | 
				
			||||||
 | 
					                            );
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        CompiledTypeLayout {
 | 
				
			||||||
 | 
					                            ty: *input,
 | 
				
			||||||
 | 
					                            layout: layout.into(),
 | 
				
			||||||
 | 
					                            body: CompiledTypeLayoutBody::Array { element },
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    CanonicalType::Bundle(bundle) => {
 | 
				
			||||||
 | 
					                        let mut layout = TypeLayout::empty();
 | 
				
			||||||
 | 
					                        let fields = bundle
 | 
				
			||||||
 | 
					                            .fields()
 | 
				
			||||||
 | 
					                            .iter()
 | 
				
			||||||
 | 
					                            .map(
 | 
				
			||||||
 | 
					                                |BundleField {
 | 
				
			||||||
 | 
					                                     name,
 | 
				
			||||||
 | 
					                                     flipped: _,
 | 
				
			||||||
 | 
					                                     ty,
 | 
				
			||||||
 | 
					                                 }| {
 | 
				
			||||||
 | 
					                                    let ty = CompiledTypeLayout::get(*ty);
 | 
				
			||||||
 | 
					                                    let offset = layout
 | 
				
			||||||
 | 
					                                        .allocate(
 | 
				
			||||||
 | 
					                                            &ty.layout
 | 
				
			||||||
 | 
					                                                .with_prefixed_debug_names(&format!(".{name}")),
 | 
				
			||||||
 | 
					                                        )
 | 
				
			||||||
 | 
					                                        .start();
 | 
				
			||||||
 | 
					                                    CompiledBundleField { offset, ty }
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                            .collect();
 | 
				
			||||||
 | 
					                        CompiledTypeLayout {
 | 
				
			||||||
 | 
					                            ty: *input,
 | 
				
			||||||
 | 
					                            layout: layout.into(),
 | 
				
			||||||
 | 
					                            body: CompiledTypeLayoutBody::Bundle { fields },
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        MyMemoize.get_owned(ty)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
 | 
				
			||||||
 | 
					struct CompiledValue {
 | 
				
			||||||
 | 
					    layout: CompiledTypeLayout,
 | 
				
			||||||
 | 
					    range: TypeIndexRange,
 | 
				
			||||||
 | 
					    write: Option<(CompiledTypeLayout, TypeIndexRange)>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl CompiledValue {
 | 
				
			||||||
 | 
					    fn map(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        mut f: impl FnMut(CompiledTypeLayout, TypeIndexRange) -> (CompiledTypeLayout, TypeIndexRange),
 | 
				
			||||||
 | 
					    ) -> Self {
 | 
				
			||||||
 | 
					        let (layout, range) = f(self.layout, self.range);
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            layout,
 | 
				
			||||||
 | 
					            range,
 | 
				
			||||||
 | 
					            write: self.write.map(|(layout, range)| f(layout, range)),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct Compiler {
 | 
					pub struct Compiler {
 | 
				
			||||||
    insns: Insns<InsnsBuilding>,
 | 
					    insns: Insns<InsnsBuilding>,
 | 
				
			||||||
    modules: HashMap<Interned<Module<Bundle>>, Rc<RefCell<CompilingModule>>>,
 | 
					    base_module: Interned<Module<Bundle>>,
 | 
				
			||||||
    module_queue: Vec<Interned<Module<Bundle>>>,
 | 
					    modules: HashMap<InstantiatedModule, CompiledModule>,
 | 
				
			||||||
 | 
					    compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Compiler {
 | 
					impl Compiler {
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new(base_module: Interned<Module<Bundle>>) -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            insns: Insns::new(),
 | 
					            insns: Insns::new(),
 | 
				
			||||||
 | 
					            base_module,
 | 
				
			||||||
            modules: HashMap::new(),
 | 
					            modules: HashMap::new(),
 | 
				
			||||||
            module_queue: Vec::new(),
 | 
					            compiled_values: HashMap::new(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn add_module(&mut self, module: Interned<Module<Bundle>>) {
 | 
					    fn compile_value(&mut self, target: TargetInInstantiatedModule) -> CompiledValue {
 | 
				
			||||||
        self.modules.entry(module).or_insert_with(|| {
 | 
					        if let Some(&retval) = self.compiled_values.get(&target) {
 | 
				
			||||||
            self.module_queue.push(module);
 | 
					            return retval;
 | 
				
			||||||
            Rc::new(RefCell::new(CompilingModule {
 | 
					        }
 | 
				
			||||||
                compiled_module: None,
 | 
					        match target.target {
 | 
				
			||||||
            }))
 | 
					            Target::Base(base) => {
 | 
				
			||||||
 | 
					                let unprefixed_layout = CompiledTypeLayout::get(base.canonical_ty());
 | 
				
			||||||
 | 
					                let layout = unprefixed_layout.with_prefixed_debug_names(&format!(
 | 
				
			||||||
 | 
					                    "{:?}.{:?}",
 | 
				
			||||||
 | 
					                    target.instantiated_module,
 | 
				
			||||||
 | 
					                    base.target_name()
 | 
				
			||||||
 | 
					                ));
 | 
				
			||||||
 | 
					                let range = self.insns.allocate_variable(&layout.layout);
 | 
				
			||||||
 | 
					                let write = match *base {
 | 
				
			||||||
 | 
					                    TargetBase::ModuleIO(_)
 | 
				
			||||||
 | 
					                    | TargetBase::MemPort(_)
 | 
				
			||||||
 | 
					                    | TargetBase::Wire(_)
 | 
				
			||||||
 | 
					                    | TargetBase::Instance(_) => None,
 | 
				
			||||||
 | 
					                    TargetBase::Reg(_) => {
 | 
				
			||||||
 | 
					                        let write_layout = unprefixed_layout.with_prefixed_debug_names(&format!(
 | 
				
			||||||
 | 
					                            "{:?}.{:?}$next",
 | 
				
			||||||
 | 
					                            target.instantiated_module,
 | 
				
			||||||
 | 
					                            base.target_name()
 | 
				
			||||||
 | 
					                        ));
 | 
				
			||||||
 | 
					                        Some((
 | 
				
			||||||
 | 
					                            write_layout,
 | 
				
			||||||
 | 
					                            self.insns.allocate_variable(&write_layout.layout),
 | 
				
			||||||
 | 
					                        ))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                CompiledValue {
 | 
				
			||||||
 | 
					                    range,
 | 
				
			||||||
 | 
					                    layout,
 | 
				
			||||||
 | 
					                    write,
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Target::Child(target_child) => {
 | 
				
			||||||
 | 
					                let parent = self.compile_value(TargetInInstantiatedModule {
 | 
				
			||||||
 | 
					                    instantiated_module: target.instantiated_module,
 | 
				
			||||||
 | 
					                    target: *target_child.parent(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					                match *target_child.path_element() {
 | 
				
			||||||
 | 
					                    TargetPathElement::BundleField(TargetPathBundleField { name }) => {
 | 
				
			||||||
 | 
					                        parent.map(|layout, range| {
 | 
				
			||||||
 | 
					                            let CompiledTypeLayout {
 | 
				
			||||||
 | 
					                                ty: CanonicalType::Bundle(bundle),
 | 
				
			||||||
 | 
					                                layout: _,
 | 
				
			||||||
 | 
					                                body: CompiledTypeLayoutBody::Bundle { fields },
 | 
				
			||||||
 | 
					                            } = layout
 | 
				
			||||||
 | 
					                            else {
 | 
				
			||||||
 | 
					                                unreachable!();
 | 
				
			||||||
 | 
					                            };
 | 
				
			||||||
 | 
					                            let field_index = bundle.name_indexes()[&name];
 | 
				
			||||||
 | 
					                            (
 | 
				
			||||||
 | 
					                                fields[field_index].ty,
 | 
				
			||||||
 | 
					                                range.slice(TypeIndexRange::new(
 | 
				
			||||||
 | 
					                                    fields[field_index].offset,
 | 
				
			||||||
 | 
					                                    fields[field_index].ty.layout.len(),
 | 
				
			||||||
 | 
					                                )),
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    TargetPathElement::ArrayElement(TargetPathArrayElement { index }) => parent
 | 
				
			||||||
 | 
					                        .map(|layout, range| {
 | 
				
			||||||
 | 
					                            let CompiledTypeLayoutBody::Array { element } = layout.body else {
 | 
				
			||||||
 | 
					                                unreachable!();
 | 
				
			||||||
 | 
					                            };
 | 
				
			||||||
 | 
					                            (*element, range.index_array(element.layout.len(), index))
 | 
				
			||||||
 | 
					                        }),
 | 
				
			||||||
 | 
					                    TargetPathElement::DynArrayElement(_) => unreachable!(),
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn compile_block(
 | 
					    fn compile_block(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        module: Interned<Module<Bundle>>,
 | 
					        parent_module: Interned<InstantiatedModule>,
 | 
				
			||||||
        block: Block,
 | 
					        block: Block,
 | 
				
			||||||
        cond_stack: Interned<CondStack>,
 | 
					        cond_stack: Interned<CondStack>,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
| 
						 | 
					@ -98,7 +349,7 @@ impl Compiler {
 | 
				
			||||||
                    blocks: [then_block, else_block],
 | 
					                    blocks: [then_block, else_block],
 | 
				
			||||||
                }) => {
 | 
					                }) => {
 | 
				
			||||||
                    self.compile_block(
 | 
					                    self.compile_block(
 | 
				
			||||||
                        module,
 | 
					                        parent_module,
 | 
				
			||||||
                        then_block,
 | 
					                        then_block,
 | 
				
			||||||
                        CondStack::IfTrue {
 | 
					                        CondStack::IfTrue {
 | 
				
			||||||
                            parent: cond_stack,
 | 
					                            parent: cond_stack,
 | 
				
			||||||
| 
						 | 
					@ -108,7 +359,7 @@ impl Compiler {
 | 
				
			||||||
                        .intern_sized(),
 | 
					                        .intern_sized(),
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    self.compile_block(
 | 
					                    self.compile_block(
 | 
				
			||||||
                        module,
 | 
					                        parent_module,
 | 
				
			||||||
                        else_block,
 | 
					                        else_block,
 | 
				
			||||||
                        CondStack::IfFalse {
 | 
					                        CondStack::IfFalse {
 | 
				
			||||||
                            parent: cond_stack,
 | 
					                            parent: cond_stack,
 | 
				
			||||||
| 
						 | 
					@ -125,7 +376,7 @@ impl Compiler {
 | 
				
			||||||
                }) => {
 | 
					                }) => {
 | 
				
			||||||
                    for (variant_index, block) in blocks.into_iter().enumerate() {
 | 
					                    for (variant_index, block) in blocks.into_iter().enumerate() {
 | 
				
			||||||
                        self.compile_block(
 | 
					                        self.compile_block(
 | 
				
			||||||
                            module,
 | 
					                            parent_module,
 | 
				
			||||||
                            block,
 | 
					                            block,
 | 
				
			||||||
                            CondStack::MatchArm {
 | 
					                            CondStack::MatchArm {
 | 
				
			||||||
                                parent: cond_stack,
 | 
					                                parent: cond_stack,
 | 
				
			||||||
| 
						 | 
					@ -137,67 +388,79 @@ impl Compiler {
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Stmt::Declaration(stmt_declaration) => todo!(),
 | 
					                Stmt::Declaration(declaration) => match declaration {
 | 
				
			||||||
 | 
					                    StmtDeclaration::Wire(wire) => todo!(),
 | 
				
			||||||
 | 
					                    StmtDeclaration::Reg(reg) => todo!(),
 | 
				
			||||||
 | 
					                    StmtDeclaration::Instance(StmtInstance {
 | 
				
			||||||
 | 
					                        annotations,
 | 
				
			||||||
 | 
					                        instance,
 | 
				
			||||||
 | 
					                    }) => {
 | 
				
			||||||
 | 
					                        self.compile_module(
 | 
				
			||||||
 | 
					                            InstantiatedModule::Child {
 | 
				
			||||||
 | 
					                                parent: parent_module,
 | 
				
			||||||
 | 
					                                instance: instance.intern_sized(),
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            .intern_sized(),
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                        todo!()
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fn compile_module(&mut self, module: Interned<Module<Bundle>>) -> CompiledModule {
 | 
					    fn compile_module(&mut self, module: Interned<InstantiatedModule>) -> &CompiledModule {
 | 
				
			||||||
        let step_entry_pc = self.insns.next_insn_pc();
 | 
					        let module_io = module
 | 
				
			||||||
        match module.body() {
 | 
					            .leaf_module()
 | 
				
			||||||
 | 
					            .module_io()
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .map(
 | 
				
			||||||
 | 
					                |&AnnotatedModuleIO {
 | 
				
			||||||
 | 
					                     annotations: _,
 | 
				
			||||||
 | 
					                     module_io,
 | 
				
			||||||
 | 
					                 }| {
 | 
				
			||||||
 | 
					                    self.compile_value(TargetInInstantiatedModule {
 | 
				
			||||||
 | 
					                        instantiated_module: *module,
 | 
				
			||||||
 | 
					                        target: Target::from(module_io),
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .collect();
 | 
				
			||||||
 | 
					        match module.leaf_module().body() {
 | 
				
			||||||
            ModuleBody::Normal(NormalModuleBody { body }) => {
 | 
					            ModuleBody::Normal(NormalModuleBody { body }) => {
 | 
				
			||||||
                self.compile_block(module, body, CondStack::Always.intern_sized())
 | 
					                self.compile_block(module, body, CondStack::Always.intern_sized())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ModuleBody::Extern(_extern_module_body) => {
 | 
					            ModuleBody::Extern(_extern_module_body) => {
 | 
				
			||||||
                todo!("simulating extern module: {}", module.name_id());
 | 
					                todo!("simulating extern module: {:?}", module);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.insns.push(Insn::Return, module.source_location());
 | 
					        let hashbrown::hash_map::Entry::Vacant(entry) = self.modules.entry(*module) else {
 | 
				
			||||||
        CompiledModule { step_entry_pc }
 | 
					            unreachable!("compiled same instantiated module twice");
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        entry.insert(CompiledModule { module_io })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn run(mut self) -> Compiled {
 | 
					    pub fn run(mut self) -> Compiled {
 | 
				
			||||||
        while let Some(module) = self.module_queue.pop() {
 | 
					        self.compile_module(InstantiatedModule::Base(self.base_module).intern_sized());
 | 
				
			||||||
            let compiling_module = self.modules[&module].clone();
 | 
					 | 
				
			||||||
            let mut compiling_module = compiling_module.borrow_mut();
 | 
					 | 
				
			||||||
            let CompilingModule { compiled_module } = &mut *compiling_module;
 | 
					 | 
				
			||||||
            assert!(compiled_module.is_none());
 | 
					 | 
				
			||||||
            *compiled_module = Some(self.compile_module(module));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Compiled {
 | 
					        Compiled {
 | 
				
			||||||
            insns: Insns::from(self.insns).intern_sized(),
 | 
					            insns: Insns::from(self.insns).intern_sized(),
 | 
				
			||||||
            modules: self
 | 
					            modules: self.modules,
 | 
				
			||||||
                .modules
 | 
					 | 
				
			||||||
                .into_iter()
 | 
					 | 
				
			||||||
                .map(|(module, compiling_module)| {
 | 
					 | 
				
			||||||
                    (
 | 
					 | 
				
			||||||
                        module,
 | 
					 | 
				
			||||||
                        Rc::into_inner(compiling_module)
 | 
					 | 
				
			||||||
                            .expect("only reference is Compiler::modules")
 | 
					 | 
				
			||||||
                            .into_inner()
 | 
					 | 
				
			||||||
                            .compiled_module
 | 
					 | 
				
			||||||
                            .expect("module is compiled by Compiler::run"),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                .collect(),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct CompiledModule {
 | 
					struct CompiledModule {
 | 
				
			||||||
    step_entry_pc: usize,
 | 
					    module_io: Interned<[CompiledValue]>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct Compiled {
 | 
					pub struct Compiled {
 | 
				
			||||||
    insns: Interned<Insns>,
 | 
					    insns: Interned<Insns<InsnsBuildingDone>>,
 | 
				
			||||||
    modules: HashMap<Interned<Module<Bundle>>, CompiledModule>,
 | 
					    modules: HashMap<InstantiatedModule, CompiledModule>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Compiled {
 | 
					impl Compiled {
 | 
				
			||||||
    pub fn new<T: BundleType>(module: Module<T>) -> Self {
 | 
					    pub fn new<T: BundleType>(module: Module<T>) -> Self {
 | 
				
			||||||
        let mut compiler = Compiler::new();
 | 
					        Compiler::new(module.canonical().intern()).run()
 | 
				
			||||||
        compiler.add_module(module.canonical().intern());
 | 
					 | 
				
			||||||
        compiler.run()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue