| #!/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()) |