move slowifdeclmux to class
[pinmux.git] / src / bsv / peripheral_gen / base.py
index 15d029576747dec3ab33b28f24f349c212bbd056..6a22061cb8a14aad4f174619ecf63b6c29b6b1aa 100644 (file)
 import types
-from copy import deepcopy
 
 
-class PBase(object):
+def li(txt, indent):
+    indent = ' ' * indent
+    istxt = False
+    if isinstance(txt, str):
+        istxt = True
+        txt = txt.split('\n')
+    res = []
+    for line in txt:
+        line = line.split('\n')
+        res += line
+    txt = res
+    res = []
+    for line in txt:
+        res.append(indent + line)
+    if istxt:
+        res = '\n'.join(res)
+    return res
+
+
+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)
+        return "interface PeripheralSide%s %s;" % (name.upper(), sname)
+
+    def has_axi_master(self):
+        return False
+
+    def irq_name(self):
+        return ""
 
-    def slowifdeclmux(self):
+    def mk_dma_irq(self, name, count):
+        if not self.irq_name():
+            return ''
+        sname = self.get_iname(count)
+        return "{0}_interrupt".format(sname)
+
+    def mk_dma_rule(self, name, count):
+        irqname = self.mk_dma_irq(name, count)
+        if not irqname:
+            return ''
+        pirqname = self.irq_name().format(count)
+        template = "   {0}.send(\n" + \
+                   "           slow_peripherals.{1});"
+        return template.format(irqname, pirqname)
+
+    def get_clock_reset(self, name, count):
+        return "slow_clock,slow_reset"
+
+    def mk_dma_sync(self, name, count):
+        irqname = self.mk_dma_irq(name, count)
+        if not irqname:
+            return ''
+        sname = self.peripheral.iname().format(count)
+        template = "SyncBitIfc#(Bit#(1)) {0} <-\n" + \
+                   "           <-mkSyncBitToCC({1});"
+        return template.format(irqname, self.get_clock_reset(name, count))
+
+    def mk_dma_connect(self, name, count):
+        irqname = self.mk_dma_irq(name, count)
+        if not irqname:
+            return ''
+        return "{0}.read".format(irqname)
+
+    def fastifdecl(self, name, count):
         return ''
 
-    def slowifinstance(self):
+    def slowifdeclmux(self, name, count):
         return ''
 
     def slowimport(self):
@@ -24,45 +132,101 @@ class PBase(object):
     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_slave_name(self, name, ifacenum):
+    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, idx, name, ifacenum, typ=''):
         name = name.upper()
-        return "{0}{1}_slave_num".format(name, ifacenum)
+        return "{0}{1}{3}_{2}slave_num".format(name, ifacenum, typ, idx)
 
-    def axi_slave_idx(self, idx, name, ifacenum):
-        name = self.axi_slave_name(name, ifacenum)
+    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_addr_map(self, name, ifacenum):
-        bname = self.axibase(name, ifacenum)
-        bend = self.axiend(name, ifacenum)
-        name = self.axi_slave_name(name, ifacenum)
-        return """\
-        if(addr>=`{0} && addr<=`{1})
-            return tuple2(True,fromInteger(valueOf({2})));
-        else""".format(bname, bend, name)
+    def axi_slave_idx(self, idx, name, ifacenum, typ):
+        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, 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):
+    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
         # it (see Interface.__init__ outen)
@@ -72,11 +236,16 @@ class PBase(object):
             pname = p['name']
             #n = "{0}{1}".format(self.name, self.mksuffix(name, count))
             n = name  # "{0}{1}".format(self.name, self.mksuffix(name, count))
-            ret.append("    //%s %s" % (n, str(p)))
-            sname = self.peripheral.pname(pname).format(count)
-            ps = "pinmux.peripheral_side.%s" % sname
+            ret.append("//%s %s" % (n, str(p)))
+            if ptyp == 'fast':
+                sname = self.get_iname(count)
+                sname = "{0}.{1}".format(sname, pname)
+                ps = "slow_peripherals.%s" % sname
+            else:
+                sname = self.peripheral.iname().format(count)
+                sname = "{0}.{1}".format(sname, pname)
+                ps = "pinmux.peripheral_side.%s" % sname
             if typ == 'out' or typ == 'inout':
-                ret.append("    rule con_%s%d_%s_out;" % (name, count, pname))
                 fname = self.pinname_out(pname)
                 if not n.startswith('gpio'):  # XXX EURGH! horrible hack
                     n_ = "{0}{1}".format(n, count)
@@ -87,7 +256,10 @@ class PBase(object):
                         ps_ = ps + '_out'
                     else:
                         ps_ = ps
-                    ret.append("      {0}({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)
@@ -95,8 +267,10 @@ class PBase(object):
                     if isinstance(fname, str):
                         fname = "{0}.{1}".format(n_, fname)
                     fname = self.pinname_tweak(pname, 'outen', fname)
-                    ret.append("      {0}_outen({1});".format(ps, fname))
-                ret.append("    endrule")
+                    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:
@@ -104,44 +278,186 @@ class PBase(object):
                         ps_ = ps + '_in'
                     else:
                         ps_ = ps
-                    ret.append(
-                        "    rule con_%s%d_%s_in;" %
-                        (name, count, pname))
                     n_ = "{0}{1}".format(n, count)
                     n_ = '{0}.{1}'.format(n_, fname)
                     n_ = self.ifname_tweak(pname, 'in', n_)
-                    ret.append("      {1}({0});".format(ps_, n_))
-                    ret.append("    endrule")
+                    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 mkfast_peripheral(self, size=0):
+        return ''
+
     def mkslow_peripheral(self, size=0):
         return ''
 
     def mksuffix(self, name, i):
         return i
 
-    def __mk_connection(self, con, aname):
-        txt = "        mkConnection (slow_fabric.v_to_slaves\n" + \
-            "                    [fromInteger(valueOf({1}))],\n" + \
-            "                    {0});"
+    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 ''
-        return txt.format(con, aname)
-
-    def mk_connection(self, count, name=None):
-        if name is None:
-            name = self.name
-        print "PBase mk_conn", self.name, count
-        aname = self.axi_slave_name(name, count)
-        #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)
+        con = con.format(count, aname)
+        return txt.format(con, aname, fabricname)
+
+    def __mk_master_connection(self, con, aname, count, fabricname):
+        txt = "mkConnection ({0}, {2}.v_from_masters\n" + \
+              "            [fromInteger(valueOf({1}))]);\n"
+
+        print "PBase __mk_master_connection", self.name, aname
+        if not con:
+            return ''
+        con = con.format(count, aname)
+        return txt.format(con, aname, fabricname)
+
+    def mk_master_connection(self, name, count, fabricname, typ):
+        if not self.has_axi_master():
+            return ''
+        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, name, count, fabricname, typ, name_override=None):
+        if name_override:  # needed for GPIO
+            name = name_override
+        print "PBase mk_conn", name, count
+        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 ''
@@ -171,570 +487,80 @@ class PBase(object):
         if niq == 0:
             return ('', irq_offs)
         name = self.get_iname(inum)
