not by resources
therefore forget Pins class and wire up jtag IOConn directly by calling
C4MJTAG.add_io() directly
next step is to wire up the Shift Register stuff
+resiotypes = {'i': IOType.In,
+ 'o': IOType.Out,
+ 'oe': IOType.TriOut,
+ 'io': IOType.InTriOut,
+ }
+
scanlens = {IOType.In: 1,
IOType.Out: 1,
IOType.TriOut: 2,
scanlens = {IOType.In: 1,
IOType.Out: 1,
IOType.TriOut: 2,
'gpio': gpios,
'i2c': ['sda*', 'scl+']}
'gpio': gpios,
'i2c': ['sda*', 'scl+']}
# TODO: move to suitable location
class Pins:
"""declare a list of pins, including name and direction. grouped by fn
the pin dictionary needs to be in a reliable order so that the JTAG
Boundary Scan is also in a reliable order
"""
# TODO: move to suitable location
class Pins:
"""declare a list of pins, including name and direction. grouped by fn
the pin dictionary needs to be in a reliable order so that the JTAG
Boundary Scan is also in a reliable order
"""
- def __init__(self, pindict):
+ def __init__(self, pindict=None):
+ if pindict is None:
+ pindict = {}
self.io_names = OrderedDict()
if isinstance(pindict, OrderedDict):
self.io_names.update(pindict)
self.io_names = OrderedDict()
if isinstance(pindict, OrderedDict):
self.io_names.update(pindict)
# enumerate pin specs and create IOConn Records.
# we store the boundary scan register offset in the IOConn record
# enumerate pin specs and create IOConn Records.
# we store the boundary scan register offset in the IOConn record
- self.ios = [] # these are enumerated in external_ports
+ self.ios = {} # these are enumerated in external_ports
self.scan_len = 0
for fn, pin, iotype, pin_name, scan_idx in list(self):
io = self.add_io(iotype=iotype, name=pin_name)
io._scan_idx = scan_idx # hmm shouldn't really do this
self.scan_len += scan_idx # record full length of boundary scan
self.scan_len = 0
for fn, pin, iotype, pin_name, scan_idx in list(self):
io = self.add_io(iotype=iotype, name=pin_name)
io._scan_idx = scan_idx # hmm shouldn't really do this
self.scan_len += scan_idx # record full length of boundary scan
+ self.ios[pin_name] = io
# this is redundant. or maybe part of testing, i don't know.
self.sr = self.add_shiftreg(ircode=4, length=3,
# this is redundant. or maybe part of testing, i don't know.
self.sr = self.add_shiftreg(ircode=4, length=3,
"""
ports = super().external_ports() # gets JTAG signal names
ports += list(self.wb.fields.values()) # wishbone signals
"""
ports = super().external_ports() # gets JTAG signal names
ports += list(self.wb.fields.values()) # wishbone signals
+ for io in self.ios.values():
ports += list(io.core.fields.values()) # io "core" signals
ports += list(io.pad.fields.values()) # io "pad" signals"
return ports
ports += list(io.core.fields.values()) # io "core" signals
ports += list(io.pad.fields.values()) # io "pad" signals"
return ports
from nmigen.build.res import ResourceManager, ResourceError
from nmigen import Elaboratable, Signal, Module, Instance
from collections import OrderedDict
from nmigen.build.res import ResourceManager, ResourceError
from nmigen import Elaboratable, Signal, Module, Instance
from collections import OrderedDict
+from jtag import JTAG, resiotypes
from copy import deepcopy
# Was thinking of using these functions, but skipped for simplicity for now
from copy import deepcopy
# Was thinking of using these functions, but skipped for simplicity for now
# and can't have one until a clock has been established by ASICPlatform.
class Blinker(Elaboratable):
def __init__(self, pinset):
# and can't have one until a clock has been established by ASICPlatform.
class Blinker(Elaboratable):
def __init__(self, pinset):
- self.jtag = JTAG(pinset, "sync")
+ self.jtag = JTAG({}, "sync")
def elaborate(self, platform):
m = Module()
def elaborate(self, platform):
m = Module()
toolchain = None
default_clk = "clk" # should be picked up / overridden by platform sys.clk
default_rst = "rst" # should be picked up / overridden by platform sys.rst
toolchain = None
default_clk = "clk" # should be picked up / overridden by platform sys.clk
default_rst = "rst" # should be picked up / overridden by platform sys.rst
- def __init__(self, pinset):
+
+ def __init__(self, resources, jtag):
self.pad_mgr = ResourceManager([], [])
self.pad_mgr = ResourceManager([], [])
super().__init__()
# create set of pin resources based on the pinset, this is for the core
super().__init__()
# create set of pin resources based on the pinset, this is for the core
- resources = create_resources(pinset)
self.add_resources(resources)
# record resource lookup between core IO names and pads
self.padlookup = {}
def request(self, name, number=0, *, dir=None, xdr=None):
self.add_resources(resources)
# record resource lookup between core IO names and pads
self.padlookup = {}
def request(self, name, number=0, *, dir=None, xdr=None):
+ """request a Resource (e.g. name="uart", number=0) which will
+ return a data structure containing Records of all the pins.
+
+ this override will also - automatically - create a JTAG Boundary Scan
+ connection *without* any change to the actual Platform.request() API
+ """
# okaaaay, bit of shenanigens going on: the important data structure
# here is Resourcemanager._ports. requests add to _ports, which is
# what needs redirecting. therefore what has to happen is to
# okaaaay, bit of shenanigens going on: the important data structure
# here is Resourcemanager._ports. requests add to _ports, which is
# what needs redirecting. therefore what has to happen is to
print ("core", core)
print ("pads", pads)
print ("core", core)
print ("pads", pads)
- # each of these returns a tuple (res, pin, port, attrs)
+ # pad/core each return a list of tuples of (res, pin, port, attrs)
for pad, core in zip(pads, core):
for pad, core in zip(pads, core):
+ # create a lookup on pin name to get at the hidden pad instance
+ # this pin name will be handed to get_input, get_output etc.
+ # and without the padlookup you can't find the (duplicate) pad.
+ # note that self.padlookup and self.jtag.ios use the *exact* same
+ # pin.name per pin
pin = pad[1]
corepin = core[1]
if pin is None: continue # skip when pin is None
assert corepin is not None # if pad was None, core should be too
print ("iter", pad, pin.name)
assert pin.name not in self.padlookup # no overwrites allowed!
pin = pad[1]
corepin = core[1]
if pin is None: continue # skip when pin is None
assert corepin is not None # if pad was None, core should be too
print ("iter", pad, pin.name)
assert pin.name not in self.padlookup # no overwrites allowed!
- assert pin.name == corepin.name # has to be the same!
- self.padlookup[pin.name] = core
+ assert pin.name == corepin.name # has to be the same!
+ self.padlookup[pin.name] = pad # store pad by pin name
+
+ # now add the IO Shift Register. first identify the type
+ # then request a JTAG IOConn. we can't wire it up (yet) because
+ # we don't have a Module() instance. doh. that comes in get_input
+ # and get_output etc. etc.
+ iotype = resiotypes[pin.dir] # look up the C4M-JTAG IOType
+ io = self.jtag.add_io(iotype=iotype, name=pin.name) # create IOConn
+ self.jtag.ios[pin.name] = io # store IOConn Record by pin name
# finally return the value just like ResourceManager.request()
return value
# finally return the value just like ResourceManager.request()
return value
p.build(Blinker())
"""
pinset = dummy_pinset()
p.build(Blinker())
"""
pinset = dummy_pinset()
-p = ASICPlatform (pinset)
-p.build(Blinker(pinset))
+resources = create_resources(pinset)
+p = ASICPlatform (resources, top.jtag)
+p.build(top)