blob: d797e2c6ebe7f9572813be64f0b401c33595cce7 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2020 The Skywater PDK Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import csv
import os
import pprint
import re
import sys
from collections import defaultdict
import common
import flatten
import argparse
from pathlib import Path
RE_MODEL_START = re.compile(r'^model\s+(?P<model>[^ ]+)\s+bsim(?P<bsim>[0-9vV]+)\s+{(\n|$)')
RE_MODEL_END = re.compile(r'^[\s\n]*ends(?P<end>.*)(\n|$)')
RE_ROW = re.compile(r'^\s*(?P<row>[0-9]+):\s*type=(?P<type>.*?)(\n|$)')
RE_PARAM = re.compile(r'^[+]\s*(?P<param>[^ ]+)\s*=\s*(?P<value>.+?)(\n|$)')
RE_GROUP = re.compile(r'[*\s]*?(?P<group>[^*\n]+?)[*\s]*(\n|$)')
GROUPS = defaultdict(set)
FIELDS = set()
def write_csv(outname, models):
w = csv.writer(open(outname,'w'))
row = ['model', 'bin', 'num_bins']
row.extend(sorted(FIELDS))
w.writerow(row)
for m in models:
for i, r in enumerate(m['rows']):
row = []
row.append(m['model'])
row.append(i)
row.append(len(m['rows']))
for f in sorted(FIELDS):
row.append(r.get(f, 'N\A'))
w.writerow(row)
def pm3_to_rows(infile):
models = [None]
rows = []
row_params = {}
group = None
for comment, bit in flatten.read_bits(infile, 'spice'):
if comment:
m = RE_GROUP.match(bit)
if m:
group = m.group('group').title()
print('g', group)
else:
print('#', repr(bit))
else:
for l in bit.splitlines(keepends=True):
if models[-1] is None:
m = RE_MODEL_START.match(l)
if not m:
print("Skipping", repr(l))
continue
models.pop(-1)
models.append({
'model': m.group('model'),
'bsim': m.group('bsim'),
'rows': [],
})
continue
m = RE_MODEL_END.match(l)
if m:
if row_params:
models[-1]['rows'].append(row_params)
print("Ends", m.group('end'))
models.append(None)
break
m = RE_ROW.match(l)
if m:
if row_params:
models[-1]['rows'].append(row_params)
row = m.group('row')
t = m.group('type')
row_params = {
'row': 0,
'type': t,
}
continue
m = RE_PARAM.match(l)
if m:
params = {}
name = [m.group('param')]
value = []
bits = m.group('value').split()
print(name, bits)
while bits:
value.append(bits.pop(0))
if bits and bits[0] in ('+', '*'):
value.append(bits.pop(0))
value.append(bits.pop(0))
if value[-1][-1] == '(':
value.append(bits.pop(0))
continue
params["".join(name)] = " ".join(value)
if bits:
name = [bits.pop(0)]
value = []
assert bits.pop(0) == '=', repr(l)
print(params)
for k in params:
FIELDS.add(k)
GROUPS[group].add(k)
assert k not in row_params
try:
params[k] = float(params[k])
except ValueError:
pass
row_params[k] = params[k]
continue
if l.strip():
print('?', repr(l))
assert models[-1] == None
models.pop(-1)
return models
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
"input_dir",
help="The path to the directory containing skywater-pdk",
type=Path)
args = parser.parse_args()
files = sorted(args.input_dir.rglob('*.pm3'))
pprint.pprint(files)
models = []
for pn in files:
pn = str(pn)
if 'rf' in pn:
continue
print()
print(pn)
print('='*75)
newmodels = pm3_to_rows(pn)
base, ext = os.path.splitext(pn)
print('-'*75)
outfile = base+'.csv'
print(outfile)
# write_csv(outfile, newmodels)
print(newmodels)
print('='*75)
models.extend(newmodels)
write_csv('out.csv', models)