add a simulator #3
|
@ -2641,3 +2641,50 @@ impl<T: Type> ModuleIO<T> {
|
||||||
self.ty
|
self.ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
pub enum InstantiatedModule {
|
||||||
|
Base(Interned<Module<Bundle>>),
|
||||||
|
Child {
|
||||||
|
parent: Interned<InstantiatedModule>,
|
||||||
|
instance: Interned<Instance<Bundle>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstantiatedModule {
|
||||||
|
pub 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)]
|
||||||
|
pub struct TargetInInstantiatedModule {
|
||||||
|
pub instantiated_module: InstantiatedModule,
|
||||||
|
pub target: Target,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
pub struct ExprInInstantiatedModule<T: Type> {
|
||||||
|
pub instantiated_module: InstantiatedModule,
|
||||||
|
pub target: Expr<T>,
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
pub mod deduce_resets;
|
||||||
pub mod simplify_enums;
|
pub mod simplify_enums;
|
||||||
pub mod simplify_memories;
|
pub mod simplify_memories;
|
||||||
pub mod visit;
|
pub mod visit;
|
||||||
|
|
191
crates/fayalite/src/module/transform/deduce_resets.rs
Normal file
191
crates/fayalite/src/module/transform/deduce_resets.rs
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
|
use petgraph::graph::{NodeIndex, UnGraph};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
bundle::{BundleField, BundleType},
|
||||||
|
enum_::{EnumType, EnumVariant},
|
||||||
|
expr::target::{TargetPathArrayElement, TargetPathBundleField, TargetPathElement},
|
||||||
|
intern::{Intern, Interned, Memoize},
|
||||||
|
module::{
|
||||||
|
AnnotatedModuleIO, ExprInInstantiatedModule, ExternModuleBody, InstantiatedModule,
|
||||||
|
ModuleBody, NormalModuleBody, TargetInInstantiatedModule,
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DeduceResetsError {
|
||||||
|
ResetIsNotDrivenByAsyncOrSync { target: TargetInInstantiatedModule },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DeduceResetsError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
DeduceResetsError::ResetIsNotDrivenByAsyncOrSync { target } => {
|
||||||
|
write!(f, "deduce_reset failed: Reset signal is not driven by any AsyncReset or SyncReset signals: {target:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for DeduceResetsError {}
|
||||||
|
|
||||||
|
impl From<DeduceResetsError> for std::io::Error {
|
||||||
|
fn from(value: DeduceResetsError) -> Self {
|
||||||
|
std::io::Error::new(std::io::ErrorKind::Other, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Node {
|
||||||
|
target: TargetInInstantiatedModule,
|
||||||
|
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>>,
|
||||||
|
graph: UnGraph<Node, ()>,
|
||||||
|
fallback_to_sync_reset: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_contains_any_undeduced_resets(ty: CanonicalType) -> bool {
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
struct MyMemoize;
|
||||||
|
impl Memoize for MyMemoize {
|
||||||
|
type Input = CanonicalType;
|
||||||
|
type InputOwned = CanonicalType;
|
||||||
|
type Output = bool;
|
||||||
|
|
||||||
|
fn inner(self, input: &Self::Input) -> Self::Output {
|
||||||
|
match input {
|
||||||
|
CanonicalType::UInt(_) => false,
|
||||||
|
CanonicalType::SInt(_) => false,
|
||||||
|
CanonicalType::Bool(_) => false,
|
||||||
|
CanonicalType::Array(ty) => type_contains_any_undeduced_resets(ty.element()),
|
||||||
|
CanonicalType::Enum(ty) => {
|
||||||
|
ty.variants().iter().any(|EnumVariant { ty, .. }| {
|
||||||
|
ty.is_some_and(|ty| type_contains_any_undeduced_resets(ty))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
CanonicalType::Bundle(ty) => ty
|
||||||
|
.fields()
|
||||||
|
.iter()
|
||||||
|
.any(|&BundleField { ty, .. }| type_contains_any_undeduced_resets(ty)),
|
||||||
|
CanonicalType::AsyncReset(_) => false,
|
||||||
|
CanonicalType::SyncReset(_) => false,
|
||||||
|
CanonicalType::Reset(_) => true,
|
||||||
|
CanonicalType::Clock(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let ty = target.target.canonical_ty();
|
||||||
|
let node_id = self.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
|
||||||
|
}
|
||||||
|
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(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
match body {
|
||||||
|
ModuleBody::Normal(NormalModuleBody { body }) => todo!(),
|
||||||
|
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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deduce_resets(
|
||||||
|
module: Interned<Module<Bundle>>,
|
||||||
|
fallback_to_sync_reset: bool,
|
||||||
|
) -> 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))
|
||||||
|
}
|
|
@ -16,9 +16,9 @@ use crate::{
|
||||||
int::BoolOrIntType,
|
int::BoolOrIntType,
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
module::{
|
module::{
|
||||||
AnnotatedModuleIO, Block, Id, ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt,
|
AnnotatedModuleIO, Block, Id, InstantiatedModule, ModuleBody, NameId, NormalModuleBody,
|
||||||
StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg,
|
ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance,
|
||||||
StmtWire,
|
StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
sim::{
|
sim::{
|
||||||
|
@ -68,47 +68,6 @@ struct Cond {
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
struct CompiledBundleField {
|
struct CompiledBundleField {
|
||||||
offset: TypeIndex,
|
offset: TypeIndex,
|
||||||
|
|
Loading…
Reference in a new issue