From a47c6e660b6c691e6546f892c99564e178d10377 Mon Sep 17 00:00:00 2001 From: Staf Verhaegen Date: Sat, 3 Apr 2021 20:57:50 +0200 Subject: [PATCH] Support running tb on test_issuer subblock. Use wrapper class around dut that select proper signals depending on top cell used. Should be able to be used later to extend to post_pnr netlist. --- ls180/pre_pnr/Makefile | 1 - ...{run_iverilog.sh => run_iverilog_ls180.sh} | 5 +- ls180/pre_pnr/run_iverilog_ti.sh | 13 ++ ls180/pre_pnr/test.py | 204 ++++++++++-------- 4 files changed, 131 insertions(+), 92 deletions(-) rename ls180/pre_pnr/{run_iverilog.sh => run_iverilog_ls180.sh} (71%) create mode 100755 ls180/pre_pnr/run_iverilog_ti.sh diff --git a/ls180/pre_pnr/Makefile b/ls180/pre_pnr/Makefile index 663ece6..4fbc60f 100644 --- a/ls180/pre_pnr/Makefile +++ b/ls180/pre_pnr/Makefile @@ -11,7 +11,6 @@ VERILOG_SOURCES := \ ../../../litex/florent/ls180.v \ # END VERILOG_SOURCES -TOPLEVEL := ls180 MODULE := test include $(shell cocotb-config --makefiles)/Makefile.sim diff --git a/ls180/pre_pnr/run_iverilog.sh b/ls180/pre_pnr/run_iverilog_ls180.sh similarity index 71% rename from ls180/pre_pnr/run_iverilog.sh rename to ls180/pre_pnr/run_iverilog_ls180.sh index 2866883..eae0986 100755 --- a/ls180/pre_pnr/run_iverilog.sh +++ b/ls180/pre_pnr/run_iverilog_ls180.sh @@ -4,9 +4,10 @@ touch mem.init mem_1.init mem_2.init mem_3.init mem_4.init # Only run test in reset state as running CPU takes too much time to simulate make \ SIM=icarus \ - COCOTB_RESULTS_FILE=results_iverilog.xml \ + TOPLEVEL=ls180 \ + COCOTB_RESULTS_FILE=results_iverilog_ls180.xml \ COCOTB_HDL_TIMEUNIT=100ps \ TESTCASE="idcode_reset,idcodesvf_reset,boundary_scan_reset" \ - SIM_BUILD=sim_build_iverilog + SIM_BUILD=sim_build_iverilog_ls180 diff --git a/ls180/pre_pnr/run_iverilog_ti.sh b/ls180/pre_pnr/run_iverilog_ti.sh new file mode 100755 index 0000000..e01138a --- /dev/null +++ b/ls180/pre_pnr/run_iverilog_ti.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +touch mem.init mem_1.init mem_2.init mem_3.init mem_4.init +# Only run test in reset state as running CPU takes too much time to simulate +make \ + SIM=icarus \ + TOPLEVEL=test_issuer \ + COCOTB_RESULTS_FILE=results_iverilog_ti.xml \ + COCOTB_HDL_TIMEUNIT=100ps \ + TESTCASE="idcode_reset,idcodesvf_reset,boundary_scan_reset" \ + SIM_BUILD=sim_build_iverilog_ti + + diff --git a/ls180/pre_pnr/test.py b/ls180/pre_pnr/test.py index 8752043..25e8caf 100644 --- a/ls180/pre_pnr/test.py +++ b/ls180/pre_pnr/test.py @@ -17,34 +17,53 @@ from soc.debug.jtag import Pins # Helper functions # +class DUTWrapper: + def __init__(self, dut): + self.dut = dut + try: + ti = dut.test_issuer + except AttributeError: + ti = dut + ti._discover_all() + self.ti = ti + self.clk = ti.clk + self.rst = ti.rst + self.tck = ti.TAP_bus__tck + self.tms = ti.TAP_bus__tms + self.tdi = ti.TAP_bus__tdi + self.tdo = ti.TAP_bus__tdo + + def info(self, *args, **kwargs): + return self.dut._log.info(*args, **kwargs) + class JTAGPin: def __init__(self, pin): self.type_ = pin[2] self.name = pin[3] - def log(self, dut): + def log(self, wrap): if self.type_ == IOType.In: - core_i = getattr(dut.test_issuer, f"{self.name}__core__i").value - pad_i = getattr(dut.test_issuer, f"{self.name}__pad__i").value - dut._log.info(f"{self.name}: core.i={core_i}, pad.i={pad_i}") + core_i = getattr(wrap.ti, f"{self.name}__core__i").value + pad_i = getattr(wrap.ti, f"{self.name}__pad__i").value + wrap.info(f"{self.name}: core.i={core_i}, pad.i={pad_i}") elif self.type_ == IOType.Out: - core_o = getattr(dut.test_issuer, f"{self.name}__core__o").value - pad_o = getattr(dut.test_issuer, f"{self.name}__pad__o").value - dut._log.info(f"{self.name}: core.o={core_o}, pad.o={pad_o}") + core_o = getattr(wrap.ti, f"{self.name}__core__o").value + pad_o = getattr(wrap.ti, f"{self.name}__pad__o").value + wrap.info(f"{self.name}: core.o={core_o}, pad.o={pad_o}") elif self.type_ == IOType.TriOut: - core_o = getattr(dut.test_issuer, f"{self.name}__core__o").value - core_oe = getattr(dut.test_issuer, f"{self.name}__core__oe").value - pad_o = getattr(dut.test_issuer, f"{self.name}__pad__o").value - pad_oe = getattr(dut.test_issuer, f"{self.name}__pad__oe").value - dut._log.info(f"{self.name}: core.(o={core_o}, oe={core_oe}), pad.(o={pad_o}, oe={pad_oe})") + core_o = getattr(wrap.ti, f"{self.name}__core__o").value + core_oe = getattr(wrap.ti, f"{self.name}__core__oe").value + pad_o = getattr(wrap.ti, f"{self.name}__pad__o").value + pad_oe = getattr(wrap.ti, f"{self.name}__pad__oe").value + wrap.info(f"{self.name}: core.(o={core_o}, oe={core_oe}), pad.(o={pad_o}, oe={pad_oe})") elif self.type_ == IOType.InTriOut: - core_i = getattr(dut.test_issuer, f"{self.name}__core__i").value - core_o = getattr(dut.test_issuer, f"{self.name}__core__o").value - core_oe = getattr(dut.test_issuer, f"{self.name}__core__oe").value - pad_i = getattr(dut.test_issuer, f"{self.name}__pad__i").value - pad_o = getattr(dut.test_issuer, f"{self.name}__pad__o").value - pad_oe = getattr(dut.test_issuer, f"{self.name}__pad__oe").value - dut._log.info(f"{self.name}: core.(i={core_i}, o={core_o}, oe={core_oe}), pad.(i={core_i}, o={pad_o}, oe={pad_oe})") + core_i = getattr(wrap.ti, f"{self.name}__core__i").value + core_o = getattr(wrap.ti, f"{self.name}__core__o").value + core_oe = getattr(wrap.ti, f"{self.name}__core__oe").value + pad_i = getattr(wrap.ti, f"{self.name}__pad__i").value + pad_o = getattr(wrap.ti, f"{self.name}__pad__o").value + pad_oe = getattr(wrap.ti, f"{self.name}__pad__oe").value + wrap.info(f"{self.name}: core.(i={core_i}, o={core_o}, oe={core_oe}), pad.(i={core_i}, o={pad_o}, oe={pad_oe})") else: raise ValueError(f"Unsupported pin type {self.type_}") @@ -54,28 +73,29 @@ class JTAGPin: elif self.type_ == IOType.TriOut: return [1, val] elif self.type_ == IOType.InTriOut: - return [val, 1, val] + return [val, val, 1] else: raise ValueError(f"Unsupported pin type {self.type_}") - def check(self, dut, val): + def check(self, wrap, val): if self.type_ == IOType.In: - assert getattr(dut.test_issuer, f"{self.name}__core__i").value == val + assert getattr(wrap.ti, f"{self.name}__core__i").value == val elif self.type_ == IOType.Out: - assert getattr(dut.test_issuer, f"{self.name}__pad__o").value == val + assert getattr(wrap.ti, f"{self.name}__pad__o").value == val elif self.type_ == IOType.TriOut: - assert getattr(dut.test_issuer, f"{self.name}__core__o").value == val - assert getattr(dut.test_issuer, f"{self.name}__core__oe").value == 1 + assert getattr(wrap.ti, f"{self.name}__core__o").value == val + assert getattr(wrap.ti, f"{self.name}__core__oe").value == 1 elif self.type_ == IOType.InTriOut: - assert getattr(dut.test_issuer, f"{self.name}__core__i").value == val - assert getattr(dut.test_issuer, f"{self.name}__pad__o").value == val - assert getattr(dut.test_issuer, f"{self.name}__pad__oe").value == val + assert getattr(wrap.ti, f"{self.name}__core__i").value == val + assert getattr(wrap.ti, f"{self.name}__pad__o").value == val + assert getattr(wrap.ti, f"{self.name}__pad__oe").value == val else: raise ValueError(f"Unsupported pin type {self.type_}") -def log_pins(dut, pins): + +def log_pins(wrap, pins): for pin in pins: - pin.log(dut) + pin.log(wrap) def get_jtag_boundary(): @@ -92,79 +112,83 @@ def get_jtag_boundary(): return pins -def setup_sim(dut, *, clk_period, run): +def setup_sim(dut, *, info, clk_period, run): """Initialize CPU and setup clock""" + wrap = DUTWrapper(dut) + wrap.info(info) + clk_steps = get_sim_steps(clk_period, "ns") - cocotb.fork(Clock(dut.sys_clk, clk_steps).start()) + cocotb.fork(Clock(wrap.clk, clk_steps).start()) - dut.sys_rst <= 1 - dut.sys_clk <= 0 + wrap.rst <= 1 + wrap.clk <= 0 if run: yield Timer(int(10.5*clk_steps)) - dut.sys_rst <= 0 + wrap.rst <= 0 yield Timer(int(5*clk_steps)) -def setup_jtag(dut, *, tck_period): + return wrap + +def setup_jtag(wrap, *, tck_period): # Make this a generator if False: yield Timer(0) - return JTAG_Master(dut.jtag_tck, dut.jtag_tms, - dut.jtag_tdi, dut.jtag_tdo, + return JTAG_Master(wrap.tck, wrap.tms, wrap.tdi, wrap.tdo, clk_period=tck_period, ir_width=4) -def execute_svf(dut, *, jtag, svf_filename): +def execute_svf(wrap, *, jtag, svf_filename): yield jtag.reset() jtag_svf = SVF_Executor(jtag) with open(svf_filename, "r") as f: svf_deck = f.read() - yield jtag_svf.run(svf_deck, p=dut._log.info) + yield jtag_svf.run(svf_deck, p=wrap.info) # # IDCODE using JTAG_master # -def idcode(dut, *, jtag): +def idcode(wrap, *, jtag): yield jtag.idcode() result1 = jtag.result - dut._log.info("IDCODE1: {}".format(result1)) + wrap.info("IDCODE1: {}".format(result1)) assert(result1 == BinaryValue("00000000000000000001100011111111")) yield jtag.idcode() result2 = jtag.result - dut._log.info("IDCODE2: {}".format(result2)) + wrap.info("IDCODE2: {}".format(result2)) assert(result1 == result2) @cocotb.test() def idcode_reset(dut): - dut._log.info("Running IDCODE test; cpu in reset...") - clk_period = 100 # 10MHz tck_period = 300 # 3MHz - yield from setup_sim(dut, clk_period=clk_period, run=False) - jtag = yield from setup_jtag(dut, tck_period = tck_period) + info = "Running IDCODE test; cpu in reset..." + wrap = yield from setup_sim(dut, info=info, clk_period=clk_period, + run=False) + jtag = yield from setup_jtag(wrap, tck_period = tck_period) - yield from idcode(dut, jtag=jtag) + yield from idcode(wrap, jtag=jtag) - dut._log.info("IDCODE test completed") + wrap.info("IDCODE test completed") @cocotb.test() def idcode_run(dut): - dut._log.info("Running IDCODE test; cpu running...") - clk_period = 100 # 10MHz tck_period = 300 # 3MHz - yield from setup_sim(dut, clk_period=clk_period, run=True) - jtag = yield from setup_jtag(dut, tck_period = tck_period) + info = "Running IDCODE test; cpu running..." + wrap = yield from setup_sim(dut, info=info, clk_period=clk_period, + run=True) + jtag = yield from setup_jtag(wrap, tck_period = tck_period) - yield from idcode(dut, jtag=jtag) + yield from idcode(wrap, jtag=jtag) - dut._log.info("IDCODE test completed") + wrap.info("IDCODE test completed") # # Read IDCODE from SVF file @@ -172,87 +196,89 @@ def idcode_run(dut): @cocotb.test() def idcodesvf_reset(dut): - dut._log.info("Running IDCODE through SVF test; cpu in reset...") - clk_period = 100 # 10MHz tck_period = 300 # 3MHz - yield from setup_sim(dut, clk_period=clk_period, run=False) - jtag = yield from setup_jtag(dut, tck_period = tck_period) + info = "Running IDCODE through SVF test; cpu in reset..." + wrap = yield from setup_sim(dut, info=info, clk_period=clk_period, + run=False) + jtag = yield from setup_jtag(wrap, tck_period = tck_period) - yield from execute_svf(dut, jtag=jtag, svf_filename="idcode.svf") + yield from execute_svf(wrap, jtag=jtag, svf_filename="idcode.svf") - dut._log.info("IDCODE test completed") + wrap.info("IDCODE test completed") @cocotb.test() def idcodesvf_run(dut): - dut._log.info("Running IDCODE through SVF test; cpu running...") - clk_period = 100 # 10MHz tck_period = 300 # 3MHz - yield from setup_sim(dut, clk_period=clk_period, run=True) - jtag = yield from setup_jtag(dut, tck_period = tck_period) + info = "Running IDCODE through SVF test; cpu running..." + wrap = yield from setup_sim(dut, info=info, clk_period=clk_period, + run=True) + jtag = yield from setup_jtag(wrap, tck_period = tck_period) - yield from execute_svf(dut, jtag=jtag, svf_filename="idcode.svf") + yield from execute_svf(wrap, jtag=jtag, svf_filename="idcode.svf") - dut._log.info("IDCODE test completed") + wrap.info("IDCODE test completed") # # Boundary scan # -def boundary_scan(dut, *, jtag): +def boundary_scan(wrap, *, jtag): pins = get_jtag_boundary() yield jtag.reset() - dut._log.info("") - dut._log.info("Before scan") - log_pins(dut, pins) + wrap.info("") + wrap.info("Before scan") + log_pins(wrap, pins) yield jtag.load_ir([0, 0, 0, 0]) data = chain(*(pin.data(i%2) for i, pin in enumerate(pins))) yield jtag.shift_data(data) - dut._log.info("") - dut._log.info("After scan") - log_pins(dut, pins) + wrap.info("") + wrap.info("After scan") + log_pins(wrap, pins) +# pins[0].check(dut, 1) yield jtag.reset() - dut._log.info("") - dut._log.info("After reset") - log_pins(dut, pins) + wrap.info("") + wrap.info("After reset") + log_pins(wrap, pins) +# pins[0].check(dut, 0) @cocotb.test() def boundary_scan_reset(dut): - dut._log.info("Running boundary scan test; cpu in reset...") - clk_period = 100 # 10MHz tck_period = 300 # 3MHz - yield from setup_sim(dut, clk_period=clk_period, run=False) - jtag = yield from setup_jtag(dut, tck_period = tck_period) + info = "Running boundary scan test; cpu in reset..." + wrap = yield from setup_sim(dut, info=info, clk_period=clk_period, + run=False) + jtag = yield from setup_jtag(wrap, tck_period = tck_period) - yield from boundary_scan(dut, jtag=jtag) + yield from boundary_scan(wrap, jtag=jtag) - dut._log.info("IDCODE test completed") + wrap.info("IDCODE test completed") @cocotb.test() def boundary_scan_run(dut): - dut._log.info("Running boundary scan test; cpu running...") - clk_period = 100 # 10MHz tck_period = 300 # 3MHz - yield from setup_sim(dut, clk_period=clk_period, run=True) - jtag = yield from setup_jtag(dut, tck_period = tck_period) + info = "Running boundary scan test; cpu running..." + wrap = yield from setup_sim(dut, info=info, clk_period=clk_period, + run=True) + jtag = yield from setup_jtag(wrap, tck_period = tck_period) - yield from boundary_scan(dut, jtag=jtag) + yield from boundary_scan(wrap, jtag=jtag) - dut._log.info("IDCODE test completed") + wrap.info("IDCODE test completed") # demo / debug how to get boundary scan names. run "python3 test.py" -- 2.30.2