3 from copy
import deepcopy
4 from collections
import OrderedDict
9 def create_sv(fname
, pins
):
10 """unsophisticated drawer of an SVG
14 width
= len(pins
['pads.north']) * scale
15 height
= len(pins
['pads.east']) * scale
16 woffs
= scale
*18#-width/2
17 hoffs
= scale
*18#-height/2
19 dwg
= svgwrite
.Drawing(fname
, profile
='full',
20 size
=(width
+scale
*40, height
+scale
*40))
21 dwg
.add(dwg
.rect((woffs
-scale
*2, hoffs
-scale
*2),
22 (woffs
+width
-scale
*12, hoffs
+height
-scale
*12),
23 stroke
=svgwrite
.rgb(255, 255, 16, '%'),
24 stroke_width
=scale
/10.0))
26 dwg
.add(dwg
.text("Libre-SOC ls180",
27 insert
=(woffs
+width
/2-scale
*5, woffs
+height
/2),
29 dwg
.add(dwg
.text("In collaboration with LIP6.fr",
30 insert
=(woffs
+width
/2-scale
*5, woffs
+height
/2+scale
),
32 dwg
.add(dwg
.text("Cell Libraries by Chips4Makers",
33 insert
=(woffs
+width
/2-scale
*5, woffs
+height
/2+scale
*2),
36 for i
, pin
in enumerate(pins
['pads.west']):
37 ht
= hoffs
+ height
- (i
* scale
) + scale
*0.5
38 dwg
.add(dwg
.line((woffs
-scale
*2, ht
-scale
*0.5),
39 (woffs
-scale
*4.5, ht
-scale
*0.5),
40 stroke
=svgwrite
.rgb(255, 255, 16, '%'),
41 stroke_width
=scale
/10.0))
42 dwg
.add(dwg
.text(pin
.upper(), insert
=(woffs
-scale
*12, ht
),
44 dwg
.add(dwg
.text("W%d" % (i
+1), insert
=(woffs
-scale
*1.5, ht
),
47 for i
, pin
in enumerate(pins
['pads.east']):
48 ht
= hoffs
+ height
- (i
* scale
) + scale
*0.5
49 wd
= width
+ woffs
+ scale
*2
50 dwg
.add(dwg
.line((wd
+scale
*2, ht
-scale
*0.5),
51 (wd
+scale
*4.5, ht
-scale
*0.5),
52 stroke
=svgwrite
.rgb(255, 255, 16, '%'),
53 stroke_width
=scale
/10.0))
54 dwg
.add(dwg
.text(pin
.upper(), insert
=(wd
+scale
*5, ht
-scale
*0.25),
56 dwg
.add(dwg
.text("E%d" % (i
+1), insert
=(wd
, ht
-scale
*0.25),
59 for i
, pin
in enumerate(pins
['pads.north']):
60 wd
= woffs
+ i
* scale
+ scale
*1.5
61 dwg
.add(dwg
.line((wd
, hoffs
-scale
*2),
62 (wd
, hoffs
-scale
*4.5),
63 stroke
=svgwrite
.rgb(255, 255, 16, '%'),
64 stroke_width
=scale
/10.0))
65 pos
=(wd
, hoffs
-scale
*5.0)
66 txt
= dwg
.text(pin
.upper(), insert
=pos
, fill
='white')
69 pos
=(wd
+scale
*0.25, hoffs
-scale
*0.25)
70 txt
= dwg
.text("N%d" % (i
+1), insert
=pos
, fill
='white')
74 for i
, pin
in enumerate(pins
['pads.south']):
75 wd
= woffs
+ i
* scale
+ scale
*1.5
76 ht
= hoffs
+ height
+ scale
*2
77 dwg
.add(dwg
.line((wd
, ht
+scale
*2),
79 stroke
=svgwrite
.rgb(255, 255, 16, '%'),
80 stroke_width
=scale
/10.0))
81 pos
=(wd
-scale
*0.25, ht
+scale
*5.0)
82 txt
= dwg
.text(pin
.upper(), insert
=pos
, fill
='white')
85 pos
=(wd
-scale
*0.25, ht
+scale
*0.25)
86 txt
= dwg
.text("S%d" % (i
+1), insert
=pos
, fill
='white')
93 def display(of
, pins
, banksel
=None, muxwidth
=4):
95 | Pin | Mux0 | Mux1 | Mux2 | Mux3 |
96 | --- | ----------- | ----------- | ----------- | ----------- |
98 pinidx
= sorted(pins
.keys())
100 pdata
= pins
.get(pin
)
103 for mux
in range(muxwidth
):
106 name
, bank
= pdata
[mux
]
111 res
= '| %3d |' % pin
112 for mux
in range(muxwidth
):
116 name
, bank
= pdata
[mux
]
117 res
+= " %s %-9s |" % (bank
, name
)
118 of
.write("%s\n" % res
)
124 if not f
.startswith('FB_'):
128 return f2
[0], int(f2
[1])
131 while f
and not f
[0].isdigit():
134 return a
, int(f
) if f
else None
146 def find_fn(fname
, names
):
148 if fname
.startswith(n
):
151 def map_name(pinmap
, fn
, fblower
, pin
, rename
):
153 if pin
[:-1].isdigit():
154 print "map name digit", pin
, fn
, fblower
155 if fn
in ['PWM', 'EINT', 'VDD', 'VSS']:
156 return fn
.lower() + pin
.lower()
158 return 'gpio' + pin
[1:].lower()
162 pk
= '%s%s_%s' % (fblower
, pin
[0], pin
[:-1])
163 elif pin
[:-1].isdigit() and fn
!= 'EINT':
164 pk
= '%s%s_out' % (fblower
, pin
[:-1])
166 pk
= '%s_%s' % (fblower
, pin
[:-1])
167 print "map name", pk
, fblower
, pinmap
.has_key(pk
)
168 if not pinmap
.has_key(pk
):
170 remapped
= pinmap
[pk
]
171 uscore
= remapped
.find('_')
174 fn
, pin
= remapped
[:uscore
], remapped
[uscore
+1:] + pin
[-1]
177 def python_pindict(of
, pinmap
, pins
, function_names
, dname
, remap
):
180 of
.write("\n%s = OrderedDict()\n" % dname
)
182 for k
, pingroup
in pins
.byspec
.items():
183 (a
, n
) = k
.split(":")
187 of
.write("%s['%s'] = [ " % (dname
, fblower
))
190 for i
, p
in enumerate(pingroup
):
191 name
= map_name(pinmap
, k
[0], fblower
, p
, remap
)
192 res
[fblower
].append(name
)
193 of
.write("'%s', " % name
)
195 if count
== 4 and i
!= len(pingroup
)-1:
199 print " dict %s" % dname
, a
, n
, pingroup
203 def python_dict_fns(of
, pinmap
, pins
, function_names
):
204 of
.write("# auto-generated by Libre-SOC pinmux program: do not edit\n")
205 of
.write("# python src/pinmux_generator.py -v -s {spec} -o {output}\n")
206 of
.write("# use OrderedDict to fix stable order for JTAG Boundary Scan\n")
207 of
.write("from collections import OrderedDict\n")
209 fn_names
= function_names
.keys()
212 fnidx
= list(fns
.keys())
213 fnidx
.sort(key
=fnsplit
)
215 print "python fnames", function_names
216 print "python speckeys", pins
.byspec
.keys()
217 print "python dict fns", dir(pins
.gpio
)
218 print pins
.gpio
.pinfn('', '')
219 print pins
.pwm
.pinfn('', '')
220 print pins
.sdmmc
.pinfn('', '')
221 print "by spec", pins
.byspec
224 pd
= python_pindict(of
, {}, pins
, function_names
, 'pindict', False)
225 ld
= python_pindict(of
, pinmap
, pins
, function_names
, 'litexdict', True)
229 # process results and create name map
230 litexmap
= OrderedDict()
234 for pname
, lname
in zip(pl
, ll
):
235 pname
= "%s_%s" % (k
, pname
[:-1]) # strip direction +/-/*
236 lname
= lname
[:-1] # strip direction +/-/*
237 if k
in ['eint', 'pwm', 'gpio', 'vdd', 'vss']: # sigh
238 lname
= "%s_%s" % (k
, lname
)
239 litexmap
[pname
] = lname
240 print "litexmap", litexmap
241 of
.write("litexmap = {\n")
242 for k
, v
in litexmap
.items():
243 of
.write("\t'%s': '%s',\n" % (k
, v
))
248 def display_fns(of
, bankspec
, pins
, function_names
):
249 fn_names
= function_names
.keys()
251 for (pin
, pdata
) in pins
.items():
252 for mux
in range(0, 4): # skip GPIO for now
255 name
, bank
= pdata
[mux
]
256 assert name
is not None, str(bank
)
259 fns
[name
].append((pin
- bankspec
[bank
], mux
, bank
))
261 fnidx
= list(fns
.keys())
262 fnidx
.sort(key
=fnsplit
)
265 fnbase
= find_fn(fname
, fn_names
)
266 #fblower = fnbase.lower()
267 assert fnbase
in function_names
, "fn %s not in descriptions %s" % \
268 (fname
, str(function_names
.keys()))
269 #print "name", fname, fnbase
270 if fnbase
!= current_fn
:
271 if current_fn
is not None:
273 of
.write("## %s\n\n%s\n\n" % (fnbase
, function_names
[fnbase
]))
275 of
.write("* %-9s :" % fname
)
276 for (pin
, mux
, bank
) in fns
[fname
]:
277 of
.write(" %s%d/%d" % (bank
, pin
, mux
))
283 def check_functions(of
, title
, bankspec
, fns
, pins
, required
, eint
, pwm
,
286 pins
= deepcopy(pins
)
287 if descriptions
is None:
294 of
.write("# Pinmap for %s\n\n" % title
)
296 print "fn_idx", fnidx
298 print "fnspec", pins
.fnspec
.keys()
299 print "required", required
300 for name
in required
:
301 of
.write("## %s\n\n" % name
)
302 if descriptions
and name
in descriptions
:
303 of
.write("%s\n\n" % descriptions
[name
])
305 name
= name
.split(':')
307 findbank
= name
[0][0]
308 findmux
= int(name
[0][1:])
314 name
= name
.split('/')
325 if not fname
.startswith(name
):
327 for k
in pins
.fnspec
.keys():
328 if fname
.startswith(k
):
329 fk
= list(pins
.fnspec
[k
].keys())
332 #print fname, fn, dir(fn)
334 count
= len(fn
.pingroup
)
335 for pin
, mux
, bank
in fns
[fname
]:
336 if findbank
is not None:
341 pin_
= pin
+ bankspec
[bank
]
343 pinfound
[pin_
] = (fname
, pin_
, bank
, pin
, mux
)
345 pinidx
= sorted(pinfound
.keys())
349 print ("pinidx", pinidx
)
351 fname
, pin_
, bank
, pin
, mux
= pinfound
[pin_
]
355 if len(found
) > count
:
359 of
.write("* %s %d %s%d/%d\n" % (fname
, pin_
, bank
, pin
, mux
))
362 if removedcount
!= count
:
364 print "no match between required and available pins"
366 print ("not all found", name
, removedcount
, count
, title
, found
,
368 print ("pins found", pinfound
)
375 for name
in descriptions
.keys():
376 if not name
.startswith('GPIO'):
384 of
.write("## GPIO\n\n")
390 if descriptions
and fname
in descriptions
:
391 desc
= ': %s' % descriptions
[fname
]
394 pin_
= pin
+ bankspec
[bank
]
399 of
.write("* %-8s %d %s%-2d %s\n" % (fname
, pin_
, bank
, pin
, desc
))
403 display_group(of
, bankspec
, "EINT", eint
, fns
, pins
, descriptions
)
405 display_group(of
, bankspec
, "PWM", pwm
, fns
, pins
, descriptions
)
407 of
.write("## Unused Pinouts (spare as GPIO) for '%s'\n\n" % title
)
408 if descriptions
and 'GPIO' in descriptions
:
409 of
.write("%s\n\n" % descriptions
['GPIO'])
416 def display_group(of
, bankspec
, title
, todisplay
, fns
, pins
, descriptions
):
417 of
.write("## %s\n\n" % title
)
420 for fname
in todisplay
:
422 if descriptions
and fname
in descriptions
:
423 desc
= ': %s' % descriptions
[fname
]
424 fname
= fname
.split(':')
426 findbank
= fname
[0][0]
427 findmux
= int(fname
[0][1:])
433 for (pin
, mux
, bank
) in fns
[fname
]:
434 if findbank
is not None:
441 pin_
= pin
+ bankspec
[bank
]
446 of
.write("* %s %d %s%d/%d %s\n" %
447 (fname
, pin_
, bank
, pin
, mux
, desc
))
451 def display_fixed(of
, fixed
, offs
):
453 fkeys
= sorted(fixed
.keys())
456 for pin
, k
in enumerate(fkeys
):
457 of
.write("## %s\n\n" % k
)
460 for name
in fixed
[k
]:
464 if prevname
[:2] == name
[:2] and linecount
!= 0:
465 of
.write(" %s" % name
)
470 of
.write("* %d: %d %s" % (pin_
, pin
, name
))
472 res
.append((pin_
, name
))