prjxray/fuzzers/007-timing/timgrid_vc2v.py

166 lines
4.3 KiB
Python

#!/usr/bin/env python3
import sys
import os
import time
import json
from collections import OrderedDict
import timfuz
corner_s2i = OrderedDict(
[
('fast_max', 0),
('fast_min', 1),
('slow_max', 2),
('slow_min', 3),
])
corner2minmax = {
'fast_max': max,
'fast_min': min,
'slow_max': max,
'slow_min': min,
}
def merge_bdict(vi, vo):
'''
vi: input dictionary
vo: output dictionary
values are corner delay 4 tuples
'''
for name, bis in vi.items():
bos = vo.get(name, [None, None, None, None])
for cornerk, corneri in corner_s2i.items():
bo = bos[corneri]
bi = bis[corneri]
# no new data
if bi is None:
pass
# no previous data
elif bo is None:
bos[corneri] = bi
# combine
else:
minmax = corner2minmax[cornerk]
bos[corneri] = minmax(bi, bo)
def merge_tiles(tileji, tilejo):
'''
{
"tiles": {
"BRKH_B_TERM_INT": {
"pips": {},
"wires": {
"B_TERM_UTURN_INT_ER1BEG0": [
null,
null,
93,
null
],
'''
for tilek, tilevi in tileji.items():
# No previous data? Copy
tilevo = tilejo.get(tilek, None)
if tilevo is None:
tilejo[tilek] = tilevi
# Otherwise combine
else:
merge_bdict(tilevi['pips'], tilevo['pips'])
merge_bdict(tilevi['wires'], tilevo['wires'])
def merge_sites(siteji, sitejo):
for k, vi in siteji.items():
vo = sitejo.get(k, None)
# No previous data? Copy
if vo is None:
sitejo[k] = vi
# Otherwise combine
else:
merge_bdict(vi, vo)
def build_tilejo(fnins):
# merge all inputs into blank output
tilejo = {"tiles": {}, "sites": {}}
for fnin in fnins:
tileji = json.load(open(fnin, 'r'))
merge_tiles(tileji['tiles'], tilejo['tiles'])
merge_sites(tileji['sites'], tilejo['sites'])
return tilejo
def check_corner_minmax(tilej, verbose=False):
# Post processing pass looking for min/max inconsistencies
# Especially an issue due to complexities around under-constrained elements
# (ex: pivots set to 0 delay)
print('Checking for min/max consistency')
checks = 0
bad = 0
for tilev in tilej['tiles'].values():
def process_type(etype):
nonlocal checks
nonlocal bad
for pipk, pipv in tilev[etype].items():
for corner in ('slow', 'fast'):
mini = corner_s2i[corner + '_min']
minv = pipv[mini]
maxi = corner_s2i[corner + '_max']
maxv = pipv[maxi]
if minv is not None and maxv is not None:
checks += 1
if minv > maxv:
if verbose:
print(
'WARNING: element %s %s min/max adjusted on corner %s'
% (etype, pipk, corner))
bad += 1
pipv[mini] = maxv
pipv[maxi] = minv
process_type('pips')
process_type('wires')
print('')
print('minmax: %u / %u pairs bad pairs adjusted' % (bad, checks))
timfuz.tilej_stats(tilej)
def run(fnins, fnout, verbose=False):
tilejo = build_tilejo(fnins)
check_corner_minmax(tilejo)
# XXX: check fast vs slow?
# check_corners_minmax(tilejo)
json.dump(
tilejo,
open(fnout, 'w'),
sort_keys=True,
indent=4,
separators=(',', ': '))
def main():
import argparse
parser = argparse.ArgumentParser(
description='Combine multiple tile corners into one .json file')
parser.add_argument(
'--out', required=True, help='Combined timgrid-v.json files')
parser.add_argument('fnins', nargs='+', help='Input timgrid-vc.json files')
args = parser.parse_args()
run(args.fnins, args.out, verbose=False)
if __name__ == '__main__':
main()