def test_target_clock(capsys, target, simulator): circ = TestBasicClkCircuit actions = [ Print(TEST_START + '\n'), Poke(circ.I, 0), Eval(), Print("%x\n", circ.I), Expect(circ.O, 0), Poke(circ.CLK, 0), Print("%x\n", circ.O), Step(circ.CLK, 1), Poke(circ.I, BitVector[1](1)), Eval(), Print("%x\n", circ.O), ] run(circ, actions, target, simulator, flags=["-Wno-lint"], disp_type='realtime') messages = outlines(capsys) idx = messages.index(TEST_START) + 1 actual = "\n".join(messages[idx:idx + 3]) assert actual == """\
def test_print_nested_arrays(capfd, target, simulator): circ = common.TestNestedArraysCircuit actions = [ Poke(circ.I, [BitVector(i, 4) for i in range(3)]), Print(circ.I), Eval(), Expect(circ.O, [BitVector(i, 4) for i in range(3)]), Print(circ.O), Poke(circ.I, [BitVector(4 - i, 4) for i in range(3)]), Eval(), Print(circ.O), ] run(circ, actions, target, simulator, flags=["-Wno-lint"]) out, err = capfd.readouterr() if target == fault.verilator_target.VerilatorTarget: actual = "\n".join(out.splitlines()[-9:]) else: if simulator == "ncsim": actual = "\n".join(out.splitlines()[-9 - 3:-3]) elif simulator == "vcs": actual = "\n".join(out.splitlines()[-9 - 6:-6]) else: raise NotImplementedError(f"Unsupported simulator: {simulator}") assert actual == """\ NestedArraysCircuit.I[0] = 0 NestedArraysCircuit.I[1] = 1 NestedArraysCircuit.I[2] = 2 NestedArraysCircuit.O[0] = 0 NestedArraysCircuit.O[1] = 1 NestedArraysCircuit.O[2] = 2 NestedArraysCircuit.O[0] = 4 NestedArraysCircuit.O[1] = 3 NestedArraysCircuit.O[2] = 2""", out
def test_print_nested_arrays(capsys, target, simulator): circ = TestNestedArraysCircuit actions = [ Poke(circ.I, [BitVector[4](i) for i in range(3)]), ] + [Print("%x\n", i) for i in circ.I] + [ Eval(), Expect(circ.O, [BitVector[4](i) for i in range(3)]), ] + [Print("%x\n", i) for i in circ.O] + [ Poke(circ.I, [BitVector[4](4 - i) for i in range(3)]), Eval(), ] + [Print("%x\n", i) for i in circ.O] run(circ, actions, target, simulator, flags=["-Wno-lint"], disp_type='realtime') messages = outlines(capsys) if target == fault.verilator_target.VerilatorTarget: actual = "\n".join(messages[-10:-1]) else: if simulator == "ncsim": actual = "\n".join(messages[-13:-4]) elif simulator == "vcs": actual = "\n".join(messages[-16:-7]) else: raise NotImplementedError(f"Unsupported simulator: {simulator}") assert actual == """\
def test_print_double_nested_arrays(capsys, target, simulator): circ = TestDoubleNestedArraysCircuit actions = [Print(TEST_START + '\n')] + [ Poke(circ.I, [[BitVector[4](i + j * 3) for i in range(3)] for j in range(2)]), Eval(), ] + [Print("%x\n", j) for i in circ.I for j in i] + [ Eval(), Expect(circ.O, [[BitVector[4](i + j * 3) for i in range(3)] for j in range(2)]), ] + [Print("%x\n", j) for i in circ.O for j in i] + [ Poke(circ.I, [[BitVector[4](i + (j + 1) * 3) for i in range(3)] for j in range(2)]), Eval(), ] + [Print("%x\n", j) for i in circ.O for j in i] run(circ, actions, target, simulator, flags=["-Wno-lint"], disp_type='realtime') messages = outlines(capsys) idx = messages.index(TEST_START) + 1 actual = "\n".join(messages[idx:idx + 18]) assert actual == """\
def test_tester_basic(target, simulator): circ = common.TestBasicCircuit tester = fault.Tester(circ) tester.zero_inputs() check(tester.actions[0], Poke(circ.I, 0)) tester.poke(circ.I, 1) tester.eval() tester.expect(circ.O, 1) tester.print(circ.O, "%08x") check(tester.actions[1], Poke(circ.I, 1)) check(tester.actions[2], Eval()) check(tester.actions[3], Expect(circ.O, 1)) check(tester.actions[4], Print(circ.O, "%08x")) tester.eval() check(tester.actions[5], Eval()) with tempfile.TemporaryDirectory() as _dir: if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator) tester.compile_and_run("coreir") tester.clear() assert tester.actions == []
def test_print_double_nested_arrays(capsys, target, simulator): circ = TestDoubleNestedArraysCircuit actions = [ Poke(circ.I, [[BitVector[4](i + j * 3) for i in range(3)] for j in range(2)]), ] + [Print("%x\n", j) for i in circ.I for j in i] + [ Eval(), Expect(circ.O, [[BitVector[4](i + j * 3) for i in range(3)] for j in range(2)]), ] + [Print("%x\n", j) for i in circ.O for j in i] + [ Poke(circ.I, [[BitVector[4](i + (j + 1) * 3) for i in range(3)] for j in range(2)]), Eval(), ] + [Print("%x\n", j) for i in circ.O for j in i] run(circ, actions, target, simulator, flags=["-Wno-lint"], disp_type='realtime') messages = outlines(capsys) if target == fault.verilator_target.VerilatorTarget: actual = "\n".join(messages[-19:-1]) else: if simulator == "ncsim": actual = "\n".join(messages[-22:-4]) elif simulator == "vcs": actual = "\n".join(messages[-25:-7]) else: raise NotImplementedError(f"Unsupported simulator: {simulator}") assert actual == """\ 0 1 2 3 4 5 0 1 2 3 4 5 3 4 5 6 7 8\ """, out
def test_tester_basic(target, simulator): circ = TestBasicCircuit tester = fault.Tester(circ) tester.zero_inputs() check(tester.actions[0], Poke(circ.I, 0)) tester.poke(circ.I, 1) tester.eval() tester.expect(circ.O, 1) tester.print("%08x", circ.O) check(tester.actions[1], Poke(circ.I, 1)) check(tester.actions[2], Eval()) check(tester.actions[3], Expect(circ.O, 1)) print(tester.actions[4]) print(Print("%08x", circ.O)) check(tester.actions[4], Print("%08x", circ.O)) tester.eval() check(tester.actions[5], Eval()) tester.poke(circ.I, 0) tester.eval() tester.expect(circ.O, 0) tester.poke(circ.I, True) tester.eval() tester.expect(circ.O, True) tester.poke(circ.I, False) tester.eval() tester.expect(circ.O, False) tester.poke(circ.I, False) tester.eval() tester.expect(circ.O, False) tester.poke(circ.I, hwtypes.Bit(1)) tester.eval() tester.expect(circ.O, hwtypes.Bit(1)) tester.poke(circ.I, hwtypes.Bit(0)) tester.eval() tester.expect(circ.O, hwtypes.Bit(0)) with tempfile.TemporaryDirectory(dir=".") as _dir: if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator, magma_opts={"sv": True}) tester.compile_and_run("coreir") tester.clear() assert tester.actions == []
def test_target_clock(capfd, target, simulator): circ = common.TestBasicClkCircuit actions = [ Poke(circ.I, 0), Print(circ.I), Expect(circ.O, 0), Poke(circ.CLK, 0), Print(circ.O), Step(circ.CLK, 1), Poke(circ.I, BitVector(1, 1)), Eval(), Print(circ.O), ] run(circ, actions, target, simulator, flags=["-Wno-lint"]) out, err = capfd.readouterr() lines = out.splitlines() if target == fault.verilator_target.VerilatorTarget: assert lines[-3] == "BasicClkCircuit.I = 0", out assert lines[-2] == "BasicClkCircuit.O = 0", out assert lines[-1] == "BasicClkCircuit.O = 1", out else: if simulator == "ncsim": assert lines[-6] == "BasicClkCircuit.I = 0", out assert lines[-5] == "BasicClkCircuit.O = 0", out assert lines[-4] == "BasicClkCircuit.O = 1", out elif simulator == "vcs": assert lines[-9] == "BasicClkCircuit.I = 0", out assert lines[-8] == "BasicClkCircuit.O = 0", out assert lines[-7] == "BasicClkCircuit.O = 1", out else: raise NotImplementedError(f"Unsupported simulator: {simulator}")
def test_target_basic(target, simulator): """ Test basic workflow with a simple circuit. """ circ = TestBasicCircuit actions = (Poke(circ.I, 0), Eval(), Expect(circ.O, 0)) run(circ, actions, target, simulator)
def test_tester_nested_array_tuple_broadcast(target, simulator): circ = TestNestedArrayTupleCircuit tester = fault.Tester(circ) expected = [] val = (random.randint(0, (1 << 4) - 1), random.randint(0, (1 << 4) - 1)) tester.poke(circ.I, val) for j in range(2): for i in range(3): expected.append(Poke(circ.I[j][i].a, val[0])) expected.append(Poke(circ.I[j][i].b, val[1])) tester.eval() expected.append(Eval()) for j in range(2): for i in range(3): tester.expect(circ.O[j][i], val) expected.append(Expect(circ.O[j][i].a, val[0])) expected.append(Expect(circ.O[j][i].b, val[1])) for i, exp in enumerate(expected): check(tester.actions[i], exp) with tempfile.TemporaryDirectory(dir=".") as _dir: if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator, magma_opts={"sv": True})
def test_verilator_trace(): circ = TestBasicClkCircuit actions = [ Poke(circ.I, 0), Print("%x", circ.I), Expect(circ.O, 0), Poke(circ.CLK, 0), Print("%x", circ.O), Step(circ.CLK, 1), Poke(circ.I, BitVector[1](1)), Eval(), Print("%x", circ.O), ] flags = ["-Wno-lint", "--trace"] with tempfile.TemporaryDirectory(dir=".") as tempdir: assert not os.path.isfile(f"{tempdir}/logs/BasicClkCircuit.vcd"), \ "Expected logs to be empty" m.compile(f"{tempdir}/{circ.name}", circ, output="coreir-verilog") target = fault.verilator_target.VerilatorTarget( circ, directory=f"{tempdir}/", flags=flags, skip_compile=True) target.run(actions) assert os.path.isfile(f"{tempdir}/logs/BasicClkCircuit.vcd"), \ "Expected VCD to exist"
def test_print_double_nested_arrays(capfd, target, simulator): circ = common.TestDoubleNestedArraysCircuit actions = [ Poke(circ.I, [[BitVector(i + j * 3, 4) for i in range(3)] for j in range(2)]), Print(circ.I), Eval(), Expect(circ.O, [[BitVector(i + j * 3, 4) for i in range(3)] for j in range(2)]), Print(circ.O), Poke(circ.I, [[BitVector(i + (j + 1) * 3, 4) for i in range(3)] for j in range(2)]), Eval(), Print(circ.O), ] run(circ, actions, target, simulator, flags=["-Wno-lint"]) out, err = capfd.readouterr() print(out) if target == fault.verilator_target.VerilatorTarget: actual = "\n".join(out.splitlines()[-18:]) else: if simulator == "ncsim": actual = "\n".join(out.splitlines()[-18 - 3:-3]) elif simulator == "vcs": actual = "\n".join(out.splitlines()[-18 - 6:-6]) else: raise NotImplementedError(f"Unsupported simulator: {simulator}") assert actual == """\ DoubleNestedArraysCircuit.I[0][0] = 0 DoubleNestedArraysCircuit.I[0][1] = 1 DoubleNestedArraysCircuit.I[0][2] = 2 DoubleNestedArraysCircuit.I[1][0] = 3 DoubleNestedArraysCircuit.I[1][1] = 4 DoubleNestedArraysCircuit.I[1][2] = 5 DoubleNestedArraysCircuit.O[0][0] = 0 DoubleNestedArraysCircuit.O[0][1] = 1 DoubleNestedArraysCircuit.O[0][2] = 2 DoubleNestedArraysCircuit.O[1][0] = 3 DoubleNestedArraysCircuit.O[1][1] = 4 DoubleNestedArraysCircuit.O[1][2] = 5 DoubleNestedArraysCircuit.O[0][0] = 3 DoubleNestedArraysCircuit.O[0][1] = 4 DoubleNestedArraysCircuit.O[0][2] = 5 DoubleNestedArraysCircuit.O[1][0] = 6 DoubleNestedArraysCircuit.O[1][1] = 7 DoubleNestedArraysCircuit.O[1][2] = 8\ """, out
def generate_code(self, actions, verilator_includes, num_tests, circuit): if verilator_includes: # Include the top circuit by default verilator_includes.insert(0, f'{self.circuit_name}') includes = [ f'"V{self.circuit_name}.h"', ] + [ f'"V{self.circuit_name}_{include}.h"' for include in verilator_includes ] + [ '"verilated.h"', '<iostream>', '<fstream>', '<verilated_vcd_c.h>', '<sys/types.h>', '<sys/stat.h>', ] # if we're using the GetValue feature, then we need to open/close a # file in which GetValue results will be written if any(isinstance(action, GetValue) for action in actions): actions = [FileOpen(self.value_file)] + actions actions += [FileClose(self.value_file)] main_body = "" for i, action in enumerate(actions): code = self.generate_action_code(i, action) for line in code: main_body += f" {line}\n" for i in range(num_tests): main_body += self.add_assumptions(circuit, actions, i) code = self.make_eval(i, Eval()) for line in code: main_body += f" {line}\n" main_body += self.add_guarantees(circuit, actions, i) includes += [ f'"V{self.circuit_name}_{include}.h"' for include in self.debug_includes ] includes_src = "\n".join(["#include " + i for i in includes]) if self.use_kratos: includes_src += "\nvoid initialize_runtime();\n" includes_src += "void teardown_runtime();\n" kratos_start_call = "initialize_runtime();" kratos_exit_call = "teardown_runtime();" else: kratos_start_call = "" kratos_exit_call = "" src = src_tpl.format(includes=includes_src, main_body=main_body, circuit_name=self.circuit_name, kratos_start_call=kratos_start_call, kratos_exit_call=kratos_exit_call) return src
def test_magma_simulator_target_nested_arrays_bulk(backend): circ = common.TestNestedArraysCircuit expected = [random_bv(4) for i in range(3)] actions = [] actions.append(Poke(circ.I, expected)) actions.append(Eval()) actions.append(Expect(circ.O, expected)) run(circ, actions, None, backend)
def test_target_nested_arrays_bulk(target, simulator): circ = common.TestNestedArraysCircuit expected = [random.randint(0, (1 << 4) - 1) for i in range(3)] actions = [] actions.append(Poke(circ.I, expected)) actions.append(Eval()) actions.append(Expect(circ.O, expected)) run(circ, actions, target, simulator)
def test_action_strs(): circ = common.TestBasicClkCircuit assert str(Poke(circ.I, 1)) == 'Poke(BasicClkCircuit.I, 1)' assert str(Expect(circ.O, 1)) == 'Expect(BasicClkCircuit.O, 1)' assert str(Eval()) == 'Eval()' assert str(Step(circ.CLK, 1)) == 'Step(BasicClkCircuit.CLK, steps=1)' assert str(Print(circ.O, "%08x")) == 'Print(BasicClkCircuit.O, "%08x")' assert str(Peek(circ.O)) == 'Peek(BasicClkCircuit.O)'
def test_target_peek(target, simulator): circ = TestPeekCircuit actions = [] for i in range(3): x = random_bv(3) actions.append(Poke(circ.I, x)) actions.append(Eval()) actions.append(Expect(circ.O0, Peek(circ.O1))) run(circ, actions, target, simulator)
def test_target_sint_sign_extend(width, target, simulator): circ = define_simple_circuit(m.SInt[width], f"test_target_sint_sign_extend_{width}") actions = [ Poke(circ.I, -2), Eval(), Expect(circ.O, -2), ] run(circ, actions, target, simulator)
def test_tester_basic(): circ = TestBasicCircuit builder = VectorBuilder(circ) builder.process(Poke(circ.I, BitVector[1](0))) builder.process(Expect(circ.O, BitVector[1](0))) assert builder.vectors == [[BitVector[1](0), BitVector[1](0)]] builder.process(Eval()) assert builder.vectors == [[BitVector[1](0), BitVector[1](0)], [BitVector[1](0), fault.AnyValue]]
def test_magma_simulator_target_basic(backend): """ Test basic python simulator workflow with a simple circuit. """ circ = common.TestBasicCircuit actions = [ Poke(circ.I, BitVector(0, 1)), Expect(circ.O, BitVector(0, 1)), Eval(), Poke(circ.I, BitVector(1, 1)), Expect(circ.O, BitVector(0, 1)), Eval(), Poke(circ.I, BitVector(0, 1)), Expect(circ.O, BitVector(1, 1)), Eval(), Expect(circ.O, BitVector(0, 1)), ] run(circ, actions, None, backend)
def test_magma_simulator_target_peek(backend): circ = common.TestPeekCircuit actions = [] for i in range(3): x = random_bv(3) actions.append(Poke(circ.I, x)) actions.append(Eval()) actions.append(Expect(circ.O0, Peek(circ.O1))) run(circ, actions, None, backend)
def test_target_nested_arrays_by_element(target, simulator): circ = TestNestedArraysCircuit expected = [random.randint(0, (1 << 4) - 1) for i in range(3)] actions = [] for i, val in enumerate(expected): actions.append(Poke(circ.I[i], val)) actions.append(Eval()) for i, val in enumerate(expected): actions.append(Expect(circ.O[i], val)) run(circ, actions, target, simulator)
def test_target_tuple(target, simulator): circ = TestTupleCircuit actions = [ Poke(circ.I.a, 5), Poke(circ.I.b, 11), Eval(), Expect(circ.O.a, 5), Expect(circ.O.b, 11), ] run(circ, actions, target, simulator)
def test_magma_simulator_target_nested_arrays_by_element(backend): circ = common.TestNestedArraysCircuit expected = [random_bv(4) for i in range(3)] actions = [] for i, val in enumerate(expected): actions.append(Poke(circ.I[i], val)) actions.append(Eval()) for i, val in enumerate(expected): actions.append(Expect(circ.O[i], val)) run(circ, actions, None, backend)
def test_retarget_tester(target, simulator): circ = TestBasicClkCircuit expected = [ Poke(circ.I, 0), Eval(), Expect(circ.O, 0), Poke(circ.CLK, 0), Step(circ.CLK, 1), Print("%08x", circ.O) ] tester = fault.Tester(circ, circ.CLK) tester.poke(circ.I, 0) tester.eval() tester.expect(circ.O, 0) tester.poke(circ.CLK, 0) tester.step() tester.print("%08x", circ.O) for i, exp in enumerate(expected): check(tester.actions[i + 1], exp) circ_copy = TestBasicClkCircuitCopy copy = tester.retarget(circ_copy, circ_copy.CLK) copy_expected = [ Poke(circ_copy.I, 0), Eval(), Expect(circ_copy.O, 0), Poke(circ_copy.CLK, 0), Step(circ_copy.CLK, 1), Print("%08x", circ_copy.O) ] for i, exp in enumerate(copy_expected): check(copy.actions[i + 1], exp) with tempfile.TemporaryDirectory(dir=".") as _dir: if target == "verilator": copy.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: copy.compile_and_run(target, directory=_dir, simulator=simulator, magma_opts={"sv": True})
def test_retarget_tester(target, simulator): circ = common.TestBasicClkCircuit expected = [ Poke(circ.I, 0), Eval(), Expect(circ.O, 0), Poke(circ.CLK, 0), Step(circ.CLK, 1), Print(circ.O, "%08x") ] tester = fault.Tester(circ, circ.CLK, default_print_format_str="%08x") tester.poke(circ.I, 0) tester.eval() tester.expect(circ.O, 0) tester.poke(circ.CLK, 0) tester.step() tester.print(circ.O) for i, exp in enumerate(expected): check(tester.actions[i], exp) circ_copy = common.TestBasicClkCircuitCopy copy = tester.retarget(circ_copy, circ_copy.CLK) assert copy.default_print_format_str == "%08x" copy_expected = [ Poke(circ_copy.I, 0), Eval(), Expect(circ_copy.O, 0), Poke(circ_copy.CLK, 0), Step(circ_copy.CLK, 1), Print(circ_copy.O, "%08x") ] for i, exp in enumerate(copy_expected): check(copy.actions[i], exp) with tempfile.TemporaryDirectory() as _dir: if target == "verilator": copy.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: copy.compile_and_run(target, directory=_dir, simulator=simulator)
def test_tester_peek_input(target, simulator): circ = TestBasicCircuit tester = fault.Tester(circ) tester.poke(circ.I, 1) tester.eval() tester.expect(circ.O, tester.peek(circ.I)) check(tester.actions[0], Poke(circ.I, 1)) check(tester.actions[1], Eval()) check(tester.actions[2], Expect(circ.O, Peek(circ.I))) with tempfile.TemporaryDirectory(dir=".") as _dir: if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator)
def test_action_strs(): circ = common.TestBasicClkCircuit assert str(Poke(circ.I, 1)) == 'Poke(BasicClkCircuit.I, 1)' assert str(Expect(circ.O, 1)) == 'Expect(BasicClkCircuit.O, 1)' assert str(Eval()) == 'Eval()' assert str(Step(circ.CLK, 1)) == 'Step(BasicClkCircuit.CLK, steps=1)' assert str(Print(circ.O, "%08x")) == 'Print(BasicClkCircuit.O, "%08x")' assert str(Peek(circ.O)) == 'Peek(BasicClkCircuit.O)' index = f"__fault_loop_var_action_0" assert str(Loop(12, index, [Peek(circ.O), Poke(circ.I, 1)])) == \ f'Loop(12, {index}, ' \ f'[Peek(BasicClkCircuit.O), Poke(BasicClkCircuit.I, 1)])' file = File("my_file", Tester(circ), "r", 1) assert str(FileOpen(file)) == 'FileOpen(File<"my_file">)' assert str(FileRead(file)) == 'FileRead(File<"my_file">)' assert str(FileWrite(file, 3)) == 'FileWrite(File<"my_file">, 3)' assert str(FileClose(file)) == 'FileClose(File<"my_file">)'
def test_tester_128(target, simulator): circ = TestUInt128Circuit tester = fault.Tester(circ) expected = [] val = random.randint(0, (1 << 128) - 1) tester.poke(circ.I, val) tester.eval() tester.expect(circ.O, val) expected.append(Poke(circ.I, val)) expected.append(Eval()) expected.append(Expect(circ.O, val)) for i, exp in enumerate(expected): check(tester.actions[i], exp) with tempfile.TemporaryDirectory(dir=".") as _dir: if target == "verilator": tester.compile_and_run(target, directory=_dir, flags=["-Wno-fatal"]) else: tester.compile_and_run(target, directory=_dir, simulator=simulator)
def generate_code(self, actions, verilator_includes, num_tests, circuit): if verilator_includes: # Include the top circuit by default verilator_includes.insert(0, f'{self.circuit_name}') includes = [ f'"V{self.circuit_name}.h"', ] + [ f'"V{self.circuit_name}_{include}.h"' for include in verilator_includes ] + [ '"verilated.h"', '<iostream>', '<fstream>', '<verilated_vcd_c.h>', '<sys/types.h>', '<sys/stat.h>', ] main_body = "" for i, action in enumerate(actions): code = self.generate_action_code(i, action) for line in code: main_body += f" {line}\n" for i in range(num_tests): main_body += self.add_assumptions(circuit, actions, i) code = self.make_eval(i, Eval()) for line in code: main_body += f" {line}\n" main_body += self.add_guarantees(circuit, actions, i) includes += [ f'"V{self.circuit_name}_{include}.h"' for include in self.debug_includes ] includes_src = "\n".join(["#include " + i for i in includes]) src = src_tpl.format( includes=includes_src, main_body=main_body, circuit_name=self.circuit_name, ) return src