This commit is contained in:
parent
8449854cac
commit
9ad4ec0f39
|
@ -111,6 +111,7 @@ expr_enum! {
|
|||
BundleLiteral(ops::BundleLiteral),
|
||||
ArrayLiteral(ops::ArrayLiteral<CanonicalType, DynSize>),
|
||||
EnumLiteral(ops::EnumLiteral),
|
||||
Uninit(ops::Uninit),
|
||||
NotU(ops::NotU),
|
||||
NotS(ops::NotS),
|
||||
NotB(ops::NotB),
|
||||
|
@ -697,3 +698,13 @@ pub fn check_match_expr<T: Type>(
|
|||
_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()
|
||||
}
|
||||
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(
|
||||
&mut self,
|
||||
expr: ops::EnumLiteral<Enum>,
|
||||
|
@ -1367,6 +1381,7 @@ impl<'a> Exporter<'a> {
|
|||
ExprEnum::EnumLiteral(enum_literal) => {
|
||||
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::NotS(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::BundleLiteral(_)
|
||||
| ExprEnum::ArrayLiteral(_)
|
||||
| ExprEnum::Uninit(_)
|
||||
| ExprEnum::NotU(_)
|
||||
| ExprEnum::NotS(_)
|
||||
| ExprEnum::NotB(_)
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use crate::{
|
|||
cli::Cli,
|
||||
clock::{Clock, ClockDomain, ToClock},
|
||||
enum_::{HdlNone, HdlOption, HdlSome},
|
||||
expr::{CastBitsTo, CastTo, CastToBits, Expr, ReduceBits, ToExpr},
|
||||
expr::{CastBitsTo, CastTo, CastToBits, Expr, MakeUninitExpr, ReduceBits, ToExpr},
|
||||
hdl, hdl_module,
|
||||
int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType},
|
||||
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>",
|
||||
"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": {
|
||||
"data": {
|
||||
"$kind": "Struct",
|
||||
|
|
Loading…
Reference in a new issue