1 from itertools
import chain
4 from cocotb
.clock
import Clock
5 from cocotb
.triggers
import Timer
, RisingEdge
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:
30 self
.clk
= dut
.sys_clk
31 self
.rst
= dut
.sys_rst
32 self
.tck
= dut
.jtag_tck
33 self
.tms
= dut
.jtag_tms
34 self
.tdi
= dut
.jtag_tdi
35 self
.tdo
= dut
.jtag_tdo
38 ls180
.test_issuer
._discover
_all
()
39 ls180
.test_issuer
.ti
._discover
_all
()
40 ls180
.test_issuer
.ti
.dbg
._discover
_all
()
42 def info(self
, *args
, **kwargs
):
43 return self
.dut
._log
.info(*args
, **kwargs
)
47 def __init__(self
, pin
):
56 if self
.type_
== IOType
.In
:
57 core_i
= getattr(wrap
.ti
, f
"{self.name}__core__i").value
58 pad_i
= getattr(wrap
.ti
, f
"{self.name}__pad__i").value
59 wrap
.info(f
"{self.name}: core.i={core_i}, pad.i={pad_i}")
60 elif self
.type_
== IOType
.Out
:
61 core_o
= getattr(wrap
.ti
, f
"{self.name}__core__o").value
62 pad_o
= getattr(wrap
.ti
, f
"{self.name}__pad__o").value
63 wrap
.info(f
"{self.name}: core.o={core_o}, pad.o={pad_o}")
64 elif self
.type_
== IOType
.TriOut
:
65 core_o
= getattr(wrap
.ti
, f
"{self.name}__core__o").value
66 core_oe
= getattr(wrap
.ti
, f
"{self.name}__core__oe").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.(o={core_o}, oe={core_oe}), " \
70 "pad.(o={pad_o}, oe={pad_oe})")
71 elif self
.type_
== IOType
.InTriOut
:
72 core_i
= getattr(wrap
.ti
, f
"{self.name}__core__i").value
73 core_o
= getattr(wrap
.ti
, f
"{self.name}__core__o").value
74 core_oe
= getattr(wrap
.ti
, f
"{self.name}__core__oe").value
75 pad_i
= getattr(wrap
.ti
, f
"{self.name}__pad__i").value
76 pad_o
= getattr(wrap
.ti
, f
"{self.name}__pad__o").value
77 pad_oe
= getattr(wrap
.ti
, f
"{self.name}__pad__oe").value
78 wrap
.info(f
"{self.name}: core.(i={core_i}, o={core_o}, " \
79 "oe={core_oe}), pad.(i={core_i}, o={pad_o}, " \
82 raise ValueError(f
"Unsupported pin type {self.type_}")
84 def data(self
, *, i
=None, o
=None, oe
=None):
85 if self
.type_
== IOType
.In
:
88 elif self
.type_
== IOType
.Out
:
91 elif self
.type_
== IOType
.TriOut
:
92 assert (o
is not None) and (oe
is not None)
94 elif self
.type_
== IOType
.InTriOut
:
95 assert (i
is not None) and(o
is not None) and (oe
is not None)
98 raise ValueError(f
"Unsupported pin type {self.type_}")
100 def check(self
, *, wrap
, i
=None, o
=None, oe
=None):
101 if self
.type_
in (IOType
.In
, IOType
.InTriOut
):
102 sig
= f
"{self.name}__core__i"
103 val
= getattr(wrap
.ti
, sig
).value
105 raise ValueError(f
"'{sig}' should be {i}, not {val}")
106 if self
.type_
in (IOType
.Out
, IOType
.TriOut
, IOType
.InTriOut
):
107 sig
= f
"{self.name}__pad__o"
108 val
= getattr(wrap
.ti
, sig
).value
110 raise ValueError(f
"'{sig}' should be {o}, not {val}")
111 if self
.type_
in (IOType
.TriOut
, IOType
.InTriOut
):
112 sig
= f
"{self.name}__pad__oe"
113 val
= getattr(wrap
.ti
, sig
).value
115 raise ValueError(f
"'{sig}' should be {oe}, not {val}")
118 def log_pins(wrap
, pins
):
123 def get_jtag_boundary():
124 """gets the list of information for jtag boundary scan
126 # currently only a subset of pins is enabled. nuisance
129 'eint', 'gpio', 'mspi0',
130 # 'mspi1', - disabled for now
131 # 'pwm', 'sd0', - disabled for now
133 pins
= tuple(JTAGPin(pin
) for pin
in Pins(get_pinspecs(subset
=subset
)))
137 def setup_sim(dut
, *, info
, clk_period
, run
):
138 """Initialize CPU and setup clock"""
140 wrap
= DUTWrapper(dut
)
146 clk_steps
= get_sim_steps(clk_period
, "ns")
147 cocotb
.fork(Clock(wrap
.clk
, clk_steps
).start())
150 yield Timer(int(10.5*clk_steps
))
152 yield Timer(int(3*clk_steps
))
157 def setup_jtag(wrap
, *, tck_period
):
158 # TODO: Make this a generator
161 clk_steps
= get_sim_steps(tck_period
, "ns")
162 return JTAG_Master(wrap
.tck
, wrap
.tms
, wrap
.tdi
, wrap
.tdo
,
163 clk_period
=clk_steps
,
166 def execute_svf(wrap
, *, jtag
, svf_filename
):
169 jtag_svf
= SVF_Executor(jtag
)
170 with
open(svf_filename
, "r") as f
:
172 yield jtag_svf
.run(svf_deck
, p
=wrap
.info
)
175 # IDCODE using JTAG_master
178 def idcode(wrap
, *, jtag
):
180 result1
= jtag
.result
181 wrap
.info("IDCODE1: {}".format(result1
))
182 assert(result1
== BinaryValue("00000000000000000001100011111111"))
185 result2
= jtag
.result
186 wrap
.info("IDCODE2: {}".format(result2
))
188 assert(result1
== result2
)
192 def idcode_reset(dut
):
193 clk_period
= 100 # 10MHz
194 tck_period
= 300 # 3MHz
196 info
= "Running IDCODE test; cpu in reset..."
197 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
199 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
201 yield from idcode(wrap
, jtag
=jtag
)
203 wrap
.info("IDCODE test completed")
208 clk_period
= 100 # 10MHz
209 tck_period
= 300 # 3MHz
211 info
= "Running IDCODE test; cpu running..."
212 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
214 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
216 yield from idcode(wrap
, jtag
=jtag
)
218 wrap
.info("IDCODE test completed")
221 # Read IDCODE from SVF file
225 def idcodesvf_reset(dut
):
226 clk_period
= 100 # 10MHz
227 tck_period
= 300 # 3MHz
229 info
= "Running IDCODE through SVF test; cpu in reset..."
230 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
232 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
234 yield from execute_svf(wrap
, jtag
=jtag
, svf_filename
="idcode.svf")
236 wrap
.info("IDCODE test completed")
240 def idcodesvf_run(dut
):
241 clk_period
= 100 # 10MHz
242 tck_period
= 300 # 3MHz
244 info
= "Running IDCODE through SVF test; cpu running..."
245 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
247 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
249 yield from execute_svf(wrap
, jtag
=jtag
, svf_filename
="idcode.svf")
251 wrap
.info("IDCODE test completed")
257 def boundary_scan(wrap
, *, jtag
):
258 pins
= get_jtag_boundary()
263 wrap
.info("Before scan")
266 yield jtag
.load_ir([0, 0, 0, 0])
267 pinsdata
= tuple(pin
.data(i
=i
%2, o
=((i
%3)%2), oe
=((i
%5)%2))
268 for i
, pin
in enumerate(pins
))
269 yield jtag
.shift_data(chain(*pinsdata
))
272 wrap
.info("After scan")
274 for i
, pin
in enumerate(pins
):
275 pin
.check(wrap
=wrap
, i
=i
%2, o
=((i
%3)%2), oe
=((i
%5)%2))
280 wrap
.info("After reset")
285 def boundary_scan_reset(dut
):
286 clk_period
= 100 # 10MHz
287 tck_period
= 300 # 3MHz
289 info
= "Running boundary scan test; cpu in reset..."
290 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
292 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
294 yield from boundary_scan(wrap
, jtag
=jtag
)
296 wrap
.info("IDCODE test completed")
300 def boundary_scan_run(dut
):
301 clk_period
= 100 # 10MHz
302 tck_period
= 300 # 3MHz
304 info
= "Running boundary scan test; cpu running..."
305 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
307 jtag
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
309 yield from boundary_scan(wrap
, jtag
=jtag
)
311 wrap
.info("IDCODE test completed")
315 def wishbone_basic(dut
):
317 Test of an added Wishbone interface
319 clk_period
= 100 # 10MHz
320 tck_period
= 300 # 0.3MHz
322 data_in
= BinaryValue()
323 # these have to match with soc.debug.jtag.JTAG ircodes
324 cmd_MEMADDRESS
= BinaryValue("0101") # 5
325 cmd_MEMREAD
= BinaryValue("0110") # 6
326 cmd_MEMREADWRITE
= BinaryValue("0111") # 7
328 info
= "Running Wishbone basic test"
329 wrap
= yield from setup_sim(dut
, info
=info
, clk_period
=clk_period
,
331 master
= yield from setup_jtag(wrap
, tck_period
= tck_period
)
334 #clk_steps = get_sim_steps(clk_period, "ns")
335 #yield Timer(int(4.5*clk_steps))
338 #yield master.reset()
340 #yield Timer(int(10.5*clk_steps))
344 # Load the memory address
345 yield master
.load_ir(cmd_MEMADDRESS
)
346 dut
._log
.info("Loading address")
348 data_in
.binstr
= "000000000000000000000000000001"
349 dut
._log
.info(" input: {}".format(data_in
.binstr
))
350 yield master
.shift_data(data_in
)
351 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
354 yield master
.load_ir(cmd_MEMREADWRITE
)
355 dut
._log
.info("Writing memory")
357 data_in
.binstr
= "01010101" * 4
358 dut
._log
.info(" input: {}".format(data_in
.binstr
))
359 yield master
.shift_data(data_in
)
360 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
362 data_in
.binstr
= "10101010" * 4
363 dut
._log
.info(" input: {}".format(data_in
.binstr
))
364 yield master
.shift_data(data_in
)
365 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
367 # Load the memory address
368 yield master
.load_ir(cmd_MEMADDRESS
)
369 dut
._log
.info("Loading address")
371 data_in
.binstr
= "000000000000000000000000000001"
372 dut
._log
.info(" input: {}".format(data_in
.binstr
))
373 yield master
.shift_data(data_in
)
374 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
375 assert master
.result
.binstr
== "000000000000000000000000000000"
378 yield master
.load_ir(cmd_MEMREADWRITE
)
379 dut
._log
.info("Reading and writing memory")
381 data_in
.binstr
= "10101010" * 4
382 dut
._log
.info(" input: {}".format(data_in
.binstr
))
383 yield master
.shift_data(data_in
)
384 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
385 assert master
.result
.binstr
== "01010101" * 4
387 data_in
.binstr
= "01010101" * 4
388 dut
._log
.info(" input: {}".format(data_in
.binstr
))
389 yield master
.shift_data(data_in
)
390 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
391 assert master
.result
.binstr
== "10101010" * 4
393 # Load the memory address
394 yield master
.load_ir(cmd_MEMADDRESS
)
395 dut
._log
.info("Loading address")
397 data_in
.binstr
= "000000000000000000000000000001"
398 dut
._log
.info(" input: {}".format(data_in
.binstr
))
399 yield master
.shift_data(data_in
)
400 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
401 assert master
.result
.binstr
== "00000000000000000000000000010"
404 yield master
.load_ir(cmd_MEMREAD
)
405 dut
._log
.info("Reading memory")
406 data_in
.binstr
= "00000000" * 4
408 dut
._log
.info(" input: {}".format(data_in
.binstr
))
409 yield master
.shift_data(data_in
)
410 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
411 assert master
.result
.binstr
== "10101010" * 4
413 dut
._log
.info(" input: {}".format(data_in
.binstr
))
414 yield master
.shift_data(data_in
)
415 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
416 assert master
.result
.binstr
== "01010101" * 4
418 # Load the memory address
419 yield master
.load_ir(cmd_MEMADDRESS
) # MEMADDR
420 dut
._log
.info("Loading address")
422 data_in
.binstr
= "000000000000000000000000000001"
423 dut
._log
.info(" input: {}".format(data_in
.binstr
))
424 yield master
.shift_data(data_in
)
425 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
426 assert master
.result
.binstr
== "00000000000000000000000000010"
429 yield master
.load_ir(cmd_MEMREAD
) # MEMREAD
430 dut
._log
.info("Reading memory")
431 data_in
.binstr
= "00000000" * 4
433 dut
._log
.info(" input: {}".format(data_in
.binstr
))
434 yield master
.shift_data(data_in
)
435 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
436 assert master
.result
.binstr
== "10101010" * 4
438 dut
._log
.info(" input: {}".format(data_in
.binstr
))
439 yield master
.shift_data(data_in
)
440 dut
._log
.info(" output: {}".format(master
.result
.binstr
))
441 assert master
.result
.binstr
== "01010101" * 4
443 dut
._log
.info("{!r}".format(wbmem
))
446 # demo / debug how to get boundary scan names. run "python3 test.py"
447 if __name__
== '__main__':
448 pinouts
= get_jtag_boundary()
450 # example: ('eint', '2', <IOType.In: 1>, 'eint_2', 125)