remove print statements
[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, cell, 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 idx += 1
58 if idx < len(cell):
59 cell = cell[idx]
60 else:
61 cell = ''
62 if not cell:
63 return '0'
64 temp = transfn(cell)
65 x = ifaces.getifacetype(temp)
66 if x == 'input':
67 return '0' # inputs don't get passed through to the out mux
68 if suffix == '_outen' and x == 'out':
69 return '1'
70 return "wr%s%s" % (cell, suffix or '')
71
72 # XXX this needs to move into interface_decl.py
73
74
75 def mkcomment(ifaces, cell, idx, outenmode=False):
76 """ returns a comment string for the cell when muxed
77 """
78 idx += 1
79 if idx >= len(cell):
80 return ' // unused'
81 cname = cell[idx]
82 if not cname:
83 return ' // unused'
84 temp = transfn(cname)
85 x = ifaces.getifacetype(temp)
86 #print (cname, x)
87 if x == 'input':
88 return ' // %s is an input' % cname
89 if outenmode and x == 'inout':
90 return ' // bi-directional'
91 if outenmode and x == 'out':
92 return ' // %s is an output' % cname
93
94 return ""
95
96
97 def mkmux(p, ifaces, cell, suffix, outenmode):
98 """ creates a straight many-to-one muxer that accepts
99 multiple inputs and, based on an "address" routes
100 a given indexed input through to the (one) output
101 """
102 comment = 'outen' if outenmode else 'output'
103 fmtstr = "\t\t\twr%s==%d?%s:%s\n" # mux-selector format
104 ret = ''
105 ret += " // %s muxer for cell idx %s\n" % (comment, cell[0])
106 ret += " %s%s=\n" % (cn(cell[0]), suffix)
107 for i in range(
108 0, (1 << p.cell_bitwidth) - 1): # full mux range (minus 1)
109 comment = mkcomment(ifaces, cell, i, outenmode)
110 cf = fmt(ifaces, cell, i, suffix)
111 ret += fmtstr % (cn(cell[0]), i, cf, comment)
112 comment = mkcomment(ifaces, cell, i + 1, outenmode)
113 ret += "\t\t\t" + fmt(ifaces, cell, i + 1, suffix) # last line
114 ret += ";%s\n" % comment
115
116 return ret
117
118
119 def init(p, ifaces):
120 """ generates the actual output pinmux for each io-cell. blank lines
121 need to output "0" to the iopad, if there is no entry in
122 that column.
123
124 text is outputted in the format:
125 x_out =
126 muxer_sel==0 ? a :
127 muxer_sel==1 ? b :
128 muxer_sel==2 ? 0 :
129 d
130
131 last line doesn't need selector-logic, obviously.
132
133 note that it's *important* that all muxer options be covered
134 (hence going up to 1<<cell_bitwidth) even if the muxer cells
135 are blank (no entries), because muxer selection could be to
136 the last one, and we do not want the "default" (last line)
137 to be the output.
138 """
139 p.cell_bitwidth = get_cell_bit_width(p)
140 p.pinmux = ' '
141 global dedicated_wire
142 for cell in p.muxed_cells:
143
144 # first do the outputs
145 p.pinmux += mkmux(p, ifaces, cell, '_out', False)
146 p.pinmux += "\n"
147
148 # now do the output enablers (outens)
149 p.pinmux += mkmux(p, ifaces, cell, '_outen', True)
150
151 # ======================================================== #
152
153 # check each cell if "peripheral input/inout" then assign its wire
154 # Here we check the direction of each signal in the dictionary.
155 # We choose to keep the dictionary within the code and not user-input
156 # since the interfaces are always standard and cannot change from
157 # user-to-user. Plus this also reduces human-error as well :)
158 p.pinmux += "\n"
159 p.pinmux += " // priority-in-muxer for cell idx %s\n" % (cell[0])
160 for i in range(0, len(cell) - 1):
161 cname = cell[i + 1]
162 if not cname: # skip blank entries, no need to test
163 continue
164 temp = transfn(cname)
165 x = ifaces.getifacetype(temp)
166 #print (cname, temp, x)
167 assert x is not None, "ERROR: The signal : " + \
168 str(cname) + \
169 " of pinmap.txt isn't present \nin the current" + \
170 " dictionary. Update dictionary or fix-typo."
171 if x == "input":
172 p.pinmux += \
173 mux_wire.format(cell[0], i, "wr" + cname) + "\n"
174 elif x == "inout":
175 p.pinmux += \
176 mux_wire.format(cell[0], i, "wr" + cname +
177 "_in") + "\n"
178 # ============================================================ #
179
180 # ================== Logic for dedicated pins ========= #
181 p.pinmux += "\n /*=========================================*/\n"
182 p.pinmux += " // dedicated cells\n\n"
183 for cell in p.dedicated_cells:
184 p.pinmux += " // dedicated cell idx %s\n" % (cell[0])
185 p.pinmux += " %s_out=%s_io;\n" % (cn(cell[0]), cell[1])
186 temp = transfn(cell[1])
187 x = ifaces.getifacetype(temp)
188 #print cell, temp, x
189 if x == "input":
190 p.pinmux += \
191 dedicated_wire.format(cell[0], "wr" + cell[1]) + "\n"
192 elif x == "inout":
193 p.pinmux += \
194 dedicated_wire.format(cell[0], "wr" + cell[1] + "_in") + "\n"
195 else:
196 p.pinmux += "\n"
197 # =======================================================#