get access to jtag boundary scan pads for uart_0_tx/rx
[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 c4m.nmigen.jtag.tap import TAP, IOType
29 from c4m.nmigen.jtag.bus import Interface as JTAGInterface
30 #from soc.debug.dmi import DMIInterface, DBGCore
31 #from soc.debug.test.dmi_sim import dmi_sim
32 #from soc.debug.test.jtagremote import JTAGServer, JTAGClient
33 from nmigen.build.res import ResourceError
34
35 # Was thinking of using these functions, but skipped for simplicity for now
36 # XXX nope. the output from JSON file.
37 #from pinfunctions import (i2s, lpc, emmc, sdmmc, mspi, mquadspi, spi,
38 # quadspi, i2c, mi2c, jtag, uart, uartfull, rgbttl, ulpi, rgmii, flexbus1,
39 # flexbus2, sdram1, sdram2, sdram3, vss, vdd, sys, eint, pwm, gpio)
40
41 # File for stage 1 pinmux tested proposed by Luke,
42 # https://bugs.libre-soc.org/show_bug.cgi?id=50#c10
43
44
45 def dummy_pinset():
46 # sigh this needs to come from pinmux.
47 gpios = []
48 for i in range(4):
49 gpios.append("%d*" % i)
50 return {'uart': ['tx+', 'rx-'],
51 'gpio': gpios,
52 #'jtag': ['tms-', 'tdi-', 'tdo+', 'tck+'],
53 'i2c': ['sda*', 'scl+']}
54
55 """
56 a function is needed which turns the results of dummy_pinset()
57 into:
58
59 [UARTResource("uart", 0, tx=..., rx=..),
60 I2CResource("i2c", 0, scl=..., sda=...),
61 Resource("gpio", 0, Subsignal("i"...), Subsignal("o"...)
62 Resource("gpio", 1, Subsignal("i"...), Subsignal("o"...)
63 ...
64 ]
65 """
66
67
68 def create_resources(pinset):
69 resources = []
70 for periph, pins in pinset.items():
71 print(periph, pins)
72 if periph == 'i2c':
73 #print("I2C required!")
74 resources.append(I2CResource('i2c', 0, sda='sda', scl='scl'))
75 elif periph == 'uart':
76 #print("UART required!")
77 resources.append(UARTResource('uart', 0, tx='tx', rx='rx'))
78 elif periph == 'gpio':
79 #print("GPIO required!")
80 print ("GPIO is defined as '*' type, meaning i, o and oe needed")
81 ios = []
82 for pin in pins:
83 pname = "gpio"+pin[:-1] # strip "*" on end
84 # urrrr... tristsate and io assume a single pin which is
85 # of course exactly what we don't want in an ASIC: we want
86 # *all three* pins but the damn port is not outputted
87 # as a triplet, it's a single Record named "io". sigh.
88 # therefore the only way to get a triplet of i/o/oe
89 # is to *actually* create explicit triple pins
90 # XXX ARRRGH, doesn't work
91 #pad = Subsignal("io",
92 # Pins("%s_i %s_o %s_oe" % (pname, pname, pname),
93 # dir="io", assert_width=3))
94 #ios.append(Resource(pname, 0, pad))
95 pads = []
96 pads.append(Subsignal("i",
97 Pins(pname+"_i", dir="i", assert_width=1)))
98 pads.append(Subsignal("o",
99 Pins(pname+"_o", dir="o", assert_width=1)))
100 pads.append(Subsignal("oe",
101 Pins(pname+"_oe", dir="o", assert_width=1)))
102 ios.append(Resource.family(pname, 0, default_name=pname,
103 ios=pads))
104 resources.append(Resource.family(periph, 0, default_name="gpio",
105 ios=ios))
106
107 # add clock and reset
108 clk = Resource("clk", 0, Pins("sys_clk", dir="i"))
109 rst = Resource("rst", 0, Pins("sys_rst", dir="i"))
110 resources.append(clk)
111 resources.append(rst)
112 return resources
113
114
115 def JTAGResource(*args):
116 io = []
117 io.append(Subsignal("tms", Pins("tms", dir="i", assert_width=1)))
118 io.append(Subsignal("tdi", Pins("tdi", dir="i", assert_width=1)))
119 io.append(Subsignal("tck", Pins("tck", dir="i", assert_width=1)))
120 io.append(Subsignal("tdo", Pins("tdo", dir="o", assert_width=1)))
121 return Resource.family(*args, default_name="jtag", ios=io)
122
123 def UARTResource(*args, rx, tx):
124 io = []
125 io.append(Subsignal("rx", Pins(rx, dir="i", assert_width=1)))
126 io.append(Subsignal("tx", Pins(tx, dir="o", assert_width=1)))
127 return Resource.family(*args, default_name="uart", ios=io)
128
129
130 def I2CResource(*args, scl, sda):
131 ios = []
132 pads = []
133 pads.append(Subsignal("i", Pins(sda+"_i", dir="i", assert_width=1)))
134 pads.append(Subsignal("o", Pins(sda+"_o", dir="o", assert_width=1)))
135 pads.append(Subsignal("oe", Pins(sda+"_oe", dir="o", assert_width=1)))
136 ios.append(Resource.family(sda, 0, default_name=sda, ios=pads))
137 pads = []
138 pads.append(Subsignal("i", Pins(scl+"_i", dir="i", assert_width=1)))
139 pads.append(Subsignal("o", Pins(scl+"_o", dir="o", assert_width=1)))
140 pads.append(Subsignal("oe", Pins(scl+"_oe", dir="o", assert_width=1)))
141 ios.append(Resource.family(scl, 0, default_name=scl, ios=pads))
142 return Resource.family(*args, default_name="i2c", ios=ios)
143
144
145 # top-level demo module.
146 class Blinker(Elaboratable):
147 def __init__(self, pinset, resources, no_jtag_connect=False):
148 self.no_jtag_connect = no_jtag_connect
149 self.jtag = JTAG({}, "sync", resources=resources)
150 #memory = Memory(width=32, depth=16)
151 #self.sram = SRAM(memory=memory, bus=self.jtag.wb)
152
153 def elaborate(self, platform):
154 jtag_resources = self.jtag.pad_mgr.resources
155 m = Module()
156 m.submodules.jtag = self.jtag
157 #m.submodules.sram = self.sram
158
159 #count = Signal(5)
160 #m.d.sync += count.eq(count+1)
161 print ("resources", platform, jtag_resources.items())
162 gpio = self.jtag.request('gpio')
163 print (gpio, gpio.layout, gpio.fields)
164 # get the GPIO bank, mess about with some of the pins
165 #m.d.comb += gpio.gpio0.o.eq(1)
166 #m.d.comb += gpio.gpio1.o.eq(gpio.gpio2.i)
167 #m.d.comb += gpio.gpio1.oe.eq(count[4])
168 #m.d.sync += count[0].eq(gpio.gpio1.i)
169
170 num_gpios = 4
171 gpio_i_ro = Signal(num_gpios)
172 gpio_o_test = Signal(num_gpios)
173 gpio_oe_test = Signal(num_gpios)
174
175 # Create a read-only copy of core-side GPIO input signals
176 # for Simulation asserts
177 m.d.comb += gpio_i_ro[0].eq(gpio.gpio0.i)
178 m.d.comb += gpio_i_ro[1].eq(gpio.gpio1.i)
179 m.d.comb += gpio_i_ro[2].eq(gpio.gpio2.i)
180 m.d.comb += gpio_i_ro[3].eq(gpio.gpio3.i)
181
182 # Wire up the output signal of each gpio by XOR'ing each bit of
183 # gpio_o_test with gpio's input
184 # Wire up each bit of gpio_oe_test signal to oe signal of each gpio.
185 # Turn into a loop at some point, probably a way without
186 # using get_attr()
187 m.d.comb += gpio.gpio0.o.eq(gpio_o_test[0] ^ gpio.gpio0.i)
188 m.d.comb += gpio.gpio1.o.eq(gpio_o_test[1] ^ gpio.gpio1.i)
189 m.d.comb += gpio.gpio2.o.eq(gpio_o_test[2] ^ gpio.gpio2.i)
190 m.d.comb += gpio.gpio3.o.eq(gpio_o_test[3] ^ gpio.gpio3.i)
191
192 m.d.comb += gpio.gpio0.oe.eq(gpio_oe_test[0])
193 m.d.comb += gpio.gpio1.oe.eq(gpio_oe_test[1])
194 m.d.comb += gpio.gpio2.oe.eq(gpio_oe_test[2])
195 m.d.comb += gpio.gpio3.oe.eq(gpio_oe_test[3])
196
197 # get the UART resource, mess with the output tx
198 uart = self.jtag.request('uart')
199 print ("uart fields", uart, uart.fields)
200 self.intermediary = Signal()
201 m.d.comb += uart.tx.eq(self.intermediary)
202 m.d.comb += self.intermediary.eq(uart.rx)
203
204 # I2C
205 num_i2c = 1
206 i2c_sda_oe_test = Signal(num_i2c)
207 i2c_scl_oe_test = Signal(num_i2c)
208 i2c = self.jtag.request('i2c')
209 print ("i2c fields", i2c, i2c.fields)
210 # Connect in loopback
211 m.d.comb += i2c.scl.o.eq(i2c.scl.i)
212 m.d.comb += i2c.sda.o.eq(i2c.sda.i)
213 # Connect output enable to test port for sim
214 m.d.comb += i2c.sda.oe.eq(i2c_sda_oe_test)
215 m.d.comb += i2c.scl.oe.eq(i2c_scl_oe_test)
216
217 # to even be able to get at objects, you first have to make them
218 # available - i.e. not as local variables
219 # Public attributes are equivalent to input/output ports in hdl's
220 self.gpio = gpio
221 self.uart = uart
222 self.i2c = i2c
223 self.i2c_sda_oe_test = i2c_sda_oe_test
224 self.i2c_scl_oe_test = i2c_scl_oe_test
225 self.gpio_i_ro = gpio_i_ro
226 self.gpio_o_test = gpio_o_test
227 self.gpio_oe_test = gpio_oe_test
228
229 # sigh these wire up to the pads so you cannot set Signals
230 # that are already wired
231 if self.no_jtag_connect: # bypass jtag pad connect for testing purposes
232 return m
233 return self.jtag.boundary_elaborate(m, platform)
234
235 def ports(self):
236 return list(self)
237
238 def __iter__(self):
239 yield from self.jtag.iter_ports()
240
241 '''
242 _trellis_command_templates = [
243 r"""
244 {{invoke_tool("yosys")}}
245 {{quiet("-q")}}
246 {{get_override("yosys_opts")|options}}
247 -l {{name}}.rpt
248 {{name}}.ys
249 """,
250 ]
251 '''
252
253 # sigh, have to create a dummy platform for now.
254 # TODO: investigate how the heck to get it to output ilang. or verilog.
255 # or, anything, really. but at least it doesn't barf
256 class ASICPlatform(TemplatedPlatform):
257 connectors = []
258 resources = OrderedDict()
259 required_tools = []
260 command_templates = ['/bin/true'] # no command needed: stops barfing
261 file_templates = {
262 **TemplatedPlatform.build_script_templates,
263 "{{name}}.il": r"""
264 # {{autogenerated}}
265 {{emit_rtlil()}}
266 """,
267 "{{name}}.debug.v": r"""
268 /* {{autogenerated}} */
269 {{emit_debug_verilog()}}
270 """,
271 }
272 toolchain = None
273 default_clk = "clk" # should be picked up / overridden by platform sys.clk
274 default_rst = "rst" # should be picked up / overridden by platform sys.rst
275
276 def __init__(self, resources, jtag):
277 self.jtag = jtag
278 super().__init__()
279
280 # create set of pin resources based on the pinset, this is for the core
281 #jtag_resources = self.jtag.pad_mgr.resources
282 self.add_resources(resources)
283
284 # add JTAG without scan
285 self.add_resources([JTAGResource('jtag', 0)], no_boundary_scan=True)
286
287 def add_resources(self, resources, no_boundary_scan=False):
288 print ("ASICPlatform add_resources", resources)
289 return super().add_resources(resources)
290
291 #def iter_ports(self):
292 # yield from super().iter_ports()
293 # for io in self.jtag.ios.values():
294 # print ("iter ports", io.layout, io)
295 # for field in io.core.fields:
296 # yield getattr(io.core, field)
297 # for field in io.pad.fields:
298 # yield getattr(io.pad, field)
299
300 # XXX these aren't strictly necessary right now but the next
301 # phase is to add JTAG Boundary Scan so it maaay be worth adding?
302 # at least for the print statements
303 def get_input(self, pin, port, attrs, invert):
304 self._check_feature("single-ended input", pin, attrs,
305 valid_xdrs=(0,), valid_attrs=None)
306
307 m = Module()
308 print (" get_input", pin, "port", port, port.layout)
309 m.d.comb += pin.i.eq(self._invert_if(invert, port))
310 return m
311
312 def get_output(self, pin, port, attrs, invert):
313 self._check_feature("single-ended output", pin, attrs,
314 valid_xdrs=(0,), valid_attrs=None)
315
316 m = Module()
317 print (" get_output", pin, "port", port, port.layout)
318 m.d.comb += port.eq(self._invert_if(invert, pin.o))
319 return m
320
321 def get_tristate(self, pin, port, attrs, invert):
322 self._check_feature("single-ended tristate", pin, attrs,
323 valid_xdrs=(0,), valid_attrs=None)
324
325 print (" get_tristate", pin, "port", port, port.layout)
326 m = Module()
327 print (" pad", pin, port, attrs)
328 print (" pin", pin.layout)
329 return m
330 # m.submodules += Instance("$tribuf",
331 # p_WIDTH=pin.width,
332 # i_EN=pin.oe,
333 # i_A=self._invert_if(invert, pin.o),
334 # o_Y=port,
335 # )
336 m.d.comb += io.core.o.eq(pin.o)
337 m.d.comb += io.core.oe.eq(pin.oe)
338 m.d.comb += pin.i.eq(io.core.i)
339 m.d.comb += io.pad.i.eq(port.i)
340 m.d.comb += port.o.eq(io.pad.o)
341 m.d.comb += port.oe.eq(io.pad.oe)
342 return m
343
344 def get_input_output(self, pin, port, attrs, invert):
345 self._check_feature("single-ended input/output", pin, attrs,
346 valid_xdrs=(0,), valid_attrs=None)
347
348 print (" get_input_output", pin, "port", port, port.layout)
349 m = Module()
350 print (" port layout", port.layout)
351 print (" pin", pin)
352 print (" layout", pin.layout)
353 #m.submodules += Instance("$tribuf",
354 # p_WIDTH=pin.width,
355 # i_EN=io.pad.oe,
356 # i_A=self._invert_if(invert, io.pad.o),
357 # o_Y=port,
358 #)
359 # Create aliases for the port sub-signals
360 port_i = port.io[0]
361 port_o = port.io[1]
362 port_oe = port.io[2]
363
364 m.d.comb += pin.i.eq(self._invert_if(invert, port_i))
365 m.d.comb += port_o.eq(self._invert_if(invert, pin.o))
366 m.d.comb += port_oe.eq(pin.oe)
367
368 return m
369
370 def toolchain_prepare(self, fragment, name, **kwargs):
371 """override toolchain_prepare in order to grab the fragment
372 """
373 self.fragment = fragment
374 return super().toolchain_prepare(fragment, name, **kwargs)
375
376
377
378 def test_case0():
379 print("Starting sanity test case!")
380 print("printing out list of stuff in top")
381 print ("JTAG IOs", top.jtag.ios)
382 # ok top now has a variable named "gpio", let's enumerate that too
383 print("printing out list of stuff in top.gpio and its type")
384 print(top.gpio.__class__.__name__, dir(top.gpio))
385 # ok, it's a nmigen Record, therefore it has a layout. let's print
386 # that too
387 print("top.gpio is a Record therefore has fields and a layout")
388 print(" layout:", top.gpio.layout)
389 print(" fields:", top.gpio.fields)
390 print("Fun never ends...")
391 print(" layout, gpio2:", top.gpio.layout['gpio2'])
392 print(" fields, gpio2:", top.gpio.fields['gpio2'])
393 print(top.jtag.__class__.__name__, dir(top.jtag))
394 print("Pads:")
395 print(top.jtag.resource_table_pads[('gpio', 0)])
396
397 # etc etc. you get the general idea
398 delayVal = 0.2e-6
399 yield top.uart.rx.eq(0)
400 yield Delay(delayVal)
401 yield Settle()
402 yield top.gpio.gpio2.o.eq(0)
403 yield top.gpio.gpio3.o.eq(1)
404 yield
405 yield top.gpio.gpio3.oe.eq(1)
406 yield
407 yield top.gpio.gpio3.oe.eq(0)
408 # grab the JTAG resource pad
409 gpios_pad = top.jtag.resource_table_pads[('gpio', 0)]
410 yield gpios_pad.gpio3.i.eq(1)
411 yield Delay(delayVal)
412 yield Settle()
413 yield top.gpio.gpio2.oe.eq(1)
414 yield top.gpio.gpio3.oe.eq(1)
415 yield gpios_pad.gpio3.i.eq(0)
416 yield top.jtag.gpio.gpio2.i.eq(1)
417 yield Delay(delayVal)
418 yield Settle()
419 gpio_o2 = 0
420 for _ in range(20):
421 # get a value first (as an integer). you were trying to set
422 # it to the actual Signal. this is not going to work. or if
423 # it does, it's very scary.
424 gpio_o2 = not gpio_o2
425 yield top.gpio.gpio2.o.eq(gpio_o2)
426
427 # ditto: here you are trying to set to an AST expression
428 # which is inadviseable (likely to fail)
429 gpio_o3 = not gpio_o2
430 yield top.gpio.gpio3.o.eq(gpio_o3)
431 yield Delay(delayVal)
432 yield Settle()
433 # grab the JTAG resource pad
434 uart_pad = top.jtag.resource_table_pads[('uart', 0)]
435 yield uart_pad.rx.i.eq(gpio_o2)
436 yield Delay(delayVal)
437 yield Settle()
438 yield # one clock cycle
439 tx_val = yield uart_pad.tx.o
440 print ("xmit uart", tx_val, gpio_o2)
441
442 print ("jtag pad table keys")
443 print (top.jtag.resource_table_pads.keys())
444 uart_pad = top.jtag.resource_table_pads[('uart', 0)]
445 print ("uart pad", uart_pad)
446 print ("uart pad", uart_pad.layout)
447
448 yield top.gpio.gpio2.oe.eq(0)
449 yield top.gpio.gpio3.oe.eq(0)
450 yield top.jtag.gpio.gpio2.i.eq(0)
451 yield Delay(delayVal)
452 yield Settle()
453
454 # Code borrowed from cesar, runs, but shouldn't actually work because of
455 # self. statements and non-existent signal names.
456 def test_case1():
457 print("Example test case")
458 yield Passive()
459 while True:
460 # Settle() is needed to give a quick response to
461 # the zero delay case
462 yield Settle()
463 # wait for rel_o to become active
464 while not (yield self.rel_o):
465 yield
466 yield Settle()
467 # read the transaction parameters
468 assert self.expecting, "an unexpected result was produced"
469 delay = (yield self.delay)
470 expected = (yield self.expected)
471 # wait for `delay` cycles
472 for _ in range(delay):
473 yield
474 # activate go_i for one cycle
475 yield self.go_i.eq(1)
476 yield self.count.eq(self.count + 1)
477 yield
478 # check received data against the expected value
479 result = (yield self.port)
480 assert result == expected,\
481 f"expected {expected}, received {result}"
482 yield self.go_i.eq(0)
483 yield self.port.eq(0)
484
485 def test_gpios():
486 print("Starting GPIO test case!")
487
488 num_gpios = top.gpio_o_test.width
489 # Grab GPIO outpud pad resource from JTAG BS - end of chain
490 print (top.jtag.boundary_scan_pads.keys())
491 gpio0_o = top.jtag.boundary_scan_pads['gpio_0__gpio0__o']['o']
492 gpio1_o = top.jtag.boundary_scan_pads['gpio_0__gpio1__o']['o']
493 gpio2_o = top.jtag.boundary_scan_pads['gpio_0__gpio2__o']['o']
494 gpio3_o = top.jtag.boundary_scan_pads['gpio_0__gpio3__o']['o']
495 gpio_pad_out = [ gpio0_o, gpio1_o, gpio2_o, gpio3_o]
496
497 # Grab GPIO output enable pad resource from JTAG BS - end of chain
498 gpio0_oe = top.jtag.boundary_scan_pads['gpio_0__gpio0__oe']['o']
499 gpio1_oe = top.jtag.boundary_scan_pads['gpio_0__gpio1__oe']['o']
500 gpio2_oe = top.jtag.boundary_scan_pads['gpio_0__gpio2__oe']['o']
501 gpio3_oe = top.jtag.boundary_scan_pads['gpio_0__gpio3__oe']['o']
502 gpio_pad_oe = [gpio0_oe, gpio1_oe, gpio2_oe, gpio3_oe]
503
504 # Grab GPIO input pad resource from JTAG BS - start of chain
505 gpio0_pad_in = top.jtag.boundary_scan_pads['gpio_0__gpio0__i']['i']
506 gpio1_pad_in = top.jtag.boundary_scan_pads['gpio_0__gpio1__i']['i']
507 gpio2_pad_in = top.jtag.boundary_scan_pads['gpio_0__gpio2__i']['i']
508 gpio3_pad_in = top.jtag.boundary_scan_pads['gpio_0__gpio3__i']['i']
509 gpio_pad_in = [gpio0_pad_in, gpio1_pad_in, gpio2_pad_in, gpio3_pad_in]
510
511 # Have the sim run through a for-loop where the gpio_o_test is
512 # incremented like a counter (0000, 0001...)
513 # At each iteration of the for-loop, assert:
514 # + output set at core matches output seen at pad
515 # TODO + input set at pad matches input seen at core
516 # TODO + if gpio_o_test bit is cleared, output seen at pad matches
517 # input seen at pad
518 num_gpio_o_states = num_gpios**2
519 pad_out = [0] * num_gpios
520 pad_oe = [0] * num_gpios
521 #print("Num of permutations of gpio_o_test record: ", num_gpio_o_states)
522 for gpio_o_val in range(0, num_gpio_o_states):
523 yield top.gpio_o_test.eq(gpio_o_val)
524 #yield Settle()
525 yield # Move to the next clk cycle
526
527 # Cycle through all input combinations
528 for gpio_i_val in range(0, num_gpio_o_states):
529 # Set each gpio input at pad to test value
530 for gpio_bit in range(0, num_gpios):
531 yield gpio_pad_in[gpio_bit].eq((gpio_i_val >> gpio_bit) & 0x1)
532 yield
533 # After changing the gpio0/1/2/3 inputs,
534 # the output is also going to change.
535 # *therefore it must be read again* to get the
536 # snapshot (as a python value)
537 for gpio_bit in range(0, num_gpios):
538 pad_out[gpio_bit] = yield gpio_pad_out[gpio_bit]
539 yield
540 for gpio_bit in range(0, num_gpios):
541 # check core and pad in
542 gpio_i_ro = yield top.gpio_i_ro[gpio_bit]
543 out_test_bit = ((gpio_o_val & (1 << gpio_bit)) != 0)
544 in_bit = ((gpio_i_val & (1 << gpio_bit)) != 0)
545 # Check that the core end input matches pad
546 assert in_bit == gpio_i_ro
547 # Test that the output at pad matches:
548 # Pad output == given test output XOR test input
549 assert (out_test_bit ^ in_bit) == pad_out[gpio_bit]
550
551 # For debugging - VERY verbose
552 #print("---------------------")
553 #print("Test Out: ", bin(gpio_o_val))
554 #print("Test Input: ", bin(gpio_i_val))
555 # Print MSB first
556 #print("Pad Output: ", list(reversed(pad_out)))
557 #print("---------------------")
558
559 # For-loop for testing output enable signals
560 for gpio_o_val in range(0, num_gpio_o_states):
561 yield top.gpio_oe_test.eq(gpio_o_val)
562 yield # Move to the next clk cycle
563
564 for gpio_bit in range(0, num_gpios):
565 pad_oe[gpio_bit] = yield gpio_pad_oe[gpio_bit]
566 yield
567
568 for gpio_bit in range(0, num_gpios):
569 oe_test_bit = ((gpio_o_val & (1 << gpio_bit)) != 0)
570 # oe set at core matches oe seen at pad:
571 assert oe_test_bit == pad_oe[gpio_bit]
572 # For debugging - VERY verbose
573 #print("---------------------")
574 #print("Test Output Enable: ", bin(gpio_o_val))
575 # Print MSB first
576 #print("Pad Output Enable: ", list(reversed(pad_oe)))
577 #print("---------------------")
578 print("GPIO Test PASSED!")
579
580 def test_uart():
581 # grab the JTAG resource pad
582 print ()
583 print ("bs pad keys", top.jtag.boundary_scan_pads.keys())
584 print ()
585 uart_rx_pad = top.jtag.boundary_scan_pads['uart_0__rx']['i']
586 uart_tx_pad = top.jtag.boundary_scan_pads['uart_0__tx']['o']
587
588 print ("uart rx pad", uart_rx_pad)
589 print ("uart tx pad", uart_tx_pad)
590
591 # Test UART by writing 0 and 1 to RX
592 # Internally TX connected to RX,
593 # so match pad TX with RX
594 for i in range(0, 2):
595 yield uart_rx_pad.eq(i)
596 #yield uart_rx_pad.eq(i)
597 yield Settle()
598 yield # one clock cycle
599 tx_val = yield uart_tx_pad
600 print ("xmit uart", tx_val, 1)
601 assert tx_val == i
602
603 print("UART Test PASSED!")
604
605 def test_i2c():
606 i2c_sda_i_pad = top.jtag.boundary_scan_pads['i2c_0__sda__i']['i']
607 i2c_sda_o_pad = top.jtag.boundary_scan_pads['i2c_0__sda__o']['o']
608 i2c_sda_oe_pad = top.jtag.boundary_scan_pads['i2c_0__sda__oe']['o']
609
610 i2c_scl_i_pad = top.jtag.boundary_scan_pads['i2c_0__scl__i']['i']
611 i2c_scl_o_pad = top.jtag.boundary_scan_pads['i2c_0__scl__o']['o']
612 i2c_scl_oe_pad = top.jtag.boundary_scan_pads['i2c_0__scl__oe']['o']
613
614 #i2c_pad = top.jtag.resource_table_pads[('i2c', 0)]
615 #print ("i2c pad", i2c_pad)
616 #print ("i2c pad", i2c_pad.layout)
617
618 for i in range(0, 2):
619 yield i2c_sda_i_pad.eq(i) #i2c_pad.sda.i.eq(i)
620 yield i2c_scl_i_pad.eq(i) #i2c_pad.scl.i.eq(i)
621 yield top.i2c_sda_oe_test.eq(i)
622 yield top.i2c_scl_oe_test.eq(i)
623 yield Settle()
624 yield # one clock cycle
625 sda_o_val = yield i2c_sda_o_pad
626 scl_o_val = yield i2c_scl_o_pad
627 sda_oe_val = yield i2c_sda_oe_pad
628 scl_oe_val = yield i2c_scl_oe_pad
629 print ("Test input: ", i, " SDA/SCL out: ", sda_o_val, scl_o_val,
630 " SDA/SCL oe: ", sda_oe_val, scl_oe_val)
631 assert sda_o_val == i
632 assert scl_o_val == i
633 assert sda_oe_val == i
634 assert scl_oe_val == i
635
636 print("I2C Test PASSED!")
637
638
639
640 def test_debug_print():
641 print("Test used for getting object methods/information")
642 print("Moved here to clear clutter of gpio test")
643
644 print ("printing out info about the resource gpio0")
645 print (top.gpio['gpio0']['i'])
646 print ("this is a PIN resource", type(top.gpio['gpio0']['i']))
647 # yield can only be done on SIGNALS or RECORDS,
648 # NOT Pins/Resources gpio0_core_in = yield top.gpio['gpio0']['i']
649 #print("Test gpio0 core in: ", gpio0_core_in)
650
651 print("JTAG")
652 print(top.jtag.__class__.__name__, dir(top.jtag))
653 print("TOP")
654 print(top.__class__.__name__, dir(top))
655 print("PORT")
656 print(top.ports.__class__.__name__, dir(top.ports))
657 print("GPIO")
658 print(top.gpio.__class__.__name__, dir(top.gpio))
659
660 print("UART")
661 print(dir(top.jtag.boundary_scan_pads['uart_0__rx__pad__i']))
662 print(top.jtag.boundary_scan_pads['uart_0__rx__pad__i'].keys())
663 print(top.jtag.boundary_scan_pads['uart_0__tx__pad__o'])
664 #print(type(top.jtag.boundary_scan_pads['uart_0__rx__pad__i']['rx']))
665 print ("jtag pad table keys")
666 print (top.jtag.resource_table_pads.keys())
667 print(type(top.jtag.resource_table_pads[('uart', 0)].rx.i))
668 print(top.jtag.boundary_scan_pads['uart_0__rx__i'])
669
670 print("I2C")
671 print(top.jtag.boundary_scan_pads['i2c_0__sda__i'])
672 print(type(top.jtag.boundary_scan_pads['i2c_0__sda__i']['i']))
673
674 print(top.jtag.resource_table_pads)
675 print(top.jtag.boundary_scan_pads)
676
677
678 # Trying to read input from core side, looks like might be a pin...
679 # XXX don't "look like" - don't guess - *print it out*
680 #print ("don't guess, CHECK", type(top.gpio.gpio0.i))
681
682 print () # extra print to divide the output
683 yield
684
685 if __name__ == '__main__':
686 """
687 and to create a Platform instance with that list, and build
688 something random
689
690 p=Platform()
691 p.resources=listofstuff
692 p.build(Blinker())
693 """
694 pinset = dummy_pinset()
695 print(pinset)
696 resources = create_resources(pinset)
697 top = Blinker(pinset, resources, no_jtag_connect=False)#True)
698
699 vl = rtlil.convert(top, ports=top.ports())
700 with open("test_jtag_blinker.il", "w") as f:
701 f.write(vl)
702
703 if False:
704 # XXX these modules are all being added *AFTER* the build process links
705 # everything together. the expectation that this would work is...
706 # unrealistic. ordering, clearly, is important.
707
708 # dut = JTAG(test_pinset(), wb_data_wid=64, domain="sync")
709 top.jtag.stop = False
710 # rather than the client access the JTAG bus directly
711 # create an alternative that the client sets
712 class Dummy: pass
713 cdut = Dummy()
714 cdut.cbus = JTAGInterface()
715
716 # set up client-server on port 44843-something
717 top.jtag.s = JTAGServer()
718 cdut.c = JTAGClient()
719 top.jtag.s.get_connection()
720 #else:
721 # print ("running server only as requested,
722 # use openocd remote to test")
723 # sys.stdout.flush()
724 # top.jtag.s.get_connection(None) # block waiting for connection
725
726 # take copy of ir_width and scan_len
727 cdut._ir_width = top.jtag._ir_width
728 cdut.scan_len = top.jtag.scan_len
729
730 p = ASICPlatform (resources, top.jtag)
731 p.build(top)
732 # this is what needs to gets treated as "top", after "main module" top
733 # is augmented with IO pads with JTAG tacked on. the expectation that
734 # the get_input() etc functions will be called magically by some other
735 # function is unrealistic.
736 top_fragment = p.fragment
737
738 # XXX simulating top (the module that does not itself contain IO pads
739 # because that's covered by build) cannot possibly be expected to work
740 # particularly when modules have been added *after* the platform build()
741 # function has been called.
742
743 sim = Simulator(top)
744 sim.add_clock(1e-6, domain="sync") # standard clock
745
746 #sim.add_sync_process(wrap(jtag_srv(top))) #? jtag server
747 #if len(sys.argv) != 2 or sys.argv[1] != 'server':
748 # actual jtag tester
749 #sim.add_sync_process(wrap(jtag_sim(cdut, top.jtag)))
750 # handles (pretends to be) DMI
751 #sim.add_sync_process(wrap(dmi_sim(top.jtag)))
752
753 #sim.add_sync_process(wrap(test_case1()))
754 #sim.add_sync_process(wrap(test_case0()))
755
756 #sim.add_sync_process(wrap(test_gpios()))
757 sim.add_sync_process(wrap(test_uart()))
758 sim.add_sync_process(wrap(test_i2c()))
759 #sim.add_sync_process(wrap(test_debug_print()))
760
761 with sim.write_vcd("blinker_test.vcd"):
762 sim.run()