create a val0 which is set to 0 to get round compilation error
[pinmux.git] / src / bsv / actual_pinmux.py
1 import math
2 from string import digits
3 try:
4 from string import maketrans
5 except ImportError:
6 maketrans = str.maketrans
7
8
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
13 mux_wire = '''\
14 rule assign_{2}_on_cell{0}(wrcell{0}_mux=={1});
15 {2}<=cell{0}_mux_in;
16 endrule
17 '''
18 dedicated_wire = '''
19 rule assign_{1}_on_cell{0};
20 {1}<=cell{0}_mux_in;
21 endrule
22 '''
23 # ============================================================
24 digits = maketrans('0123456789', ' ' * 10) # delete space later
25
26
27 def get_cell_bit_width(p):
28 max_num_cells = 0
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))
32
33
34 def cn(idx): # idx is an integer
35 return "cell%s_mux" % str(idx)
36
37
38 def transfn(temp):
39 """ removes the number from the string of signal name.
40 """
41 temp = temp.split('_')
42 if len(temp) == 2:
43 temp[0] = temp[0].translate(digits)
44 temp[0] = temp[0] .replace(' ', '')
45 return '_'.join(temp)
46
47
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.
56
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.
65 """
66 idx += 1
67 if idx < len(cells):
68 cell = cells[idx]
69 else:
70 cell = ''
71 if not cell:
72 return 'val0'
73 temp = transfn(cell)
74 x = ifaces.getifacetype(temp)
75 if x == 'input':
76 return 'val0' # 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 if x == 'out': # sigh hack, should be using interface_decl
80 suffix = ''
81 return "wr%s%s" % (cell, suffix or '')
82
83 # XXX this needs to move into interface_decl.py
84
85
86 def mkcomment(ifaces, cell, idx, outenmode=False):
87 """ returns a comment string for the cell when muxed
88 """
89 idx += 1
90 if idx >= len(cell):
91 return ' // unused'
92 cname = cell[idx]
93 if not cname:
94 return ' // unused'
95 temp = transfn(cname)
96 x = ifaces.getifacetype(temp)
97 #print (cname, x)
98 if x == 'input':
99 return ' // %s is an input' % cname
100 if outenmode and x == 'inout':
101 return ' // bi-directional'
102 if outenmode and x == 'out':
103 return ' // %s is an output' % cname
104
105 return ""
106
107
108 def mkmux(p, ifaces, cell, suffix, outenmode):
109 """ creates a straight many-to-one muxer that accepts
110 multiple inputs and, based on an "address" routes
111 a given indexed input through to the (one) output
112 """
113 comment = 'outen' if outenmode else 'output'
114 fmtstr = "\t\t\twr%s==%d?%s:%s\n" # mux-selector format
115 ret = ''
116 ret += " // %s muxer for cell idx %s\n" % (comment, cell[0])
117 ret += " %s%s=\n" % (cn(cell[0]), suffix)
118 for i in range(
119 0, (1 << p.cell_bitwidth) - 1): # full mux range (minus 1)
120 comment = mkcomment(ifaces, cell, i, outenmode)
121 cf = fmt(ifaces, cell, i, suffix)
122 ret += fmtstr % (cn(cell[0]), i, cf, comment)
123 comment = mkcomment(ifaces, cell, i + 1, outenmode)
124 ret += "\t\t\t" + fmt(ifaces, cell, i + 1, suffix) # last line
125 ret += ";%s\n" % comment
126
127 return ret
128
129
130 def init(p, ifaces):
131 """ generates the actual output pinmux for each io-cell. blank lines
132 need to output "0" to the iopad, if there is no entry in
133 that column.
134
135 text is outputted in the format:
136 x_out =
137 muxer_sel==0 ? a :
138 muxer_sel==1 ? b :
139 muxer_sel==2 ? 0 :
140 d
141
142 last line doesn't need selector-logic, obviously.
143
144 note that it's *important* that all muxer options be covered
145 (hence going up to 1<<cell_bitwidth) even if the muxer cells
146 are blank (no entries), because muxer selection could be to
147 the last one, and we do not want the "default" (last line)
148 to be the output.
149 """
150 p.cell_bitwidth = get_cell_bit_width(p)
151 p.pinmux = ' '
152 global dedicated_wire
153 for cell in p.muxed_cells:
154
155 # first do the outputs
156 p.pinmux += mkmux(p, ifaces, cell, '_out', False)
157 p.pinmux += "\n"
158
159 # now do the output enablers (outens)
160 p.pinmux += mkmux(p, ifaces, cell, '_outen', True)
161
162 # ======================================================== #
163
164 # check each cell if "peripheral input/inout" then assign its wire
165 # Here we check the direction of each signal in the dictionary.
166 # We choose to keep the dictionary within the code and not user-input
167 # since the interfaces are always standard and cannot change from
168 # user-to-user. Plus this also reduces human-error as well :)
169 p.pinmux += "\n"
170 p.pinmux += " // priority-in-muxer for cell idx %s\n" % (cell[0])
171 for i in range(0, len(cell) - 1):
172 cname = cell[i + 1]
173 if not cname: # skip blank entries, no need to test
174 continue
175 temp = transfn(cname)
176 x = ifaces.getifacetype(temp)
177 #print (cname, temp, x)
178 assert x is not None, "ERROR: The signal : " + \
179 str(cname) + \
180 " of pinmap.txt isn't present \nin the current" + \
181 " dictionary. Update dictionary or fix-typo."
182 if x == "input":
183 p.pinmux += \
184 mux_wire.format(cell[0], i, "wr" + cname) + "\n"
185 elif x == "inout":
186 p.pinmux += \
187 mux_wire.format(cell[0], i, "wr" + cname +
188 "_in") + "\n"
189 # ============================================================ #
190
191 # ================== Logic for dedicated pins ========= #
192 p.pinmux += "\n /*=========================================*/\n"
193 p.pinmux += " // dedicated cells\n\n"
194 for cell in p.dedicated_cells:
195 p.pinmux += " // dedicated cell idx %s\n" % (cell[0])
196 p.pinmux += " %s_out=%s_io;\n" % (cn(cell[0]), cell[1])
197 temp = transfn(cell[1])
198 x = ifaces.getifacetype(temp)
199 #print cell, temp, x
200 if x == "input":
201 p.pinmux += \
202 dedicated_wire.format(cell[0], "wr" + cell[1]) + "\n"
203 elif x == "inout":
204 p.pinmux += \
205 dedicated_wire.format(cell[0], "wr" + cell[1] + "_in") + "\n"
206 else:
207 p.pinmux += "\n"
208 # =======================================================#