def test_inside(sva, capsys): class Main(m.Circuit): io = m.IO(a=m.In(m.Bits[2])) + m.ClockIO() if sva: f.assert_(f.sva(io.a, "inside {0, 1}"), on=f.posedge(io.CLK)) else: f.assert_(io.a | f.inside | {0, 1}, on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.a = 0 tester.advance_cycle() tester.circuit.a = 1 tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.a = 2 tester.advance_cycle() with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out
def test_until_with(sva, capsys): class Main(m.Circuit): io = m.IO(a=m.In(m.Bit), b=m.In(m.Bit), c=m.In(m.Bit)) + m.ClockIO() if sva: seq = f.sequence(f.sva(io.b, "until_with !", io.c)) f.assert_(f.sva(f.rose(io.a), "|->", seq), on=f.posedge(io.CLK)) else: seq = f.sequence(io.b | f.until_with | f.not_(io.c)) f.assert_(f.rose(io.a) | f.implies | seq, on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.a = 0 tester.circuit.c = 1 tester.advance_cycle() # Posedge a, b high until the cycle c goes low tester.circuit.a = 1 tester.circuit.b = 1 tester.advance_cycle() for i in range(random.randint(3, 7)): tester.advance_cycle() tester.circuit.c = 0 tester.advance_cycle() tester.circuit.b = 0 tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.a = 0 tester.circuit.c = 1 tester.advance_cycle() # Posedge a, b goes low before c tester.circuit.a = 1 tester.circuit.b = 1 tester.advance_cycle() tester.advance_cycle() tester.circuit.b = 0 tester.advance_cycle() tester.circuit.c = 0 tester.advance_cycle() with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out
def test_disable_if(): class Main(m.Circuit): io = m.IO(a=m.In(m.Bit), b=m.In(m.Bit)) io += m.ClockIO(has_resetn=True) f.assert_(io.a | f.implies | f.delay[2] | io.b, on=f.posedge(io.CLK), disable_iff=f.not_(io.RESETN)) f.assert_(f.sva(io.a, "|-> ##2", io.b), on=f.posedge(io.CLK), disable_iff=f.not_(io.RESETN)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.RESETN = 1 tester.circuit.a = 1 tester.advance_cycle() tester.circuit.a = 0 tester.advance_cycle() tester.circuit.b = 1 tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.RESETN = 1 tester.circuit.a = 1 tester.advance_cycle() tester.circuit.a = 0 tester.advance_cycle() tester.circuit.RESETN = 0 tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.RESETN = 1 tester.circuit.a = 1 tester.advance_cycle() tester.circuit.a = 0 tester.advance_cycle() tester.advance_cycle() with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True})
def test_basic_assert_fail(sva, capsys): class Main(m.Circuit): io = m.IO(I=m.In(m.Bits[8]), O=m.Out(m.Bits[8])) + m.ClockIO() io.O @= m.Register(T=m.Bits[8])()(io.I) if sva: f.assert_(f.sva(io.I, "|-> ##1", io.O.value() == 0), on=f.posedge(io.CLK)) else: f.assert_(io.I | f.implies | f.delay[1] | (io.O.value() == 0), on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.I = 0 tester.advance_cycle() tester.advance_cycle() tester.circuit.I = 1 tester.advance_cycle() tester.advance_cycle() with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out
def test_basic_assert(): class Main(m.Circuit): io = m.IO(I=m.In(m.Bits[8]), O=m.Out(m.Bits[8])) + m.ClockIO() io.O @= m.Register(T=m.Bits[8])()(io.I) f.assert_(io.I | f.implies | f.delay[1] | io.O, on=f.posedge(io.CLK)) f.assert_(f.sva(io.I, "|-> ##1", io.O), on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.O.expect(1) tester.circuit.I = 0 tester.advance_cycle() tester.circuit.O.expect(0) tester.advance_cycle() tester.circuit.I = 1 tester.circuit.O.expect(0) tester.advance_cycle() tester.circuit.I = 0 tester.circuit.O.expect(1) tester.advance_cycle() tester.circuit.O.expect(0) tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True})
def test_user_namespace(target, simulator): t = f.SynchronousTester(SimpleALU, SimpleALU.CLK) t.circuit.config_en = 1 t.circuit.config_data = 0 t.advance_cycle() t.circuit.a = 1 t.circuit.b = 2 t.advance_cycle() t.circuit.c.expect(3) with tempfile.TemporaryDirectory(dir=".") as _dir: if target == "verilator": t.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"], magma_opts={ "user_namespace": "my_namespace", "sv": True }) else: t.compile_and_run(target, directory=_dir, simulator=simulator, magma_opts={ "user_namespace": "my_namespace", "sv": True })
def test_sipo_basic(): class test_sipo_basic(m.Circuit): io = m.IO(I=m.In(m.Bit), O=m.Out(m.Bits[5])) + m.ClockIO() io.O @= SIPO(5, m.Bit)()(io.I) m.compile("build/test_sipo_basic", test_sipo_basic) assert check_files_equal(__file__, f"build/test_sipo_basic.v", f"gold/test_sipo_basic.v") tester = fault.SynchronousTester(test_sipo_basic, test_sipo_basic.CLK) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.O.expect(0b00001) tester.advance_cycle() tester.circuit.O.expect(0b00011) tester.circuit.I = 0 tester.advance_cycle() tester.circuit.O.expect(0b00110) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.O.expect(0b01101) tester.circuit.I = 0 tester.advance_cycle() tester.circuit.O.expect(0b11010) tester.compile_and_run("verilator", skip_compile=True, directory=os.path.join(os.path.dirname(__file__), "build"))
def test_eventually(sva, capsys): class Main(m.Circuit): io = m.IO(write=m.In(m.Bit), read=m.In(m.Bit)) + m.ClockIO() if sva: f.assert_(f.sva(io.write == 1, f"|-> s_eventually", io.read == 1), on=f.posedge(io.CLK)) else: f.assert_( (io.write == 1) | f.implies | f.eventually | (io.read == 1), on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.write = 1 tester.circuit.read = 0 tester.advance_cycle() tester.circuit.write = 0 for i in range(random.randint(3, 7)): tester.advance_cycle() # Read does not eventually go high with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out tester.circuit.read = 1 tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True})
def test_repetition_or_more(sva, zero_or_one, capsys): # TODO: Parens/precedence with nested sequences (could wrap in seq object?) class Main(m.Circuit): io = m.IO(write=m.In(m.Bit), read=m.In(m.Bit)) + m.ClockIO() if sva: seq0 = f.sva(~io.read, "##1", io.write) seq1 = f.sva(io.read, "##1", io.write) symb = "*" if zero_or_one == 0 else "+" f.assert_(f.sva(seq0, "|-> ##1", io.read, f"[{symb}] ##1", seq1), on=f.posedge(io.CLK)) else: seq0 = ~io.read | f.delay[1] | io.write seq1 = io.read | f.delay[1] | io.write f.assert_(seq0 | f.implies | f.delay[1] | io.read | f.repeat[zero_or_one:] | f.delay[1] | seq1, on=f.posedge(io.CLK)) for i in range(0, 3): tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.write = 0 tester.circuit.read = 0 tester.advance_cycle() tester.circuit.write = 1 tester.advance_cycle() # Should fail if we don't see seq2 with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out # do repeated sequence i times for _ in range(i): tester.circuit.write = 0 tester.circuit.read = 1 tester.advance_cycle() tester.circuit.write = 0 tester.circuit.read = 1 tester.advance_cycle() tester.circuit.write = 1 tester.circuit.read = 0 tester.advance_cycle() tester.circuit.write = 0 tester.advance_cycle() if i == 0 and zero_or_one == 1: # Should fail on first try (0 times) with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) else: tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True})
def test_sipo_product(): class T(m.Product): X = m.Bit Y = m.Bits[5] class test_sipo_product(m.Circuit): io = m.IO(I=m.In(T), O=m.Out(m.Array[5, T])) + m.ClockIO() io.O @= SIPO(5, T)()(io.I) m.compile("build/test_sipo_product", test_sipo_product) assert check_files_equal(__file__, f"build/test_sipo_product.v", f"gold/test_sipo_product.v") tester = fault.SynchronousTester(test_sipo_product, test_sipo_product.CLK) sequence = [ { "X": 1, "Y": 3 }, { "X": 0, "Y": 1 }, { "X": 0, "Y": 2 }, { "X": 1, "Y": 4 }, { "X": 0, "Y": 7 }, ] for i in range(len(sequence)): tester.circuit.I = sequence[i] tester.advance_cycle() for j in range(0, i + 1): tester.circuit.O[j].expect(sequence[i - j]) for j in range(i + 1, len(sequence)): tester.circuit.O[j].expect(0) tester.circuit.I = 0 for i in range(len(sequence)): tester.advance_cycle() for j in range(i + 1, len(sequence)): tester.circuit.O[j].expect(sequence[i - j]) for j in range(0, i + 1): tester.circuit.O[j].expect(0) tester.compile_and_run("verilator", skip_compile=True, directory=os.path.join(os.path.dirname(__file__), "build"))
def test_sw(sw, input_bv, output_bv): t = fault.SynchronousTester(sw, sw.CLK) t.circuit.inputMemBlockValid = False t.circuit.outputMemAddrReady = False t.circuit.outputMemBlockReady = False t.circuit.inputMemAddrReady = False t.advance_cycle() inputLeft = input_bv curInputAddr = sw.inputStartAddr lengthLine = True while len(inputLeft) > 0: t.circuit.inputMemAddrReady = True t.wait_until_high(t.circuit.inputMemAddrValid) t.circuit.inputMemAddr.expect(curInputAddr) curLen = 1 if lengthLine else \ min(64, len(inputLeft) // sw.busWidth) # bits left should be multiple of busWidth t.circuit.inputMemAddrLen.expect(curLen - 1) t.advance_cycle() t.circuit.inputMemAddrReady = False t.circuit.inputMemBlockValid = True for i in range(curLen): t.circuit.inputMemBlock = inputLeft[:sw.busWidth] t.wait_until_high(t.circuit.inputMemBlockReady) t.advance_cycle() curInputAddr += sw.busWidth // 8 inputLeft = inputLeft[sw.busWidth:] t.circuit.inputMemBlockValid = False lengthLine = False outputLeft = output_bv curOutputAddr = sw.outputStartAddr while len(outputLeft) > 0: t.circuit.outputMemAddrReady = True t.wait_until_high(t.circuit.outputMemAddrValid) t.circuit.outputMemAddr.expect(curOutputAddr) t.advance_cycle() t.circuit.outputMemAddrReady = False t.circuit.outputMemBlockReady = True t.wait_until_high(t.circuit.outputMemBlockValid) outputBits = min(sw.busWidth, len(outputLeft)) t.expect(t.circuit.outputMemBlock[:outputBits], outputLeft[:outputBits]) t.advance_cycle() t.circuit.outputMemBlockReady = False curOutputAddr += sw.busWidth // 8 outputLeft = outputLeft[outputBits:] t.circuit.finished.expect(True) t.compile_and_run("verilator")
def test_repetition(sva, capsys): class Main(m.Circuit): io = m.IO(write=m.In(m.Bit), read=m.In(m.Bit)) + m.ClockIO() N = 2 if sva: seq0 = f.sequence(f.sva(~io.read, "##1", io.write)) seq1 = f.sequence(f.sva(io.read, "##1", io.write)) f.assert_(f.sva(~io.read & ~io.write, "[*2] |->", seq0, f"[*{N}] ##1", seq1), on=f.posedge(io.CLK)) else: seq0 = f.sequence(~io.read | f.delay[1] | io.write) seq1 = f.sequence(io.read | f.delay[1] | io.write) f.assert_(~io.read & ~io.write | f.repeat[2] | f.implies | seq0 | f.repeat[N] | f.delay[1] | seq1, on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.write = 0 tester.circuit.read = 0 tester.advance_cycle() for _ in range(2): tester.circuit.write = 0 tester.circuit.read = 0 tester.advance_cycle() tester.circuit.write = 1 tester.advance_cycle() # Should fail if we don't see seq2 with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out, out tester.circuit.write = 0 tester.circuit.read = 1 tester.advance_cycle() tester.circuit.write = 1 tester.circuit.read = 0 tester.advance_cycle() tester.circuit.write = 0 tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True})
def test_assume(capsys): class Main(m.Circuit): io = m.IO(I=m.In(m.Bit), O=m.Out(m.Bit)) + m.ClockIO() io.O @= m.Register(T=m.Bit)()(io.I) f.assume(io.I | f.delay[1] | ~io.I, on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.I = 1 tester.advance_cycle() # assume behaves like assert in simulation (but used as an assumption for # formal tools) with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True})
def test_ifdef_and_name(capsys, compile_guard): class Main(m.Circuit): io = m.IO(a=m.In(m.Bit), b=m.In(m.Bit)) io += m.ClockIO(has_resetn=True) f.assert_(io.a | f.implies | f.delay[2] | io.b, on=f.posedge(io.CLK), disable_iff=f.not_(io.RESETN), compile_guard=compile_guard, name="foo") temp = m.Bit(name="temp") temp @= io.a f.assert_(f.sva(temp, "|-> ##2", io.b), on=f.posedge(io.CLK), disable_iff=f.not_(io.RESETN), compile_guard=compile_guard, name="bar") tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.RESETN = 1 tester.circuit.a = 1 tester.advance_cycle() tester.circuit.a = 0 tester.advance_cycle() tester.advance_cycle() # Should not fail with no ASSERT_ON tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) # Check that wire prefix is generated properly with open("build/Main.v", "r") as file_: assert "wire _FAULT_ASSERT_WIRE_0" in file_.read() # Should fail with pytest.raises(AssertionError): if isinstance(compile_guard, str): compile_guard = [compile_guard] tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"] + [f"+define+{guard}" for guard in compile_guard], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.foo has failed" in out assert "Assertion Main_tb.dut.bar has failed" in out
def test_goto_repetition(sva, num_reps, capsys): class Main(m.Circuit): io = m.IO(write=m.In(m.Bit), read=m.In(m.Bit)) + m.ClockIO() if sva: symb = num_reps if isinstance(symb, slice): symb = f"{symb.start}:{symb.stop}" f.assert_(f.sva(io.write == 1, f"[-> {symb}]", '##1', io.read, '##1', io.write), on=f.posedge(io.CLK)) else: f.assert_((io.write == 1) | f.goto[num_reps] | f.delay[1] | io.read | f.delay[1] | io.write, on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.write = 1 tester.circuit.read = 0 n = num_reps if isinstance(n, slice): n = random.randint(n.start, n.stop) for i in range(n): tester.advance_cycle() tester.circuit.read = 1 tester.circuit.write = 0 tester.advance_cycle() tester.circuit.read = 1 tester.circuit.write = 1 tester.advance_cycle() tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) tester.circuit.read = 0 tester.advance_cycle() with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out
def test_cover(capsys): class Main(m.Circuit): io = m.IO(I=m.In(m.Bit), O=m.Out(m.Bit)) + m.ClockIO() io.O @= m.Register(T=m.Bit)()(io.I) f.cover(io.I | f.delay[1] | ~io.I, on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.I = 1 tester.advance_cycle() tester.circuit.I = 1 tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}, disp_type="realtime", coverage=True) out, _ = capsys.readouterr() # not covered assert """\ Disabled Finish Failed Assertion Name 0 0 0 Main_tb.dut.__cover1 Total Assertions = 1, Failing Assertions = 0, Unchecked Assertions = 1\ """ in out tester.circuit.I = 1 tester.advance_cycle() tester.circuit.I = 0 tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}, disp_type="realtime", coverage=True) out, _ = capsys.readouterr() # covered assert """\ Disabled Finish Failed Assertion Name 0 1 0 Main_tb.dut.__cover1 Total Assertions = 1, Failing Assertions = 0, Unchecked Assertions = 0\ """ in out
def test_default_clock_function(): def my_assert(property, on=None, disable_iff=None): # If needed, create undriven clock/reset temporaries, will be driven by # automatic clock wiring logic if on is None: on = f.posedge(m.Clock()) if disable_iff is None: disable_iff = f.not_(m.AsyncResetN()) f.assert_(property, on=on, disable_iff=disable_iff) class ClockIntf(m.Product): clock = m.In(m.Clock) reset = m.In(m.AsyncResetN) class Main(m.Circuit): io = m.IO(I=m.In(m.Bits[8]), O=m.Out(m.Bits[8])) io += m.IO(clocks=ClockIntf) io.O @= m.Register(T=m.Bits[8], reset_type=m.AsyncResetN)()(io.I) my_assert(io.I | f.implies | f.delay[1] | io.O) tester = f.SynchronousTester(Main, Main.clocks.clock) I_seq = [1, 0, 1, 0, 0] O_seq = [1, 0, 1, 0, 0] tester.circuit.clocks.reset = 1 for I, O in zip(I_seq, O_seq): tester.circuit.I = I tester.advance_cycle() tester.circuit.O.expect(O) # Should disable during reset tester.circuit.I = 1 tester.circuit.clocks.reset = 0 tester.advance_cycle() tester.circuit.O.expect(0) tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={ "inline": True, "drive_undriven": True, "terminate_unused": True })
def test_variable_delay(sva, capsys): class Main(m.Circuit): io = m.IO(write=m.In(m.Bit), read=m.In(m.Bit)) + m.ClockIO() if sva: f.assert_(f.sva(io.write, "|-> ##[1:2]", io.read), on=f.posedge(io.CLK)) f.assert_(f.sva(io.write, "|-> ##[*]", io.read), on=f.posedge(io.CLK)) f.assert_(f.sva(io.write, "|-> ##[+]", io.read), on=f.posedge(io.CLK)) else: f.assert_(io.write | f.implies | f.delay[1:2] | io.read, on=f.posedge(io.CLK)) f.assert_(io.write | f.implies | f.delay[0:] | io.read, on=f.posedge(io.CLK)) f.assert_(io.write | f.implies | f.delay[1:] | io.read, on=f.posedge(io.CLK)) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.write = 1 tester.advance_cycle() tester.circuit.write = 0 tester.circuit.read = 1 tester.advance_cycle() tester.circuit.write = 1 tester.circuit.read = 0 tester.advance_cycle() tester.circuit.write = 0 tester.advance_cycle() tester.circuit.read = 1 tester.advance_cycle() tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.write = 1 tester.circuit.read = 0 tester.advance_cycle() tester.advance_cycle() tester.advance_cycle() with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out tester = f.SynchronousTester(Main, Main.CLK) tester.circuit.write = 1 tester.circuit.read = 1 tester.advance_cycle() # Does not pass 1 or more cycles tester.circuit.read = 0 tester.advance_cycle() tester.advance_cycle() with pytest.raises(AssertionError): tester.compile_and_run("system-verilog", simulator="ncsim", flags=["-sv"], magma_opts={"inline": True}) out, _ = capsys.readouterr() assert "Assertion Main_tb.dut.__assert_1 has failed" in out
def test_queue(with_bug): T = m.Bits[8] Queue4x8 = Queue(T, 4, with_bug=with_bug) class Monitor(m.Circuit): io = m.IO(enq=m.In(m.ReadyValid[T]), deq=m.In( m.ReadyValid[T])) + m.ClockIO() m.inline_verilog("""\ reg [7:0] data [0:3]; reg [2:0] write_pointer; reg [2:0] read_pointer; wire wen; wire ren; wire full; wire empty; assign wen = {io.enq.valid} & {io.enq.ready}; assign ren = {io.deq.ready} & {io.deq.valid}; assign empty = write_pointer == read_pointer; assign full = ((write_pointer[1:0] == read_pointer[1:0]) & (write_pointer[2] == ~read_pointer[2])); always @(posedge {io.CLK}) begin if (wen) begin assert (!full) else $error("Trying to write to full buffer"); data[write_pointer[1:0]] <= {io.enq.data}; write_pointer <= write_pointer + 1; end if (ren) begin assert (!empty) else $error("Trying to read from empty buffer"); assert ({io.deq.data} == data[read_pointer[1:0]]) else $error("Got wrong read data: io.deq.data %x != %x", {io.deq.data}, data[read_pointer[1:0]]); read_pointer <= read_pointer + 1; end end""") class DUT(m.Circuit): io = m.IO( enq=m.DeqIO[T], deq=m.EnqIO[T], ) + m.ClockIO() queue = Queue4x8() queue.enq @= io.enq queue.deq @= io.deq monitor = Monitor() monitor.enq.valid @= io.enq.valid monitor.enq.data @= io.enq.data monitor.enq.ready @= queue.enq.ready monitor.deq.valid @= queue.deq.valid monitor.deq.data @= queue.deq.data monitor.deq.ready @= io.deq.ready tester = fault.SynchronousTester(DUT, DUT.CLK) data = [0xDE, 0xAD, 0xBE, 0xEF] for i in range(32): tester.circuit.enq.data = random.choice(data) tester.circuit.enq.valid = random.randint(0, 1) tester.circuit.deq.ready = random.randint(0, 1) tester.advance_cycle() try: tester.compile_and_run("verilator", flags=["--assert"], magma_opts={"inline": True}) assert not with_bug except AssertionError: assert with_bug