JTAG boundary scan test 1st attempt
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 8 Oct 2020 13:48:42 +0000 (14:48 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 8 Oct 2020 13:48:42 +0000 (14:48 +0100)
src/soc/debug/jtag.py
src/soc/debug/jtagutils.py
src/soc/debug/test/test_jtag_tap_srv.py

index 2a9507a12a7098e7b2f892b7f024bcb29b39394d..03f69768e7847224c9ffaa8d1c31b46b42c4cb0c 100644 (file)
@@ -13,11 +13,13 @@ from soc.debug.dmi2jtag import DMITAP
 # map from pinmux to c4m jtag iotypes
 iotypes = {'-': IOType.In,
            '+': IOType.Out,
+           '>': IOType.TriOut,
            '*': IOType.InTriOut,
         }
 
 scanlens = {IOType.In: 1,
            IOType.Out: 1,
+           IOType.TriOut: 2,
            IOType.InTriOut: 3,
             }
 
@@ -67,15 +69,17 @@ class JTAG(DMITAP, Pins):
         # enumerate pin specs and create IOConn Records.
         # we store the boundary scan register offset in the IOConn record
         self.ios = [] # these are enumerated in external_ports
+        self.scan_len = 0
         for fn, pin, iotype, pin_name, scan_idx in list(self):
             io = self.add_io(iotype=iotype, name=pin_name)
             io._scan_idx = scan_idx # hmm shouldn't really do this
+            self.scan_len += scan_idx # record full length of boundary scan
             self.ios.append(io)
 
         # this is redundant.  or maybe part of testing, i don't know.
         self.sr = self.add_shiftreg(ircode=4, length=3)
 
-        # create and connect wishbone 
+        # create and connect wishbone
         self.wb = self.add_wishbone(ircodes=[5, 6, 7],
                                    address_width=29, data_width=wb_data_wid,
                                    name="jtag_wb")
index f0b1830d23cfe4c4f5ae762191cc5b653e29ddd2..7f77558fea100e0842f47fb0ef233db153b514b2 100644 (file)
@@ -71,17 +71,24 @@ def jtag_set_idle(dut):
     yield from tms_state_set(dut, [1, 1, 0])
 
 
-def jtag_read_write_reg(dut, addr, d_len, d_in=0):
+def jtag_set_ir(dut, addr):
     yield from jtag_set_run(dut)
     yield from jtag_set_shift_ir(dut)
-    yield from tms_data_getset(dut, 0, dut._ir_width, addr)
+    result = yield from tms_data_getset(dut, 0, dut._ir_width, addr)
     yield from jtag_set_idle(dut)
+    return result
+
 
+def jtag_set_get_dr(dut, d_len, d_in=0):
     yield from jtag_set_shift_dr(dut)
     result = yield from tms_data_getset(dut, 0, d_len, d_in)
     yield from jtag_set_idle(dut)
     return result
 
+def jtag_read_write_reg(dut, addr, d_len, d_in=0):
+    yield from jtag_set_ir(dut, addr)
+    return (yield from jtag_set_get_dr(dut, d_len, d_in))
+
 
 def jtag_srv(dut):
     while not dut.stop:
index 597eb0a6940a3cea2d2df6b01da53ed6e56814e4..2fdeeefeb7067824df3126f3be371e71fc4adcea 100644 (file)
@@ -9,7 +9,7 @@ from c4m.nmigen.jtag.tap import TAP, IOType
 from c4m.nmigen.jtag.bus import Interface as JTAGInterface
 from soc.debug.dmi import DMIInterface, DBGCore
 from soc.debug.test.dmi_sim import dmi_sim
-from soc.debug.jtag import JTAG, dummy_pinset
+from soc.debug.jtag import JTAG
 from soc.debug.test.jtagremote import JTAGServer, JTAGClient
 
 from nmigen_soc.wishbone.sram import SRAM
@@ -18,7 +18,15 @@ from nmigen import Memory, Signal, Module
 from nmigen.back.pysim import Simulator, Delay, Settle, Tick
 from nmutil.util import wrap
 from soc.debug.jtagutils import (jtag_read_write_reg,
-                                 jtag_srv, jtag_set_reset)
+                                 jtag_srv, jtag_set_reset,
+                                 jtag_set_ir, jtag_set_get_dr)
+
+def test_pinset():
+    return {
+            # in, out, tri-out, tri-inout
+            'test': ['io0-', 'io1+', 'io2>', 'io3*'],
+           }
+
 
 # JTAG-ircodes for accessing DMI
 DMI_ADDR = 8
@@ -30,6 +38,12 @@ WB_ADDR = 5
 WB_READ = 6
 WB_WRRD = 7
 
+# JTAG boundary scan reg addresses
+BS_EXTEST = 0
+BS_INTEST = 0
+BS_SAMPLE = 2
+BS_PRELOAD = 2
+
 
 def jtag_sim(dut, srv_dut):
 
@@ -41,6 +55,77 @@ def jtag_sim(dut, srv_dut):
     print ("idcode", hex(idcode))
     assert idcode == 0x18ff
 
