from spec.iomux import IOMuxBlockSingle
from spec.base import PinSpec
from spec.jtag import iotypes
+from spec.pinfunctions import pinspec
+
+import code
io_layout = (("i", 1),
("oe", 1),
Really basic example, uart tx/rx and i2c sda/scl pinmux
"""
class ManPinmux(Elaboratable):
- def __init__(self, requested):
+ def __init__(self, ps):
print("Test Manual Pinmux!")
+ self.gen_pinmux_dict(ps)
- self.requested = requested
- self.n_ports = 4
- self.port = Signal(log2_int(self.n_ports))
self.pads = {}
- self.muxes = {}
+
+ print("--------------------")
# Automatically create the necessary periph/pad Records/Signals
# depending on the given dict specification
for pad in self.requested.keys():
self.pads[pad] = {}
self.pads[pad]["pad"] = Record(name=pad, layout=io_layout)
- self.muxes[pad] = IOMuxBlockSingle(self.n_ports)
+ self.pads[pad]["n_ports"] = len(self.requested[pad])
+ if self.pads[pad]["n_ports"] == 1:
+ pass # skip mux creation
+ else:
+ print(self.pads[pad]["n_ports"])
+ # Need to determine num of bits - to make number a pow of 2
+ portsize = self.pads[pad]["n_ports"].bit_length()
+ self.pads[pad]["port"] = Signal(portsize, name="%s_port" % (pad))
+ self.muxes[pad] = IOMuxBlockSingle(self.pads[pad]["n_ports"])
for mux in self.requested[pad].keys():
- periph = self.requested[pad][mux][0]
- unit = self.requested[pad][mux][1]
- sig = self.requested[pad][mux][2][:-1]
- sig_type = iotypes[self.requested[pad][mux][2][-1]]
+ periph = self.requested[pad][mux]["periph"]
+ suffix = self.requested[pad][mux]["suffix"]
+ sig = self.requested[pad][mux]["signal"][:-1]
+ sig_type = iotypes[self.requested[pad][mux]["signal"][-1]]
#print(sig, sig_type)
if sig_type == iotypes['*']:
- self.pads[pad][mux] = Record(name="%s%d" % (sig, unit),
+ self.pads[pad][mux] = Record(name="%s%s" % (sig, suffix),
layout=io_layout)
elif sig_type == iotypes['+']:
- self.pads[pad][mux] = Signal(name="%s%d_o" % (sig, unit))
+ self.pads[pad][mux] = Signal(name="%s%s_o" % (sig, suffix))
elif sig_type == iotypes['-']:
- self.pads[pad][mux] = Signal(name="%s%d_i" % (sig, unit))
+ self.pads[pad][mux] = Signal(name="%s%s_i" % (sig, suffix))
print(self.pads)
def elaborate(self, platform):
m = Module()
comb, sync = m.d.comb, m.d.sync
muxes = self.muxes
- port = self.port
pads = self.pads
for pad in pads.keys():
- m.submodules[pad+"_mux"] = muxes[pad]
- # all muxes controlled by the same multi-bit signal
- comb += muxes[pad].port.eq(port)
+ if len(self.requested[pad]) == 1:
+ pass
+ else:
+ port = self.pads[pad]["port"]
+ m.submodules[pad+"_mux"] = muxes[pad]
+ # TODO: all muxes controlled by the same multi-bit signal
+ comb += muxes[pad].port.eq(port)
# print(self.requested)
# print(self.pads)
# This section connects the periphs to the assigned ports
# ---------------------------
for pad in pads.keys():
- for mux in self.requested[pad].keys():
- periph = self.requested[pad][mux][0]
- num = int(mux[3])
- sig = self.requested[pad][mux][2][:-1]
- sig_type = iotypes[self.requested[pad][mux][2][-1]]
+ if len(self.requested[pad]) == 1:
+ # connect directly
+ mux = 0 # assume only port0 has been defined
+ print(self.requested[pad])
+ periph = self.requested[pad][mux]["periph"]
+ #suffix = self.requested[pad][mux]["suffix"]
+ sig = self.requested[pad][mux]["signal"][:-1]
+ sig_type = iotypes[self.requested[pad][mux]["signal"][-1]]
if sig_type == iotypes['*']:
- comb += muxes[pad].periph_ports[num].o.eq(pads[pad][mux].o)
- comb += muxes[pad].periph_ports[num].oe.eq(
- pads[pad][mux].oe)
- comb += pads[pad][mux].i.eq(muxes[pad].periph_ports[num].i)
+ comb += pads[pad]["pad"].o.eq(pads[pad][mux].o)
+ comb += pads[pad]["pad"].oe.eq(pads[pad][mux].oe)
+ comb += pads[pad][mux].i.eq(pads[pad]["pad"].i)
elif sig_type == iotypes['+']:
- comb += muxes[pad].periph_ports[num].o.eq(pads[pad][mux])
+ comb += pads[pad]["pad"].o.eq(pads[pad][mux].o)
elif sig_type == iotypes['-']:
- comb += pads[pad][mux].eq(muxes[pad].periph_ports[num].i)
+ comb += pads[pad][mux].i.eq(pads[pad]["pad"].i)
+ else:
+ for mux in self.requested[pad].keys():
+ periph = self.requested[pad][mux]["periph"]
+ #suffix = self.requested[pad][mux]["suffix"]
+ sig = self.requested[pad][mux]["signal"][:-1]
+ sig_type = iotypes[self.requested[pad][mux]["signal"][-1]]
+ num = int(mux)
+ print(pad, mux, sig, sig_type)
+ print(len(muxes[pad].periph_ports))
+ if sig_type == iotypes['*']:
+ comb += muxes[pad].periph_ports[num].o.eq(
+ pads[pad][mux].o)
+ comb += muxes[pad].periph_ports[num].oe.eq(
+ pads[pad][mux].oe)
+ comb += pads[pad][mux].i.eq(
+ muxes[pad].periph_ports[num].i)
+ elif sig_type == iotypes['+']:
+ comb += muxes[pad].periph_ports[num].o.eq(
+ pads[pad][mux])
+ elif sig_type == iotypes['-']:
+ comb += pads[pad][mux].eq(
+ muxes[pad].periph_ports[num].i)
# ---------------------------
# Here is where the muxes are assigned to the actual pads
# ---------------------------
for pad in pads.keys():
- comb += pads[pad]["pad"].o.eq(muxes[pad].out_port.o)
- comb += pads[pad]["pad"].oe.eq(muxes[pad].out_port.oe)
- comb += muxes[pad].out_port.i.eq(pads[pad]["pad"].i)
+ if len(self.requested[pad]) == 1:
+ pass # if only one periph, no mux present
+ else:
+ comb += pads[pad]["pad"].o.eq(muxes[pad].out_port.o)
+ comb += pads[pad]["pad"].oe.eq(muxes[pad].out_port.oe)
+ comb += muxes[pad].out_port.i.eq(pads[pad]["pad"].i)
return m
def __iter__(self):
+ print("=============")
+ print(self.pads)
+ print("=============")
for pad in list(self.pads.keys()):
for field in self.pads[pad]["pad"].fields.values():
yield field
for mux in self.pads[pad].keys():
+ print(type(self.pads[pad][mux]))
+ print(pad, mux, self.pads[pad][mux])
if type(self.pads[pad][mux]) == Signal:
yield self.pads[pad][mux]
- else:
+ elif type(self.pads[pad][mux]) == Record:
for field in self.pads[pad][mux].fields.values():
yield field
- yield self.port
+ else:
+ print("%s is a var, not Sig/Rec, skipping!" % mux)
def ports(self):
return list(self)
-def set_port(dut, port, delay=1e-6):
- yield dut.port.eq(port)
- yield Delay(delay)
+ def gen_pinmux_dict(self, ps, write_file=False):
+ if write_file:
+ with open("test.mdwn", "w") as of:
+ pinout, bankspec, pin_spec, fixedpins = ps.write(of)
+ #print(ps.items())
+ #print(ps.byspec)
+ #print(ps.fnspec)
+ # TODO: get from ps
+ self.requested = {}
+ self.muxes = {}
+
+ # Create local list of peripheral names defined in pinfunctions.py
+ defined_func = []
+ for pfunc in pinspec:
+ defined_func.append(pfunc[0])
+
+ for pin in ps.items():
+ pin_no = pin[0]
+ for mux in pin[1].keys():
+ bank = pin[1][mux][1]
+ signal_str = pin[1][mux][0]
+ pad = "%s%d" % (bank, pin_no)
+ # Get the signal name prefix
+ index_under = signal_str.find('_')
+ """
+ periph format: [periph+suffix]
+ GPIO periph format: [periph+bank+suffix]
+ Problem is that GPIO has a different suffix to UART/TWI.
+ Assuming that other peripherals may have their own name formats.
+ keep stripping last chars from string until remainder matches
+ one of the existing peripheral names
+ probably very inefficient...
+ NO ERROR CHECKING
+ """
+ periph = signal_str[:index_under]
+ func = signal_str[index_under+1:]
+ while periph != '':
+ if periph in defined_func:
+ break # Found valid periph
+ periph = periph.rstrip(periph[-1])
+
+ # flag for peripheral string, needed as GPIO has a diff format
+ # to UART and TWI, TODO: may need to check for other periph
+ if periph == "GPIO":
+ check_string = periph + bank
+ else:
+ check_string = periph
+
+ # Find the suffix for the specified periph/pin
+ suffix = ''
+ for a in ps.fnspec.items():
+ for key in a[1]:
+ if check_string in key:
+ print(key, a[1][key])
+ suffix = a[1][key].suffix
+ else:
+ continue
+
+ # key to use in PinSpec.byspec has format: [perith+':'+suffix]
+ # need to get the suffix from Pin object
+ #index = len(periph)
+ #print(signal_str[index:index_under])
+ signal = ''
+ for sig_spec in ps.byspec[periph+':'+suffix]:
+ if func in sig_spec:
+ signal = sig_spec
+ #suffix = ps.fnspec[fnspec_key][fnspec_key]
+ print(pad, signal_str, signal_str[:index_under],
+ periph, func, suffix, signal, mux)
+ print("Now adding to internal pinmux dict")
+ if not (pad in self.requested.keys()):
+ self.requested[pad] = {}
+ self.requested[pad][mux] = {"periph":periph, "suffix":suffix,
+ "signal":signal}
+ print(self.requested)
+
+def set_port(dut, pad, port, delay=1e-6):
+ if dut.pads[pad]["n_ports"] == 1:
+ print("Pad %s only has one function, skipping setting mux!" % pad)
+ else:
+ yield dut.pads[pad]["port"].eq(port)
+ yield Delay(delay)
"""
GPIO test function
yield sda.o.eq(1) # 'release' the SDA line
# Test the GPIO/UART/I2C connectivity
-def test_man_pinmux(dut, requested):
+def test_man_pinmux(dut):
+ requested = dut.requested
# TODO: Convert to automatic
# [{"pad":%s, "port":%d}, {"pad":%s, "port":%d},...]
#gpios = [{"padname":"N1", "port":GPIO_MUX},
# {"padname":"N2", "port":GPIO_MUX}]
# [[txPAD, MUXx, rxPAD, MUXx],...] - diff ports not supported yet
- uarts = [{"txpadname":"N1", "rxpadname":"N2", "mux":UART_MUX}]
+ #uarts = [{"txpadname":"N1", "rxpadname":"N2", "mux":UART_MUX}]
+ uarts = {}
# [[sdaPAD, MUXx, sclPAD, MUXx],...] - diff ports not supported yet
- i2cs = [{"sdapadname":"N1", "sclpadname":"N2", "mux":I2C_MUX}]
+ #i2cs = [{"sdapadname":"N1", "sclpadname":"N2", "mux":I2C_MUX}]
+ i2cs = {}
gpios = []
delay = 1e-6
for pad in requested.keys():
for mux in requested[pad].keys():
- periph = requested[pad][mux][0]
-
- if periph == "gpio":
+ periph = requested[pad][mux]["periph"]
+ suffix = requested[pad][mux]["suffix"]
+ if periph == "GPIO":
# [{"padname":%s, "port": %d}, ...]
- gpios.append({"padname":pad, "mux": int(mux[3])})
- if periph == "uart":
- # TODO:
- pass
- if periph == "i2c":
- # TODO:
- pass
+ gpios.append({"padname":pad, "mux": mux})
+ if periph == "UART":
+ # Make sure dict exists
+ if not (suffix in uarts.keys()):
+ uarts[suffix] = {}
+
+ if requested[pad][mux]["signal"][:-1] == "TX":
+ uarts[suffix]["txpadname"] = pad
+ uarts[suffix]["txmux"] = mux
+ elif requested[pad][mux]["signal"][:-1] == "RX":
+ uarts[suffix]["rxpadname"] = pad
+ uarts[suffix]["rxmux"] = mux
+ if periph == "TWI":
+ if not (suffix in i2cs.keys()):
+ i2cs[suffix] = {}
+ if requested[pad][mux]["signal"][:-1] == "SDA":
+ i2cs[suffix]["sdapadname"] = pad
+ i2cs[suffix]["sdamux"] = mux
+ elif requested[pad][mux]["signal"][:-1] == "SCL":
+ i2cs[suffix]["sclpadname"] = pad
+ i2cs[suffix]["sclmux"] = mux
print(gpios)
+ print(uarts)
+ print(i2cs)
+
# GPIO test
for gpio_periph in gpios:
padname = gpio_periph["padname"]
gpio_port = gpio_periph["mux"]
- gp = dut.pads[padname]["mux%d" % gpio_port]
+ gp = dut.pads[padname][gpio_port]
pad = dut.pads[padname]["pad"]
- yield from set_port(dut, gpio_port)
+ yield from set_port(dut, padname, gpio_port)
yield from gpio(gp, pad, 0x5a5)
# UART test
- for uart_periph in uarts:
- txpadname = uart_periph["txpadname"]
- rxpadname = uart_periph["rxpadname"]
- uart_port = uart_periph["mux"]
- tx = dut.pads[txpadname]["mux%d" % uart_port]
- rx = dut.pads[rxpadname]["mux%d" % uart_port]
+ for suffix in uarts.keys():
+ txpadname = uarts[suffix]["txpadname"]
+ rxpadname = uarts[suffix]["rxpadname"]
+ txport = uarts[suffix]["txmux"]
+ rxport = uarts[suffix]["rxmux"]
+ tx = dut.pads[txpadname][txport]
+ rx = dut.pads[rxpadname][rxport]
txpad = dut.pads[txpadname]["pad"]
rxpad = dut.pads[rxpadname]["pad"]
- yield from set_port(dut, UART_MUX)
+ yield from set_port(dut, txpadname, txport)
+ yield from set_port(dut, rxpadname, rxport)
yield from uart_send(tx, rx, txpad, rxpad, 0x42)
# I2C test
- for i2c_periph in i2cs:
- sdapadname = i2c_periph["sdapadname"]
- sclpadname = i2c_periph["sclpadname"]
- i2c_port = i2c_periph["mux"]
- sda = dut.pads[sdapadname]["mux%d" % i2c_port]
- scl = dut.pads[sclpadname]["mux%d" % i2c_port]
+ for suffix in i2cs.keys():
+ sdapadname = i2cs[suffix]["sdapadname"]
+ sclpadname = i2cs[suffix]["sclpadname"]
+ sdaport = i2cs[suffix]["sdamux"]
+ sclport = i2cs[suffix]["sclmux"]
+ sda = dut.pads[sdapadname][sdaport]
+ scl = dut.pads[sclpadname][sclport]
sdapad = dut.pads[sdapadname]["pad"]
-
- yield from set_port(dut, I2C_MUX)
- yield from i2c_send(sda, scl, sdapad, 0x67)
+ yield from set_port(dut, sdapadname, sdaport)
+ yield from set_port(dut, sclpadname, sclport)
+ yield from i2c_send(sda, scl, sdapad, 0x67)
def gen_gtkw_doc(module_name, requested, filename):
# GTKWave doc generation
temp_traces[1].append(('%s__i' % pad, 'in'))
temp_traces[1].append(('%s__o' % pad, 'out'))
temp_traces[1].append(('%s__oe' % pad, 'out'))
+ # Port signal - only exists if more than one periph per pad
+ if len(requested[pad]) >= 1:
+ temp_traces[1].append(('%s_port[%d:0]'
+ % (pad, (n_ports-1).bit_length()-1), 'in'))
+
+ traces.append(temp_traces)
+ temp_traces = ("Pad %s Peripherals" % pad, [])
for mux in requested[pad].keys():
- periph = requested[pad][mux][0]
- unit_num = requested[pad][mux][1]
- if len(requested[pad][mux]) == 3:
- pin = requested[pad][mux][2]
+ periph = requested[pad][mux]["periph"]
+ suffix = requested[pad][mux]["suffix"]
+ # TODO: cleanup
+ pin = requested[pad][mux]["signal"][:-1]
+
+ sig_type = iotypes[requested[pad][mux]["signal"][-1]]
+ #print(sig, sig_type)
+ if periph == "GPIO":
+ name_format = "%s%s" % (pin, suffix)
else:
- pin = "io"
-
- if periph == "gpio":
- temp_traces[1].append(('gp%d__i' % unit_num, 'in'))
- temp_traces[1].append(('gp%d__o' % unit_num, 'out'))
- temp_traces[1].append(('gp%d__oe' % unit_num, 'out'))
- elif periph == "uart":
- if pin == "tx":
- temp_traces[1].append(('tx%d__o' % unit_num, 'out'))
- temp_traces[1].append(('tx%d__oe' % unit_num, 'out'))
- pass
- elif pin == "rx":
- temp_traces[1].append(('rx%d' % unit_num, 'in'))
- pass
- elif periph == "i2c":
- temp_traces[1].append(('%s%d__i' % (pin, unit_num), 'in'))
- temp_traces[1].append(('%s%d__o' % (pin, unit_num), 'out'))
- temp_traces[1].append(('%s%d__oe' % (pin, unit_num), 'out'))
+ name_format = "%s%s" % (pin, suffix)
+ if sig_type == iotypes['*']:
+ temp_traces[1].append(('%s__i' % name_format, 'in'))
+ temp_traces[1].append(('%s__o' % name_format, 'out'))
+ temp_traces[1].append(('%s__oe' % name_format, 'out'))
+ # Single underscore because Signal, not Record
+ if sig_type == iotypes['+']:
+ temp_traces[1].append(('%s_o' % name_format, 'out'))
+ if sig_type == iotypes['-']:
+ temp_traces[1].append(('%s_i' % name_format, 'in'))
traces.append(temp_traces)
- # master port signal
- temp_traces = ('Misc', [
- ('port[%d:0]' % ((n_ports-1).bit_length()-1), 'in')
- ])
- traces.append(temp_traces)
-
#print(traces)
write_gtkw(filename+".gtkw", filename+".vcd", traces, style,
module=module_name)
-def sim_man_pinmux():
+def sim_man_pinmux(ps):
filename = "test_man_pinmux"
+ """
requested = {"N1": {"mux%d" % GPIO_MUX: ["gpio", 0, '0*'],
"mux%d" % UART_MUX: ["uart", 0, 'tx+'],
"mux%d" % I2C_MUX: ["i2c", 0, 'sda*']},
"N3": {"mux%d" % GPIO_MUX: ["gpio", 2, '0*']},
"N4": {"mux%d" % GPIO_MUX: ["gpio", 3, '0*']}
}
- dut = ManPinmux(requested)
+ """
+ dut = ManPinmux(ps)
vl = rtlil.convert(dut, ports=dut.ports())
with open(filename+".il", "w") as f:
f.write(vl)
sim = Simulator(m)
- sim.add_process(wrap(test_man_pinmux(dut, requested)))
+ sim.add_process(wrap(test_man_pinmux(dut)))
sim_writer = sim.write_vcd(filename+".vcd")
with sim_writer:
sim.run()
gen_gtkw_doc("top.manpinmux", dut.requested, filename)
+
if __name__ == '__main__':
- sim_man_pinmux()
#pinbanks = []
#fixedpins = []
#function_names = []
#testspec = PinSpec()
pinbanks = {
'A': (4, 4), # bankname: (num of pins, muxwidth)
- #'B': (18, 4),
+ 'B': (2, 4),
#'C': (24, 1),
#'D': (93, 1),
}
ps = PinSpec(pinbanks, fixedpins, function_names)
# Unit number, (Bank, pin #), mux, start, num # pins
ps.gpio("", ('A', 0), 0, 0, 4)
+ ps.gpio("2", ('B', 0), 0, 0, 2)
ps.uart("0", ('A', 0), 1)
ps.i2c("0", ('A', 0), 2)
+ sim_man_pinmux(ps)
- print(dir(ps.gpio))
- #print(ps.gpio.pinouts, ps.gpio.bankspec, ps.gpio.pinfn, ps.gpio.fname)
"""
desc_dict_keys = ['UART0', 'TWI0', 'GPIOA_A0', 'GPIOA_A1', 'GPIOA_A2',
'GPIOA_A3']
'GPIOA_A3': 'Test GPIO3'}
ps.add_scenario("Test Manual Pinmux", desc_dict_keys, eint, pwm, desc)
"""
- print("---------------------------------")
- #with open("test.mdwn", "w") as of:
- # pinout, bankspec, pin_spec, fixedpins = ps.write(of)
- #print("---------------------------------")
-
- bk = ps.pinbanks.keys()
- for bank in bk:
- muxwidth = ps.muxwidths[bank]
- print(bank, muxwidth)
- pinidx = sorted(ps.keys())
- for pin in pinidx:
- print("---------------------------------")
- print(pin)
- pdata = ps.get(pin)
- for mux in range(muxwidth):
- if mux not in pdata:
- print("Mux %d : NC" % mux)
- else:
- name, assigned_bank = pdata[mux]
- print("Mux %d : %s" % (mux, name))
-
-
-
+ #gen_pinmux_dict(ps)
+ #code.interact(local=locals())