mirror of https://github.com/openXC7/prjxray.git
145 lines
4.1 KiB
Python
145 lines
4.1 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 build_tilejo(fnins):
|
|
'''
|
|
{
|
|
"tiles": {
|
|
"BRKH_B_TERM_INT": {
|
|
"pips": {},
|
|
"wires": {
|
|
"B_TERM_UTURN_INT_ER1BEG0": [
|
|
null,
|
|
null,
|
|
93,
|
|
null
|
|
],
|
|
'''
|
|
|
|
tilejo = {"tiles": {}}
|
|
for fnin in fnins:
|
|
tileji = json.load(open(fnin, 'r'))
|
|
for tilek, tilevi in tileji['tiles'].items():
|
|
# No previous data? Copy
|
|
tilevo = tilejo['tiles'].get(tilek, None)
|
|
if tilevo is None:
|
|
tilejo['tiles'][tilek] = tilevi
|
|
# Otherwise combine
|
|
else:
|
|
|
|
def process_type(etype):
|
|
for pipk, pipvi in tilevi[etype].items():
|
|
pipvo = tilevo[etype][pipk]
|
|
for cornerk, corneri in corner_s2i.items():
|
|
cornervo = pipvo[corneri]
|
|
cornervi = pipvi[corneri]
|
|
# no new data
|
|
if cornervi is None:
|
|
pass
|
|
# no previous data
|
|
elif cornervo is None:
|
|
pipvo[corneri] = cornervi
|
|
# combine
|
|
else:
|
|
minmax = corner2minmax[cornerk]
|
|
pipvo[corneri] = minmax(cornervi, cornervo)
|
|
|
|
process_type('pips')
|
|
process_type('wires')
|
|
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 check_corners_minmax(tilej, verbose=False):
|
|
# TODO: check fast vs slow
|
|
pass
|
|
|
|
|
|
def run(fnins, fnout, verbose=False):
|
|
tilejo = build_tilejo(fnins)
|
|
check_corner_minmax(tilejo)
|
|
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()
|