1c747a33a410a42d1532286faedad33c6cc07da4
[pinmux.git] / src / spec / testing_stage1.py
1 #!/usr/bin/env python3
2 from nmigen.build.dsl import Resource, Subsignal, Pins
3 from nmigen.build.plat import TemplatedPlatform
4 from nmigen.build.res import ResourceManager, ResourceError
5 from nmigen import Elaboratable, Signal, Module, Instance
6 from collections import OrderedDict
7 from jtag import JTAG, resiotypes
8 from copy import deepcopy
9 from nmigen.cli import rtlil
10 import sys
11
12 # extra dependencies for jtag testing (?)
13 from soc.bus.sram import SRAM
14
15 from nmigen import Memory
16 from nmigen.sim import Simulator, Delay, Settle, Tick
17
18 from nmutil.util import wrap
19
20 from soc.debug.jtagutils import (jtag_read_write_reg,
21 jtag_srv, jtag_set_reset,
22 jtag_set_ir, jtag_set_get_dr)
23
24 from c4m.nmigen.jtag.tap import TAP, IOType
25 from c4m.nmigen.jtag.bus import Interface as JTAGInterface
26 from soc.debug.dmi import DMIInterface, DBGCore
27 from soc.debug.test.dmi_sim import dmi_sim
28 from soc.debug.test.jtagremote import JTAGServer, JTAGClient
29 from nmigen.build.res import ResourceError
30
31 # Was thinking of using these functions, but skipped for simplicity for now
32 # XXX nope. the output from JSON file.
33 #from pinfunctions import (i2s, lpc, emmc, sdmmc, mspi, mquadspi, spi,
34 # quadspi, i2c, mi2c, jtag, uart, uartfull, rgbttl, ulpi, rgmii, flexbus1,
35 # flexbus2, sdram1, sdram2, sdram3, vss, vdd, sys, eint, pwm, gpio)
36
37 # File for stage 1 pinmux tested proposed by Luke,
38 # https://bugs.libre-soc.org/show_bug.cgi?id=50#c10
39
40
41 def dummy_pinset():
42 # sigh this needs to come from pinmux.
43 gpios = []
44 for i in range(4):
45 gpios.append("%d*" % i)
46 return {'uart': ['tx+', 'rx-'],
47 'gpio': gpios,
48 #'jtag': ['tms-', 'tdi-', 'tdo+', 'tck+'],
49 'i2c': ['sda*', 'scl+']}
50
51 """
52 a function is needed which turns the results of dummy_pinset()
53 into:
54
55 [UARTResource("uart", 0, tx=..., rx=..),
56 I2CResource("i2c", 0, scl=..., sda=...),
57 Resource("gpio", 0, Subsignal("i"...), Subsignal("o"...)
58 Resource("gpio", 1, Subsignal("i"...), Subsignal("o"...)
59 ...
60 ]
61 """
62
63
64 def create_resources(pinset):
65 resources = []
66 for periph, pins in pinset.items():
67 print(periph, pins)
68 if periph == 'i2c':
69 #print("I2C required!")
70 resources.append(I2CResource('i2c', 0, sda='sda', scl='scl'))
71 elif periph == 'uart':
72 #print("UART required!")
73 resources.append(UARTResource('uart', 0, tx='tx', rx='rx'))
74 elif periph == 'gpio':
75 #print("GPIO required!")
76 print ("GPIO is defined as '*' type, meaning i, o and oe needed")
77 ios = []
78 for pin in pins:
79 pname = "gpio"+pin[:-1] # strip "*" on end
80 # urrrr... tristsate and io assume a single pin which is
81 # of course exactly what we don't want in an ASIC: we want
82 # *all three* pins but the damn port is not outputted
83 # as a triplet, it's a single Record named "io". sigh.
84 # therefore the only way to get a triplet of i/o/oe
85 # is to *actually* create explicit triple pins
86 pad = Subsignal("io",
87 Pins("%s_i %s_o %s_oe" % (pname, pname, pname),
88 dir="io", assert_width=3))
89 ios.append(Resource(pname, 0, pad))
90 resources.append(Resource.family(periph, 0, default_name="gpio",
91 ios=ios))
92
93 # add clock and reset
94 clk = Resource("clk", 0, Pins("sys_clk", dir="i"))
95 rst = Resource("rst", 0, Pins("sys_rst", dir="i"))
96 resources.append(clk)
97 resources.append(rst)
98 return resources
99
100
101 def JTAGResource(*args):
102 io = []
103 io.append(Subsignal("tms", Pins("tms", dir="i", assert_width=1)))
104 io.append(Subsignal("tdi", Pins("tdi", dir="i", assert_width=1)))
105 io.append(Subsignal("tck", Pins("tck", dir="i", assert_width=1)))
106 io.append(Subsignal("tdo", Pins("tdo", dir="o", assert_width=1)))
107 return Resource.family(*args, default_name="jtag", ios=io)
108
109 def UARTResource(*args, rx, tx):
110 io = []
111 io.append(Subsignal("rx", Pins(rx, dir="i", assert_width=1)))
112 io.append(Subsignal("tx", Pins(tx, dir="o", assert_width=1)))
113 return Resource.family(*args, default_name="uart", ios=io)
114
115
116 def I2CResource(*args, scl, sda):
117 io = []
118 io.append(Subsignal("scl", Pins(scl, dir="io", assert_width=1)))
119 io.append(Subsignal("sda", Pins(sda, dir="io", assert_width=1)))
120 return Resource.family(*args, default_name="i2c", ios=io)
121
122
123 # ridiculously-simple top-level module. doesn't even have a sync domain
124 # and can't have one until a clock has been established by ASICPlatform.
125 class Blinker(Elaboratable):
126 def __init__(self, pinset, resources):
127 self.jtag = JTAG({}, "sync")
128 self.jtag.pad_mgr = ResourceManager([], [])
129 self.jtag.core_mgr = ResourceManager([], [])
130 self.jtag.pad_mgr.add_resources(resources)
131 self.jtag.core_mgr.add_resources(resources)
132 # record resource lookup between core IO names and pads
133 self.jtag.padlookup = {}
134 self.jtag.requests_made = []
135 self.jtag.boundary_scan_pads = []
136 memory = Memory(width=32, depth=16)
137 self.sram = SRAM(memory=memory, bus=self.jtag.wb)
138
139 def elaborate(self, platform):
140 jtag_resources = self.jtag.pad_mgr.resources
141 core_resources = self.jtag.core_mgr.resources
142 m = Module()
143 m.submodules.jtag = self.jtag
144 m.submodules.sram = self.sram
145
146 count = Signal(5)
147 m.d.sync += count.eq(count+1)
148 print ("resources", platform, jtag_resources.items())
149 gpio = self.jtag_request(m, 'gpio')
150 print (gpio, gpio.layout, gpio.fields)
151 # get the GPIO bank, mess about with some of the pins
152 m.d.comb += gpio.gpio0.io.o.eq(1)
153 m.d.comb += gpio.gpio1.io.o.eq(gpio.gpio2.io.i)
154 m.d.comb += gpio.gpio1.io.oe.eq(count[4])
155 m.d.sync += count[0].eq(gpio.gpio1.io.i)
156 # get the UART resource, mess with the output tx
157 uart = self.jtag_request(m, 'uart')
158 print (uart, uart.fields)
159 intermediary = Signal()
160 m.d.comb += uart.tx.eq(intermediary)
161 m.d.comb += intermediary.eq(uart.rx)
162
163 # platform requested: make the exact same requests,
164 # then add JTAG afterwards
165 if platform is not None:
166 for (name, number, dir, xdr) in self.jtag.requests_made:
167 platform.request(name, number, dir=dir, xdr=xdr)
168
169 # wire up JTAG otherwise we are in trouble (no clock)
170 jtag = platform.request('jtag')
171 m.d.comb += self.jtag.bus.tdi.eq(jtag.tdi)
172 m.d.comb += self.jtag.bus.tck.eq(jtag.tck)
173 m.d.comb += self.jtag.bus.tms.eq(jtag.tms)
174 m.d.comb += jtag.tdo.eq(self.jtag.bus.tdo)
175
176 return m
177
178 def ports(self):
179 return list(self)
180
181 def __iter__(self):
182 yield self.jtag.bus.tdi
183 yield self.jtag.bus.tdo
184 yield self.jtag.bus.tck
185 yield self.jtag.bus.tms
186 yield from self.jtag.boundary_scan_pads
187
188 def jtag_request(self, m, name, number=0, *, dir=None, xdr=None):
189 """request a Resource (e.g. name="uart", number=0) which will
190 return a data structure containing Records of all the pins.
191
192 this override will also - automatically - create a JTAG Boundary Scan
193 connection *without* any change to the actual Platform.request() API
194 """
195 pad_mgr = self.jtag.pad_mgr
196 core_mgr = self.jtag.core_mgr
197 padlookup = self.jtag.padlookup
198 # okaaaay, bit of shenanigens going on: the important data structure
199 # here is Resourcemanager._ports. requests add to _ports, which is
200 # what needs redirecting. therefore what has to happen is to
201 # capture the number of ports *before* the request. sigh.
202 start_ports = len(core_mgr._ports)
203 value = core_mgr.request(name, number, dir=dir, xdr=xdr)
204 end_ports = len(core_mgr._ports)
205
206 # take a copy of the requests made
207 self.jtag.requests_made.append((name, number, dir, xdr))
208
209 # now make a corresponding (duplicate) request to the pad manager
210 # BUT, if it doesn't exist, don't sweat it: all it means is, the
211 # application did not request Boundary Scan for that resource.
212 pad_start_ports = len(pad_mgr._ports)
213 pvalue = pad_mgr.request(name, number, dir=dir, xdr=xdr)
214 pad_end_ports = len(pad_mgr._ports)
215
216 # ok now we have the lengths: now create a lookup between the pad
217 # and the core, so that JTAG boundary scan can be inserted in between
218 core = core_mgr._ports[start_ports:end_ports]
219 pads = pad_mgr._ports[pad_start_ports:pad_end_ports]
220 # oops if not the same numbers added. it's a duplicate. shouldn't happen
221 assert len(core) == len(pads), "argh, resource manager error"
222 print ("core", core)
223 print ("pads", pads)
224
225 # pad/core each return a list of tuples of (res, pin, port, attrs)
226 for pad, core in zip(pads, core):
227 # create a lookup on pin name to get at the hidden pad instance
228 # this pin name will be handed to get_input, get_output etc.
229 # and without the padlookup you can't find the (duplicate) pad.
230 # note that self.padlookup and self.jtag.ios use the *exact* same
231 # pin.name per pin
232 padpin = pad[1]
233 corepin = core[1]
234 if padpin is None: continue # skip when pin is None
235 assert corepin is not None # if pad was None, core should be too
236 print ("iter", pad, padpin.name)
237 print ("existing pads", padlookup.keys())
238 assert padpin.name not in padlookup # no overwrites allowed!
239 assert padpin.name == corepin.name # has to be the same!
240 padlookup[padpin.name] = (core, pad) # store pad by pin name
241
242 # now add the IO Shift Register. first identify the type
243 # then request a JTAG IOConn. we can't wire it up (yet) because
244 # we don't have a Module() instance. doh. that comes in get_input
245 # and get_output etc. etc.
246 iotype = resiotypes[padpin.dir] # look up the C4M-JTAG IOType
247 io = self.jtag.add_io(iotype=iotype, name=padpin.name) # IOConn
248 self.jtag.ios[padpin.name] = io # store IOConn Record by pin name
249
250 # and connect up core to pads based on type. could create
251 # Modules here just like in Platform.get_input/output but
252 # in some ways it is clearer by being simpler to wire them globally
253
254 if padpin.dir == 'i':
255 print ("jtag_request add input pin", padpin)
256 print (" corepin", corepin)
257 print (" jtag io core", io.core)
258 print (" jtag io pad", io.pad)
259 # corepin is to be returned, here. so, connect jtag corein to it
260 m.d.comb += corepin.i.eq(io.core.i)
261 # and padpin to JTAG pad
262 m.d.comb += io.pad.i.eq(padpin.i)
263 self.jtag.boundary_scan_pads.append(padpin.i)
264 elif padpin.dir == 'o':
265 print ("jtag_request add output pin", padpin)
266 print (" corepin", corepin)
267 print (" jtag io core", io.core)
268 print (" jtag io pad", io.pad)
269 # corepin is to be returned, here. connect it to jtag core out
270 m.d.comb += io.core.o.eq(corepin.o)
271 # and JTAG pad to padpin
272 m.d.comb += padpin.o.eq(io.pad.o)
273 self.jtag.boundary_scan_pads.append(padpin.o)
274 elif padpin.dir == 'io':
275 print ("jtag_request add io pin", padpin)
276 print (" corepin", corepin)
277 print (" jtag io core", io.core)
278 print (" jtag io pad", io.pad)
279 # corepin is to be returned, here. so, connect jtag corein to it
280 m.d.comb += corepin.i.eq(io.core.i)
281 # and padpin to JTAG pad
282 m.d.comb += io.pad.i.eq(padpin.i)
283 # corepin is to be returned, here. connect it to jtag core out
284 m.d.comb += io.core.o.eq(corepin.o)
285 # and JTAG pad to padpin
286 m.d.comb += padpin.o.eq(io.pad.o)
287 # corepin is to be returned, here. connect it to jtag core out
288 m.d.comb += io.core.oe.eq(corepin.oe)
289 # and JTAG pad to padpin
290 m.d.comb += padpin.oe.eq(io.pad.oe)
291 `
292 self.jtag.boundary_scan_pads.append(padpin.i)
293 self.jtag.boundary_scan_pads.append(padpin.o)
294 self.jtag.boundary_scan_pads.append(padpin.oe)
295
296 # finally return the *CORE* value just like ResourceManager.request()
297 # so that the module using this can connect to *CORE* i/o to the
298 # resource. pads are taken care of
299 return value
300
301
302 '''
303 _trellis_command_templates = [
304 r"""
305 {{invoke_tool("yosys")}}
306 {{quiet("-q")}}
307 {{get_override("yosys_opts")|options}}
308 -l {{name}}.rpt
309 {{name}}.ys
310 """,
311 ]
312 '''
313
314 # sigh, have to create a dummy platform for now.
315 # TODO: investigate how the heck to get it to output ilang. or verilog.
316 # or, anything, really. but at least it doesn't barf
317 class ASICPlatform(TemplatedPlatform):
318 connectors = []
319 resources = OrderedDict()
320 required_tools = []
321 command_templates = ['/bin/true'] # no command needed: stops barfing
322 file_templates = {
323 **TemplatedPlatform.build_script_templates,
324 "{{name}}.il": r"""
325 # {{autogenerated}}
326 {{emit_rtlil()}}
327 """,
328 "{{name}}.debug.v": r"""
329 /* {{autogenerated}} */
330 {{emit_debug_verilog()}}
331 """,
332 }
333 toolchain = None
334 default_clk = "clk" # should be picked up / overridden by platform sys.clk
335 default_rst = "rst" # should be picked up / overridden by platform sys.rst
336
337 def __init__(self, resources, jtag):
338 self.jtag = jtag
339 super().__init__()
340
341 # create set of pin resources based on the pinset, this is for the core
342 #jtag_resources = self.jtag.pad_mgr.resources
343 self.add_resources(resources)
344
345 # add JTAG without scan
346 self.add_resources([JTAGResource('jtag', 0)], no_boundary_scan=True)
347
348 def _request(self, name, number=0, *, dir=None, xdr=None):
349 """request a Resource (e.g. name="uart", number=0) which will
350 return a data structure containing Records of all the pins.
351
352 this override will also - automatically - create a JTAG Boundary Scan
353 connection *without* any change to the actual Platform.request() API
354 """
355 pad_mgr = self.jtag.pad_mgr
356 pad_mgr = self.jtag.pad_mgr
357 padlookup = self.jtag.padlookup
358 # okaaaay, bit of shenanigens going on: the important data structure
359 # here is Resourcemanager._ports. requests add to _ports, which is
360 # what needs redirecting. therefore what has to happen is to
361 # capture the number of ports *before* the request. sigh.
362 start_ports = len(self._ports)
363 value = super().request(name, number, dir=dir, xdr=xdr)
364 end_ports = len(self._ports)
365
366 # now make a corresponding (duplicate) request to the pad manager
367 # BUT, if it doesn't exist, don't sweat it: all it means is, the
368 # application did not request Boundary Scan for that resource.
369 pad_start_ports = len(pad_mgr._ports)
370 try:
371 pvalue = pad_mgr.request(name, number, dir=dir, xdr=xdr)
372 except ResourceError:
373 return value
374 pad_end_ports = len(pad_mgr._ports)
375
376 # ok now we have the lengths: now create a lookup between the pad
377 # and the core, so that JTAG boundary scan can be inserted in between
378 core = self._ports[start_ports:end_ports]
379 pads = pad_mgr._ports[pad_start_ports:pad_end_ports]
380 # oops if not the same numbers added. it's a duplicate. shouldn't happen
381 assert len(core) == len(pads), "argh, resource manager error"
382 print ("core", core)
383 print ("pads", pads)
384
385 # pad/core each return a list of tuples of (res, pin, port, attrs)
386 for pad, core in zip(pads, core):
387 # create a lookup on pin name to get at the hidden pad instance
388 # this pin name will be handed to get_input, get_output etc.
389 # and without the padlookup you can't find the (duplicate) pad.
390 # note that self.padlookup and self.jtag.ios use the *exact* same
391 # pin.name per pin
392 pin = pad[1]
393 corepin = core[1]
394 if pin is None: continue # skip when pin is None
395 assert corepin is not None # if pad was None, core should be too
396 print ("iter", pad, pin.name)
397 print ("existing pads", padlookup.keys())
398 assert pin.name not in padlookup # no overwrites allowed!
399 assert pin.name == corepin.name # has to be the same!
400 padlookup[pin.name] = pad # store pad by pin name
401
402 # now add the IO Shift Register. first identify the type
403 # then request a JTAG IOConn. we can't wire it up (yet) because
404 # we don't have a Module() instance. doh. that comes in get_input
405 # and get_output etc. etc.
406 iotype = resiotypes[pin.dir] # look up the C4M-JTAG IOType
407 io = self.jtag.add_io(iotype=iotype, name=pin.name) # create IOConn
408 self.jtag.ios[pin.name] = io # store IOConn Record by pin name
409
410 # finally return the value just like ResourceManager.request()
411 return value
412
413 def add_resources(self, resources, no_boundary_scan=False):
414 print ("ASICPlatform add_resources", resources)
415 super().add_resources(resources)
416 return
417 if no_boundary_scan:
418 return
419 # make a *second* - identical - set of pin resources for the IO ring
420 padres = deepcopy(resources)
421 self.jtag.pad_mgr.add_resources(padres)
422
423 #def iter_ports(self):
424 # yield from super().iter_ports()
425 # for io in self.jtag.ios.values():
426 # print ("iter ports", io.layout, io)
427 # for field in io.core.fields:
428 # yield getattr(io.core, field)
429 # for field in io.pad.fields:
430 # yield getattr(io.pad, field)
431
432 # XXX these aren't strictly necessary right now but the next
433 # phase is to add JTAG Boundary Scan so it maaay be worth adding?
434 # at least for the print statements
435 def get_input(self, pin, port, attrs, invert):
436 padlookup = self.jtag.padlookup
437 self._check_feature("single-ended input", pin, attrs,
438 valid_xdrs=(0,), valid_attrs=None)
439
440 m = Module()
441 print (" get_input", pin, "port", port, port.layout)
442 if pin.name in ['clk_0', 'rst_0']: # sigh
443 # simple pass-through from port to pin
444 print("No JTAG chain in-between")
445 m.d.comb += pin.i.eq(self._invert_if(invert, port))
446 return m
447 if pin.name not in padlookup:
448 print("No pin named %s, not connecting to JTAG BS" % pin.name)
449 m.d.comb += pin.i.eq(self._invert_if(invert, port))
450 return m
451 (padres, padpin, padport, padattrs) = padlookup[pin.name]
452 io = self.jtag.ios[pin.name]
453 print (" pad", padres, padpin, padport, attrs)
454 print (" padpin", padpin.layout)
455 print (" jtag", io.core.layout, io.pad.layout)
456 m.d.comb += pin.i.eq(io.core.i)
457 m.d.comb += padpin.i.eq(pin.i)
458 m.d.comb += padport.io.eq(self._invert_if(invert, port))
459 m.d.comb += io.pad.i.eq(padport.io)
460
461 print("+=+=+= pin: ", pin)
462 print("+=+=+= port: ", port.layout)
463 print("+=+=+= pad pin: ", padpin)
464 print("+=+=+= pad port: ", padport)
465 return m
466
467 def get_output(self, pin, port, attrs, invert):
468 padlookup = self.jtag.padlookup
469 self._check_feature("single-ended output", pin, attrs,
470 valid_xdrs=(0,), valid_attrs=None)
471
472 m = Module()
473 print (" get_output", pin, "port", port, port.layout)
474 if pin.name in ['clk_0', 'rst_0']: # sigh
475 # simple pass-through from pin to port
476 print("No JTAG chain in-between")
477 m.d.comb += port.eq(self._invert_if(invert, pin.o))
478 return m
479 if pin.name not in padlookup:
480 print("No pin named %s, not connecting to JTAG BS" % pin.name)
481 m.d.comb += port.eq(self._invert_if(invert, pin.o))
482 return m
483 (padres, padpin, padport, padattrs) = padlookup[pin.name]
484 io = self.jtag.ios[pin.name]
485 print (" pad", padres, padpin, padport, padattrs)
486 print (" pin", padpin.layout)
487 print (" jtag", io.core.layout, io.pad.layout)
488 m.d.comb += io.core.o.eq(self._invert_if(invert, pin.o))
489 m.d.comb += pin.o.eq(padpin.o)
490 m.d.comb += port.eq(padport.io)
491 m.d.comb += padport.io.eq(io.pad.o)
492 return m
493
494 def get_tristate(self, pin, port, attrs, invert):
495 padlookup = self.jtag.padlookup
496 self._check_feature("single-ended tristate", pin, attrs,
497 valid_xdrs=(0,), valid_attrs=None)
498
499 print (" get_tristate", pin, "port", port, port.layout)
500 m = Module()
501 if pin.name in ['clk_0', 'rst_0']: # sigh
502 print("No JTAG chain in-between")
503 m.submodules += Instance("$tribuf",
504 p_WIDTH=pin.width,
505 i_EN=pin.oe,
506 i_A=self._invert_if(invert, pin.o),
507 o_Y=port,
508 )
509 return m
510 return m
511 (res, pin, port, attrs) = padlookup[pin.name]
512 io = self.jtag.ios[pin.name]
513 print (" pad", res, pin, port, attrs)
514 print (" pin", pin.layout)
515 print (" jtag", io.core.layout, io.pad.layout)
516 #m.submodules += Instance("$tribuf",
517 # p_WIDTH=pin.width,
518 # i_EN=io.pad.oe,
519 # i_A=self._invert_if(invert, io.pad.o),
520 # o_Y=port,
521 #)
522 m.d.comb += io.core.o.eq(pin.o)
523 m.d.comb += io.core.oe.eq(pin.oe)
524 m.d.comb += pin.i.eq(io.core.i)
525 m.d.comb += io.pad.i.eq(port.i)
526 m.d.comb += port.o.eq(io.pad.o)
527 m.d.comb += port.oe.eq(io.pad.oe)
528 return m
529
530 def get_input_output(self, pin, port, attrs, invert):
531 padlookup = self.jtag.padlookup
532 self._check_feature("single-ended input/output", pin, attrs,
533 valid_xdrs=(0,), valid_attrs=None)
534
535 print (" get_input_output", pin, "port", port, port.layout)
536 m = Module()
537 if pin.name in ['clk_0', 'rst_0']: # sigh
538 print("No JTAG chain in-between")
539 m.submodules += Instance("$tribuf",
540 p_WIDTH=pin.width,
541 i_EN=pin.oe,
542 i_A=self._invert_if(invert, pin.o),
543 o_Y=port,
544 )
545 m.d.comb += pin.i.eq(self._invert_if(invert, port))
546 return m
547 (padres, padpin, padport, padattrs) = padlookup[pin.name]
548 io = self.jtag.ios[pin.name]
549 print (" padres", padres)
550 print (" padpin", padpin)
551 print (" layout", padpin.layout)
552 print (" padport", padport)
553 print (" layout", padport.layout)
554 print (" padattrs", padattrs)
555 print (" port layout", port.layout)
556 print (" pin", pin)
557 print (" layout", pin.layout)
558 print (" jtag io.core", io.core.layout)
559 print (" jtag io.pad", io.pad.layout)
560 #m.submodules += Instance("$tribuf",
561 # p_WIDTH=pin.width,
562 # i_EN=io.pad.oe,
563 # i_A=self._invert_if(invert, io.pad.o),
564 # o_Y=port,
565 #)
566 # Create aliases for the port sub-signals
567 port_i = port.io[0]
568 port_o = port.io[1]
569 port_oe = port.io[2]
570
571 padport_i = padport.io[0]
572 padport_o = padport.io[1]
573 padport_oe = padport.io[2]
574
575 # connect i
576 m.d.comb += pin.i.eq(io.core.i)
577 m.d.comb += padpin.i.eq(pin.i)
578 m.d.comb += padport_i.eq(self._invert_if(invert, port_i))
579 m.d.comb += io.pad.i.eq(padport_i)
580
581 # connect o
582 m.d.comb += io.core.o.eq(self._invert_if(invert, pin.o))
583 m.d.comb += pin.o.eq(padpin.o)
584 m.d.comb += port_o.eq(padport_o)
585 m.d.comb += padport_o.eq(io.pad.o)
586
587 # connect oe
588 m.d.comb += io.core.oe.eq(self._invert_if(invert, pin.oe))
589 m.d.comb += pin.oe.eq(padpin.oe)
590 m.d.comb += port_oe.eq(padport_oe)
591 m.d.comb += padport_oe.eq(io.pad.oe)
592
593 return m
594
595 def toolchain_prepare(self, fragment, name, **kwargs):
596 """override toolchain_prepare in order to grab the fragment
597 """
598 self.fragment = fragment
599 return super().toolchain_prepare(fragment, name, **kwargs)
600
601 """
602 and to create a Platform instance with that list, and build
603 something random
604
605 p=Platform()
606 p.resources=listofstuff
607 p.build(Blinker())
608 """
609 pinset = dummy_pinset()
610 print(pinset)
611 resources = create_resources(pinset)
612 top = Blinker(pinset, resources)
613
614 vl = rtlil.convert(top, ports=top.ports())
615 with open("test_jtag_blinker.il", "w") as f:
616 f.write(vl)
617
618 sys.exit(0)
619
620 if False:
621 # XXX these modules are all being added *AFTER* the build process links
622 # everything together. the expectation that this would work is...
623 # unrealistic. ordering, clearly, is important.
624
625 # dut = JTAG(test_pinset(), wb_data_wid=64, domain="sync")
626 top.jtag.stop = False
627 # rather than the client access the JTAG bus directly
628 # create an alternative that the client sets
629 class Dummy: pass
630 cdut = Dummy()
631 cdut.cbus = JTAGInterface()
632
633 # set up client-server on port 44843-something
634 top.jtag.s = JTAGServer()
635 cdut.c = JTAGClient()
636 top.jtag.s.get_connection()
637 #else:
638 # print ("running server only as requested, use openocd remote to test")
639 # sys.stdout.flush()
640 # top.jtag.s.get_connection(None) # block waiting for connection
641
642 # take copy of ir_width and scan_len
643 cdut._ir_width = top.jtag._ir_width
644 cdut.scan_len = top.jtag.scan_len
645
646 p = ASICPlatform (resources, top.jtag)
647 p.build(top)
648 # this is what needs to gets treated as "top", after "main module" top
649 # is augmented with IO pads with JTAG tacked on. the expectation that
650 # the get_input() etc functions will be called magically by some other
651 # function is unrealistic.
652 top_fragment = p.fragment
653
654 # XXX simulating top (the module that does not itself contain IO pads
655 # because that's covered by build) cannot possibly be expected to work
656 # particularly when modules have been added *after* the platform build()
657 # function has been called.
658
659 sim = Simulator(top)
660 sim.add_clock(1e-6, domain="sync") # standard clock
661
662 sim.add_sync_process(wrap(jtag_srv(top))) #? jtag server
663 #if len(sys.argv) != 2 or sys.argv[1] != 'server':
664 sim.add_sync_process(wrap(jtag_sim(cdut, top.jtag))) # actual jtag tester
665 sim.add_sync_process(wrap(dmi_sim(top.jtag))) # handles (pretends to be) DMI
666
667 with sim.write_vcd("dmi2jtag_test_srv.vcd"):
668 sim.run()