forked from libre-chip/fayalite
add support for incomplete_wire -- a wire that you can supply the type of later
This commit is contained in:
parent
ff94dda922
commit
df55a514e4
5 changed files with 231 additions and 8 deletions
|
@ -22,7 +22,7 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{CanonicalType, Type},
|
||||
util::ScopedRef,
|
||||
wire::Wire,
|
||||
wire::{IncompleteWire, Wire},
|
||||
};
|
||||
use hashbrown::{hash_map::Entry, HashMap, HashSet};
|
||||
use num_bigint::BigInt;
|
||||
|
@ -118,9 +118,35 @@ pub trait BlockRef: 'static + Send + Sync + Copy + Eq + Hash + fmt::Debug {}
|
|||
|
||||
impl BlockRef for BlockId {}
|
||||
|
||||
pub(crate) enum IncompleteDeclaration {
|
||||
Incomplete {
|
||||
name: ScopedNameId,
|
||||
source_location: SourceLocation,
|
||||
},
|
||||
Complete(StmtDeclaration<ModuleBuilding>),
|
||||
Taken,
|
||||
}
|
||||
|
||||
impl fmt::Debug for IncompleteDeclaration {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Incomplete {
|
||||
name,
|
||||
source_location: _,
|
||||
} => f
|
||||
.debug_struct("Incomplete")
|
||||
.field("name", name)
|
||||
.finish_non_exhaustive(),
|
||||
Self::Complete(v) => v.fmt(f),
|
||||
Self::Taken => f.write_str("Taken"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BuilderBlock {
|
||||
memories: Vec<Rc<RefCell<MemBuilderTarget>>>,
|
||||
incomplete_declarations: Vec<Rc<RefCell<IncompleteDeclaration>>>,
|
||||
stmts: Vec<Stmt<ModuleBuilding>>,
|
||||
}
|
||||
|
||||
|
@ -831,13 +857,34 @@ impl From<NormalModuleBody<ModuleBuilding>> for NormalModuleBody {
|
|||
annotations_map: &mut HashMap<StmtDeclaration<ModuleBuilding>, Vec<TargetedAnnotation>>,
|
||||
block_id: BlockId,
|
||||
) -> Block {
|
||||
let BuilderBlock { memories, stmts } = &mut blocks[block_id.as_usize()];
|
||||
let BuilderBlock {
|
||||
memories,
|
||||
incomplete_declarations,
|
||||
stmts,
|
||||
} = &mut blocks[block_id.as_usize()];
|
||||
let memories = Interned::from_iter(
|
||||
memories
|
||||
.drain(..)
|
||||
.filter_map(|memory| memory.borrow().make_memory()),
|
||||
);
|
||||
let stmts = std::mem::take(stmts);
|
||||
let stmts = Vec::from_iter(
|
||||
incomplete_declarations
|
||||
.drain(..)
|
||||
.map(|decl| {
|
||||
match std::mem::replace(
|
||||
&mut *decl.borrow_mut(),
|
||||
IncompleteDeclaration::Taken,
|
||||
) {
|
||||
IncompleteDeclaration::Incomplete {
|
||||
name,
|
||||
source_location,
|
||||
} => panic!("incomplete declaration: {name:?}\nat: {source_location}"),
|
||||
IncompleteDeclaration::Complete(v) => Stmt::Declaration(v),
|
||||
IncompleteDeclaration::Taken => unreachable!(),
|
||||
}
|
||||
})
|
||||
.chain(stmts.drain(..)),
|
||||
);
|
||||
let stmts = Interned::from_iter(stmts.into_iter().map(|stmt| {
|
||||
match stmt {
|
||||
Stmt::Connect(stmt) => stmt.into(),
|
||||
|
@ -908,6 +955,7 @@ impl NormalModuleBody<ModuleBuilding> {
|
|||
let index = self.body.blocks.len();
|
||||
self.body.blocks.push(BuilderBlock {
|
||||
memories: vec![],
|
||||
incomplete_declarations: vec![],
|
||||
stmts: vec![],
|
||||
});
|
||||
BlockId(index)
|
||||
|
@ -1943,6 +1991,7 @@ impl ModuleBuilder {
|
|||
body: BuilderModuleBody {
|
||||
blocks: vec![BuilderBlock {
|
||||
memories: vec![],
|
||||
incomplete_declarations: vec![],
|
||||
stmts: vec![],
|
||||
}],
|
||||
annotations_map: HashMap::new(),
|
||||
|
@ -2156,6 +2205,42 @@ pub fn wire<T: Type>(implicit_name: ImplicitName<'_>, ty: T) -> Expr<T> {
|
|||
wire_with_loc(implicit_name.0, SourceLocation::caller(), ty)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn incomplete_declaration(
|
||||
name: &str,
|
||||
source_location: SourceLocation,
|
||||
) -> Rc<RefCell<IncompleteDeclaration>> {
|
||||
ModuleBuilder::with(|m| {
|
||||
let mut impl_ = m.impl_.borrow_mut();
|
||||
let scoped_name = ScopedNameId(m.name, impl_.name_id_gen.gen(name.intern()));
|
||||
drop(impl_);
|
||||
let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete {
|
||||
name: scoped_name,
|
||||
source_location,
|
||||
}));
|
||||
let mut impl_ = m.impl_.borrow_mut();
|
||||
impl_
|
||||
.body
|
||||
.builder_normal_body()
|
||||
.block(m.block_stack.top())
|
||||
.incomplete_declarations
|
||||
.push(retval.clone());
|
||||
retval
|
||||
})
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn incomplete_wire_with_loc(name: &str, source_location: SourceLocation) -> IncompleteWire {
|
||||
IncompleteWire {
|
||||
declaration: incomplete_declaration(name, source_location),
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn incomplete_wire(implicit_name: ImplicitName<'_>) -> IncompleteWire {
|
||||
incomplete_wire_with_loc(implicit_name.0, SourceLocation::caller())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn reg_builder_with_loc(name: &str, source_location: SourceLocation) -> RegBuilder<(), (), ()> {
|
||||
ModuleBuilder::with(|m| {
|
||||
|
|
|
@ -9,8 +9,8 @@ pub use crate::{
|
|||
int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType},
|
||||
memory::{Mem, MemBuilder, ReadUnderWrite},
|
||||
module::{
|
||||
annotate, connect, connect_any, instance, memory, memory_array, memory_with_init,
|
||||
reg_builder, wire, Instance, Module, ModuleBuilder,
|
||||
annotate, connect, connect_any, incomplete_wire, instance, memory, memory_array,
|
||||
memory_with_init, reg_builder, wire, Instance, Module, ModuleBuilder,
|
||||
},
|
||||
reg::Reg,
|
||||
reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset},
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use crate::{
|
||||
expr::Flow,
|
||||
expr::{Expr, Flow, ToExpr},
|
||||
intern::Interned,
|
||||
module::{NameId, ScopedNameId},
|
||||
module::{IncompleteDeclaration, NameId, ScopedNameId, StmtDeclaration, StmtWire},
|
||||
source_location::SourceLocation,
|
||||
ty::{CanonicalType, Type},
|
||||
};
|
||||
use std::fmt;
|
||||
use std::{cell::RefCell, fmt, rc::Rc};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Wire<T: Type> {
|
||||
|
@ -76,3 +76,57 @@ impl<T: Type> Wire<T> {
|
|||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IncompleteWire {
|
||||
pub(crate) declaration: Rc<RefCell<IncompleteDeclaration>>,
|
||||
}
|
||||
|
||||
impl IncompleteWire {
|
||||
#[track_caller]
|
||||
pub fn complete<T: Type>(&mut self, ty: T) -> Expr<T> {
|
||||
let canonical_type = ty.canonical();
|
||||
let mut declaration = self.declaration.borrow_mut();
|
||||
if let IncompleteDeclaration::Incomplete {
|
||||
name,
|
||||
source_location,
|
||||
} = *declaration
|
||||
{
|
||||
*declaration = IncompleteDeclaration::Complete(
|
||||
StmtWire {
|
||||
annotations: (),
|
||||
wire: Wire {
|
||||
name,
|
||||
source_location,
|
||||
ty: canonical_type,
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
match *declaration {
|
||||
IncompleteDeclaration::Complete(StmtDeclaration::Wire(StmtWire {
|
||||
wire:
|
||||
Wire {
|
||||
name,
|
||||
source_location,
|
||||
ty: wire_ty,
|
||||
},
|
||||
..
|
||||
})) => {
|
||||
drop(declaration);
|
||||
assert_eq!(wire_ty, canonical_type, "type mismatch");
|
||||
Wire {
|
||||
name,
|
||||
source_location,
|
||||
ty,
|
||||
}
|
||||
.to_expr()
|
||||
}
|
||||
IncompleteDeclaration::Taken => panic!("can't use wire outside of containing module"),
|
||||
IncompleteDeclaration::Complete(_) | IncompleteDeclaration::Incomplete { .. } => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue