WIP adding deduce_resets pass
All checks were successful
/ deps (push) Successful in 19s
/ test (push) Successful in 4m46s
/ deps (pull_request) Successful in 13s
/ test (pull_request) Successful in 4m45s

This commit is contained in:
Jacob Lifshay 2024-11-22 16:07:18 -08:00
parent 11ddbc43c7
commit 913baa37e9
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
4 changed files with 242 additions and 44 deletions

View file

@ -2641,3 +2641,50 @@ impl<T: Type> ModuleIO<T> {
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>,
}

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
pub mod deduce_resets;
pub mod simplify_enums;
pub mod simplify_memories;
pub mod visit;

View 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))
}

View file

@ -16,9 +16,9 @@ use crate::{
int::BoolOrIntType,
intern::{Intern, Interned, Memoize},
module::{
AnnotatedModuleIO, Block, Id, ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt,
StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg,
StmtWire,
AnnotatedModuleIO, Block, Id, InstantiatedModule, ModuleBody, NameId, NormalModuleBody,
ScopedNameId, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance,
StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule,
},
prelude::*,
sim::{
@ -68,47 +68,6 @@ struct Cond {
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)]
struct CompiledBundleField {
offset: TypeIndex,