cc3ab4e3cfdb1da0c12d28b4ad57ba229b38704b
[soc-cocotb-sim.git] / ls180 / pre_pnr / test.py
1 from itertools import chain
2
3 import cocotb
4 from cocotb.clock import Clock
5 from cocotb.triggers import Timer
6 from cocotb.utils import get_sim_steps
7 from cocotb.binary import BinaryValue
8
9 from c4m.nmigen.jtag.tap import IOType
10 from c4m.cocotb.jtag.c4m_jtag import JTAG_Master
11 from c4m.cocotb.jtag.c4m_jtag_svfcocotb import SVF_Executor
12
13 from soc.config.pinouts import get_pinspecs
14 from soc.debug.jtag import Pins
15
16 #
17 # Helper functions
18 #
19
20 class DUTWrapper:
21 def __init__(self, dut):
22 self.dut = dut
23 try:
24 ti = dut.test_issuer
25 except AttributeError:
26 ti = dut
27 ti._discover_all()
28 self.ti = ti
29 self.clk = ti.clk
30 self.rst = ti.rst
31 self.tck = ti.TAP_bus__tck
32 self.tms = ti.TAP_bus__tms
33 self.tdi = ti.TAP_bus__tdi
34 self.tdo = ti.TAP_bus__tdo
35
36 def info(self, *args, **kwargs):
37 return self.dut._log.info(*args, **kwargs)
38
39 class JTAGPin:
40 def __init__(self, pin):
41 self.type_ = pin[2]
42 self.name = pin[3]
43
44 def log(self, wrap):
45 if self.type_ == IOType.In:
46 core_i = getattr(wrap.ti, f"{self.name}__core__i").value
47 pad_i = getattr(wrap.ti, f"{self.name}__pad__i").value
48 wrap.info(f"{self.name}: core.i={core_i}, pad.i={pad_i}")
49 elif self.type_ == IOType.Out:
50 core_o = getattr(wrap.ti, f"{self.name}__core__o").value
51 pad_o = getattr(wrap.ti, f"{self.name}__pad__o").value
52 wrap.info(f"{self.name}: core.o={core_o}, pad.o={pad_o}")
53 elif self.type_ == IOType.TriOut:
54 core_o = getattr(wrap.ti, f"{self.name}__core__o").value
55 core_oe = getattr(wrap.ti, f"{self.name}__core__oe").value
56 pad_o = getattr(wrap.ti, f"{self.name}__pad__o").value
57 pad_oe = getattr(wrap.ti, f"{self.name}__pad__oe").value
58 wrap.info(f"{self.name}: core.(o={core_o}, oe={core_oe}), " \
59 "pad.(o={pad_o}, oe={pad_oe})")
60 elif self.type_ == IOType.InTriOut:
61 core_i = getattr(wrap.ti, f"{self.name}__core__i").value
62 core_o = getattr(wrap.ti, f"{self.name}__core__o").value
63 core_oe = getattr(wrap.ti, f"{self.name}__core__oe").value
64 pad_i = getattr(wrap.ti, f"{self.name}__pad__i").value
65 pad_o = getattr(wrap.ti, f"{self.name}__pad__o").value
66 pad_oe = getattr(wrap.ti, f"{self.name}__pad__oe").value
67 wrap.info(f"{self.name}: core.(i={core_i}, o={core_o}, " \
68 "oe={core_oe}), pad.(i={core_i}, o={pad_o}, " \
69 "oe={pad_oe})")
70 else:
71 raise ValueError(f"Unsupported pin type {self.type_}")
72
73 def data(self, *, i=None, o=None, oe=None):
74 if self.type_ == IOType.In:
75 assert i is not None
76 return [i]
77 elif self.type_ == IOType.Out:
78 assert o is not None
79 return [o]
80 elif self.type_ == IOType.TriOut:
81 assert (o is not None) and (oe is not None)
82 return [o, oe]
83 elif self.type_ == IOType.InTriOut:
84 assert (i is not None) and(o is not None) and (oe is not None)
85 return [i, o, oe]
86 else:
87 raise ValueError(f"Unsupported pin type {self.type_}")
88
89 def check(self, *, wrap, i=None, o=None, oe=None):
90 if self.type_ in (IOType.In, IOType.InTriOut):
91 sig = f"{self.name}__core__i"
92 val = getattr(wrap.ti, sig).value
93 if val != i:
94 raise ValueError(f"'{sig}' should be {i}, not {val}")
95 if self.type_ in (IOType.Out, IOType.TriOut, IOType.InTriOut):
96 sig = f"{self.name}__pad__o"
97 val = getattr(wrap.ti, sig).value
98 if val != o:
99 raise ValueError(f"'{sig}' should be {o}, not {val}")
100 if self.type_ in (IOType.TriOut, IOType.InTriOut):
101 sig = f"{self.name}__pad__oe"
102 val = getattr(wrap.ti, sig).value
103 if val != oe:
104 raise ValueError(f"'{sig}' should be {oe}, not {val}")
105
106
107 def log_pins(wrap, pins):
108 for pin in pins:
109 pin.log(wrap)
110
111
112 def get_jtag_boundary():
113 """gets the list of information for jtag boundary scan
114 """
115 # currently only a subset of pins is enabled. nuisance
116 subset = ['uart',
117 'mtwi',
118 'eint', 'gpio', 'mspi0',
119 # 'mspi1', - disabled for now
120 # 'pwm', 'sd0', - disabled for now
121 'sdr']
122 pins = tuple(JTAGPin(pin) for pin in Pins(get_pinspecs(subset=subset)))
123 return pins
124
125
126 def setup_sim(dut, *, info, clk_period, run):
127 """Initialize CPU and setup clock"""
128
129 wrap = DUTWrapper(dut)
130 wrap.info(info)
131
132 clk_steps = get_sim_steps(clk_period, "ns")
133 cocotb.fork(Clock(wrap.clk, clk_steps).start())
134
135 wrap.rst <= 1
136 wrap.clk <= 0
137 if run:
138 yield Timer(int(10.5*clk_steps))
139 wrap.rst <= 0
140 yield Timer(int(5*clk_steps))
141
142 return wrap
143
144 def setup_jtag(wrap, *, tck_period):
145 # Make this a generator
146 if False:
147 yield Timer(0)
148 return JTAG_Master(wrap.tck, wrap.tms, wrap.tdi, wrap.tdo,
149 clk_period=tck_period,
150 ir_width=4)
151
152 def execute_svf(wrap, *, jtag, svf_filename):
153 yield jtag.reset()
154
155 jtag_svf = SVF_Executor(jtag)
156 with open(svf_filename, "r") as f:
157 svf_deck = f.read()
158 yield jtag_svf.run(svf_deck, p=wrap.info)
159
160 #
161 # IDCODE using JTAG_master
162 #
163
164 def idcode(wrap, *, jtag):
165 yield jtag.idcode()
166 result1 = jtag.result
167 wrap.info("IDCODE1: {}".format(result1))
168 assert(result1 == BinaryValue("00000000000000000001100011111111"))
169
170 yield jtag.idcode()
171 result2 = jtag.result
172 wrap.info("IDCODE2: {}".format(result2))
173
174 assert(result1 == result2)
175
176 @cocotb.test()
177 def idcode_reset(dut):
178 clk_period = 100 # 10MHz
179 tck_period = 300 # 3MHz
180
181 info = "Running IDCODE test; cpu in reset..."
182 wrap = yield from setup_sim(dut, info=info, clk_period=clk_period,
183 run=False)
184 jtag = yield from setup_jtag(wrap, tck_period = tck_period)
185
186 yield from idcode(wrap, jtag=jtag)
187
188 wrap.info("IDCODE test completed")
189
190 @cocotb.test()
191 def idcode_run(dut):
192 clk_period = 100 # 10MHz
193 tck_period = 300 # 3MHz
194
195 info = "Running IDCODE test; cpu running..."
196 wrap = yield from setup_sim(dut, info=info, clk_period=clk_period,
197 run=True)
198 jtag = yield from setup_jtag(wrap, tck_period = tck_period)
199
200 yield from idcode(wrap, jtag=jtag)
201
202 wrap.info("IDCODE test completed")
203
204 #
205 # Read IDCODE from SVF file
206 #
207
208 @cocotb.test()
209 def idcodesvf_reset(dut):
210 clk_period = 100 # 10MHz
211 tck_period = 300 # 3MHz
212
213 info = "Running IDCODE through SVF test; cpu in reset..."
214 wrap = yield from setup_sim(dut, info=info, clk_period=clk_period,
215 run=False)
216 jtag = yield from setup_jtag(wrap, tck_period = tck_period)
217
218 yield from execute_svf(wrap, jtag=jtag, svf_filename="idcode.svf")
219
220 wrap.info("IDCODE test completed")
221
222 @cocotb.test()
223 def idcodesvf_run(dut):
224 clk_period = 100 # 10MHz
225 tck_period = 300 # 3MHz
226
227 info = "Running IDCODE through SVF test; cpu running..."
228 wrap = yield from setup_sim(dut, info=info, clk_period=clk_period,
229 run=True)
230 jtag = yield from setup_jtag(wrap, tck_period = tck_period)
231
232 yield from execute_svf(wrap, jtag=jtag, svf_filename="idcode.svf")
233
234 wrap.info("IDCODE test completed")
235
236 #
237 # Boundary scan
238 #
239
240 def boundary_scan(wrap, *, jtag):
241 pins = get_jtag_boundary()
242
243 yield jtag.reset()
244
245 wrap.info("")
246 wrap.info("Before scan")
247 log_pins(wrap, pins)
248
249 yield jtag.load_ir([0, 0, 0, 0])
250 pinsdata = tuple(pin.data(i=i%2, o=((i%3)%2), oe=((i%5)%2))
251 for i, pin in enumerate(pins))
252 yield jtag.shift_data(chain(*pinsdata))
253
254 wrap.info("")
255 wrap.info("After scan")
256 log_pins(wrap, pins)
257 for i, pin in enumerate(pins):
258 pin.check(wrap=wrap, i=i%2, o=((i%3)%2), oe=((i%5)%2))
259
260 yield jtag.reset()
261
262 wrap.info("")
263 wrap.info("After reset")
264 log_pins(wrap, pins)
265
266
267 @cocotb.test()
268 def boundary_scan_reset(dut):
269 clk_period = 100 # 10MHz
270 tck_period = 300 # 3MHz
271
272 info = "Running boundary scan test; cpu in reset..."
273 wrap = yield from setup_sim(dut, info=info, clk_period=clk_period,
274 run=False)
275 jtag = yield from setup_jtag(wrap, tck_period = tck_period)
276
277 yield from boundary_scan(wrap, jtag=jtag)
278
279 wrap.info("IDCODE test completed")
280
281 @cocotb.test()
282 def boundary_scan_run(dut):
283 clk_period = 100 # 10MHz
284 tck_period = 300 # 3MHz
285
286 info = "Running boundary scan test; cpu running..."
287 wrap = yield from setup_sim(dut, info=info, clk_period=clk_period,
288 run=True)
289 jtag = yield from setup_jtag(wrap, tck_period = tck_period)
290
291 yield from boundary_scan(wrap, jtag=jtag)
292
293 wrap.info("IDCODE test completed")
294
295
296 # demo / debug how to get boundary scan names. run "python3 test.py"
297 if __name__ == '__main__':
298 pinouts = get_jtag_boundary()
299 for pin in pinouts:
300 # example: ('eint', '2', <IOType.In: 1>, 'eint_2', 125)
301 print (pin)