1 from itertools
import chain
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
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
13 from soc
.config
.pinouts
import get_pinspecs
14 from soc
.debug
.jtag
import Pins
22 def __init__(self
, dut
):
26 except AttributeError:
32 self
.tck
= ti
.TAP_bus__tck
33 self
.tms
= ti
.TAP_bus__tms
34 self
.tdi
= ti
.TAP_bus__tdi
35 self
.tdo
= ti
.TAP_bus__tdo
37 def info(self
, *args
, **kwargs
):
38 return self
.dut
._log
.info(*args
, **kwargs
)
42 def __init__(self
, pin
):
47 if self
.type_
== IOType
.In
:
48 core_i
= getattr(wrap
.ti
, f
"{self.name}__core__i").value
49 pad_i
= getattr(wrap
.ti
, f
"{self.name}__pad__i").value
50 wrap
.info(f
"{self.name}: core.i={core_i}, pad.i={pad_i}")
51 elif self
.type_
== IOType
.Out
:
52 core_o
= getattr(wrap
.ti
, f
"{self.name}__core__o").value
53 pad_o
= getattr(wrap
.ti
, f
"{self.name}__pad__o").value
54 wrap
.info(f
"{self.name}: core.o={core_o}, pad.o={pad_o}")
55 elif self
.type_
== IOType
.TriOut
:
56 core_o
= getattr(wrap
.ti
, f
"{self.name}__core__o").value
57 core_oe
= getattr(wrap
.ti
, f
"{self.name}__core__oe").value
58 pad_o
= getattr(wrap
.ti
, f
"{self.name}__pad__o").value
59 pad_oe
= getattr(wrap
.ti
, f
"{self.name}__pad__oe").value
60 wrap
.info(f
"{self.name}: core.(o={core_o}, oe={core_oe}), " \
61 "pad.(o={pad_o}, oe={pad_oe})")
62 elif self
.type_
== IOType
.InTriOut
:
63 core_i
= getattr(wrap
.ti
, f
"{self.name}__core__i").value
64 core_o
= getattr(wrap
.ti
, f
"{self.name}__core__o").value
65 core_oe
= getattr(wrap
.ti
, f
"{self.name}__core__oe").value
66 pad_i
= getattr(wrap
.ti
, f
"{self.name}__pad__i").value
67 pad_o
= getattr(wrap
.ti
, f
"{self.name}__pad__o").value
68 pad_oe
= getattr(wrap
.ti
, f
"{self.name}__pad__oe").value
69 wrap
.info(f
"{self.name}: core.(i={core_i}, o={core_o}, " \
70 "oe={core_oe}), pad.(i={core_i}, o={pad_o}, " \
73 raise ValueError(f
"Unsupported pin type {self.type_}")
75 def data(self
, *, i
=None, o
=None, oe
=None):
76 if self
.type_
== IOType
.In
:
79 elif self
.type_
== IOType
.Out
:
82 elif self
.type_
== IOType
.TriOut
:
83 assert (o
is not None) and (oe
is not None)
85 elif self
.type_
== IOType
.InTriOut
:
86 assert (i
is not None) and(o
is not None) and (oe
is not None)
89 raise ValueError(f
"Unsupported pin type {self.type_}")
91 def check(self
, *, wrap
, i
=None, o
=None, oe
=None):
92 if self
.type_
in (IOType
.In
, IOType
.InTriOut
):
93 sig
= f
"{self.name}__core__i"
94 val
= getattr(wrap
.ti
, sig
).value
96 raise ValueError(f
"'{sig}' should be {i}, not {val}")
97 if self
.type_
in (IOType
.Out
, IOType
.TriOut
, IOType
.InTriOut
):
98 sig
= f
"{self.name}__pad__o"
99 val
= getattr(wrap
.ti
, sig
).value
101 raise ValueError(f
"'{sig}' should be {o}, not {val}")
102 if self
.type_
in (IOType
.TriOut
, IOType
.InTriOut
):
103 sig
= f
"{self.name}__pad__oe"
104 val
= getattr(wrap
.ti
, sig
).value
106 raise ValueError(f
"'{sig}' should be {oe}, not {val}")
109 def log_pins(wrap
, pins
):
114 def get_jtag_boundary():
115 """gets the list of information for jtag boundary scan
117 # currently only a subset of pins is enabled. nuisance
120 'eint', 'gpio', 'mspi0',
121 # 'mspi1', - disabled for now
122 # 'pwm', 'sd0', - disabled for now
124 pins
= tuple(JTAGPin(pin
) for pin
in Pins(get_pinspecs(subset
=subset
)))
128 def setup_sim(dut
, *, info
, clk_period
, run
):
129 """Initialize CPU and setup clock"""
131 wrap
= DUTWrapper(dut
)
134 clk_steps
= get_sim_steps(clk_period
, "ns")
135 cocotb
.fork(Clock(wrap
.clk
, clk_steps
).start())
140 yield Timer(int(10.5*clk_steps
))
142 yield Timer(int(5*clk_steps
))
147 def setup_jtag(wrap
, *, tck_period
):
149 # Yield is never executed but it makes this function a generator
151 return JTAG_Master(wrap
.tck
, wrap
.tms
, wrap
.tdi
, wrap
.tdo
,
152 clk_period
=tck_period
,
155 def execute_svf(wrap
, *, jtag
, svf_filename
):
158 jtag_svf
= SVF_Executor(jtag
)
159 with
open(svf_filename
, "r") as f
:
161 yield jtag_svf
.run(svf_deck
, p
=wrap
.info
)
164 # IDCODE using JTAG_master
167 def idcode(wrap
, *, jtag
):
169 result1
= jtag
.result
170 wrap
.info("IDCODE1: {}".format(result1
))
171 assert(result1
== BinaryValue("00000000000000000001100011111111"))
174 result2
= jtag
.result
175 wrap
.info("IDCODE2: {}".format(result2
))
177 assert(result1
== result2
)
181 def idcode_reset(dut
):
182 clk_period
= 100 # 10MHz
183 tck_period
= 300 # 3MHz
185 info
= "Running IDCODE test; cpu in reset..."
186 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
188 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
190 yield from idcode(wrap
, jtag
=jtag
)
192 wrap
.info("IDCODE test completed")
197 clk_period
= 100 # 10MHz
198 tck_period
= 300 # 3MHz
200 info
= "Running IDCODE test; cpu running..."
201 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
203 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
205 yield from idcode(wrap
, jtag
=jtag
)
207 wrap
.info("IDCODE test completed")
210 # Read IDCODE from SVF file
214 def idcodesvf_reset(dut
):
215 clk_period
= 100 # 10MHz
216 tck_period
= 300 # 3MHz
218 info
= "Running IDCODE through SVF test; cpu in reset..."
219 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
221 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
223 yield from execute_svf(wrap
, jtag
=jtag
, svf_filename
="idcode.svf")
225 wrap
.info("IDCODE test completed")
229 def idcodesvf_run(dut
):
230 clk_period
= 100 # 10MHz
231 tck_period
= 300 # 3MHz
233 info
= "Running IDCODE through SVF test; cpu running..."
234 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
236 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
238 yield from execute_svf(wrap
, jtag
=jtag
, svf_filename
="idcode.svf")
240 wrap
.info("IDCODE test completed")
246 def boundary_scan(wrap
, *, jtag
):
247 pins
= get_jtag_boundary()
252 wrap
.info("Before scan")
255 yield jtag
.load_ir([0, 0, 0, 0])
256 pinsdata
= tuple(pin
.data(i
=i
%2, o
=((i
%3)%2), oe
=((i
%5)%2))
257 for i
, pin
in enumerate(pins
))
258 yield jtag
.shift_data(chain(*pinsdata
))
261 wrap
.info("After scan")
263 for i
, pin
in enumerate(pins
):
264 pin
.check(wrap
=wrap
, i
=i
%2, o
=((i
%3)%2), oe
=((i
%5)%2))
269 wrap
.info("After reset")
274 def boundary_scan_reset(dut
):
275 clk_period
= 100 # 10MHz
276 tck_period
= 300 # 3MHz
278 info
= "Running boundary scan test; cpu in reset..."
279 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
281 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
283 yield from boundary_scan(wrap
, jtag
=jtag
)
285 wrap
.info("IDCODE test completed")
289 def boundary_scan_run(dut
):
290 clk_period
= 100 # 10MHz
291 tck_period
= 300 # 3MHz
293 info
= "Running boundary scan test; cpu running..."
294 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
296 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
298 yield from boundary_scan(wrap
, jtag
=jtag
)
300 wrap
.info("IDCODE test completed")
304 def wishbone_basic(dut
):
305 """Test of an added Wishbone interface
307 for this test the soc JTAG TAP address width is 29 bits and data is 64
308 JTAG has access to the *full* memory range, including peripherals,
309 as defined by the litex setup.
311 clk_period
= 100 # 10MHz
312 tck_period
= 300 # 3MHz
314 data_in
= BinaryValue()
315 # these have to match with soc.debug.jtag.JTAG ircodes
316 cmd_MEMADDRESS
= BinaryValue("0101") # 5
317 cmd_MEMREAD
= BinaryValue("0110") # 6
318 cmd_MEMREADWRITE
= BinaryValue("0111") # 7
320 info
= "Running Wishbone basic test"
321 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
323 master
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
325 # Load the memory address
326 yield master
.load_ir(cmd_MEMADDRESS
)
327 dut
._log
.info("Loading address")
329 # WBaddresses in soc.debug.jtag.JTAG are 29 bits
330 data_in
.binstr
= "00000000000000000000000000001"
331 dut
._log
.info(" input: {}".format(data_in
.binstr
))
332 yield master
.shift_data(data_in
)
333 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
336 yield master
.load_ir(cmd_MEMREADWRITE
)
337 dut
._log
.info("Writing memory")
340 data_in
.binstr
= "01010101" * 8
341 dut
._log
.info(" input: {}".format(data_in
.binstr
))
342 yield master
.shift_data(data_in
)
343 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
345 data_in
.binstr
= "10101010" * 8
346 dut
._log
.info(" input: {}".format(data_in
.binstr
))
347 yield master
.shift_data(data_in
)
348 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
350 # Load the memory address
351 yield master
.load_ir(cmd_MEMADDRESS
)
352 dut
._log
.info("Loading address")
354 data_in
.binstr
= "00000000000000000000000000001"
355 dut
._log
.info(" input: {}".format(data_in
.binstr
))
356 yield master
.shift_data(data_in
)
357 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
358 assert master
.result
.binstr
== "00000000000000000000000000000"
361 yield master
.load_ir(cmd_MEMREADWRITE
)
362 dut
._log
.info("Reading and writing memory")
364 data_in
.binstr
= "10101010" * 8
365 dut
._log
.info(" input: {}".format(data_in
.binstr
))
366 yield master
.shift_data(data_in
)
367 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
368 assert master
.result
.binstr
== "01010101" * 8
370 data_in
.binstr
= "01010101" * 8
371 dut
._log
.info(" input: {}".format(data_in
.binstr
))
372 yield master
.shift_data(data_in
)
373 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
374 assert master
.result
.binstr
== "10101010" * 8
376 # Load the memory address
377 yield master
.load_ir(cmd_MEMADDRESS
)
378 dut
._log
.info("Loading address")
380 data_in
.binstr
= "00000000000000000000000000001"
381 dut
._log
.info(" input: {}".format(data_in
.binstr
))
382 yield master
.shift_data(data_in
)
383 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
384 assert master
.result
.binstr
== "00000000000000000000000000010"
387 yield master
.load_ir(cmd_MEMREAD
)
388 dut
._log
.info("Reading memory")
389 data_in
.binstr
= "00000000" * 8
391 dut
._log
.info(" input: {}".format(data_in
.binstr
))
392 yield master
.shift_data(data_in
)
393 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
394 assert master
.result
.binstr
== "10101010" * 8
396 dut
._log
.info(" input: {}".format(data_in
.binstr
))
397 yield master
.shift_data(data_in
)
398 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
399 assert master
.result
.binstr
== "01010101" * 8
401 # Load the memory address
402 yield master
.load_ir(cmd_MEMADDRESS
) # MEMADDR
403 dut
._log
.info("Loading address")
405 data_in
.binstr
= "00000000000000000000000000001"
406 dut
._log
.info(" input: {}".format(data_in
.binstr
))
407 yield master
.shift_data(data_in
)
408 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
409 assert master
.result
.binstr
== "00000000000000000000000000010"
412 yield master
.load_ir(cmd_MEMREAD
) # MEMREAD
413 dut
._log
.info("Reading memory")
414 data_in
.binstr
= "00000000" * 8
416 dut
._log
.info(" input: {}".format(data_in
.binstr
))
417 yield master
.shift_data(data_in
)
418 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
419 assert master
.result
.binstr
== "10101010" * 8
421 dut
._log
.info(" input: {}".format(data_in
.binstr
))
422 yield master
.shift_data(data_in
)
423 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
424 assert master
.result
.binstr
== "01010101" * 8
426 dut
._log
.info("{!r}".format(wbmem
))
429 # demo / debug how to get boundary scan names. run "python3 test.py"
430 if __name__
== '__main__':
431 pinouts
= get_jtag_boundary()
433 # example: ('eint', '2', <IOType.In: 1>, 'eint_2', 125)