Almost finished asserts in unit test, starting cleanup.
[pinmux.git] / src / spec / testing_stage1.py
1 #!/usr/bin/env python3
2 """
3 pinmux documented here https://libre-soc.org/docs/pinmux/
4 """
5 from nmigen.build.dsl import Resource, Subsignal, Pins
6 from nmigen.build.plat import TemplatedPlatform
7 from nmigen.build.res import ResourceManager, ResourceError
8 from nmigen.hdl.rec import Layout
9 from nmigen import Elaboratable, Signal, Module, Instance
10 from collections import OrderedDict
11 from jtag import JTAG, resiotypes
12 from copy import deepcopy
13 from nmigen.cli import rtlil
14 import sys
15
16 # extra dependencies for jtag testing (?)
17 #from soc.bus.sram import SRAM
18
19 #from nmigen import Memory
20 from nmigen.sim import Simulator, Delay, Settle, Tick, Passive
21
22 from nmutil.util import wrap
23
24 #from soc.debug.jtagutils import (jtag_read_write_reg,
25 # jtag_srv, jtag_set_reset,
26 # jtag_set_ir, jtag_set_get_dr)
27
28 from soc.debug.test.test_jtag_tap import (jtag_read_write_reg,
29 jtag_set_reset,
30 jtag_set_shift_ir,
31 jtag_set_shift_dr,
32 jtag_set_run,
33 jtag_set_idle)
34
35 from c4m.nmigen.jtag.tap import TAP, IOType
36 from c4m.nmigen.jtag.bus import Interface as JTAGInterface
37 from soc.debug.dmi import DMIInterface, DBGCore
38 #from soc.debug.test.dmi_sim import dmi_sim
39 #from soc.debug.test.jtagremote import JTAGServer, JTAGClient
40 from nmigen.build.res import ResourceError
41
42 # Was thinking of using these functions, but skipped for simplicity for now
43 # XXX nope. the output from JSON file.
44 #from pinfunctions import (i2s, lpc, emmc, sdmmc, mspi, mquadspi, spi,
45 # quadspi, i2c, mi2c, jtag, uart, uartfull, rgbttl, ulpi, rgmii, flexbus1,
46 # flexbus2, sdram1, sdram2, sdram3, vss, vdd, sys, eint, pwm, gpio)
47
48 # File for stage 1 pinmux tested proposed by Luke,
49 # https://bugs.libre-soc.org/show_bug.cgi?id=50#c10
50
51
52 def dummy_pinset():
53 # sigh this needs to come from pinmux.
54 gpios = []
55 for i in range(4):
56 gpios.append("%d*" % i)
57 return {'uart': ['tx+', 'rx-'],
58 'gpio': gpios,
59 #'jtag': ['tms-', 'tdi-', 'tdo+', 'tck+'],
60 'i2c': ['sda*', 'scl+']}
61
62 """
63 a function is needed which turns the results of dummy_pinset()
64 into:
65
66 [UARTResource("uart", 0, tx=..., rx=..),
67 I2CResource("i2c", 0, scl=..., sda=...),
68 Resource("gpio", 0, Subsignal("i"...), Subsignal("o"...)
69 Resource("gpio", 1, Subsignal("i"...), Subsignal("o"...)
70 ...
71 ]
72 """
73
74
75 def create_resources(pinset):
76 resources = []
77 for periph, pins in pinset.items():
78 print(periph, pins)
79 if periph == 'i2c':
80 #print("I2C required!")
81 resources.append(I2CResource('i2c', 0, sda='sda', scl='scl'))
82 elif periph == 'uart':
83 #print("UART required!")
84 resources.append(UARTResource('uart', 0, tx='tx', rx='rx'))
85 elif periph == 'gpio':
86 #print("GPIO required!")
87 print ("GPIO is defined as '*' type, meaning i, o and oe needed")
88 ios = []
89 for pin in pins:
90 pname = "gpio"+pin[:-1] # strip "*" on end
91 # urrrr... tristsate and io assume a single pin which is
92 # of course exactly what we don't want in an ASIC: we want
93 # *all three* pins but the damn port is not outputted
94 # as a triplet, it's a single Record named "io". sigh.
95 # therefore the only way to get a triplet of i/o/oe
96 # is to *actually* create explicit triple pins
97 # XXX ARRRGH, doesn't work
98 #pad = Subsignal("io",
99 # Pins("%s_i %s_o %s_oe" % (pname, pname, pname),
100 # dir="io", assert_width=3))
101 #ios.append(Resource(pname, 0, pad))
102 pads = []
103 pads.append(Subsignal("i",
104 Pins(pname+"_i", dir="i", assert_width=1)))
105 pads.append(Subsignal("o",
106 Pins(pname+"_o", dir="o", assert_width=1)))
107 pads.append(Subsignal("oe",
108 Pins(pname+"_oe", dir="o", assert_width=1)))
109 ios.append(Resource.family(pname, 0, default_name=pname,
110 ios=pads))
111 resources.append(Resource.family(periph, 0, default_name="gpio",
112 ios=ios))
113
114 # add clock and reset
115 clk = Resource("clk", 0, Pins("sys_clk", dir="i"))
116 rst = Resource("rst", 0, Pins("sys_rst", dir="i"))
117 resources.append(clk)
118 resources.append(rst)
119 return resources
120
121
122 def JTAGResource(*args):
123 io = []
124 io.append(Subsignal("tms", Pins("tms", dir="i", assert_width=1)))
125 io.append(Subsignal("tdi", Pins("tdi", dir="i", assert_width=1)))
126 io.append(Subsignal("tck", Pins("tck", dir="i", assert_width=1)))
127 io.append(Subsignal("tdo", Pins("tdo", dir="o", assert_width=1)))
128 return Resource.family(*args, default_name="jtag", ios=io)
129
130 def UARTResource(*args, rx, tx):
131 io = []
132 io.append(Subsignal("rx", Pins(rx, dir="i", assert_width=1)))
133 io.append(Subsignal("tx", Pins(tx, dir="o", assert_width=1)))
134 return Resource.family(*args, default_name="uart", ios=io)
135
136
137 def I2CResource(*args, scl, sda):
138 ios = []
139 pads = []
140 pads.append(Subsignal("i", Pins(sda+"_i", dir="i", assert_width=1)))
141 pads.append(Subsignal("o", Pins(sda+"_o", dir="o", assert_width=1)))
142 pads.append(Subsignal("oe", Pins(sda+"_oe", dir="o", assert_width=1)))
143 ios.append(Resource.family(sda, 0, default_name=sda, ios=pads))
144 pads = []
145 pads.append(Subsignal("i", Pins(scl+"_i", dir="i", assert_width=1)))
146 pads.append(Subsignal("o", Pins(scl+"_o", dir="o", assert_width=1)))
147 pads.append(Subsignal("oe", Pins(scl+"_oe", dir="o", assert_width=1)))
148 ios.append(Resource.family(scl, 0, default_name=scl, ios=pads))
149 return Resource.family(*args, default_name="i2c", ios=ios)
150
151
152 # top-level demo module.
153 class Blinker(Elaboratable):
154 def __init__(self, pinset, resources, no_jtag_connect=False):
155 self.no_jtag_connect = no_jtag_connect
156 self.jtag = JTAG({}, "sync", resources=resources)
157 #memory = Memory(width=32, depth=16)
158 #self.sram = SRAM(memory=memory, bus=self.jtag.wb)
159
160 def elaborate(self, platform):
161 jtag_resources = self.jtag.pad_mgr.resources
162 m = Module()
163 m.submodules.jtag = self.jtag
164 #m.submodules.sram = self.sram
165
166 #count = Signal(5)
167 #m.d.sync += count.eq(count+1)
168 print ("resources", platform, jtag_resources.items())
169 gpio = self.jtag.request('gpio')
170 print (gpio, gpio.layout, gpio.fields)
171 # get the GPIO bank, mess about with some of the pins
172 #m.d.comb += gpio.gpio0.o.eq(1)
173 #m.d.comb += gpio.gpio1.o.eq(gpio.gpio2.i)
174 #m.d.comb += gpio.gpio1.oe.eq(count[4])
175 #m.d.sync += count[0].eq(gpio.gpio1.i)
176
177 num_gpios = 4
178 gpio_i_ro = Signal(num_gpios)
179 gpio_o_test = Signal(num_gpios)
180 gpio_oe_test = Signal(num_gpios)
181
182 # Create a read-only copy of core-side GPIO input signals
183 # for Simulation asserts
184 m.d.comb += gpio_i_ro[0].eq(gpio.gpio0.i)
185 m.d.comb += gpio_i_ro[1].eq(gpio.gpio1.i)
186 m.d.comb += gpio_i_ro[2].eq(gpio.gpio2.i)
187 m.d.comb += gpio_i_ro[3].eq(gpio.gpio3.i)
188
189 # Wire up the output signal of each gpio by XOR'ing each bit of
190 # gpio_o_test with gpio's input
191 # Wire up each bit of gpio_oe_test signal to oe signal of each gpio.
192 # Turn into a loop at some point, probably a way without
193 # using get_attr()
194 m.d.comb += gpio.gpio0.o.eq(gpio_o_test[0] ^ gpio.gpio0.i)
195 m.d.comb += gpio.gpio1.o.eq(gpio_o_test[1] ^ gpio.gpio1.i)
196 m.d.comb += gpio.gpio2.o.eq(gpio_o_test[2] ^ gpio.gpio2.i)
197 m.d.comb += gpio.gpio3.o.eq(gpio_o_test[3] ^ gpio.gpio3.i)
198
199 m.d.comb += gpio.gpio0.oe.eq(gpio_oe_test[0])
200 m.d.comb += gpio.gpio1.oe.eq(gpio_oe_test[1])
201 m.d.comb += gpio.gpio2.oe.eq(gpio_oe_test[2])
202 m.d.comb += gpio.gpio3.oe.eq(gpio_oe_test[3])
203
204 # get the UART resource, mess with the output tx
205 uart = self.jtag.request('uart')
206 print ("uart fields", uart, uart.fields)
207 self.intermediary = Signal()
208 m.d.comb += uart.tx.eq(self.intermediary)
209 m.d.comb += self.intermediary.eq(uart.rx)
210
211 # I2C
212 num_i2c = 1
213 i2c_sda_oe_test = Signal(num_i2c)
214 i2c_scl_oe_test = Signal(num_i2c)
215 i2c = self.jtag.request('i2c')
216 print ("i2c fields", i2c, i2c.fields)
217 # Connect in loopback
218 m.d.comb += i2c.scl.o.eq(i2c.scl.i)
219 m.d.comb += i2c.sda.o.eq(i2c.sda.i)
220 # Connect output enable to test port for sim
221 m.d.comb += i2c.sda.oe.eq(i2c_sda_oe_test)
222 m.d.comb += i2c.scl.oe.eq(i2c_scl_oe_test)
223
224 # to even be able to get at objects, you first have to make them
225 # available - i.e. not as local variables
226 # Public attributes are equivalent to input/output ports in hdl's
227 self.gpio = gpio
228 self.uart = uart
229 self.i2c = i2c
230 self.i2c_sda_oe_test = i2c_sda_oe_test
231 self.i2c_scl_oe_test = i2c_scl_oe_test
232 self.gpio_i_ro = gpio_i_ro
233 self.gpio_o_test = gpio_o_test
234 self.gpio_oe_test = gpio_oe_test
235
236 # sigh these wire up to the pads so you cannot set Signals
237 # that are already wired
238 if self.no_jtag_connect: # bypass jtag pad connect for testing purposes
239 return m
240 return self.jtag.boundary_elaborate(m, platform)
241
242 def ports(self):
243 return list(self)
244
245 def __iter__(self):
246 yield from self.jtag.iter_ports()
247
248 '''
249 _trellis_command_templates = [
250 r"""
251 {{invoke_tool("yosys")}}
252 {{quiet("-q")}}
253 {{get_override("yosys_opts")|options}}
254 -l {{name}}.rpt
255 {{name}}.ys
256 """,
257 ]
258 '''
259
260 # sigh, have to create a dummy platform for now.
261 # TODO: investigate how the heck to get it to output ilang. or verilog.
262 # or, anything, really. but at least it doesn't barf
263 class ASICPlatform(TemplatedPlatform):
264 connectors = []
265 resources = OrderedDict()
266 required_tools = []
267 command_templates = ['/bin/true'] # no command needed: stops barfing
268 file_templates = {
269 **TemplatedPlatform.build_script_templates,
270 "{{name}}.il": r"""
271 # {{autogenerated}}
272 {{emit_rtlil()}}
273 """,
274 "{{name}}.debug.v": r"""
275 /* {{autogenerated}} */
276 {{emit_debug_verilog()}}
277 """,
278 }
279 toolchain = None
280 default_clk = "clk" # should be picked up / overridden by platform sys.clk
281 default_rst = "rst" # should be picked up / overridden by platform sys.rst
282
283 def __init__(self, resources, jtag):
284 self.jtag = jtag
285 super().__init__()
286
287 # create set of pin resources based on the pinset, this is for the core
288 #jtag_resources = self.jtag.pad_mgr.resources
289 self.add_resources(resources)
290
291 # add JTAG without scan
292 self.add_resources([JTAGResource('jtag', 0)], no_boundary_scan=True)
293
294 def add_resources(self, resources, no_boundary_scan=False):
295 print ("ASICPlatform add_resources", resources)
296 return super().add_resources(resources)
297
298 #def iter_ports(self):
299 # yield from super().iter_ports()
300 # for io in self.jtag.ios.values():
301 # print ("iter ports", io.layout, io)
302 # for field in io.core.fields:
303 # yield getattr(io.core, field)
304 # for field in io.pad.fields:
305 # yield getattr(io.pad, field)
306
307 # XXX these aren't strictly necessary right now but the next
308 # phase is to add JTAG Boundary Scan so it maaay be worth adding?
309 # at least for the print statements
310 def get_input(self, pin, port, attrs, invert):
311 self._check_feature("single-ended input", pin, attrs,
312 valid_xdrs=(0,), valid_attrs=None)
313
314 m = Module()
315 print (" get_input", pin, "port", port, port.layout)
316 m.d.comb += pin.i.eq(self._invert_if(invert, port))
317 return m
318
319 def get_output(self, pin, port, attrs, invert):
320 self._check_feature("single-ended output", pin, attrs,
321 valid_xdrs=(0,), valid_attrs=None)
322
323 m = Module()
324 print (" get_output", pin, "port", port, port.layout)
325 m.d.comb += port.eq(self._invert_if(invert, pin.o))
326 return m
327
328 def get_tristate(self, pin, port, attrs, invert):
329 self._check_feature("single-ended tristate", pin, attrs,
330 valid_xdrs=(0,), valid_attrs=None)
331
332 print (" get_tristate", pin, "port", port, port.layout)
333 m = Module()
334 print (" pad", pin, port, attrs)
335 print (" pin", pin.layout)
336 return m
337 # m.submodules += Instance("$tribuf",
338 # p_WIDTH=pin.width,
339 # i_EN=pin.oe,
340 # i_A=self._invert_if(invert, pin.o),
341 # o_Y=port,
342 # )
343 m.d.comb += io.core.o.eq(pin.o)
344 m.d.comb += io.core.oe.eq(pin.oe)
345 m.d.comb += pin.i.eq(io.core.i)
346 m.d.comb += io.pad.i.eq(port.i)
347 m.d.comb += port.o.eq(io.pad.o)
348 m.d.comb += port.oe.eq(io.pad.oe)
349 return m
350
351 def get_input_output(self, pin, port, attrs, invert):
352 self._check_feature("single-ended input/output", pin, attrs,
353 valid_xdrs=(0,), valid_attrs=None)
354
355 print (" get_input_output", pin, "port", port, port.layout)
356 m = Module()
357 print (" port layout", port.layout)
358 print (" pin", pin)
359 print (" layout", pin.layout)
360 #m.submodules += Instance("$tribuf",
361 # p_WIDTH=pin.width,
362 # i_EN=io.pad.oe,
363 # i_A=self._invert_if(invert, io.pad.o),
364 # o_Y=port,
365 #)
366 # Create aliases for the port sub-signals
367 port_i = port.io[0]
368 port_o = port.io[1]
369 port_oe = port.io[2]
370
371 m.d.comb += pin.i.eq(self._invert_if(invert, port_i))
372 m.d.comb += port_o.eq(self._invert_if(invert, pin.o))
373 m.d.comb += port_oe.eq(pin.oe)
374
375 return m
376
377 def toolchain_prepare(self, fragment, name, **kwargs):
378 """override toolchain_prepare in order to grab the fragment
379 """
380 self.fragment = fragment
381 return super().toolchain_prepare(fragment, name, **kwargs)
382
383
384
385 def test_case0():
386 print("Starting sanity test case!")
387 print("printing out list of stuff in top")
388 print ("JTAG IOs", top.jtag.ios)
389 # ok top now has a variable named "gpio", let's enumerate that too
390 print("printing out list of stuff in top.gpio and its type")
391 print(top.gpio.__class__.__name__, dir(top.gpio))
392 # ok, it's a nmigen Record, therefore it has a layout. let's print
393 # that too
394 print("top.gpio is a Record therefore has fields and a layout")
395 print(" layout:", top.gpio.layout)
396 print(" fields:", top.gpio.fields)
397 print("Fun never ends...")
398 print(" layout, gpio2:", top.gpio.layout['gpio2'])
399 print(" fields, gpio2:", top.gpio.fields['gpio2'])
400 print(top.jtag.__class__.__name__, dir(top.jtag))
401 print("Pads:")
402 print(top.jtag.resource_table_pads[('gpio', 0)])
403
404 # etc etc. you get the general idea
405 delayVal = 0.2e-6
406 yield top.uart.rx.eq(0)
407 yield Delay(delayVal)
408 yield Settle()
409 yield top.gpio.gpio2.o.eq(0)
410 yield top.gpio.gpio3.o.eq(1)
411 yield
412 yield top.gpio.gpio3.oe.eq(1)
413 yield
414 yield top.gpio.gpio3.oe.eq(0)
415 # grab the JTAG resource pad
416 gpios_pad = top.jtag.resource_table_pads[('gpio', 0)]
417 yield gpios_pad.gpio3.i.eq(1)
418 yield Delay(delayVal)
419 yield Settle()
420 yield top.gpio.gpio2.oe.eq(1)
421 yield top.gpio.gpio3.oe.eq(1)
422 yield gpios_pad.gpio3.i.eq(0)
423 yield top.jtag.gpio.gpio2.i.eq(1)
424 yield Delay(delayVal)
425 yield Settle()
426 gpio_o2 = 0
427 for _ in range(20):
428 # get a value first (as an integer). you were trying to set
429 # it to the actual Signal. this is not going to work. or if
430 # it does, it's very scary.
431 gpio_o2 = not gpio_o2
432 yield top.gpio.gpio2.o.eq(gpio_o2)
433
434 # ditto: here you are trying to set to an AST expression
435 # which is inadviseable (likely to fail)
436 gpio_o3 = not gpio_o2
437 yield top.gpio.gpio3.o.eq(gpio_o3)
438 yield Delay(delayVal)
439 yield Settle()
440 # grab the JTAG resource pad
441 uart_pad = top.jtag.resource_table_pads[('uart', 0)]
442 yield uart_pad.rx.i.eq(gpio_o2)
443 yield Delay(delayVal)
444 yield Settle()
445 yield # one clock cycle
446 tx_val = yield uart_pad.tx.o
447 print ("xmit uart", tx_val, gpio_o2)
448
449 print ("jtag pad table keys")
450 print (top.jtag.resource_table_pads.keys())
451 uart_pad = top.jtag.resource_table_pads[('uart', 0)]
452 print ("uart pad", uart_pad)
453 print ("uart pad", uart_pad.layout)
454
455 yield top.gpio.gpio2.oe.eq(0)
456 yield top.gpio.gpio3.oe.eq(0)
457 yield top.jtag.gpio.gpio2.i.eq(0)
458 yield Delay(delayVal)
459 yield Settle()
460
461 # Code borrowed from cesar, runs, but shouldn't actually work because of
462 # self. statements and non-existent signal names.
463 def test_case1():
464 print("Example test case")
465 yield Passive()
466 while True:
467 # Settle() is needed to give a quick response to
468 # the zero delay case
469 yield Settle()
470 # wait for rel_o to become active
471 while not (yield self.rel_o):
472 yield
473 yield Settle()
474 # read the transaction parameters
475 assert self.expecting, "an unexpected result was produced"
476 delay = (yield self.delay)
477 expected = (yield self.expected)
478 # wait for `delay` cycles
479 for _ in range(delay):
480 yield
481 # activate go_i for one cycle
482 yield self.go_i.eq(1)
483 yield self.count.eq(self.count + 1)
484 yield
485 # check received data against the expected value
486 result = (yield self.port)
487 assert result == expected,\
488 f"expected {expected}, received {result}"
489 yield self.go_i.eq(0)
490 yield self.port.eq(0)
491
492 def test_gpios(dut):
493 print("Starting GPIO test case!")
494
495 num_gpios = dut.gpio_o_test.width
496 # Grab GPIO outpud pad resource from JTAG BS - end of chain
497 print (dut.jtag.boundary_scan_pads.keys())
498 gpio0_o = dut.jtag.boundary_scan_pads['gpio_0__gpio0__o']['o']
499 gpio1_o = dut.jtag.boundary_scan_pads['gpio_0__gpio1__o']['o']
500 gpio2_o = dut.jtag.boundary_scan_pads['gpio_0__gpio2__o']['o']
501 gpio3_o = dut.jtag.boundary_scan_pads['gpio_0__gpio3__o']['o']
502 gpio_pad_out = [ gpio0_o, gpio1_o, gpio2_o, gpio3_o]
503
504 # Grab GPIO output enable pad resource from JTAG BS - end of chain
505 gpio0_oe = dut.jtag.boundary_scan_pads['gpio_0__gpio0__oe']['o']
506 gpio1_oe = dut.jtag.boundary_scan_pads['gpio_0__gpio1__oe']['o']
507 gpio2_oe = dut.jtag.boundary_scan_pads['gpio_0__gpio2__oe']['o']
508 gpio3_oe = dut.jtag.boundary_scan_pads['gpio_0__gpio3__oe']['o']
509 gpio_pad_oe = [gpio0_oe, gpio1_oe, gpio2_oe, gpio3_oe]
510
511 # Grab GPIO input pad resource from JTAG BS - start of chain
512 gpio0_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio0__i']['i']
513 gpio1_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio1__i']['i']
514 gpio2_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio2__i']['i']
515 gpio3_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio3__i']['i']
516 gpio_pad_in = [gpio0_pad_in, gpio1_pad_in, gpio2_pad_in, gpio3_pad_in]
517
518 # Have the sim run through a for-loop where the gpio_o_test is
519 # incremented like a counter (0000, 0001...)
520 # At each iteration of the for-loop, assert:
521 # + output set at core matches output seen at pad
522 # TODO + input set at pad matches input seen at core
523 # TODO + if gpio_o_test bit is cleared, output seen at pad matches
524 # input seen at pad
525 num_gpio_o_states = num_gpios**2
526 pad_out = [0] * num_gpios
527 pad_oe = [0] * num_gpios
528 #print("Num of permutations of gpio_o_test record: ", num_gpio_o_states)
529 for gpio_o_val in range(0, num_gpio_o_states):
530 yield dut.gpio_o_test.eq(gpio_o_val)
531 #yield Settle()
532 yield # Move to the next clk cycle
533
534 # Cycle through all input combinations
535 for gpio_i_val in range(0, num_gpio_o_states):
536 # Set each gpio input at pad to test value
537 for gpio_bit in range(0, num_gpios):
538 yield gpio_pad_in[gpio_bit].eq((gpio_i_val >> gpio_bit) & 0x1)
539 yield
540 # After changing the gpio0/1/2/3 inputs,
541 # the output is also going to change.
542 # *therefore it must be read again* to get the
543 # snapshot (as a python value)
544 for gpio_bit in range(0, num_gpios):
545 pad_out[gpio_bit] = yield gpio_pad_out[gpio_bit]
546 yield
547 for gpio_bit in range(0, num_gpios):
548 # check core and pad in
549 gpio_i_ro = yield dut.gpio_i_ro[gpio_bit]
550 out_test_bit = ((gpio_o_val & (1 << gpio_bit)) != 0)
551 in_bit = ((gpio_i_val & (1 << gpio_bit)) != 0)
552 # Check that the core end input matches pad
553 assert in_bit == gpio_i_ro
554 # Test that the output at pad matches:
555 # Pad output == given test output XOR test input
556 assert (out_test_bit ^ in_bit) == pad_out[gpio_bit]
557
558 # For debugging - VERY verbose
559 #print("---------------------")
560 #print("Test Out: ", bin(gpio_o_val))
561 #print("Test Input: ", bin(gpio_i_val))
562 # Print MSB first
563 #print("Pad Output: ", list(reversed(pad_out)))
564 #print("---------------------")
565
566 # For-loop for testing output enable signals
567 for gpio_o_val in range(0, num_gpio_o_states):
568 yield dut.gpio_oe_test.eq(gpio_o_val)
569 yield # Move to the next clk cycle
570
571 for gpio_bit in range(0, num_gpios):
572 pad_oe[gpio_bit] = yield gpio_pad_oe[gpio_bit]
573 yield
574
575 for gpio_bit in range(0, num_gpios):
576 oe_test_bit = ((gpio_o_val & (1 << gpio_bit)) != 0)
577 # oe set at core matches oe seen at pad:
578 assert oe_test_bit == pad_oe[gpio_bit]
579 # For debugging - VERY verbose
580 #print("---------------------")
581 #print("Test Output Enable: ", bin(gpio_o_val))
582 # Print MSB first
583 #print("Pad Output Enable: ", list(reversed(pad_oe)))
584 #print("---------------------")
585
586 # Reset test ouput register
587 yield dut.gpio_o_test.eq(0)
588 print("GPIO Test PASSED!")
589
590 def test_uart(dut):
591 # grab the JTAG resource pad
592 print ()
593 print ("bs pad keys", dut.jtag.boundary_scan_pads.keys())
594 print ()
595 uart_rx_pad = dut.jtag.boundary_scan_pads['uart_0__rx']['i']
596 uart_tx_pad = dut.jtag.boundary_scan_pads['uart_0__tx']['o']
597
598 print ("uart rx pad", uart_rx_pad)
599 print ("uart tx pad", uart_tx_pad)
600
601 # Test UART by writing 0 and 1 to RX
602 # Internally TX connected to RX,
603 # so match pad TX with RX
604 for i in range(0, 2):
605 yield uart_rx_pad.eq(i)
606 #yield uart_rx_pad.eq(i)
607 yield Settle()
608 yield # one clock cycle
609 tx_val = yield uart_tx_pad
610 print ("xmit uart", tx_val, 1)
611 assert tx_val == i
612
613 print("UART Test PASSED!")
614
615 def test_i2c(dut):
616 i2c_sda_i_pad = dut.jtag.boundary_scan_pads['i2c_0__sda__i']['i']
617 i2c_sda_o_pad = dut.jtag.boundary_scan_pads['i2c_0__sda__o']['o']
618 i2c_sda_oe_pad = dut.jtag.boundary_scan_pads['i2c_0__sda__oe']['o']
619
620 i2c_scl_i_pad = dut.jtag.boundary_scan_pads['i2c_0__scl__i']['i']
621 i2c_scl_o_pad = dut.jtag.boundary_scan_pads['i2c_0__scl__o']['o']
622 i2c_scl_oe_pad = dut.jtag.boundary_scan_pads['i2c_0__scl__oe']['o']
623
624 #i2c_pad = dut.jtag.resource_table_pads[('i2c', 0)]
625 #print ("i2c pad", i2c_pad)
626 #print ("i2c pad", i2c_pad.layout)
627
628 for i in range(0, 2):
629 yield i2c_sda_i_pad.eq(i) #i2c_pad.sda.i.eq(i)
630 yield i2c_scl_i_pad.eq(i) #i2c_pad.scl.i.eq(i)
631 yield dut.i2c_sda_oe_test.eq(i)
632 yield dut.i2c_scl_oe_test.eq(i)
633 yield Settle()
634 yield # one clock cycle
635 sda_o_val = yield i2c_sda_o_pad
636 scl_o_val = yield i2c_scl_o_pad
637 sda_oe_val = yield i2c_sda_oe_pad
638 scl_oe_val = yield i2c_scl_oe_pad
639 print ("Test input: ", i, " SDA/SCL out: ", sda_o_val, scl_o_val,
640 " SDA/SCL oe: ", sda_oe_val, scl_oe_val)
641 assert sda_o_val == i
642 assert scl_o_val == i
643 assert sda_oe_val == i
644 assert scl_oe_val == i
645
646 print("I2C Test PASSED!")
647
648 # JTAG boundary scan reg addresses - See c4m/nmigen/jtag/tap.py line #357
649 BS_EXTEST = 0
650 BS_INTEST = 0
651 BS_SAMPLE = 2
652 BS_PRELOAD = 2
653 def test_jtag_bs_chain(dut):
654 #print(dir(dut.jtag))
655 #print(dir(dut))
656 print("JTAG BS Reset")
657 yield from jtag_set_reset(dut.jtag)
658
659 #print("JTAG I/O dictionary of core/pad signals:")
660 #print(dut.jtag.ios.keys())
661 # Based on number of ios entries, produce a test shift reg pattern - TODO
662 bslen = len(dut.jtag.ios)
663 bsdata = 2**bslen - 1 # Fill with all 1s for now
664 fulldata = bsdata # for testing
665 emptydata = 0 # for testing
666
667 # TODO: make into a loop for future expansion
668 # All pad input signals to drive and output via TDO
669 i2c_sda_i_pad = dut.jtag.boundary_scan_pads['i2c_0__sda__i']['i']
670 i2c_scl_i_pad = dut.jtag.boundary_scan_pads['i2c_0__scl__i']['i']
671 uart_rx_pad = dut.jtag.boundary_scan_pads['uart_0__rx']['i']
672 gpio0_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio0__i']['i']
673 gpio1_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio1__i']['i']
674 gpio2_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio2__i']['i']
675 gpio3_pad_in = dut.jtag.boundary_scan_pads['gpio_0__gpio3__i']['i']
676
677 # Assert all for now
678 #yield i2c_sda_i_pad.eq(1)
679 #yield i2c_scl_i_pad.eq(1)
680 #yield uart_rx_pad.eq(1)
681 #yield gpio0_pad_in.eq(1)
682 #yield gpio1_pad_in.eq(1)
683 #yield gpio2_pad_in.eq(1)
684 #yield gpio3_pad_in.eq(1)
685
686 mask_inputs = produce_ios_io_mask(dut, is_input=True)
687 mask_outputs = produce_ios_io_mask(dut, is_input=False)
688 # TODO: make format based on bslen
689 print("Input Mask: {0:20b}".format(mask_inputs))
690 print("Output Mask: {0:20b}".format(mask_outputs))
691
692 print("All pad inputs/core outputs reset, bs data all set")
693 print("Sending TDI data with core/pads disconnected")
694 result = yield from jtag_read_write_reg(dut.jtag, BS_EXTEST, bslen,
695 bsdata)
696 print("TDI BS Data: {0:b}, Data Length (bits): {1}"
697 .format(bsdata, bslen))
698 print("TDO BS Data: {0:b}".format(result))
699 yield from check_ios_keys(dut, mask_outputs)
700
701 # Reset shift register between tests
702 yield from jtag_set_reset(dut.jtag)
703
704 print("Sending TDI data with core/pads connected")
705 result = yield from jtag_read_write_reg(dut.jtag, BS_SAMPLE, bslen,
706 bsdata)
707 print("TDI BS Data: {0:b}, Data Length (bits): {1}"
708 .format(bsdata, bslen))
709 print("TDO BS Data: {0:b}".format(result))
710 yield from check_ios_keys(dut, emptydata)
711
712 # Reset shift register between tests
713 yield from jtag_set_reset(dut.jtag)
714
715 print("All pad inputs/core outputs set, bs data clear")
716 bsdata = 0 # clear, as all input already asserted
717 # Run through GPIO, UART, and I2C tests so that all signals are asserted
718 yield from test_gpios(dut)
719 yield from test_uart(dut)
720 yield from test_i2c(dut)
721
722 print("Sending TDI data with core/pads disconnected")
723 result = yield from jtag_read_write_reg(dut.jtag, BS_EXTEST, bslen,
724 bsdata)
725 print("TDI BS Data: {0:b}, Data Length (bits): {1}"
726 .format(bsdata, bslen))
727 print("TDO BS Data: {0:b}".format(result))
728 #yield from check_ios_keys(dut, fulldata)
729
730 # Reset shift register between tests
731 yield from jtag_set_reset(dut.jtag)
732
733 print("Sending TDI data with core/pads connected")
734 result = yield from jtag_read_write_reg(dut.jtag, BS_SAMPLE, bslen,
735 bsdata)
736 print("TDI BS Data: {0:b}, Data Length (bits): {1}"
737 .format(bsdata, bslen))
738 print("TDO BS Data: {0:b}".format(result))
739 yield from check_ios_keys(dut, fulldata)
740
741 # Reset shift register between tests
742 yield from jtag_set_reset(dut.jtag)
743
744 print("JTAG Boundary Scan Chain Test PASSED!")
745
746 #yield from print_all_ios_keys(dut)
747
748 def check_ios_keys(dut, test_vector):
749 print("Checking ios signals with given test vector")
750 bslen = len(dut.jtag.ios)
751 ios_keys = list(dut.jtag.ios.keys())
752 for i in range(0, bslen):
753 signal = ios_keys[i]
754 test_value = (test_vector >> i) & 0b1
755 # Check if outputs are asserted
756 if ('__o' in ios_keys[i]) or ('__tx' in ios_keys[i]):
757 temp_result = yield dut.jtag.boundary_scan_pads[signal]['o']
758 print("Core Output | Name: ", signal, " Value: ", temp_result)
759 else:
760 temp_result = yield dut.jtag.boundary_scan_pads[signal]['i']
761 print("Pad Input | Name: ", signal, " Value: ", temp_result)
762 assert temp_result == test_value
763
764 def produce_ios_io_mask(dut, is_input=False):
765 if is_input:
766 mask_type = "input"
767 else:
768 mask_type = "output"
769 print("Determine the", mask_type, "mask")
770 bslen = len(dut.jtag.ios)
771 ios_keys = list(dut.jtag.ios.keys())
772 mask = 0
773 for i in range(0, bslen):
774 signal = ios_keys[i]
775 if (('__o' in ios_keys[i]) or ('__tx' in ios_keys[i])):
776 if is_input == False:
777 mask += (1 << i)
778 else:
779 if is_input == True:
780 mask += (1 << i)
781 return mask
782
783 def print_all_ios_keys(dut):
784 print("Print all ios keys")
785 bslen = len(dut.jtag.ios)
786 ios_keys = list(dut.jtag.ios.keys())
787 for i in range(0, bslen):
788 signal = ios_keys[i]
789 # Check if outputs are asserted
790 if ('__o' in ios_keys[i]) or ('__tx' in ios_keys[i]):
791 print("Core Output | Name: ", signal)
792 else:
793 print("Pad Input | Name: ", signal)
794
795
796
797 # Copied from test_jtag_tap.py
798 # JTAG-ircodes for accessing DMI
799 DMI_ADDR = 5
800 DMI_READ = 6
801 DMI_WRRD = 7
802
803 # JTAG-ircodes for accessing Wishbone
804 WB_ADDR = 8
805 WB_READ = 9
806 WB_WRRD = 10
807
808 def test_jtag_dmi_wb():
809 print(dir(top.jtag))
810 print(dir(top))
811 print("JTAG BS Reset")
812 yield from jtag_set_reset(top.jtag)
813
814 print("JTAG I/O dictionary of core/pad signals:")
815 print(top.jtag.ios.keys())
816
817 # Copied from test_jtag_tap
818 # Don't know if the ID is the same for all JTAG instances
819 ####### JTAGy stuff (IDCODE) ######
820
821 # read idcode
822 idcode = yield from jtag_read_write_reg(top.jtag, 0b1, 32)
823 print ("idcode", hex(idcode))
824 assert idcode == 0x18ff
825
826 ####### JTAG to DMI ######
827
828 # write DMI address
829 yield from jtag_read_write_reg(top.jtag, DMI_ADDR, 8, DBGCore.CTRL)
830
831 # read DMI CTRL register
832 status = yield from jtag_read_write_reg(top.jtag, DMI_READ, 64)
833 print ("dmi ctrl status", hex(status))
834 #assert status == 4
835
836 # write DMI address
837 yield from jtag_read_write_reg(top.jtag, DMI_ADDR, 8, 0)
838
839 # write DMI CTRL register
840 status = yield from jtag_read_write_reg(top.jtag, DMI_WRRD, 64, 0b101)
841 print ("dmi ctrl status", hex(status))
842 #assert status == 4 # returned old value (nice! cool feature!)
843
844 # write DMI address
845 yield from jtag_read_write_reg(top.jtag, DMI_ADDR, 8, DBGCore.CTRL)
846
847 # read DMI CTRL register
848 status = yield from jtag_read_write_reg(top.jtag, DMI_READ, 64)
849 print ("dmi ctrl status", hex(status))
850 #assert status == 6
851
852 # write DMI MSR address
853 yield from jtag_read_write_reg(top.jtag, DMI_ADDR, 8, DBGCore.MSR)
854
855 # read DMI MSR register
856 msr = yield from jtag_read_write_reg(top.jtag, DMI_READ, 64)
857 print ("dmi msr", hex(msr))
858 #assert msr == 0xdeadbeef
859
860 ####### JTAG to Wishbone ######
861
862 # write Wishbone address
863 yield from jtag_read_write_reg(top.jtag, WB_ADDR, 16, 0x18)
864
865 # write/read wishbone data
866 data = yield from jtag_read_write_reg(top.jtag, WB_WRRD, 16, 0xfeef)
867 print ("wb write", hex(data))
868
869 # write Wishbone address
870 yield from jtag_read_write_reg(top.jtag, WB_ADDR, 16, 0x18)
871
872 # write/read wishbone data
873 data = yield from jtag_read_write_reg(top.jtag, WB_READ, 16, 0)
874 print ("wb read", hex(data))
875
876 ####### done - tell dmi_sim to stop (otherwise it won't) ########
877
878 top.jtag.stop = True
879
880 def test_debug_print(dut):
881 print("Test used for getting object methods/information")
882 print("Moved here to clear clutter of gpio test")
883
884 print ("printing out info about the resource gpio0")
885 print (dut.gpio['gpio0']['i'])
886 print ("this is a PIN resource", type(dut.gpio['gpio0']['i']))
887 # yield can only be done on SIGNALS or RECORDS,
888 # NOT Pins/Resources gpio0_core_in = yield top.gpio['gpio0']['i']
889 #print("Test gpio0 core in: ", gpio0_core_in)
890
891 print("JTAG")
892 print(dut.jtag.__class__.__name__, dir(dut.jtag))
893 print("TOP")
894 print(dut.__class__.__name__, dir(dut))
895 print("PORT")
896 print(dut.ports.__class__.__name__, dir(dut.ports))
897 print("GPIO")
898 print(dut.gpio.__class__.__name__, dir(dut.gpio))
899
900 print("UART")
901 print(dir(dut.jtag.boundary_scan_pads['uart_0__rx__pad__i']))
902 print(dut.jtag.boundary_scan_pads['uart_0__rx__pad__i'].keys())
903 print(dut.jtag.boundary_scan_pads['uart_0__tx__pad__o'])
904 #print(type(dut.jtag.boundary_scan_pads['uart_0__rx__pad__i']['rx']))
905 print ("jtag pad table keys")
906 print (dut.jtag.resource_table_pads.keys())
907 print(type(dut.jtag.resource_table_pads[('uart', 0)].rx.i))
908 print(dut.jtag.boundary_scan_pads['uart_0__rx__i'])
909
910 print("I2C")
911 print(dut.jtag.boundary_scan_pads['i2c_0__sda__i'])
912 print(type(dut.jtag.boundary_scan_pads['i2c_0__sda__i']['i']))
913
914 print(dut.jtag.resource_table_pads)
915 print(dut.jtag.boundary_scan_pads)
916
917
918 # Trying to read input from core side, looks like might be a pin...
919 # XXX don't "look like" - don't guess - *print it out*
920 #print ("don't guess, CHECK", type(top.gpio.gpio0.i))
921
922 print () # extra print to divide the output
923 yield
924
925 def setup_blinker(build_blinker=False):
926 """
927 and to create a Platform instance with that list, and build
928 something random
929
930 p=Platform()
931 p.resources=listofstuff
932 p.build(Blinker())
933 """
934
935 pinset = dummy_pinset()
936 print(pinset)
937 resources = create_resources(pinset)
938 top = Blinker(pinset, resources, no_jtag_connect=False)#True)
939
940 vl = rtlil.convert(top, ports=top.ports())
941 with open("test_jtag_blinker.il", "w") as f:
942 f.write(vl)
943
944 if build_blinker:
945 # XXX these modules are all being added *AFTER* the build process links
946 # everything together. the expectation that this would work is...
947 # unrealistic. ordering, clearly, is important.
948
949 # This JTAG code copied from test, probably not needed
950 # dut = JTAG(test_pinset(), wb_data_wid=64, domain="sync")
951 top.jtag.stop = False
952 # rather than the client access the JTAG bus directly
953 # create an alternative that the client sets
954 class Dummy: pass
955 cdut = Dummy()
956 cdut.cbus = JTAGInterface()
957
958 # set up client-server on port 44843-something
959 top.jtag.s = JTAGServer()
960 cdut.c = JTAGClient()
961 top.jtag.s.get_connection()
962 #else:
963 # print ("running server only as requested,
964 # use openocd remote to test")
965 # sys.stdout.flush()
966 # top.jtag.s.get_connection(None) # block waiting for connection
967
968 # take copy of ir_width and scan_len
969 cdut._ir_width = top.jtag._ir_width
970 cdut.scan_len = top.jtag.scan_len
971
972 p = ASICPlatform (resources, top.jtag)
973 p.build(top)
974 # this is what needs to gets treated as "top", after "main module" top
975 # is augmented with IO pads with JTAG tacked on. the expectation that
976 # the get_input() etc functions will be called magically by some other
977 # function is unrealistic.
978 top_fragment = p.fragment
979
980 return top
981
982 def test_jtag():
983 dut = setup_blinker(build_blinker=False)
984
985 # XXX simulating top (the module that does not itself contain IO pads
986 # because that's covered by build) cannot possibly be expected to work
987 # particularly when modules have been added *after* the platform build()
988 # function has been called.
989
990 sim = Simulator(dut)
991 sim.add_clock(1e-6, domain="sync") # standard clock
992
993 #sim.add_sync_process(wrap(jtag_srv(top))) #? jtag server
994 #if len(sys.argv) != 2 or sys.argv[1] != 'server':
995 # actual jtag tester
996 #sim.add_sync_process(wrap(jtag_sim(cdut, top.jtag)))
997 # handles (pretends to be) DMI
998 #sim.add_sync_process(wrap(dmi_sim(top.jtag)))
999
1000 #sim.add_sync_process(wrap(test_gpios(top)))
1001 #sim.add_sync_process(wrap(test_uart(top)))
1002 #sim.add_sync_process(wrap(test_i2c(top)))
1003 #sim.add_sync_process(wrap(test_debug_print()))
1004
1005 sim.add_sync_process(wrap(test_jtag_bs_chain(dut)))
1006
1007 with sim.write_vcd("blinker_test.vcd"):
1008 sim.run()
1009
1010 if __name__ == '__main__':
1011 test_jtag()