2 from string
import digits
4 from string
import maketrans
6 maketrans
= str.maketrans
9 # ============== common bsv templates ============ #
10 # first argument is the io-cell number being assigned.
11 # second argument is the mux value.
12 # Third argument is the signal from the pinmap file
14 rule assign_{2}_on_cell{0}(wrcell{0}_mux=={1});
19 rule assign_{1}_on_cell{0};
23 # ============================================================
24 digits
= maketrans('0123456789', ' ' * 10) # delete space later
27 def cn(idx
): # idx is an integer
28 return "cell%s_mux" % str(idx
)
32 """ removes the number from the string of signal name.
34 temp
= temp
.split('_')
36 temp
[0] = temp
[0].translate(digits
)
37 temp
[0] = temp
[0] .replace(' ', '')
41 # XXX this needs to move into interface_decl.py
42 # and made to use ifaceoutfmtfn and ifaceinfmtfn
43 def fmt(ifaces
, cells
, idx
, suffix
=None):
44 """ blank entries need to output a 0 to the pin (it could just as
45 well be a 1 but we choose 0). reason: blank entries in
46 the pinmap.txt file indicate that there's nothing to choose
47 from. however the user may still set the muxer to that value,
48 and rather than throw an exception we choose to output... zero.
50 NOTE: IMPORTANT. when a function is an output-only there
51 is a special-case assumption that:
52 * (a) GPIO is always the first mux entry
53 * (b) GPIO's outen is also used to set the pad
54 the reason for this is that it is assumed better that
55 multiple pads be switched simutaneously to outputs
56 by setting the GPIO direction rather than having them
57 set arbitrarily by changing the muxer registers.
67 x
= ifaces
.getifacetype(temp
)
69 return 'val0' # inputs don't get passed through to the out mux
70 if suffix
== '_outen' and x
== 'out':
71 return "wr%s%s" % (cells
[1], suffix
or '') # USE GPIO FOR SELECTION
72 if x
== 'out': # sigh hack, should be using interface_decl
74 return "wr%s%s" % (cell
, suffix
or '')
76 # XXX this needs to move into interface_decl.py
79 def mkcomment(ifaces
, cell
, idx
, outenmode
=False):
80 """ returns a comment string for the cell when muxed
89 x
= ifaces
.getifacetype(temp
)
92 return ' // %s is an input' % cname
93 if outenmode
and x
== 'inout':
94 return ' // bi-directional'
95 if outenmode
and x
== 'out':
96 return ' // %s is an output' % cname
101 def mkmux(p
, ifaces
, cell
, suffix
, outenmode
):
102 """ creates a straight many-to-one muxer that accepts
103 multiple inputs and, based on an "address" routes
104 a given indexed input through to the (one) output
106 comment
= 'outen' if outenmode
else 'output'
107 fmtstr
= "\t\t\twr%s==%d?%s:%s\n" # mux-selector format
109 ret
+= " // %s muxer for cell idx %s\n" % (comment
, cell
[0])
110 ret
+= " %s%s=\n" % (cn(cell
[0]), suffix
)
112 0, (1 << p
.cell_bitwidth
) - 1): # full mux range (minus 1)
113 comment
= mkcomment(ifaces
, cell
, i
, outenmode
)
114 cf
= fmt(ifaces
, cell
, i
, suffix
)
115 ret
+= fmtstr
% (cn(cell
[0]), i
, cf
, comment
)
116 comment
= mkcomment(ifaces
, cell
, i
+ 1, outenmode
)
117 ret
+= "\t\t\t" + fmt(ifaces
, cell
, i
+ 1, suffix
) # last line
118 ret
+= ";%s\n" % comment
124 """ generates the actual output pinmux for each io-cell. blank lines
125 need to output "0" to the iopad, if there is no entry in
128 text is outputted in the format:
135 last line doesn't need selector-logic, obviously.
137 note that it's *important* that all muxer options be covered
138 (hence going up to 1<<cell_bitwidth) even if the muxer cells
139 are blank (no entries), because muxer selection could be to
140 the last one, and we do not want the "default" (last line)
144 global dedicated_wire
145 for cell
in p
.muxed_cells
:
147 # first do the outputs
148 p
.pinmux
+= mkmux(p
, ifaces
, cell
, '_out', False)
151 # now do the output enablers (outens)
152 p
.pinmux
+= mkmux(p
, ifaces
, cell
, '_outen', True)
154 # ======================================================== #
156 # check each cell if "peripheral input/inout" then assign its wire
157 # Here we check the direction of each signal in the dictionary.
158 # We choose to keep the dictionary within the code and not user-input
159 # since the interfaces are always standard and cannot change from
160 # user-to-user. Plus this also reduces human-error as well :)
162 p
.pinmux
+= " // priority-in-muxer for cell idx %s\n" % (cell
[0])
163 for i
in range(0, len(cell
) - 1):
165 if not cname
: # skip blank entries, no need to test
167 temp
= transfn(cname
)
168 x
= ifaces
.getifacetype(temp
)
169 print (cname
, temp
, x
)
170 assert x
is not None, "ERROR: The signal : " + \
172 " of pinmap.txt isn't present \nin the current" + \
173 " dictionary. Update dictionary or fix-typo."
176 mux_wire
.format(cell
[0], i
, "wr" + cname
) + "\n"
179 mux_wire
.format(cell
[0], i
, "wr" + cname
+
181 # ============================================================ #
183 # ================== Logic for dedicated pins ========= #
184 p
.pinmux
+= "\n /*=========================================*/\n"
185 p
.pinmux
+= " // dedicated cells\n\n"
186 for cell
in p
.dedicated_cells
:
187 p
.pinmux
+= " // dedicated cell idx %s\n" % (cell
[0])
188 p
.pinmux
+= " %s_out=%s_io;\n" % (cn(cell
[0]), cell
[1])
189 temp
= transfn(cell
[1])
190 x
= ifaces
.getifacetype(temp
)
194 dedicated_wire
.format(cell
[0], "wr" + cell
[1]) + "\n"
197 dedicated_wire
.format(cell
[0], "wr" + cell
[1] + "_in") + "\n"
200 # =======================================================#