This commit is contained in:
parent
8449854cac
commit
9ad4ec0f39
|
@ -111,6 +111,7 @@ expr_enum! {
|
||||||
BundleLiteral(ops::BundleLiteral),
|
BundleLiteral(ops::BundleLiteral),
|
||||||
ArrayLiteral(ops::ArrayLiteral<CanonicalType, DynSize>),
|
ArrayLiteral(ops::ArrayLiteral<CanonicalType, DynSize>),
|
||||||
EnumLiteral(ops::EnumLiteral),
|
EnumLiteral(ops::EnumLiteral),
|
||||||
|
Uninit(ops::Uninit),
|
||||||
NotU(ops::NotU),
|
NotU(ops::NotU),
|
||||||
NotS(ops::NotS),
|
NotS(ops::NotS),
|
||||||
NotB(ops::NotB),
|
NotB(ops::NotB),
|
||||||
|
@ -697,3 +698,13 @@ pub fn check_match_expr<T: Type>(
|
||||||
_check_fn: impl FnOnce(T::MatchVariant, Infallible),
|
_check_fn: impl FnOnce(T::MatchVariant, Infallible),
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MakeUninitExpr: Type {
|
||||||
|
fn uninit(self) -> Expr<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> MakeUninitExpr for T {
|
||||||
|
fn uninit(self) -> Expr<Self> {
|
||||||
|
ops::Uninit::new(self).to_expr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2529,3 +2529,41 @@ impl<T: Type> ToExpr for CastBitsTo<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct Uninit<T: Type = CanonicalType> {
|
||||||
|
ty: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> Uninit<T> {
|
||||||
|
#[track_caller]
|
||||||
|
pub fn new(ty: T) -> Self {
|
||||||
|
Self { ty }
|
||||||
|
}
|
||||||
|
pub fn ty(self) -> T {
|
||||||
|
self.ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Type> ToLiteralBits for Uninit<T> {
|
||||||
|
fn to_literal_bits(&self) -> Result<Interned<BitSlice>, NotALiteralExpr> {
|
||||||
|
Err(NotALiteralExpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_get_target_none!([T: Type] Uninit<T>);
|
||||||
|
|
||||||
|
impl<T: Type> ToExpr for Uninit<T> {
|
||||||
|
type Type = T;
|
||||||
|
|
||||||
|
fn to_expr(&self) -> Expr<Self::Type> {
|
||||||
|
Expr {
|
||||||
|
__enum: ExprEnum::Uninit(Uninit {
|
||||||
|
ty: self.ty.canonical(),
|
||||||
|
})
|
||||||
|
.intern(),
|
||||||
|
__ty: self.ty,
|
||||||
|
__flow: Flow::Source,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -912,6 +912,20 @@ impl<'a> Exporter<'a> {
|
||||||
}
|
}
|
||||||
ident.to_string()
|
ident.to_string()
|
||||||
}
|
}
|
||||||
|
fn uninit_expr(
|
||||||
|
&mut self,
|
||||||
|
expr: ops::Uninit,
|
||||||
|
definitions: &RcDefinitions,
|
||||||
|
const_ty: bool,
|
||||||
|
) -> String {
|
||||||
|
let ident = self.module.ns.make_new("_uninit_expr");
|
||||||
|
let ty = expr.ty();
|
||||||
|
let ty_ident = self.type_state.ty(ty);
|
||||||
|
let const_ = if const_ty { "const " } else { "" };
|
||||||
|
definitions.add_definition_line(format_args!("wire {ident}: {const_}{ty_ident}"));
|
||||||
|
definitions.add_definition_line(format_args!("invalidate {ident}"));
|
||||||
|
ident.to_string()
|
||||||
|
}
|
||||||
fn enum_literal_expr(
|
fn enum_literal_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ops::EnumLiteral<Enum>,
|
expr: ops::EnumLiteral<Enum>,
|
||||||
|
@ -1367,6 +1381,7 @@ impl<'a> Exporter<'a> {
|
||||||
ExprEnum::EnumLiteral(enum_literal) => {
|
ExprEnum::EnumLiteral(enum_literal) => {
|
||||||
self.enum_literal_expr(enum_literal, definitions, const_ty)
|
self.enum_literal_expr(enum_literal, definitions, const_ty)
|
||||||
}
|
}
|
||||||
|
ExprEnum::Uninit(uninit) => self.uninit_expr(uninit, definitions, const_ty),
|
||||||
ExprEnum::NotU(expr) => self.expr_unary("not", expr.arg(), definitions, const_ty),
|
ExprEnum::NotU(expr) => self.expr_unary("not", expr.arg(), definitions, const_ty),
|
||||||
ExprEnum::NotS(expr) => self.expr_unary("not", expr.arg(), definitions, const_ty),
|
ExprEnum::NotS(expr) => self.expr_unary("not", expr.arg(), definitions, const_ty),
|
||||||
ExprEnum::NotB(expr) => self.expr_unary("not", expr.arg(), definitions, const_ty),
|
ExprEnum::NotB(expr) => self.expr_unary("not", expr.arg(), definitions, const_ty),
|
||||||
|
|
|
@ -287,6 +287,7 @@ impl Folder for State {
|
||||||
| ExprEnum::BoolLiteral(_)
|
| ExprEnum::BoolLiteral(_)
|
||||||
| ExprEnum::BundleLiteral(_)
|
| ExprEnum::BundleLiteral(_)
|
||||||
| ExprEnum::ArrayLiteral(_)
|
| ExprEnum::ArrayLiteral(_)
|
||||||
|
| ExprEnum::Uninit(_)
|
||||||
| ExprEnum::NotU(_)
|
| ExprEnum::NotU(_)
|
||||||
| ExprEnum::NotS(_)
|
| ExprEnum::NotS(_)
|
||||||
| ExprEnum::NotB(_)
|
| ExprEnum::NotB(_)
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub use crate::{
|
||||||
cli::Cli,
|
cli::Cli,
|
||||||
clock::{Clock, ClockDomain, ToClock},
|
clock::{Clock, ClockDomain, ToClock},
|
||||||
enum_::{HdlNone, HdlOption, HdlSome},
|
enum_::{HdlNone, HdlOption, HdlSome},
|
||||||
expr::{CastBitsTo, CastTo, CastToBits, Expr, ReduceBits, ToExpr},
|
expr::{CastBitsTo, CastTo, CastToBits, Expr, MakeUninitExpr, ReduceBits, ToExpr},
|
||||||
hdl, hdl_module,
|
hdl, hdl_module,
|
||||||
int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType},
|
int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType},
|
||||||
memory::{Mem, MemBuilder, ReadUnderWrite},
|
memory::{Mem, MemBuilder, ReadUnderWrite},
|
||||||
|
|
|
@ -3139,3 +3139,46 @@ circuit check_annotations: %[[
|
||||||
"#,
|
"#,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[hdl_module(outline_generated)]
|
||||||
|
pub fn check_uninit<T: Type>(ty: T) {
|
||||||
|
#[hdl]
|
||||||
|
let o: T = m.output(ty);
|
||||||
|
connect(o, ty.uninit());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_uninit() {
|
||||||
|
let _n = SourceLocation::normalize_files_for_tests();
|
||||||
|
let m = check_uninit((UInt[3], SInt[5], Clock));
|
||||||
|
dbg!(m);
|
||||||
|
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
|
||||||
|
assert_export_firrtl! {
|
||||||
|
m =>
|
||||||
|
"/test/check_uninit.fir": r"FIRRTL version 3.2.0
|
||||||
|
circuit check_uninit:
|
||||||
|
type Ty0 = {`0`: UInt<3>, `1`: SInt<5>, `2`: Clock}
|
||||||
|
module check_uninit: @[module-XXXXXXXXXX.rs 1:1]
|
||||||
|
output o: Ty0 @[module-XXXXXXXXXX.rs 2:1]
|
||||||
|
wire _uninit_expr: Ty0
|
||||||
|
invalidate _uninit_expr
|
||||||
|
connect o, _uninit_expr @[module-XXXXXXXXXX.rs 3:1]
|
||||||
|
",
|
||||||
|
};
|
||||||
|
let m = check_uninit(Array[HdlOption[()]][3]);
|
||||||
|
dbg!(m);
|
||||||
|
#[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
|
||||||
|
assert_export_firrtl! {
|
||||||
|
m =>
|
||||||
|
"/test/check_uninit_1.fir": r"FIRRTL version 3.2.0
|
||||||
|
circuit check_uninit_1:
|
||||||
|
type Ty0 = {}
|
||||||
|
type Ty1 = {|HdlNone, HdlSome: Ty0|}
|
||||||
|
module check_uninit_1: @[module-XXXXXXXXXX.rs 1:1]
|
||||||
|
output o: Ty1[3] @[module-XXXXXXXXXX.rs 2:1]
|
||||||
|
wire _uninit_expr: Ty1[3]
|
||||||
|
invalidate _uninit_expr
|
||||||
|
connect o, _uninit_expr @[module-XXXXXXXXXX.rs 3:1]
|
||||||
|
",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -283,6 +283,16 @@
|
||||||
"fold_where": "T: Fold<State>",
|
"fold_where": "T: Fold<State>",
|
||||||
"visit_where": "T: Visit<State>"
|
"visit_where": "T: Visit<State>"
|
||||||
},
|
},
|
||||||
|
"ops::Uninit": {
|
||||||
|
"data": {
|
||||||
|
"$kind": "Struct",
|
||||||
|
"$constructor": "ops::Uninit::new",
|
||||||
|
"ty()": "Visible"
|
||||||
|
},
|
||||||
|
"generics": "<T: Type>",
|
||||||
|
"fold_where": "T: Fold<State>",
|
||||||
|
"visit_where": "T: Visit<State>"
|
||||||
|
},
|
||||||
"ops::NotU": {
|
"ops::NotU": {
|
||||||
"data": {
|
"data": {
|
||||||
"$kind": "Struct",
|
"$kind": "Struct",
|
||||||
|
|
Loading…
Reference in a new issue