Test File: test_pe_col.py

Back to Test: Systolic Gauss-Jordan.

Source file: test/systolic_gauss_jordan/test_pe_col.py

RTL counterpart

What this test checks

This is the direct cocotb truth-table test for the column processing element. It exercises the local stored bit, the incoming opcode token, and the emitted data/output behavior for every relevant small input combination.

The test:

  • resets the DUT

  • optionally preloads the local stored bit

  • enumerates data_i and all opcode values

  • compares observed outputs and next state against the Python golden model

How to run it

make -C test/systolic_gauss_jordan TEST=pe_col

What to inspect while reading it

  • reset_dut() for the suite-wide reset pattern

  • step() for the one-cycle drive-and-sample helper

  • pe_col_truth_table_exhaustive() for the contract being asserted

Python source

 1import cocotb
 2from cocotb.clock import Clock
 3from cocotb.triggers import FallingEdge, ReadOnly, RisingEdge
 4
 5from trapeziod_test_utils import (
 6    OP_ADD,
 7    OP_LOCK,
 8    OP_PASS,
 9    OP_SWAP,
10    OPCODE_NAMES,
11    pe_col_golden,
12)
13
14
15async def reset_dut(dut):
16    await FallingEdge(dut.clk)
17    dut.rst.value = 1
18    dut.en_i.value = 1
19    dut.data_i.value = 0
20    dut.op_i.value = OP_PASS
21
22    for _ in range(2):
23        await RisingEdge(dut.clk)
24
25    dut.rst.value = 0
26
27
28async def step(dut, data_i, op_i):
29    await FallingEdge(dut.clk)
30    dut.data_i.value = data_i
31    dut.op_i.value = op_i
32    await RisingEdge(dut.clk)
33    await ReadOnly()
34
35    return {
36        "r": int(dut.r.value),
37        "data_o": int(dut.data_o.value),
38        "op_o": int(dut.op_o.value),
39    }
40
41
42@cocotb.test()
43async def pe_col_truth_table_exhaustive(dut):
44    cocotb.start_soon(Clock(dut.clk, 10, unit="ns").start())
45    dut.en_i.value = 1
46
47    opcodes = [OP_PASS, OP_SWAP, OP_ADD, OP_LOCK]
48
49    for r_prev in (0, 1):
50        for data_i in (0, 1):
51            for op_i in opcodes:
52                await reset_dut(dut)
53
54                if r_prev == 1:
55                    preload = await step(dut, 1, OP_LOCK)
56                    assert preload["r"] == 1, "Failed to preload pe_col.r to 1"
57
58                observed = await step(dut, data_i, op_i)
59                expected = pe_col_golden(r_prev=r_prev, data_i=data_i, op_i=op_i)
60
61                mismatch_row = (
62                    f"(r_prev={r_prev}, data_i={data_i}, op_i={OPCODE_NAMES[op_i]})"
63                )
64
65                assert observed["r"] == expected["r_next"], (
66                    f"{mismatch_row}: expected r_next={expected['r_next']}, "
67                    f"got {observed['r']}"
68                )
69                assert observed["data_o"] == expected["data_o"], (
70                    f"{mismatch_row}: expected data_o={expected['data_o']}, "
71                    f"got {observed['data_o']}"
72                )
73                assert observed["op_o"] == expected["op_o"], (
74                    f"{mismatch_row}: expected op_o={OPCODE_NAMES[expected['op_o']]}, "
75                    f"got {OPCODE_NAMES.get(observed['op_o'], observed['op_o'])}"
76                )