return res
-class PBase(object):
+class MMapConfig(object):
+
+ def get_mmap_configs(self):
+ res = []
+ for cfg in self.peripheral.configs:
+ res.append(cfg.get('mmap', None))
+ # XXX HACK! assume all configs same for each peripheral!
+ return res[0]
+
+ def map_to_idx(self, cfg, idx):
+ if isinstance(idx, int):
+ return idx
+ for (i, c) in enumerate(cfg):
+ if c[0] == idx:
+ return i
+ assert "config name %s not found" % s
+
+ def get_mmap_cfg_start(self, idx):
+ cfg = self.get_mmap_configs()
+ if cfg is None:
+ nregs = self.num_axi_regs32()
+ if isinstance(nregs, int) or len(nregs) == 1:
+ return 0
+ return "_%d_" % idx
+ idx = self.map_to_idx(cfg, idx)
+ return cfg[idx][1]
+
+ def get_mmap_cfg_name(self, idx):
+ cfg = self.get_mmap_configs()
+ if cfg is None:
+ nregs = self.num_axi_regs32()
+ if isinstance(nregs, int) or len(nregs) == 1:
+ return ""
+ return "_%d_" % idx
+ return cfg[idx][0]
+
+ def num_axi_regs32cfg(self):
+ cfg = self.get_mmap_configs()
+ if cfg is None:
+ return self.num_axi_regs32()
+ regs = []
+ for c in cfg:
+ regs.append(c[2])
+ return regs
+
+
+class PBase(MMapConfig):
def __init__(self, name):
self.name = name
+ MMapConfig.__init__(self)
def extifdecl(self, name, count):
sname = self.get_iname(count)
if not irqname:
return ''
pirqname = self.irq_name().format(count)
- template = " {0}_interrupt.send(\n" + \
+ template = " {0}.send(\n" + \
" slow_peripherals.{1});"
return template.format(irqname, pirqname)
def get_iname(self, inum):
return "{0}{1}".format(self.name, self.mksuffix(self.name, inum))
- def axibase(self, name, ifacenum):
+ def axibase(self, name, ifacenum, idx):
name = name.upper()
- return "%(name)s%(ifacenum)dBase" % locals()
+ return "%(name)s%(ifacenum)d%(idx)sBase" % locals()
- def axiend(self, name, ifacenum):
+ def axiend(self, name, ifacenum, idx):
name = name.upper()
- return "%(name)s%(ifacenum)dEnd" % locals()
+ return "%(name)s%(ifacenum)d%(idx)sEnd" % locals()
- def axi_reg_def(self, start, name, ifacenum):
+ def _axi_reg_def(self, idx, numregs, start, name, ifacenum):
name = name.upper()
- offs = self.num_axi_regs32() * 4 * 16
+ offs = numregs * 4 * 16
if offs == 0:
return ('', 0)
- end = start + offs - 1
- bname = self.axibase(name, ifacenum)
- bend = self.axiend(name, ifacenum)
- comment = "%d 32-bit regs" % self.num_axi_regs32()
- return (" `define %(bname)s 'h%(start)08X\n"
- " `define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
+ cfgstart = self.get_mmap_cfg_start(idx)
+ if cfgstart:
+ start = cfgstart
+ end = start + offs - 1
+ offs = 0 # don't do contiguous addressing
+ else:
+ end = start + offs - 1
+ bname = self.axibase(name, ifacenum, idx)
+ bend = self.axiend(name, ifacenum, idx)
+ comment = "%d 32-bit regs" % numregs
+ return ("`define %(bname)s 'h%(start)08X\n"
+ "`define %(bend)s 'h%(end)08X // %(comment)s" % locals(),
offs)
+ def axi_reg_def(self, start, name, ifacenum):
+ offs = self.num_axi_regs32cfg()
+ if offs == 0:
+ return ('', 0)
+ if not isinstance(offs, list):
+ offs = [offs]
+ res = []
+ offstotal = 0
+ print offs
+ for (idx, nregs) in enumerate(offs):
+ cfg = self.get_mmap_cfg_name(idx)
+ (txt, off) = self._axi_reg_def(cfg, nregs, start, name, ifacenum)
+ start += off
+ offstotal += off
+ res.append(txt)
+ return ('\n'.join(res), offstotal)
+
def axi_master_name(self, name, ifacenum, typ=''):
name = name.upper()
return "{0}{1}_master_num".format(name, ifacenum)
- def axi_slave_name(self, name, ifacenum, typ=''):
+ def axi_slave_name(self, idx, name, ifacenum, typ=''):
name = name.upper()
- return "{0}{1}_{2}slave_num".format(name, ifacenum, typ)
+ return "{0}{1}{3}_{2}slave_num".format(name, ifacenum, typ, idx)
def axi_master_idx(self, idx, name, ifacenum, typ):
name = self.axi_master_name(name, ifacenum, typ)
return ("typedef {0} {1};".format(idx, name), 1)
def axi_slave_idx(self, idx, name, ifacenum, typ):
- name = self.axi_slave_name(name, ifacenum, typ)
- return ("typedef {0} {1};".format(idx, name), 1)
+ offs = self.num_axi_regs32()
+ if offs == 0:
+ return ''
+ if not isinstance(offs, list):
+ offs = [offs]
+ res = []
+ for (i, nregs) in enumerate(offs):
+ cfg = self.get_mmap_cfg_name(i)
+ name_ = self.axi_slave_name(cfg, name, ifacenum, typ)
+ res.append("typedef {0} {1};".format(idx + i, name_))
+ return ('\n'.join(res), len(offs))
def axi_fastaddr_map(self, name, ifacenum):
return self.axi_addr_map(name, ifacenum, 'fast')
- def axi_addr_map(self, name, ifacenum, typ=""):
- bname = self.axibase(name, ifacenum)
- bend = self.axiend(name, ifacenum)
- name = self.axi_slave_name(name, ifacenum, typ)
+ def _axi_addr_map(self, idx, name, ifacenum, typ=""):
+ bname = self.axibase(name, ifacenum, idx)
+ bend = self.axiend(name, ifacenum, idx)
+ name = self.axi_slave_name(idx, name, ifacenum, typ)
template = """\
if(addr>=`{0} && addr<=`{1})
return tuple2(True,fromInteger(valueOf({2})));
else"""
return template.format(bname, bend, name)
+ def axi_addr_map(self, name, ifacenum, typ=""):
+ offs = self.num_axi_regs32()
+ if offs == 0:
+ return ''
+ if not isinstance(offs, list):
+ offs = [offs]
+ res = []
+ for (idx, nregs) in enumerate(offs):
+ cfg = self.get_mmap_cfg_name(idx)
+ res.append(self._axi_addr_map(cfg, name, ifacenum, typ))
+ return '\n'.join(res)
+
def _mk_pincon(self, name, count, ptyp):
# TODO: really should be using bsv.interface_decl.Interfaces
# pin-naming rules.... logic here is hard-coded to duplicate
ps_ = ps + '_out'
else:
ps_ = ps
- ret.append("mkConnection({0},\n\t\t\t{1}.{2});"
- .format(ps_, n_, fname))
+ cn = self._mk_actual_connection('out', name,
+ count, typ,
+ pname, ps_, n_, fname)
+ ret += cn
fname = None
if p.get('outen'):
fname = self.pinname_outen(pname)
if isinstance(fname, str):
fname = "{0}.{1}".format(n_, fname)
fname = self.pinname_tweak(pname, 'outen', fname)
- ret.append("mkConnection({0}_outen,\n\t\t\t{1});"
- .format(ps, fname))
+ cn = self._mk_actual_connection('outen', name,
+ count, typ,
+ pname, ps, n, fname)
+ ret += cn
if typ == 'in' or typ == 'inout':
fname = self.pinname_in(pname)
if fname:
n_ = "{0}{1}".format(n, count)
n_ = '{0}.{1}'.format(n_, fname)
n_ = self.ifname_tweak(pname, 'in', n_)
- ret.append(
- "mkConnection({1},\n\t\t\t{0});".format(
- ps_, n_))
+ cn = self._mk_actual_connection('in', name,
+ count, typ,
+ pname, ps_, n_, fname)
+ ret += cn
+ return '\n'.join(ret)
+
+ def _mk_vpincon(self, name, count, ptyp, typ, pname, stype=None):
+ if stype is None:
+ stype = pname
+ ret = []
+ ret.append("//%s %s %s %s %s" % (name, ptyp, typ, pname, stype))
+ if ptyp == 'fast':
+ sname = self.get_iname(count)
+ ps = "slow_peripherals.%s" % sname
+ else:
+ sname = self.peripheral.iname().format(count)
+ ps = "pinmux.peripheral_side.%s" % sname
+ n = self.get_iname(count)
+ if typ == 'in':
+ n = "{0}.{1}".format(n, stype)
+ ps_ = "{0}.{1}".format(ps, pname)
+ ret += self._mk_actual_connection(typ, name, count, typ,
+ pname, ps_, n, stype)
+ return '\n'.join(ret)
+
+ def _mk_actual_connection(self, ctype, name, count, typ,
+ pname, ps, n, fname):
+ ret = []
+ ck = self.get_clock_reset(name, count)
+ if ctype == 'out':
+ if ck == PBase.get_clock_reset(self, name, count):
+ ret.append("mkConnection({0},\n\t\t\t{1}.{2});"
+ .format(ps, n, fname))
+ else:
+ n2 = "{0}{1}".format(name, count)
+ sync = '{0}_{1}_sync'.format(n2, pname)
+ ret.append("mkConnection({0},\n\t\t\t{1}.get);"
+ .format(ps, sync))
+ ret.append("mkConnection({0}.put,\n\t\t\t{1}.{2});"
+ .format(sync, n, fname))
+ elif ctype == 'outen':
+ ret.append("mkConnection({0}_outen,\n\t\t\t{1});"
+ .format(ps, fname))
+ elif ctype == 'in':
+ if ck == PBase.get_clock_reset(self, name, count):
+ ret.append("mkConnection({1},\n\t\t\t{0});".format(
+ ps, n))
+ else:
+ n2 = "{0}{1}".format(name, count)
+ sync = '{0}_{1}_sync'.format(n2, pname)
+ ret.append("mkConnection({1}.put,\n\t\t\t{0});".format(
+ ps, sync))
+ ret.append("mkConnection({1},\n\t\t\t{0}.get);".format(
+ sync, n))
+ return ret
+
+ def _mk_clk_con(self, name, count, ctype):
+ ret = []
+ ck = self.get_clock_reset(name, count)
+ if ck == PBase.get_clock_reset(self, name, count):
+ return ''
+ if ctype == 'slow':
+ spc = self.get_clk_spc(ctype)
+ else:
+ spc = ck
+ ck = self.get_clk_spc(ctype)
+ template = "Ifc_sync#({0}) {1}_sync <-mksyncconnection(\n" + \
+ " {2}, {3});"
+ for p in self.peripheral.pinspecs:
+ typ = p['type']
+ pname = p['name']
+ n = name
+ if typ == 'out' or typ == 'inout':
+ fname = self.pinname_out(pname)
+ if not fname:
+ continue
+ if not n.startswith('gpio'): # XXX EURGH! horrible hack
+ n_ = "{0}{1}".format(n, count)
+ else:
+ n_ = n
+ n_ = '{0}_{1}'.format(n_, pname)
+ ret.append(template.format("Bit#(1)", n_, ck, spc))
+ if typ == 'in' or typ == 'inout':
+ fname = self.pinname_in(pname)
+ if not fname:
+ continue
+ #fname = self.pinname_in(pname)
+ n_ = "{0}{1}".format(n, count)
+ n_ = '{0}_{1}'.format(n_, pname)
+ #n_ = self.ifname_tweak(pname, 'in', n_)
+ ret.append(template.format("Bit#(1)", n_, spc, ck))
return '\n'.join(ret)
+ def get_clk_spc(self, ctype):
+ if ctype == 'slow':
+ return "sp_clock, sp_reset"
+ else:
+ return "core_clock, core_reset"
+
+ def _mk_clk_vcon(self, name, count, ctype, typ, pname, bitspec):
+ ck = self.get_clock_reset(name, count)
+ if ck == PBase.get_clock_reset(self, name, count):
+ return ''
+ if ctype == 'slow':
+ spc = self.get_clk_spc(ctype)
+ else:
+ spc = ck
+ ck = self.get_clk_spc(ctype)
+ template = "Ifc_sync#({0}) {1}_sync <-mksyncconnection(\n" + \
+ " {2}, {3});"""
+
+ n_ = "{0}{1}".format(name, count)
+ n_ = '{0}_{1}'.format(n_, pname)
+ if typ == 'in' or typ == 'inout':
+ ck, spc = spc, ck
+ return template.format(bitspec, n_, ck, spc)
+
def mk_cellconn(self, *args):
return ''
def mksuffix(self, name, i):
return i
- def __mk_connection(self, con, aname, fabricname):
+ def __mk_connection(self, con, aname, count, fabricname):
txt = "mkConnection ({2}.v_to_slaves\n" + \
" [fromInteger(valueOf({1}))],\n" + \
" {0});"
print "PBase __mk_connection", self.name, aname
if not con:
return ''
+ con = con.format(count, aname)
return txt.format(con, aname, fabricname)
- def __mk_master_connection(self, con, aname):
- txt = "mkConnection (slow_fabric.v_to_slaves\n" + \
- " [fromInteger(valueOf({1}))],\n" + \
- " {0});"
+ def __mk_master_connection(self, con, aname, count, fabricname):
+ txt = "mkConnection ({0}, {2}.v_from_masters\n" + \
+ " [fromInteger(valueOf({1}))]);\n"
- print "PBase __mk_connection", self.name, aname
+ print "PBase __mk_master_connection", self.name, aname
if not con:
return ''
- return txt.format(con, aname)
+ con = con.format(count, aname)
+ return txt.format(con, aname, fabricname)
+
+ def mk_master_connection(self, count, fabricname, typ, name=None):
+ if not self.has_axi_master():
+ return ''
+ if name is None:
+ name = self.name
+ print "PBase mk_master_conn", self.name, count
+ aname = self.axi_master_name(name, count, typ)
+ ret = []
+ connections = self._mk_connection(name, count, True)
+ if not isinstance(connections, list):
+ connections = [connections]
+ for con in connections:
+ ret.append(self.__mk_master_connection(con, aname, count,
+ fabricname))
+ return '\n'.join(ret)
def mk_connection(self, count, fabricname, typ, name=None):
if name is None:
name = self.name
print "PBase mk_conn", self.name, count
- aname = self.axi_slave_name(name, count, typ)
- #dname = self.mksuffix(name, count)
- #dname = "{0}{1}".format(name, dname)
- con = self._mk_connection(name, count).format(count, aname)
- return self.__mk_connection(con, aname, fabricname)
+ ret = []
+ connections = self._mk_connection(name, count)
+ if not isinstance(connections, list):
+ connections = [connections]
+ for (idx, con) in enumerate(connections):
+ cfg = self.get_mmap_cfg_name(idx)
+ aname = self.axi_slave_name(cfg, name, count, typ)
+ ret.append(self.__mk_connection(con, aname, count, fabricname))
+ return '\n'.join(ret)
def _mk_connection(self, name=None, count=0):
return ''
'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
'mkfast_peripheral',
'mk_plic', 'mk_ext_ifacedef',
- 'mk_connection', 'mk_cellconn', '_mk_pincon']:
+ '_mk_clk_con', 'mk_ext_ifacedef',
+ 'mk_connection', 'mk_master_connection',
+ 'mk_cellconn', '_mk_pincon']:
fn = CallFn(self, fname)
setattr(self, fname, types.MethodType(fn, self))
ret = []
for (name, count) in self.ifacecount:
for i in range(count):
- iname = self.data[name].iname().format(i)
- print "extfast", iname, self.is_on_fastbus(name, i)
if self.is_on_fastbus(name, i):
continue
ret.append(self.data[name].extfastifinstance(name, i))
ret = []
for (name, count) in self.ifacecount:
for i in range(count):
- iname = self.data[name].iname().format(i)
ret.append(self.data[name].extifinstance2(name, i))
return '\n'.join(li(list(filter(None, ret)), 8))
ret = []
for (name, count) in self.ifacecount:
for i in range(count):
- iname = self.data[name].iname().format(i)
if not self.is_on_fastbus(name, i):
continue
ret.append(self.data[name].extifinstance(name, i))
ret.append(x.format(suffix))
return '\n'.join(li(list(filter(None, ret)), 8))
- def mk_fast_connection(self, *args):
+ def _mk_connection(self, fabric, typ, indent, master, *args):
ret = []
for (name, count) in self.ifacecount:
for i in range(count):
if self.is_on_fastbus(name, i):
continue
- txt = self.data[name].mk_connection(i, "fabric", "fast")
+ if master:
+ txt = self.data[name].mk_master_connection(i, fabric, typ)
+ else:
+ txt = self.data[name].mk_connection(i, fabric, typ)
if name == 'gpioa':
print "txt", txt
- print self.data[name].mk_connection
ret.append(txt)
- return '\n'.join(li(list(filter(None, ret)), 12))
+ return '\n'.join(li(list(filter(None, ret)), indent))
+
+ def mk_master_connection(self, *args):
+ return self._mk_connection("fabric", "fast", 8, True, *args)
+
+ def mk_fast_connection(self, *args):
+ return self._mk_connection("fabric", "fast", 12, False, *args)
def mk_connection(self, *args):
- ret = []
- for (name, count) in self.ifacecount:
- for i in range(count):
- if self.is_on_fastbus(name, i):
- continue
- txt = self.data[name].mk_connection(i, "slow_fabric", "")
- if name == 'gpioa':
- print "txt", txt
- print self.data[name].mk_connection
- ret.append(txt)
- return '\n'.join(li(list(filter(None, ret)), 8))
+ return self._mk_connection("slow_fabric", "", 8, False, *args)
def mk_cellconn(self):
ret = []
for i in range(count):
if self.is_on_fastbus(name, i):
continue
- res = self.data[name].mk_cellconn(cellcount, name, i)
+ res = self.data[name].mk_cellconn(name, i, cellcount)
if not res:
continue
(txt, cellcount) = res
def _mk_pincon(self, typ):
ret = []
for (name, count) in self.ifacecount:
- for i in range(count):
- if self.is_on_fastbus(name, i):
- continue
- txt = self.data[name]._mk_pincon(name, i, typ)
- ret.append(txt)
- return '\n'.join(li(list(filter(None, ret)), 4))
+ ret += list(MkPinCon(self, name, count, typ))
+ return '\n'.join(li(list(ret), 4))
def mk_dma_irq(self):
ret = []
def mk_sloirqsdef(self):
return " `define NUM_SLOW_IRQS {0}".format(self.num_slow_irqs)
+ def mk_fastclk_con(self):
+ return self._mk_clk_con("fast")
+
+ def mk_slowclk_con(self):
+ return self._mk_clk_con("slow")
+
+ def _mk_clk_con(self, ctype):
+ ret = []
+ for (name, count) in self.ifacecount:
+ ret += list(MkClkCon(self, name, count, ctype))
+ return '\n'.join(li(list(filter(None, ret)), 8))
+
def is_on_fastbus(self, name, i):
#print "fastbus mode", self.fastbusmode, name, i
iname = self.data[name].iname().format(i)
return iname not in self.fastbus
return iname in self.fastbus
+class IfaceIter(object):
+
+ def __init__(self, name, count, *args):
+ self.i = 0
+ self.name = name
+ self.maxcount = count
+ self.args = args
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ while True:
+ if self.i >= self.maxcount:
+ raise StopIteration
+ if self.check(self.name, self.i):
+ res = self.item(self.name, self.i, *self.args)
+ if res:
+ self.i += 1
+ return res
+ self.i += 1
+
+ def next(self):
+ return self.__next__()
+
+
+class MkPinCon(IfaceIter):
+
+ def __init__(self, ifaces, name, count, *args):
+ self.ifaces = ifaces
+ IfaceIter.__init__(self, name, count, *args)
+
+ def check(self, name, i):
+ return not self.ifaces.is_on_fastbus(name, i)
+
+ def item(self, name, i, typ):
+ return self.ifaces.data[name]._mk_pincon(name, i, typ)
+
+class MkClkCon(IfaceIter):
+
+ def __init__(self, ifaces, name, count, *args):
+ self.ifaces = ifaces
+ IfaceIter.__init__(self, name, count, *args)
+
+ def check(self, name, i):
+ return not self.ifaces.is_on_fastbus(name, i)
+
+ def item(self, name, i, ctype):
+ return self.ifaces.data[name]._mk_clk_con(name, i, ctype)
+
class PFactory(object):
def getcls(self, name):
from uart import uart
from quart import quart
from sdmmc import sdmmc
+ from emmc import emmc
from pwm import pwm
from eint import eint
from rs232 import rs232
from gpio import gpio
from rgbttl import rgbttl
from flexbus import flexbus
+ from sdram import sdram
for k, v in {'uart': uart,
'rs232': rs232,
'twi': twi,
+ 'sdr': sdram,
'quart': quart,
'mqspi': mqspi,
'mspi': mspi,
'spi': spi,
'pwm': pwm,
'eint': eint,
- 'sd': sdmmc,
+ 'mmc': sdmmc,
+ 'emmc': emmc,
'jtag': jtag,
'lcd': rgbttl,
'fb': flexbus,