shuffle interface-reading code around to create InterfacesBase class
[pinmux.git] / src / bsv / interface_decl.py
index c10fa9a2b737904fbff795b6904be2e142558edf..5493d16a23d26e7195ffed541071767834bc3725 100644 (file)
@@ -1,10 +1,13 @@
 import os.path
 
-from UserDict import UserDict
-
-from wire_def import generic_io  # special case
-from wire_def import muxwire  # special case
+try:
+    from UserDict import UserDict
+except ImportError:
+    from collections import UserDict
 
+from bsv.wire_def import generic_io  # special case
+from bsv.wire_def import muxwire  # special case
+from ifacebase import InterfacesBase
 
 class Pin(object):
     """ pin interface declaration.
@@ -18,15 +21,24 @@ class Pin(object):
                  enabled=True,
                  io=False,
                  action=False,
-                 bitspec=None):
+                 bitspec=None,
+                 outenmode=False):
         self.name = name
         self.ready = ready
         self.enabled = enabled
         self.io = io
         self.action = action
-        self.bitspec = bitspec if bitspec else '1'
+        self.bitspec = bitspec if bitspec else 'Bit#(1)'
+        self.outenmode = outenmode
 
-    def ifacefmt(self, fmtfn=None):
+    # bsv will look like this (method declaration):
+    """
+    (*always_ready,always_enabled*) method Bit#(1) io0_cell_outen;
+    (*always_ready,always_enabled,result="io"*) method
+                       Action io0_inputval (Bit#(1) in);
+    """
+
+    def ifacefmt(self, fmtfn):
         res = '    '
         status = []
         if self.ready:
@@ -46,29 +58,40 @@ class Pin(object):
         if self.action:
             res += " Action "
             res += name
-            res += ' (Bit#(%s) in)' % self.bitspec
+            res += ' (%s in)' % self.bitspec
         else:
-            res += " Bit#(%s) " % self.bitspec
+            res += " %s " % self.bitspec
             res += name
         res += ";"
         return res
 
-    def ifacedef(self, fmtoutfn=None, fmtinfn=None, fmtdecfn=None):
+    # 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:
             fmtname = fmtinfn(self.name)
             res += "Action  "
             res += fmtdecfn(self.name)
-            res += '(Bit#(%s) in);\n' % self.bitspec
+            res += '(%s in);\n' % self.bitspec
             res += '         %s<=in;\n' % fmtname
             res += '      endmethod'
         else:
             fmtname = fmtoutfn(self.name)
             res += "%s=%s;" % (self.name, fmtname)
         return res
+    # sample bsv wire (wire definiton):
+    """
+    Wire#(Bit#(2)) wrcell0_mux<-mkDWire(0);
+    """
 
-    def wirefmt(self, fmtoutfn=None, fmtinfn=None, fmtdecfn=None):
-        res = '      Wire#(Bit#(%s)) ' % self.bitspec
+    def wirefmt(self, fmtoutfn, fmtinfn, fmtdecfn):
+        res = '      Wire#(%s) ' % self.bitspec
         if self.action:
             res += '%s' % fmtinfn(self.name)
         else:
@@ -80,29 +103,58 @@ class Pin(object):
 class Interface(object):
     """ 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
+        so the name must *not* be extended numerically (see pname)
+    """
+    # sample interface object:
+    """
+    twiinterface_decl = Interface('twi',
+                                  [{'name': 'sda', 'outen': True},
+                                   {'name': 'scl', 'outen': True},
+                                   ])
     """
 
-    def __init__(self, ifacename, pinspecs):
+    def __init__(self, ifacename, pinspecs, ganged=None, single=False):
         self.ifacename = ifacename
-        self.pins = []
-        self.pinspecs = pinspecs
+        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:
             _p = {}
             _p.update(p)
             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" % (self.pname(p['name']), psuffix)
                     _p['action'] = psuffix != 'in'
                     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:
                 _p['name'] = self.pname(p['name'])
                 self.pins.append(Pin(**_p))
 
+    # sample interface object:
+    """
+        uartinterface_decl = Interface('uart',
+                                   [{'name': 'rx'},
+                                    {'name': 'tx', 'action': True},
+                                    ])
+    """
+    """
+    getifacetype is called multiple times in actual_pinmux.py
+    x = ifaces.getifacetype(temp), where temp is uart_rx, spi_mosi
+    Purpose is to identify is function : input/output/inout
+    """
+
     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'
@@ -112,49 +164,64 @@ class Interface(object):
         return None
 
     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.
+        """
+        if self.single:
+            return '%s_%s' % (self.ifacename, name)
         return '%s{0}_%s' % (self.ifacename, name)
 
+    def busfmt(self, *args):
+        """ this function creates a bus "ganging" system based
+            on input from the {interfacename}.txt file.
+            only inout pins that are under the control of the
+            interface may be "ganged" together.
+        """
+        if not self.ganged:
+            return ''  # when self.ganged is None
+        #print self.ganged
+        res = []
+        for (k, pnames) in self.ganged.items():
+            name = self.pname('%senable' % k).format(*args)
+            decl = 'Bit#(1) %s = 0;' % name
+            res.append(decl)
+            ganged = []
+            for p in self.pinspecs:
+                if p['name'] not in pnames:
+                    continue
+                pname = self.pname(p['name']).format(*args)
+                if p.get('outen') is True:
+                    outname = self.ifacefmtoutfn(pname)
+                    ganged.append("%s_outen" % outname)  # match wirefmt
+
+            gangedfmt = '{%s} = duplicate(%s);'
+            res.append(gangedfmt % (',\n  '.join(ganged), name))
+        return '\n'.join(res) + '\n\n'
+
     def wirefmt(self, *args):
         res = '\n'.join(map(self.wirefmtpin, self.pins)).format(*args)
         res += '\n'
-        for p in self.pinspecs:
-            name = self.pname(p['name']).format(*args)
-            res += "      GenericIOType %s_io = GenericIOType{\n" % name
-            params = []
-            if p.get('outen') is True:
-                outname = self.ifacefmtoutfn(name)
-                params.append('outputval:%s_out,' % outname)
-                params.append('output_en:%s_outen,' % outname)
-                params.append('input_en:~%s_outen,' % outname)
-            elif p.get('action'):
-                outname = self.ifacefmtoutfn(name)
-                params.append('outputval:%s,' % outname)
-                params.append('output_en:1,')
-                params.append('input_en:0,')
-            else:
-                params.append('outputval:0,')
-                params.append('output_en:0,')
-                params.append('input_en:1,')
-            params += ['pullup_en:0,', 'pulldown_en:0,',
-                       'pushpull_en:0,', 'drivestrength:0,',
-                       'opendrain_en:0']
-            for param in params:
-                res += '                 %s\n' % param
-            res += '      };\n'
         return '\n' + res
 
     def ifacefmt(self, *args):
         res = '\n'.join(map(self.ifacefmtdecpin, self.pins)).format(*args)
-        return '\n' + res
+        return '\n' + res  # pins is a list
 
     def ifacefmtdecfn(self, name):
-        return name
+        return name  # like: uart
 
     def ifacefmtdecfn2(self, name):
-        return 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
+        return "wr%s" % name  # like wruart
 
     def ifacefmtinfn(self, name):
         return "wr%s" % name
@@ -167,8 +234,14 @@ class Interface(object):
         return pin.ifacefmt(self.ifacefmtdecfn)
 
     def ifacefmtpin(self, pin):
-        return pin.ifacedef(self.ifacefmtoutfn, self.ifacefmtinfn,
-                            self.ifacefmtdecfn2)
+        decfn = self.ifacefmtdecfn2
+        outfn = self.ifacefmtoutfn
+        #print pin, pin.outenmode
+        if pin.outenmode:
+            decfn = self.ifacefmtdecfn3
+            outfn = self.ifacefmtoutenfn
+        return pin.ifacedef(outfn, self.ifacefmtinfn,
+                            decfn)
 
     def ifacedef(self, *args):
         res = '\n'.join(map(self.ifacefmtpin, self.pins))
@@ -184,9 +257,12 @@ class MuxInterface(Interface):
 
 class IOInterface(Interface):
 
+    def ifacefmtoutenfn(self, name):
+        return "cell{0}_mux_outen"
+
     def ifacefmtoutfn(self, name):
         """ for now strip off io{0}_ part """
-        return "cell{0}_mux_out.%s" % name[6:]
+        return "cell{0}_mux_out"
 
     def ifacefmtinfn(self, name):
         return "cell{0}_mux_in"
@@ -195,62 +271,25 @@ class IOInterface(Interface):
         return generic_io.format(*args)
 
 
-class Interfaces(UserDict):
+class Interfaces(InterfacesBase):
     """ contains a list of interface definitions
     """
 
-    def __init__(self, pth):
-        self.pth = pth
-        self.ifacecount = []
-        UserDict.__init__(self, {})
-        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]
-                count = int(ln[1])
-                spec = self.read_spec(pth, name)
-                self.ifaceadd(name, count, Interface(name, spec))
-
-    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 ifaceadd(self, name, count, iface, at=None):
-        if at is None:
-            at = len(self.ifacecount)
-        self.ifacecount.insert(at, (name, count))
-        self[name] = iface
-
-    def read_spec(self, pth, name):
-        spec = []
-        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")
-                d = {'name': ln[0]}
-                if ln[1] == 'out':
-                    d['action'] = True
-                elif ln[1] == 'inout':
-                    d['outen'] = True
-                spec.append(d)
-        return spec
+    def __init__(self, pth=None):
+        InterfacesBase.__init__(self, Interface, pth)
 
     def ifacedef(self, f, *args):
         for (name, count) in self.ifacecount:
             for i in range(count):
                 f.write(self.data[name].ifacedef(i))
 