-        res.append("    // PLIC rules for {0}".format(name))
+        res.append("// PLIC rules for {0}".format(name))
         for idx in range(niq):
             plic_obj = self.plic_object(name, idx)
             print "plic_obj", name, idx, plic_obj
             plic = mkplic_rule.format(name, plic_obj, irq_offs)
             res.append(plic)
-            irq_offs += 1 # increment to next irq
+            irq_offs += 1  # increment to next irq
         return ('\n'.join(res), irq_offs)
 
     def mk_ext_ifacedef(self, iname, inum):
         return ''
 
-
-mkplic_rule = """\
-     rule rl_connect_{0}_to_plic_{2};
-        if({1} == 1'b1) begin
-            ff_gateway_queue[{2}].enq(1);
-            plic.ifc_external_irq[{2}].irq_frm_gateway(True);
-        end
-     endrule
-"""
-
-class uart(PBase):
-
-    def slowimport(self):
-        return "    import Uart_bs         :: *;\n" + \
-               "    import RS232_modified::*;"
-
-    def slowifdecl(self):
-        return "            interface RS232 uart{0}_coe;\n" + \
-               "            method Bit#(1) uart{0}_intr;"
-
-    def num_axi_regs32(self):
-        return 8
-
-    def mkslow_peripheral(self, size=0):
-        return "        Ifc_Uart_bs uart{0} <- \n" + \
-               "                mkUart_bs(clocked_by sp_clock,\n" + \
-               "                    reset_by uart_reset, sp_clock, sp_reset);"
-
-    def _mk_connection(self, name=None, count=0):
-        return "uart{0}.slave_axi_uart"
-
-    def pinname_out(self, pname):
-        return {'tx': 'coe_rs232.sout'}.get(pname, '')
-
-    def pinname_in(self, pname):
-        return {'rx': 'coe_rs232.sin'}.get(pname, '')
-
-
-class quart(PBase):
-
-    def slowimport(self):
-        return "    import Uart16550         :: *;"
-
-    def slowifdecl(self):
-        return "            interface RS232_PHY_Ifc quart{0}_coe;\n" + \
-               "            method Bit#(1) quart{0}_intr;"
-
-    def num_axi_regs32(self):
-        return 8
-
-    def mkslow_peripheral(self, size=0):
-        return "        Uart16550_AXI4_Lite_Ifc quart{0} <- \n" + \
-               "                mkUart16550(clocked_by sp_clock,\n" + \
-               "                    reset_by uart_reset, sp_clock, sp_reset);"
-
-    def _mk_connection(self, name=None, count=0):
-        return "quart{0}.slave_axi_uart"
-
-    def pinname_out(self, pname):
-        return {'tx' : 'coe_rs232.modem_output_stx',
-                'rts': 'coe_rs232.modem_output_rts',
-               }.get(pname, '')
-
-    def _pinname_in(self, pname):
-        return {'rx': 'coe_rs232.modem_input.srx', 
-                'cts': 'coe_rs232.modem_input.cts'
-               }.get(pname, '')
-
-    def mk_pincon(self, name, count):
-        ret = [PBase.mk_pincon(self, name, count)]
-        ret.append("    rule con_%s%d_io_in;" % (name, count))
-        ret.append("       {0}{1}.coe_rs232.modem_input(".format(name, count))
-        for idx, pname in enumerate(['rx', 'cts']):
-            sname = self.peripheral.pname(pname).format(count)
-            ps = "pinmux.peripheral_side.%s" % sname
-            ret.append("            {0},".format(ps))
-        ret.append("            1'b1,1'b0,1'b1")
-        ret.append("        );")
-        ret.append("    endrule")
-
-        return '\n'.join(ret)
-
-    def num_irqs(self):
-        return 1
-
-    def plic_object(self, pname, idx):
-        return "{0}_interrupt.read".format(pname)
-
-    def mk_plic(self, inum, irq_offs):
-        name = self.get_iname(inum)
-        ret = [uart_plic_template.format(name, irq_offs)]
-        (ret2, irq_offs) = PBase.mk_plic(self, inum, irq_offs)
-        ret.append(ret2)
-        return ('\n'.join(ret), irq_offs)
-
-    def mk_ext_ifacedef(self, iname, inum):
-        name = self.get_iname(inum)
-        return "        method {0}_intr = {0}.irq;".format(name)
-
-    def slowifdeclmux(self):
-        return "        method Bit#(1) {1}{0}_intr;"
-
-uart_plic_template = """\
-     // PLIC {0} synchronisation with irq {1}
-     SyncBitIfc#(Bit#(1)) {0}_interrupt <-
-                                mkSyncBitToCC(sp_clock, uart_reset);
-     rule plic_synchronize_{0}_interrupt_{1};
-         {0}_interrupt.send({0}.irq);
-     endrule
-"""
-
-class rs232(PBase):
-
-    def slowimport(self):
-        return "    import Uart_bs::*;\n" + \
-               "    import RS232_modified::*;"
-
-    def slowifdecl(self):
-        return "            interface RS232 uart{0}_coe;"
-
-    def num_axi_regs32(self):
-        return 2
-
-    def mkslow_peripheral(self, size=0):
-        return "        //Ifc_Uart_bs uart{0} <-" + \
-               "        //       mkUart_bs(clocked_by uart_clock,\n" + \
-               "        //          reset_by uart_reset,sp_clock, sp_reset);" +\
-               "        Ifc_Uart_bs uart{0} <-" + \
-               "                mkUart_bs(clocked_by sp_clock,\n" + \
-               "                    reset_by sp_reset, sp_clock, sp_reset);"
-
-    def _mk_connection(self, name=None, count=0):
-        return "uart{0}.slave_axi_uart"
-
-    def pinname_out(self, pname):
-        return {'tx': 'coe_rs232.sout'}.get(pname, '')
-
-    def pinname_in(self, pname):
-        return {'rx': 'coe_rs232.sin'}.get(pname, '')
-
-
-class twi(PBase):
-
-    def slowimport(self):
-        return "    import I2C_top           :: *;"
-
-    def slowifdecl(self):
-        return "            interface I2C_out twi{0}_out;\n" + \
-               "            method Bit#(1) twi{0}_isint;"
-
-    def num_axi_regs32(self):
-        return 8
-
-    def mkslow_peripheral(self, size=0):
-        return "        I2C_IFC twi{0} <- mkI2CController();"
-
-    def _mk_connection(self, name=None, count=0):
-        return "twi{0}.slave_i2c_axi"
-
-    def pinname_out(self, pname):
-        return {'sda': 'out.sda_out',
-                'scl': 'out.scl_out'}.get(pname, '')
-
-    def pinname_in(self, pname):
-        return {'sda': 'out.sda_in',
-                'scl': 'out.scl_in'}.get(pname, '')
-
-    def pinname_outen(self, pname):
-        return {'sda': 'out.sda_out_en',
-                'scl': 'out.scl_out_en'}.get(pname, '')
-
-    def pinname_tweak(self, pname, typ, txt):
-        if typ == 'outen':
-            return "pack({0})".format(txt)
-        return txt
-
-    def num_irqs(self):
-        return 3
-
-    def plic_object(self, pname, idx):
-        return ["{0}.isint()",
-                "{0}.timerint()",
-                "{0}.isber()"
-               ][idx].format(pname)
-
-    def mk_ext_ifacedef(self, iname, inum):
-        name = self.get_iname(inum)
-        return "        method {0}_isint = {0}.isint;".format(name)
-
-    def slowifdeclmux(self):
-        return "        method Bit#(1) {1}{0}_isint;"
-
-
-class eint(PBase):
-
-    def slowimport(self):
-        size = len(self.peripheral.pinspecs)
-        return "    `define NUM_EINTS %d" % size
-
-    def mkslow_peripheral(self, size=0):
-        size = len(self.peripheral.pinspecs)
-        return "        Wire#(Bit#(%d)) wr_interrupt <- mkWire();" % size
-
-    def axi_slave_name(self, name, ifacenum):
+    def extfastifinstance(self, name, count):
         return ''
 
