e8d31bae2ff1426619dabb61e3b055ecd9146cd1
[soc.git] / src / soc / debug / test / test_jtag_tap_srv.py
1 """DMI 2 JTAG test
2
3 based on Staf Verhaegen (Chips4Makers) wishbone TAP
4 """
5
6 import sys
7 from nmigen import (Module, Signal, Elaboratable, Const)
8 from c4m.nmigen.jtag.tap import TAP, IOType
9 from c4m.nmigen.jtag.bus import Interface as JTAGInterface
10 from soc.debug.dmi import DMIInterface, DBGCore
11 from soc.debug.test.dmi_sim import dmi_sim
12 from soc.debug.dmi2jtag import DMITAP
13 from soc.debug.test.jtagremote import JTAGServer, JTAGClient
14
15 from nmigen_soc.wishbone.sram import SRAM
16 from nmigen import Memory, Signal, Module
17
18 from nmigen.back.pysim import Simulator, Delay, Settle, Tick
19 from nmutil.util import wrap
20
21 def client_sync(dut):
22 tck = yield dut.cbus.tck
23 tms = yield dut.cbus.tms
24 tdi = yield dut.cbus.tdi
25 dut.c.jtagremote_client_send((tck, tms, tdi))
26 #print ("about to client recv")
27 while True:
28 tdo = dut.c.jtagremote_client_recv(timeout=0)
29 if tdo is not None:
30 break
31 yield
32 yield dut.cbus.tdo.eq(tdo)
33
34
35 def tms_state_set(dut, bits):
36 for bit in bits:
37 yield dut.cbus.tck.eq(1)
38 yield dut.cbus.tms.eq(bit)
39 yield from client_sync(dut)
40 yield
41 yield dut.cbus.tck.eq(0)
42 yield from client_sync(dut)
43 yield
44 yield from client_sync(dut)
45 yield dut.cbus.tms.eq(0)
46 yield from client_sync(dut)
47
48
49 def tms_data_getset(dut, tms, d_len, d_in=0):
50 res = 0
51 yield dut.cbus.tms.eq(tms)
52 for i in range(d_len):
53 tdi = 1 if (d_in & (1<<i)) else 0
54 yield dut.cbus.tck.eq(1)
55 yield from client_sync(dut)
56 res |= (1<<i) if (yield dut.bus.tdo) else 0
57 yield
58 yield from client_sync(dut)
59 yield dut.cbus.tdi.eq(tdi)
60 yield dut.cbus.tck.eq(0)
61 yield from client_sync(dut)
62 yield
63 yield from client_sync(dut)
64 yield dut.cbus.tms.eq(0)
65 yield from client_sync(dut)
66
67 return res
68
69
70 def jtag_set_reset(dut):
71 yield from tms_state_set(dut, [1, 1, 1, 1, 1])
72
73 def jtag_set_shift_dr(dut):
74 yield from tms_state_set(dut, [1, 0, 0])
75
76 def jtag_set_shift_ir(dut):
77 yield from tms_state_set(dut, [1, 1, 0])
78
79 def jtag_set_run(dut):
80 yield from tms_state_set(dut, [0])
81
82 def jtag_set_idle(dut):
83 yield from tms_state_set(dut, [1, 1, 0])
84
85
86 def jtag_read_write_reg(dut, addr, d_len, d_in=0):
87 yield from jtag_set_run(dut)
88 yield from jtag_set_shift_ir(dut)
89 yield from tms_data_getset(dut, 0, dut._ir_width, addr)
90 yield from jtag_set_idle(dut)
91
92 yield from jtag_set_shift_dr(dut)
93 result = yield from tms_data_getset(dut, 0, d_len, d_in)
94 yield from jtag_set_idle(dut)
95 return result
96
97
98 # JTAG-ircodes for accessing DMI
99 DMI_ADDR = 5
100 DMI_READ = 6
101 DMI_WRRD = 7
102
103 # JTAG-ircodes for accessing Wishbone
104 WB_ADDR = 8
105 WB_READ = 9
106 WB_WRRD = 10
107
108
109 def jtag_srv(dut):
110 while not dut.stop:
111 # loop and receive data from client
112 tdo = yield dut.bus.tdo
113 #print ("server tdo data", tdo)
114 data = dut.s.jtagremote_server_recv(tdo)
115 #print ("server recv data", data)
116 if not data:
117 yield
118 continue
119 tck, tms, tdi = data
120 yield dut.bus.tck.eq(tck)
121 yield dut.bus.tms.eq(tms)
122 yield dut.bus.tdi.eq(tdi)
123 yield
124
125
126 def jtag_sim(dut):
127
128 ####### JTAGy stuff (IDCODE) ######
129
130 # read idcode
131 yield from jtag_set_reset(dut)
132 idcode = yield from jtag_read_write_reg(dut, 0b1, 32)
133 print ("idcode", hex(idcode))
134 assert idcode == 0x18ff
135
136 ####### JTAG to DMI ######
137
138 # write DMI address
139 yield from jtag_read_write_reg(dut, DMI_ADDR, 8, DBGCore.CTRL)
140
141 # read DMI CTRL register
142 status = yield from jtag_read_write_reg(dut, DMI_READ, 64)
143 print ("dmi ctrl status", hex(status))
144 assert status == 4
145
146 # write DMI address
147 yield from jtag_read_write_reg(dut, DMI_ADDR, 8, 0)
148
149 # write DMI CTRL register
150 status = yield from jtag_read_write_reg(dut, DMI_WRRD, 64, 0b101)
151 print ("dmi ctrl status", hex(status))
152 assert status == 4 # returned old value (nice! cool feature!)
153
154 # write DMI address
155 yield from jtag_read_write_reg(dut, DMI_ADDR, 8, DBGCore.CTRL)
156
157 # read DMI CTRL register
158 status = yield from jtag_read_write_reg(dut, DMI_READ, 64)
159 print ("dmi ctrl status", hex(status))
160 assert status == 5
161
162 # write DMI MSR address
163 yield from jtag_read_write_reg(dut, DMI_ADDR, 8, DBGCore.MSR)
164
165 # read DMI MSR register
166 msr = yield from jtag_read_write_reg(dut, DMI_READ, 64)
167 print ("dmi msr", hex(msr))
168 assert msr == 0xdeadbeef
169
170 ####### JTAG to Wishbone ######
171
172 # write Wishbone address
173 yield from jtag_read_write_reg(dut, WB_ADDR, 16, 0x18)
174
175 # write/read wishbone data
176 data = yield from jtag_read_write_reg(dut, WB_WRRD, 16, 0xfeef)
177 print ("wb write", hex(data))
178
179 # write Wishbone address
180 yield from jtag_read_write_reg(dut, WB_ADDR, 16, 0x18)
181
182 # write/read wishbone data
183 data = yield from jtag_read_write_reg(dut, WB_READ, 16, 0)
184 print ("wb read", hex(data))
185
186 ####### done - tell dmi_sim to stop (otherwise it won't) ########
187
188 dut.stop = True
189
190
191 if __name__ == '__main__':
192 dut = DMITAP(ir_width=4)
193 dut.stop = False
194
195 # set up client-server on port 44843-something
196 dut.s = JTAGServer()
197 if len(sys.argv) != 2 and sys.argv[1] != 'server':
198 dut.c = JTAGClient()
199 dut.s.get_connection()
200 else:
201 dut.s.get_connection(None) # block waiting for connection
202
203 # rather than the client access the JTAG bus directly
204 # create an alternative that the client sets
205 dut.cbus = JTAGInterface()
206
207 iotypes = (IOType.In, IOType.Out, IOType.TriOut, IOType.InTriOut)
208 ios = [dut.add_io(iotype=iotype) for iotype in iotypes]
209 dut.sr = dut.add_shiftreg(ircode=4, length=3) # test loopback register
210
211 # create and connect wishbone SRAM (a quick way to do WB test)
212 dut.wb = dut.add_wishbone(ircodes=[WB_ADDR, WB_READ, WB_WRRD],
213 address_width=16, data_width=16)
214 memory = Memory(width=16, depth=16)
215 sram = SRAM(memory=memory, bus=dut.wb)
216
217 # create DMI2JTAG (goes through to dmi_sim())
218 dut.dmi = dut.add_dmi(ircodes=[DMI_ADDR, DMI_READ, DMI_WRRD])
219
220 m = Module()
221 m.submodules.ast = dut
222 m.submodules.sram = sram
223 m.d.comb += dut.sr.i.eq(dut.sr.o) # loopback
224
225 sim = Simulator(m)
226 sim.add_clock(1e-6, domain="sync") # standard clock
227
228 sim.add_sync_process(wrap(jtag_srv(dut))) # jtag server
229 if len(sys.argv) != 2 and sys.argv[1] != 'server':
230 sim.add_sync_process(wrap(jtag_sim(dut))) # actual jtag tester
231 else:
232 print ("running server only as requested, use openocd remote to test")
233 sim.add_sync_process(wrap(dmi_sim(dut))) # handles (pretends to be) DMI
234
235 with sim.write_vcd("dmi2jtag_test_srv.vcd"):
236 sim.run()