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