add a simulator #3
|
@ -180,7 +180,7 @@ impl Block {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct StmtConnect {
|
pub struct StmtConnect {
|
||||||
pub lhs: Expr<CanonicalType>,
|
pub lhs: Expr<CanonicalType>,
|
||||||
pub rhs: Expr<CanonicalType>,
|
pub rhs: Expr<CanonicalType>,
|
||||||
|
@ -235,7 +235,7 @@ impl fmt::Debug for StmtConnect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct StmtFormal {
|
pub struct StmtFormal {
|
||||||
pub kind: FormalKind,
|
pub kind: FormalKind,
|
||||||
pub clk: Expr<Clock>,
|
pub clk: Expr<Clock>,
|
||||||
|
@ -284,6 +284,8 @@ pub struct StmtIf<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||||
pub blocks: [S::Block; 2],
|
pub blocks: [S::Block; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Copy for StmtIf {}
|
||||||
|
|
||||||
impl<S: ModuleBuildingStatus> StmtIf<S> {
|
impl<S: ModuleBuildingStatus> StmtIf<S> {
|
||||||
pub fn then_block(&self) -> S::Block {
|
pub fn then_block(&self) -> S::Block {
|
||||||
self.blocks[0]
|
self.blocks[0]
|
||||||
|
@ -315,6 +317,8 @@ pub struct StmtMatch<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||||
pub blocks: Interned<[S::Block]>,
|
pub blocks: Interned<[S::Block]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Copy for StmtMatch {}
|
||||||
|
|
||||||
impl StmtMatch {
|
impl StmtMatch {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn assert_validity(&self) {
|
fn assert_validity(&self) {
|
||||||
|
@ -459,6 +463,8 @@ pub struct StmtWire<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||||
pub wire: Wire<CanonicalType>,
|
pub wire: Wire<CanonicalType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Copy for StmtWire {}
|
||||||
|
|
||||||
#[derive(Hash, Clone, PartialEq, Eq, Debug)]
|
#[derive(Hash, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct StmtReg<S: ModuleBuildingStatus = ModuleBuilt> {
|
pub struct StmtReg<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||||
pub annotations: S::StmtAnnotations,
|
pub annotations: S::StmtAnnotations,
|
||||||
|
@ -473,6 +479,8 @@ pub struct StmtInstance<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||||
pub instance: Instance<Bundle>,
|
pub instance: Instance<Bundle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Copy for StmtInstance {}
|
||||||
|
|
||||||
wrapper_enum! {
|
wrapper_enum! {
|
||||||
#[impl(
|
#[impl(
|
||||||
(<S: ModuleBuildingStatus>) self: StmtDeclaration<S> = self,
|
(<S: ModuleBuildingStatus>) self: StmtDeclaration<S> = self,
|
||||||
|
@ -490,6 +498,8 @@ wrapper_enum! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Copy for StmtDeclaration {}
|
||||||
|
|
||||||
impl<S: ModuleBuildingStatus> StmtDeclaration<S> {
|
impl<S: ModuleBuildingStatus> StmtDeclaration<S> {
|
||||||
pub fn annotations(&self) -> S::StmtAnnotations {
|
pub fn annotations(&self) -> S::StmtAnnotations {
|
||||||
match self {
|
match self {
|
||||||
|
@ -546,6 +556,8 @@ wrapper_enum! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Copy for Stmt {}
|
||||||
|
|
||||||
impl<S: ModuleBuildingStatus> Stmt<S> {
|
impl<S: ModuleBuildingStatus> Stmt<S> {
|
||||||
pub fn sub_stmt_blocks(&self) -> &[S::Block] {
|
pub fn sub_stmt_blocks(&self) -> &[S::Block] {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -2,20 +2,28 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
use petgraph::graph::{NodeIndex, UnGraph};
|
use petgraph::{
|
||||||
|
graph::{NodeIndex, UnGraph},
|
||||||
|
unionfind::UnionFind,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bundle::{BundleField, BundleType},
|
bundle::{BundleField, BundleType},
|
||||||
enum_::{EnumType, EnumVariant},
|
enum_::{EnumType, EnumVariant},
|
||||||
expr::target::{TargetPathArrayElement, TargetPathBundleField, TargetPathElement},
|
expr::{
|
||||||
|
ops,
|
||||||
|
target::{TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement},
|
||||||
|
Flow,
|
||||||
|
},
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
module::{
|
module::{
|
||||||
AnnotatedModuleIO, ExprInInstantiatedModule, ExternModuleBody, InstantiatedModule,
|
AnnotatedModuleIO, Block, ExprInInstantiatedModule, ExternModuleBody, InstantiatedModule,
|
||||||
ModuleBody, NormalModuleBody, TargetInInstantiatedModule,
|
ModuleBody, ModuleIO, NormalModuleBody, Stmt, StmtConnect, StmtDeclaration, StmtFormal,
|
||||||
|
StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use std::fmt;
|
use std::{convert::Infallible, fmt};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DeduceResetsError {
|
pub enum DeduceResetsError {
|
||||||
|
@ -40,18 +48,132 @@ impl From<DeduceResetsError> for std::io::Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
enum ResetTarget {
|
||||||
|
Base {
|
||||||
|
base: Interned<TargetBase>,
|
||||||
|
},
|
||||||
|
BundleField {
|
||||||
|
parent: Interned<ResetTarget>,
|
||||||
|
field_ty: CanonicalType,
|
||||||
|
field_index: usize,
|
||||||
|
},
|
||||||
|
EnumVariant {
|
||||||
|
parent: Interned<ResetTarget>,
|
||||||
|
variant_ty: CanonicalType,
|
||||||
|
variant_index: usize,
|
||||||
|
},
|
||||||
|
/// Array's Elements:
|
||||||
|
/// deduce_resets requires all array elements to deduce to the same pattern of async/sync resets,
|
||||||
|
/// so we don't track individual array elements but instead track all of an array's elements together.
|
||||||
|
ArraysElements {
|
||||||
|
parent: Interned<ResetTarget>,
|
||||||
|
element_ty: CanonicalType,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResetTarget {
|
||||||
|
fn canonical_ty(self) -> CanonicalType {
|
||||||
|
match self {
|
||||||
|
ResetTarget::Base { base } => base.canonical_ty(),
|
||||||
|
ResetTarget::BundleField { field_ty, .. } => field_ty,
|
||||||
|
ResetTarget::EnumVariant { variant_ty, .. } => variant_ty,
|
||||||
|
ResetTarget::ArraysElements { element_ty, .. } => element_ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn parent(self) -> Option<Interned<ResetTarget>> {
|
||||||
|
match self {
|
||||||
|
ResetTarget::Base { .. } => None,
|
||||||
|
ResetTarget::BundleField { parent, .. }
|
||||||
|
| ResetTarget::EnumVariant { parent, .. }
|
||||||
|
| ResetTarget::ArraysElements { parent, .. } => Some(parent),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn base(mut self) -> Interned<TargetBase> {
|
||||||
|
loop {
|
||||||
|
match self {
|
||||||
|
ResetTarget::Base { base } => break base,
|
||||||
|
ResetTarget::BundleField { parent, .. }
|
||||||
|
| ResetTarget::EnumVariant { parent, .. }
|
||||||
|
| ResetTarget::ArraysElements { parent, .. } => self = *parent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn bundle_field(self, field_index: usize) -> Self {
|
||||||
|
let field_ty = Bundle::from_canonical(self.canonical_ty()).fields()[field_index].ty;
|
||||||
|
Self::BundleField {
|
||||||
|
parent: self.intern_sized(),
|
||||||
|
field_ty,
|
||||||
|
field_index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn enum_variant(self, variant_index: usize) -> Self {
|
||||||
|
let variant_ty = Enum::from_canonical(self.canonical_ty()).variants()[variant_index]
|
||||||
|
.ty
|
||||||
|
.expect("known to have a variant field");
|
||||||
|
Self::EnumVariant {
|
||||||
|
parent: self.intern_sized(),
|
||||||
|
variant_ty,
|
||||||
|
variant_index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn arrays_elements(self) -> Self {
|
||||||
|
let element_ty = <Array>::from_canonical(self.canonical_ty()).element();
|
||||||
|
Self::ArraysElements {
|
||||||
|
parent: self.intern_sized(),
|
||||||
|
element_ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn for_each_child<E>(self, mut f: impl FnMut(ResetTarget) -> Result<(), E>) -> Result<(), E> {
|
||||||
|
match self.canonical_ty() {
|
||||||
|
CanonicalType::UInt(_)
|
||||||
|
| CanonicalType::SInt(_)
|
||||||
|
| CanonicalType::Bool(_)
|
||||||
|
| CanonicalType::AsyncReset(_)
|
||||||
|
| CanonicalType::SyncReset(_)
|
||||||
|
| CanonicalType::Reset(_)
|
||||||
|
| CanonicalType::Clock(_) => Ok(()),
|
||||||
|
CanonicalType::Array(_) => f(self.arrays_elements()),
|
||||||
|
CanonicalType::Enum(ty) => {
|
||||||
|
for variant_index in 0..ty.variants().len() {
|
||||||
|
f(self.enum_variant(variant_index))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
CanonicalType::Bundle(ty) => {
|
||||||
|
for field_index in 0..ty.fields().len() {
|
||||||
|
f(self.bundle_field(field_index))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<TargetBase>> From<T> for ResetTarget {
|
||||||
|
fn from(base: T) -> Self {
|
||||||
|
ResetTarget::Base {
|
||||||
|
base: TargetBase::intern_sized(base.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
struct ResetTargetInInstantiatedModule {
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
target: ResetTarget,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Node {
|
struct Node {
|
||||||
target: TargetInInstantiatedModule,
|
target: ResetTargetInInstantiatedModule,
|
||||||
deduced_type: Option<CanonicalType>,
|
deduced_type: Option<CanonicalType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct State {
|
struct State {
|
||||||
base_module: Interned<Module<Bundle>>,
|
base_module: Interned<Module<Bundle>>,
|
||||||
transformed_exprs:
|
node_ids: HashMap<ResetTargetInInstantiatedModule, NodeIndex<u32>>,
|
||||||
HashMap<ExprInInstantiatedModule<CanonicalType>, ExprInInstantiatedModule<CanonicalType>>,
|
|
||||||
node_ids: HashMap<TargetInInstantiatedModule, NodeIndex<u32>>,
|
|
||||||
graph: UnGraph<Node, ()>,
|
graph: UnGraph<Node, ()>,
|
||||||
fallback_to_sync_reset: bool,
|
fallback_to_sync_reset: bool,
|
||||||
}
|
}
|
||||||
|
@ -89,88 +211,499 @@ fn type_contains_any_undeduced_resets(ty: CanonicalType) -> bool {
|
||||||
MyMemoize.get_owned(ty)
|
MyMemoize.get_owned(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
trait ProcessStep {
|
||||||
fn add_target_to_graph_recursive(
|
type Error;
|
||||||
&mut self,
|
type Processed<T>;
|
||||||
target: TargetInInstantiatedModule,
|
fn processed_as_ref<T>(v: &Self::Processed<T>) -> Self::Processed<&T>;
|
||||||
) -> NodeIndex<u32> {
|
fn processed_as_mut<T>(v: &mut Self::Processed<T>) -> Self::Processed<&mut T>;
|
||||||
let entry = match self.node_ids.entry(target) {
|
fn processed_zip<T, U>(t: Self::Processed<T>, u: Self::Processed<U>)
|
||||||
Entry::Vacant(entry) => entry,
|
-> Self::Processed<(T, U)>;
|
||||||
Entry::Occupied(entry) => {
|
fn processed_map<T, U>(v: Self::Processed<T>, f: impl FnOnce(T) -> U) -> Self::Processed<U>;
|
||||||
return *entry.get();
|
fn processed_make<T>(t: T) -> Self::Processed<T>;
|
||||||
|
fn processed_from_iter<T, O: FromIterator<T>>(
|
||||||
|
iter: impl IntoIterator<Item = Self::Processed<T>>,
|
||||||
|
) -> Self::Processed<O>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_process_step_with_empty_processed {
|
||||||
|
() => {
|
||||||
|
type Processed<T> = ();
|
||||||
|
fn processed_as_ref<T>(v: &Self::Processed<T>) -> Self::Processed<&T> {
|
||||||
|
*v
|
||||||
|
}
|
||||||
|
fn processed_as_mut<T>(v: &mut Self::Processed<T>) -> Self::Processed<&mut T> {
|
||||||
|
*v
|
||||||
|
}
|
||||||
|
fn processed_zip<T, U>(
|
||||||
|
t: Self::Processed<T>,
|
||||||
|
u: Self::Processed<U>,
|
||||||
|
) -> Self::Processed<(T, U)> {
|
||||||
|
let _ = t;
|
||||||
|
let _ = u;
|
||||||
|
()
|
||||||
|
}
|
||||||
|
fn processed_map<T, U>(
|
||||||
|
v: Self::Processed<T>,
|
||||||
|
f: impl FnOnce(T) -> U,
|
||||||
|
) -> Self::Processed<U> {
|
||||||
|
let _ = f;
|
||||||
|
v
|
||||||
|
}
|
||||||
|
fn processed_make<T>(t: T) -> Self::Processed<T> {
|
||||||
|
let _ = t;
|
||||||
|
()
|
||||||
|
}
|
||||||
|
fn processed_from_iter<T, O: FromIterator<T>>(
|
||||||
|
iter: impl IntoIterator<Item = Self::Processed<T>>,
|
||||||
|
) -> Self::Processed<O> {
|
||||||
|
FromIterator::from_iter(iter)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ty = target.target.canonical_ty();
|
}
|
||||||
let node_id = self.graph.add_node(Node {
|
|
||||||
|
struct Processed<T, Step: ProcessStep>(Step::Processed<T>);
|
||||||
|
|
||||||
|
impl<T, Step: ProcessStep> Processed<T, Step> {
|
||||||
|
fn as_ref(&self) -> Processed<&T, Step> {
|
||||||
|
Processed(Step::processed_as_ref(&self.0))
|
||||||
|
}
|
||||||
|
fn as_mut(&mut self) -> Processed<&mut T, Step> {
|
||||||
|
Processed(Step::processed_as_mut(&mut self.0))
|
||||||
|
}
|
||||||
|
fn zip<U>(self, u: Processed<U, Step>) -> Processed<(T, U), Step> {
|
||||||
|
Processed(Step::processed_zip(self.0, u.0))
|
||||||
|
}
|
||||||
|
fn new(v: T) -> Self {
|
||||||
|
Processed(Step::processed_make(v))
|
||||||
|
}
|
||||||
|
fn map<U>(self, f: impl FnOnce(T) -> U) -> Processed<U, Step> {
|
||||||
|
Processed(Step::processed_map(self.0, f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: FromIterator<A>, A, Step: ProcessStep> FromIterator<Processed<A, Step>>
|
||||||
|
for Processed<C, Step>
|
||||||
|
{
|
||||||
|
fn from_iter<T: IntoIterator<Item = Processed<A, Step>>>(iter: T) -> Self {
|
||||||
|
Processed(Step::processed_from_iter(iter.into_iter().map(|v| v.0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AddNodesToGraphStep;
|
||||||
|
|
||||||
|
impl ProcessStep for AddNodesToGraphStep {
|
||||||
|
type Error = Infallible;
|
||||||
|
impl_process_step_with_empty_processed!();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AddEdgesToGraphStep {
|
||||||
|
union_find: UnionFind<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcessStep for AddEdgesToGraphStep {
|
||||||
|
type Error = Infallible;
|
||||||
|
impl_process_step_with_empty_processed!();
|
||||||
|
}
|
||||||
|
|
||||||
|
trait RunProcessStep<Step: ProcessStep>: Sized {
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RunProcessStep<AddNodesToGraphStep> for ResetTarget {
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut AddNodesToGraphStep,
|
||||||
|
) -> Result<Processed<Self, AddNodesToGraphStep>, Infallible> {
|
||||||
|
let target = ResetTargetInInstantiatedModule {
|
||||||
|
instantiated_module,
|
||||||
|
target: self,
|
||||||
|
};
|
||||||
|
let Entry::Vacant(entry) = state.node_ids.entry(target) else {
|
||||||
|
return Ok(Processed(()));
|
||||||
|
};
|
||||||
|
let ty = self.canonical_ty();
|
||||||
|
let node_id = state.graph.add_node(Node {
|
||||||
target,
|
target,
|
||||||
deduced_type: type_contains_any_undeduced_resets(ty).then_some(ty),
|
deduced_type: type_contains_any_undeduced_resets(ty).then_some(ty),
|
||||||
});
|
});
|
||||||
entry.insert(node_id);
|
entry.insert(node_id);
|
||||||
match target.target.canonical_ty() {
|
self.for_each_child(|target| -> Result<(), Infallible> {
|
||||||
CanonicalType::UInt(_)
|
target.run_process_step(instantiated_module, state, step)?;
|
||||||
| CanonicalType::SInt(_)
|
Ok(())
|
||||||
| CanonicalType::Bool(_)
|
})?;
|
||||||
| CanonicalType::AsyncReset(_)
|
Ok(Processed(()))
|
||||||
| 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(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConnectAndLhsInstantiatedModule {
|
||||||
|
lhs_instantiated_module: InstantiatedModule,
|
||||||
|
lhs: Expr<CanonicalType>,
|
||||||
|
rhs: Expr<CanonicalType>,
|
||||||
|
source_location: SourceLocation,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for ConnectAndLhsInstantiatedModule {
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
rhs_instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
let Self {
|
||||||
|
lhs_instantiated_module,
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
source_location,
|
||||||
|
} = self;
|
||||||
|
todo!();
|
||||||
}
|
}
|
||||||
CanonicalType::Enum(_) => {}
|
}
|
||||||
CanonicalType::Bundle(ty) => {
|
|
||||||
for BundleField { name, .. } in ty.fields() {
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtConnect {
|
||||||
self.add_target_to_graph_recursive(TargetInInstantiatedModule {
|
fn run_process_step(
|
||||||
instantiated_module: target.instantiated_module,
|
self,
|
||||||
target: target.target.join(
|
instantiated_module: InstantiatedModule,
|
||||||
TargetPathElement::from(TargetPathBundleField { name }).intern_sized(),
|
state: &mut State,
|
||||||
),
|
step: &mut Step,
|
||||||
});
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
let StmtConnect {
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
source_location,
|
||||||
|
} = self;
|
||||||
|
Ok(ConnectAndLhsInstantiatedModule {
|
||||||
|
lhs_instantiated_module: instantiated_module,
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
source_location,
|
||||||
}
|
}
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(
|
||||||
|
|ConnectAndLhsInstantiatedModule {
|
||||||
|
lhs_instantiated_module: _,
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
source_location,
|
||||||
|
}| StmtConnect {
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
source_location,
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
CanonicalType::Reset(_) => {}
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtFormal {
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
_instantiated_module: InstantiatedModule,
|
||||||
|
_state: &mut State,
|
||||||
|
_step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
// no inputs are Reset
|
||||||
|
Ok(Processed::new(self))
|
||||||
}
|
}
|
||||||
node_id
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtIf {
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
fn build_graph_for_module(&mut self, instantiated_module: Interned<InstantiatedModule>) {
|
}
|
||||||
let Module {
|
|
||||||
name: _,
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtMatch {
|
||||||
source_location: _,
|
fn run_process_step(
|
||||||
body,
|
self,
|
||||||
io_ty: _,
|
instantiated_module: InstantiatedModule,
|
||||||
module_io,
|
state: &mut State,
|
||||||
module_annotations: _,
|
step: &mut Step,
|
||||||
} = *instantiated_module.leaf_module();
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
for AnnotatedModuleIO {
|
todo!()
|
||||||
annotations: _,
|
}
|
||||||
module_io,
|
}
|
||||||
} in module_io
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for ModuleIO<CanonicalType>
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
Ok(ResetTarget::from(self)
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(|target| {
|
||||||
|
let ResetTarget::Base { base } = target else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
let TargetBase::ModuleIO(module_io) = *base else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
module_io
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtWire
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
let Self { annotations, wire } = self;
|
||||||
|
Ok(ResetTarget::from(wire)
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(|target| {
|
||||||
|
let ResetTarget::Base { base } = target else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
let TargetBase::Wire(wire) = *base else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
Self { annotations, wire }
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtReg
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
let Self { annotations, reg } = self;
|
||||||
|
Ok(ResetTarget::from(reg)
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(|target| {
|
||||||
|
let ResetTarget::Base { base } = target else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
let TargetBase::Reg(reg) = *base else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
Self { annotations, reg }
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtInstance
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
let Self {
|
||||||
|
annotations,
|
||||||
|
instance,
|
||||||
|
} = self;
|
||||||
|
let child_instantiated_module = InstantiatedModule::Child {
|
||||||
|
parent: instantiated_module.intern_sized(),
|
||||||
|
instance: instance.intern_sized(),
|
||||||
|
};
|
||||||
|
instance
|
||||||
|
.instantiated()
|
||||||
|
.run_process_step(child_instantiated_module, state, step)?;
|
||||||
|
for (field_index, AnnotatedModuleIO { module_io, .. }) in
|
||||||
|
instance.instantiated().module_io().into_iter().enumerate()
|
||||||
{
|
{
|
||||||
self.add_target_to_graph_recursive(TargetInInstantiatedModule {
|
let (lhs_instantiated_module, lhs, rhs_instantiated_module, rhs) = match module_io
|
||||||
instantiated_module: *instantiated_module,
|
.flow()
|
||||||
target: module_io.into(),
|
{
|
||||||
});
|
Flow::Source => {
|
||||||
|
// connect to submodule's input from instance input
|
||||||
|
(
|
||||||
|
child_instantiated_module,
|
||||||
|
module_io.to_expr(),
|
||||||
|
instantiated_module,
|
||||||
|
ops::FieldAccess::new_by_index(instance.to_expr(), field_index).to_expr(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
match body {
|
Flow::Sink => {
|
||||||
ModuleBody::Normal(NormalModuleBody { body }) => todo!(),
|
// connect to instance output from submodule's output
|
||||||
ModuleBody::Extern(ExternModuleBody {
|
(
|
||||||
|
instantiated_module,
|
||||||
|
ops::FieldAccess::new_by_index(instance.to_expr(), field_index).to_expr(),
|
||||||
|
child_instantiated_module,
|
||||||
|
module_io.to_expr(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Flow::Duplex => unreachable!(),
|
||||||
|
};
|
||||||
|
ConnectAndLhsInstantiatedModule {
|
||||||
|
lhs_instantiated_module,
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
source_location: instance.source_location(),
|
||||||
|
}
|
||||||
|
.run_process_step(rhs_instantiated_module, state, step)?;
|
||||||
|
}
|
||||||
|
Ok(ResetTarget::from(instance)
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(|target| {
|
||||||
|
let ResetTarget::Base { base } = target else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
let TargetBase::Instance(instance) = *base else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
annotations,
|
||||||
|
instance,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for StmtDeclaration
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
Ok(match self {
|
||||||
|
StmtDeclaration::Wire(decl) => decl
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(StmtDeclaration::from),
|
||||||
|
StmtDeclaration::Reg(decl) => decl
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(StmtDeclaration::from),
|
||||||
|
StmtDeclaration::Instance(decl) => decl
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(StmtDeclaration::from),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for Stmt
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
Ok(match self {
|
||||||
|
Stmt::Connect(stmt) => stmt
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(Stmt::from),
|
||||||
|
Stmt::Formal(stmt) => stmt
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(Stmt::from),
|
||||||
|
Stmt::If(stmt) => stmt
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(Stmt::from),
|
||||||
|
Stmt::Match(stmt) => stmt
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(Stmt::from),
|
||||||
|
Stmt::Declaration(stmt) => stmt
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(Stmt::from),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for Block
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
let Block { memories, stmts } = self;
|
||||||
|
// memories and memory ports won't ever contain any Reset values,
|
||||||
|
// so always just use the old `memories` value. we add the ports to the graph anyway to make the other logic easier.
|
||||||
|
for memory in memories {
|
||||||
|
for port in memory.ports() {
|
||||||
|
ResetTarget::from(port).run_process_step(instantiated_module, state, step)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let stmts = Result::<Processed<_, _>, _>::from_iter(
|
||||||
|
stmts
|
||||||
|
.iter()
|
||||||
|
.map(|stmt| stmt.run_process_step(instantiated_module, state, step)),
|
||||||
|
)?;
|
||||||
|
Ok(stmts.map(|stmts| Block { memories, stmts }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Step: ProcessStep> RunProcessStep<Step> for Module<Bundle>
|
||||||
|
where
|
||||||
|
ResetTarget: RunProcessStep<Step>,
|
||||||
|
{
|
||||||
|
fn run_process_step(
|
||||||
|
self,
|
||||||
|
instantiated_module: InstantiatedModule,
|
||||||
|
state: &mut State,
|
||||||
|
step: &mut Step,
|
||||||
|
) -> Result<Processed<Self, Step>, Step::Error> {
|
||||||
|
let module = *instantiated_module.leaf_module();
|
||||||
|
let module_io =
|
||||||
|
Result::<Processed<Interned<[_]>, _>, _>::from_iter(module.module_io().iter().map(
|
||||||
|
|&AnnotatedModuleIO {
|
||||||
|
annotations,
|
||||||
|
module_io,
|
||||||
|
}| {
|
||||||
|
Ok(module_io
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(|module_io| AnnotatedModuleIO {
|
||||||
|
annotations,
|
||||||
|
module_io,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
))?;
|
||||||
|
let body = match module.body() {
|
||||||
|
ModuleBody::Normal(NormalModuleBody { body }) => body
|
||||||
|
.run_process_step(instantiated_module, state, step)?
|
||||||
|
.map(|body| ModuleBody::Normal(NormalModuleBody { body })),
|
||||||
|
body @ ModuleBody::Extern(ExternModuleBody {
|
||||||
verilog_name: _,
|
verilog_name: _,
|
||||||
parameters: _,
|
parameters: _,
|
||||||
}) => {}
|
}) => Processed::new(body),
|
||||||
}
|
};
|
||||||
}
|
Ok(module_io.zip(body).map(|(module_io, body)| {
|
||||||
fn deduce_types(&mut self) -> Result<(), DeduceResetsError> {
|
Module::new_unchecked(
|
||||||
todo!()
|
module.name_id(),
|
||||||
}
|
module.source_location(),
|
||||||
fn transform_module(&mut self, module: Interned<Module<Bundle>>) -> Interned<Module<Bundle>> {
|
body,
|
||||||
todo!()
|
module_io,
|
||||||
|
module.module_annotations(),
|
||||||
|
)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,12 +713,16 @@ pub fn deduce_resets(
|
||||||
) -> Result<Interned<Module<Bundle>>, DeduceResetsError> {
|
) -> Result<Interned<Module<Bundle>>, DeduceResetsError> {
|
||||||
let mut state = State {
|
let mut state = State {
|
||||||
base_module: module,
|
base_module: module,
|
||||||
transformed_exprs: HashMap::new(),
|
|
||||||
node_ids: HashMap::new(),
|
node_ids: HashMap::new(),
|
||||||
graph: UnGraph::new_undirected(),
|
graph: UnGraph::new_undirected(),
|
||||||
fallback_to_sync_reset,
|
fallback_to_sync_reset,
|
||||||
};
|
};
|
||||||
state.build_graph_for_module(InstantiatedModule::Base(module).intern_sized());
|
let Ok(Processed(())) = module.run_process_step(
|
||||||
state.deduce_types()?;
|
InstantiatedModule::Base(module),
|
||||||
Ok(state.transform_module(module))
|
&mut state,
|
||||||
|
&mut AddNodesToGraphStep,
|
||||||
|
);
|
||||||
|
todo!("add edges");
|
||||||
|
todo!("deduce types");
|
||||||
|
Ok(todo!("transform module"))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue