f8ba09d4e2bc20aae985946699d895afb9059d5e
3 from copy
import deepcopy
4 from collections
import OrderedDict
7 def bond_int_to_ext(pin
, bank
):
8 """ note that internal numbering is 0-31 whereas the DISPLAY internal
9 numbering is 1-32. this uses the INTERNAL numbering.
13 outer ring numbers: the python list order of the outer pads
14 middle numbers: the package number wires (plus side they are on)
15 inner numbers: the IO pad *python internal (0-31)* numbers plus side
18 N102 N101 N100 99 N 68 N67 N66 N65
19 W29 W30 W31 N0 N N31 E29 E30 E31
25 W2 W1 W0 S0 S S31 E0 E1 E2
26 S1 S2 S3 4 S 35 S36 S37 S38
30 # returns side, order-on-the-side, pin number
32 return 'N', pin
+3, 99-pin
34 return 'S', pin
+3, 4+pin
36 if pin
>= 29: # 29, 30, 31
37 return 'N', pin
-29, 100+(31-pin
)
39 return 'S', 2-pin
, 3-pin
40 return 'W', pin
-3, 103+(28-pin
)
43 return 'N', pin
+6, 67-(pin
-29)
45 return 'S', pin
+35, 36+pin
46 return 'E', pin
-3, 39+(pin
-3)
49 def create_sv(fname
, pins
):
50 """unsophisticated drawer of an SVG
56 print ("WARNING, no SVG image, not producing image %s" % fname
)
59 # create internal to external map
60 bondmap
= {'N': {}, 'S': {}, 'E': {}, 'W': {} }
61 padside
= {'pads.north': 'N', 'pads.east': 'E', 'pads.south': 'S',
63 for pinpad
, bank
in padside
.items():
64 for ipin
in range(len(pins
[pinpad
])):
65 eside
, enum
, epinnum
= bond_int_to_ext(ipin
, bank
)
66 bondmap
[eside
][enum
] = (epinnum
, ipin
, bank
)
67 with
open("/tmp/bondmap.txt", "w") as f
:
68 for k
,v
in bondmap
.items():
70 for enum
, (epinnum
, ipin
, bank
) in v
.items():
71 f
.write(" %d %d -> %s %d\n" % (enum
, epinnum
, bank
, ipin
))
74 width
= len(pins
['pads.north']) * scale
75 height
= len(pins
['pads.east']) * scale
76 woffs
= scale
*40#-width/2
77 hoffs
= scale
*40#-height/2
79 dwg
= svgwrite
.Drawing(fname
, profile
='full',
80 size
=(width
+scale
*80, height
+scale
*80))
81 dwg
.add(dwg
.rect((woffs
-scale
*2, hoffs
-scale
*2),
82 (woffs
+width
-scale
*34, hoffs
+height
-scale
*34),
83 stroke
=svgwrite
.rgb(16, 255, 16, '%'),
84 stroke_width
=scale
/10.0))
86 dwg
.add(dwg
.text("Libre-SOC ls180 QFP-128",
87 insert
=(woffs
+width
/2-scale
*5, woffs
+height
/2),
89 dwg
.add(dwg
.text("In collaboration with LIP6.fr",
90 insert
=(woffs
+width
/2-scale
*5, woffs
+height
/2+scale
),
92 dwg
.add(dwg
.text("Cell Libraries by Chips4Makers",
93 insert
=(woffs
+width
/2-scale
*5, woffs
+height
/2+scale
*2),
96 outerpos
= {'N': {}, 'S': {}, 'E': {}, 'W': {} }
97 for i
, pin
in enumerate(pins
['pads.west']):
98 ht
= hoffs
+ height
- (i
* scale
) + scale
*0.5
99 endline
= (woffs
-scale
*4.5, ht
-scale
*0.5)
100 dwg
.add(dwg
.line((woffs
-scale
*2, ht
-scale
*0.5),
102 stroke
=svgwrite
.rgb(16, 255, 16, '%'),
103 stroke_width
=scale
/10.0))
104 dwg
.add(dwg
.text(pin
.upper(), insert
=(woffs
-scale
*14, ht
),
106 dwg
.add(dwg
.text("W%d" % (i
+1), insert
=(woffs
-scale
*1.5, ht
),
109 for i
, pin
in enumerate(pins
['pads.east']):
110 ht
= hoffs
+ height
- (i
* scale
) + scale
*0.5
111 wd
= width
+ woffs
+ scale
*2
112 endline
= (wd
+scale
*4.5, ht
-scale
*0.5)
113 dwg
.add(dwg
.line((wd
+scale
*2, ht
-scale
*0.5),
115 stroke
=svgwrite
.rgb(16, 255, 16, '%'),
116 stroke_width
=scale
/10.0))
117 dwg
.add(dwg
.text(pin
.upper(), insert
=(wd
+scale
*5, ht
-scale
*0.25),
119 dwg
.add(dwg
.text("E%d" % (i
+1), insert
=(wd
, ht
-scale
*0.25),
122 for i
, pin
in enumerate(pins
['pads.north']):
123 wd
= woffs
+ i
* scale
+ scale
*1.5
124 endline
= (wd
, hoffs
-scale
*4.5)
125 dwg
.add(dwg
.line((wd
, hoffs
-scale
*2),
127 stroke
=svgwrite
.rgb(16, 255, 16, '%'),
128 stroke_width
=scale
/10.0))
129 pos
=(wd
, hoffs
-scale
*5.0)
130 txt
= dwg
.text(pin
.upper(), insert
=pos
, fill
='black')
133 pos
=(wd
+scale
*0.25, hoffs
-scale
*0.25)
134 txt
= dwg
.text("N%d" % (i
+1), insert
=pos
, fill
='white')
138 for i
, pin
in enumerate(pins
['pads.south']):
139 wd
= woffs
+ i
* scale
+ scale
*1.5
140 ht
= hoffs
+ height
+ scale
*2
141 endline
= (wd
, ht
+scale
*4.5)
142 dwg
.add(dwg
.line((wd
, ht
+scale
*2),
144 stroke
=svgwrite
.rgb(16, 255, 16, '%'),
145 stroke_width
=scale
/10.0))
146 pos
=(wd
-scale
*0.25, ht
+scale
*5.0)
147 txt
= dwg
.text(pin
.upper(), insert
=pos
, fill
='black')
150 pos
=(wd
-scale
*0.25, ht
+scale
*0.25)
151 txt
= dwg
.text("S%d" % (i
+1), insert
=pos
, fill
='white')
158 def display(of
, pins
, banksel
=None, muxwidth
=4):
160 | Pin | Mux0 | Mux1 | Mux2 | Mux3 |
161 | --- | ----------- | ----------- | ----------- | ----------- |
163 pinidx
= sorted(pins
.keys())
165 pdata
= pins
.get(pin
)
168 for mux
in range(muxwidth
):
171 name
, bank
= pdata
[mux
]
176 res
= '| %3d |' % pin
177 for mux
in range(muxwidth
):
181 name
, bank
= pdata
[mux
]
182 res
+= " %s %-9s |" % (bank
, name
)
183 of
.write("%s\n" % res
)
189 if not f
.startswith('FB_'):
193 return f2
[0], int(f2
[1])
196 while f
and not f
[0].isdigit():
199 return a
, int(f
) if f
else None
211 def find_fn(fname
, names
):
213 if fname
.startswith(n
):
216 def map_name(pinmap
, fn
, fblower
, pin
, rename
):
218 if pin
[:-1].isdigit():
219 print "map name digit", pin
, fn
, fblower
220 if fn
in ['PWM', 'EINT', 'VDD', 'VSS']:
221 return fn
.lower() + pin
.lower()
223 return 'gpio' + pin
[1:].lower()
227 pk
= '%s%s_%s' % (fblower
, pin
[0], pin
[:-1])
228 elif pin
[:-1].isdigit() and fn
!= 'EINT':
229 pk
= '%s%s_out' % (fblower
, pin
[:-1])
231 pk
= '%s_%s' % (fblower
, pin
[:-1])
232 print "map name", pk
, fblower
, pinmap
.has_key(pk
)
233 if not pinmap
.has_key(pk
):
235 remapped
= pinmap
[pk
]
236 uscore
= remapped
.find('_')
239 fn
, pin
= remapped
[:uscore
], remapped
[uscore
+1:] + pin
[-1]
242 def python_pindict(of
, pinmap
, pins
, function_names
, dname
, remap
):
245 of
.write("\n%s = OrderedDict()\n" % dname
)
247 for k
, pingroup
in pins
.byspec
.items():
248 (a
, n
) = k
.split(":")
252 of
.write("%s['%s'] = [ " % (dname
, fblower
))
255 for i
, p
in enumerate(pingroup
):
256 name
= map_name(pinmap
, k
[0], fblower
, p
, remap
)
257 res
[fblower
].append(name
)
258 of
.write("'%s', " % name
)
260 if count
== 4 and i
!= len(pingroup
)-1:
264 print " dict %s" % dname
, a
, n
, pingroup
268 def python_dict_fns(of
, pinmap
, pins
, function_names
):
269 of
.write("# auto-generated by Libre-SOC pinmux program: do not edit\n")
270 of
.write("# python src/pinmux_generator.py -v -s {spec} -o {output}\n")
271 of
.write("# use OrderedDict to fix stable order for JTAG Boundary Scan\n")
272 of
.write("from collections import OrderedDict\n")
274 fn_names
= function_names
.keys()
277 fnidx
= list(fns
.keys())
278 fnidx
.sort(key
=fnsplit
)
280 print "python fnames", function_names
281 print "python speckeys", pins
.byspec
.keys()
282 print "python dict fns", dir(pins
.gpio
)
283 print pins
.gpio
.pinfn('', '')
284 print pins
.pwm
.pinfn('', '')
285 print pins
.sdmmc
.pinfn('', '')
286 print "by spec", pins
.byspec
289 pd
= python_pindict(of
, {}, pins
, function_names
, 'pindict', False)
290 ld
= python_pindict(of
, pinmap
, pins
, function_names
, 'litexdict', True)
294 # process results and create name map
295 litexmap
= OrderedDict()
299 for pname
, lname
in zip(pl
, ll
):
300 pname
= "%s_%s" % (k
, pname
[:-1]) # strip direction +/-/*
301 lname
= lname
[:-1] # strip direction +/-/*
302 if k
in ['eint', 'pwm', 'gpio', 'vdd', 'vss']: # sigh
303 lname
= "%s_%s" % (k
, lname
)
304 litexmap
[pname
] = lname
305 print "litexmap", litexmap
306 of
.write("litexmap = {\n")
307 for k
, v
in litexmap
.items():
308 of
.write("\t'%s': '%s',\n" % (k
, v
))
313 def display_fns(of
, bankspec
, pins
, function_names
):
314 fn_names
= function_names
.keys()
316 for (pin
, pdata
) in pins
.items():
317 for mux
in range(0, 4): # skip GPIO for now
320 name
, bank
= pdata
[mux
]
321 assert name
is not None, str(bank
)
324 fns
[name
].append((pin
- bankspec
[bank
], mux
, bank
))
326 fnidx
= list(fns
.keys())
327 fnidx
.sort(key
=fnsplit
)
330 fnbase
= find_fn(fname
, fn_names
)
331 #fblower = fnbase.lower()
332 assert fnbase
in function_names
, "fn %s not in descriptions %s" % \
333 (fname
, str(function_names
.keys()))
334 #print "name", fname, fnbase
335 if fnbase
!= current_fn
:
336 if current_fn
is not None:
338 of
.write("## %s\n\n%s\n\n" % (fnbase
, function_names
[fnbase
]))
340 of
.write("* %-9s :" % fname
)
341 for (pin
, mux
, bank
) in fns
[fname
]:
342 of
.write(" %s%d/%d" % (bank
, pin
, mux
))
348 def check_functions(of
, title
, bankspec
, fns
, pins
, required
, eint
, pwm
,
351 pins
= deepcopy(pins
)
352 if descriptions
is None:
359 of
.write("# Pinmap for %s\n\n" % title
)
361 print "fn_idx", fnidx
363 print "fnspec", pins
.fnspec
.keys()
364 print "required", required
365 for name
in required
:
366 of
.write("## %s\n\n" % name
)
367 if descriptions
and name
in descriptions
:
368 of
.write("%s\n\n" % descriptions
[name
])
370 name
= name
.split(':')
372 findbank
= name
[0][0]
373 findmux
= int(name
[0][1:])
379 name
= name
.split('/')
390 if not fname
.startswith(name
):
392 for k
in pins
.fnspec
.keys():
393 if fname
.startswith(k
):
394 fk
= list(pins
.fnspec
[k
].keys())
397 #print fname, fn, dir(fn)
399 count
= len(fn
.pingroup
)
400 for pin
, mux
, bank
in fns
[fname
]:
401 if findbank
is not None:
406 pin_
= pin
+ bankspec
[bank
]
408 pinfound
[pin_
] = (fname
, pin_
, bank
, pin
, mux
)
410 pinidx
= sorted(pinfound
.keys())
414 print ("pinidx", pinidx
)
416 fname
, pin_
, bank
, pin
, mux
= pinfound
[pin_
]
420 if len(found
) > count
:
424 of
.write("* %s %d %s%d/%d\n" % (fname
, pin_
, bank
, pin
, mux
))
427 if removedcount
!= count
:
429 print "no match between required and available pins"
431 print ("not all found", name
, removedcount
, count
, title
, found
,
433 print ("pins found", pinfound
)
440 for name
in descriptions
.keys():
441 if not name
.startswith('GPIO'):
449 of
.write("## GPIO\n\n")
455 if descriptions
and fname
in descriptions
:
456 desc
= ': %s' % descriptions
[fname
]
459 pin_
= pin
+ bankspec
[bank
]
464 of
.write("* %-8s %d %s%-2d %s\n" % (fname
, pin_
, bank
, pin
, desc
))
468 display_group(of
, bankspec
, "EINT", eint
, fns
, pins
, descriptions
)
470 display_group(of
, bankspec
, "PWM", pwm
, fns
, pins
, descriptions
)
472 of
.write("## Unused Pinouts (spare as GPIO) for '%s'\n\n" % title
)
473 if descriptions
and 'GPIO' in descriptions
:
474 of
.write("%s\n\n" % descriptions
['GPIO'])
481 def display_group(of
, bankspec
, title
, todisplay
, fns
, pins
, descriptions
):
482 of
.write("## %s\n\n" % title
)
485 for fname
in todisplay
:
487 if descriptions
and fname
in descriptions
:
488 desc
= ': %s' % descriptions
[fname
]
489 fname
= fname
.split(':')
491 findbank
= fname
[0][0]
492 findmux
= int(fname
[0][1:])
498 for (pin
, mux
, bank
) in fns
[fname
]:
499 if findbank
is not None:
506 pin_
= pin
+ bankspec
[bank
]
511 of
.write("* %s %d %s%d/%d %s\n" %
512 (fname
, pin_
, bank
, pin
, mux
, desc
))
516 def display_fixed(of
, fixed
, offs
):
518 fkeys
= sorted(fixed
.keys())
521 for pin
, k
in enumerate(fkeys
):
522 of
.write("## %s\n\n" % k
)
525 for name
in fixed
[k
]:
529 if prevname
[:2] == name
[:2] and linecount
!= 0:
530 of
.write(" %s" % name
)
535 of
.write("* %d: %d %s" % (pin_
, pin
, name
))
537 res
.append((pin_
, name
))