when muxwidth == 1 output pin directly
[pinmux.git] / src / bsv / actual_pinmux.py
index a4ff0e4089dfcaffb7edcbc07627e119e58f4672..7156fd154af5d8edbadbfbcdad481f6e309568bf 100644 (file)
@@ -1,3 +1,4 @@
+import math
 from string import digits
 try:
     from string import maketrans
@@ -9,7 +10,7 @@ except ImportError:
 # first argument is the io-cell number being assigned.
 # second argument is the mux value.
 # Third argument is the signal from the pinmap file
-mux_wire = '''
+mux_wire = '''\
       rule assign_{2}_on_cell{0}(wrcell{0}_mux=={1});
         {2}<=cell{0}_mux_in;
       endrule
@@ -36,38 +37,130 @@ def transfn(temp):
         temp[0] = temp[0] .replace(' ', '')
     return '_'.join(temp)
 
-def fmt(ifaces, cell):
+
+# XXX this needs to move into interface_decl.py
+# and made to use ifaceoutfmtfn and ifaceinfmtfn
+def fmt(ifaces, cells, idx, suffix=None):
     """ blank entries need to output a 0 to the pin (it could just as
         well be a 1 but we choose 0).  reason: blank entries in
         the pinmap.txt file indicate that there's nothing to choose
         from.  however the user may still set the muxer to that value,
         and rather than throw an exception we choose to output... zero.
+
+        NOTE: IMPORTANT.  when a function is an output-only there
+        is a special-case assumption that:
+        * (a) GPIO is always the first mux entry
+        * (b) GPIO's outen is also used to set the pad
+        the reason for this is that it is assumed better that
+        multiple pads be switched simutaneously to outputs
+        by setting the GPIO direction rather than having them
+        set arbitrarily by changing the muxer registers.
     """
-    empty = '0' # XXX TODO: fix this, as it's assigned to GenericIOType
+    idx += 1
+    if idx < len(cells):
+        cell = cells[idx]
+    else:
+        cell = ''
+    #print "fmt", idx, cells, cell
     if not cell:
-        return empty
-    # work out the type.  if it's an input, return empty
-    temp = cell[1].translate(digits)
+        return 'val0'
+    temp = transfn(cell)
+    x = ifaces.getifacetype(temp)
+    if x == 'input':
+        return 'val0'  # inputs don't get passed through to the out mux
+    if suffix == '_outen' and x == 'out':
+        return "wr%s%s" % (cells[1], suffix or '')  # USE GPIO FOR SELECTION
+    if x == 'out':  # sigh hack, should be using interface_decl
+        suffix = ''
+    return "wr%s%s" % (cell, suffix or '')
+
+# XXX this needs to move into interface_decl.py
+
+
+def mkcomment(ifaces, cell, idx, outenmode=False):
+    """ returns a comment string for the cell when muxed
+    """
+    idx += 1
+    if idx >= len(cell):
+        return ' // unused'
+    cname = cell[idx]
+    if not cname:
+        return ' // unused'
+    temp = transfn(cname)
     x = ifaces.getifacetype(temp)
+    #print (cname, x)
     if x == 'input':
-        return empty
-    return "%s_io" % cell
+        return ' // %s is an input' % cname
+    if outenmode and x == 'inout':
+        return ' // bi-directional'
+    if outenmode and x == 'out':
+        return ' // %s is an output' % cname
+
+    return ""
+
+
+def mkmux(p, ifaces, cell, suffix, outenmode):
+    """ creates a straight many-to-one muxer that accepts
+        multiple inputs and, based on an "address" routes
+        a given indexed input through to the (one) output
+    """
+    cellnum = cell[0]
+    comment = 'outen' if outenmode else 'output'
+    fmtstr = "\t\t\twr%s==%d?%s:%s\n"  # mux-selector format
+    ret = ''
+    ret += "      // %s muxer for cell idx %s\n" % (comment, cellnum)
+    ret += "      %s%s=\n" % (cn(cellnum), suffix)
+    i = 0
+    mwid = p.get_muxwidth(cellnum)
+    if mwid > 1:
+        for i in range(0, mwid - 1):  # full mux range (minus 1)
+            comment = mkcomment(ifaces, cell, i, outenmode)
+            cf = fmt(ifaces, cell, i, suffix)
+            ret += fmtstr % (cn(cell[0]), i, cf, comment)
+        i += 1
+    comment = mkcomment(ifaces, cell, i, outenmode)
+    ret += "\t\t\t" + fmt(ifaces, cell, i, suffix)  # last line
+    ret += ";%s\n" % comment
+
+    return ret
+
 
 def init(p, ifaces):
     """ generates the actual output pinmux for each io-cell.  blank lines
         need to output "0" to the iopad, if there is no entry in
         that column.
+
+        text is outputted in the format:
+            x_out =
+                muxer_sel==0 ? a :
+                muxer_sel==1 ? b :
+                muxer_sel==2 ? 0 :
+                d
+
+        last line doesn't need selector-logic, obviously.
+
+        note that it's *important* that all muxer options be covered
+        (hence going up to 1<<cell_bitwidth) even if the muxer cells
+        are blank (no entries), because muxer selection could be to
+        the last one, and we do not want the "default" (last line)
+        to be the output.
     """
     p.pinmux = ' '
     global dedicated_wire
     for cell in p.muxed_cells:
-        p.pinmux += "      // output muxer for cell idx %s\n" % cell[0]
-        p.pinmux += "      %s_out=" % cn(cell[0])
-        for i in range(0, len(cell) - 2):
-            p.pinmux += "wr%s" % cn(cell[0]) + \
-                "==" + str(i) + "?" + fmt(ifaces, cell[i + 1]) + ":\n\t\t\t"
-        p.pinmux += fmt(ifaces, cell[i + 2])
-        p.pinmux += ";\n"
+
+        cellidx = cell[0]
+
+        p.pinmux += "      // --------------------\n"
+        p.pinmux += "      // ----- cell %s -----\n\n" % (cellidx)
+
+        # first do the outputs
+        p.pinmux += mkmux(p, ifaces, cell, '_out', False)
+        p.pinmux += "\n"
+
+        # now do the output enablers (outens)
+        p.pinmux += mkmux(p, ifaces, cell, '_outen', True)
+
         # ======================================================== #
 
         # check each cell if "peripheral input/inout" then assign its wire
@@ -75,35 +168,48 @@ def init(p, ifaces):
         # We choose to keep the dictionary within the code and not user-input
         # since the interfaces are always standard and cannot change from
         # user-to-user. Plus this also reduces human-error as well :)
+        p.pinmux += "\n"
+        p.pinmux += "      // priority-in-muxer for cell idx %s\n" % (cellidx)
         for i in range(0, len(cell) - 1):
             cname = cell[i + 1]
-            if not cname: # skip blank entries, no need to test
+            if not cname:  # skip blank entries, no need to test
                 continue
             temp = transfn(cname)
             x = ifaces.getifacetype(temp)
-            #print (cname, temp, x)
+            print (cname, temp, x)
             assert x is not None, "ERROR: The signal : " + \
                 str(cname) + \
                 " of pinmap.txt isn't present \nin the current" + \
                 " dictionary. Update dictionary or fix-typo."
-            if x == "input":
-                p.pinmux += \
-                    mux_wire.format(cell[0], i, "wr" + cname) + "\n"
-            elif x == "inout":
-                p.pinmux += \
-                    mux_wire.format(cell[0], i, "wr" + cname +
-                                                "_in") + "\n"
-    # ============================================================ #
+            bwid = p.get_muxbitwidth(cellidx)
+            if bwid > 0:
+                muxcell(p, cname, x, cell, i)
+            else:
+                dedcell(p, x, cell)
 
     # ==================  Logic for dedicated pins ========= #
+    p.pinmux += "\n      /*=========================================*/\n"
+    p.pinmux += "      // dedicated cells\n\n"
     for cell in p.dedicated_cells:
+        p.pinmux += "      // dedicated cell idx %s\n" % (cell[0])
         p.pinmux += "      %s_out=%s_io;\n" % (cn(cell[0]), cell[1])
-        temp = cell[1].translate(digits)
+        temp = transfn(cell[1])
         x = ifaces.getifacetype(temp)
-        if x == "input":
-            pinmux = pinmux + \
-                dedicated_wire.format(cell[0], "wr" + cell[1]) + "\n"
-        elif x == "inout":
-            pinmux = pinmux + \
-                dedicated_wire.format(cell[0], "wr" + cell[1] + "_in") + "\n"
-    # =======================================================#
+        #print cell, temp, x
+        dedcell(p, x, cell)
+
+def muxcell(p, cname, x, cell, i):
+    if x == "input":
+        p.pinmux += \
+            mux_wire.format(cell[0], i, "wr" + cname) + "\n"
+    elif x == "inout":
+        p.pinmux += \
+            mux_wire.format(cell[0], i, "wr" + cname +
+                                        "_in") + "\n"
+def dedcell(p, x, cell):
+    if x == "input":
+        p.pinmux += \
+            dedicated_wire.format(cell[0], "wr" + cell[1]) + "\n"
+    elif x == "inout":
+        p.pinmux += \
+            dedicated_wire.format(cell[0], "wr" + cell[1] + "_in") + "\n"