-    def axi_slave_idx(self, idx, name, ifacenum):
-        return ('', 0)
-
-    def axi_addr_map(self, name, ifacenum):
+    def _extifinstance(self, name, count, suffix, prefix, samename=False,
+                       ifsuffix=None):
+        if ifsuffix is None:
+            ifsuffix = ''
+        pname = self.get_iname(count)
+        if samename:
+            sname = pname
+        else:
+            sname = self.peripheral.iname().format(count)
+        template = "interface {0}{3} = {2}{1}{4};"
+        return template.format(pname, sname, prefix, suffix, ifsuffix)
+
+    def extifinstance2(self, name, count):
         return ''
 
-    def ifname_tweak(self, pname, typ, txt):
-        if typ != 'in':
-            return txt
-        print "ifnameweak", pname, typ, txt
-        return "wr_interrupt[{0}] <= ".format(pname)
-
-    def mk_pincon(self, name, count):
-        ret = [PBase.mk_pincon(self, name, count)]
-        size = len(self.peripheral.pinspecs)
-        ret.append(eint_pincon_template.format(size))
-        ret.append("    rule con_%s%d_io_in;" % (name, count))
-        ret.append("    wr_interrupt <= ({")
-        for idx, p in enumerate(self.peripheral.pinspecs):
-            pname = p['name']
-            sname = self.peripheral.pname(pname).format(count)
-            ps = "pinmux.peripheral_side.%s" % sname
-            comma = '' if idx == size - 1 else ','
-            ret.append("             {0}{1}".format(ps, comma))
-        ret.append("        });")
-        ret.append("    endrule")
-
-        return '\n'.join(ret)
-
-
-eint_pincon_template = '''\
-    // EINT is offset at end of other peripheral interrupts
-`ifdef PLIC
-    for(Integer i=0;i<{0};i=i+ 1)begin
-      rule connect_int_to_plic(wr_interrupt[i]==1);
-                ff_gateway_queue[i+`NUM_SLOW_IRQS].enq(1);
-                plic.ifc_external_irq[i+`NUM_SLOW_IRQS].irq_frm_gateway(True);
-      endrule
-    end
-`endif
-'''
+    def extifinstance(self, name, count):
+        return self._extifinstance(name, count, "",
+                                   "pinmux.peripheral_side.")
 
 
-class jtag(PBase):
-
-    def axi_slave_name(self, name, ifacenum):
-        return ''
-
-    def axi_slave_idx(self, idx, name, ifacenum):
-        return ('', 0)
-
-    def axi_addr_map(self, name, ifacenum):
-        return ''
-
-    def slowifdeclmux(self):
-        return "        method  Action jtag_ms (Bit#(1) in);\n" +  \
-               "        method  Bit#(1) jtag_di;\n" + \
-               "        method  Action jtag_do (Bit#(1) in);\n" + \
-               "        method  Action jtag_ck (Bit#(1) in);"
-
-    def slowifinstance(self):
-        return jtag_method_template # bit of a lazy hack this...
-
-jtag_method_template = """\
-        method  Action jtag_ms (Bit#(1) in);
-          pinmux.peripheral_side.jtag_ms(in);
-        endmethod
-        method  Bit#(1) jtag_di=pinmux.peripheral_side.jtag_di;
-        method  Action jtag_do (Bit#(1) in);
-          pinmux.peripheral_side.jtag_do(in);
-        endmethod
-        method  Action jtag_ck (Bit#(1) in);
-          pinmux.peripheral_side.jtag_ck(in);
-        endmethod
+mkplic_rule = """\
+rule rl_connect_{0}_to_plic_{2};
+   if({1} == 1'b1) begin
+       ff_gateway_queue[{2}].enq(1);
+       plic.ifc_external_irq[{2}].irq_frm_gateway(True);
+   end
+endrule
 """
 
-class sdmmc(PBase):
-
-    def slowimport(self):
-        return "    import sdcard_dummy              :: *;"
-
-    def slowifdecl(self):
-        return "            interface QSPI_out sd{0}_out;\n" + \
-               "            method Bit#(1) sd{0}_isint;"
-
-    def num_axi_regs32(self):
-        return 13
-
-    def mkslow_peripheral(self):
-        return "        Ifc_sdcard_dummy sd{0} <-  mksdcard_dummy();"
-
-    def _mk_connection(self, name=None, count=0):
-        return "sd{0}.slave"
-
-    def pinname_in(self, pname):
-        return "%s_in" % pname
-
-    def pinname_out(self, pname):
-        if pname.startswith('d'):
-            return "%s_out" % pname
-        return pname
-
-    def pinname_outen(self, pname):
-        if pname.startswith('d'):
-            return "%s_outen" % pname
-
-
-class spi(PBase):
-
-    def slowimport(self):
-        return "    import qspi              :: *;"
-
-    def slowifdecl(self):
-        return "            interface QSPI_out spi{0}_out;\n" + \
-               "            method Bit#(1) spi{0}_isint;"
-
-    def num_axi_regs32(self):
-        return 13
-
-    def mkslow_peripheral(self):
-        return "        Ifc_qspi spi{0} <-  mkqspi();"
-
-    def _mk_connection(self, name=None, count=0):
-        return "spi{0}.slave"
-
-    def pinname_out(self, pname):
-        return {'clk': 'out.clk_o',
-                'nss': 'out.ncs_o',
-                'mosi': 'out.io_o[0]',
-                'miso': 'out.io_o[1]',
-                }.get(pname, '')
-
-    def pinname_outen(self, pname):
-        return {'clk': 1,
-                'nss': 1,
-                'mosi': 'out.io_enable[0]',
-                'miso': 'out.io_enable[1]',
-                }.get(pname, '')
-
-    def mk_pincon(self, name, count):
-        ret = [PBase.mk_pincon(self, name, count)]
-        # special-case for gpio in, store in a temporary vector
-        plen = len(self.peripheral.pinspecs)
-        ret.append("    // XXX NSS and CLK are hard-coded master")
-        ret.append("    // TODO: must add spi slave-mode")
-        ret.append("    // all ins done in one rule from 4-bitfield")
-        ret.append("    rule con_%s%d_io_in;" % (name, count))
-        ret.append("       {0}{1}.out.io_i({{".format(name, count))
-        for idx, pname in enumerate(['mosi', 'miso']):
-            sname = self.peripheral.pname(pname).format(count)
-            ps = "pinmux.peripheral_side.%s_in" % sname
-            ret.append("            {0},".format(ps))
-        ret.append("            1'b0,1'b0")
-        ret.append("        });")
-        ret.append("    endrule")
-        return '\n'.join(ret)
-
-    def mk_ext_ifacedef(self, iname, inum):
-        name = self.get_iname(inum)
-        return "        method {0}_isint = {0}.interrupts[5];".format(name)
-
-    def slowifdeclmux(self):
-        return "        method Bit#(1) {1}{0}_isint;"
-
-
-class qspi(PBase):
-
-    def slowimport(self):
-        return "    import qspi              :: *;"
-
-    def slowifdecl(self):
-        return "            interface QSPI_out qspi{0}_out;\n" + \
-               "            method Bit#(1) qspi{0}_isint;"
-
-    def num_axi_regs32(self):
-        return 13
-
-    def mkslow_peripheral(self, size=0):
-        return "        Ifc_qspi qspi{0} <-  mkqspi();"
-
-    def _mk_connection(self, name=None, count=0):
-        return "qspi{0}.slave"
-
-    def pinname_out(self, pname):
-        return {'ck': 'out.clk_o',
-                'nss': 'out.ncs_o',
-                'io0': 'out.io_o[0]',
-                'io1': 'out.io_o[1]',
-                'io2': 'out.io_o[2]',
-                'io3': 'out.io_o[3]',
-                }.get(pname, '')
-
-    def pinname_outen(self, pname):
-        return {'ck': 1,
-                'nss': 1,
-                'io0': 'out.io_enable[0]',
-                'io1': 'out.io_enable[1]',
-                'io2': 'out.io_enable[2]',
-                'io3': 'out.io_enable[3]',
-                }.get(pname, '')
-
-    def mk_pincon(self, name, count):
-        ret = [PBase.mk_pincon(self, name, count)]
-        # special-case for gpio in, store in a temporary vector
-        plen = len(self.peripheral.pinspecs)
-        ret.append("    // XXX NSS and CLK are hard-coded master")
-        ret.append("    // TODO: must add qspi slave-mode")
-        ret.append("    // all ins done in one rule from 4-bitfield")
-        ret.append("    rule con_%s%d_io_in;" % (name, count))
-        ret.append("       {0}{1}.out.io_i({{".format(name, count))
-        for i, p in enumerate(self.peripheral.pinspecs):
-            typ = p['type']
-            pname = p['name']
-            if not pname.startswith('io'):
-                continue
-            idx = pname[1:]
-            n = name
-            sname = self.peripheral.pname(pname).format(count)
-            ps = "pinmux.peripheral_side.%s_in" % sname
-            comma = '' if i == 5 else ','
-            ret.append("            {0}{1}".format(ps, comma))
-        ret.append("        });")
-        ret.append("    endrule")
-        return '\n'.join(ret)
-
-    def num_irqs(self):
-        return 6
-
-    def plic_object(self, pname, idx):
-        return "{0}.interrupts()[{1}]".format(pname, idx)
-
-    def mk_ext_ifacedef(self, iname, inum):
-        name = self.get_iname(inum)
-        return "        method {0}_isint = {0}.interrupts[5];".format(name)
-
-    def slowifdeclmux(self):
-        return "        method Bit#(1) {1}{0}_isint;"
-
-
-
-class pwm(PBase):
-
-    def slowimport(self):
-        return "    import pwm::*;"
-
-    def slowifdecl(self):
-        return "        interface PWMIO pwm{0}_io;"
-
-    def num_axi_regs32(self):
-        return 4
-
-    def mkslow_peripheral(self, size=0):
-        return "        Ifc_PWM_bus pwm{0} <- mkPWM_bus(sp_clock);"
-
-    def _mk_connection(self, name=None, count=0):
-        return "pwm{0}.axi4_slave"
-
-    def pinname_out(self, pname):
-        return {'out': 'pwm_io.pwm_o'}.get(pname, '')
-
-
-class gpio(PBase):
-
-    def slowimport(self):
-        return "    import pinmux::*;\n" + \
-               "    import mux::*;\n" + \
-               "    import gpio::*;\n"
-
-    def slowifdeclmux(self):
-        size = len(self.peripheral.pinspecs)
-        return "        interface GPIO_config#(%d) pad_config{0};" % size
-
-    def num_axi_regs32(self):
-        return 2
-
-    def axi_slave_idx(self, idx, name, ifacenum):
-        """ generates AXI slave number definition, except
-            GPIO also has a muxer per bank
-        """
-        name = name.upper()
-        mname = 'mux' + name[4:]
-        mname = mname.upper()
-        print "AXIslavenum", name, mname
-        (ret, x) = PBase.axi_slave_idx(self, idx, name, ifacenum)
-        (ret2, x) = PBase.axi_slave_idx(self, idx + 1, mname, ifacenum)
-        return ("%s\n%s" % (ret, ret2), 2)
-
-    def mkslow_peripheral(self, size=0):
-        print "gpioslow", self.peripheral, dir(self.peripheral)
-        size = len(self.peripheral.pinspecs)
-        return "        MUX#(%d) mux{0} <- mkmux();\n" % size + \
-               "        GPIO#(%d) gpio{0} <- mkgpio();" % size
-
-    def mk_connection(self, count):
-        print "GPIO mk_conn", self.name, count
-        res = []
-        dname = self.mksuffix(self.name, count)
-        for i, n in enumerate(['gpio' + dname, 'mux' + dname]):
-            res.append(PBase.mk_connection(self, count, n))
-        return '\n'.join(res)
-
-    def _mk_connection(self, name=None, count=0):
-        n = self.mksuffix(name, count)
-        if name.startswith('gpio'):
-            return "gpio{0}.axi_slave".format(n)
-        if name.startswith('mux'):
-            return "mux{0}.axi_slave".format(n)
-
-    def mksuffix(self, name, i):
-        if name.startswith('mux'):
-            return name[3:]
-        return name[4:]
-
-    def mk_cellconn(self, cellnum, name, count):
-        ret = []
-        bank = self.mksuffix(name, count)
-        txt = "       pinmux.mux_lines.cell{0}_mux(mux{1}.mux_config.mux[{2}]);"
-        for p in self.peripheral.pinspecs:
-            ret.append(txt.format(cellnum, bank, p['name'][1:]))
-            cellnum += 1
-        return ("\n".join(ret), cellnum)
-
-    def pinname_out(self, pname):
-        return "func.gpio_out[{0}]".format(pname[1:])
-
-    def pinname_outen(self, pname):
-        return "func.gpio_out_en[{0}]".format(pname[1:])
-
-    def mk_pincon(self, name, count):
-        ret = [PBase.mk_pincon(self, name, count)]
-        # special-case for gpio in, store in a temporary vector
-        plen = len(self.peripheral.pinspecs)
-        ret.append("    rule con_%s%d_in;" % (name, count))
-        ret.append("       Vector#({0},Bit#(1)) temp;".format(plen))
-        for p in self.peripheral.pinspecs:
-            typ = p['type']
-            pname = p['name']
-            idx = pname[1:]
-            n = name
-            sname = self.peripheral.pname(pname).format(count)
-            ps = "pinmux.peripheral_side.%s_in" % sname
-            ret.append("        temp[{0}]={1};".format(idx, ps))
-        ret.append("        {0}.func.gpio_in(temp);".format(name))
-        ret.append("    endrule")
-        return '\n'.join(ret)
+axi_master_declarations = """\
+typedef 0 Dmem_master_num;
+typedef 1 Imem_master_num;
+{0}
+typedef TAdd#(LastGen_master_num, `ifdef Debug 1 `else 0 `endif )
+                Debug_master_num;
+typedef TAdd#(Debug_master_num, `ifdef DMA 1 `else 0 `endif )
+                DMA_master_num;
+typedef TAdd#(DMA_master_num,1)
+                Num_Masters;
+"""
 
+axi_fastslave_declarations = """\
+{0}
+typedef  TAdd#(LastGen_fastslave_num,1)      Sdram_slave_num;
+typedef  TAdd#(Sdram_slave_num   ,`ifdef SDRAM      1 `else 0 `endif )
+                      Sdram_cfg_slave_num;
+typedef TAdd#(Sdram_cfg_slave_num,`ifdef BOOTROM    1 `else 0 `endif )
+                BootRom_slave_num   ;
+typedef TAdd#(BootRom_slave_num  ,`ifdef Debug      1 `else 0 `endif )
+                Debug_slave_num ;
+typedef  TAdd#(Debug_slave_num   , `ifdef TCMemory  1 `else 0 `endif )
+                TCM_slave_num;
+typedef  TAdd#(TCM_slave_num     ,`ifdef DMA        1 `else 0 `endif )
+                Dma_slave_num;
+typedef  TAdd#(Dma_slave_num      ,1 )      SlowPeripheral_slave_num;
+typedef  TAdd#(SlowPeripheral_slave_num,`ifdef VME  1 `else 0 `endif )
+                VME_slave_num;
+typedef TAdd#(VME_slave_num,1) Num_Fast_Slaves;
+"""
 
 axi_slave_declarations = """\
 typedef  0  SlowMaster;
@@ -749,9 +575,9 @@ typedef TAdd#(AxiExp1_slave_num,1) Num_Slow_Slaves;
 """
 
 pinmux_cellrule = """\
-    rule connect_select_lines_pinmux;
+rule connect_select_lines_pinmux;
 {0}
-    endrule
+endrule
 """
 
 
@@ -775,10 +601,18 @@ class PeripheralIface(object):
         if slow:
             self.slow = slow(ifacename)
             self.slow.peripheral = self
-        for fname in ['slowimport', 
-                      'slowifinstance', 'slowifdecl', 'slowifdeclmux',
-                      'mkslow_peripheral', 'mk_plic', 'mk_ext_ifacedef',
-                      'mk_connection', 'mk_cellconn', 'mk_pincon']:
+        for fname in ['slowimport',
+                      'extfastifinstance',
+                      'extifinstance2', 'extifinstance', 'extifdecl',
+                      'slowifdecl', 'slowifdeclmux',
+                      'fastifdecl',
+                      'mkslow_peripheral',
+                      'mk_dma_sync', 'mk_dma_connect', 'mk_dma_rule',
+                      'mkfast_peripheral',
+                      'mk_plic', 'mk_ext_ifacedef',
+                      '_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))
 
@@ -795,54 +629,130 @@ class PeripheralIface(object):
             return ('', 0)
         return self.slow.axi_reg_def(start, self.ifacename, count)
 
-    def axi_slave_idx(self, start, count):
+    def axi_master_idx(self, start, count, typ):
+        if not self.slow or not self.slow.has_axi_master():
+            return ('', 0)
+        return self.slow.axi_master_idx(start, self.ifacename, count, typ)
+
+    def axi_slave_idx(self, start, count, typ):
         if not self.slow:
             return ('', 0)
-        return self.slow.axi_slave_idx(start, self.ifacename, count)
+        return self.slow.axi_slave_idx(start, self.ifacename, count, typ)
+
+    def axi_fastaddr_map(self, name, count):
+        if not self.slow:
+            return ''
+        return self.slow.axi_fastaddr_map(self.ifacename, count)
 
-    def axi_addr_map(self, count):
+    def axi_addr_map(self, name, count):
         if not self.slow:
             return ''
         return self.slow.axi_addr_map(self.ifacename, count)
 
 
+class CallIfaceFn(object):
+    def __init__(self, ifaces, kls, indent):
+        self.ifaces = ifaces
+        self.kls = kls
+        self.indent = indent
+
+    def __call__(self, ifaces, *args):
+        ret = []
+        for (name, count) in self.ifaces.ifacecount:
+            print "CallIfaceFn", self.kls, self.ifaces
+            print "CallIfaceFn args", name, count, args
+            ret += list(self.kls(self.ifaces, name, count, *args))
+        return '\n'.join(li(list(filter(None, ret)), self.indent))
+
+
 class PeripheralInterfaces(object):
     def __init__(self):
-        pass
+        self.fastbusmode = False
+
+        for (fname, kls, indent) in (
+            ('_mk_connection', MkConnection, 8),
+            ('_mk_pincon', MkPinCon, 4),
+            ('_mk_clk_con', MkClkCon, 8),
+            ('mk_ext_ifacedef', MkExtIface, 8),
+            ('axi_addr_map', MkAxiAddrMap, 8),
+            ('axi_fastaddr_map', MkAxiFastAddrMap, 8),
+            ('slowifdeclmux', MkSlowIfDeclMux, 8),
+        ):
+            fn = CallIfaceFn(self, kls, indent)
+            setattr(self, fname, types.MethodType(fn, self))
 
     def slowimport(self, *args):
         ret = []
         for (name, count) in self.ifacecount:
             #print "slowimport", name, self.data[name].slowimport
             ret.append(self.data[name].slowimport())
-        return '\n'.join(list(filter(None, ret)))
+        return '\n'.join(li(list(filter(None, ret)), 4))
 
-    def slowifinstance(self, *args):
+    def extfastifinstance(self, *args):
         ret = []
         for (name, count) in self.ifacecount:
-            #print "slowimport", name, self.data[name].slowimport
-            ret.append(self.data[name].slowifinstance())
-        return '\n'.join(list(filter(None, ret)))
+            for i in range(count):
+                if self.is_on_fastbus(name, i):
+                    continue
+                ret.append(self.data[name].extfastifinstance(name, i))
+        return '\n'.join(li(list(filter(None, ret)), 8))
 
-    def slowifdeclmux(self, *args):
+    def extifinstance2(self, *args):
         ret = []
         for (name, count) in self.ifacecount:
             for i in range(count):
-                ret.append(self.data[name].slowifdeclmux().format(i, name))
-        return '\n'.join(list(filter(None, ret)))
+                ret.append(self.data[name].extifinstance2(name, i))
+        return '\n'.join(li(list(filter(None, ret)), 8))
+
+    def extifinstance(self, *args):
+        ret = []
+        for (name, count) in self.ifacecount:
+            for i in range(count):
+                if not self.is_on_fastbus(name, i):
+                    continue
+                ret.append(self.data[name].extifinstance(name, i))
+        return '\n'.join(li(list(filter(None, ret)), 8))
+
+    def extifdecl(self, *args):
+        ret = []
+        for (name, count) in self.ifacecount:
+            for i in range(count):
+                if not self.is_on_fastbus(name, i):
+                    continue
+                ret.append(self.data[name].extifdecl(name, i))
+        return '\n'.join(li(list(filter(None, ret)), 8))
+
+    def fastifdecl(self, *args):
+        ret = []
+        for (name, count) in self.ifacecount:
+            for i in range(count):
+                print "fastifdecl", name, i, self.is_on_fastbus(name, i)
+                if self.is_on_fastbus(name, i):
+                    continue
+                ret.append(self.data[name].fastifdecl(name, i))
+        return '\n'.join(li(list(filter(None, ret)), 4))
 
     def slowifdecl(self, *args):
         ret = []
         for (name, count) in self.ifacecount:
             for i in range(count):
+                if self.is_on_fastbus(name, i):
+                    continue
                 ret.append(self.data[name].slowifdecl().format(i, name))
         return '\n'.join(list(filter(None, ret)))
 
+    def axi_fastmem_def(self, *args):
+        return self._axi_reg_def(0x50000000, *args)
+
     def axi_reg_def(self, *args):
+        return self._axi_reg_def(0x00011100, *args)
+
+    def _axi_reg_def(self, start, *args):
         ret = []
-        start = 0x00011100  # start of AXI peripherals address
         for (name, count) in self.ifacecount:
             for i in range(count):
+                if self.is_on_fastbus(name, i):
+                    continue
                 x = self.data[name].axi_reg_def(start, i)
                 #print ("ifc", name, x)
                 (rdef, offs) = x
@@ -850,108 +760,304 @@ class PeripheralInterfaces(object):
                 start += offs
         return '\n'.join(list(filter(None, ret)))
 
-    def axi_slave_idx(self, *args):
+    def _axi_num_idx(self, start, template, typ, idxtype, *args):
         ret = []
-        start = 0
         for (name, count) in self.ifacecount:
             for i in range(count):
-                (rdef, offs) = self.data[name].axi_slave_idx(start, i)
+                if self.is_on_fastbus(name, i):
+                    continue
+                if typ == 'master':
+                    fn = self.data[name].axi_master_idx
+                else:
+                    fn = self.data[name].axi_slave_idx
+                (rdef, offs) = fn(start, i, idxtype)
                 #print ("ifc", name, rdef, offs)
                 ret.append(rdef)
                 start += offs
-        ret.append("typedef %d LastGen_slave_num;" % (start - 1))
+        ret.append("typedef %d LastGen_%s_num;" % (start - 1, typ))
         decls = '\n'.join(list(filter(None, ret)))
-        return axi_slave_declarations.format(decls)
+        return template.format(decls)
+
+    def axi_slave_idx(self, *args):
+        return self._axi_num_idx(0, axi_slave_declarations, 'slave',
+                                 '', *args)
+
+    def axi_fastslave_idx(self, *args):
+        return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
+                                 'fast', *args)
+
+    def axi_master_idx(self, *args):
+        return self._axi_num_idx(2, axi_master_declarations, 'master',
+                                 'master', *args)
+
+    def axi_fastslave_idx(self, *args):
+        return self._axi_num_idx(0, axi_fastslave_declarations, 'fastslave',
+                                 'fast', *args)
 
-    def axi_addr_map(self, *args):
+    def mkfast_peripheral(self, *args):
         ret = []
         for (name, count) in self.ifacecount:
             for i in range(count):
-                ret.append(self.data[name].axi_addr_map(i))
-        return '\n'.join(list(filter(None, ret)))
+                if self.is_on_fastbus(name, i):
+                    continue
+                #print "mkfast", name, count
+                x = self.data[name].mkfast_peripheral()
+                print name, count, x
+                suffix = self.data[name].mksuffix(name, i)
+                ret.append(x.format(suffix))
+        return '\n'.join(li(list(filter(None, ret)), 8))
 
     def mkslow_peripheral(self, *args):
         ret = []
         for (name, count) in self.ifacecount:
             for i in range(count):
-                print "mkslow", name, count
+                if self.is_on_fastbus(name, i):
+                    continue
+                #print "mkslow", name, count
                 x = self.data[name].mkslow_peripheral()
                 print name, count, x
                 suffix = self.data[name].mksuffix(name, i)
                 ret.append(x.format(suffix))
-        return '\n'.join(list(filter(None, ret)))
+        return '\n'.join(li(list(filter(None, ret)), 8))
+
+    def mk_master_connection(self, *args):
+        return self._mk_connection("fabric", "fast", True, *args)
+
+    def mk_fast_connection(self, *args):
+        return self._mk_connection("fabric", "fast", False, *args)
 
     def mk_connection(self, *args):
-        ret = []
-        for (name, count) in self.ifacecount:
-            for i in range(count):
-                print "mk_conn", name, i
-                txt = self.data[name].mk_connection(i)
-                if name == 'gpioa':
-                    print "txt", txt
-                    print self.data[name].mk_connection
-                ret.append(txt)
-        return '\n'.join(list(filter(None, ret)))
+        return self._mk_connection("slow_fabric", "", False, *args)
 
     def mk_cellconn(self):
         ret = []
         cellcount = 0
         for (name, count) in self.ifacecount:
             for i in range(count):
-                res = self.data[name].mk_cellconn(cellcount, name, i)
+                if self.is_on_fastbus(name, i):
+                    continue
+                res = self.data[name].mk_cellconn(name, i, cellcount)
                 if not res:
                     continue
                 (txt, cellcount) = res
                 ret.append(txt)
-        ret = '\n'.join(list(filter(None, ret)))
-        return pinmux_cellrule.format(ret)
+        ret = li('\n'.join(list(filter(None, ret))), 4)
+        return li(pinmux_cellrule.format(ret), 4)
 
     def mk_pincon(self):
-        ret = []
-        for (name, count) in self.ifacecount:
-            for i in range(count):
-                txt = self.data[name].mk_pincon(name, i)
-                ret.append(txt)
-        return '\n'.join(list(filter(None, ret)))
+        return self._mk_pincon("slow")
 
-    def mk_ext_ifacedef(self):
+    def mk_fast_pincon(self):
+        return self._mk_pincon("fast")
+
+    def mk_dma_irq(self):
         ret = []
+        sync = []
+        rules = []
+        cnct = []
+
+        self.dma_count = 0
+
         for (name, count) in self.ifacecount:
+            ifacerules = []
             for i in range(count):
-                txt = self.data[name].mk_ext_ifacedef(name, i)
-                ret.append(txt)
-        return '\n'.join(list(filter(None, ret)))
+                if not self.is_on_fastbus(name, i):
+                    continue
+                txt = self.data[name].mk_dma_sync(name, i)
+                if txt:
+                    self.dma_count += 1
+                sync.append(txt)
+                txt = self.data[name].mk_dma_rule(name, i)
+                ifacerules.append(txt)
+                txt = self.data[name].mk_dma_connect(name, i)
+                cnct.append(txt)
+            ifacerules = list(filter(None, ifacerules))
+            if ifacerules:
+                txt = "rule synchronize_%s_interrupts;" % name
+                rules.append(txt)
+                rules += ifacerules
+                rules.append("endrule")
+
+        cnct = list(filter(None, cnct))
+        ct = self.dma_count
+        _cnct = ["rule rl_connect_interrupt_to_DMA;",
+                 "  Bit #(%d) lv_interrupt_to_DMA={" % ct]
+        spc = "                      "
+        spcsep = ",\n" + spc
+        cnct = _cnct + [spc + spcsep.join(cnct)]
+        cnct.append("   };")
+        cnct.append("   dma.interrupt_from_peripherals(\n" +
+                    "       lv_interrupt_to_DMA);")
+        cnct.append("endrule;")
+
+        ret = list(filter(None, sync + rules + cnct))
+        ret = li(ret, 15)
+        return '\n'.join(ret)
 
+    def num_dmachannels(self):
+        return "`define NUM_DMACHANNELS {0}".format(self.dma_count)
 
     def mk_plic(self):
         ret = []
-        irq_offs = 8 # XXX: DMA scovers 0-7?
+        irq_offs = 8  # XXX: DMA scovers 0-7?
         for (name, count) in self.ifacecount:
             for i in range(count):
+                if self.is_on_fastbus(name, i):
+                    continue
                 res = self.data[name].mk_plic(i, irq_offs)
                 if not res:
                     continue
                 (txt, irq_offs) = res
                 ret.append(txt)
         self.num_slow_irqs = irq_offs
-        return '\n'.join(list(filter(None, ret)))
+        return '\n'.join(li(list(filter(None, ret)), 4))
 
     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 is_on_fastbus(self, name, i):
+        #print "fastbus mode", self.fastbusmode, name, i
+        iname = self.data[name].iname().format(i)
+        if self.fastbusmode:
+            return iname not in self.fastbus
+        return iname in self.fastbus
+
+
+class IfaceIter(object):
+
+    def __init__(self, ifaces, name, count, *args):
+        self.ifaces = ifaces
+        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):
+                #print "iter", self.item
+                #print "item args", self.args
+                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 MkSlowIfDeclMux(IfaceIter):
+
+    def check(self, name, i):
+        return True
+
+    def item(self, name, i):
+        return self.ifaces.data[name].slowifdeclmux(name, i)
+
+
+class MkAxiFastAddrMap(IfaceIter):
+
+    def check(self, name, i):
+        return not self.ifaces.is_on_fastbus(name, i)
+
+    def item(self, name, i):
+        return self.ifaces.data[name].axi_fastaddr_map(name, i)
+
+
+class MkAxiAddrMap(IfaceIter):
+
+    def check(self, name, i):
+        return not self.ifaces.is_on_fastbus(name, i)
+
+    def item(self, name, i):
+        return self.ifaces.data[name].axi_addr_map(name, i)
+
+
+class MkConnection(IfaceIter):
+
+    def check(self, name, i):
+        return not self.ifaces.is_on_fastbus(name, i)
+
+    def item(self, name, i, fabric, typ, master):
+        if master:
+            return self.ifaces.data[name].mk_master_connection(name,
+                                                               i, fabric, typ)
+        return self.ifaces.data[name].mk_connection(name, i, fabric, typ)
+
+
+class MkExtIface(IfaceIter):
+
+    def check(self, name, i):
+        return not self.ifaces.is_on_fastbus(name, i)
+
+    def item(self, name, i):
+        return self.ifaces.data[name].mk_ext_ifacedef(name, i)
+
+
+class MkPinCon(IfaceIter):
+
+    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 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 twi import twi
+        from eint import eint
+        from jtag import jtag
+        from spi import spi, mspi
+        from qspi import qspi, mqspi
+        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,
                      'qspi': qspi,
                      'spi': spi,
                      'pwm': pwm,
                      'eint': eint,
-                     'sd': sdmmc,
+                     'mmc': sdmmc,
+                     'emmc': emmc,
                      'jtag': jtag,
+                     'lcd': rgbttl,
+                     'fb': flexbus,
                      'gpio': gpio
                      }.items():
             if name.startswith(k):