+    ####### JTAG Boundary scan ######
+
+    bslen = dut.scan_len
+    print ("scan len", bslen)
+
+    # sample test
+    bs_actual = 0b100110
+    yield srv_dut.ios[0].pad.i.eq(1)
+    yield srv_dut.ios[1].core.o.eq(0)
+    yield srv_dut.ios[2].core.o.eq(1)
+    yield srv_dut.ios[2].core.oe.eq(1)
+    yield srv_dut.ios[3].pad.i.eq(0)
+    yield srv_dut.ios[3].core.o.eq(0)
+    yield srv_dut.ios[3].core.oe.eq(1)
+
+    bs = yield from jtag_read_write_reg(dut, BS_SAMPLE, bslen, bs_actual)
+    print ("bs scan", bin(bs))
+
+    print ("io0 pad.i", (yield srv_dut.ios[0].pad.i))
+    print ("io1 core.o", (yield srv_dut.ios[1].core.o))
+    print ("io2 core.o", (yield srv_dut.ios[2].core.o))
+    print ("io2 core.oe", (yield srv_dut.ios[2].core.oe))
+    print ("io3 core.i", (yield srv_dut.ios[3].core.i))
+    print ("io3 pad.o", (yield srv_dut.ios[3].pad.o))
+    print ("io3 pad.oe", (yield srv_dut.ios[3].pad.oe))
+
+    # extest
+    ir_actual = yield from jtag_set_ir(dut, BS_EXTEST)
+    print ("ir extest", bin(ir_actual))
+
+    print ("io0 pad.i", (yield srv_dut.ios[0].pad.i))
+    print ("io1 core.o", (yield srv_dut.ios[1].core.o))
+    print ("io2 core.o", (yield srv_dut.ios[2].core.o))
+    print ("io2 core.oe", (yield srv_dut.ios[2].core.oe))
+    print ("io3 core.i", (yield srv_dut.ios[3].core.i))
+    print ("io3 pad.o", (yield srv_dut.ios[3].pad.o))
+    print ("io3 pad.oe", (yield srv_dut.ios[3].pad.oe))
+
+    # set pins
+    bs_actual = 0b1011001
+    yield srv_dut.ios[0].pad.i.eq(0)
+    yield srv_dut.ios[1].core.o.eq(1)
+    yield srv_dut.ios[2].core.o.eq(0)
+    yield srv_dut.ios[2].core.oe.eq(0)
+    yield srv_dut.ios[3].pad.i.eq(1)
+    yield srv_dut.ios[3].core.o.eq(1)
+    yield srv_dut.ios[3].core.oe.eq(0)
+
+    bs = yield from jtag_set_get_dr(dut, bslen, bs_actual)
+    print ("bs scan", bin(bs))
+
+    print ("io0 pad.i", (yield srv_dut.ios[0].pad.i))
+    print ("io1 core.o", (yield srv_dut.ios[1].core.o))
+    print ("io2 core.o", (yield srv_dut.ios[2].core.o))
+    print ("io2 core.oe", (yield srv_dut.ios[2].core.oe))
+    print ("io3 core.i", (yield srv_dut.ios[3].core.i))
+    print ("io3 pad.o", (yield srv_dut.ios[3].pad.o))
+    print ("io3 pad.oe", (yield srv_dut.ios[3].pad.oe))
+
+    # reset
+    yield from jtag_set_reset(dut)
+    print ("bs reset")
+
+    print ("io0 pad.i", (yield srv_dut.ios[0].pad.i))
+    print ("io1 core.o", (yield srv_dut.ios[1].core.o))
+    print ("io2 core.o", (yield srv_dut.ios[2].core.o))
+    print ("io2 core.oe", (yield srv_dut.ios[2].core.oe))
+    print ("io3 core.i", (yield srv_dut.ios[3].core.i))
+    print ("io3 pad.o", (yield srv_dut.ios[3].pad.o))
+    print ("io3 pad.oe", (yield srv_dut.ios[3].pad.oe))
+
     ####### JTAG to DMI ######
 
     # write DMI address
@@ -98,7 +183,7 @@ def jtag_sim(dut, srv_dut):
 
 
 if __name__ == '__main__':
-    dut = JTAG(dummy_pinset(), wb_data_wid=64)
+    dut = JTAG(test_pinset(), wb_data_wid=64)
     dut.stop = False
 
     # rather than the client access the JTAG bus directly
@@ -106,7 +191,6 @@ if __name__ == '__main__':
     class Dummy: pass
     cdut = Dummy()
     cdut.cbus = JTAGInterface()
-    cdut._ir_width = 4
 
     # set up client-server on port 44843-something
     dut.s = JTAGServer()
@@ -116,6 +200,10 @@ if __name__ == '__main__':
     else:
         dut.s.get_connection(None) # block waiting for connection
 
+    # take copy of ir_width and scan_len
+    cdut._ir_width = dut._ir_width
+    cdut.scan_len = dut.scan_len
+
     memory = Memory(width=64, depth=16)
     sram = SRAM(memory=memory, bus=dut.wb)