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