808985ce5f4fa884939bbb217e73672508f385dd
[pinmux.git] / src / spec / ifaceprint.py
1 #!/usr/bin/env python
2
3 from copy import deepcopy
4 from collections import OrderedDict
5
6 def display(of, pins, banksel=None, muxwidth=4):
7 of.write("""\
8 | Pin | Mux0 | Mux1 | Mux2 | Mux3 |
9 | --- | ----------- | ----------- | ----------- | ----------- |
10 """)
11 pinidx = sorted(pins.keys())
12 for pin in pinidx:
13 pdata = pins.get(pin)
14 if banksel:
15 skip = False
16 for mux in range(muxwidth):
17 if mux not in pdata:
18 continue
19 name, bank = pdata[mux]
20 if banksel != bank:
21 skip = True
22 if skip:
23 continue
24 res = '| %3d |' % pin
25 for mux in range(muxwidth):
26 if mux not in pdata:
27 res += " |"
28 continue
29 name, bank = pdata[mux]
30 res += " %s %-9s |" % (bank, name)
31 of.write("%s\n" % res)
32
33
34 def fnsplit(f):
35 a = ''
36 n = 0
37 if not f.startswith('FB_'):
38 f2 = f.split('_')
39 if len(f2) == 2:
40 if f2[1].isdigit():
41 return f2[0], int(f2[1])
42 return f2[0], f2[1]
43 #print f
44 while f and not f[0].isdigit():
45 a += f[0]
46 f = f[1:]
47 return a, int(f) if f else None
48
49
50 def fnsort(f1, f2):
51 a1, n1 = fnsplit(f1)
52 a2, n2 = fnsplit(f2)
53 x = cmp(a1, a2)
54 if x != 0:
55 return x
56 return cmp(n1, n2)
57
58
59 def find_fn(fname, names):
60 for n in names:
61 if fname.startswith(n):
62 return n
63
64 def map_name(pinmap, fn, fblower, pin, rename):
65 if not rename:
66 if pin[:-1].isdigit():
67 print "map name digit", pin, fn, fblower
68 if fn in ['PWM', 'EINT', 'VDD', 'VSS']:
69 return fn.lower() + pin.lower()
70 if fn == 'GPIO':
71 return 'gpio' + pin[1:].lower()
72 return pin.lower()
73 pin = pin.lower()
74 if fn == 'GPIO':
75 pk = '%s%s_%s' % (fblower, pin[0], pin[:-1])
76 elif pin[:-1].isdigit() and fn != 'EINT':
77 pk = '%s%s_out' % (fblower, pin[:-1])
78 else:
79 pk = '%s_%s' % (fblower, pin[:-1])
80 print "map name", pk, fblower, pinmap.has_key(pk)
81 if not pinmap.has_key(pk):
82 return pin.lower()
83 remapped = pinmap[pk]
84 uscore = remapped.find('_')
85 if uscore == -1:
86 return pin.lower()
87 fn, pin = remapped[:uscore], remapped[uscore+1:] + pin[-1]
88 return pin.lower()
89
90 def python_pindict(of, pinmap, pins, function_names, dname, remap):
91
92 res = OrderedDict()
93 of.write("\n%s = OrderedDict()\n" % dname)
94
95 for k, pingroup in pins.byspec.items():
96 (a, n) = k.split(":")
97 if n.isdigit():
98 a = "%s%s" % (a, n)
99 fblower = a.lower()
100 of.write("%s['%s'] = [ " % (dname, fblower))
101 res[fblower] = []
102 count = 0
103 for i, p in enumerate(pingroup):
104 name = map_name(pinmap, k[0], fblower, p, remap)
105 res[fblower].append(name)
106 of.write("'%s', " % name)
107 count += 1
108 if count == 4 and i != len(pingroup)-1:
109 of.write("\n ")
110 count = 0
111 of.write("]\n")
112 print " dict %s" % dname, a, n, pingroup
113 of.write("\n\n")
114 return res
115
116 def python_dict_fns(of, pinmap, pins, function_names):
117 of.write("# auto-generated by Libre-SOC pinmux program: do not edit\n")
118 of.write("# python src/pinmux_generator.py -v -s {spec} -o {output}\n")
119 of.write("# use OrderedDict to fix stable order for JTAG Boundary Scan\n")
120 of.write("from collections import OrderedDict\n")
121
122 fn_names = function_names.keys()
123 fns = {}
124
125 fnidx = list(fns.keys())
126 fnidx.sort(key=fnsplit)
127
128 print "python fnames", function_names
129 print "python speckeys", pins.byspec.keys()
130 print "python dict fns", dir(pins.gpio)
131 print pins.gpio.pinfn('', '')
132 print pins.pwm.pinfn('', '')
133 print pins.sdmmc.pinfn('', '')
134 print "by spec", pins.byspec
135 print pinmap
136
137 pd = python_pindict(of, {}, pins, function_names, 'pindict', False)
138 ld = python_pindict(of, pinmap, pins, function_names, 'litexdict', True)
139
140 print "pd", pd
141 print "ld", ld
142 # process results and create name map
143 litexmap = OrderedDict()
144 for k in pd.keys():
145 pl = pd[k]
146 ll = ld[k]
147 for pname, lname in zip(pl, ll):
148 pname = "%s_%s" % (k, pname[:-1]) # strip direction +/-/*
149 lname = lname[:-1] # strip direction +/-/*
150 if k in ['eint', 'pwm', 'gpio', 'vdd', 'vss']: # sigh
151 lname = "%s_%s" % (k, lname)
152 litexmap[pname] = lname
153 print "litexmap", litexmap
154 of.write("litexmap = {\n")
155 for k, v in litexmap.items():
156 of.write("\t'%s': '%s',\n" % (k, v))
157 of.write("}\n")
158 return litexmap
159
160
161 def display_fns(of, bankspec, pins, function_names):
162 fn_names = function_names.keys()
163 fns = {}
164 for (pin, pdata) in pins.items():
165 for mux in range(0, 4): # skip GPIO for now
166 if mux not in pdata:
167 continue
168 name, bank = pdata[mux]
169 assert name is not None, str(bank)
170 if name not in fns:
171 fns[name] = []
172 fns[name].append((pin - bankspec[bank], mux, bank))
173
174 fnidx = list(fns.keys())
175 fnidx.sort(key=fnsplit)
176 current_fn = None
177 for fname in fnidx:
178 fnbase = find_fn(fname, fn_names)
179 #fblower = fnbase.lower()
180 assert fnbase in function_names, "fn %s not in descriptions %s" % \
181 (fname, str(function_names.keys()))
182 #print "name", fname, fnbase
183 if fnbase != current_fn:
184 if current_fn is not None:
185 of.write('\n')
186 of.write("## %s\n\n%s\n\n" % (fnbase, function_names[fnbase]))
187 current_fn = fnbase
188 of.write("* %-9s :" % fname)
189 for (pin, mux, bank) in fns[fname]:
190 of.write(" %s%d/%d" % (bank, pin, mux))
191 of.write('\n')
192
193 return fns
194
195
196 def check_functions(of, title, bankspec, fns, pins, required, eint, pwm,
197 descriptions=None):
198 fns = deepcopy(fns)
199 pins = deepcopy(pins)
200 if descriptions is None:
201 descriptions = {}
202 fnidx = fns.keys()
203
204 #print dir(fns)
205 #print dir(pins)
206
207 of.write("# Pinmap for %s\n\n" % title)
208
209 print "fn_idx", fnidx
210 print "fns", fns
211 print "fnspec", pins.fnspec.keys()
212 print "required", required
213 for name in required:
214 of.write("## %s\n\n" % name)
215 if descriptions and name in descriptions:
216 of.write("%s\n\n" % descriptions[name])
217
218 name = name.split(':')
219 if len(name) == 2:
220 findbank = name[0][0]
221 findmux = int(name[0][1:])
222 name = name[1]
223 else:
224 name = name[0]
225 findbank = None
226 findmux = None
227 name = name.split('/')
228 if len(name) == 2:
229 count = int(name[1])
230 else:
231 count = 100000
232 name = name[0]
233 #print name
234 found = set()
235 pinfound = {}
236 located = set()
237 for fname in fnidx:
238 if not fname.startswith(name):
239 continue
240 for k in pins.fnspec.keys():
241 if fname.startswith(k):
242 fk = list(pins.fnspec[k].keys())
243 fn = pins.fnspec[k]
244 fn = fn[fk[0]]
245 #print fname, fn, dir(fn)
246 if count == 100000:
247 count = len(fn.pingroup)
248 for pin, mux, bank in fns[fname]:
249 if findbank is not None:
250 if findbank != bank:
251 continue
252 if findmux != mux:
253 continue
254 pin_ = pin + bankspec[bank]
255 if pin_ in pins:
256 pinfound[pin_] = (fname, pin_, bank, pin, mux)
257
258 pinidx = sorted(pinfound.keys())
259
260 fname = None
261 removedcount = 0
262 print ("pinidx", pinidx)
263 for pin_ in pinidx:
264 fname, pin_, bank, pin, mux = pinfound[pin_]
265 if fname in found:
266 continue
267 found.add(fname)
268 if len(found) > count:
269 continue
270 del pins[pin_]
271 removedcount += 1
272 of.write("* %s %d %s%d/%d\n" % (fname, pin_, bank, pin, mux))
273
274 print fns
275 if removedcount != count:
276 if fname is None:
277 print "no match between required and available pins"
278 else:
279 print ("not all found", name, removedcount, count, title, found,
280 fns[fname])
281 print ("pins found", pinfound)
282
283 # fnidx.sort(fnsort)
284 of.write('\n')
285
286 # gpios
287 gpios = []
288 for name in descriptions.keys():
289 if not name.startswith('GPIO'):
290 continue
291 if name == 'GPIO':
292 continue
293 gpios.append(name)
294 gpios.sort()
295
296 if gpios:
297 of.write("## GPIO\n\n")
298
299 for fname in gpios:
300 if fname in found:
301 continue
302 desc = ''
303 if descriptions and fname in descriptions:
304 desc = ': %s' % descriptions[fname]
305 bank = fname[4]
306 pin = int(fname[7:])
307 pin_ = pin + bankspec[bank]
308 if pin_ not in pins:
309 continue
310 del pins[pin_]
311 found.add(fname)
312 of.write("* %-8s %d %s%-2d %s\n" % (fname, pin_, bank, pin, desc))
313 of.write('\n')
314
315 if eint:
316 display_group(of, bankspec, "EINT", eint, fns, pins, descriptions)
317 if pwm:
318 display_group(of, bankspec, "PWM", pwm, fns, pins, descriptions)
319
320 of.write("## Unused Pinouts (spare as GPIO) for '%s'\n\n" % title)
321 if descriptions and 'GPIO' in descriptions:
322 of.write("%s\n\n" % descriptions['GPIO'])
323 display(of, pins)
324 of.write('\n')
325
326 return pins # unused
327
328
329 def display_group(of, bankspec, title, todisplay, fns, pins, descriptions):
330 of.write("## %s\n\n" % title)
331
332 found = set()
333 for fname in todisplay:
334 desc = ''
335 if descriptions and fname in descriptions:
336 desc = ': %s' % descriptions[fname]
337 fname = fname.split(':')
338 if len(fname) == 2:
339 findbank = fname[0][0]
340 findmux = int(fname[0][1:])
341 fname = fname[1]
342 else:
343 fname = fname[0]
344 findbank = None
345 findmux = None
346 for (pin, mux, bank) in fns[fname]:
347 if findbank is not None:
348 if findbank != bank:
349 continue
350 if findmux != mux:
351 continue
352 if fname in found:
353 continue
354 pin_ = pin + bankspec[bank]
355 if pin_ not in pins:
356 continue
357 del pins[pin_]
358 found.add(fname)
359 of.write("* %s %d %s%d/%d %s\n" %
360 (fname, pin_, bank, pin, mux, desc))
361 of.write('\n')
362
363
364 def display_fixed(of, fixed, offs):
365
366 fkeys = sorted(fixed.keys())
367 pin_ = offs
368 res = []
369 for pin, k in enumerate(fkeys):
370 of.write("## %s\n\n" % k)
371 prevname = ''
372 linecount = 0
373 for name in fixed[k]:
374 if linecount == 4:
375 linecount = 0
376 of.write('\n')
377 if prevname[:2] == name[:2] and linecount != 0:
378 of.write(" %s" % name)
379 linecount += 1
380 else:
381 if linecount != 0:
382 of.write('\n')
383 of.write("* %d: %d %s" % (pin_, pin, name))
384 linecount = 1
385 res.append((pin_, name))
386
387 prevname = name
388 pin_ += 1
389 if linecount != 0:
390 of.write('\n')
391 of.write('\n')
392
393 return res