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 get_cell_bit_width(p
):
29 for cell
in p
.muxed_cells
:
30 max_num_cells
= max(len(cell
) - 1, max_num_cells
)
31 return int(math
.log(max_num_cells
+ 1, 2))
34 def cn(idx
): # idx is an integer
35 return "cell%s_mux" % str(idx
)
39 """ removes the number from the string of signal name.
41 temp
= temp
.split('_')
43 temp
[0] = temp
[0].translate(digits
)
44 temp
[0] = temp
[0] .replace(' ', '')
48 # XXX this needs to move into interface_decl.py
49 # and made to use ifaceoutfmtfn and ifaceinfmtfn
50 def fmt(ifaces
, cells
, idx
, suffix
=None):
51 """ blank entries need to output a 0 to the pin (it could just as
52 well be a 1 but we choose 0). reason: blank entries in
53 the pinmap.txt file indicate that there's nothing to choose
54 from. however the user may still set the muxer to that value,
55 and rather than throw an exception we choose to output... zero.
57 NOTE: IMPORTANT. when a function is an output-only there
58 is a special-case assumption that:
59 * (a) GPIO is always the first mux entry
60 * (b) GPIO's outen is also used to set the pad
61 the reason for this is that it is assumed better that
62 multiple pads be switched simutaneously to outputs
63 by setting the GPIO direction rather than having them
64 set arbitrarily by changing the muxer registers.
74 x
= ifaces
.getifacetype(temp
)
76 return '0' # inputs don't get passed through to the out mux
77 if suffix
== '_outen' and x
== 'out':
78 return "wr%s%s" % (cells
[1], suffix
or '') # USE GPIO FOR SELECTION
79 return "wr%s%s" % (cell
, suffix
or '')
81 # XXX this needs to move into interface_decl.py
84 def mkcomment(ifaces
, cell
, idx
, outenmode
=False):
85 """ returns a comment string for the cell when muxed
94 x
= ifaces
.getifacetype(temp
)
97 return ' // %s is an input' % cname
98 if outenmode
and x
== 'inout':
99 return ' // bi-directional'
100 if outenmode
and x
== 'out':
101 return ' // %s is an output' % cname
106 def mkmux(p
, ifaces
, cell
, suffix
, outenmode
):
107 """ creates a straight many-to-one muxer that accepts
108 multiple inputs and, based on an "address" routes
109 a given indexed input through to the (one) output
111 comment
= 'outen' if outenmode
else 'output'
112 fmtstr
= "\t\t\twr%s==%d?%s:%s\n" # mux-selector format
114 ret
+= " // %s muxer for cell idx %s\n" % (comment
, cell
[0])
115 ret
+= " %s%s=\n" % (cn(cell
[0]), suffix
)
117 0, (1 << p
.cell_bitwidth
) - 1): # full mux range (minus 1)
118 comment
= mkcomment(ifaces
, cell
, i
, outenmode
)
119 cf
= fmt(ifaces
, cell
, i
, suffix
)
120 ret
+= fmtstr
% (cn(cell
[0]), i
, cf
, comment
)
121 comment
= mkcomment(ifaces
, cell
, i
+ 1, outenmode
)
122 ret
+= "\t\t\t" + fmt(ifaces
, cell
, i
+ 1, suffix
) # last line
123 ret
+= ";%s\n" % comment
129 """ generates the actual output pinmux for each io-cell. blank lines
130 need to output "0" to the iopad, if there is no entry in
133 text is outputted in the format:
140 last line doesn't need selector-logic, obviously.
142 note that it's *important* that all muxer options be covered
143 (hence going up to 1<<cell_bitwidth) even if the muxer cells
144 are blank (no entries), because muxer selection could be to
145 the last one, and we do not want the "default" (last line)
148 p
.cell_bitwidth
= get_cell_bit_width(p
)
150 global dedicated_wire
151 for cell
in p
.muxed_cells
:
153 # first do the outputs
154 p
.pinmux
+= mkmux(p
, ifaces
, cell
, '_out', False)
157 # now do the output enablers (outens)
158 p
.pinmux
+= mkmux(p
, ifaces
, cell
, '_outen', True)
160 # ======================================================== #
162 # check each cell if "peripheral input/inout" then assign its wire
163 # Here we check the direction of each signal in the dictionary.
164 # We choose to keep the dictionary within the code and not user-input
165 # since the interfaces are always standard and cannot change from
166 # user-to-user. Plus this also reduces human-error as well :)
168 p
.pinmux
+= " // priority-in-muxer for cell idx %s\n" % (cell
[0])
169 for i
in range(0, len(cell
) - 1):
171 if not cname
: # skip blank entries, no need to test
173 temp
= transfn(cname
)
174 x
= ifaces
.getifacetype(temp
)
175 #print (cname, temp, x)
176 assert x
is not None, "ERROR: The signal : " + \
178 " of pinmap.txt isn't present \nin the current" + \
179 " dictionary. Update dictionary or fix-typo."
182 mux_wire
.format(cell
[0], i
, "wr" + cname
) + "\n"
185 mux_wire
.format(cell
[0], i
, "wr" + cname
+
187 # ============================================================ #
189 # ================== Logic for dedicated pins ========= #
190 p
.pinmux
+= "\n /*=========================================*/\n"
191 p
.pinmux
+= " // dedicated cells\n\n"
192 for cell
in p
.dedicated_cells
:
193 p
.pinmux
+= " // dedicated cell idx %s\n" % (cell
[0])
194 p
.pinmux
+= " %s_out=%s_io;\n" % (cn(cell
[0]), cell
[1])
195 temp
= transfn(cell
[1])
196 x
= ifaces
.getifacetype(temp
)
200 dedicated_wire
.format(cell
[0], "wr" + cell
[1]) + "\n"
203 dedicated_wire
.format(cell
[0], "wr" + cell
[1] + "_in") + "\n"
206 # =======================================================#