timfuz: combine tile process corners

Signed-off-by: John McMaster <johndmcmaster@gmail.com>
This commit is contained in:
John McMaster 2018-09-12 18:30:09 -07:00
parent 2a28dabf02
commit c104e70724
4 changed files with 154 additions and 15 deletions

View File

@ -1,5 +1,26 @@
all:
cd speed && make
cd timgrid && make
cd projects && make
# for now hammering on just picorv32
# consider instead aggregating multiple projects
PRJ?=picorv32
PRJN?=8
all: build/tilea.json
clean:
rm -rf build
cd speed && $(MAKE) clean
cd timgrid && $(MAKE) clean
cd projects && $(MAKE) clean
speed/build/speed.json:
cd speed && $(MAKE)
timgrid/build/timgrid.json:
cd timgrid && $(MAKE)
build/tilea.json: projects/$(PRJ)/build/tilea.json
mkdir -p build
cp projects/$(PRJ)/build/tilea.json build/tilea.json
projects/$(PRJ)/build/tilea.json: speed/build/speed.json timgrid/build/timgrid.json
cd projects/$(PRJ) && $(MAKE) N=$(PRJN)

View File

@ -13,19 +13,11 @@ Currently this document focuses exclusively on fabric timing delays.
## Quick start
```
pushd speed
make
popd
pushd timgrid
make
popd
pushd projects/placelut
make N=1
popd
```
This will take a relatively long time (say 45 min) and generate build/tilea.json
## Vivado background

View File

@ -12,7 +12,7 @@ BADPRJ_OK?=N
TILEA_JSONS=build/fast_max/tilea.json build/fast_min/tilea.json build/slow_max/tilea.json build/slow_min/tilea.json
all: $(TILEA_JSONS)
all: build/tilea.json
# make build/checksub first
build/fast_max/tilea.json: build/checksub
@ -76,3 +76,6 @@ build/checksub: build/grouped.csv build/sub.json
python3 $(TIMFUZ_DIR)/checksub.py --sub-json build/sub.json build/grouped.csv
touch build/checksub
build/tilea.json: $(TILEA_JSONS)
python3 $(TIMFUZ_DIR)/tile_combine.py --out build/tilea.json $(TILEA_JSONS)

View File

@ -0,0 +1,123 @@
#!/usr/bin/env python3
import sys
import os
import time
import json
from collections import OrderedDict
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('minmax: %u / %u bad' % (bad, checks))
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 .json file')
parser.add_argument('fnins', nargs='+', help='Input .json files')
args = parser.parse_args()
run(args.fnins, args.out, verbose=False)
if __name__ == '__main__':
main()