blob: 248f871f3004f05b516893e7c01f675853a13b6f [file] [log] [blame]
#!/usr/bin/env python3
from collections import defaultdict
import json
import os
import pprint
import re
import sys
import textwrap
NUM = re.compile('_[0-9]+$')
def sort_(s):
"""
>>> sort_('a')
('a', 0)
>>> sort_('a_1')
('a', 1)
>>> sort_('a_100')
('a', 100)
>>> sort_(('a', '123'))
[('a', 0), '123']
>>> sort_(('123_3_3', ('hello', 1)))
[('123_3', 3), ('hello', 1)]
"""
if isinstance(s, tuple):
return [sort_(s[0])]+list(s[1:])
m = NUM.search(s)
if m:
return (s[:m.start(0)], int(m.group(0)[1:]))
else:
return (s, 0)
def out(l):
"""
>>> out([
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_1',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_3',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_5',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_6',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_7',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_0',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_4',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_2',
... 'sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_8'])
('sky130_fd_pr__rf_pfet_01v8_bM02__vth0_diff_', '0..8')
"""
l = list(l)
if len(l) == 1:
return l
p = os.path.commonprefix(l)
if p:
try:
o = tuple(sorted(int(i[len(p):]) for i in l))
if len(o) > 2:
seq = tuple(range(o[0], o[-1]+1))
if o == seq:
o = '{}..{}'.format(o[0], o[-1])
except ValueError:
o = tuple(sorted((i[len(p):] for i in l), key=sort_))
l = (p, o)
else:
l.sort(key=sort_)
return l
def pf(i, width=None):
"""
>>> pf(0.0)
' 0.0'
>>> pf(-0.04702)
'-0.04702'
>>> pf(0.0, 10)
' 0.0 '
>>> pf(-0.04702, 10)
'-0.04702 '
>>> pf(0.00120508503584265)
' 0.00120508503584265'
>>> pf(0.00120508503584265, 10)
' 0.001205 '
>>> pf(-0.00120508503584265)
'-0.00120508503584265'
>>> pf(-0.00120508503584265, 10)
'-0.001205 '
"""
s = str(i)
if s and s[0] != '-':
s = ' '+s
if width:
if len(s) > width:
if s[0] == ' ':
s = ' %-0{}f'.format(width-1) % i
elif s[0] == '-':
s = '%-0{}f'.format(width) % i
else:
s = s.ljust(width)
return s
def main():
params = json.load(open('spice-params.json'))
constants = defaultdict(lambda: defaultdict(list))
used_by = defaultdict(lambda: defaultdict(list))
for p in params:
for f, v in params[p].items():
if 'value' in v:
assert len(v['value']), v['value']
v0 = v['value'][0]
constants[p][v0].append(f)
elif 'deps' in v:
for d in v['deps']:
used_by[d][p].append(f)
def undefaultdict(d):
for k in list(d.keys()):
if isinstance(d[k], defaultdict):
d[k] = undefaultdict(d[k])
return dict(d)
constants = undefaultdict(constants)
used_by = undefaultdict(used_by)
print()
print()
print("Constants")
print('-'*75)
lk = max(len(k) for k in constants)
lv = max(max(len(pf(s)) for s in v.keys()) for v in constants.values())
lv = min(lv, len('-0.00024908'))
for k, v in sorted(constants.items(), key=sort_):
s = list(sorted(v.keys()))
if len(s) == 1:
s = pf(s.pop(0), lv)
else:
s = ", ".join(pf(i, lv) for i in s)
print(k.ljust(lk), "[] == ", s)
print('-'*75)
print()
print()
print("Used by")
print('-'*75)
l = max(len(k) for k in used_by)
for k, v in sorted(used_by.items(), key=sort_):
v = out(v.keys())
if len(v) > MAX_LEN:
v = v[:int(MAX_LEN/2)-1]+['...']+v[-int(MAX_LEN/2):]
elif len(v) == 2 and len(v[1]) > MAX_LEN:
v = (v[0], tuple(list(v[1][:int(MAX_LEN/2)-1])+['...']+list(v[1][-int(MAX_LEN/2):])))
k = " {} --> ".format(k.ljust(l))
vs = textwrap.indent(pprint.pformat(v, compact=False), ' '*len(k))
sys.stdout.write(k)
sys.stdout.write(vs[len(k):])
sys.stdout.write('\n')
print('-'*75)
MAX_LEN = 100
if __name__ == "__main__":
import doctest
fails, _ = doctest.testmod()
if fails != 0:
sys.exit("Some test failed!")
sys.exit(main())