mirror of https://github.com/openXC7/prjxray.git
166 lines
4.3 KiB
Python
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()
|