#!/usr/bin/env python
+from spec.pinfunctions import pinspec
from copy import deepcopy
+def namesuffix(name, suffix, namelist):
+ names = []
+ for n in namelist:
+ if n:
+ names.append("%s%s_%s" % (name, suffix, n))
+ else:
+ names.append("%s_%s" % (name, suffix))
+ return names
+
+
+class PinGen(object):
+ """ a meta-helper which creates pins from the pinspec
+ and adds them to the pinouts.
+
+ __call__ is used to effectively create a lambda function, which
+ in combination with setattr (below) gives the function a name
+ in the Pinouts class, according to the pinspec.
+
+ arguments to __call__ (which ends up as Pinouts.i2s, Pinouts.sdmmc
+ and so on, according to spec.pinfunctions.pinspec) are:
+
+ suffix: e.g. GPIO or SD or SPI
+ offs : a tuple of (Bank, Bank offset) as a string, integer
+ mux : which column in the multiplexer
+ start : the start of a subset of pins to be inserted
+ limit : the end of the subset (or the number if start also given)
+ spec : *EXTRA* pins to be inserted (at different implicit positions)
+
+ the pins are inserted with the suffix, starting from the
+ offset position using offs as the row and mux as the column,
+ and working in a constant increment down the rows.
+
+ spec is slightly complicated, basically there's extra
+ functions that we want to be on the same pin (but a different mux)
+ because their use is mutually-exclusive. without this spec
+ argument the extra pins would need to be MANUALLY moved about
+ during the development of the pinmux, if the "main" pins
+ were also moved about. this would be a pain.
+
+ so instead, extra pins are given of the form:
+ { 'EXTRA1' : ('PREEXISTING_NAME', MUX_COLUMN),
+ ...
+ }
+
+ where the function EXTRA1 will always be placed on the SAME ROW
+ as PREEXISTING_NAME, just in MUX_COLUMN. this may be done
+ several times i.e. multiple new EXTRA functions can be added
+ on the same row as PRE_EXISTING_NAME, just with different
+ MUX_COLUMN values.
+
+ Note: spec must implicitly be in the same Bank.
+ """
+
+ def __init__(self, pinouts, fname, pinfn, bankspec):
+ self.pinouts = pinouts
+ self.bankspec = bankspec
+ self.pinfn = pinfn
+ self.fname = fname
+
+ def __call__(self, suffix, offs, mux,
+ start=None, limit=None, spec=None, origsuffix=None,
+ rev=False):
+ bank = offs[0]
+ pf = self.pinfn(suffix, bank)
+ print ("pf", suffix, bank, pf)
+ pingroup, gangedgroup, clock = pf
+ if clock:
+ self.pinouts.clocks[self.fname] = clock
+ if isinstance(pingroup, tuple):
+ prefix, pingroup = pingroup
+ else:
+ prefix = self.fname
+ if start and limit: # limit turns into an offset from start
+ limit = start + limit
+ sk = "%s:%s" % (self.fname, str(suffix))
+ print ("pingroup pre", sk, pingroup)
+ pingroup = pingroup[start:limit] # see comment in spec.pinfunctions
+ if rev:
+ # reverse order of pingroup
+ pingroup.reverse()
+ print ("pingroup post", sk, pingroup)
+ if sk in self.pinouts.byspec:
+ self.pinouts.byspec[sk] += pingroup
+ else:
+ self.pinouts.byspec[sk] = deepcopy(pingroup)
+ pins = Pins(prefix, pingroup, self.bankspec,
+ suffix, offs, bank, mux,
+ spec, origsuffix=suffix, gangedgrp=gangedgroup)
+ fname = self.pinouts.pinmerge(pins)
+ self.pinouts.setganged(fname, gangedgroup)
+
+# pinouts class
+
+
class Pinouts(object):
- def __init__(self):
+ def __init__(self, bankspec):
+ self.bankspec = bankspec
self.pins = {}
self.fnspec = {}
+ self.ganged = {}
+ self.clocks = {}
+ self.byspec = {}
+ for fname, pinfn in pinspec:
+ if isinstance(pinfn, tuple):
+ name, pinfn = pinfn
+ else:
+ name = pinfn.__name__
+ pin = PinGen(self, fname, pinfn, self.bankspec)
+ setattr(self, name, pin)
+
+ def setganged(self, fname, grp):
+ grp = map(lambda x: x[:-1], grp)
+ if fname not in self.ganged:
+ self.ganged[fname] = []
+ self.ganged[fname] += grp
def __contains__(self, k):
return k in self.pins
if pinidx not in self.pins:
self.pins[pinidx] = v
else:
+ for k in v:
+ assert k not in self.pins[pinidx], \
+ "pin %d position %d already taken\n%s\n%s" % \
+ (pinidx, k, str(v), self.pins[pinidx])
self.pins[pinidx].update(v)
def keys(self):
def __getitem__(self, k):
return self.pins[k]
+ def pinmerge(self, fn):
+ # hack, store the function specs in the pins dict
+ fname = fn.fname
+ suffix = fn.origsuffix
+ bank = fn.bank
+
+ if not hasattr(self, 'fnspec'):
+ self.fnspec = pins
+ if fname == 'GPIO':
+ fname = fname + bank
+ assert 'EINT' not in self
+ if fname not in self.fnspec:
+ self.add_spec(fname, {})
+ if suffix or fname == 'EINT' or fname == 'PWM':
+ specname = fname + suffix
+ else:
+ specname = fname
+ # print "fname bank specname suffix ", fname, bank, specname, repr(
+ # suffix)
+ if specname in self.fnspec[fname]:
+ # ok so some declarations may bring in different
+ # names at different stages (EINT, PWM, flexbus1/2)
+ # so we have to merge the names in. main thing is
+ # the pingroup
+ tomerge = self.fnspec[fname][specname]
+ for p in fn.pingroup:
+ if p not in tomerge.pingroup:
+ tomerge.pingroup.append(p)
+ tomerge.pins.update(fn.pins)
+ tomerge.fntype.update(fn.fntype)
+ else:
+ self.fnspec[fname][specname] = deepcopy(fn)
+
+ # merge actual pins
+ for (pinidx, v) in fn.pins.items():
+ self.update(pinidx, v)
+
+ return fname
+
class Pins(object):
def __init__(self, fname, pingroup, bankspec, suffix, offs, bank, mux,
- spec=None, limit=None, origsuffix=None):
+ spec=None, limit=None, origsuffix=None, gangedgrp=None):
# function type can be in, out or inout, represented by - + *
# strip function type out of each pin name
self.fname = fname
self.pingroup = pingroup
+ self.gangedgroup = gangedgrp
self.bankspec = bankspec
self.suffix = suffix
self.origsuffix = origsuffix or suffix
continue
if name not in spec:
continue
- idx_, mux_, bank_ = spec[name]
+ idx_, mux_ = spec[name]
idx_ = names[idx_]
- pin = {mux_: (name_, bank_)}
+ pin = {mux_: (name_, bank)}
if idx_ in res:
res[idx_].update(pin)
else:
res[idx_] = pin
self.pins = res
-
-
-def i2s(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
- i2spins = ['MCK+', 'BCK+', 'LRCK+', 'DI-', 'DO+']
- # for i in range(4):
- # i2spins.append("DO%d+" % i)
- return Pins('IIS', i2spins, bankspec, suffix, offs, bank, mux, spec, limit,
- origsuffix=suffix)
-
-
-def emmc(bankspec, suffix, offs, bank, mux=1, spec=None):
- emmcpins = ['CMD+', 'CLK+']
- for i in range(8):
- emmcpins.append("D%d*" % i)
- return Pins('MMC', emmcpins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def sdmmc(bankspec, suffix, offs, bank, mux=1, spec=None,
- start=None, limit=None):
- sdmmcpins = ['CMD+', 'CLK+']
- for i in range(4):
- sdmmcpins.append("D%d*" % i)
- sdmmcpins = sdmmcpins[start:limit]
- return Pins('SD', sdmmcpins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def spi(bankspec, suffix, offs, bank, mux=1, spec=None):
- spipins = ['CLK*', 'NSS*', 'MOSI*', 'MISO*']
- return Pins('SPI', spipins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def quadspi(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
- spipins = ['CK*', 'NSS*', 'IO0*', 'IO1*', 'IO2*', 'IO3*']
- return Pins(
- 'QSPI',
- spipins,
- bankspec,
- suffix,
- offs,
- bank,
- mux,
- spec,
- limit,
- origsuffix=suffix)
-
-
-def i2c(bankspec, suffix, offs, bank, mux=1, spec=None):
- spipins = ['SDA*', 'SCL*']
- return Pins('TWI', spipins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def jtag(bankspec, suffix, offs, bank, mux=1, spec=None):
- jtagpins = ['MS+', 'DI-', 'DO+', 'CK+']
- return Pins('JTAG', jtagpins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def uart(bankspec, suffix, offs, bank, mux=1, spec=None):
- uartpins = ['TX+', 'RX-']
- return Pins('UART', uartpins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def namesuffix(name, suffix, namelist):
- names = []
- for n in namelist:
- if n:
- names.append("%s%s_%s" % (name, suffix, n))
- else:
- names.append("%s_%s" % (name, suffix))
- return names
-
-
-def ulpi(bankspec, suffix, offs, bank, mux=1, spec=None):
- ulpipins = ['CK+', 'DIR+', 'STP+', 'NXT+']
- for i in range(8):
- ulpipins.append('D%d*' % i)
- return Pins('ULPI', ulpipins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def uartfull(bankspec, suffix, offs, bank, mux=1, spec=None):
- uartpins = ['TX+', 'RX-', 'CTS-', 'RTS+']
- return Pins('UARTQ', uartpins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def rgbttl(bankspec, suffix, offs, bank, mux=1, spec=None):
- ttlpins = ['CK+', 'DE+', 'HS+', 'VS+']
- for i in range(24):
- ttlpins.append("D%d+" % i)
- return Pins('LCD', ttlpins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def rgmii(bankspec, suffix, offs, bank, mux=1, spec=None):
- buspins = []
- for i in range(4):
- buspins.append("ERXD%d-" % i)
- for i in range(4):
- buspins.append("ETXD%d+" % i)
- buspins += ['ERXCK-', 'ERXERR-', 'ERXDV-',
- 'EMDC+', 'EMDIO*',
- 'ETXEN+', 'ETXCK+', 'ECRS-',
- 'ECOL+', 'ETXERR+']
- return Pins('RG', buspins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def flexbus1(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
- buspins = []
- for i in range(8):
- buspins.append("AD%d*" % i)
- for i in range(2):
- buspins.append("CS%d+" % i)
- buspins += ['ALE', 'OE', 'RW', 'TA', 'CLK+',
- 'A0', 'A1', 'TS', 'TBST',
- 'TSIZ0', 'TSIZ1']
- for i in range(4):
- buspins.append("BWE%d" % i)
- for i in range(2, 6):
- buspins.append("CS%d+" % i)
- return Pins('FB', buspins, bankspec, suffix, offs, bank, mux, spec, limit,
- origsuffix=suffix)
-
-
-def flexbus2(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
- buspins = []
- for i in range(8, 32):
- buspins.append("AD%d*" % i)
- return Pins('FB', buspins, bankspec, suffix, offs, bank, mux, spec, limit,
- origsuffix=suffix)
-
-
-def sdram1(bankspec, suffix, offs, bank, mux=1, spec=None):
- buspins = []
- for i in range(16):
- buspins.append("SDRDQM%d*" % i)
- for i in range(12):
- buspins.append("SDRAD%d+" % i)
- for i in range(8):
- buspins.append("SDRDQ%d+" % i)
- for i in range(3):
- buspins.append("SDRCS%d#+" % i)
- for i in range(2):
- buspins.append("SDRDQ%d+" % i)
- for i in range(2):
- buspins.append("SDRBA%d+" % i)
- buspins += ['SDRCKE+', 'SDRRAS#+', 'SDRCAS#+', 'SDRWE#+',
- 'SDRRST+']
- return Pins('SDR', buspins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def sdram2(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
- buspins = []
- for i in range(3, 6):
- buspins.append("SDRCS%d#+" % i)
- for i in range(8, 32):
- buspins.append("SDRDQ%d*" % i)
- return Pins('SDR', buspins, bankspec, suffix, offs, bank, mux, spec, limit,
- origsuffix=suffix)
-
-
-def mcu8080(bankspec, suffix, offs, bank, mux=1, spec=None):
- buspins = []
- for i in range(8):
- buspins.append("MCUD%d*" % i)
- for i in range(8):
- buspins.append("MCUAD%d+" % (i + 8))
- for i in range(6):
- buspins.append("MCUCS%d+" % i)
- for i in range(2):
- buspins.append("MCUNRB%d+" % i)
- buspins += ['MCUCD+', 'MCURD+', 'MCUWR+', 'MCUCLE+', 'MCUALE+',
- 'MCURST+']
- return Pins('MCU', buspins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def _pinbank(bankspec, prefix, suffix, offs, bank, gpiooffs, gpionum=1, mux=1,
- spec=None):
- gpiopins = []
- for i in range(gpiooffs, gpiooffs + gpionum):
- gpiopins.append("%s%d*" % (bank, i))
- return Pins(prefix, gpiopins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def eint(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
- gpiopins = []
- for i in range(gpiooffs, gpiooffs + gpionum):
- gpiopins.append("%d*" % (i))
- return Pins('EINT', gpiopins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def pwm(bankspec, suffix, offs, bank, pwmoffs, pwmnum=1, mux=1, spec=None):
- pwmpins = []
- for i in range(pwmoffs, pwmoffs + pwmnum):
- pwmpins.append("%d+" % (i))
- return Pins('PWM', pwmpins, bankspec, suffix, offs, bank, mux, spec,
- origsuffix=suffix)
-
-
-def gpio(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
- return _pinbank(bankspec, "GPIO%s" % bank, suffix, offs, bank, gpiooffs,
- gpionum, mux=0, spec=None)
-
-
-def pinmerge(pins, fn):
- # hack, store the function specs in the pins dict
- fname = fn.fname
- suffix = fn.origsuffix
- bank = fn.bank
-
- if not hasattr(pins, 'fnspec'):
- pins.fnspec = pins
- if fname == 'GPIO':
- fname = fname + bank
- assert 'EINT' not in pins
- if fname not in pins.fnspec:
- pins.add_spec(fname, {})
- if suffix or fname == 'EINT' or fname == 'PWM':
- specname = fname + suffix
- else:
- specname = fname
- print "fname bank specname suffix ", fname, bank, specname, repr(suffix)
- if specname in pins.fnspec[fname]:
- # ok so some declarations may bring in different
- # names at different stages (EINT, PWM, flexbus1/2)
- # so we have to merge the names in. main thing is
- # the pingroup
- tomerge = pins.fnspec[fname][specname]
- for p in fn.pingroup:
- if p not in tomerge.pingroup:
- tomerge.pingroup.append(p)
- tomerge.pins.update(fn.pins)
- tomerge.fntype.update(fn.fntype)
- else:
- pins.fnspec[fname][specname] = deepcopy(fn)
-
- # merge actual pins
- for (pinidx, v) in fn.pins.items():
- pins.update(pinidx, v)