add a core-mgr *and* a pad-mgr to JTAG class so that an *entire* set
[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 memory = Memory(width=32, depth=16)
136 self.sram = SRAM(memory=memory, bus=self.jtag.wb)
137
138 def elaborate(self, platform):
139 jtag_resources = self.jtag.pad_mgr.resources
140 core_resources = self.jtag.core_mgr.resources
141 m = Module()
142 m.submodules.jtag = self.jtag
143 m.submodules.sram = self.sram
144
145 count = Signal(5)
146 m.d.sync += count.eq(count+1)
147 print ("resources", platform, jtag_resources.items())
148 gpio = self.jtag_request(m, 'gpio')
149 print (gpio, gpio.layout, gpio.fields)
150 # get the GPIO bank, mess about with some of the pins
151 m.d.comb += gpio.gpio0.io.o.eq(1)
152 m.d.comb += gpio.gpio1.io.o.eq(gpio.gpio2.io.i)
153 m.d.comb += gpio.gpio1.io.oe.eq(count[4])
154 m.d.sync += count[0].eq(gpio.gpio1.io.i)
155 # get the UART resource, mess with the output tx
156 uart = self.jtag_request(m, 'uart')
157 print (uart, uart.fields)
158 intermediary = Signal()
159 m.d.comb += uart.tx.eq(intermediary)
160 m.d.comb += intermediary.eq(uart.rx)
161
162 # platform requested: make the exact same requests,
163 # then add JTAG afterwards
164 if platform is not None:
165 for (name, number, dir, xdr) in self.jtag.requests_made:
166 platform.request(name, number, dir=dir, xdr=xdr)
167
168 # wire up JTAG otherwise we are in trouble (no clock)
169 jtag = platform.request('jtag')
170 m.d.comb += self.jtag.bus.tdi.eq(jtag.tdi)
171 m.d.comb += self.jtag.bus.tck.eq(jtag.tck)
172 m.d.comb += self.jtag.bus.tms.eq(jtag.tms)
173 m.d.comb += jtag.tdo.eq(self.jtag.bus.tdo)
174
175 return m
176
177 def ports(self):
178 return list(self)
179
180 def __iter__(self):
181 yield self.jtag.bus.tdi
182 yield self.jtag.bus.tdo
183 yield self.jtag.bus.tck
184 yield self.jtag.bus.tms
185
186 def jtag_request(self, m, name, number=0, *, dir=None, xdr=None):
187 """request a Resource (e.g. name="uart", number=0) which will
188 return a data structure containing Records of all the pins.
189
190 this override will also - automatically - create a JTAG Boundary Scan
191 connection *without* any change to the actual Platform.request() API
192 """
193 pad_mgr = self.jtag.pad_mgr
194 core_mgr = self.jtag.core_mgr
195 padlookup = self.jtag.padlookup
196 # okaaaay, bit of shenanigens going on: the important data structure
197 # here is Resourcemanager._ports. requests add to _ports, which is
198 # what needs redirecting. therefore what has to happen is to
199 # capture the number of ports *before* the request. sigh.
200 start_ports = len(core_mgr._ports)
201 value = core_mgr.request(name, number, dir=dir, xdr=xdr)
202 end_ports = len(core_mgr._ports)
203
204 # take a copy of the requests made
205 self.jtag.requests_made.append((name, number, dir, xdr))
206
207 # now make a corresponding (duplicate) request to the pad manager
208 # BUT, if it doesn't exist, don't sweat it: all it means is, the
209 # application did not request Boundary Scan for that resource.
210 pad_start_ports = len(pad_mgr._ports)
211 pvalue = pad_mgr.request(name, number, dir=dir, xdr=xdr)
212 pad_end_ports = len(pad_mgr._ports)
213
214 # ok now we have the lengths: now create a lookup between the pad
215 # and the core, so that JTAG boundary scan can be inserted in between
216 core = core_mgr._ports[start_ports:end_ports]
217 pads = pad_mgr._ports[pad_start_ports:pad_end_ports]
218 # oops if not the same numbers added. it's a duplicate. shouldn't happen
219 assert len(core) == len(pads), "argh, resource manager error"
220 print ("core", core)
221 print ("pads", pads)
222
223 # pad/core each return a list of tuples of (res, pin, port, attrs)
224 for pad, core in zip(pads, core):
225 # create a lookup on pin name to get at the hidden pad instance
226 # this pin name will be handed to get_input, get_output etc.
227 # and without the padlookup you can't find the (duplicate) pad.
228 # note that self.padlookup and self.jtag.ios use the *exact* same
229 # pin.name per pin
230 padpin = pad[1]
231 corepin = core[1]
232 if padpin is None: continue # skip when pin is None
233 assert corepin is not None # if pad was None, core should be too
234 print ("iter", pad, padpin.name)
235 print ("existing pads", padlookup.keys())
236 assert padpin.name not in padlookup # no overwrites allowed!
237 assert padpin.name == corepin.name # has to be the same!
238 padlookup[padpin.name] = (core, pad) # store pad by pin name
239
240 # now add the IO Shift Register. first identify the type
241 # then request a JTAG IOConn. we can't wire it up (yet) because
242 # we don't have a Module() instance. doh. that comes in get_input
243 # and get_output etc. etc.
244 iotype = resiotypes[padpin.dir] # look up the C4M-JTAG IOType
245 io = self.jtag.add_io(iotype=iotype, name=padpin.name) # IOConn
246 self.jtag.ios[padpin.name] = io # store IOConn Record by pin name
247
248 # and connect up core to pads based on type
249 if padpin.dir == 'i':
250 print ("jtag_request add input pin", padpin)
251 print (" corepin", corepin)
252 print (" jtag io core", io.core)
253 print (" jtag io pad", io.pad)
254 # corepin is to be returned, here. so, connect jtag corein to it
255 m.d.comb += corepin.i.eq(io.core.i)
256 # and padpin to JTAG pad
257 m.d.comb += io.pad.i.eq(padpin.i)
258 elif padpin.dir == 'o':
259 print ("jtag_request add output pin", padpin)
260 print (" corepin", corepin)
261 print (" jtag io core", io.core)
262 print (" jtag io pad", io.pad)
263 # corepin is to be returned, here. connect it to jtag core out
264 m.d.comb += io.core.o.eq(corepin.o)
265 # and JTAG pad to padpin
266 m.d.comb += padpin.o.eq(io.pad.o)
267 elif padpin.dir == 'io':
268 print ("jtag_request add io pin", padpin)
269 print (" corepin", corepin)
270 print (" jtag io core", io.core)
271 print (" jtag io pad", io.pad)
272 # corepin is to be returned, here. so, connect jtag corein to it
273 m.d.comb += corepin.i.eq(io.core.i)
274 # and padpin to JTAG pad
275 m.d.comb += io.pad.i.eq(padpin.i)
276 # corepin is to be returned, here. connect it to jtag core out
277 m.d.comb += io.core.o.eq(corepin.o)
278 # and JTAG pad to padpin
279 m.d.comb += padpin.o.eq(io.pad.o)
280 # corepin is to be returned, here. connect it to jtag core out
281 m.d.comb += io.core.oe.eq(corepin.oe)
282 # and JTAG pad to padpin
283 m.d.comb += padpin.oe.eq(io.pad.oe)
284
285 # finally return the *CORE* value just like ResourceManager.request()
286 # so that the module using this can connect to *CORE* i/o to the
287 # resource. pads are taken care of
288 return value
289
290
291 '''
292 _trellis_command_templates = [
293 r"""
294 {{invoke_tool("yosys")}}
295 {{quiet("-q")}}
296 {{get_override("yosys_opts")|options}}
297 -l {{name}}.rpt
298 {{name}}.ys
299 """,
300 ]
301 '''
302
303 # sigh, have to create a dummy platform for now.
304 # TODO: investigate how the heck to get it to output ilang. or verilog.
305 # or, anything, really. but at least it doesn't barf
306 class ASICPlatform(TemplatedPlatform):
307 connectors = []
308 resources = OrderedDict()
309 required_tools = []
310 command_templates = ['/bin/true'] # no command needed: stops barfing
311 file_templates = {
312 **TemplatedPlatform.build_script_templates,
313 "{{name}}.il": r"""
314 # {{autogenerated}}
315 {{emit_rtlil()}}
316 """,
317 "{{name}}.debug.v": r"""
318 /* {{autogenerated}} */
319 {{emit_debug_verilog()}}
320 """,
321 }
322 toolchain = None
323 default_clk = "clk" # should be picked up / overridden by platform sys.clk
324 default_rst = "rst" # should be picked up / overridden by platform sys.rst
325
326 def __init__(self, resources, jtag):
327 self.jtag = jtag
328 super().__init__()
329
330 # create set of pin resources based on the pinset, this is for the core
331 #jtag_resources = self.jtag.pad_mgr.resources
332 self.add_resources(resources)
333
334 # add JTAG without scan
335 self.add_resources([JTAGResource('jtag', 0)], no_boundary_scan=True)
336
337 def _request(self, name, number=0, *, dir=None, xdr=None):
338 """request a Resource (e.g. name="uart", number=0) which will
339 return a data structure containing Records of all the pins.
340
341 this override will also - automatically - create a JTAG Boundary Scan
342 connection *without* any change to the actual Platform.request() API
343 """
344 pad_mgr = self.jtag.pad_mgr
345 pad_mgr = self.jtag.pad_mgr
346 padlookup = self.jtag.padlookup
347 # okaaaay, bit of shenanigens going on: the important data structure
348 # here is Resourcemanager._ports. requests add to _ports, which is
349 # what needs redirecting. therefore what has to happen is to
350 # capture the number of ports *before* the request. sigh.
351 start_ports = len(self._ports)
352 value = super().request(name, number, dir=dir, xdr=xdr)
353 end_ports = len(self._ports)
354
355 # now make a corresponding (duplicate) request to the pad manager
356 # BUT, if it doesn't exist, don't sweat it: all it means is, the
357 # application did not request Boundary Scan for that resource.
358 pad_start_ports = len(pad_mgr._ports)
359 try:
360 pvalue = pad_mgr.request(name, number, dir=dir, xdr=xdr)
361 except ResourceError:
362 return value
363 pad_end_ports = len(pad_mgr._ports)
364
365 # ok now we have the lengths: now create a lookup between the pad
366 # and the core, so that JTAG boundary scan can be inserted in between
367 core = self._ports[start_ports:end_ports]
368 pads = pad_mgr._ports[pad_start_ports:pad_end_ports]
369 # oops if not the same numbers added. it's a duplicate. shouldn't happen
370 assert len(core) == len(pads), "argh, resource manager error"
371 print ("core", core)
372 print ("pads", pads)
373
374 # pad/core each return a list of tuples of (res, pin, port, attrs)
375 for pad, core in zip(pads, core):
376 # create a lookup on pin name to get at the hidden pad instance
377 # this pin name will be handed to get_input, get_output etc.
378 # and without the padlookup you can't find the (duplicate) pad.
379 # note that self.padlookup and self.jtag.ios use the *exact* same
380 # pin.name per pin
381 pin = pad[1]
382 corepin = core[1]
383 if pin is None: continue # skip when pin is None
384 assert corepin is not None # if pad was None, core should be too
385 print ("iter", pad, pin.name)
386 print ("existing pads", padlookup.keys())
387 assert pin.name not in padlookup # no overwrites allowed!
388 assert pin.name == corepin.name # has to be the same!
389 padlookup[pin.name] = pad # store pad by pin name
390
391 # now add the IO Shift Register. first identify the type
392 # then request a JTAG IOConn. we can't wire it up (yet) because
393 # we don't have a Module() instance. doh. that comes in get_input
394 # and get_output etc. etc.
395 iotype = resiotypes[pin.dir] # look up the C4M-JTAG IOType
396 io = self.jtag.add_io(iotype=iotype, name=pin.name) # create IOConn
397 self.jtag.ios[pin.name] = io # store IOConn Record by pin name
398
399 # finally return the value just like ResourceManager.request()
400 return value
401
402 def add_resources(self, resources, no_boundary_scan=False):
403 print ("ASICPlatform add_resources", resources)
404 super().add_resources(resources)
405 return
406 if no_boundary_scan:
407 return
408 # make a *second* - identical - set of pin resources for the IO ring
409 padres = deepcopy(resources)
410 self.jtag.pad_mgr.add_resources(padres)
411
412 #def iter_ports(self):
413 # yield from super().iter_ports()
414 # for io in self.jtag.ios.values():
415 # print ("iter ports", io.layout, io)
416 # for field in io.core.fields:
417 # yield getattr(io.core, field)
418 # for field in io.pad.fields:
419 # yield getattr(io.pad, field)
420
421 # XXX these aren't strictly necessary right now but the next
422 # phase is to add JTAG Boundary Scan so it maaay be worth adding?
423 # at least for the print statements
424 def get_input(self, pin, port, attrs, invert):
425 padlookup = self.jtag.padlookup
426 self._check_feature("single-ended input", pin, attrs,
427 valid_xdrs=(0,), valid_attrs=None)
428
429 m = Module()
430 print (" get_input", pin, "port", port, port.layout)
431 if pin.name in ['clk_0', 'rst_0']: # sigh
432 # simple pass-through from port to pin
433 print("No JTAG chain in-between")
434 m.d.comb += pin.i.eq(self._invert_if(invert, port))
435 return m
436 if pin.name not in padlookup:
437 print("No pin named %s, not connecting to JTAG BS" % pin.name)
438 m.d.comb += pin.i.eq(self._invert_if(invert, port))
439 return m
440 (padres, padpin, padport, padattrs) = padlookup[pin.name]
441 io = self.jtag.ios[pin.name]
442 print (" pad", padres, padpin, padport, attrs)
443 print (" padpin", padpin.layout)
444 print (" jtag", io.core.layout, io.pad.layout)
445 m.d.comb += pin.i.eq(io.core.i)
446 m.d.comb += padpin.i.eq(pin.i)
447 m.d.comb += padport.io.eq(self._invert_if(invert, port))
448 m.d.comb += io.pad.i.eq(padport.io)
449
450 print("+=+=+= pin: ", pin)
451 print("+=+=+= port: ", port.layout)
452 print("+=+=+= pad pin: ", padpin)
453 print("+=+=+= pad port: ", padport)
454 return m
455
456 def get_output(self, pin, port, attrs, invert):
457 padlookup = self.jtag.padlookup
458 self._check_feature("single-ended output", pin, attrs,
459 valid_xdrs=(0,), valid_attrs=None)
460
461 m = Module()
462 print (" get_output", pin, "port", port, port.layout)
463 if pin.name in ['clk_0', 'rst_0']: # sigh
464 # simple pass-through from pin to port
465 print("No JTAG chain in-between")
466 m.d.comb += port.eq(self._invert_if(invert, pin.o))
467 return m
468 if pin.name not in padlookup:
469 print("No pin named %s, not connecting to JTAG BS" % pin.name)
470 m.d.comb += port.eq(self._invert_if(invert, pin.o))
471 return m
472 (padres, padpin, padport, padattrs) = padlookup[pin.name]
473 io = self.jtag.ios[pin.name]
474 print (" pad", padres, padpin, padport, padattrs)
475 print (" pin", padpin.layout)
476 print (" jtag", io.core.layout, io.pad.layout)
477 m.d.comb += io.core.o.eq(self._invert_if(invert, pin.o))
478 m.d.comb += pin.o.eq(padpin.o)
479 m.d.comb += port.eq(padport.io)
480 m.d.comb += padport.io.eq(io.pad.o)
481 return m
482
483 def get_tristate(self, pin, port, attrs, invert):
484 padlookup = self.jtag.padlookup
485 self._check_feature("single-ended tristate", pin, attrs,
486 valid_xdrs=(0,), valid_attrs=None)
487
488 print (" get_tristate", pin, "port", port, port.layout)
489 m = Module()
490 if pin.name in ['clk_0', 'rst_0']: # sigh
491 print("No JTAG chain in-between")
492 m.submodules += Instance("$tribuf",
493 p_WIDTH=pin.width,
494 i_EN=pin.oe,
495 i_A=self._invert_if(invert, pin.o),
496 o_Y=port,
497 )
498 return m
499 return m
500 (res, pin, port, attrs) = padlookup[pin.name]
501 io = self.jtag.ios[pin.name]
502 print (" pad", res, pin, port, attrs)
503 print (" pin", pin.layout)
504 print (" jtag", io.core.layout, io.pad.layout)
505 #m.submodules += Instance("$tribuf",
506 # p_WIDTH=pin.width,
507 # i_EN=io.pad.oe,
508 # i_A=self._invert_if(invert, io.pad.o),
509 # o_Y=port,
510 #)
511 m.d.comb += io.core.o.eq(pin.o)
512 m.d.comb += io.core.oe.eq(pin.oe)
513 m.d.comb += pin.i.eq(io.core.i)
514 m.d.comb += io.pad.i.eq(port.i)
515 m.d.comb += port.o.eq(io.pad.o)
516 m.d.comb += port.oe.eq(io.pad.oe)
517 return m
518
519 def get_input_output(self, pin, port, attrs, invert):
520 padlookup = self.jtag.padlookup
521 self._check_feature("single-ended input/output", pin, attrs,
522 valid_xdrs=(0,), valid_attrs=None)
523
524 print (" get_input_output", pin, "port", port, port.layout)
525 m = Module()
526 if pin.name in ['clk_0', 'rst_0']: # sigh
527 print("No JTAG chain in-between")
528 m.submodules += Instance("$tribuf",
529 p_WIDTH=pin.width,
530 i_EN=pin.oe,
531 i_A=self._invert_if(invert, pin.o),
532 o_Y=port,
533 )
534 m.d.comb += pin.i.eq(self._invert_if(invert, port))
535 return m
536 (padres, padpin, padport, padattrs) = padlookup[pin.name]
537 io = self.jtag.ios[pin.name]
538 print (" padres", padres)
539 print (" padpin", padpin)
540 print (" layout", padpin.layout)
541 print (" padport", padport)
542 print (" layout", padport.layout)
543 print (" padattrs", padattrs)
544 print (" port layout", port.layout)
545 print (" pin", pin)
546 print (" layout", pin.layout)
547 print (" jtag io.core", io.core.layout)
548 print (" jtag io.pad", io.pad.layout)
549 #m.submodules += Instance("$tribuf",
550 # p_WIDTH=pin.width,
551 # i_EN=io.pad.oe,
552 # i_A=self._invert_if(invert, io.pad.o),
553 # o_Y=port,
554 #)
555 # Create aliases for the port sub-signals
556 port_i = port.io[0]
557 port_o = port.io[1]
558 port_oe = port.io[2]
559
560 padport_i = padport.io[0]
561 padport_o = padport.io[1]
562 padport_oe = padport.io[2]
563
564 # connect i
565 m.d.comb += pin.i.eq(io.core.i)
566 m.d.comb += padpin.i.eq(pin.i)
567 m.d.comb += padport_i.eq(self._invert_if(invert, port_i))
568 m.d.comb += io.pad.i.eq(padport_i)
569
570 # connect o
571 m.d.comb += io.core.o.eq(self._invert_if(invert, pin.o))
572 m.d.comb += pin.o.eq(padpin.o)
573 m.d.comb += port_o.eq(padport_o)
574 m.d.comb += padport_o.eq(io.pad.o)
575
576 # connect oe
577 m.d.comb += io.core.oe.eq(self._invert_if(invert, pin.oe))
578 m.d.comb += pin.oe.eq(padpin.oe)
579 m.d.comb += port_oe.eq(padport_oe)
580 m.d.comb += padport_oe.eq(io.pad.oe)
581
582 return m
583
584 def toolchain_prepare(self, fragment, name, **kwargs):
585 """override toolchain_prepare in order to grab the fragment
586 """
587 self.fragment = fragment
588 return super().toolchain_prepare(fragment, name, **kwargs)
589
590 """
591 and to create a Platform instance with that list, and build
592 something random
593
594 p=Platform()
595 p.resources=listofstuff
596 p.build(Blinker())
597 """
598 pinset = dummy_pinset()
599 print(pinset)
600 resources = create_resources(pinset)
601 top = Blinker(pinset, resources)
602
603 vl = rtlil.convert(top, ports=top.ports())
604 with open("test_jtag_blinker.il", "w") as f:
605 f.write(vl)
606
607 sys.exit(0)
608
609 if False:
610 # XXX these modules are all being added *AFTER* the build process links
611 # everything together. the expectation that this would work is...
612 # unrealistic. ordering, clearly, is important.
613
614 # dut = JTAG(test_pinset(), wb_data_wid=64, domain="sync")
615 top.jtag.stop = False
616 # rather than the client access the JTAG bus directly
617 # create an alternative that the client sets
618 class Dummy: pass
619 cdut = Dummy()
620 cdut.cbus = JTAGInterface()
621
622 # set up client-server on port 44843-something
623 top.jtag.s = JTAGServer()
624 cdut.c = JTAGClient()
625 top.jtag.s.get_connection()
626 #else:
627 # print ("running server only as requested, use openocd remote to test")
628 # sys.stdout.flush()
629 # top.jtag.s.get_connection(None) # block waiting for connection
630
631 # take copy of ir_width and scan_len
632 cdut._ir_width = top.jtag._ir_width
633 cdut.scan_len = top.jtag.scan_len
634
635 p = ASICPlatform (resources, top.jtag)
636 p.build(top)
637 # this is what needs to gets treated as "top", after "main module" top
638 # is augmented with IO pads with JTAG tacked on. the expectation that
639 # the get_input() etc functions will be called magically by some other
640 # function is unrealistic.
641 top_fragment = p.fragment
642
643 # XXX simulating top (the module that does not itself contain IO pads
644 # because that's covered by build) cannot possibly be expected to work
645 # particularly when modules have been added *after* the platform build()
646 # function has been called.
647
648 sim = Simulator(top)
649 sim.add_clock(1e-6, domain="sync") # standard clock
650
651 sim.add_sync_process(wrap(jtag_srv(top))) #? jtag server
652 #if len(sys.argv) != 2 or sys.argv[1] != 'server':
653 sim.add_sync_process(wrap(jtag_sim(cdut, top.jtag))) # actual jtag tester
654 sim.add_sync_process(wrap(dmi_sim(top.jtag))) # handles (pretends to be) DMI
655
656 with sim.write_vcd("dmi2jtag_test_srv.vcd"):
657 sim.run()