create client-server version of jtag debug unit test
[soc.git] / src / soc / debug / jtag.py
1 """JTAG interface
2
3 using Staf Verhaegen (Chips4Makers) wishbone TAP
4 """
5
6 from nmigen import (Module, Signal, Elaboratable)
7 from nmigen.cli import rtlil
8 from c4m.nmigen.jtag.tap import IOType
9 from soc.debug.dmi import DMIInterface, DBGCore
10 from soc.debug.dmi2jtag import DMITAP
11
12 # map from pinmux to c4m jtag iotypes
13 iotypes = {'-': IOType.In,
14 '+': IOType.Out,
15 '*': IOType.InTriOut}
16
17
18 # TODO: move to suitable location
19 class Pins:
20 """declare a list of pins, including name and direction. grouped by fn
21 """
22 def __init__(self):
23 # sigh this needs to come from pinmux.
24 gpios = []
25 for i in range(16):
26 gpios.append("gpio%d*" % i)
27 self.io_names = {'serial': ['tx+', 'rx-'], 'gpio': gpios}
28
29 def __iter__(self):
30 # start parsing io_names and enumerate them to return pin specs
31 for fn, pins in self.io_names.items():
32 for pin in pins:
33 # decode the pin name and determine the c4m jtag io type
34 name, pin_type = pin[:-1], pin[-1]
35 iotype = iotypes[pin_type]
36 pin_name = "%s_%s" % (fn, name)
37 yield (fn, name, iotype, pin_name)
38
39
40 class JTAG(DMITAP, Pins):
41 def __init__(self):
42 DMITAP.__init__(self, ir_width=4)
43 Pins.__init__(self)
44
45 # enumerate pin specs and create IOConn Records.
46 self.ios = [] # these are enumerated in external_ports
47 for fn, pin, iotype, pin_name in list(self):
48 self.ios.append(self.add_io(iotype=iotype, name=pin_name))
49
50 # this is redundant. or maybe part of testing, i don't know.
51 self.sr = self.add_shiftreg(ircode=4, length=3)
52
53 # create and connect wishbone
54 self.wb = self.add_wishbone(ircodes=[5, 6, 7],
55 address_width=29, data_width=64,
56 name="jtag_wb")
57
58 # create DMI2JTAG (goes through to dmi_sim())
59 self.dmi = self.add_dmi(ircodes=[8, 9, 10])
60
61 def elaborate(self, platform):
62 m = super().elaborate(platform)
63 m.d.comb += self.sr.i.eq(self.sr.o) # loopback as part of test?
64 return m
65
66 def external_ports(self):
67 """create a list of ports that goes into the top level il (or verilog)
68 """
69 ports = super().external_ports() # gets JTAG signal names
70 ports += list(self.wb.fields.values()) # wishbone signals
71 for io in self.ios:
72 ports += list(io.core.fields.values()) # io "core" signals
73 ports += list(io.pad.fields.values()) # io "pad" signals"
74 return ports
75
76
77 if __name__ == '__main__':
78 dut = JTAG()
79
80 vl = rtlil.convert(dut)
81 with open("test_jtag.il", "w") as f:
82 f.write(vl)
83