+    def busfmt(self, f, *args):
+        f.write("import BUtils::*;\n\n")
+        for (name, count) in self.ifacecount:
+            for i in range(count):
+                bf = self.data[name].busfmt(i)
+                f.write(bf)
+
     def ifacefmt(self, f, *args):
         comment = '''
           // interface declaration between %s-{0} and pinmux'''
@@ -277,17 +316,11 @@ mux_interface = MuxInterface('cell', [{'name': 'mux', 'ready': False,
                                        'enabled': False,
                                        'bitspec': '{1}', 'action': True}])
 
-io_interface = IOInterface('io',
-                           [{'name': 'outputval', 'enabled': False},
-                            {'name': 'output_en', 'enabled': False},
-                            {'name': 'input_en', 'enabled': False},
-                            {'name': 'pullup_en', 'enabled': False},
-                            {'name': 'pulldown_en', 'enabled': False},
-                            {'name': 'drivestrength', 'enabled': False},
-                            {'name': 'pushpull_en', 'enabled': False},
-                            {'name': 'opendrain_en', 'enabled': False},
-                            {'name': 'inputval', 'action': True, 'io': True},
-                            ])
+io_interface = IOInterface(
+    'io',
+    [{'name': 'cell_out', 'enabled': True, },
+     {'name': 'cell_outen', 'enabled': True, 'outenmode': True, },
+     {'name': 'cell_in', 'action': True, 'io': True}, ])
 
 # == Peripheral Interface definitions == #
 # these are the interface of the peripherals to the pin mux
@@ -336,19 +369,19 @@ if __name__ == '__main__':
         l1 = l1.split("\n")
         l2 = l2.split("\n")
         for p1, p2 in zip(l1, l2):
-            print repr(p1)
-            print repr(p2)
-            print
+            print (repr(p1))
+            print (repr(p2))
+            print ()
             assert p1 == p2
 
     ifaces = Interfaces()
 
     ifaceuart = ifaces['uart']
-    print ifaceuart.ifacedef(0)
-    print uartinterface_decl.ifacedef(0)
+    print (ifaceuart.ifacedef(0))
+    print (uartinterface_decl.ifacedef(0))
     assert ifaceuart.ifacedef(0) == uartinterface_decl.ifacedef(0)
 
     ifacetwi = ifaces['twi']
-    print ifacetwi.ifacedef(0)
-    print twiinterface_decl.ifacedef(0)
+    print (ifacetwi.ifacedef(0))
+    print (twiinterface_decl.ifacedef(0))
     assert ifacetwi.ifacedef(0) == twiinterface_decl.ifacedef(0)