expand SimValue support

This commit is contained in:
Jacob Lifshay 2025-03-30 00:55:38 -07:00
parent 5028401a5a
commit a40eaaa2da
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
13 changed files with 864 additions and 342 deletions

View file

@ -7,13 +7,7 @@ use fayalite::{
module::{instance_with_loc, reg_builder_with_loc},
prelude::*,
reset::ResetType,
sim::{
time::SimDuration,
value::{SimValue, ToSimValue},
vcd::VcdWriterDecls,
Simulation,
},
ty::StaticType,
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation},
util::RcWriter,
};
use std::num::NonZeroUsize;
@ -391,113 +385,110 @@ fn test_enums() {
let mut sim = Simulation::new(enums());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
sim.write_bool(sim.io().en, false);
sim.write_bool_or_int(sim.io().which_in, 0_hdl_u2);
sim.write_bool_or_int(sim.io().data_in, 0_hdl_u4);
sim.write(sim.io().cd.clk, false);
sim.write(sim.io().cd.rst, true);
sim.write(sim.io().en, false);
sim.write(sim.io().which_in, 0_hdl_u2);
sim.write(sim.io().data_in, 0_hdl_u4);
sim.advance_time(SimDuration::from_micros(1));
sim.write_clock(sim.io().cd.clk, true);
sim.write(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(100));
sim.write_reset(sim.io().cd.rst, false);
sim.write(sim.io().cd.rst, false);
sim.advance_time(SimDuration::from_nanos(900));
type BOutTy = HdlOption<(UInt<1>, Bool)>;
#[derive(Debug, PartialEq)]
#[hdl(cmp_eq)]
struct IO {
en: bool,
which_in: u8,
data_in: u8,
which_out: u8,
data_out: u8,
b_out: SimValue<BOutTy>,
en: Bool,
which_in: UInt<2>,
data_in: UInt<4>,
which_out: UInt<2>,
data_out: UInt<4>,
b_out: HdlOption<(UInt<1>, Bool)>,
}
let io_cycles = [
#[hdl(sim)]
IO {
en: false,
which_in: 0,
data_in: 0,
which_out: 0,
data_out: 0,
b_out: HdlNone().to_sim_value(StaticType::TYPE),
which_in: 0_hdl_u2,
data_in: 0_hdl_u4,
which_out: 0_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlNone(),
},
#[hdl(sim)]
IO {
en: true,
which_in: 1,
data_in: 0,
which_out: 0,
data_out: 0,
b_out: HdlNone().to_sim_value(StaticType::TYPE),
which_in: 1_hdl_u2,
data_in: 0_hdl_u4,
which_out: 0_hdl_u2,
data_out: 0_hdl_u4,
b_out: HdlNone(),
},
#[hdl(sim)]
IO {
en: false,
which_in: 0,
data_in: 0,
which_out: 1,
data_out: 0,
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
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)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 1,
data_in: 0xF,
which_out: 1,
data_out: 0,
b_out: HdlSome((0_hdl_u1, false)).to_sim_value(StaticType::TYPE),
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)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 1,
data_in: 0xF,
which_out: 1,
data_out: 0x3,
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
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)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 2,
data_in: 0xF,
which_out: 1,
data_out: 0x3,
b_out: HdlSome((1_hdl_u1, true)).to_sim_value(StaticType::TYPE),
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)),
},
#[hdl(sim)]
IO {
en: true,
which_in: 2,
data_in: 0xF,
which_out: 2,
data_out: 0xF,
b_out: HdlNone().to_sim_value(StaticType::TYPE),
which_in: 2_hdl_u2,
data_in: 0xF_hdl_u4,
which_out: 2_hdl_u2,
data_out: 0xF_hdl_u4,
b_out: HdlNone(),
},
];
for (
cycle,
expected @ IO {
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl(sim)]
let IO {
en,
which_in,
data_in,
which_out: _,
data_out: _,
b_out: _,
},
) in io_cycles.into_iter().enumerate()
{
sim.write_bool(sim.io().en, en);
sim.write_bool_or_int(sim.io().which_in, which_in.cast_to_static());
sim.write_bool_or_int(sim.io().data_in, data_in.cast_to_static());
let io = IO {
} = 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 {
en,
which_in,
data_in,
which_out: sim
.read_bool_or_int(sim.io().which_out)
.to_bigint()
.try_into()
.expect("known to be in range"),
data_out: sim
.read_bool_or_int(sim.io().data_out)
.to_bigint()
.try_into()
.expect("known to be in range"),
which_out: sim.read(sim.io().which_out),
data_out: sim.read(sim.io().data_out),
b_out: sim.read(sim.io().b_out),
};
assert_eq!(
@ -559,7 +550,7 @@ fn test_memories() {
w_mask: (Bool, Bool),
}
let io_cycles = [
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: false,
@ -569,7 +560,7 @@ fn test_memories() {
w_data: (0u8, 0i8),
w_mask: (false, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -579,7 +570,7 @@ fn test_memories() {
w_data: (0x10u8, 0x20i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -589,7 +580,7 @@ fn test_memories() {
w_data: (0x30u8, 0x40i8),
w_mask: (false, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -599,7 +590,7 @@ fn test_memories() {
w_data: (0x50u8, 0x60i8),
w_mask: (true, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -609,7 +600,7 @@ fn test_memories() {
w_data: (0x70u8, -0x80i8),
w_mask: (false, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -619,7 +610,7 @@ fn test_memories() {
w_data: (0x90u8, 0xA0u8 as i8),
w_mask: (false, false),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -629,7 +620,7 @@ fn test_memories() {
w_data: (0x90u8, 0xA0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -639,7 +630,7 @@ fn test_memories() {
w_data: (0xB0u8, 0xC0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
@ -649,7 +640,7 @@ fn test_memories() {
w_data: (0xD0u8, 0xE0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 1_hdl_u4,
r_en: true,
@ -659,7 +650,7 @@ fn test_memories() {
w_data: (0xD0u8, 0xE0u8 as i8),
w_mask: (true, true),
},
#[hdl]
#[hdl(sim)]
IO {
r_addr: 2_hdl_u4,
r_en: true,
@ -671,7 +662,7 @@ fn test_memories() {
},
];
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl]
#[hdl(sim)]
let IO {
r_addr,
r_en,
@ -681,13 +672,13 @@ fn test_memories() {
w_data,
w_mask,
} = expected;
sim.write(sim.io().r.addr, r_addr);
sim.write(sim.io().r.en, r_en);
sim.write(sim.io().w.addr, w_addr);
sim.write(sim.io().w.en, w_en);
sim.write(sim.io().w.data, w_data);
sim.write(sim.io().w.mask, w_mask);
let io = (#[hdl]
sim.write(sim.io().r.addr, &r_addr);
sim.write(sim.io().r.en, &r_en);
sim.write(sim.io().w.addr, &w_addr);
sim.write(sim.io().w.en, &w_en);
sim.write(sim.io().w.data, &w_data);
sim.write(sim.io().w.mask, &w_mask);
let io = #[hdl(sim)]
IO {
r_addr,
r_en,
@ -696,20 +687,19 @@ fn test_memories() {
w_en,
w_data,
w_mask,
})
.to_sim_value(StaticType::TYPE);
};
assert_eq!(
expected.to_sim_value(StaticType::TYPE),
expected,
io,
"vcd:\n{}\ncycle: {cycle}",
String::from_utf8(writer.take()).unwrap(),
);
sim.advance_time(SimDuration::from_micros(1));
sim.write_clock(sim.io().r.clk, true);
sim.write_clock(sim.io().w.clk, true);
sim.write(sim.io().r.clk, true);
sim.write(sim.io().w.clk, true);
sim.advance_time(SimDuration::from_micros(1));
sim.write_clock(sim.io().r.clk, false);
sim.write_clock(sim.io().w.clk, false);
sim.write(sim.io().r.clk, false);
sim.write(sim.io().w.clk, false);
}
sim.flush_traces().unwrap();
let vcd = String::from_utf8(writer.take()).unwrap();