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