forked from libre-chip/fayalite
WIP: reimplement fayalite::formal and add support to the simulator
This commit is contained in:
parent
31353862ce
commit
00b65ae57a
13 changed files with 463 additions and 116 deletions
|
|
@ -227,6 +227,7 @@ expr_enum! {
|
||||||
RegSync(Reg<CanonicalType, SyncReset>),
|
RegSync(Reg<CanonicalType, SyncReset>),
|
||||||
RegAsync(Reg<CanonicalType, AsyncReset>),
|
RegAsync(Reg<CanonicalType, AsyncReset>),
|
||||||
MemPort(MemPort<DynPortType>),
|
MemPort(MemPort<DynPortType>),
|
||||||
|
FormalInput(ops::FormalInputExpr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@ use crate::{
|
||||||
HdlPartialEqImpl, HdlPartialOrd, HdlPartialOrdImpl, NotALiteralExpr, ReduceBitsImpl,
|
HdlPartialEqImpl, HdlPartialOrd, HdlPartialOrdImpl, NotALiteralExpr, ReduceBitsImpl,
|
||||||
ToExpr, ToLiteralBits, ToSimValueInner, ToValueless, ValueType, Valueless,
|
ToExpr, ToLiteralBits, ToSimValueInner, ToValueless, ValueType, Valueless,
|
||||||
target::{
|
target::{
|
||||||
GetTarget, Target, TargetPathArrayElement, TargetPathBundleField,
|
GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField,
|
||||||
TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString,
|
TargetPathDynArrayElement, TargetPathElement, TargetPathToTraceAsString,
|
||||||
TargetPathTraceAsStringInner,
|
TargetPathTraceAsStringInner,
|
||||||
},
|
},
|
||||||
value_category::ValueCategoryExpr,
|
value_category::ValueCategoryExpr,
|
||||||
},
|
},
|
||||||
|
formal::FormalInput,
|
||||||
int::{
|
int::{
|
||||||
Bool, BoolOrIntType, DynSize, IntType, KnownSize, SInt, SIntType, SIntValue, Size, UInt,
|
Bool, BoolOrIntType, DynSize, IntType, KnownSize, SInt, SIntType, SIntValue, Size, UInt,
|
||||||
UIntType, UIntValue,
|
UIntType, UIntValue,
|
||||||
|
|
@ -4881,3 +4882,66 @@ impl<T: Type> ToExpr for TraceAsStringAsInner<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct FormalInputExpr<T: Type = CanonicalType> {
|
||||||
|
formal_input: FormalInput,
|
||||||
|
ty: T,
|
||||||
|
target: Interned<Target>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> fmt::Debug for FormalInputExpr<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.formal_input.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> FormalInputExpr<T> {
|
||||||
|
pub fn new(formal_input: FormalInput) -> Self {
|
||||||
|
Self {
|
||||||
|
formal_input,
|
||||||
|
ty: T::from_canonical(formal_input.ty()),
|
||||||
|
target: Target::Base(TargetBase::FormalInput(formal_input).intern_sized())
|
||||||
|
.intern_sized(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn formal_input(self) -> FormalInput {
|
||||||
|
self.formal_input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> GetTarget for FormalInputExpr<T> {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
Some(self.target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToLiteralBits for FormalInputExpr<T> {
|
||||||
|
fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> {
|
||||||
|
Err(NotALiteralExpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ValueType for FormalInputExpr<T> {
|
||||||
|
type Type = T;
|
||||||
|
type ValueCategory = ValueCategoryExpr;
|
||||||
|
|
||||||
|
fn ty(&self) -> Self::Type {
|
||||||
|
self.ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToExpr for FormalInputExpr<T> {
|
||||||
|
fn to_expr(&self) -> Expr<Self::Type> {
|
||||||
|
Expr {
|
||||||
|
__enum: ExprEnum::FormalInput(FormalInputExpr {
|
||||||
|
formal_input: self.formal_input,
|
||||||
|
ty: self.formal_input.ty(),
|
||||||
|
target: self.target,
|
||||||
|
})
|
||||||
|
.intern(),
|
||||||
|
__ty: self.ty,
|
||||||
|
__flow: self.formal_input.flow(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use crate::{
|
||||||
array::Array,
|
array::Array,
|
||||||
bundle::{Bundle, BundleField},
|
bundle::{Bundle, BundleField},
|
||||||
expr::{Expr, Flow, ToExpr, ValueType, value_category::ValueCategoryExpr},
|
expr::{Expr, Flow, ToExpr, ValueType, value_category::ValueCategoryExpr},
|
||||||
|
formal::FormalInput,
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{DynPortType, MemPort},
|
memory::{DynPortType, MemPort},
|
||||||
module::{Instance, ModuleIO, TargetName},
|
module::{Instance, ModuleIO, TargetName},
|
||||||
|
|
@ -295,6 +296,10 @@ impl_target_base! {
|
||||||
#[is = is_instance]
|
#[is = is_instance]
|
||||||
#[to = instance]
|
#[to = instance]
|
||||||
Instance(Instance<Bundle>),
|
Instance(Instance<Bundle>),
|
||||||
|
#[from = from]
|
||||||
|
#[is = is_formal_input]
|
||||||
|
#[to = formal_input]
|
||||||
|
FormalInput(FormalInput),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,6 +348,7 @@ impl TargetBase {
|
||||||
TargetBase::RegAsync(v) => TargetName(v.scoped_name(), None),
|
TargetBase::RegAsync(v) => TargetName(v.scoped_name(), None),
|
||||||
TargetBase::Wire(v) => TargetName(v.scoped_name(), None),
|
TargetBase::Wire(v) => TargetName(v.scoped_name(), None),
|
||||||
TargetBase::Instance(v) => TargetName(v.scoped_name(), None),
|
TargetBase::Instance(v) => TargetName(v.scoped_name(), None),
|
||||||
|
TargetBase::FormalInput(v) => TargetName(v.scoped_name(), None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn canonical_ty(&self) -> CanonicalType {
|
pub fn canonical_ty(&self) -> CanonicalType {
|
||||||
|
|
@ -354,6 +360,7 @@ impl TargetBase {
|
||||||
TargetBase::RegAsync(v) => v.ty(),
|
TargetBase::RegAsync(v) => v.ty(),
|
||||||
TargetBase::Wire(v) => v.ty(),
|
TargetBase::Wire(v) => v.ty(),
|
||||||
TargetBase::Instance(v) => v.ty().canonical(),
|
TargetBase::Instance(v) => v.ty().canonical(),
|
||||||
|
TargetBase::FormalInput(v) => v.ty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
TargetPathTraceAsStringInner,
|
TargetPathTraceAsStringInner,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
formal::FormalKind,
|
formal::{FormalInput, FormalInputKind, FormalKind},
|
||||||
int::IntType,
|
int::IntType,
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{PortKind, PortName},
|
memory::{PortKind, PortName},
|
||||||
|
|
@ -385,77 +385,66 @@ struct BlockDefinitionsCache {
|
||||||
cast_bits_to_enum_exprs: RefCell<HashMap<(String, Enum), String>>,
|
cast_bits_to_enum_exprs: RefCell<HashMap<(String, Enum), String>>,
|
||||||
cast_bits_to_array_exprs: RefCell<HashMap<(String, Array), String>>,
|
cast_bits_to_array_exprs: RefCell<HashMap<(String, Array), String>>,
|
||||||
cast_bits_to_phantom_const_exprs: RefCell<HashMap<(String, PhantomConst), String>>,
|
cast_bits_to_phantom_const_exprs: RefCell<HashMap<(String, PhantomConst), String>>,
|
||||||
}
|
per_module_formal_inputs: RefCell<HashMap<(FormalInput, bool), String>>,
|
||||||
|
|
||||||
struct BlockDefinitionsState<'a> {
|
|
||||||
rc_definitions: RcDefinitions,
|
|
||||||
parent: &'a BlockDefinitions<'a>,
|
|
||||||
cache: BlockDefinitionsCache,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BlockDefinitions<'a> {
|
struct BlockDefinitions<'a> {
|
||||||
state: Option<BlockDefinitionsState<'a>>,
|
rc_definitions: RcDefinitions,
|
||||||
|
parent: Option<&'a BlockDefinitions<'a>>,
|
||||||
|
cache: BlockDefinitionsCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BlockDefinitions<'a> {
|
impl<'a> BlockDefinitions<'a> {
|
||||||
fn new(parent: &'a BlockDefinitions<'a>) -> Self {
|
fn new(parent: &'a BlockDefinitions<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: Some(BlockDefinitionsState {
|
rc_definitions: RcDefinitions::default(),
|
||||||
rc_definitions: RcDefinitions::default(),
|
parent: Some(parent),
|
||||||
parent,
|
cache: Default::default(),
|
||||||
cache: Default::default(),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn none() -> Self {
|
fn module() -> Self {
|
||||||
Self { state: None }
|
Self {
|
||||||
|
rc_definitions: RcDefinitions::default(),
|
||||||
|
parent: None,
|
||||||
|
cache: Default::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn get_or_write_definition<K: Hash + Eq>(
|
fn get_or_write_definition<K: Hash + Eq>(
|
||||||
&mut self,
|
&self,
|
||||||
key: K,
|
key: K,
|
||||||
field: impl Fn(&BlockDefinitionsCache) -> &RefCell<HashMap<K, String>>,
|
field: impl Fn(&BlockDefinitionsCache) -> &RefCell<HashMap<K, String>>,
|
||||||
write_definition: impl FnOnce(BlockDefinitionsWriter<'_, '_>, &K) -> Result<String>,
|
write_definition: impl FnOnce(BlockDefinitionsWriter<'_, '_>, &K) -> Result<String>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let state = self.state.as_ref().expect("should be some");
|
let mut current = self;
|
||||||
let mut cur_state = state;
|
|
||||||
loop {
|
loop {
|
||||||
let field = field(&cur_state.cache).borrow();
|
let field = field(¤t.cache).borrow();
|
||||||
if let Some(retval) = field.get(&key) {
|
if let Some(retval) = field.get(&key) {
|
||||||
return Ok(retval.clone());
|
return Ok(retval.clone());
|
||||||
}
|
}
|
||||||
let Some(parent_state) = &cur_state.parent.state else {
|
let Some(parent) = current.parent else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
cur_state = parent_state;
|
current = parent;
|
||||||
}
|
}
|
||||||
let retval = write_definition(BlockDefinitionsWriter { definitions: self }, &key)?;
|
let retval = write_definition(BlockDefinitionsWriter { definitions: self }, &key)?;
|
||||||
Ok(field(&self.state.as_ref().expect("should be some").cache)
|
Ok(field(&self.cache)
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert(retval)
|
.or_insert(retval)
|
||||||
.clone())
|
.clone())
|
||||||
}
|
}
|
||||||
fn write_out(&mut self, indent: Indent<'_>, out: &mut String) {
|
fn write_out(&self, indent: Indent<'_>, out: &mut String) {
|
||||||
self.state
|
self.rc_definitions.write_and_clear(indent, out);
|
||||||
.as_ref()
|
|
||||||
.expect("should be some")
|
|
||||||
.rc_definitions
|
|
||||||
.write_and_clear(indent, out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BlockDefinitionsWriter<'a, 'b> {
|
struct BlockDefinitionsWriter<'a, 'b> {
|
||||||
definitions: &'b mut BlockDefinitions<'a>,
|
definitions: &'b BlockDefinitions<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockDefinitionsWriter<'_, '_> {
|
impl BlockDefinitionsWriter<'_, '_> {
|
||||||
fn add_definition_line(&mut self, v: impl fmt::Display) {
|
fn add_definition_line(&self, v: impl fmt::Display) {
|
||||||
self.definitions
|
self.definitions.rc_definitions.add_definition_line(v);
|
||||||
.state
|
|
||||||
.as_ref()
|
|
||||||
.expect("should be some")
|
|
||||||
.rc_definitions
|
|
||||||
.add_definition_line(v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -467,12 +456,6 @@ impl<'a> std::ops::Deref for BlockDefinitionsWriter<'a, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::DerefMut for BlockDefinitionsWriter<'_, '_> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.definitions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EnumDef {
|
struct EnumDef {
|
||||||
variants: RefCell<Namespace>,
|
variants: RefCell<Namespace>,
|
||||||
body: String,
|
body: String,
|
||||||
|
|
@ -594,6 +577,7 @@ impl TypeState {
|
||||||
struct ModuleState {
|
struct ModuleState {
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
match_arm_values: HashMap<VariantAccess<CanonicalType>, Ident>,
|
match_arm_values: HashMap<VariantAccess<CanonicalType>, Ident>,
|
||||||
|
block_definitions: Rc<BlockDefinitions<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ModuleState {
|
impl Default for ModuleState {
|
||||||
|
|
@ -601,6 +585,7 @@ impl Default for ModuleState {
|
||||||
Self {
|
Self {
|
||||||
ns: Default::default(),
|
ns: Default::default(),
|
||||||
match_arm_values: Default::default(),
|
match_arm_values: Default::default(),
|
||||||
|
block_definitions: Rc::new(BlockDefinitions::module()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -968,7 +953,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value: Expr<FromTy>,
|
value: Expr<FromTy>,
|
||||||
to_ty: ToTy,
|
to_ty: ToTy,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let from_ty = value.ty();
|
let from_ty = value.ty();
|
||||||
|
|
@ -1003,7 +988,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
firrtl_cast_fn: Option<&str>,
|
firrtl_cast_fn: Option<&str>,
|
||||||
value: Expr<FromTy>,
|
value: Expr<FromTy>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let value = self.expr(Expr::canonical(value), definitions, const_ty)?;
|
let value = self.expr(Expr::canonical(value), definitions, const_ty)?;
|
||||||
|
|
@ -1017,7 +1002,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
base: Expr<T>,
|
base: Expr<T>,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let base_width = base.ty().width();
|
let base_width = base.ty().width();
|
||||||
|
|
@ -1035,20 +1020,19 @@ impl<'a> Exporter<'a> {
|
||||||
fn array_literal_expr(
|
fn array_literal_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::ArrayLiteral<CanonicalType, DynSize>,
|
expr: ops::ArrayLiteral<CanonicalType, DynSize>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(expr, const_ty),
|
(expr, const_ty),
|
||||||
|c| &c.array_literal_exprs,
|
|c| &c.array_literal_exprs,
|
||||||
|mut definitions, &(expr, const_ty)| {
|
|definitions, &(expr, const_ty)| {
|
||||||
let ident = self.module.ns.make_new("_array_literal_expr");
|
let ident = self.module.ns.make_new("_array_literal_expr");
|
||||||
let ty_str = self.type_state.ty(expr.ty())?;
|
let ty_str = self.type_state.ty(expr.ty())?;
|
||||||
let const_ = if const_ty { "const " } else { "" };
|
let const_ = if const_ty { "const " } else { "" };
|
||||||
definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_str}"));
|
definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_str}"));
|
||||||
for (index, element) in expr.element_values().into_iter().enumerate() {
|
for (index, element) in expr.element_values().into_iter().enumerate() {
|
||||||
let element =
|
let element = self.expr(Expr::canonical(element), &definitions, const_ty)?;
|
||||||
self.expr(Expr::canonical(element), &mut definitions, const_ty)?;
|
|
||||||
definitions
|
definitions
|
||||||
.add_definition_line(format_args!("connect {ident}[{index}], {element}"));
|
.add_definition_line(format_args!("connect {ident}[{index}], {element}"));
|
||||||
}
|
}
|
||||||
|
|
@ -1062,13 +1046,13 @@ impl<'a> Exporter<'a> {
|
||||||
fn bundle_literal_expr(
|
fn bundle_literal_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::BundleLiteral<Bundle>,
|
expr: ops::BundleLiteral<Bundle>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(expr, const_ty),
|
(expr, const_ty),
|
||||||
|c| &c.bundle_literal_exprs,
|
|c| &c.bundle_literal_exprs,
|
||||||
|mut definitions, &(expr, const_ty)| {
|
|definitions, &(expr, const_ty)| {
|
||||||
let ident = self.module.ns.make_new("_bundle_literal_expr");
|
let ident = self.module.ns.make_new("_bundle_literal_expr");
|
||||||
let ty = expr.ty();
|
let ty = expr.ty();
|
||||||
let (ty_ident, bundle_ns) = self.type_state.bundle_def(ty)?;
|
let (ty_ident, bundle_ns) = self.type_state.bundle_def(ty)?;
|
||||||
|
|
@ -1090,7 +1074,7 @@ impl<'a> Exporter<'a> {
|
||||||
);
|
);
|
||||||
let name = bundle_ns.borrow_mut().get(name);
|
let name = bundle_ns.borrow_mut().get(name);
|
||||||
let field_value =
|
let field_value =
|
||||||
self.expr(Expr::canonical(field_value), &mut definitions, const_ty)?;
|
self.expr(Expr::canonical(field_value), &definitions, const_ty)?;
|
||||||
definitions
|
definitions
|
||||||
.add_definition_line(format_args!("connect {ident}.{name}, {field_value}"));
|
.add_definition_line(format_args!("connect {ident}.{name}, {field_value}"));
|
||||||
}
|
}
|
||||||
|
|
@ -1104,13 +1088,13 @@ impl<'a> Exporter<'a> {
|
||||||
fn uninit_expr(
|
fn uninit_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::Uninit,
|
expr: ops::Uninit,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(expr, const_ty),
|
(expr, const_ty),
|
||||||
|c| &c.uninit_exprs,
|
|c| &c.uninit_exprs,
|
||||||
|mut definitions, &(expr, const_ty)| {
|
|definitions, &(expr, const_ty)| {
|
||||||
let ident = self.module.ns.make_new("_uninit_expr");
|
let ident = self.module.ns.make_new("_uninit_expr");
|
||||||
let ty = expr.ty();
|
let ty = expr.ty();
|
||||||
let ty_ident = self.type_state.ty(ty)?;
|
let ty_ident = self.type_state.ty(ty)?;
|
||||||
|
|
@ -1124,7 +1108,7 @@ impl<'a> Exporter<'a> {
|
||||||
fn enum_literal_expr(
|
fn enum_literal_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::EnumLiteral<Enum>,
|
expr: ops::EnumLiteral<Enum>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let variant_expr = expr
|
let variant_expr = expr
|
||||||
|
|
@ -1137,13 +1121,13 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Bundle,
|
ty: Bundle,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(value_str, ty),
|
(value_str, ty),
|
||||||
|c| &c.cast_bundle_to_bits_exprs,
|
|c| &c.cast_bundle_to_bits_exprs,
|
||||||
|mut definitions, &(ref value_str, ty)| {
|
|definitions, &(ref value_str, ty)| {
|
||||||
if ty.fields().is_empty() {
|
if ty.fields().is_empty() {
|
||||||
return Ok("UInt<0>(0)".into());
|
return Ok("UInt<0>(0)".into());
|
||||||
}
|
}
|
||||||
|
|
@ -1152,7 +1136,7 @@ impl<'a> Exporter<'a> {
|
||||||
return self.expr_cast_to_bits(
|
return self.expr_cast_to_bits(
|
||||||
format!("{value_str}.{field_ident}"),
|
format!("{value_str}.{field_ident}"),
|
||||||
field.ty,
|
field.ty,
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1181,7 +1165,7 @@ impl<'a> Exporter<'a> {
|
||||||
let field_bits = self.expr_cast_to_bits(
|
let field_bits = self.expr_cast_to_bits(
|
||||||
format!("{value_str}.{field_ident}"),
|
format!("{value_str}.{field_ident}"),
|
||||||
field.ty,
|
field.ty,
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1210,13 +1194,13 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Enum,
|
ty: Enum,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(value_str, ty),
|
(value_str, ty),
|
||||||
|c| &c.cast_enum_to_bits_exprs,
|
|c| &c.cast_enum_to_bits_exprs,
|
||||||
|mut definitions, &(ref value_str, ty)| {
|
|definitions, &(ref value_str, ty)| {
|
||||||
if ty.variants().is_empty() {
|
if ty.variants().is_empty() {
|
||||||
return Ok("UInt<0>(0)".into());
|
return Ok("UInt<0>(0)".into());
|
||||||
}
|
}
|
||||||
|
|
@ -1241,7 +1225,7 @@ impl<'a> Exporter<'a> {
|
||||||
let variant_bits = self.expr_cast_to_bits(
|
let variant_bits = self.expr_cast_to_bits(
|
||||||
variant_value.to_string(),
|
variant_value.to_string(),
|
||||||
variant_ty,
|
variant_ty,
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1270,13 +1254,13 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Array,
|
ty: Array,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(value_str, ty),
|
(value_str, ty),
|
||||||
|c| &c.cast_array_to_bits_exprs,
|
|c| &c.cast_array_to_bits_exprs,
|
||||||
|mut definitions, &(ref value_str, ty)| {
|
|definitions, &(ref value_str, ty)| {
|
||||||
if ty.is_empty() {
|
if ty.is_empty() {
|
||||||
return Ok("UInt<0>(0)".into());
|
return Ok("UInt<0>(0)".into());
|
||||||
}
|
}
|
||||||
|
|
@ -1284,7 +1268,7 @@ impl<'a> Exporter<'a> {
|
||||||
return self.expr_cast_to_bits(
|
return self.expr_cast_to_bits(
|
||||||
value_str.clone() + "[0]",
|
value_str.clone() + "[0]",
|
||||||
ty.element(),
|
ty.element(),
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1299,7 +1283,7 @@ impl<'a> Exporter<'a> {
|
||||||
let element_bits = self.expr_cast_to_bits(
|
let element_bits = self.expr_cast_to_bits(
|
||||||
format!("{value_str}[{index}]"),
|
format!("{value_str}[{index}]"),
|
||||||
ty.element(),
|
ty.element(),
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1328,7 +1312,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: CanonicalType,
|
ty: CanonicalType,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
match ty.unwrap_transparent_types() {
|
match ty.unwrap_transparent_types() {
|
||||||
|
|
@ -1357,13 +1341,13 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Bundle,
|
ty: Bundle,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(value_str, ty),
|
(value_str, ty),
|
||||||
|c| &c.cast_bits_to_bundle_exprs,
|
|c| &c.cast_bits_to_bundle_exprs,
|
||||||
|mut definitions, &(ref value_str, ty)| {
|
|definitions, &(ref value_str, ty)| {
|
||||||
let (ty_ident, _) = self.type_state.bundle_def(ty)?;
|
let (ty_ident, _) = self.type_state.bundle_def(ty)?;
|
||||||
let retval = self.module.ns.make_new("_cast_bits_to_bundle_expr");
|
let retval = self.module.ns.make_new("_cast_bits_to_bundle_expr");
|
||||||
definitions
|
definitions
|
||||||
|
|
@ -1420,7 +1404,7 @@ impl<'a> Exporter<'a> {
|
||||||
let field_value = self.expr_cast_bits_to(
|
let field_value = self.expr_cast_bits_to(
|
||||||
format!("{flattened_ident}.{flattened_field_ident}"),
|
format!("{flattened_ident}.{flattened_field_ident}"),
|
||||||
field.ty,
|
field.ty,
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1435,13 +1419,13 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Enum,
|
ty: Enum,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(value_str, ty),
|
(value_str, ty),
|
||||||
|c| &c.cast_bits_to_enum_exprs,
|
|c| &c.cast_bits_to_enum_exprs,
|
||||||
|mut definitions, &(ref value_str, ty)| {
|
|definitions, &(ref value_str, ty)| {
|
||||||
let (ty_ident, enum_def) = self.type_state.enum_def(ty)?;
|
let (ty_ident, enum_def) = self.type_state.enum_def(ty)?;
|
||||||
let retval = self.module.ns.make_new("_cast_bits_to_enum_expr");
|
let retval = self.module.ns.make_new("_cast_bits_to_enum_expr");
|
||||||
definitions
|
definitions
|
||||||
|
|
@ -1457,7 +1441,7 @@ impl<'a> Exporter<'a> {
|
||||||
let variant_value = self.expr_cast_bits_to(
|
let variant_value = self.expr_cast_bits_to(
|
||||||
value_str.clone(),
|
value_str.clone(),
|
||||||
variant_ty,
|
variant_ty,
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1507,7 +1491,7 @@ impl<'a> Exporter<'a> {
|
||||||
let variant_value = self.expr_cast_bits_to(
|
let variant_value = self.expr_cast_bits_to(
|
||||||
body_value.clone(),
|
body_value.clone(),
|
||||||
variant_ty,
|
variant_ty,
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1530,13 +1514,13 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Array,
|
ty: Array,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
definitions.get_or_write_definition(
|
definitions.get_or_write_definition(
|
||||||
(value_str, ty),
|
(value_str, ty),
|
||||||
|c| &c.cast_bits_to_array_exprs,
|
|c| &c.cast_bits_to_array_exprs,
|
||||||
|mut definitions, &(ref value_str, ty)| {
|
|definitions, &(ref value_str, ty)| {
|
||||||
let retval = self.module.ns.make_new("_cast_bits_to_array_expr");
|
let retval = self.module.ns.make_new("_cast_bits_to_array_expr");
|
||||||
let array_ty = self.type_state.ty(ty)?;
|
let array_ty = self.type_state.ty(ty)?;
|
||||||
definitions
|
definitions
|
||||||
|
|
@ -1565,7 +1549,7 @@ impl<'a> Exporter<'a> {
|
||||||
let element_value = self.expr_cast_bits_to(
|
let element_value = self.expr_cast_bits_to(
|
||||||
format!("{flattened_ident}[{index}]"),
|
format!("{flattened_ident}[{index}]"),
|
||||||
ty.element(),
|
ty.element(),
|
||||||
&mut definitions,
|
&definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1580,7 +1564,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: CanonicalType,
|
ty: CanonicalType,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
match ty.unwrap_transparent_types() {
|
match ty.unwrap_transparent_types() {
|
||||||
|
|
@ -1603,7 +1587,7 @@ impl<'a> Exporter<'a> {
|
||||||
CanonicalType::PhantomConst(ty) => definitions.get_or_write_definition(
|
CanonicalType::PhantomConst(ty) => definitions.get_or_write_definition(
|
||||||
(value_str, ty),
|
(value_str, ty),
|
||||||
|c| &c.cast_bits_to_phantom_const_exprs,
|
|c| &c.cast_bits_to_phantom_const_exprs,
|
||||||
|mut definitions, &(ref _value_str, _ty)| {
|
|definitions, &(ref _value_str, _ty)| {
|
||||||
let retval = self.module.ns.make_new("_cast_bits_to_phantom_const_expr");
|
let retval = self.module.ns.make_new("_cast_bits_to_phantom_const_expr");
|
||||||
definitions
|
definitions
|
||||||
.add_definition_line(format_args!("{extra_indent}wire {retval}: {{}}"));
|
.add_definition_line(format_args!("{extra_indent}wire {retval}: {{}}"));
|
||||||
|
|
@ -1620,7 +1604,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &str,
|
func: &str,
|
||||||
arg: Expr<T>,
|
arg: Expr<T>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
|
|
@ -1633,7 +1617,7 @@ impl<'a> Exporter<'a> {
|
||||||
func: &str,
|
func: &str,
|
||||||
lhs: Expr<Lhs>,
|
lhs: Expr<Lhs>,
|
||||||
rhs: Expr<Rhs>,
|
rhs: Expr<Rhs>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
|
|
@ -1642,10 +1626,25 @@ impl<'a> Exporter<'a> {
|
||||||
rhs = self.expr(Expr::canonical(rhs), definitions, const_ty)?,
|
rhs = self.expr(Expr::canonical(rhs), definitions, const_ty)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
fn expr_formal_input(&mut self, formal_input: FormalInput, const_ty: bool) -> Result<String> {
|
||||||
|
let definitions = self.module.block_definitions.clone();
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(formal_input, const_ty),
|
||||||
|
|c| &c.per_module_formal_inputs,
|
||||||
|
|definitions, &(formal_input, const_ty)| match formal_input.kind() {
|
||||||
|
FormalInputKind::FormalGlobalClock => todo!(),
|
||||||
|
FormalInputKind::FormalReset => todo!(),
|
||||||
|
FormalInputKind::AnyConst => todo!(),
|
||||||
|
FormalInputKind::AnySeq => todo!(),
|
||||||
|
FormalInputKind::AllConst => todo!(),
|
||||||
|
FormalInputKind::AllSeq => todo!(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
fn expr(
|
fn expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Expr<CanonicalType>,
|
expr: Expr<CanonicalType>,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
match *Expr::expr_enum(expr) {
|
match *Expr::expr_enum(expr) {
|
||||||
|
|
@ -2012,6 +2011,7 @@ impl<'a> Exporter<'a> {
|
||||||
let port_name = Ident::from(expr.port_name());
|
let port_name = Ident::from(expr.port_name());
|
||||||
Ok(format!("{mem_name}.{port_name}"))
|
Ok(format!("{mem_name}.{port_name}"))
|
||||||
}
|
}
|
||||||
|
ExprEnum::FormalInput(expr) => self.expr_formal_input(expr.formal_input(), const_ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn write_mem_init(
|
fn write_mem_init(
|
||||||
|
|
@ -2126,6 +2126,7 @@ impl<'a> Exporter<'a> {
|
||||||
TargetBase::RegAsync(v) => self.module.ns.get(v.name_id()),
|
TargetBase::RegAsync(v) => self.module.ns.get(v.name_id()),
|
||||||
TargetBase::Wire(v) => self.module.ns.get(v.name_id()),
|
TargetBase::Wire(v) => self.module.ns.get(v.name_id()),
|
||||||
TargetBase::Instance(v) => self.module.ns.get(v.name_id()),
|
TargetBase::Instance(v) => self.module.ns.get(v.name_id()),
|
||||||
|
TargetBase::FormalInput(_) => unreachable!("FormalInput can't be annotated"),
|
||||||
};
|
};
|
||||||
Ok(AnnotationTargetRef { base, segments })
|
Ok(AnnotationTargetRef { base, segments })
|
||||||
}
|
}
|
||||||
|
|
@ -2241,7 +2242,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
stmt_reg: StmtReg<R>,
|
stmt_reg: StmtReg<R>,
|
||||||
module_name: Ident,
|
module_name: Ident,
|
||||||
definitions: &mut BlockDefinitions<'_>,
|
definitions: &BlockDefinitions<'_>,
|
||||||
body: &mut String,
|
body: &mut String,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let StmtReg { annotations, reg } = stmt_reg;
|
let StmtReg { annotations, reg } = stmt_reg;
|
||||||
|
|
@ -2301,8 +2302,8 @@ impl<'a> Exporter<'a> {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
let lhs = self.expr(lhs, &mut definitions, false)?;
|
let lhs = self.expr(lhs, &definitions, false)?;
|
||||||
let rhs = self.expr(rhs, &mut definitions, false)?;
|
let rhs = self.expr(rhs, &definitions, false)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
body,
|
body,
|
||||||
"{indent}connect {lhs}, {rhs}{}",
|
"{indent}connect {lhs}, {rhs}{}",
|
||||||
|
|
@ -2318,9 +2319,9 @@ impl<'a> Exporter<'a> {
|
||||||
text,
|
text,
|
||||||
source_location,
|
source_location,
|
||||||
}) => {
|
}) => {
|
||||||
let clk = self.expr(Expr::canonical(clk), &mut definitions, false)?;
|
let clk = self.expr(Expr::canonical(clk), &definitions, false)?;
|
||||||
let pred = self.expr(Expr::canonical(pred), &mut definitions, false)?;
|
let pred = self.expr(Expr::canonical(pred), &definitions, false)?;
|
||||||
let en = self.expr(Expr::canonical(en), &mut definitions, false)?;
|
let en = self.expr(Expr::canonical(en), &definitions, false)?;
|
||||||
let kind = match kind {
|
let kind = match kind {
|
||||||
FormalKind::Assert => "assert",
|
FormalKind::Assert => "assert",
|
||||||
FormalKind::Assume => "assume",
|
FormalKind::Assume => "assume",
|
||||||
|
|
@ -2345,7 +2346,7 @@ impl<'a> Exporter<'a> {
|
||||||
let mut when = "when";
|
let mut when = "when";
|
||||||
let mut pushed_indent;
|
let mut pushed_indent;
|
||||||
loop {
|
loop {
|
||||||
let cond_str = self.expr(Expr::canonical(cond), &mut definitions, false)?;
|
let cond_str = self.expr(Expr::canonical(cond), &definitions, false)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
body,
|
body,
|
||||||
"{indent}{when} {cond_str}:{}",
|
"{indent}{when} {cond_str}:{}",
|
||||||
|
|
@ -2388,7 +2389,7 @@ impl<'a> Exporter<'a> {
|
||||||
writeln!(
|
writeln!(
|
||||||
body,
|
body,
|
||||||
"{indent}match {}:{}",
|
"{indent}match {}:{}",
|
||||||
self.expr(Expr::canonical(expr), &mut definitions, false)?,
|
self.expr(Expr::canonical(expr), &definitions, false)?,
|
||||||
FileInfo::new(source_location),
|
FileInfo::new(source_location),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -2442,13 +2443,13 @@ impl<'a> Exporter<'a> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Reg(stmt_reg)) => {
|
Stmt::Declaration(StmtDeclaration::Reg(stmt_reg)) => {
|
||||||
self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?;
|
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?;
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegSync(stmt_reg)) => {
|
Stmt::Declaration(StmtDeclaration::RegSync(stmt_reg)) => {
|
||||||
self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?;
|
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?;
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegAsync(stmt_reg)) => {
|
Stmt::Declaration(StmtDeclaration::RegAsync(stmt_reg)) => {
|
||||||
self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?;
|
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?;
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
||||||
annotations,
|
annotations,
|
||||||
|
|
@ -2475,6 +2476,7 @@ impl<'a> Exporter<'a> {
|
||||||
}
|
}
|
||||||
fn module(&mut self, module: Interned<Module<Bundle>>) -> Result<String> {
|
fn module(&mut self, module: Interned<Module<Bundle>>) -> Result<String> {
|
||||||
self.module = ModuleState::default();
|
self.module = ModuleState::default();
|
||||||
|
let module_definitions = self.module.block_definitions.clone();
|
||||||
let indent = self.indent;
|
let indent = self.indent;
|
||||||
let module_name = self.global_ns.get(module.name_id());
|
let module_name = self.global_ns.get(module.name_id());
|
||||||
let mut body = String::new();
|
let mut body = String::new();
|
||||||
|
|
@ -2543,12 +2545,10 @@ impl<'a> Exporter<'a> {
|
||||||
"extmodule"
|
"extmodule"
|
||||||
}
|
}
|
||||||
ModuleBody::Normal(NormalModuleBody { body: top_block }) => {
|
ModuleBody::Normal(NormalModuleBody { body: top_block }) => {
|
||||||
body.push_str(&self.block(
|
let body_str =
|
||||||
module,
|
self.block(module, top_block, &module_indent, &module_definitions)?;
|
||||||
top_block,
|
module_definitions.write_out(indent, &mut body);
|
||||||
&module_indent,
|
body.push_str(&body_str);
|
||||||
&BlockDefinitions::none(),
|
|
||||||
)?);
|
|
||||||
"module"
|
"module"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,195 @@
|
||||||
// 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
|
||||||
use crate::{
|
use crate::{
|
||||||
|
expr::target::{GetTarget, Target},
|
||||||
int::BoolOrIntType,
|
int::BoolOrIntType,
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
|
module::{NameId, NameIdOrGlobal, ScopedNameId},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use std::sync::OnceLock;
|
use std::{fmt, sync::OnceLock};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub enum FormalInputKind {
|
||||||
|
FormalGlobalClock,
|
||||||
|
FormalReset,
|
||||||
|
AnyConst,
|
||||||
|
AnySeq,
|
||||||
|
AllConst,
|
||||||
|
AllSeq,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormalInputKind {
|
||||||
|
pub fn fixed_ty(self) -> Option<CanonicalType> {
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock => Some(Clock.into()),
|
||||||
|
Self::FormalReset => Some(SyncReset.into()),
|
||||||
|
Self::AnyConst => None,
|
||||||
|
Self::AnySeq => None,
|
||||||
|
Self::AllConst => None,
|
||||||
|
Self::AllSeq => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fixed_id(self) -> Option<crate::module::Id> {
|
||||||
|
struct Cache {
|
||||||
|
formal_global_clock: crate::module::Id,
|
||||||
|
formal_reset: crate::module::Id,
|
||||||
|
}
|
||||||
|
static CACHE: OnceLock<Cache> = OnceLock::new();
|
||||||
|
let cache = || {
|
||||||
|
CACHE.get_or_init(
|
||||||
|
#[cold]
|
||||||
|
|| Cache {
|
||||||
|
formal_global_clock: crate::module::Id::new(),
|
||||||
|
formal_reset: crate::module::Id::new(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock => Some(cache().formal_global_clock),
|
||||||
|
Self::FormalReset => Some(cache().formal_reset),
|
||||||
|
Self::AnyConst => None,
|
||||||
|
Self::AnySeq => None,
|
||||||
|
Self::AllConst => None,
|
||||||
|
Self::AllSeq => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn fixed_source_location(self) -> Option<SourceLocation> {
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock | Self::FormalReset => Some(SourceLocation::builtin()),
|
||||||
|
Self::AnyConst | Self::AnySeq | Self::AllConst | Self::AllSeq => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn name(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::FormalGlobalClock => "formal_global_clock",
|
||||||
|
Self::FormalReset => "formal_reset",
|
||||||
|
Self::AnyConst => "any_const",
|
||||||
|
Self::AnySeq => "any_seq",
|
||||||
|
Self::AllConst => "all_const",
|
||||||
|
Self::AllSeq => "all_seq",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn interned_name(self) -> Interned<str> {
|
||||||
|
macro_rules! impl_interned_name {
|
||||||
|
($($variant:ident,)*) => {
|
||||||
|
match self {
|
||||||
|
$(Self::$variant => {
|
||||||
|
static CACHE: OnceLock<Interned<str>> = OnceLock::new();
|
||||||
|
*CACHE.get_or_init(|| Self::$variant.name().intern())
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
impl_interned_name! {
|
||||||
|
FormalGlobalClock,
|
||||||
|
FormalReset,
|
||||||
|
AnyConst,
|
||||||
|
AnySeq,
|
||||||
|
AllConst,
|
||||||
|
AllSeq,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct FormalInputData {
|
||||||
|
kind: FormalInputKind,
|
||||||
|
name_id: NameId,
|
||||||
|
ty: CanonicalType,
|
||||||
|
source_location: SourceLocation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct FormalInput(Interned<FormalInputData>);
|
||||||
|
|
||||||
|
impl fmt::Debug for FormalInput {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
if self.kind().fixed_ty().is_some() {
|
||||||
|
f.write_str(&self.name())
|
||||||
|
} else {
|
||||||
|
f.debug_tuple(&self.name()).field(&self.0.ty).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormalInput {
|
||||||
|
#[track_caller]
|
||||||
|
pub fn new(
|
||||||
|
kind: FormalInputKind,
|
||||||
|
name_id: NameId,
|
||||||
|
ty: CanonicalType,
|
||||||
|
source_location: SourceLocation,
|
||||||
|
) -> Self {
|
||||||
|
let NameId(name, id) = name_id;
|
||||||
|
assert_eq!(kind.interned_name(), name);
|
||||||
|
if let Some(fixed_ty) = kind.fixed_ty() {
|
||||||
|
assert_eq!(ty, fixed_ty);
|
||||||
|
} else {
|
||||||
|
assert!(
|
||||||
|
ty.is_castable_from_bits(),
|
||||||
|
"{name} type must be castable from bits. got:\n{ty:#?}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(fixed_source_location) = kind.fixed_source_location() {
|
||||||
|
assert_eq!(source_location, fixed_source_location);
|
||||||
|
}
|
||||||
|
if let Some(fixed_id) = kind.fixed_id() {
|
||||||
|
assert_eq!(id, fixed_id);
|
||||||
|
}
|
||||||
|
Self(
|
||||||
|
FormalInputData {
|
||||||
|
kind,
|
||||||
|
name_id,
|
||||||
|
ty,
|
||||||
|
source_location,
|
||||||
|
}
|
||||||
|
.intern_sized(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pub fn kind(self) -> FormalInputKind {
|
||||||
|
self.0.kind
|
||||||
|
}
|
||||||
|
pub fn name(self) -> Interned<str> {
|
||||||
|
self.0.name_id.0
|
||||||
|
}
|
||||||
|
pub fn name_id(self) -> NameId {
|
||||||
|
self.0.name_id
|
||||||
|
}
|
||||||
|
pub fn scoped_name(self) -> ScopedNameId {
|
||||||
|
ScopedNameId(NameIdOrGlobal::Global, self.name_id())
|
||||||
|
}
|
||||||
|
pub fn source_location(self) -> SourceLocation {
|
||||||
|
self.0.source_location
|
||||||
|
}
|
||||||
|
pub(crate) fn must_connect_to(self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
pub(crate) fn flow(self) -> crate::expr::Flow {
|
||||||
|
crate::expr::Flow::Source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValueType for FormalInput {
|
||||||
|
type Type = CanonicalType;
|
||||||
|
type ValueCategory = crate::expr::value_category::ValueCategoryExpr;
|
||||||
|
|
||||||
|
fn ty(&self) -> Self::Type {
|
||||||
|
self.0.ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToExpr for FormalInput {
|
||||||
|
fn to_expr(&self) -> Expr<Self::Type> {
|
||||||
|
crate::expr::ops::FormalInputExpr::new(*self).to_expr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetTarget for FormalInput {
|
||||||
|
fn target(&self) -> Option<Interned<Target>> {
|
||||||
|
Some(Target::from(*self).intern_sized())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
pub enum FormalKind {
|
pub enum FormalKind {
|
||||||
|
|
|
||||||
|
|
@ -727,7 +727,57 @@ impl fmt::Display for NameId {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct ScopedNameId(pub NameId, pub NameId);
|
pub enum NameIdOrGlobal {
|
||||||
|
Global,
|
||||||
|
NameId(NameId),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NameIdOrGlobal {
|
||||||
|
pub fn name_id(self) -> Option<NameId> {
|
||||||
|
match self {
|
||||||
|
Self::Global => None,
|
||||||
|
Self::NameId(v) => Some(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn assert_is_name_id(self) {
|
||||||
|
match self {
|
||||||
|
Self::Global => panic!("expected a NameId, got NameIdOrGlobal::Global"),
|
||||||
|
Self::NameId(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn unwrap_name_id(self) -> NameId {
|
||||||
|
match self {
|
||||||
|
Self::Global => panic!("expected a NameId, got NameIdOrGlobal::Global"),
|
||||||
|
Self::NameId(v) => v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for NameIdOrGlobal {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NameIdOrGlobal {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Global => f.write_str("<<Global>>"),
|
||||||
|
Self::NameId(name_id) => fmt::Display::fmt(name_id, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NameId> for NameIdOrGlobal {
|
||||||
|
fn from(value: NameId) -> Self {
|
||||||
|
Self::NameId(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct ScopedNameId(pub NameIdOrGlobal, pub NameId);
|
||||||
|
|
||||||
impl fmt::Debug for ScopedNameId {
|
impl fmt::Debug for ScopedNameId {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
|
@ -805,7 +855,7 @@ impl<T: BundleType> Instance<T> {
|
||||||
self.containing_module_name_id().0
|
self.containing_module_name_id().0
|
||||||
}
|
}
|
||||||
pub fn containing_module_name_id(self) -> NameId {
|
pub fn containing_module_name_id(self) -> NameId {
|
||||||
self.scoped_name.0
|
self.scoped_name.0.unwrap_name_id()
|
||||||
}
|
}
|
||||||
pub fn name(self) -> Interned<str> {
|
pub fn name(self) -> Interned<str> {
|
||||||
self.name_id().0
|
self.name_id().0
|
||||||
|
|
@ -822,11 +872,13 @@ impl<T: BundleType> Instance<T> {
|
||||||
pub fn source_location(self) -> SourceLocation {
|
pub fn source_location(self) -> SourceLocation {
|
||||||
self.source_location
|
self.source_location
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn new_unchecked(
|
pub fn new_unchecked(
|
||||||
scoped_name: ScopedNameId,
|
scoped_name: ScopedNameId,
|
||||||
instantiated: Interned<Module<T>>,
|
instantiated: Interned<Module<T>>,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
scoped_name.0.assert_is_name_id();
|
||||||
Self {
|
Self {
|
||||||
scoped_name,
|
scoped_name,
|
||||||
instantiated,
|
instantiated,
|
||||||
|
|
@ -2118,7 +2170,8 @@ impl transform::visit::Visitor for AssertExprValidity<'_> {
|
||||||
| ExprEnum::CastToBits(_)
|
| ExprEnum::CastToBits(_)
|
||||||
| ExprEnum::CastBitsTo(_)
|
| ExprEnum::CastBitsTo(_)
|
||||||
| ExprEnum::ToTraceAsString(_)
|
| ExprEnum::ToTraceAsString(_)
|
||||||
| ExprEnum::TraceAsStringAsInner(_) => v.default_visit(self),
|
| ExprEnum::TraceAsStringAsInner(_)
|
||||||
|
| ExprEnum::FormalInput(_) => v.default_visit(self),
|
||||||
ExprEnum::VariantAccess(_)
|
ExprEnum::VariantAccess(_)
|
||||||
| ExprEnum::ModuleIO(_)
|
| ExprEnum::ModuleIO(_)
|
||||||
| ExprEnum::Instance(_)
|
| ExprEnum::Instance(_)
|
||||||
|
|
@ -2369,7 +2422,7 @@ impl<T: Type, R: ResetType> RegBuilder<Expr<ClockDomain<R>>, Option<Expr<T>>, T>
|
||||||
ty,
|
ty,
|
||||||
} = self;
|
} = self;
|
||||||
ModuleBuilder::with(|module_builder| {
|
ModuleBuilder::with(|module_builder| {
|
||||||
let scoped_name = ScopedNameId(module_builder.name, NameId(name, Id::new()));
|
let scoped_name = ScopedNameId(module_builder.name.into(), NameId(name, Id::new()));
|
||||||
let reg = Reg::new_unchecked(scoped_name, source_location, ty, clock_domain, init);
|
let reg = Reg::new_unchecked(scoped_name, source_location, ty, clock_domain, init);
|
||||||
let retval = reg.to_expr();
|
let retval = reg.to_expr();
|
||||||
// convert before borrow_mut since ModuleBuilder could be reentered by T::canonical()
|
// convert before borrow_mut since ModuleBuilder could be reentered by T::canonical()
|
||||||
|
|
@ -2765,6 +2818,7 @@ pub fn annotate<T: Type>(target: Expr<T>, annotations: impl IntoAnnotations) {
|
||||||
instance,
|
instance,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
TargetBase::FormalInput(_) => panic!("not a valid annotation target"),
|
||||||
};
|
};
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
unwrap!(m.impl_.borrow_mut().body.builder_normal_body_opt())
|
unwrap!(m.impl_.borrow_mut().body.builder_normal_body_opt())
|
||||||
|
|
@ -2779,7 +2833,7 @@ pub fn annotate<T: Type>(target: Expr<T>, annotations: impl IntoAnnotations) {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn wire_with_loc<T: Type>(name: &str, source_location: SourceLocation, ty: T) -> Expr<T> {
|
pub fn wire_with_loc<T: Type>(name: &str, source_location: SourceLocation, ty: T) -> Expr<T> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let wire = Wire::<T>::new_unchecked(scoped_name, source_location, ty);
|
let wire = Wire::<T>::new_unchecked(scoped_name, source_location, ty);
|
||||||
let retval = wire.to_expr();
|
let retval = wire.to_expr();
|
||||||
let canonical_wire = wire.canonical();
|
let canonical_wire = wire.canonical();
|
||||||
|
|
@ -2811,7 +2865,7 @@ fn incomplete_declaration(
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> Rc<RefCell<IncompleteDeclaration>> {
|
) -> Rc<RefCell<IncompleteDeclaration>> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete {
|
let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete {
|
||||||
name: scoped_name,
|
name: scoped_name,
|
||||||
source_location,
|
source_location,
|
||||||
|
|
@ -2987,7 +3041,7 @@ pub fn instance_with_loc<T: BundleType>(
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> Expr<T> {
|
) -> Expr<T> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let instance = Instance::<T> {
|
let instance = Instance::<T> {
|
||||||
scoped_name,
|
scoped_name,
|
||||||
instantiated,
|
instantiated,
|
||||||
|
|
@ -3026,7 +3080,7 @@ fn memory_impl<Element: Type, Len: Size>(
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
) -> MemBuilder<Element, Len> {
|
) -> MemBuilder<Element, Len> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
let scoped_name = ScopedNameId(m.name, NameId(name.intern(), Id::new()));
|
let scoped_name = ScopedNameId(m.name.into(), NameId(name.intern(), Id::new()));
|
||||||
let (retval, target_mem) = MemBuilder::new(scoped_name, source_location, mem_element_type);
|
let (retval, target_mem) = MemBuilder::new(scoped_name, source_location, mem_element_type);
|
||||||
let mut impl_ = m.impl_.borrow_mut();
|
let mut impl_ = m.impl_.borrow_mut();
|
||||||
let body = impl_.body.builder_normal_body();
|
let body = impl_.body.builder_normal_body();
|
||||||
|
|
@ -3181,7 +3235,7 @@ impl<T: Type> ModuleIO<T> {
|
||||||
NameId(self.bundle_field.name, self.id)
|
NameId(self.bundle_field.name, self.id)
|
||||||
}
|
}
|
||||||
pub fn scoped_name(&self) -> ScopedNameId {
|
pub fn scoped_name(&self) -> ScopedNameId {
|
||||||
ScopedNameId(self.containing_module_name, self.name_id())
|
ScopedNameId(self.containing_module_name.into(), self.name_id())
|
||||||
}
|
}
|
||||||
pub fn source_location(&self) -> SourceLocation {
|
pub fn source_location(&self) -> SourceLocation {
|
||||||
self.source_location
|
self.source_location
|
||||||
|
|
|
||||||
|
|
@ -1215,6 +1215,7 @@ impl<P: Pass> RunPass<P> for ExprEnum {
|
||||||
ExprEnum::RegSync(expr) => reg_expr_run_pass(expr, pass_args),
|
ExprEnum::RegSync(expr) => reg_expr_run_pass(expr, pass_args),
|
||||||
ExprEnum::RegAsync(expr) => reg_expr_run_pass(expr, pass_args),
|
ExprEnum::RegAsync(expr) => reg_expr_run_pass(expr, pass_args),
|
||||||
ExprEnum::MemPort(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
ExprEnum::MemPort(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
|
ExprEnum::FormalInput(expr) => Ok(expr.run_pass(pass_args)?.map(ExprEnum::from)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1932,6 +1933,8 @@ impl_run_pass_copy!([] SVAttributeAnnotation);
|
||||||
impl_run_pass_copy!([] UInt);
|
impl_run_pass_copy!([] UInt);
|
||||||
impl_run_pass_copy!([] usize);
|
impl_run_pass_copy!([] usize);
|
||||||
impl_run_pass_copy!([] FormalKind);
|
impl_run_pass_copy!([] FormalKind);
|
||||||
|
impl_run_pass_copy!([] crate::formal::FormalInput);
|
||||||
|
impl_run_pass_copy!([] ops::FormalInputExpr);
|
||||||
impl_run_pass_copy!([] PhantomConst);
|
impl_run_pass_copy!([] PhantomConst);
|
||||||
|
|
||||||
macro_rules! impl_run_pass_for_struct {
|
macro_rules! impl_run_pass_for_struct {
|
||||||
|
|
@ -2248,6 +2251,9 @@ impl<P: Pass> RunPass<P> for TargetBase {
|
||||||
&TargetBase::RegAsync(v) => v.into(),
|
&TargetBase::RegAsync(v) => v.into(),
|
||||||
TargetBase::Wire(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Wire)),
|
TargetBase::Wire(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Wire)),
|
||||||
TargetBase::Instance(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Instance)),
|
TargetBase::Instance(v) => return Ok(v.run_pass(pass_args)?.map(TargetBase::Instance)),
|
||||||
|
TargetBase::FormalInput(v) => {
|
||||||
|
return Ok(v.run_pass(pass_args)?.map(TargetBase::FormalInput));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(reg.run_pass(pass_args)?.map(|reg| match reg {
|
Ok(reg.run_pass(pass_args)?.map(|reg| match reg {
|
||||||
AnyReg::Reg(reg) => TargetBase::Reg(reg),
|
AnyReg::Reg(reg) => TargetBase::Reg(reg),
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ struct ModuleState {
|
||||||
|
|
||||||
impl ModuleState {
|
impl ModuleState {
|
||||||
fn gen_name(&mut self, name: &str) -> ScopedNameId {
|
fn gen_name(&mut self, name: &str) -> ScopedNameId {
|
||||||
ScopedNameId(self.module_name, NameId(name.intern(), Id::new()))
|
ScopedNameId(self.module_name.into(), NameId(name.intern(), Id::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -824,7 +824,8 @@ impl Folder for State {
|
||||||
| ExprEnum::Wire(_)
|
| ExprEnum::Wire(_)
|
||||||
| ExprEnum::Reg(_)
|
| ExprEnum::Reg(_)
|
||||||
| ExprEnum::RegSync(_)
|
| ExprEnum::RegSync(_)
|
||||||
| ExprEnum::RegAsync(_) => op.default_fold(self)?,
|
| ExprEnum::RegAsync(_)
|
||||||
|
| ExprEnum::FormalInput(_) => op.default_fold(self)?,
|
||||||
};
|
};
|
||||||
self.module_state_stack
|
self.module_state_stack
|
||||||
.last_mut()
|
.last_mut()
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ use crate::{
|
||||||
TargetPathTraceAsStringInner,
|
TargetPathTraceAsStringInner,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
formal::FormalKind,
|
formal::{FormalInput, FormalInputKind, FormalKind},
|
||||||
int::{Bool, SIntType, SIntValue, Size, UIntType, UIntValue},
|
int::{Bool, SIntType, SIntValue, Size, UIntType, UIntValue},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{Mem, MemPort, PortKind, PortName, PortType, ReadUnderWrite},
|
memory::{Mem, MemPort, PortKind, PortName, PortType, ReadUnderWrite},
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ impl<T: Type, R: ResetType> Reg<T, R> {
|
||||||
if let Some(init) = init {
|
if let Some(init) = init {
|
||||||
assert_eq!(ty, init.ty(), "register's type must match init type");
|
assert_eq!(ty, init.ty(), "register's type must match init type");
|
||||||
}
|
}
|
||||||
|
scoped_name.0.assert_is_name_id();
|
||||||
Self {
|
Self {
|
||||||
name: scoped_name,
|
name: scoped_name,
|
||||||
source_location,
|
source_location,
|
||||||
|
|
@ -94,7 +95,7 @@ impl<T: Type, R: ResetType> Reg<T, R> {
|
||||||
self.containing_module_name_id().0
|
self.containing_module_name_id().0
|
||||||
}
|
}
|
||||||
pub fn containing_module_name_id(&self) -> NameId {
|
pub fn containing_module_name_id(&self) -> NameId {
|
||||||
self.name.0
|
self.name.0.unwrap_name_id()
|
||||||
}
|
}
|
||||||
pub fn name(&self) -> Interned<str> {
|
pub fn name(&self) -> Interned<str> {
|
||||||
self.name_id().0
|
self.name_id().0
|
||||||
|
|
|
||||||
|
|
@ -595,6 +595,7 @@ impl<W: fmt::Write> Visitor for XdcFileWriter<W> {
|
||||||
v,
|
v,
|
||||||
instance.source_location(),
|
instance.source_location(),
|
||||||
)? {},
|
)? {},
|
||||||
|
TargetBase::FormalInput(_) => unreachable!("FormalInput can't be annotated"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,13 @@ impl<T: Type> Wire<T> {
|
||||||
ty: T::from_canonical(ty),
|
ty: T::from_canonical(ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
pub fn new_unchecked(
|
pub fn new_unchecked(
|
||||||
scoped_name: ScopedNameId,
|
scoped_name: ScopedNameId,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
ty: T,
|
ty: T,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
scoped_name.0.assert_is_name_id();
|
||||||
Self {
|
Self {
|
||||||
name: scoped_name,
|
name: scoped_name,
|
||||||
source_location,
|
source_location,
|
||||||
|
|
@ -76,7 +78,7 @@ impl<T: Type> Wire<T> {
|
||||||
self.containing_module_name_id().0
|
self.containing_module_name_id().0
|
||||||
}
|
}
|
||||||
pub fn containing_module_name_id(&self) -> NameId {
|
pub fn containing_module_name_id(&self) -> NameId {
|
||||||
self.name.0
|
self.name.0.unwrap_name_id()
|
||||||
}
|
}
|
||||||
pub fn name(&self) -> Interned<str> {
|
pub fn name(&self) -> Interned<str> {
|
||||||
self.name_id().0
|
self.name_id().0
|
||||||
|
|
|
||||||
|
|
@ -1043,6 +1043,16 @@
|
||||||
"fold_where": "T: Fold<State>",
|
"fold_where": "T: Fold<State>",
|
||||||
"visit_where": "T: Visit<State>"
|
"visit_where": "T: Visit<State>"
|
||||||
},
|
},
|
||||||
|
"ops::FormalInputExpr": {
|
||||||
|
"data": {
|
||||||
|
"$kind": "Struct",
|
||||||
|
"$constructor": "ops::FormalInputExpr::new",
|
||||||
|
"formal_input()": "Visible"
|
||||||
|
},
|
||||||
|
"generics": "<T: Type>",
|
||||||
|
"fold_where": "T: Fold<State>",
|
||||||
|
"visit_where": "T: Visit<State>"
|
||||||
|
},
|
||||||
"BlockId": {
|
"BlockId": {
|
||||||
"data": {
|
"data": {
|
||||||
"$kind": "Opaque"
|
"$kind": "Opaque"
|
||||||
|
|
@ -1277,7 +1287,8 @@
|
||||||
"RegSync": "Visible",
|
"RegSync": "Visible",
|
||||||
"RegAsync": "Visible",
|
"RegAsync": "Visible",
|
||||||
"Wire": "Visible",
|
"Wire": "Visible",
|
||||||
"Instance": "Visible"
|
"Instance": "Visible",
|
||||||
|
"FormalInput": "Visible"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"TargetChild": {
|
"TargetChild": {
|
||||||
|
|
@ -1349,6 +1360,21 @@
|
||||||
"generics": "<T: Type>",
|
"generics": "<T: Type>",
|
||||||
"fold_where": "T: Fold<State>",
|
"fold_where": "T: Fold<State>",
|
||||||
"visit_where": "T: Visit<State>"
|
"visit_where": "T: Visit<State>"
|
||||||
|
},
|
||||||
|
"FormalInput": {
|
||||||
|
"data": {
|
||||||
|
"$kind": "Struct",
|
||||||
|
"$constructor": "FormalInput::new",
|
||||||
|
"kind": "Visible",
|
||||||
|
"name_id": "Visible",
|
||||||
|
"ty": "Visible",
|
||||||
|
"source_location": "Visible"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"FormalInputKind": {
|
||||||
|
"data": {
|
||||||
|
"$kind": "Opaque"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue