--- /dev/null
+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.cocotb.jtag.c4m_jtag import JTAG_Master
+from c4m.cocotb.jtag.c4m_jtag_svfcocotb import SVF_Executor
+
+from itertools import chain
+
+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
+
+from itertools import chain
+
+from c4m.nmigen.jtag.tap import IOType
+
+#
+# Helper functions
+#
+
+class DUTWrapper:
+ def __init__(self, dut):
+ self.dut = dut
+ ti = dut.instance_corona.core.subckt_22_jtag
+ ti._discover_all()
+ self.ti = ti
+ self.sys_clk = dut.sys_clk
+ self.sys_rst = dut.sys_rst
+ self.jtag_tck = dut.jtag_tck
+ self.jtag_tms = dut.jtag_tms
+ self.jtag_tdi = dut.jtag_tdi
+ self.jtag_tdo = dut.jtag_tdo
+ self.vdd = dut.vdd
+ self.vss = dut.vss
+ self.iovdd = dut.iovdd
+ self.iovss = dut.iovss
+
+ def info(self, *args, **kwargs):
+ return self.dut._log.info(*args, **kwargs)
+
+
+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(wrap.sys_clk, clk_steps).start())
+
+ wrap.vdd <= 1
+ wrap.vss <= 0
+ wrap.iovdd <= 1
+ wrap.iovss <= 0
+ wrap.sys_rst <= 1
+ wrap.sys_clk <= 0
+ # adder test (ignore this)
+ dut.a <= 3
+ dut.b <= 2
+
+ if run:
+ yield Timer(int(10.5*clk_steps))
+ wrap.sys_rst <= 0
+ yield Timer(int(5*clk_steps))
+
+ return wrap
+
+def setup_jtag(dut, *, tck_period):
+ # Make this a generator
+ if False:
+ yield Timer(0)
+ clk_steps = get_sim_steps(tck_period, "ns")
+ return JTAG_Master(dut.jtag_tck, dut.jtag_tms,
+ dut.jtag_tdi, dut.jtag_tdo,
+ clk_period=clk_steps,
+ ir_width=4)
+
+
+# demo / debug how to get boundary scan names. run "python3 test.py"
+if __name__ == '__main__':
+ pinouts = get_jtag_boundary()
+ for pin in pinouts:
+ # example: ('eint', '2', <IOType.In: 1>, 'eint_2', 125)
+ print (pin)
+
+
+#
+# Helper functions
+#
+
+class JTAGPin:
+ def __init__(self, pin):
+ self.pin = pin
+ self.type_ = pin[2]
+ self.name = pin[3]
+
+ def __repr__(self):
+ return str(self.pin)
+
+ def log(self, wrap):
+ if self.type_ == IOType.In:
+ 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(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(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(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_}")
+
+ def data(self, *, i=None, o=None, oe=None):
+ if self.type_ == IOType.In:
+ assert i is not None
+ return [i]
+ elif self.type_ == IOType.Out:
+ assert o is not None
+ return [o]
+ elif self.type_ == IOType.TriOut:
+ assert (o is not None) and (oe is not None)
+ return [o, oe]
+ elif self.type_ == IOType.InTriOut:
+ assert (i is not None) and(o is not None) and (oe is not None)
+ return [i, o, oe]
+ else:
+ raise ValueError(f"Unsupported pin type {self.type_}")
+
+ def check(self, *, wrap, i=None, o=None, oe=None):
+ if self.type_ in (IOType.In, IOType.InTriOut):
+ sig = f"{self.name}_core_i"
+ val = getattr(wrap.ti, sig).value
+ if val != i:
+ raise ValueError(f"'{sig}' should be {i}, not {val}")
+ if self.type_ in (IOType.Out, IOType.TriOut, IOType.InTriOut):
+ sig = f"{self.name}_pad_o"
+ val = getattr(wrap.ti, sig).value
+ if val != o:
+ raise ValueError(f"'{sig}' should be {o}, not {val}")
+ if self.type_ in (IOType.TriOut, IOType.InTriOut):
+ sig = f"{self.name}_pad_oe"
+ val = getattr(wrap.ti, sig).value
+ if val != oe:
+ raise ValueError(f"'{sig}' should be {oe}, not {val}")
+
+
+def log_pins(wrap, pins):
+ for pin in pins:
+ pin.log(wrap)
+
+
+def get_jtag_boundary():
+ """gets the list of information for jtag boundary scan
+ """
+ pins = []
+ for pname in ["a_0", "a_1", "a_2", "a_3",
+ "b_0", "b_1", "b_2", "b_3",
+ "f_0", "f_1", "f_2", "f_3"]:
+ if pname.startswith('f'):
+ ptype = IOType.Out
+ else:
+ ptype = IOType.In
+ pin = (None, None, ptype, pname)
+ pins.append(JTAGPin(pin))
+ return pins
+
+
+#
+# Boundary scan
+#
+
+def boundary_scan(wrap, *, jtag):
+ pins = get_jtag_boundary()
+
+ yield jtag.reset()
+
+ wrap.info("")
+ wrap.info("Before scan")
+ log_pins(wrap, pins)
+
+ yield jtag.load_ir([0, 0, 0, 0])
+ pinsdata = tuple(pin.data(i=i%2, o=((i%3)%2), oe=((i%5)%2))
+ for i, pin in enumerate(pins))
+ yield jtag.shift_data(chain(*pinsdata))
+
+ wrap.info("")
+ wrap.info("After scan")
+ log_pins(wrap, pins)
+ for i, pin in enumerate(pins):
+ pin.check(wrap=wrap, i=i%2, o=((i%3)%2), oe=((i%5)%2))
+
+ yield jtag.reset()
+
+ wrap.info("")
+ wrap.info("After reset")
+ log_pins(wrap, pins)
+
+
+@cocotb.test()
+def boundary_scan_reset(dut):
+ clk_period = 100 # 10MHz
+ tck_period = 300 # 3MHz
+
+ 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(wrap, jtag=jtag)
+
+ wrap.info("IDCODE test completed")
+
+