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