Add more caching, reduce the number of duplicate wires in generated FIRRTL, and make Module verification check that expressions are visible #76
5 changed files with 996 additions and 627 deletions
|
|
@ -2,17 +2,12 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
use crate::{
|
use crate::{
|
||||||
annotations::{
|
annotations::{Annotation, TargetedAnnotation},
|
||||||
Annotation, BlackBoxInlineAnnotation, BlackBoxPathAnnotation, CustomFirrtlAnnotation,
|
|
||||||
DocStringAnnotation, DontTouchAnnotation, SVAttributeAnnotation, TargetedAnnotation,
|
|
||||||
},
|
|
||||||
array::Array,
|
|
||||||
build::{ToArgs, WriteArgs},
|
build::{ToArgs, WriteArgs},
|
||||||
bundle::{Bundle, BundleField, BundleType},
|
bundle::{BundleField, BundleType},
|
||||||
clock::Clock,
|
enum_::{EnumType, EnumVariant},
|
||||||
enum_::{Enum, EnumType, EnumVariant},
|
|
||||||
expr::{
|
expr::{
|
||||||
CastBitsTo, Expr, ExprEnum, ToExpr, ValueType,
|
ExprEnum,
|
||||||
ops::{self, VariantAccess},
|
ops::{self, VariantAccess},
|
||||||
target::{
|
target::{
|
||||||
Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement,
|
Target, TargetBase, TargetPathArrayElement, TargetPathBundleField, TargetPathElement,
|
||||||
|
|
@ -20,29 +15,28 @@ use crate::{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
formal::FormalKind,
|
formal::FormalKind,
|
||||||
int::{Bool, DynSize, IntType, SIntValue, UInt, UIntValue},
|
int::IntType,
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{Mem, PortKind, PortName, ReadUnderWrite},
|
memory::{PortKind, PortName},
|
||||||
module::{
|
module::{
|
||||||
AnnotatedModuleIO, Block, ExternModuleBody, ExternModuleParameter,
|
AnnotatedModuleIO, Block, ExternModuleBody, ExternModuleParameter,
|
||||||
ExternModuleParameterValue, Module, ModuleBody, ModuleIO, NameId, NameOptId,
|
ExternModuleParameterValue, ModuleBody, ModuleIO, NameId, NameOptId, NormalModuleBody,
|
||||||
NormalModuleBody, Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance,
|
Stmt, StmtConnect, StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg,
|
||||||
StmtMatch, StmtReg, StmtWire,
|
StmtWire,
|
||||||
transform::{
|
transform::{
|
||||||
simplify_enums::{SimplifyEnumsError, SimplifyEnumsKind, simplify_enums},
|
simplify_enums::{SimplifyEnumsError, SimplifyEnumsKind, simplify_enums},
|
||||||
simplify_memories::simplify_memories,
|
simplify_memories::simplify_memories,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
reset::{AsyncReset, Reset, ResetType, SyncReset},
|
prelude::*,
|
||||||
source_location::SourceLocation,
|
reset::ResetType,
|
||||||
ty::{CanonicalType, OpaqueSimValueSize, Type},
|
ty::OpaqueSimValueSize,
|
||||||
util::{
|
util::{
|
||||||
BitSliceWriteWithBase, DebugAsRawString, GenericConstBool, HashMap, HashSet,
|
BitSliceWriteWithBase, DebugAsRawString, GenericConstBool, HashMap, HashSet,
|
||||||
const_str_array_is_strictly_ascending,
|
const_str_array_is_strictly_ascending,
|
||||||
},
|
},
|
||||||
vendor::xilinx::XilinxAnnotation,
|
vendor::xilinx::XilinxAnnotation,
|
||||||
};
|
};
|
||||||
use bitvec::slice::BitSlice;
|
|
||||||
use clap::value_parser;
|
use clap::value_parser;
|
||||||
use num_traits::Signed;
|
use num_traits::Signed;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -378,6 +372,107 @@ impl<K, V> DefinitionsMap<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct BlockDefinitionsCache {
|
||||||
|
array_literal_exprs:
|
||||||
|
RefCell<HashMap<(ops::ArrayLiteral<CanonicalType, DynSize>, bool), String>>,
|
||||||
|
bundle_literal_exprs: RefCell<HashMap<(ops::BundleLiteral, bool), String>>,
|
||||||
|
uninit_exprs: RefCell<HashMap<(ops::Uninit, bool), String>>,
|
||||||
|
cast_bundle_to_bits_exprs: RefCell<HashMap<(String, Bundle), String>>,
|
||||||
|
cast_enum_to_bits_exprs: RefCell<HashMap<(String, Enum), String>>,
|
||||||
|
cast_array_to_bits_exprs: RefCell<HashMap<(String, Array), String>>,
|
||||||
|
cast_bits_to_bundle_exprs: RefCell<HashMap<(String, Bundle), String>>,
|
||||||
|
cast_bits_to_enum_exprs: RefCell<HashMap<(String, Enum), String>>,
|
||||||
|
cast_bits_to_array_exprs: RefCell<HashMap<(String, Array), String>>,
|
||||||
|
cast_bits_to_phantom_const_exprs: RefCell<HashMap<(String, PhantomConst), String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BlockDefinitionsState<'a> {
|
||||||
|
rc_definitions: RcDefinitions,
|
||||||
|
parent: &'a BlockDefinitions<'a>,
|
||||||
|
cache: BlockDefinitionsCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BlockDefinitions<'a> {
|
||||||
|
state: Option<BlockDefinitionsState<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BlockDefinitions<'a> {
|
||||||
|
fn new(parent: &'a BlockDefinitions<'a>) -> Self {
|
||||||
|
Self {
|
||||||
|
state: Some(BlockDefinitionsState {
|
||||||
|
rc_definitions: RcDefinitions::default(),
|
||||||
|
parent,
|
||||||
|
cache: Default::default(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn none() -> Self {
|
||||||
|
Self { state: None }
|
||||||
|
}
|
||||||
|
fn get_or_write_definition<K: Hash + Eq>(
|
||||||
|
&mut self,
|
||||||
|
key: K,
|
||||||
|
field: impl Fn(&BlockDefinitionsCache) -> &RefCell<HashMap<K, String>>,
|
||||||
|
write_definition: impl FnOnce(BlockDefinitionsWriter<'_, '_>, &K) -> Result<String>,
|
||||||
|
) -> Result<String> {
|
||||||
|
let state = self.state.as_ref().expect("should be some");
|
||||||
|
let mut cur_state = state;
|
||||||
|
loop {
|
||||||
|
let field = field(&cur_state.cache).borrow();
|
||||||
|
if let Some(retval) = field.get(&key) {
|
||||||
|
return Ok(retval.clone());
|
||||||
|
}
|
||||||
|
let Some(parent_state) = &cur_state.parent.state else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
cur_state = parent_state;
|
||||||
|
}
|
||||||
|
let retval = write_definition(BlockDefinitionsWriter { definitions: self }, &key)?;
|
||||||
|
Ok(field(&self.state.as_ref().expect("should be some").cache)
|
||||||
|
.borrow_mut()
|
||||||
|
.entry(key)
|
||||||
|
.or_insert(retval)
|
||||||
|
.clone())
|
||||||
|
}
|
||||||
|
fn write_out(&mut self, indent: Indent<'_>, out: &mut String) {
|
||||||
|
self.state
|
||||||
|
.as_ref()
|
||||||
|
.expect("should be some")
|
||||||
|
.rc_definitions
|
||||||
|
.write_and_clear(indent, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BlockDefinitionsWriter<'a, 'b> {
|
||||||
|
definitions: &'b mut BlockDefinitions<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockDefinitionsWriter<'_, '_> {
|
||||||
|
fn add_definition_line(&mut self, v: impl fmt::Display) {
|
||||||
|
self.definitions
|
||||||
|
.state
|
||||||
|
.as_ref()
|
||||||
|
.expect("should be some")
|
||||||
|
.rc_definitions
|
||||||
|
.add_definition_line(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> std::ops::Deref for BlockDefinitionsWriter<'a, '_> {
|
||||||
|
type Target = BlockDefinitions<'a>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.definitions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
@ -498,16 +593,13 @@ impl TypeState {
|
||||||
|
|
||||||
struct ModuleState {
|
struct ModuleState {
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
definitions: RcDefinitions,
|
|
||||||
match_arm_values: HashMap<VariantAccess<CanonicalType>, Ident>,
|
match_arm_values: HashMap<VariantAccess<CanonicalType>, Ident>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ModuleState {
|
impl Default for ModuleState {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let definitions = RcDefinitions::default();
|
|
||||||
Self {
|
Self {
|
||||||
ns: Default::default(),
|
ns: Default::default(),
|
||||||
definitions,
|
|
||||||
match_arm_values: Default::default(),
|
match_arm_values: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -876,7 +968,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value: Expr<FromTy>,
|
value: Expr<FromTy>,
|
||||||
to_ty: ToTy,
|
to_ty: ToTy,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let from_ty = value.ty();
|
let from_ty = value.ty();
|
||||||
|
|
@ -911,7 +1003,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: &RcDefinitions,
|
definitions: &mut 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)?;
|
||||||
|
|
@ -925,7 +1017,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
base: Expr<T>,
|
base: Expr<T>,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let base_width = base.ty().width();
|
let base_width = base.ty().width();
|
||||||
|
|
@ -943,28 +1035,40 @@ 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: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(expr, const_ty),
|
||||||
|
|c| &c.array_literal_exprs,
|
||||||
|
|mut 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 = self.expr(Expr::canonical(element), definitions, const_ty)?;
|
let element =
|
||||||
definitions.add_definition_line(format_args!("connect {ident}[{index}], {element}"));
|
self.expr(Expr::canonical(element), &mut definitions, const_ty)?;
|
||||||
|
definitions
|
||||||
|
.add_definition_line(format_args!("connect {ident}[{index}], {element}"));
|
||||||
}
|
}
|
||||||
if expr.element_values().is_empty() {
|
if expr.element_values().is_empty() {
|
||||||
definitions.add_definition_line(format_args!("invalidate {ident}"));
|
definitions.add_definition_line(format_args!("invalidate {ident}"));
|
||||||
}
|
}
|
||||||
Ok(ident.to_string())
|
Ok(ident.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn bundle_literal_expr(
|
fn bundle_literal_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::BundleLiteral<Bundle>,
|
expr: ops::BundleLiteral<Bundle>,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(expr, const_ty),
|
||||||
|
|c| &c.bundle_literal_exprs,
|
||||||
|
|mut 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)?;
|
||||||
|
|
@ -981,23 +1085,32 @@ impl<'a> Exporter<'a> {
|
||||||
{
|
{
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
!flipped,
|
!flipped,
|
||||||
"can't have bundle literal with flipped field -- this should have been caught in BundleLiteral::new_unchecked"
|
"can't have bundle literal with flipped field -- \
|
||||||
|
this should have been caught in BundleLiteral::new_unchecked"
|
||||||
);
|
);
|
||||||
let name = bundle_ns.borrow_mut().get(name);
|
let name = bundle_ns.borrow_mut().get(name);
|
||||||
let field_value = self.expr(Expr::canonical(field_value), definitions, const_ty)?;
|
let field_value =
|
||||||
definitions.add_definition_line(format_args!("connect {ident}.{name}, {field_value}"));
|
self.expr(Expr::canonical(field_value), &mut definitions, const_ty)?;
|
||||||
|
definitions
|
||||||
|
.add_definition_line(format_args!("connect {ident}.{name}, {field_value}"));
|
||||||
}
|
}
|
||||||
if ty.fields().is_empty() {
|
if ty.fields().is_empty() {
|
||||||
definitions.add_definition_line(format_args!("invalidate {ident}"));
|
definitions.add_definition_line(format_args!("invalidate {ident}"));
|
||||||
}
|
}
|
||||||
Ok(ident.to_string())
|
Ok(ident.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn uninit_expr(
|
fn uninit_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::Uninit,
|
expr: ops::Uninit,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(expr, const_ty),
|
||||||
|
|c| &c.uninit_exprs,
|
||||||
|
|mut 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)?;
|
||||||
|
|
@ -1005,11 +1118,13 @@ impl<'a> Exporter<'a> {
|
||||||
definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_ident}"));
|
definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_ident}"));
|
||||||
definitions.add_definition_line(format_args!("invalidate {ident}"));
|
definitions.add_definition_line(format_args!("invalidate {ident}"));
|
||||||
Ok(ident.to_string())
|
Ok(ident.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn enum_literal_expr(
|
fn enum_literal_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::EnumLiteral<Enum>,
|
expr: ops::EnumLiteral<Enum>,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let variant_expr = expr
|
let variant_expr = expr
|
||||||
|
|
@ -1022,9 +1137,13 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Bundle,
|
ty: Bundle,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(value_str, ty),
|
||||||
|
|c| &c.cast_bundle_to_bits_exprs,
|
||||||
|
|mut 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());
|
||||||
}
|
}
|
||||||
|
|
@ -1033,7 +1152,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,
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1062,7 +1181,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,
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1080,16 +1199,24 @@ impl<'a> Exporter<'a> {
|
||||||
ty.type_properties().bit_width
|
ty.type_properties().bit_width
|
||||||
));
|
));
|
||||||
let cat_expr = cat_expr.expect("bundle already checked to have fields");
|
let cat_expr = cat_expr.expect("bundle already checked to have fields");
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}connect {retval}, {cat_expr}"));
|
definitions.add_definition_line(format_args!(
|
||||||
|
"{extra_indent}connect {retval}, {cat_expr}"
|
||||||
|
));
|
||||||
Ok(retval.to_string())
|
Ok(retval.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn expr_cast_enum_to_bits(
|
fn expr_cast_enum_to_bits(
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Enum,
|
ty: Enum,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(value_str, ty),
|
||||||
|
|c| &c.cast_enum_to_bits_exprs,
|
||||||
|
|mut 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());
|
||||||
}
|
}
|
||||||
|
|
@ -1114,11 +1241,12 @@ 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,
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
"{extra_indent}connect {retval}, pad(cat({variant_bits}, UInt<{}>({variant_index})), {})",
|
"{extra_indent}connect {retval}, \
|
||||||
|
pad(cat({variant_bits}, UInt<{}>({variant_index})), {})",
|
||||||
ty.discriminant_bit_width(),
|
ty.discriminant_bit_width(),
|
||||||
ty.type_properties().bit_width,
|
ty.type_properties().bit_width,
|
||||||
));
|
));
|
||||||
|
|
@ -1135,22 +1263,28 @@ impl<'a> Exporter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(retval.to_string())
|
Ok(retval.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn expr_cast_array_to_bits(
|
fn expr_cast_array_to_bits(
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Array,
|
ty: Array,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(value_str, ty),
|
||||||
|
|c| &c.cast_array_to_bits_exprs,
|
||||||
|
|mut 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());
|
||||||
}
|
}
|
||||||
if ty.len() == 1 {
|
if ty.len() == 1 {
|
||||||
return self.expr_cast_to_bits(
|
return self.expr_cast_to_bits(
|
||||||
value_str + "[0]",
|
value_str.clone() + "[0]",
|
||||||
ty.element(),
|
ty.element(),
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1165,7 +1299,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(),
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1183,14 +1317,18 @@ impl<'a> Exporter<'a> {
|
||||||
ty.type_properties().bit_width
|
ty.type_properties().bit_width
|
||||||
));
|
));
|
||||||
let cat_expr = cat_expr.expect("array already checked to have elements");
|
let cat_expr = cat_expr.expect("array already checked to have elements");
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}connect {retval}, {cat_expr}"));
|
definitions.add_definition_line(format_args!(
|
||||||
|
"{extra_indent}connect {retval}, {cat_expr}"
|
||||||
|
));
|
||||||
Ok(retval.to_string())
|
Ok(retval.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn expr_cast_to_bits(
|
fn expr_cast_to_bits(
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: CanonicalType,
|
ty: CanonicalType,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
match ty.unwrap_transparent_types() {
|
match ty.unwrap_transparent_types() {
|
||||||
|
|
@ -1219,14 +1357,20 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Bundle,
|
ty: Bundle,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(value_str, ty),
|
||||||
|
|c| &c.cast_bits_to_bundle_exprs,
|
||||||
|
|mut 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.add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}"));
|
definitions
|
||||||
|
.add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}"));
|
||||||
if ty.fields().is_empty() {
|
if ty.fields().is_empty() {
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
definitions
|
||||||
|
.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
||||||
return Ok(retval.to_string());
|
return Ok(retval.to_string());
|
||||||
}
|
}
|
||||||
let flattened_bundle_ty = Bundle::new(Interned::from_iter(ty.fields().iter().map(
|
let flattened_bundle_ty = Bundle::new(Interned::from_iter(ty.fields().iter().map(
|
||||||
|
|
@ -1260,9 +1404,12 @@ impl<'a> Exporter<'a> {
|
||||||
.type_state
|
.type_state
|
||||||
.get_bundle_field(flattened_bundle_ty, field.name)?;
|
.get_bundle_field(flattened_bundle_ty, field.name)?;
|
||||||
let field_ident = self.type_state.get_bundle_field(ty, field.name)?;
|
let field_ident = self.type_state.get_bundle_field(ty, field.name)?;
|
||||||
if let Some(field_bit_width_minus_one) = field.ty.bit_width().checked_sub(1usize) {
|
if let Some(field_bit_width_minus_one) =
|
||||||
|
field.ty.bit_width().checked_sub(1usize)
|
||||||
|
{
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
"{extra_indent}connect {flattened_ident}.{flattened_field_ident}, bits({value_str}, {}, {field_offset})",
|
"{extra_indent}connect {flattened_ident}.{flattened_field_ident}, \
|
||||||
|
bits({value_str}, {}, {field_offset})",
|
||||||
field_offset + field_bit_width_minus_one
|
field_offset + field_bit_width_minus_one
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1273,7 +1420,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,
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1281,26 +1428,38 @@ impl<'a> Exporter<'a> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(retval.to_string())
|
Ok(retval.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn expr_cast_bits_to_enum(
|
fn expr_cast_bits_to_enum(
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Enum,
|
ty: Enum,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(value_str, ty),
|
||||||
|
|c| &c.cast_bits_to_enum_exprs,
|
||||||
|
|mut 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.add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}"));
|
definitions
|
||||||
|
.add_definition_line(format_args!("{extra_indent}wire {retval}: {ty_ident}"));
|
||||||
if ty.variants().is_empty() {
|
if ty.variants().is_empty() {
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
definitions
|
||||||
|
.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
||||||
return Ok(retval.to_string());
|
return Ok(retval.to_string());
|
||||||
}
|
}
|
||||||
if let [variant] = *ty.variants() {
|
if let [variant] = *ty.variants() {
|
||||||
let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?;
|
let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?;
|
||||||
if let Some(variant_ty) = variant.ty {
|
if let Some(variant_ty) = variant.ty {
|
||||||
let variant_value =
|
let variant_value = self.expr_cast_bits_to(
|
||||||
self.expr_cast_bits_to(value_str, variant_ty, definitions, extra_indent)?;
|
value_str.clone(),
|
||||||
|
variant_ty,
|
||||||
|
&mut definitions,
|
||||||
|
extra_indent,
|
||||||
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
"{extra_indent}connect {retval}, {}({enum_variant}, {variant_value})",
|
"{extra_indent}connect {retval}, {}({enum_variant}, {variant_value})",
|
||||||
enum_def.body
|
enum_def.body
|
||||||
|
|
@ -1329,15 +1488,18 @@ impl<'a> Exporter<'a> {
|
||||||
};
|
};
|
||||||
for (variant_index, variant) in ty.variants().into_iter().enumerate() {
|
for (variant_index, variant) in ty.variants().into_iter().enumerate() {
|
||||||
let when_cond = format!(
|
let when_cond = format!(
|
||||||
"eq(UInt<{discriminant_bit_width}>({variant_index}), tail({value_str}, {body_bit_width}))"
|
"eq(UInt<{discriminant_bit_width}>({variant_index}), \
|
||||||
|
tail({value_str}, {body_bit_width}))"
|
||||||
);
|
);
|
||||||
if variant_index == ty.variants().len() - 1 {
|
if variant_index == ty.variants().len() - 1 {
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}else:"));
|
definitions.add_definition_line(format_args!("{extra_indent}else:"));
|
||||||
} else if variant_index == 0 {
|
} else if variant_index == 0 {
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}when {when_cond}:"));
|
|
||||||
} else {
|
|
||||||
definitions
|
definitions
|
||||||
.add_definition_line(format_args!("{extra_indent}else when {when_cond}:"));
|
.add_definition_line(format_args!("{extra_indent}when {when_cond}:"));
|
||||||
|
} else {
|
||||||
|
definitions.add_definition_line(format_args!(
|
||||||
|
"{extra_indent}else when {when_cond}:"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let when_pushed_indent = extra_indent.push();
|
let when_pushed_indent = extra_indent.push();
|
||||||
let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?;
|
let enum_variant = self.type_state.get_enum_variant(ty, variant.name)?;
|
||||||
|
|
@ -1345,7 +1507,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,
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1361,20 +1523,28 @@ impl<'a> Exporter<'a> {
|
||||||
drop(when_pushed_indent);
|
drop(when_pushed_indent);
|
||||||
}
|
}
|
||||||
Ok(retval.to_string())
|
Ok(retval.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn expr_cast_bits_to_array(
|
fn expr_cast_bits_to_array(
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: Array,
|
ty: Array,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
definitions.get_or_write_definition(
|
||||||
|
(value_str, ty),
|
||||||
|
|c| &c.cast_bits_to_array_exprs,
|
||||||
|
|mut 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.add_definition_line(format_args!("{extra_indent}wire {retval}: {array_ty}"));
|
definitions
|
||||||
|
.add_definition_line(format_args!("{extra_indent}wire {retval}: {array_ty}"));
|
||||||
let element_bit_width = ty.element().bit_width();
|
let element_bit_width = ty.element().bit_width();
|
||||||
if ty.is_empty() || element_bit_width == 0 {
|
if ty.is_empty() || element_bit_width == 0 {
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
definitions
|
||||||
|
.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
||||||
return Ok(retval.to_string());
|
return Ok(retval.to_string());
|
||||||
}
|
}
|
||||||
let flattened_ident = self
|
let flattened_ident = self
|
||||||
|
|
@ -1387,14 +1557,15 @@ impl<'a> Exporter<'a> {
|
||||||
));
|
));
|
||||||
for index in 0..ty.len() {
|
for index in 0..ty.len() {
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
"{extra_indent}connect {flattened_ident}[{index}], bits({value_str}, {}, {})",
|
"{extra_indent}connect {flattened_ident}[{index}], \
|
||||||
|
bits({value_str}, {}, {})",
|
||||||
element_bit_width * index + element_bit_width - 1,
|
element_bit_width * index + element_bit_width - 1,
|
||||||
element_bit_width * index,
|
element_bit_width * index,
|
||||||
));
|
));
|
||||||
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(),
|
||||||
definitions,
|
&mut definitions,
|
||||||
extra_indent,
|
extra_indent,
|
||||||
)?;
|
)?;
|
||||||
definitions.add_definition_line(format_args!(
|
definitions.add_definition_line(format_args!(
|
||||||
|
|
@ -1402,12 +1573,14 @@ impl<'a> Exporter<'a> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(retval.to_string())
|
Ok(retval.to_string())
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn expr_cast_bits_to(
|
fn expr_cast_bits_to(
|
||||||
&mut self,
|
&mut self,
|
||||||
value_str: String,
|
value_str: String,
|
||||||
ty: CanonicalType,
|
ty: CanonicalType,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
extra_indent: Indent<'_>,
|
extra_indent: Indent<'_>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
match ty.unwrap_transparent_types() {
|
match ty.unwrap_transparent_types() {
|
||||||
|
|
@ -1427,12 +1600,18 @@ impl<'a> Exporter<'a> {
|
||||||
CanonicalType::AsyncReset(_) => Ok(format!("asAsyncReset({value_str})")),
|
CanonicalType::AsyncReset(_) => Ok(format!("asAsyncReset({value_str})")),
|
||||||
CanonicalType::SyncReset(_) => Ok(value_str),
|
CanonicalType::SyncReset(_) => Ok(value_str),
|
||||||
CanonicalType::Reset(_) => unreachable!("Reset is not bit castable to"),
|
CanonicalType::Reset(_) => unreachable!("Reset is not bit castable to"),
|
||||||
CanonicalType::PhantomConst(_) => {
|
CanonicalType::PhantomConst(ty) => definitions.get_or_write_definition(
|
||||||
|
(value_str, ty),
|
||||||
|
|c| &c.cast_bits_to_phantom_const_exprs,
|
||||||
|
|mut 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.add_definition_line(format_args!("{extra_indent}wire {retval}: {{}}"));
|
definitions
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
.add_definition_line(format_args!("{extra_indent}wire {retval}: {{}}"));
|
||||||
return Ok(retval.to_string());
|
definitions
|
||||||
}
|
.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
||||||
|
Ok(retval.to_string())
|
||||||
|
},
|
||||||
|
),
|
||||||
CanonicalType::DynSimOnly(_) => Err(FirrtlError::SimOnlyValuesAreNotPermitted.into()),
|
CanonicalType::DynSimOnly(_) => Err(FirrtlError::SimOnlyValuesAreNotPermitted.into()),
|
||||||
CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"),
|
CanonicalType::TraceAsString(_) => unreachable!("handled by unwrap_transparent_types"),
|
||||||
}
|
}
|
||||||
|
|
@ -1441,7 +1620,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &str,
|
func: &str,
|
||||||
arg: Expr<T>,
|
arg: Expr<T>,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
|
|
@ -1454,7 +1633,7 @@ impl<'a> Exporter<'a> {
|
||||||
func: &str,
|
func: &str,
|
||||||
lhs: Expr<Lhs>,
|
lhs: Expr<Lhs>,
|
||||||
rhs: Expr<Rhs>,
|
rhs: Expr<Rhs>,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
|
|
@ -1466,7 +1645,7 @@ impl<'a> Exporter<'a> {
|
||||||
fn expr(
|
fn expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Expr<CanonicalType>,
|
expr: Expr<CanonicalType>,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
const_ty: bool,
|
const_ty: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
match *Expr::expr_enum(expr) {
|
match *Expr::expr_enum(expr) {
|
||||||
|
|
@ -2062,7 +2241,7 @@ impl<'a> Exporter<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
stmt_reg: StmtReg<R>,
|
stmt_reg: StmtReg<R>,
|
||||||
module_name: Ident,
|
module_name: Ident,
|
||||||
definitions: &RcDefinitions,
|
definitions: &mut BlockDefinitions<'_>,
|
||||||
body: &mut String,
|
body: &mut String,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let StmtReg { annotations, reg } = stmt_reg;
|
let StmtReg { annotations, reg } = stmt_reg;
|
||||||
|
|
@ -2095,10 +2274,10 @@ impl<'a> Exporter<'a> {
|
||||||
module: Interned<Module<Bundle>>,
|
module: Interned<Module<Bundle>>,
|
||||||
block: Block,
|
block: Block,
|
||||||
_block_indent: &PushIndent<'_>,
|
_block_indent: &PushIndent<'_>,
|
||||||
definitions: Option<RcDefinitions>,
|
parent_definitions: &BlockDefinitions,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let indent = self.indent;
|
let indent = self.indent;
|
||||||
let definitions = definitions.unwrap_or_default();
|
let mut definitions = BlockDefinitions::new(parent_definitions);
|
||||||
let mut body = String::new();
|
let mut body = String::new();
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
let Block { memories, stmts } = block;
|
let Block { memories, stmts } = block;
|
||||||
|
|
@ -2122,8 +2301,8 @@ impl<'a> Exporter<'a> {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
let lhs = self.expr(lhs, &definitions, false)?;
|
let lhs = self.expr(lhs, &mut definitions, false)?;
|
||||||
let rhs = self.expr(rhs, &definitions, false)?;
|
let rhs = self.expr(rhs, &mut definitions, false)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
body,
|
body,
|
||||||
"{indent}connect {lhs}, {rhs}{}",
|
"{indent}connect {lhs}, {rhs}{}",
|
||||||
|
|
@ -2139,9 +2318,9 @@ impl<'a> Exporter<'a> {
|
||||||
text,
|
text,
|
||||||
source_location,
|
source_location,
|
||||||
}) => {
|
}) => {
|
||||||
let clk = self.expr(Expr::canonical(clk), &definitions, false)?;
|
let clk = self.expr(Expr::canonical(clk), &mut definitions, false)?;
|
||||||
let pred = self.expr(Expr::canonical(pred), &definitions, false)?;
|
let pred = self.expr(Expr::canonical(pred), &mut definitions, false)?;
|
||||||
let en = self.expr(Expr::canonical(en), &definitions, false)?;
|
let en = self.expr(Expr::canonical(en), &mut definitions, false)?;
|
||||||
let kind = match kind {
|
let kind = match kind {
|
||||||
FormalKind::Assert => "assert",
|
FormalKind::Assert => "assert",
|
||||||
FormalKind::Assume => "assume",
|
FormalKind::Assume => "assume",
|
||||||
|
|
@ -2166,7 +2345,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), &definitions, false)?;
|
let cond_str = self.expr(Expr::canonical(cond), &mut definitions, false)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
body,
|
body,
|
||||||
"{indent}{when} {cond_str}:{}",
|
"{indent}{when} {cond_str}:{}",
|
||||||
|
|
@ -2175,7 +2354,7 @@ impl<'a> Exporter<'a> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
pushed_indent = indent.push();
|
pushed_indent = indent.push();
|
||||||
let then_block_str =
|
let then_block_str =
|
||||||
self.block(module, then_block, &pushed_indent, None)?;
|
self.block(module, then_block, &pushed_indent, &definitions)?;
|
||||||
if !then_block_str.is_empty() {
|
if !then_block_str.is_empty() {
|
||||||
body.push_str(&then_block_str);
|
body.push_str(&then_block_str);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2193,7 +2372,8 @@ impl<'a> Exporter<'a> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let else_block = self.block(module, else_block, &pushed_indent, None)?;
|
let else_block =
|
||||||
|
self.block(module, else_block, &pushed_indent, &definitions)?;
|
||||||
drop(pushed_indent);
|
drop(pushed_indent);
|
||||||
if !else_block.is_empty() {
|
if !else_block.is_empty() {
|
||||||
writeln!(body, "{indent}else:").unwrap();
|
writeln!(body, "{indent}else:").unwrap();
|
||||||
|
|
@ -2208,7 +2388,7 @@ impl<'a> Exporter<'a> {
|
||||||
writeln!(
|
writeln!(
|
||||||
body,
|
body,
|
||||||
"{indent}match {}:{}",
|
"{indent}match {}:{}",
|
||||||
self.expr(Expr::canonical(expr), &definitions, false)?,
|
self.expr(Expr::canonical(expr), &mut definitions, false)?,
|
||||||
FileInfo::new(source_location),
|
FileInfo::new(source_location),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -2236,7 +2416,8 @@ impl<'a> Exporter<'a> {
|
||||||
};
|
};
|
||||||
body.push_str(":\n");
|
body.push_str(":\n");
|
||||||
let match_arm_indent = indent.push();
|
let match_arm_indent = indent.push();
|
||||||
let block = self.block(module, match_arm_block, &match_arm_indent, None)?;
|
let block =
|
||||||
|
self.block(module, match_arm_block, &match_arm_indent, &definitions)?;
|
||||||
if !block.is_empty() {
|
if !block.is_empty() {
|
||||||
body.push_str(&block);
|
body.push_str(&block);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2261,13 +2442,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, &definitions, &mut body)?;
|
self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?;
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegSync(stmt_reg)) => {
|
Stmt::Declaration(StmtDeclaration::RegSync(stmt_reg)) => {
|
||||||
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?;
|
self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?;
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegAsync(stmt_reg)) => {
|
Stmt::Declaration(StmtDeclaration::RegAsync(stmt_reg)) => {
|
||||||
self.stmt_reg(stmt_reg, module_name, &definitions, &mut body)?;
|
self.stmt_reg(stmt_reg, module_name, &mut definitions, &mut body)?;
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
||||||
annotations,
|
annotations,
|
||||||
|
|
@ -2286,7 +2467,7 @@ impl<'a> Exporter<'a> {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
definitions.write_and_clear(indent, &mut out);
|
definitions.write_out(indent, &mut out);
|
||||||
out.push_str(&body);
|
out.push_str(&body);
|
||||||
body.clear();
|
body.clear();
|
||||||
}
|
}
|
||||||
|
|
@ -2366,7 +2547,7 @@ impl<'a> Exporter<'a> {
|
||||||
module,
|
module,
|
||||||
top_block,
|
top_block,
|
||||||
&module_indent,
|
&module_indent,
|
||||||
Some(self.module.definitions.clone()),
|
&BlockDefinitions::none(),
|
||||||
)?);
|
)?);
|
||||||
"module"
|
"module"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
clock::{Clock, ClockDomain},
|
clock::{Clock, ClockDomain},
|
||||||
enum_::{Enum, EnumMatchVariantsIter, EnumType},
|
enum_::{Enum, EnumMatchVariantsIter, EnumType},
|
||||||
expr::{
|
expr::{
|
||||||
Expr, Flow, ToExpr, ValueType,
|
Expr, ExprEnum, Flow, ToExpr, ValueType,
|
||||||
ops::VariantAccess,
|
ops::VariantAccess,
|
||||||
target::{
|
target::{
|
||||||
GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField,
|
GetTarget, Target, TargetBase, TargetPathArrayElement, TargetPathBundleField,
|
||||||
|
|
@ -20,6 +20,7 @@ use crate::{
|
||||||
int::{Bool, DynSize, Size},
|
int::{Bool, DynSize, Size},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
memory::{Mem, MemBuilder, MemBuilderTarget, PortName},
|
||||||
|
module::transform::visit::{Visit, Visitor},
|
||||||
platform::PlatformIOBuilder,
|
platform::PlatformIOBuilder,
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
reset::{AsyncReset, Reset, ResetType, ResetTypeDispatch, SyncReset},
|
||||||
|
|
@ -1598,9 +1599,54 @@ impl TargetState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VisibleExprsStack {
|
||||||
|
buf: Vec<HashSet<ExprEnum>>,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VisibleExprsStack {
|
||||||
|
fn top(&mut self) -> &mut HashSet<ExprEnum> {
|
||||||
|
&mut self.buf[self.len - 1]
|
||||||
|
}
|
||||||
|
fn slice(&self) -> &[HashSet<ExprEnum>] {
|
||||||
|
&self.buf[..self.len]
|
||||||
|
}
|
||||||
|
fn contains(&self, v: &ExprEnum) -> bool {
|
||||||
|
self.slice().iter().any(|i| i.contains(v))
|
||||||
|
}
|
||||||
|
fn push_empty(&mut self) {
|
||||||
|
#[cold]
|
||||||
|
fn push_empty_cold(stack: &mut VisibleExprsStack) {
|
||||||
|
stack.buf.push(HashSet::default());
|
||||||
|
assert_eq!(stack.buf.len(), stack.len)
|
||||||
|
}
|
||||||
|
self.len += 1;
|
||||||
|
if self.len > self.buf.len() {
|
||||||
|
push_empty_cold(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn pop(&mut self) {
|
||||||
|
let Some(new_len) = self.len.checked_sub(1) else {
|
||||||
|
unreachable!("visible exprs stack underflow");
|
||||||
|
};
|
||||||
|
self.buf[new_len].clear();
|
||||||
|
self.len = new_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VisibleExprsStack {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
buf: Vec::new(),
|
||||||
|
len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AssertValidityState {
|
struct AssertValidityState {
|
||||||
module: Module<Bundle>,
|
module: Module<Bundle>,
|
||||||
blocks: Vec<Block>,
|
blocks: Vec<Block>,
|
||||||
|
visible_exprs: VisibleExprsStack,
|
||||||
target_states: HashMap<Interned<TargetBase>, TargetState>,
|
target_states: HashMap<Interned<TargetBase>, TargetState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1771,6 +1817,7 @@ impl AssertValidityState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[track_caller]
|
||||||
fn process_conditional_sub_blocks(
|
fn process_conditional_sub_blocks(
|
||||||
&mut self,
|
&mut self,
|
||||||
parent_block: usize,
|
parent_block: usize,
|
||||||
|
|
@ -1784,17 +1831,40 @@ impl AssertValidityState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
fn assert_expr_validity<T: Type>(&mut self, expr: Expr<T>, source_location: SourceLocation) {
|
||||||
|
let mut visitor = AssertExprValidity { state: self };
|
||||||
|
match visitor.visit_expr(&expr) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => match e {
|
||||||
|
InvalidExpr::ExprIsNotVisible(expr) => {
|
||||||
|
if let Some(target) = expr.target() {
|
||||||
|
panic!(
|
||||||
|
"at {source_location}: expression isn't visible here, it's defined:\n\
|
||||||
|
at {}: {expr:?}",
|
||||||
|
target.base().source_location(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
panic!("at {source_location}: expression isn't visible here: {expr:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
fn assert_subtree_validity(&mut self, block: usize) {
|
fn assert_subtree_validity(&mut self, block: usize) {
|
||||||
|
self.visible_exprs.push_empty();
|
||||||
let module = self.module;
|
let module = self.module;
|
||||||
if block == 0 {
|
if block == 0 {
|
||||||
for module_io in &*module.module_io {
|
for module_io in &*module.module_io {
|
||||||
self.insert_new_base(TargetBase::intern_sized(module_io.module_io.into()), block);
|
self.insert_new_base(TargetBase::intern_sized(module_io.module_io.into()), block);
|
||||||
|
self.visible_exprs.top().insert(module_io.module_io.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let Block { memories, stmts } = self.blocks[block];
|
let Block { memories, stmts } = self.blocks[block];
|
||||||
for m in memories {
|
for m in memories {
|
||||||
for port in m.ports() {
|
for port in m.ports() {
|
||||||
self.insert_new_base(TargetBase::intern_sized(port.into()), block);
|
self.insert_new_base(TargetBase::intern_sized(port.into()), block);
|
||||||
|
self.visible_exprs.top().insert(port.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
|
|
@ -1808,45 +1878,105 @@ impl AssertValidityState {
|
||||||
} = connect;
|
} = connect;
|
||||||
self.set_connect_side_written(lhs, source_location, true, block);
|
self.set_connect_side_written(lhs, source_location, true, block);
|
||||||
self.set_connect_side_written(rhs, source_location, false, block);
|
self.set_connect_side_written(rhs, source_location, false, block);
|
||||||
|
self.assert_expr_validity(lhs, source_location);
|
||||||
|
self.assert_expr_validity(rhs, source_location);
|
||||||
|
}
|
||||||
|
Stmt::Formal(formal) => {
|
||||||
|
let StmtFormal {
|
||||||
|
kind: _,
|
||||||
|
clk,
|
||||||
|
pred,
|
||||||
|
en,
|
||||||
|
text: _,
|
||||||
|
source_location,
|
||||||
|
} = formal;
|
||||||
|
self.assert_expr_validity(clk, source_location);
|
||||||
|
self.assert_expr_validity(pred, source_location);
|
||||||
|
self.assert_expr_validity(en, source_location);
|
||||||
}
|
}
|
||||||
Stmt::Formal(_) => {}
|
|
||||||
Stmt::If(if_stmt) => {
|
Stmt::If(if_stmt) => {
|
||||||
let sub_blocks = if_stmt.blocks.map(|block| self.make_block_index(block));
|
let StmtIf {
|
||||||
|
cond,
|
||||||
|
source_location,
|
||||||
|
blocks: sub_blocks,
|
||||||
|
} = if_stmt;
|
||||||
|
self.assert_expr_validity(cond, source_location);
|
||||||
|
let sub_blocks = sub_blocks.map(|block| self.make_block_index(block));
|
||||||
self.process_conditional_sub_blocks(block, sub_blocks)
|
self.process_conditional_sub_blocks(block, sub_blocks)
|
||||||
}
|
}
|
||||||
Stmt::Match(match_stmt) => {
|
Stmt::Match(match_stmt) => {
|
||||||
match_stmt.assert_validity();
|
match_stmt.assert_validity();
|
||||||
|
let StmtMatch {
|
||||||
|
expr,
|
||||||
|
source_location,
|
||||||
|
blocks: sub_blocks,
|
||||||
|
} = match_stmt;
|
||||||
|
self.assert_expr_validity(expr, source_location);
|
||||||
let sub_blocks = Vec::from_iter(
|
let sub_blocks = Vec::from_iter(
|
||||||
match_stmt
|
sub_blocks
|
||||||
.blocks
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|block| self.make_block_index(block)),
|
.map(|block| self.make_block_index(block)),
|
||||||
);
|
);
|
||||||
self.process_conditional_sub_blocks(block, sub_blocks.iter().copied())
|
self.visible_exprs.push_empty();
|
||||||
|
let visible_exprs_top = self.visible_exprs.top();
|
||||||
|
for variant_index in 0..expr.ty().variants().len() {
|
||||||
|
visible_exprs_top
|
||||||
|
.insert(<VariantAccess>::new_by_index(expr, variant_index).into());
|
||||||
|
}
|
||||||
|
self.process_conditional_sub_blocks(block, sub_blocks.iter().copied());
|
||||||
|
self.visible_exprs.pop();
|
||||||
}
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Wire(StmtWire {
|
Stmt::Declaration(StmtDeclaration::Wire(StmtWire {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
wire,
|
wire,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(wire.into()), block),
|
})) => {
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(wire.into()), block);
|
||||||
|
self.visible_exprs.top().insert(wire.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Reg(StmtReg {
|
Stmt::Declaration(StmtDeclaration::Reg(StmtReg {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
reg,
|
reg,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
|
})) => {
|
||||||
|
self.assert_expr_validity(reg.clock_domain(), reg.source_location());
|
||||||
|
if let Some(init) = reg.init() {
|
||||||
|
self.assert_expr_validity(init, reg.source_location());
|
||||||
|
}
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(reg.into()), block);
|
||||||
|
self.visible_exprs.top().insert(reg.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegSync(StmtReg {
|
Stmt::Declaration(StmtDeclaration::RegSync(StmtReg {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
reg,
|
reg,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
|
})) => {
|
||||||
|
self.assert_expr_validity(reg.clock_domain(), reg.source_location());
|
||||||
|
if let Some(init) = reg.init() {
|
||||||
|
self.assert_expr_validity(init, reg.source_location());
|
||||||
|
}
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(reg.into()), block);
|
||||||
|
self.visible_exprs.top().insert(reg.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::RegAsync(StmtReg {
|
Stmt::Declaration(StmtDeclaration::RegAsync(StmtReg {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
reg,
|
reg,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(reg.into()), block),
|
})) => {
|
||||||
|
self.assert_expr_validity(reg.clock_domain(), reg.source_location());
|
||||||
|
if let Some(init) = reg.init() {
|
||||||
|
self.assert_expr_validity(init, reg.source_location());
|
||||||
|
}
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(reg.into()), block);
|
||||||
|
self.visible_exprs.top().insert(reg.into());
|
||||||
|
}
|
||||||
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
Stmt::Declaration(StmtDeclaration::Instance(StmtInstance {
|
||||||
annotations: _,
|
annotations: _,
|
||||||
instance,
|
instance,
|
||||||
})) => self.insert_new_base(TargetBase::intern_sized(instance.into()), block),
|
})) => {
|
||||||
|
self.insert_new_base(TargetBase::intern_sized(instance.into()), block);
|
||||||
|
self.visible_exprs.top().insert(instance.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.visible_exprs.pop();
|
||||||
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn assert_validity(&mut self) {
|
fn assert_validity(&mut self) {
|
||||||
match self.module.body {
|
match self.module.body {
|
||||||
|
|
@ -1874,6 +2004,140 @@ impl AssertValidityState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AssertExprValidity<'a> {
|
||||||
|
state: &'a mut AssertValidityState,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InvalidExpr {
|
||||||
|
ExprIsNotVisible(Expr<CanonicalType>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl transform::visit::Visitor for AssertExprValidity<'_> {
|
||||||
|
type Error = InvalidExpr;
|
||||||
|
fn visit_expr_enum(&mut self, v: &ExprEnum) -> Result<(), Self::Error> {
|
||||||
|
match v {
|
||||||
|
ExprEnum::UIntLiteral(_)
|
||||||
|
| ExprEnum::SIntLiteral(_)
|
||||||
|
| ExprEnum::BoolLiteral(_)
|
||||||
|
| ExprEnum::PhantomConst(_)
|
||||||
|
| ExprEnum::BundleLiteral(_)
|
||||||
|
| ExprEnum::ArrayLiteral(_)
|
||||||
|
| ExprEnum::EnumLiteral(_)
|
||||||
|
| ExprEnum::Uninit(_)
|
||||||
|
| ExprEnum::NotU(_)
|
||||||
|
| ExprEnum::NotS(_)
|
||||||
|
| ExprEnum::NotB(_)
|
||||||
|
| ExprEnum::Neg(_)
|
||||||
|
| ExprEnum::BitAndU(_)
|
||||||
|
| ExprEnum::BitAndS(_)
|
||||||
|
| ExprEnum::BitAndB(_)
|
||||||
|
| ExprEnum::BitOrU(_)
|
||||||
|
| ExprEnum::BitOrS(_)
|
||||||
|
| ExprEnum::BitOrB(_)
|
||||||
|
| ExprEnum::BitXorU(_)
|
||||||
|
| ExprEnum::BitXorS(_)
|
||||||
|
| ExprEnum::BitXorB(_)
|
||||||
|
| ExprEnum::AddU(_)
|
||||||
|
| ExprEnum::AddS(_)
|
||||||
|
| ExprEnum::SubU(_)
|
||||||
|
| ExprEnum::SubS(_)
|
||||||
|
| ExprEnum::MulU(_)
|
||||||
|
| ExprEnum::MulS(_)
|
||||||
|
| ExprEnum::DivU(_)
|
||||||
|
| ExprEnum::DivS(_)
|
||||||
|
| ExprEnum::RemU(_)
|
||||||
|
| ExprEnum::RemS(_)
|
||||||
|
| ExprEnum::DynShlU(_)
|
||||||
|
| ExprEnum::DynShlS(_)
|
||||||
|
| ExprEnum::DynShrU(_)
|
||||||
|
| ExprEnum::DynShrS(_)
|
||||||
|
| ExprEnum::FixedShlU(_)
|
||||||
|
| ExprEnum::FixedShlS(_)
|
||||||
|
| ExprEnum::FixedShrU(_)
|
||||||
|
| ExprEnum::FixedShrS(_)
|
||||||
|
| ExprEnum::CmpLtB(_)
|
||||||
|
| ExprEnum::CmpLeB(_)
|
||||||
|
| ExprEnum::CmpGtB(_)
|
||||||
|
| ExprEnum::CmpGeB(_)
|
||||||
|
| ExprEnum::CmpEqB(_)
|
||||||
|
| ExprEnum::CmpNeB(_)
|
||||||
|
| ExprEnum::CmpLtU(_)
|
||||||
|
| ExprEnum::CmpLeU(_)
|
||||||
|
| ExprEnum::CmpGtU(_)
|
||||||
|
| ExprEnum::CmpGeU(_)
|
||||||
|
| ExprEnum::CmpEqU(_)
|
||||||
|
| ExprEnum::CmpNeU(_)
|
||||||
|
| ExprEnum::CmpLtS(_)
|
||||||
|
| ExprEnum::CmpLeS(_)
|
||||||
|
| ExprEnum::CmpGtS(_)
|
||||||
|
| ExprEnum::CmpGeS(_)
|
||||||
|
| ExprEnum::CmpEqS(_)
|
||||||
|
| ExprEnum::CmpNeS(_)
|
||||||
|
| ExprEnum::CastUIntToUInt(_)
|
||||||
|
| ExprEnum::CastUIntToSInt(_)
|
||||||
|
| ExprEnum::CastSIntToUInt(_)
|
||||||
|
| ExprEnum::CastSIntToSInt(_)
|
||||||
|
| ExprEnum::CastBoolToUInt(_)
|
||||||
|
| ExprEnum::CastBoolToSInt(_)
|
||||||
|
| ExprEnum::CastUIntToBool(_)
|
||||||
|
| ExprEnum::CastSIntToBool(_)
|
||||||
|
| ExprEnum::CastBoolToSyncReset(_)
|
||||||
|
| ExprEnum::CastUIntToSyncReset(_)
|
||||||
|
| ExprEnum::CastSIntToSyncReset(_)
|
||||||
|
| ExprEnum::CastBoolToAsyncReset(_)
|
||||||
|
| ExprEnum::CastUIntToAsyncReset(_)
|
||||||
|
| ExprEnum::CastSIntToAsyncReset(_)
|
||||||
|
| ExprEnum::CastSyncResetToBool(_)
|
||||||
|
| ExprEnum::CastSyncResetToUInt(_)
|
||||||
|
| ExprEnum::CastSyncResetToSInt(_)
|
||||||
|
| ExprEnum::CastSyncResetToReset(_)
|
||||||
|
| ExprEnum::CastAsyncResetToBool(_)
|
||||||
|
| ExprEnum::CastAsyncResetToUInt(_)
|
||||||
|
| ExprEnum::CastAsyncResetToSInt(_)
|
||||||
|
| ExprEnum::CastAsyncResetToReset(_)
|
||||||
|
| ExprEnum::CastResetToBool(_)
|
||||||
|
| ExprEnum::CastResetToUInt(_)
|
||||||
|
| ExprEnum::CastResetToSInt(_)
|
||||||
|
| ExprEnum::CastBoolToClock(_)
|
||||||
|
| ExprEnum::CastUIntToClock(_)
|
||||||
|
| ExprEnum::CastSIntToClock(_)
|
||||||
|
| ExprEnum::CastClockToBool(_)
|
||||||
|
| ExprEnum::CastClockToUInt(_)
|
||||||
|
| ExprEnum::CastClockToSInt(_)
|
||||||
|
| ExprEnum::FieldAccess(_)
|
||||||
|
| ExprEnum::ArrayIndex(_)
|
||||||
|
| ExprEnum::DynArrayIndex(_)
|
||||||
|
| ExprEnum::ReduceBitAndU(_)
|
||||||
|
| ExprEnum::ReduceBitAndS(_)
|
||||||
|
| ExprEnum::ReduceBitOrU(_)
|
||||||
|
| ExprEnum::ReduceBitOrS(_)
|
||||||
|
| ExprEnum::ReduceBitXorU(_)
|
||||||
|
| ExprEnum::ReduceBitXorS(_)
|
||||||
|
| ExprEnum::SliceUInt(_)
|
||||||
|
| ExprEnum::SliceSInt(_)
|
||||||
|
| ExprEnum::CastToBits(_)
|
||||||
|
| ExprEnum::CastBitsTo(_)
|
||||||
|
| ExprEnum::ToTraceAsString(_)
|
||||||
|
| ExprEnum::TraceAsStringAsInner(_) => v.default_visit(self),
|
||||||
|
ExprEnum::VariantAccess(_)
|
||||||
|
| ExprEnum::ModuleIO(_)
|
||||||
|
| ExprEnum::Instance(_)
|
||||||
|
| ExprEnum::Wire(_)
|
||||||
|
| ExprEnum::Reg(_)
|
||||||
|
| ExprEnum::RegSync(_)
|
||||||
|
| ExprEnum::RegAsync(_)
|
||||||
|
| ExprEnum::MemPort(_) => {
|
||||||
|
if self.state.visible_exprs.contains(v) {
|
||||||
|
// no need to visit inner expressions, we already checked them before adding them to visible_exprs
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(InvalidExpr::ExprIsNotVisible(v.to_expr()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: BundleType> Module<T> {
|
impl<T: BundleType> Module<T> {
|
||||||
/// you generally should use the [`#[hdl_module]`][`crate::hdl_module`] proc-macro and [`ModuleBuilder`] instead
|
/// you generally should use the [`#[hdl_module]`][`crate::hdl_module`] proc-macro and [`ModuleBuilder`] instead
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
|
@ -1999,6 +2263,7 @@ impl<T: BundleType> Module<T> {
|
||||||
AssertValidityState {
|
AssertValidityState {
|
||||||
module: self.canonical(),
|
module: self.canonical(),
|
||||||
blocks: vec![],
|
blocks: vec![],
|
||||||
|
visible_exprs: VisibleExprsStack::default(),
|
||||||
target_states: HashMap::with_capacity_and_hasher(64, Default::default()),
|
target_states: HashMap::with_capacity_and_hasher(64, Default::default()),
|
||||||
}
|
}
|
||||||
.assert_validity();
|
.assert_validity();
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ enum EnumTypeState {
|
||||||
|
|
||||||
struct ModuleState {
|
struct ModuleState {
|
||||||
module_name: NameId,
|
module_name: NameId,
|
||||||
|
expr_cache: HashMap<ExprEnum, ExprEnum>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleState {
|
impl ModuleState {
|
||||||
|
|
@ -675,6 +676,7 @@ impl Folder for State {
|
||||||
fn fold_module<T: BundleType>(&mut self, v: Module<T>) -> Result<Module<T>, Self::Error> {
|
fn fold_module<T: BundleType>(&mut self, v: Module<T>) -> Result<Module<T>, Self::Error> {
|
||||||
self.module_state_stack.push(ModuleState {
|
self.module_state_stack.push(ModuleState {
|
||||||
module_name: v.name_id(),
|
module_name: v.name_id(),
|
||||||
|
expr_cache: HashMap::default(),
|
||||||
});
|
});
|
||||||
let retval = Fold::default_fold(v, self);
|
let retval = Fold::default_fold(v, self);
|
||||||
self.module_state_stack.pop();
|
self.module_state_stack.pop();
|
||||||
|
|
@ -682,30 +684,39 @@ impl Folder for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_expr_enum(&mut self, op: ExprEnum) -> Result<ExprEnum, Self::Error> {
|
fn fold_expr_enum(&mut self, op: ExprEnum) -> Result<ExprEnum, Self::Error> {
|
||||||
match op {
|
if let Some(folded_op) = self
|
||||||
|
.module_state_stack
|
||||||
|
.last()
|
||||||
|
.expect("known to be in module")
|
||||||
|
.expr_cache
|
||||||
|
.get(&op)
|
||||||
|
{
|
||||||
|
return Ok(*folded_op);
|
||||||
|
}
|
||||||
|
let folded_op = match op {
|
||||||
ExprEnum::EnumLiteral(op) => {
|
ExprEnum::EnumLiteral(op) => {
|
||||||
let folded_variant_value = op.variant_value().map(|v| v.fold(self)).transpose()?;
|
let folded_variant_value = op.variant_value().map(|v| v.fold(self)).transpose()?;
|
||||||
Ok(*Expr::expr_enum(self.handle_enum_literal(
|
*Expr::expr_enum(self.handle_enum_literal(
|
||||||
op.ty(),
|
op.ty(),
|
||||||
op.variant_index(),
|
op.variant_index(),
|
||||||
folded_variant_value,
|
folded_variant_value,
|
||||||
)?))
|
)?)
|
||||||
}
|
}
|
||||||
ExprEnum::VariantAccess(op) => {
|
ExprEnum::VariantAccess(op) => {
|
||||||
let folded_base_expr = Expr::canonical(op.base()).fold(self)?;
|
let folded_base_expr = Expr::canonical(op.base()).fold(self)?;
|
||||||
Ok(*Expr::expr_enum(self.handle_variant_access(
|
*Expr::expr_enum(self.handle_variant_access(
|
||||||
op.base().ty(),
|
op.base().ty(),
|
||||||
folded_base_expr,
|
folded_base_expr,
|
||||||
op.variant_index(),
|
op.variant_index(),
|
||||||
)?))
|
)?)
|
||||||
}
|
}
|
||||||
ExprEnum::MemPort(mem_port) => Ok(
|
ExprEnum::MemPort(mem_port) => {
|
||||||
if let Some(&wire) = self.replacement_mem_ports.get(&mem_port) {
|
if let Some(&wire) = self.replacement_mem_ports.get(&mem_port) {
|
||||||
ExprEnum::Wire(wire)
|
ExprEnum::Wire(wire)
|
||||||
} else {
|
} else {
|
||||||
ExprEnum::MemPort(mem_port.fold(self)?)
|
ExprEnum::MemPort(mem_port.fold(self)?)
|
||||||
},
|
}
|
||||||
),
|
}
|
||||||
ExprEnum::UIntLiteral(_)
|
ExprEnum::UIntLiteral(_)
|
||||||
| ExprEnum::SIntLiteral(_)
|
| ExprEnum::SIntLiteral(_)
|
||||||
| ExprEnum::BoolLiteral(_)
|
| ExprEnum::BoolLiteral(_)
|
||||||
|
|
@ -813,8 +824,14 @@ impl Folder for State {
|
||||||
| ExprEnum::Wire(_)
|
| ExprEnum::Wire(_)
|
||||||
| ExprEnum::Reg(_)
|
| ExprEnum::Reg(_)
|
||||||
| ExprEnum::RegSync(_)
|
| ExprEnum::RegSync(_)
|
||||||
| ExprEnum::RegAsync(_) => op.default_fold(self),
|
| ExprEnum::RegAsync(_) => op.default_fold(self)?,
|
||||||
}
|
};
|
||||||
|
self.module_state_stack
|
||||||
|
.last_mut()
|
||||||
|
.expect("known to be in module")
|
||||||
|
.expr_cache
|
||||||
|
.insert(op, folded_op);
|
||||||
|
Ok(folded_op)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_block(&mut self, block: Block) -> Result<Block, Self::Error> {
|
fn fold_block(&mut self, block: Block) -> Result<Block, Self::Error> {
|
||||||
|
|
|
||||||
|
|
@ -1309,16 +1309,49 @@ trait TraceAsStringTrait: fmt::Debug + 'static + Send + Sync + SupportsPtrEqWith
|
||||||
fn can_substitute_type(&self, new_type: CanonicalType) -> bool;
|
fn can_substitute_type(&self, new_type: CanonicalType) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Type> TraceAsStringTrait for T {
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct TraceAsStringState<T: Type> {
|
||||||
|
ty: Interned<T>,
|
||||||
|
canonical_ty: CanonicalType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> TraceAsStringState<T> {
|
||||||
|
fn new(ty: Interned<T>) -> Interned<Self> {
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct MyMemoize<T: Type>(PhantomData<T>);
|
||||||
|
impl<T: Type> Memoize for MyMemoize<T> {
|
||||||
|
type Input = Interned<T>;
|
||||||
|
type InputOwned = Interned<T>;
|
||||||
|
type Output = Interned<TraceAsStringState<T>>;
|
||||||
|
|
||||||
|
fn inner(self, input: &Self::Input) -> Self::Output {
|
||||||
|
TraceAsStringState {
|
||||||
|
ty: *input,
|
||||||
|
canonical_ty: input.canonical(),
|
||||||
|
}
|
||||||
|
.intern_sized()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MyMemoize(PhantomData).get_owned(ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> fmt::Debug for TraceAsStringState<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.ty.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> TraceAsStringTrait for TraceAsStringState<T> {
|
||||||
fn trace_fmt(
|
fn trace_fmt(
|
||||||
&self,
|
&self,
|
||||||
opaque: OpaqueSimValueSlice<'_>,
|
opaque: OpaqueSimValueSlice<'_>,
|
||||||
f: &mut fmt::Formatter<'_>,
|
f: &mut fmt::Formatter<'_>,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&Type::sim_value_from_opaque(self, opaque), f)
|
fmt::Debug::fmt(&Type::sim_value_from_opaque(&*self.ty, opaque), f)
|
||||||
}
|
}
|
||||||
fn can_substitute_type(&self, new_type: CanonicalType) -> bool {
|
fn can_substitute_type(&self, new_type: CanonicalType) -> bool {
|
||||||
self.canonical().is_layout_equivalent(new_type)
|
self.canonical_ty.is_layout_equivalent(new_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1374,7 +1407,7 @@ impl<T: Type> TraceAsString<T> {
|
||||||
Self {
|
Self {
|
||||||
inner_ty: LazyInterned::Interned(inner_ty),
|
inner_ty: LazyInterned::Interned(inner_ty),
|
||||||
trace_as_string: LazyInterned::Interned(Interned::cast_unchecked(
|
trace_as_string: LazyInterned::Interned(Interned::cast_unchecked(
|
||||||
inner_ty,
|
TraceAsStringState::new(inner_ty),
|
||||||
|v| -> &dyn TraceAsStringTrait { v },
|
|v| -> &dyn TraceAsStringTrait { v },
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
|
@ -1548,7 +1581,10 @@ impl<T: StaticType> Default for TraceAsStringStaticTypeHelper<T> {
|
||||||
|
|
||||||
impl<T: StaticType> From<TraceAsStringStaticTypeHelper<T>> for Interned<dyn TraceAsStringTrait> {
|
impl<T: StaticType> From<TraceAsStringStaticTypeHelper<T>> for Interned<dyn TraceAsStringTrait> {
|
||||||
fn from(_value: TraceAsStringStaticTypeHelper<T>) -> Self {
|
fn from(_value: TraceAsStringStaticTypeHelper<T>) -> Self {
|
||||||
Interned::cast_unchecked(T::TYPE.intern_sized(), |v| -> &dyn TraceAsStringTrait { v })
|
Interned::cast_unchecked(
|
||||||
|
TraceAsStringState::new(T::TYPE.intern_sized()),
|
||||||
|
|v| -> &dyn TraceAsStringTrait { v },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -808,40 +808,8 @@ circuit check_enum_cmp_eq:
|
||||||
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
||||||
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
|
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
|
||||||
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
|
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
|
||||||
wire _cast_bits_to_array_expr_2: UInt<1>[3]
|
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1])
|
||||||
wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3]
|
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[2])
|
||||||
connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2]
|
|
||||||
wire _cast_bits_to_array_expr_3: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2]
|
|
||||||
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1])
|
|
||||||
wire _cast_bits_to_array_expr_4: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2]
|
|
||||||
wire _cast_bits_to_array_expr_5: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2]
|
|
||||||
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2])
|
|
||||||
wire _cast_array_to_bits_expr: UInt<1>[3]
|
wire _cast_array_to_bits_expr: UInt<1>[3]
|
||||||
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
|
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
|
||||||
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
|
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
|
||||||
|
|
@ -901,40 +869,8 @@ circuit check_enum_cmp_eq:
|
||||||
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
||||||
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
|
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
|
||||||
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
|
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
|
||||||
wire _cast_bits_to_array_expr_2: UInt<1>[3]
|
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1])
|
||||||
wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3]
|
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[2])
|
||||||
connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(lhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(lhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(lhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2]
|
|
||||||
wire _cast_bits_to_array_expr_3: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(rhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(rhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2]
|
|
||||||
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1])
|
|
||||||
wire _cast_bits_to_array_expr_4: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(lhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(lhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(lhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2]
|
|
||||||
wire _cast_bits_to_array_expr_5: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(rhs.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(rhs.body, 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(rhs.body, 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2]
|
|
||||||
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2])
|
|
||||||
wire _cast_array_to_bits_expr: UInt<1>[3]
|
wire _cast_array_to_bits_expr: UInt<1>[3]
|
||||||
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
|
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
|
||||||
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
|
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
|
||||||
|
|
@ -993,40 +929,8 @@ circuit check_enum_cmp_eq:
|
||||||
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2)
|
connect _cast_bits_to_array_expr_flattened_1[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2)
|
||||||
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
|
connect _cast_bits_to_array_expr_1[2], _cast_bits_to_array_expr_flattened_1[2]
|
||||||
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
|
connect _array_literal_expr[0], eq(_cast_bits_to_array_expr[0], _cast_bits_to_array_expr_1[0])
|
||||||
wire _cast_bits_to_array_expr_2: UInt<1>[3]
|
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr[1], _cast_bits_to_array_expr_1[1])
|
||||||
wire _cast_bits_to_array_expr_flattened_2: UInt<1>[3]
|
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr[2], _cast_bits_to_array_expr_1[2])
|
||||||
connect _cast_bits_to_array_expr_flattened_2[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_2[0], _cast_bits_to_array_expr_flattened_2[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_2[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_flattened_2[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_2[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_2[2], _cast_bits_to_array_expr_flattened_2[2]
|
|
||||||
wire _cast_bits_to_array_expr_3: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_3: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_3[0], _cast_bits_to_array_expr_flattened_3[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_3[1], _cast_bits_to_array_expr_flattened_3[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_3[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_3[2], _cast_bits_to_array_expr_flattened_3[2]
|
|
||||||
connect _array_literal_expr[1], eq(_cast_bits_to_array_expr_2[1], _cast_bits_to_array_expr_3[1])
|
|
||||||
wire _cast_bits_to_array_expr_4: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_4: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[0], bits(bits(bits(lhs, 9, 2), 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_4[0], _cast_bits_to_array_expr_flattened_4[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[1], bits(bits(bits(lhs, 9, 2), 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_4[1], _cast_bits_to_array_expr_flattened_4[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_4[2], bits(bits(bits(lhs, 9, 2), 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_flattened_4[2]
|
|
||||||
wire _cast_bits_to_array_expr_5: UInt<1>[3]
|
|
||||||
wire _cast_bits_to_array_expr_flattened_5: UInt<1>[3]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[0], bits(bits(bits(rhs, 9, 2), 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_array_expr_5[0], _cast_bits_to_array_expr_flattened_5[0]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[1], bits(bits(bits(rhs, 9, 2), 2, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_array_expr_5[1], _cast_bits_to_array_expr_flattened_5[1]
|
|
||||||
connect _cast_bits_to_array_expr_flattened_5[2], bits(bits(bits(rhs, 9, 2), 2, 0), 2, 2)
|
|
||||||
connect _cast_bits_to_array_expr_5[2], _cast_bits_to_array_expr_flattened_5[2]
|
|
||||||
connect _array_literal_expr[2], eq(_cast_bits_to_array_expr_4[2], _cast_bits_to_array_expr_5[2])
|
|
||||||
wire _cast_array_to_bits_expr: UInt<1>[3]
|
wire _cast_array_to_bits_expr: UInt<1>[3]
|
||||||
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
|
connect _cast_array_to_bits_expr[0], _array_literal_expr[0]
|
||||||
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
|
connect _cast_array_to_bits_expr[1], _array_literal_expr[1]
|
||||||
|
|
@ -3925,21 +3829,10 @@ circuit check_enum_connect_any:
|
||||||
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
HdlSome:
|
HdlSome:
|
||||||
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_1: Ty5
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_1: Ty6
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 2, 0), 0, 0)
|
|
||||||
wire _cast_bits_to_enum_expr_1: Ty3
|
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_1.tag, 0)):
|
|
||||||
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlNone)
|
|
||||||
else:
|
|
||||||
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlSome)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_enum_expr_1
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.body, bits(bits(i2.body, 2, 0), 2, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<1>
|
; lhs: SInt<1>
|
||||||
; rhs: SInt<2>
|
; rhs: SInt<2>
|
||||||
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr_1.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_2: Ty4
|
wire _bundle_literal_expr_2: Ty4
|
||||||
connect _bundle_literal_expr_2.tag, {|HdlNone, HdlSome|}(HdlSome)
|
connect _bundle_literal_expr_2.tag, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
||||||
|
|
@ -3961,18 +3854,18 @@ circuit check_enum_connect_any:
|
||||||
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
C:
|
C:
|
||||||
wire __connect_variant_body_3: Ty8 @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_3: Ty8 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_2: Ty8
|
wire _cast_bits_to_bundle_expr_1: Ty8
|
||||||
wire _cast_bits_to_bundle_expr_flattened_2: Ty9
|
wire _cast_bits_to_bundle_expr_flattened_1: Ty9
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
||||||
wire _cast_bits_to_enum_expr_2: Ty3
|
wire _cast_bits_to_enum_expr_1: Ty3
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_2.tag, 0)):
|
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_1.tag, 0)):
|
||||||
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlNone)
|
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
else:
|
else:
|
||||||
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlSome)
|
connect _cast_bits_to_enum_expr_1, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_enum_expr_2
|
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_enum_expr_1
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_1.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
||||||
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_2 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_4: Ty1
|
wire _bundle_literal_expr_4: Ty1
|
||||||
connect _bundle_literal_expr_4.tag, {|A, B, C|}(C)
|
connect _bundle_literal_expr_4.tag, {|A, B, C|}(C)
|
||||||
wire _cast_bundle_to_bits_expr_1: Ty9
|
wire _cast_bundle_to_bits_expr_1: Ty9
|
||||||
|
|
@ -4001,18 +3894,18 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
B:
|
B:
|
||||||
wire __connect_variant_body_5: Ty5 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_5: Ty5 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_3: Ty4
|
wire _cast_bits_to_bundle_expr_2: Ty4
|
||||||
wire _cast_bits_to_bundle_expr_flattened_3: Ty7
|
wire _cast_bits_to_bundle_expr_flattened_2: Ty7
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
||||||
wire _cast_bits_to_enum_expr_3: Ty3
|
wire _cast_bits_to_enum_expr_2: Ty3
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_3.tag, 0)):
|
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_2.tag, 0)):
|
||||||
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlNone)
|
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
else:
|
else:
|
||||||
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlSome)
|
connect _cast_bits_to_enum_expr_2, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_enum_expr_3
|
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_enum_expr_2
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.body, bits(bits(i1.body, 1, 0), 1, 1)
|
connect _cast_bits_to_bundle_expr_flattened_2.body, bits(bits(i1.body, 1, 0), 1, 1)
|
||||||
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
||||||
match _cast_bits_to_bundle_expr_3.tag: @[module-XXXXXXXXXX.rs 9:1]
|
match _cast_bits_to_bundle_expr_2.tag: @[module-XXXXXXXXXX.rs 9:1]
|
||||||
HdlNone:
|
HdlNone:
|
||||||
wire _bundle_literal_expr_6: Ty5
|
wire _bundle_literal_expr_6: Ty5
|
||||||
connect _bundle_literal_expr_6.tag, {|HdlNone, HdlSome|}(HdlNone)
|
connect _bundle_literal_expr_6.tag, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
|
|
@ -4020,21 +3913,10 @@ circuit check_enum_connect_any:
|
||||||
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
HdlSome:
|
HdlSome:
|
||||||
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_4: Ty4
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_4: Ty7
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
|
||||||
wire _cast_bits_to_enum_expr_4: Ty3
|
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_4.tag, 0)):
|
|
||||||
connect _cast_bits_to_enum_expr_4, {|HdlNone, HdlSome|}(HdlNone)
|
|
||||||
else:
|
|
||||||
connect _cast_bits_to_enum_expr_4, {|HdlNone, HdlSome|}(HdlSome)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.tag, _cast_bits_to_enum_expr_4
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.body, bits(bits(i1.body, 1, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.body, _cast_bits_to_bundle_expr_flattened_4.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<2>
|
; lhs: SInt<2>
|
||||||
; rhs: SInt<1>
|
; rhs: SInt<1>
|
||||||
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_4.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_2.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_7: Ty5
|
wire _bundle_literal_expr_7: Ty5
|
||||||
connect _bundle_literal_expr_7.tag, {|HdlNone, HdlSome|}(HdlSome)
|
connect _bundle_literal_expr_7.tag, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
||||||
|
|
@ -4056,18 +3938,18 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
C:
|
C:
|
||||||
wire __connect_variant_body_7: Ty8 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_7: Ty8 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_5: Ty8
|
wire _cast_bits_to_bundle_expr_3: Ty8
|
||||||
wire _cast_bits_to_bundle_expr_flattened_5: Ty9
|
wire _cast_bits_to_bundle_expr_flattened_3: Ty9
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
||||||
wire _cast_bits_to_enum_expr_5: Ty3
|
wire _cast_bits_to_enum_expr_3: Ty3
|
||||||
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_5.tag, 0)):
|
when eq(UInt<1>(0), tail(_cast_bits_to_bundle_expr_flattened_3.tag, 0)):
|
||||||
connect _cast_bits_to_enum_expr_5, {|HdlNone, HdlSome|}(HdlNone)
|
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlNone)
|
||||||
else:
|
else:
|
||||||
connect _cast_bits_to_enum_expr_5, {|HdlNone, HdlSome|}(HdlSome)
|
connect _cast_bits_to_enum_expr_3, {|HdlNone, HdlSome|}(HdlSome)
|
||||||
connect _cast_bits_to_bundle_expr_5.tag, _cast_bits_to_enum_expr_5
|
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_enum_expr_3
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_3.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_5.body, _cast_bits_to_bundle_expr_flattened_5.body
|
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
||||||
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_3 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_9: Ty2
|
wire _bundle_literal_expr_9: Ty2
|
||||||
connect _bundle_literal_expr_9.tag, {|A, B, C|}(C)
|
connect _bundle_literal_expr_9.tag, {|A, B, C|}(C)
|
||||||
wire _cast_bundle_to_bits_expr_3: Ty9
|
wire _cast_bundle_to_bits_expr_3: Ty9
|
||||||
|
|
@ -4134,16 +4016,10 @@ circuit check_enum_connect_any:
|
||||||
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_1, _bundle_literal_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_2: SInt<1> @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_1: Ty3
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_1: Ty3
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 2, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_bundle_expr_flattened_1.tag
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_1.body, bits(bits(i2.body, 2, 0), 2, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<1>
|
; lhs: SInt<1>
|
||||||
; rhs: SInt<2>
|
; rhs: SInt<2>
|
||||||
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr_1.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_2, asSInt(bits(_cast_bits_to_bundle_expr.body, 1, 0)) @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_2: Ty2
|
wire _bundle_literal_expr_2: Ty2
|
||||||
connect _bundle_literal_expr_2.tag, UInt<1>(0h1)
|
connect _bundle_literal_expr_2.tag, UInt<1>(0h1)
|
||||||
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
connect _bundle_literal_expr_2.body, asUInt(__connect_variant_body_2)
|
||||||
|
|
@ -4159,13 +4035,13 @@ circuit check_enum_connect_any:
|
||||||
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
connect o1, _bundle_literal_expr_3 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_3: Ty4 @[module-XXXXXXXXXX.rs 8:1]
|
wire __connect_variant_body_3: Ty4 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _cast_bits_to_bundle_expr_2: Ty4
|
wire _cast_bits_to_bundle_expr_1: Ty4
|
||||||
wire _cast_bits_to_bundle_expr_flattened_2: Ty4
|
wire _cast_bits_to_bundle_expr_flattened_1: Ty4
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_1.tag, bits(bits(i2.body, 0, 0), 0, 0)
|
||||||
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_bundle_expr_flattened_2.tag
|
connect _cast_bits_to_bundle_expr_1.tag, _cast_bits_to_bundle_expr_flattened_1.tag
|
||||||
connect _cast_bits_to_bundle_expr_flattened_2.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_1.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
connect _cast_bits_to_bundle_expr_1.body, _cast_bits_to_bundle_expr_flattened_1.body
|
||||||
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_2 @[module-XXXXXXXXXX.rs 8:1]
|
connect __connect_variant_body_3, _cast_bits_to_bundle_expr_1 @[module-XXXXXXXXXX.rs 8:1]
|
||||||
wire _bundle_literal_expr_4: Ty0
|
wire _bundle_literal_expr_4: Ty0
|
||||||
connect _bundle_literal_expr_4.tag, UInt<2>(0h2)
|
connect _bundle_literal_expr_4.tag, UInt<2>(0h2)
|
||||||
wire _cast_bundle_to_bits_expr_1: Ty4
|
wire _cast_bundle_to_bits_expr_1: Ty4
|
||||||
|
|
@ -4187,29 +4063,23 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
else when eq(i1.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 9:1]
|
else when eq(i1.tag, UInt<2>(0h1)): @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire __connect_variant_body_5: Ty3 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_5: Ty3 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_3: Ty2
|
wire _cast_bits_to_bundle_expr_2: Ty2
|
||||||
wire _cast_bits_to_bundle_expr_flattened_3: Ty2
|
wire _cast_bits_to_bundle_expr_flattened_2: Ty2
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_2.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
||||||
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_bundle_expr_flattened_3.tag
|
connect _cast_bits_to_bundle_expr_2.tag, _cast_bits_to_bundle_expr_flattened_2.tag
|
||||||
connect _cast_bits_to_bundle_expr_flattened_3.body, bits(bits(i1.body, 1, 0), 1, 1)
|
connect _cast_bits_to_bundle_expr_flattened_2.body, bits(bits(i1.body, 1, 0), 1, 1)
|
||||||
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
connect _cast_bits_to_bundle_expr_2.body, _cast_bits_to_bundle_expr_flattened_2.body
|
||||||
when eq(_cast_bits_to_bundle_expr_3.tag, UInt<1>(0h0)): @[module-XXXXXXXXXX.rs 9:1]
|
when eq(_cast_bits_to_bundle_expr_2.tag, UInt<1>(0h0)): @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_6: Ty3
|
wire _bundle_literal_expr_6: Ty3
|
||||||
connect _bundle_literal_expr_6.tag, UInt<1>(0h0)
|
connect _bundle_literal_expr_6.tag, UInt<1>(0h0)
|
||||||
connect _bundle_literal_expr_6.body, UInt<2>(0h0)
|
connect _bundle_literal_expr_6.body, UInt<2>(0h0)
|
||||||
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_5, _bundle_literal_expr_6 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_6: SInt<2> @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_4: Ty2
|
|
||||||
wire _cast_bits_to_bundle_expr_flattened_4: Ty2
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.tag, bits(bits(i1.body, 1, 0), 0, 0)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.tag, _cast_bits_to_bundle_expr_flattened_4.tag
|
|
||||||
connect _cast_bits_to_bundle_expr_flattened_4.body, bits(bits(i1.body, 1, 0), 1, 1)
|
|
||||||
connect _cast_bits_to_bundle_expr_4.body, _cast_bits_to_bundle_expr_flattened_4.body
|
|
||||||
; connect different types:
|
; connect different types:
|
||||||
; lhs: SInt<2>
|
; lhs: SInt<2>
|
||||||
; rhs: SInt<1>
|
; rhs: SInt<1>
|
||||||
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_4.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_6, asSInt(bits(_cast_bits_to_bundle_expr_2.body, 0, 0)) @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_7: Ty3
|
wire _bundle_literal_expr_7: Ty3
|
||||||
connect _bundle_literal_expr_7.tag, UInt<1>(0h1)
|
connect _bundle_literal_expr_7.tag, UInt<1>(0h1)
|
||||||
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
connect _bundle_literal_expr_7.body, asUInt(__connect_variant_body_6)
|
||||||
|
|
@ -4225,13 +4095,13 @@ circuit check_enum_connect_any:
|
||||||
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
connect o2, _bundle_literal_expr_8 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
else:
|
else:
|
||||||
wire __connect_variant_body_7: Ty4 @[module-XXXXXXXXXX.rs 9:1]
|
wire __connect_variant_body_7: Ty4 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _cast_bits_to_bundle_expr_5: Ty4
|
wire _cast_bits_to_bundle_expr_3: Ty4
|
||||||
wire _cast_bits_to_bundle_expr_flattened_5: Ty4
|
wire _cast_bits_to_bundle_expr_flattened_3: Ty4
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
connect _cast_bits_to_bundle_expr_flattened_3.tag, bits(bits(i1.body, 0, 0), 0, 0)
|
||||||
connect _cast_bits_to_bundle_expr_5.tag, _cast_bits_to_bundle_expr_flattened_5.tag
|
connect _cast_bits_to_bundle_expr_3.tag, _cast_bits_to_bundle_expr_flattened_3.tag
|
||||||
connect _cast_bits_to_bundle_expr_flattened_5.body, UInt<0>(0)
|
connect _cast_bits_to_bundle_expr_flattened_3.body, UInt<0>(0)
|
||||||
connect _cast_bits_to_bundle_expr_5.body, _cast_bits_to_bundle_expr_flattened_5.body
|
connect _cast_bits_to_bundle_expr_3.body, _cast_bits_to_bundle_expr_flattened_3.body
|
||||||
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_5 @[module-XXXXXXXXXX.rs 9:1]
|
connect __connect_variant_body_7, _cast_bits_to_bundle_expr_3 @[module-XXXXXXXXXX.rs 9:1]
|
||||||
wire _bundle_literal_expr_9: Ty1
|
wire _bundle_literal_expr_9: Ty1
|
||||||
connect _bundle_literal_expr_9.tag, UInt<2>(0h2)
|
connect _bundle_literal_expr_9.tag, UInt<2>(0h2)
|
||||||
wire _cast_bundle_to_bits_expr_3: Ty4
|
wire _cast_bundle_to_bits_expr_3: Ty4
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue