AddingPeripherals.mdwn
[pinmux.git] / src / bsv / interface_decl.py
index b5e551bcf5ca7533f5419cd3b46cc442593ebff4..83ba313e350522cf4bba37df2227cfe2755fc905 100644 (file)
@@ -7,6 +7,9 @@ except ImportError:
 
 from bsv.wire_def import generic_io  # special case
 from bsv.wire_def import muxwire  # special case
+from ifacebase import InterfacesBase
+from bsv.peripheral_gen import PeripheralIface
+from bsv.peripheral_gen import PeripheralInterfaces
 
 
 class Pin(object):
@@ -17,6 +20,8 @@ class Pin(object):
     """
 
     def __init__(self, name,
+                 name_=None,
+                 idx=None,
                  ready=True,
                  enabled=True,
                  io=False,
@@ -24,6 +29,8 @@ class Pin(object):
                  bitspec=None,
                  outenmode=False):
         self.name = name
+        self.name_ = name_
+        self.idx = idx
         self.ready = ready
         self.enabled = enabled
         self.io = io
@@ -38,6 +45,18 @@ class Pin(object):
                        Action io0_inputval (Bit#(1) in);
     """
 
+    def ifacepfmt(self, fmtfn):
+        res = '          '
+        status = []
+        res += "interface "
+        name = fmtfn(self.name_)
+        if self.action:
+            res += "Put"
+        else:
+            res += "Get"
+        res += "#(%s) %s;" % (self.bitspec, name)
+        return res
+
     def ifacefmt(self, fmtfn):
         res = '    '
         status = []
@@ -65,13 +84,6 @@ class Pin(object):
         res += ";"
         return res
 
-    # sample bsv method definition :
-    """
-    method Action  cell0_mux(Bit#(2) in);
-        wrcell0_mux<=in;
-    endmethod
-    """
-
     def ifacedef(self, fmtoutfn, fmtinfn, fmtdecfn):
         res = '      method '
         if self.action:
@@ -85,6 +97,13 @@ class Pin(object):
             fmtname = fmtoutfn(self.name)
             res += "%s=%s;" % (self.name, fmtname)
         return res
+    # sample bsv method definition :
+    """
+    method Action  cell0_mux(Bit#(2) in);
+        wrcell0_mux<=in;
+    endmethod
+    """
+
     # sample bsv wire (wire definiton):
     """
     Wire#(Bit#(2)) wrcell0_mux<-mkDWire(0);
@@ -99,8 +118,131 @@ class Pin(object):
         res += "<-mkDWire(0);"
         return res
 
+    def ifacedef2(self, fmtoutfn, fmtinfn, fmtdecfn):
+        if self.action:
+            fmtname = fmtinfn(self.name)
+            res = "            interface %s = interface Put\n" % self.name_
+            res += '              method '
+            res += "Action put"
+            #res += fmtdecfn(self.name)
+            res += '(%s in);\n' % self.bitspec
+            res += '                %s<=in;\n' % fmtname
+            res += '              endmethod\n'
+            res += '            endinterface;'
+        else:
+            fmtname = fmtoutfn(self.name)
+            res = "            interface %s = interface Get\n" % self.name_
+            res += '              method ActionValue#'
+            res += '(%s) get;\n' % self.bitspec
+            res += "                return %s;\n" % (fmtname)
+            res += '              endmethod\n'
+            res += '            endinterface;'
+        return res
+
+    def ifacedef3(self, idx, fmtoutfn, fmtinfn, fmtdecfn):
+        if self.action:
+            fmtname = fmtinfn(self.name)
+            if self.name.endswith('outen'):
+                name = "tputen"
+            else:
+                name = "tput"
+            res = "                   %s <= in[%d];" % (fmtname, idx)
+        else:
+            fmtname = fmtoutfn(self.name)
+            res = "                   tget[%d] = %s;" % (idx, fmtname)
+            name = 'tget'
+        return (name, res)
+
+
+class InterfaceFmt(object):
+
+    def ifacepfmtdecpin(self, pin):
+        return pin.ifacepfmt(self.ifacepfmtdecfn)
+
+    def ifacepfmtdecfn(self, name):
+        return name
+
+    def ifacefmtoutfn(self, name):
+        return "wr%s" % name  # like wruart
+
+    def ifacefmtdecfn2(self, name):
+        return name  # like: uart
+
+    def ifacefmtdecfn3(self, name):
+        """ HACK! """
+        return "%s_outen" % name  # like uart_outen
+
+    def ifacefmtinfn(self, name):
+        return "wr%s" % name
+
+    def ifacedef2pin(self, pin):
+        decfn = self.ifacefmtdecfn2
+        outfn = self.ifacefmtoutfn
+        # print pin, pin.outenmode
+        if pin.outenmode:
+            decfn = self.ifacefmtdecfn3
+            outfn = self.ifacefmtoutenfn
+        return pin.ifacedef2(outfn, self.ifacefmtinfn,
+                             decfn)
+
+    def vectorifacedef2(self, pins, count, names, bitfmt, *args):
+        tput = []
+        tget = []
+        tputen = []
+        if len(pins) == 0:
+            return ''
+        # XXX HACK! assume in, out and inout, create set of indices
+        # that are repeated three times.
+        plens = []
+        # ARG even worse hack for LCD *sigh*...
+        if names[1] is None and names[2] is None:
+            plens = range(len(pins))
+        else:
+            for i in range(0, len(pins), 3):
+                plens += [i / 3, i / 3, i / 3]
+        for (typ, txt) in map(self.ifacedef3pin, plens, pins):
+            if typ == 'tput':
+                tput.append(txt)
+            elif typ == 'tget':
+                tget.append(txt)
+            elif typ == 'tputen':
+                tputen.append(txt)
+        tput = '\n'.join(tput).format(*args)
+        tget = '\n'.join(tget).format(*args)
+        tputen = '\n'.join(tputen).format(*args)
+        bitfmt = bitfmt.format(count)
+        template = ["""\
+              interface {3} = interface Put#({0})
+                 method Action put({2} in);
+{1}
+                 endmethod
+               endinterface;
+""",
+                    """\
+               interface {3} = interface Put#({0})
+                 method Action put({2} in);
+{1}
+                 endmethod
+               endinterface;
+""",
+                    """\
+               interface {3} = interface Get#({0})
+                 method ActionValue#({2}) get;
+                   {2} tget;
+{1}
+                   return tget;
+                 endmethod
+               endinterface;
+"""]
+        res = ''
+        tlist = [tput, tputen, tget]
+        for i, n in enumerate(names):
+            if n:
+                res += template[i].format(count, tlist[i], bitfmt, n)
+        return '\n' + res + '\n'
 
-class Interface(object):
+
+class Interface(PeripheralIface, InterfaceFmt):
     """ create an interface from a list of pinspecs.
         each pinspec is a dictionary, see Pin class arguments
         single indicates that there is only one of these, and
@@ -115,26 +257,38 @@ class Interface(object):
     """
 
     def __init__(self, ifacename, pinspecs, ganged=None, single=False):
+        PeripheralIface.__init__(self, ifacename)
+        InterfaceFmt.__init__(self)
         self.ifacename = ifacename
         self.ganged = ganged or {}
         self.pins = []  # a list of instances of class Pin
         self.pinspecs = pinspecs  # a list of dictionary
         self.single = single
-        for p in pinspecs:
+
+        for idx, p in enumerate(pinspecs):
             _p = {}
             _p.update(p)
+            if 'type' in _p:
+                del _p['type']
             if p.get('outen') is True:  # special case, generate 3 pins
                 del _p['outen']
                 for psuffix in ['out', 'outen', 'in']:
                     # changing the name (like sda) to (twi_sda_out)
+                    _p['name_'] = "%s_%s" % (p['name'], psuffix)
                     _p['name'] = "%s_%s" % (self.pname(p['name']), psuffix)
                     _p['action'] = psuffix != 'in'
+                    _p['idx'] = idx
                     self.pins.append(Pin(**_p))
                     # will look like {'name': 'twi_sda_out', 'action': True}
                     # {'name': 'twi_sda_outen', 'action': True}
                     #{'name': 'twi_sda_in', 'action': False}
                     # NOTice - outen key is removed
             else:
+                name = p['name']
+                if name.isdigit():  # HACK!  deals with EINT case
+                    name = self.pname(name)
+                _p['name_'] = name
+                _p['idx'] = idx
                 _p['name'] = self.pname(p['name'])
                 self.pins.append(Pin(**_p))
 
@@ -154,7 +308,7 @@ class Interface(object):
     def getifacetype(self, name):
         for p in self.pinspecs:
             fname = "%s_%s" % (self.ifacename, p['name'])
-            #print "search", self.ifacename, name, fname
+            # print "search", self.ifacename, name, fname
             if fname == name:
                 if p.get('action'):
                     return 'out'
@@ -163,7 +317,7 @@ class Interface(object):
                 return 'input'
         return None
 
-    def pname(self, name):
+    def iname(self):
         """ generates the interface spec e.g. flexbus_ale
             if there is only one flexbus interface, or
             sd{0}_cmd if there are several.  string format
@@ -171,8 +325,17 @@ class Interface(object):
             appropriate.  single mode stops the numerical extension.
         """
         if self.single:
-            return '%s_%s' % (self.ifacename, name)
-        return '%s{0}_%s' % (self.ifacename, name)
+            return self.ifacename
+        return '%s{0}' % self.ifacename
+
+    def pname(self, name):
+        """ generates the interface spec e.g. flexbus_ale
+            if there is only one flexbus interface, or
+            sd{0}_cmd if there are several.  string format
+            function turns this into sd0_cmd, sd1_cmd as
+            appropriate.  single mode stops the numerical extension.
+        """
+        return "%s_%s" % (self.iname(), name)
 
     def busfmt(self, *args):
         """ this function creates a bus "ganging" system based
@@ -182,7 +345,7 @@ class Interface(object):
         """
         if not self.ganged:
             return ''  # when self.ganged is None
-        #print self.ganged
+        # print self.ganged
         res = []
         for (k, pnames) in self.ganged.items():
             name = self.pname('%senable' % k).format(*args)
@@ -206,6 +369,10 @@ class Interface(object):
         res += '\n'
         return '\n' + res
 
+    def ifacepfmt(self, *args):
+        res = '\n'.join(map(self.ifacepfmtdecpin, self.pins)).format(*args)
+        return '\n' + res  # pins is a list
+
     def ifacefmt(self, *args):
         res = '\n'.join(map(self.ifacefmtdecpin, self.pins)).format(*args)
         return '\n' + res  # pins is a list
@@ -213,19 +380,6 @@ class Interface(object):
     def ifacefmtdecfn(self, name):
         return name  # like: uart
 
-    def ifacefmtdecfn2(self, name):
-        return name  # like: uart
-
-    def ifacefmtdecfn3(self, name):
-        """ HACK! """
-        return "%s_outen" % name  # like uart_outen
-
-    def ifacefmtoutfn(self, name):
-        return "wr%s" % name  # like wruart
-
-    def ifacefmtinfn(self, name):
-        return "wr%s" % name
-
     def wirefmtpin(self, pin):
         return pin.wirefmt(self.ifacefmtoutfn, self.ifacefmtinfn,
                            self.ifacefmtdecfn2)
@@ -236,7 +390,7 @@ class Interface(object):
     def ifacefmtpin(self, pin):
         decfn = self.ifacefmtdecfn2
         outfn = self.ifacefmtoutfn
-        #print pin, pin.outenmode
+        # print pin, pin.outenmode
         if pin.outenmode:
             decfn = self.ifacefmtdecfn3
             outfn = self.ifacefmtoutenfn
@@ -248,6 +402,11 @@ class Interface(object):
         res = res.format(*args)
         return '\n' + res + '\n'
 
+    def ifacedef2(self, *args):
+        res = '\n'.join(map(self.ifacedef2pin, self.pins))
+        res = res.format(*args)
+        return '\n' + res + '\n'
+
 
 class MuxInterface(Interface):
 
@@ -271,84 +430,222 @@ class IOInterface(Interface):
         return generic_io.format(*args)
 
 
-class Interfaces(UserDict):
-    """ contains a list of interface definitions
+class InterfaceBus(InterfaceFmt):
+
+    def __init__(self, pins, is_inout, namelist, bitspec, filterbus):
+        InterfaceFmt.__init__(self)
+        self.namelist = namelist
+        self.bitspec = bitspec
+        self.fbus = filterbus  # filter identifying which are bus pins
+        self.pins_ = pins
+        self.is_inout = is_inout
+        self.buspins = filter(lambda x: x.name_.startswith(self.fbus),
+                              self.pins_)
+        self.nonbuspins = filter(lambda x: not x.name_.startswith(self.fbus),
+                                 self.pins_)
+
+    def get_nonbuspins(self):
+        return self.nonbuspins
+
+    def get_buspins(self):
+        return self.buspins
+
+    def get_n_iopinsdiv(self):
+        return 3 if self.is_inout else 1
+
+    def ifacepfmt(self, *args):
+        pins = self.get_nonbuspins()
+        res = '\n'.join(map(self.ifacepfmtdecpin, pins)).format(*args)
+        res = res.format(*args)
+
+        pins = self.get_buspins()
+        plen = len(pins) / self.get_n_iopinsdiv()
+
+        res += '\n'
+        template = "          interface {1}#(%s) {2};\n" % self.bitspec
+        for i, n in enumerate(self.namelist):
+            if not n:
+                continue
+            ftype = 'Get' if i == 2 else "Put"
+            res += template.format(plen, ftype, n)
+
+        return "\n" + res
+
+    def ifacedef2(self, *args):
+        pins = self.get_nonbuspins()
+        res = '\n'.join(map(self.ifacedef2pin, pins))
+        res = res.format(*args)
+
+        pins = self.get_buspins()
+        plen = len(pins) / self.get_n_iopinsdiv()
+        for pin in pins:
+            print "ifbus pins", pin.name_, plen
+        bitspec = self.bitspec.format(plen)
+        print self
+        return '\n' + res + self.vectorifacedef2(
+            pins, plen, self.namelist, bitspec, *args)
+
+    def ifacedef3pin(self, idx, pin):
+        decfn = self.ifacefmtdecfn2
+        outfn = self.ifacefmtoutfn
+        # print pin, pin.outenmode
+        if pin.outenmode:
+            decfn = self.ifacefmtdecfn3
+            outfn = self.ifacefmtoutenfn
+        return pin.ifacedef3(idx, outfn, self.ifacefmtinfn,
+                             decfn)
+
+
+class InterfaceMultiBus(object):
+
+    def __init__(self, pins):
+        self.multibus_specs = []
+        self.nonbuspins = pins
+        self.nonb = self.add_bus(False, [], '', "xxxxxxxnofilter")
+
+    def add_bus(self, is_inout, namelist, bitspec, filterbus):
+        pins = self.nonbuspins
+        buspins = filter(lambda x: x.name_.startswith(filterbus), pins)
+        nbuspins = filter(lambda x: not x.name_.startswith(filterbus), pins)
+        self.nonbuspins = nbuspins
+        b = InterfaceBus(buspins, is_inout,
+                         namelist, bitspec, filterbus)
+        print is_inout, namelist, filterbus, buspins
+        self.multibus_specs.append(b)
+        self.multibus_specs[0].pins_ = nbuspins
+        self.multibus_specs[0].nonbuspins = nbuspins
+
+    def ifacepfmt(self, *args):
+        res = ''
+        #res = Interface.ifacepfmt(self, *args)
+        for b in self.multibus_specs:
+            res += b.ifacepfmt(*args)
+        return res
+
+    def ifacedef2(self, *args):
+        res = ''
+        #res = Interface.ifacedef2(self, *args)
+        for b in self.multibus_specs:
+            res += b.ifacedef2(*args)
+        return res
+
+
+class InterfaceLCD(InterfaceBus, Interface):
+
+    def __init__(self, *args):
+        Interface.__init__(self, *args)
+        InterfaceBus.__init__(self, self.pins, False, ['data_out', None, None],
+                              "Bit#({0})", "out")
+
+
+class InterfaceSDRAM(InterfaceMultiBus, Interface):
+
+    def __init__(self, ifacename, pinspecs, ganged=None, single=False):
+        Interface.__init__(self, ifacename, pinspecs, ganged, single)
+        InterfaceMultiBus.__init__(self, self.pins)
+        self.add_bus(False, ['dqm', None, None],
+                     "Bit#({0})", "sdrdqm")
+        self.add_bus(True, ['d_out', 'd_out_en', 'd_in'],
+                     "Bit#({0})", "sdrd")
+        self.add_bus(False, ['ad', None, None],
+                     "Bit#({0})", "sdrad")
+        self.add_bus(False, ['ba', None, None],
+                     "Bit#({0})", "sdrba")
+
+    def ifacedef2(self, *args):
+        return InterfaceMultiBus.ifacedef2(self, *args)
+
+
+class InterfaceFlexBus(InterfaceMultiBus, Interface):
+
+    def __init__(self, ifacename, pinspecs, ganged=None, single=False):
+        Interface.__init__(self, ifacename, pinspecs, ganged, single)
+        InterfaceMultiBus.__init__(self, self.pins)
+        self.add_bus(True, ['ad_out', 'ad_out_en', 'ad_in'],
+                     "Bit#({0})", "ad")
+        self.add_bus(False, ['bwe', None, None],
+                     "Bit#({0})", "bwe")
+        self.add_bus(False, ['tsiz', None, None],
+                     "Bit#({0})", "tsiz")
+        self.add_bus(False, ['cs', None, None],
+                     "Bit#({0})", "cs")
+
+    def ifacedef2(self, *args):
+        return InterfaceMultiBus.ifacedef2(self, *args)
+
+
+class InterfaceSD(InterfaceBus, Interface):
+
+    def __init__(self, *args):
+        Interface.__init__(self, *args)
+        InterfaceBus.__init__(self, self.pins, True, ['out', 'out_en', 'in'],
+                              "Bit#({0})", "d")
+
+
+class InterfaceNSPI(InterfaceBus, Interface):
+
+    def __init__(self, *args):
+        Interface.__init__(self, *args)
+        InterfaceBus.__init__(self, self.pins, True,
+                              ['io_out', 'io_out_en', 'io_in'],
+                              "Bit#({0})", "io")
+
+
+class InterfaceEINT(Interface):
+    """ uses old-style (non-get/put) for now
     """
 
-    def __init__(self, pth=None):
-        self.pth = pth
-        self.ifacecount = []
-        UserDict.__init__(self, {})
-        if not pth:
-            return
-        ift = 'interfaces.txt'
-        if pth:
-            ift = os.path.join(pth, ift)
-        with open(ift, 'r') as ifile:
-            for ln in ifile.readlines():
-                ln = ln.strip()
-                ln = ln.split("\t")
-                name = ln[0]  # will have uart
-                count = int(ln[1])  # will have count of uart
-                # spec looks like this:
-                """
-                [{'name': 'sda', 'outen': True},
-                 {'name': 'scl', 'outen': True},
-                ]
-                """
-                spec, ganged = self.read_spec(pth, name)
-                iface = Interface(name, spec, ganged, count == 1)
-                self.ifaceadd(name, count, iface)
-
-    def getifacetype(self, fname):
-        # finds the interface type, e.g sd_d0 returns "inout"
-        for iface in self.values():
-            typ = iface.getifacetype(fname)
-            if typ:
-                return typ
-        return None
+    def ifacepfmt(self, *args):
+        res = '\n'.join(map(self.ifacefmtdecpin, self.pins)).format(*args)
+        return '\n' + res  # pins is a list
+
+    def ifacedef2(self, *args):
+        return self.ifacedef(*args)
 
-    def ifaceadd(self, name, count, iface, at=None):
-        if at is None:
-            at = len(self.ifacecount)  # ifacecount is a list
-        self.ifacecount.insert(at, (name, count))  # appends the list
-        # with (name,count) *at* times
-        self[name] = iface
 
+class InterfaceGPIO(InterfaceBus, Interface):
+    """ note: the busfilter cuts out everything as the entire set of pins
+        is a bus, but it's less code.  get_nonbuspins returns empty list.
     """
-    will check specific files of kind peripheral.txt like spi.txt,
-    uart.txt in test directory
+
+    def __init__(self, ifacename, pinspecs, ganged=None, single=False):
+        Interface.__init__(self, ifacename, pinspecs, ganged, single)
+        InterfaceBus.__init__(self, self.pins, True, ['out', 'out_en', 'in'],
+                              "Vector#({0},Bit#(1))", ifacename[-1])
+
+
+class Interfaces(InterfacesBase, PeripheralInterfaces):
+    """ contains a list of interface definitions
     """
 
-    def read_spec(self, pth, name):
-        spec = []
-        ganged = {}
-        fname = '%s.txt' % name
-        if pth:
-            ift = os.path.join(pth, fname)
-        with open(ift, 'r') as sfile:
-            for ln in sfile.readlines():
-                ln = ln.strip()
-                ln = ln.split("\t")
-                name = ln[0]
-                d = {'name': name}  # here we start to make the dictionary
-                if ln[1] == 'out':
-                    d['action'] = True  # adding element to the dict
-                elif ln[1] == 'inout':
-                    d['outen'] = True
-                    if len(ln) == 3:
-                        bus = ln[2]
-                        if bus not in ganged:
-                            ganged[bus] = []
-                        ganged[bus].append(name)
-                spec.append(d)
-        return spec, ganged
+    def __init__(self, pth=None):
+        InterfacesBase.__init__(self, Interface, pth,
+                                {'gpio': InterfaceGPIO,
+                                 'spi': InterfaceNSPI,
+                                 'mspi': InterfaceNSPI,
+                                 'lcd': InterfaceLCD,
+                                 'sd': InterfaceSD,
+                                 'fb': InterfaceFlexBus,
+                                 'sdr': InterfaceSDRAM,
+                                 'qspi': InterfaceNSPI,
+                                 'mqspi': InterfaceNSPI,
+                                 'eint': InterfaceEINT})
+        PeripheralInterfaces.__init__(self)
 
     def ifacedef(self, f, *args):
         for (name, count) in self.ifacecount:
             for i in range(count):
                 f.write(self.data[name].ifacedef(i))
 
