+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
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"""
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__':