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