+    def ifacedef2(self, f, *args):
+        c = "        interface {0} = interface PeripheralSide{1}"
+        for (name, count) in self.ifacecount:
+            for i in range(count):
+                iname = self.data[name].iname().format(i)
+                f.write(c.format(iname, name.upper()))
+                f.write(self.data[name].ifacedef2(i))
+                f.write("        endinterface;\n\n")
+
     def busfmt(self, f, *args):
         f.write("import BUtils::*;\n\n")
         for (name, count) in self.ifacecount:
@@ -356,6 +653,16 @@ class Interfaces(UserDict):
                 bf = self.data[name].busfmt(i)
                 f.write(bf)
 
+    def ifacepfmt(self, f, *args):
+        comment = '''
+      // interface declaration between {0} and pinmux
+      (*always_ready,always_enabled*)
+      interface PeripheralSide{0};'''
+        for (name, count) in self.ifacecount:
+            f.write(comment.format(name.upper()))
+            f.write(self.data[name].ifacepfmt(0))
+            f.write("\n      endinterface\n")
+
     def ifacefmt(self, f, *args):
         comment = '''
           // interface declaration between %s-{0} and pinmux'''
@@ -365,6 +672,14 @@ class Interfaces(UserDict):
                 f.write(c.format(i))
                 f.write(self.data[name].ifacefmt(i))
 
+    def ifacefmt2(self, f, *args):
+        comment = '''
+            interface PeripheralSide{0} {1};'''
+        for (name, count) in self.ifacecount:
+            for i in range(count):
+                iname = self.data[name].iname().format(i)
+                f.write(comment.format(name.upper(), iname))
+
     def wirefmt(self, f, *args):
         comment = '\n      // following wires capture signals ' \
                   'to IO CELL if %s-{0} is\n' \
@@ -378,9 +693,9 @@ class Interfaces(UserDict):
 
 # ========= Interface declarations ================ #
 
-mux_interface = MuxInterface('cell', [{'name': 'mux', 'ready': False,
-                                       'enabled': False,
-                                       'bitspec': '{1}', 'action': True}])
+mux_interface = MuxInterface('cell',
+                             [{'name': 'mux', 'ready': False, 'enabled': False,
+                               'bitspec': '{1}', 'action': True}])
 
 io_interface = IOInterface(
     'io',