add support for #[hdl(sim)] enum_ty.Variant(value) and #[hdl(sim)] EnumTy::Variant(value) and non-sim variants too

This commit is contained in:
Jacob Lifshay 2025-04-01 22:05:42 -07:00
parent 9092e45447
commit c4b6a0fee6
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
9 changed files with 817 additions and 370 deletions

View file

@ -259,6 +259,7 @@ pub trait EnumType:
MatchVariantsIter = EnumMatchVariantsIter<Self>,
>
{
type SimBuilder: From<Self>;
fn variants(&self) -> Interned<[EnumVariant]>;
fn match_activate_scope(
v: Self::MatchVariantAndInactiveScope,
@ -321,7 +322,18 @@ impl<T: EnumType> DoubleEndedIterator for EnumMatchVariantsIter<T> {
}
}
pub struct NoBuilder {
_ty: Enum,
}
impl From<Enum> for NoBuilder {
fn from(_ty: Enum) -> Self {
Self { _ty }
}
}
impl EnumType for Enum {
type SimBuilder = NoBuilder;
fn match_activate_scope(
v: Self::MatchVariantAndInactiveScope,
) -> (Self::MatchVariant, Self::MatchActiveScope) {
@ -389,6 +401,9 @@ pub struct EnumPaddingSimValue {
}
impl EnumPaddingSimValue {
pub const fn new() -> Self {
Self { bits: None }
}
pub fn bit_width(&self) -> Option<usize> {
self.bits.as_ref().map(UIntValue::width)
}
@ -659,6 +674,16 @@ impl<'a> EnumSimValueToBits<'a> {
}
}
#[doc(hidden)]
pub fn assert_is_enum_type<T: EnumType>(v: T) -> T {
v
}
#[doc(hidden)]
pub fn enum_type_to_sim_builder<T: EnumType>(v: T) -> T::SimBuilder {
v.into()
}
#[hdl]
pub enum HdlOption<T: Type> {
HdlNone,

View file

@ -317,8 +317,13 @@ pub fn enums() {
let which_out: UInt<2> = m.output();
#[hdl]
let data_out: UInt<4> = m.output();
let b_out_ty = HdlOption[(UInt[1], Bool)];
#[hdl]
let b_out: HdlOption<(UInt<1>, Bool)> = m.output();
let b_out: HdlOption<(UInt, Bool)> = m.output(HdlOption[(UInt[1], Bool)]);
#[hdl]
let b2_out: HdlOption<(UInt<1>, Bool)> = m.output();
connect_any(b2_out, b_out);
#[hdl]
struct MyStruct<T> {
@ -358,7 +363,7 @@ pub fn enums() {
}
}
connect(b_out, HdlNone());
connect(b_out, b_out_ty.HdlNone());
#[hdl]
match the_reg {
@ -369,7 +374,7 @@ pub fn enums() {
MyEnum::B(v) => {
connect(which_out, 1_hdl_u2);
connect_any(data_out, v.0 | (v.1.cast_to_static::<UInt<1>>() << 1));
connect(b_out, HdlSome(v));
connect_any(b_out, HdlSome(v));
}
MyEnum::C(v) => {
connect(which_out, 2_hdl_u2);
@ -396,100 +401,125 @@ fn test_enums() {
sim.write(sim.io().cd.rst, false);
sim.advance_time(SimDuration::from_nanos(900));
#[hdl(cmp_eq)]
struct IO {
struct IO<W: Size> {
en: Bool,
which_in: UInt<2>,
data_in: UInt<4>,
which_out: UInt<2>,
data_out: UInt<4>,
b_out: HdlOption<(UInt<1>, Bool)>,
b_out: HdlOption<(UIntType<W>, Bool)>,
b2_out: HdlOption<(UInt<1>, Bool)>,
}
let io_ty = IO[1];
let io_cycles = [
#[hdl(sim)]
IO {
IO::<_> {
en: false,
which_in: 0_hdl_u2,
data_in: 0_hdl_u4,
which_out: 0_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlNone(),
b_out: #[hdl(sim)]
(io_ty.b_out).HdlNone(),
b2_out: #[hdl(sim)]
HdlNone(),
},
#[hdl(sim)]
IO {
IO::<_> {
en: true,
which_in: 1_hdl_u2,
data_in: 0_hdl_u4,
which_out: 0_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlNone(),
b_out: #[hdl(sim)]
(io_ty.b_out).HdlNone(),
b2_out: #[hdl(sim)]
HdlNone(),
},
#[hdl(sim)]
IO {
IO::<_> {
en: false,
which_in: 0_hdl_u2,
data_in: 0_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlSome((0_hdl_u1, false)),
b_out: #[hdl(sim)]
(io_ty.b_out).HdlSome((0u8.cast_to(UInt[1]), false)),
b2_out: #[hdl(sim)]
HdlSome((0_hdl_u1, false)),
},
#[hdl(sim)]
IO {
IO::<_> {
en: true,
which_in: 1_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlSome((0_hdl_u1, false)),
b_out: #[hdl(sim)]
(io_ty.b_out).HdlSome((0u8.cast_to(UInt[1]), false)),
b2_out: #[hdl(sim)]
HdlSome((0_hdl_u1, false)),
},
#[hdl(sim)]
IO {
IO::<_> {
en: true,
which_in: 1_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0x3_hdl_u4,
b_out: HdlSome((1_hdl_u1, true)),
b_out: #[hdl(sim)]
(io_ty.b_out).HdlSome((1u8.cast_to(UInt[1]), true)),
b2_out: #[hdl(sim)]
HdlSome((1_hdl_u1, true)),
},
#[hdl(sim)]
IO {
IO::<_> {
en: true,
which_in: 2_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 1_hdl_u2,
data_out: 0x3_hdl_u4,
b_out: HdlSome((1_hdl_u1, true)),
b_out: #[hdl(sim)]
(io_ty.b_out).HdlSome((1u8.cast_to(UInt[1]), true)),
b2_out: #[hdl(sim)]
HdlSome((1_hdl_u1, true)),
},
#[hdl(sim)]
IO {
IO::<_> {
en: true,
which_in: 2_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 2_hdl_u2,
data_out: 0xF_hdl_u4,
b_out: HdlNone(),
b_out: #[hdl(sim)]
(io_ty.b_out).HdlNone(),
b2_out: #[hdl(sim)]
HdlNone(),
},
];
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl(sim)]
let IO {
let IO::<_> {
en,
which_in,
data_in,
which_out: _,
data_out: _,
b_out: _,
b2_out: _,
} = expected;
sim.write(sim.io().en, &en);
sim.write(sim.io().which_in, &which_in);
sim.write(sim.io().data_in, &data_in);
let io = #[hdl(sim)]
IO {
IO::<_> {
en,
which_in,
data_in,
which_out: sim.read(sim.io().which_out),
data_out: sim.read(sim.io().data_out),
b_out: sim.read(sim.io().b_out),
b2_out: sim.read(sim.io().b2_out),
};
assert_eq!(
expected,

File diff suppressed because it is too large Load diff

View file

@ -16,18 +16,25 @@ $var wire 1 ) \0 $end
$var wire 1 * \1 $end
$upscope $end
$upscope $end
$scope struct the_reg $end
$scope struct b2_out $end
$var string 1 + \$tag $end
$scope struct HdlSome $end
$var wire 1 , \0 $end
$var wire 1 - \1 $end
$upscope $end
$upscope $end
$scope struct the_reg $end
$var string 1 . \$tag $end
$scope struct B $end
$var reg 1 , \0 $end
$var reg 1 - \1 $end
$var reg 1 / \0 $end
$var reg 1 0 \1 $end
$upscope $end
$scope struct C $end
$scope struct a $end
$var reg 1 . \[0] $end
$var reg 1 / \[1] $end
$var reg 1 1 \[0] $end
$var reg 1 2 \[1] $end
$upscope $end
$var reg 2 0 b $end
$var reg 2 3 b $end
$upscope $end
$upscope $end
$upscope $end
@ -43,12 +50,15 @@ b0 '
sHdlNone\x20(0) (
0)
0*
sA\x20(0) +
sHdlNone\x20(0) +
0,
0-
0.
sA\x20(0) .
0/
b0 0
00
01
02
b0 3
$end
#1000000
1!
@ -66,7 +76,8 @@ b1 $
1!
b1 &
sHdlSome\x20(1) (
sB\x20(1) +
sHdlSome\x20(1) +
sB\x20(1) .
#6000000
0#
b0 $
@ -85,8 +96,10 @@ b11 '
1*
1,
1-
1.
1/
10
11
12
#10000000
0!
#11000000
@ -101,8 +114,11 @@ b1111 '
sHdlNone\x20(0) (
0)
0*
sC\x20(2) +
b11 0
sHdlNone\x20(0) +
0,
0-
sC\x20(2) .
b11 3
#14000000
0!
#15000000