WIP getting queue formal to pass -- passes for capacity <= 2
Some checks failed
/ test (push) Has been cancelled
Some checks failed
/ test (push) Has been cancelled
This commit is contained in:
parent
bc26fe32fd
commit
3e2fb9b94f
5 changed files with 343 additions and 77 deletions
|
|
@ -23,6 +23,19 @@ impl<T: Type> ReadyValid<T> {
|
|||
fire
|
||||
}
|
||||
#[hdl]
|
||||
pub fn fire_data(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<T>> {
|
||||
let expr = expr.to_expr();
|
||||
let option_ty = Expr::ty(expr).data;
|
||||
#[hdl]
|
||||
let fire_data = wire(option_ty);
|
||||
connect(fire_data, option_ty.HdlNone());
|
||||
#[hdl]
|
||||
if expr.ready {
|
||||
connect(fire_data, expr.data);
|
||||
}
|
||||
fire_data
|
||||
}
|
||||
#[hdl]
|
||||
pub fn map<R: Type>(
|
||||
expr: Expr<Self>,
|
||||
f: impl FnOnce(Expr<T>) -> Expr<R>,
|
||||
|
|
@ -163,7 +176,6 @@ pub fn queue<T: Type>(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
@ -171,27 +183,39 @@ mod tests {
|
|||
cli::FormalMode, firrtl::ExportOptions,
|
||||
module::transform::simplify_enums::SimplifyEnumsKind, testing::assert_formal,
|
||||
};
|
||||
use std::num::NonZero;
|
||||
|
||||
#[test]
|
||||
fn test_queue() {
|
||||
#[track_caller]
|
||||
fn test_queue(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) {
|
||||
assert_formal(
|
||||
format_args!("test_queue_{capacity}_{inp_ready_is_comb}_{out_valid_is_comb}"),
|
||||
queue_test(capacity, inp_ready_is_comb, out_valid_is_comb),
|
||||
FormalMode::BMC,
|
||||
20,
|
||||
None,
|
||||
ExportOptions {
|
||||
simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
|
||||
..ExportOptions::default()
|
||||
},
|
||||
);
|
||||
#[hdl_module]
|
||||
fn queue_test(capacity: NonZeroUsize, inp_ready_is_comb: bool, out_valid_is_comb: bool) {
|
||||
#[hdl]
|
||||
let clk: Clock = m.input();
|
||||
#[hdl]
|
||||
let rst: SyncReset = m.input();
|
||||
#[hdl]
|
||||
let inp_data: HdlOption<UInt<8>> = m.input();
|
||||
#[hdl]
|
||||
let out_ready: Bool = m.input();
|
||||
#[hdl]
|
||||
let start_check: Bool = m.input();
|
||||
#[hdl]
|
||||
let clk: Clock = m.input();
|
||||
#[hdl]
|
||||
let cd = wire();
|
||||
connect(
|
||||
cd,
|
||||
#[hdl]
|
||||
ClockDomain {
|
||||
clk,
|
||||
rst: rst.to_reset(),
|
||||
rst: formal_reset().to_reset(),
|
||||
},
|
||||
);
|
||||
#[hdl]
|
||||
|
|
@ -216,52 +240,139 @@ mod tests {
|
|||
} else if !ReadyValid::fire(dut.inp) & ReadyValid::fire(dut.out) {
|
||||
connect_any(next_count, count - 1u8);
|
||||
}
|
||||
hdl_assert(clk, count.cmp_eq(dut.count), "");
|
||||
hdl_assert(cd.clk, count.cmp_eq(dut.count), "");
|
||||
#[hdl]
|
||||
let index = reg_builder().clock_domain(cd).reset(HdlNone::<UInt<32>>());
|
||||
let started_check = reg_builder().clock_domain(cd).reset(false);
|
||||
#[hdl]
|
||||
let data = reg_builder().clock_domain(cd).reset(HdlNone());
|
||||
let steps_till_output = reg_builder().clock_domain(cd).reset(0u32);
|
||||
#[hdl]
|
||||
match index {
|
||||
HdlNone =>
|
||||
{
|
||||
#[hdl]
|
||||
if ReadyValid::fire(dut.inp) {
|
||||
connect(index, HdlSome(0u32));
|
||||
connect(data, dut.inp.data);
|
||||
}
|
||||
let expected_output = reg_builder().clock_domain(cd).reset(HdlNone());
|
||||
#[hdl]
|
||||
if start_check & !started_check {
|
||||
#[hdl]
|
||||
if let HdlSome(inp) = ReadyValid::fire_data(dut.inp) {
|
||||
connect(started_check, true);
|
||||
connect_any(
|
||||
steps_till_output,
|
||||
count + (!ReadyValid::fire(dut.out)).cast_to(UInt[1]),
|
||||
);
|
||||
connect(expected_output, HdlSome(inp));
|
||||
}
|
||||
HdlSome(cur_index) =>
|
||||
} else if started_check & steps_till_output.cmp_ne(0u32) & ReadyValid::fire(dut.out) {
|
||||
connect_any(steps_till_output, steps_till_output - 1u32);
|
||||
}
|
||||
#[hdl]
|
||||
let stored_output = reg_builder().clock_domain(cd).reset(HdlNone());
|
||||
#[hdl]
|
||||
if let HdlSome(out) = ReadyValid::fire_data(dut.out) {
|
||||
#[hdl]
|
||||
if (start_check & !started_check) | (started_check & steps_till_output.cmp_ne(0u32))
|
||||
{
|
||||
connect(stored_output, HdlSome(out));
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
if started_check & steps_till_output.cmp_eq(0u32) {
|
||||
#[hdl]
|
||||
if let HdlSome(expected_output) = expected_output {
|
||||
#[hdl]
|
||||
if cur_index.cmp_ge(next_count) {
|
||||
connect(index, HdlNone());
|
||||
#[hdl]
|
||||
if let HdlSome(data) = data {
|
||||
#[hdl]
|
||||
if let HdlSome(out_data) = dut.out.data {
|
||||
hdl_assert(clk, data.cmp_eq(out_data), "");
|
||||
} else {
|
||||
hdl_assert(clk, false.to_expr(), "");
|
||||
}
|
||||
} else {
|
||||
hdl_assert(clk, false.to_expr(), "");
|
||||
}
|
||||
if let HdlSome(stored_output) = stored_output {
|
||||
hdl_assert(cd.clk, stored_output.cmp_eq(expected_output), "");
|
||||
} else {
|
||||
connect(index, HdlSome((cur_index + 1u8).cast_to_static()));
|
||||
hdl_assert(cd.clk, false.to_expr(), "");
|
||||
}
|
||||
} else {
|
||||
hdl_assert(cd.clk, false.to_expr(), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_formal(
|
||||
queue_test(NonZeroUsize::new(2).unwrap(), false, false),
|
||||
FormalMode::BMC,
|
||||
20,
|
||||
None,
|
||||
ExportOptions {
|
||||
simplify_enums: Some(SimplifyEnumsKind::ReplaceWithBundleOfUInts),
|
||||
..ExportOptions::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_false_false() {
|
||||
test_queue(NonZero::new(1).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_false_true() {
|
||||
test_queue(NonZero::new(1).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_true_false() {
|
||||
test_queue(NonZero::new(1).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_true_true() {
|
||||
test_queue(NonZero::new(1).unwrap(), true, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_false_false() {
|
||||
test_queue(NonZero::new(2).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_false_true() {
|
||||
test_queue(NonZero::new(2).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_true_false() {
|
||||
test_queue(NonZero::new(2).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2_true_true() {
|
||||
test_queue(NonZero::new(2).unwrap(), true, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_false_false() {
|
||||
test_queue(NonZero::new(3).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_false_true() {
|
||||
test_queue(NonZero::new(3).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_true_false() {
|
||||
test_queue(NonZero::new(3).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_3_true_true() {
|
||||
test_queue(NonZero::new(3).unwrap(), true, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_false_false() {
|
||||
test_queue(NonZero::new(4).unwrap(), false, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_false_true() {
|
||||
test_queue(NonZero::new(4).unwrap(), false, true);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_true_false() {
|
||||
test_queue(NonZero::new(4).unwrap(), true, false);
|
||||
}
|
||||
|
||||
#[cfg(todo)]
|
||||
#[test]
|
||||
fn test_4_true_true() {
|
||||
test_queue(NonZero::new(4).unwrap(), true, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue