From: Staf Verhaegen Date: Fri, 2 Apr 2021 16:16:23 +0000 (+0200) Subject: First version of boundary scan test bench. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dfb88f18a6a925c2d70ccc9f80136490223ddef3;p=soc-cocotb-sim.git First version of boundary scan test bench. Only for pre_pnr at the moment. --- diff --git a/ls180/pre_pnr/run_iverilog.sh b/ls180/pre_pnr/run_iverilog.sh index 147dc60..2866883 100755 --- a/ls180/pre_pnr/run_iverilog.sh +++ b/ls180/pre_pnr/run_iverilog.sh @@ -6,7 +6,7 @@ make \ SIM=icarus \ COCOTB_RESULTS_FILE=results_iverilog.xml \ COCOTB_HDL_TIMEUNIT=100ps \ - TESTCASE="idcode_reset,idcodesvf_reset" \ + TESTCASE="idcode_reset,idcodesvf_reset,boundary_scan_reset" \ SIM_BUILD=sim_build_iverilog diff --git a/ls180/pre_pnr/test.py b/ls180/pre_pnr/test.py index 462fc49..f61bce6 100644 --- a/ls180/pre_pnr/test.py +++ b/ls180/pre_pnr/test.py @@ -1,9 +1,12 @@ +from itertools import product + import cocotb from cocotb.clock import Clock from cocotb.triggers import Timer from cocotb.utils import get_sim_steps from cocotb.binary import BinaryValue +from c4m.nmigen.jtag.tap import IOType from c4m.cocotb.jtag.c4m_jtag import JTAG_Master from c4m.cocotb.jtag.c4m_jtag_svfcocotb import SVF_Executor @@ -27,6 +30,53 @@ def get_jtag_boundary(): pins = Pins(get_pinspecs(subset=subset)) return pins +def log_pin(dut, pin): + _, _, type_, name, _ = pin + if type_ == IOType.In: + core_i = getattr(dut.test_issuer, f"{name}__core__i").value + pad_i = getattr(dut.test_issuer, f"{name}__pad__i").value + dut._log.info(f"{name}: core.i={core_i}, pad.i={pad_i}") + elif type_ == IOType.Out: + core_o = getattr(dut.test_issuer, f"{name}__core__o").value + pad_o = getattr(dut.test_issuer, f"{name}__pad__o").value + dut._log.info(f"{name}: core.o={core_o}, pad.o={pad_o}") + elif type_ == IOType.TriOut: + core_o = getattr(dut.test_issuer, f"{name}__core__o").value + core_oe = getattr(dut.test_issuer, f"{name}__core__oe").value + pad_o = getattr(dut.test_issuer, f"{name}__pad__o").value + pad_oe = getattr(dut.test_issuer, f"{name}__pad__oe").value + dut._log.info(f"{name}: core.(o={core_o}, oe={core_oe}), pad.(o={pad_o}, oe={pad_oe})") + elif type_ == IOType.InTriOut: + core_i = getattr(dut.test_issuer, f"{name}__core__i").value + core_o = getattr(dut.test_issuer, f"{name}__core__o").value + core_oe = getattr(dut.test_issuer, f"{name}__core__oe").value + pad_i = getattr(dut.test_issuer, f"{name}__pad__i").value + pad_o = getattr(dut.test_issuer, f"{name}__pad__o").value + pad_oe = getattr(dut.test_issuer, f"{name}__pad__oe").value + dut._log.info(f"{name}: core.(i={core_i}, o={core_o}, oe={core_oe}), pad.(t={core_i}, o={pad_o}, oe={pad_oe})") + else: + raise ValueError(f"Unsupported pin type {type_}") + +def log_pins(dut, pins): + for pin in get_jtag_boundary(): + log_pin(dut, pin) + +def check_pin(dut, pin, val): + _, _, type_, name, _ = pin + if type_ == IOType.In: + assert getattr(dut.test_issuer, f"{name}__core__i").value == val + elif type_ == IOType.Out: + assert getattr(dut.test_issuer, f"{name}__pad__o").value == val + elif type_ == IOType.TriOut: + assert getattr(dut.test_issuer, f"{name}__core__o").value == val + assert getattr(dut.test_issuer, f"{name}__core__oe").value == 1 + elif type_ == IOType.InTriOut: + assert getattr(dut.test_issuer, f"{name}__core__i").value == val + assert getattr(dut.test_issuer, f"{name}__pad__o").value == val + assert getattr(dut.test_issuer, f"{name}__pad__oe").value == val + else: + raise ValueError(f"Unsupported pin type {type_}") + def setup_sim(dut, *, clk_period, run): """Initialize CPU and setup clock""" @@ -134,6 +184,60 @@ def idcodesvf_run(dut): dut._log.info("IDCODE test completed") +# +# Boundary scan +# + +def boundary_scan(dut, *, jtag): + pins = tuple(get_jtag_boundary()) + + yield jtag.reset() + + dut._log.info("Before scan") + log_pins(dut, pins) + + yield jtag.load_ir([0, 0, 0, 0]) + yield jtag.shift_data([1]) + + dut._log.info("After scan") + log_pins(dut, pins) + check_pin(dut, pins[0], 1) + + yield jtag.reset() + + dut._log.info("After reset") + log_pins(dut, pins) + check_pin(dut, pins[0], 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) + + yield from boundary_scan(dut, jtag=jtag) + + dut._log.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) + + yield from boundary_scan(dut, jtag=jtag) + + dut._log.info("IDCODE test completed") + # demo / debug how to get boundary scan names. run "python3 test.py" if __name__ == '__main__':