mirror of
https://github.com/TinyTapeout/tt-support-tools.git
synced 2026-11-03 04:36:09 +01:00
116 lines
4.2 KiB
Python
Executable File
116 lines
4.2 KiB
Python
Executable File
import os
|
|
import csv
|
|
import json
|
|
import re
|
|
import glob
|
|
|
|
# can't find a google version
|
|
CELL_URL = 'https://antmicro-skywater-pdk-docs.readthedocs.io/en/test-submodules-in-rtd/contents/libraries/sky130_fd_sc_ls/cells/'
|
|
|
|
|
|
def print_warnings(args):
|
|
warnings = []
|
|
with open(os.path.join(args.run_dir, 'logs/synthesis/1-synthesis.log')) as f:
|
|
for line in f.readlines():
|
|
if line.startswith('Warning:'):
|
|
# bogus warning https://github.com/YosysHQ/yosys/commit/bfacaddca8a2e113e4bc3d6177612ccdba1555c8
|
|
if 'WIDTHLABEL' not in line:
|
|
warnings.append(line.strip())
|
|
if len(warnings):
|
|
print('# Synthesis warnings')
|
|
print()
|
|
for warning in warnings:
|
|
print(f'* {warning}')
|
|
|
|
|
|
def print_stats(args):
|
|
with open(os.path.join(args.run_dir, 'reports/metrics.csv')) as f:
|
|
report = list(csv.DictReader(f))[0]
|
|
|
|
print('# Routing stats')
|
|
print()
|
|
print('| Utilisation (%) | Wire length (um) |')
|
|
print('|-------------|------------------|')
|
|
print('| {} | {} |'.format(report['OpenDP_Util'], report['wire_length']))
|
|
|
|
|
|
# Print the summaries
|
|
def summarize(args):
|
|
cell_count = get_cell_count_from_gl(args)
|
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
with open(os.path.join(script_dir, 'categories.json')) as fh:
|
|
categories = json.load(fh)
|
|
with open(os.path.join(script_dir, 'defs.json')) as fh:
|
|
defs = json.load(fh)
|
|
|
|
# print all used cells, sorted by frequency
|
|
total = 0
|
|
if args.print_cell_summary:
|
|
print('# Cell usage')
|
|
print()
|
|
print('| Cell Name | Description | Count |')
|
|
print('|-----------|-------------|-------|')
|
|
for name, count in sorted(cell_count.items(), key=lambda item: item[1], reverse=True):
|
|
if count > 0:
|
|
total += count
|
|
cell_link = f'{CELL_URL}{name}'
|
|
print(f'| [{name}]({cell_link}) | {defs[name]["description"]} |{count} |')
|
|
|
|
print(f'| | Total | {total} |')
|
|
|
|
if args.print_cell_category:
|
|
by_category = {}
|
|
for cell_name in cell_count:
|
|
cat_index = categories['map'][cell_name]
|
|
cat_name = categories['categories'][cat_index]
|
|
if cat_name in by_category:
|
|
by_category[cat_name]['count'] += cell_count[cell_name]
|
|
by_category[cat_name]['examples'].append(cell_name)
|
|
else:
|
|
by_category[cat_name] = {'count' : cell_count[cell_name], 'examples' : [cell_name]}
|
|
|
|
print('# Cell usage by Category')
|
|
print()
|
|
print('| Category | Cells | Count |')
|
|
print('|---------------|----------|-------|')
|
|
for cat_name, cat_dict in sorted(by_category.items(), key=lambda x: x[1]['count'], reverse=True):
|
|
cell_links = [f'[{name}]({CELL_URL}{name})' for name in cat_dict['examples']]
|
|
print(f'|{cat_name} | {" ".join(cell_links)} | {cat_dict["count"]}|')
|
|
|
|
|
|
# Parse the lib, cell and drive strength an OpenLane gate-level Verilog file
|
|
def get_cell_count_from_gl(args):
|
|
cell_count = {}
|
|
total = 0
|
|
gl_files = glob.glob(os.path.join(args.run_dir, 'results/final/verilog/gl/*.nl.v'))
|
|
with open(gl_files[0]) as fh:
|
|
for line in fh.readlines():
|
|
m = re.search(r'sky130_(\S+)__(\S+)_(\d+)', line)
|
|
if m is not None:
|
|
total += 1
|
|
cell_lib = m.group(1)
|
|
cell_name = m.group(2)
|
|
cell_drive = m.group(3)
|
|
assert cell_lib in ['fd_sc_hd', 'ef_sc_hd']
|
|
try:
|
|
cell_count[cell_name] += 1
|
|
except KeyError:
|
|
cell_count[cell_name] = 1
|
|
return (cell_count)
|
|
|
|
|
|
# Load all the json defs and combine into one big dict, keyed by cellname
|
|
# Needs access to the PDK
|
|
def create_defs(args):
|
|
# replace this with a find
|
|
json_files = glob.glob('sky130_fd_sc_hd/latest/cells/*/definition.json')
|
|
definitions = {}
|
|
for json_file in json_files:
|
|
with open(json_file) as fh:
|
|
definition = json.load(fh)
|
|
definitions[definition['name']] = definition
|
|
|
|
with open('defs.json', 'w') as fh:
|
|
json.dump(definitions, fh)
|