add ty.uninit()
All checks were successful
/ test (push) Successful in 4m30s

This commit is contained in:
Jacob Lifshay 2024-09-22 17:26:23 -07:00
parent 8449854cac
commit 9ad4ec0f39
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
7 changed files with 119 additions and 1 deletions

View file

@ -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()
}
}

View file

@ -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,
}
}
}

View file

@ -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),

View file

@ -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(_)

View file

@ -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},

View file

@ -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]
",
};
}

View file

@ -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",