First version of boundary scan test bench.
authorStaf Verhaegen <staf@stafverhaegen.be>
Fri, 2 Apr 2021 16:16:23 +0000 (18:16 +0200)
committerStaf Verhaegen <staf@stafverhaegen.be>
Fri, 2 Apr 2021 16:16:23 +0000 (18:16 +0200)
Only for pre_pnr at the moment.

ls180/pre_pnr/run_iverilog.sh
ls180/pre_pnr/test.py

index 147dc60799321e478b7009caed79edb45be268f7..2866883a1d22ecddaaf29cf43445978a7036b034 100755 (executable)
@@ -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
 
 
index 462fc4928e9b21f0c3cee552be9d76a5f054df3a..f61bce686c5fbbe3d268e223615688983821dc6c 100644 (file)
@@ -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__':