blob: 71dbc123cf4f8e6292b14f0421a72c80e03ac3f0 [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2020 The SkyWater PDK Authors.
#
# Use of this source code is governed by the Apache 2.0
# license that can be found in the LICENSE file or at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
import csv
import os
import pathlib
import textwrap
import sys
from collections import OrderedDict
from common import copyright_header
def wrap_comment(prefix, s):
p = '* '+prefix+' '
m = '* '+(' '*len(prefix))+' '
return "\n".join(textwrap.wrap(
s, initial_indent=p, subsequent_indent=m))
def wrap_pininfo(s):
prefix = '*.PININFO '
return "\n".join(textwrap.wrap(
s, initial_indent=prefix, subsequent_indent=prefix))
def wrap_line(s):
return "\n".join(textwrap.wrap(
s, initial_indent='', subsequent_indent='+ '))
def attribs(row):
o = []
for k, v in row.items():
if not v:
continue
if isinstance(k, int):
o.append(v)
else:
o.append(f'{k}={v}')
return ' '.join(o)
def remap(rows):
headers = next(rows)
for i, h in enumerate(headers):
if not h:
headers[i] = i
o = []
for r in rows:
o.append(OrderedDict(zip(headers, r)))
return o
def convert_tsv2cdl(path):
assert path.endswith('.netlist.tsv')
dirname = os.path.dirname(path)
filename = os.path.basename(path)
basename = filename.split('.', 1)[0]
outpath = os.path.join(dirname, basename+'.cdl')
f_in = open(path, newline='')
f_out = open(outpath, 'w')
f_out.write(copyright_header['*'])
tsv_in = csv.reader(f_in, delimiter='\t')
row0 = list(next(tsv_in))
rows = remap(tsv_in)
subckt_name = row0[0]
subckt_pins = row0[1]
extra = []
while rows and rows[0]['Name'] == '':
extra = [f'{a}={b}' for a, b in rows.pop(0).items() if a]
f_out.write(f'.SUBCKT {subckt_name} ')
f_out.write(" ".join(a.split(':')[0] for a in subckt_pins.split()))
if extra:
f_out.write(' ')
f_out.write(' '.join(extra))
f_out.write('\n')
f_out.write(wrap_pininfo(f"{subckt_pins}"))
f_out.write('\n')
for row in rows:
formula = row.pop('Formula')
if row['Name'] == 'Note':
f_out.write(wrap_comment('Notes:', formula))
elif formula == 'MOSFET':
rowname = row.pop('Name')
nd = row.pop('nd')
ng = row.pop('ng')
ns = row.pop('ns')
nb = row.pop('nb')
mname = row.pop('mname')
f_out.write(wrap_line(
f"{rowname} {nd} {ng} {ns} {nb} {mname} "+attribs(row)))
elif formula in ('DIODE', 'RESISTOR'):
f_out.write(wrap_line(
f"{row.pop('Name')} " + attribs(row)))
elif row['Name'][0].upper() in ('R', 'X'):
f_out.write(wrap_line(
f"{row['Name']} {formula}"))
else:
assert False, (row, path)
f_out.write('\n')
f_out.write(f'.ENDS {subckt_name}\n')
print(f"Created {outpath}")
def main(args):
for a in args:
a = os.path.abspath(a)
if os.path.isdir(a):
return main(sorted(pathlib.Path(a).rglob('*.netlist.tsv')))
elif os.path.isfile(a):
convert_tsv2cdl(a)
else:
raise IOError(f"Unknown type: {a}")
return 0
if __name__ == "__main__":
import doctest
fails, _ = doctest.testmod()
if fails != 0:
exit(1)
sys.exit(main(sys.argv[1:]))