prjxray/fuzzers/007-timing/tile_annotate.py

157 lines
4.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import timfuz
from timfuz import loadc_Ads_bs, Ads2bounds, PREFIX_W, PREFIX_P, PREFIX_SW_EI, PREFIX_SW_EO, PREFIX_SW_I, sw_ei_s2vals, sw_eo_s2vals, sw_i_s2vals
import sys
import os
import time
import json
def add_pip_wire(tilej, bounds, verbose=False):
'''
We know all possible pips and wires from tilej
Iterate over them and see if a result was generated
'''
used_bounds = set()
for tile in tilej['tiles'].values():
def addk(pws, prefix, k, v):
variable = prefix + ':' + v
val = bounds.get(variable, None)
# print(variable, val)
if val:
used_bounds.add(variable)
else:
val = [None, None, None, None]
pws[k] = val
pips = tile['pips']
for k, v in pips.items():
#pips[k] = bounds.get('PIP_' + v, [None, None, None, None])
addk(pips, PREFIX_P, k, v)
wires = tile['wires']
for k, v in wires.items():
#wires[k] = bounds.get('WIRE_' + v, [None, None, None, None])
addk(wires, PREFIX_W, k, v)
# verify all the variables that should be used were applied
# ...except tilecon may be an ROI and we solved everything
print(
"Interconnect: %u / %u variables used" %
(len(used_bounds), len(bounds)))
if verbose:
print('Remainder: %s' % (set(bounds.keys()) - used_bounds))
def add_sites(tilej, bounds):
# XXX: no source of truth currently
# is there a way we could get this?
# Naming discussion https://github.com/SymbiFlow/prjxray/pull/126
sitej = tilej.setdefault('sites', {})
def add_ei():
for variable, bound in bounds[PREFIX_SW_EI].items():
site_type, src_site_pin, dst_bel_type, dst_bel_pin = sw_ei_s2vals(
variable)
# ex: SLICEL:AX->AFF.D
k = (
'%s:%s->%s.%s' %
(site_type, src_site_pin, dst_bel_type, dst_bel_pin))
sitej.setdefault(site_type, {})[k] = bound
def add_eo():
for variable, bound in bounds[PREFIX_SW_EO].items():
site_type, src_bel_type, src_bel_pin, dst_site_pin = sw_eo_s2vals(
variable)
# ex: SLICEL:AFF.Q->AQ
k = (
'%s:%s.%s->%s' %
(site_type, src_bel_type, src_bel_pin, dst_site_pin))
sitej.setdefault(site_type, {})[k] = bound
def add_i():
for variable, bound in bounds[PREFIX_SW_I].items():
site_type, src_bel, src_bel_pin, dst_bel, dst_bel_pin = sw_i_s2vals(
variable)
# ex: SLICEL:LUT6.O2->AFF.D
k = (
'%s:%s.%s->%s.%s' %
(site_type, src_bel, src_bel_pin, dst_bel, dst_bel_pin))
sitej.setdefault(site_type, {})[k] = bound
add_ei()
add_eo()
add_i()
print('Sites: added %u sites' % len(sitej))
print('Added site wires')
print(' Site external in: %u' % len(bounds[PREFIX_SW_EI]))
print(' Site external out: %u' % len(bounds[PREFIX_SW_EO]))
print(' Site internal: %u' % len(bounds[PREFIX_SW_I]))
def sep_bounds(bounds):
pw = {}
sites = {PREFIX_SW_EI: {}, PREFIX_SW_EO: {}, PREFIX_SW_I: {}}
for k, v in bounds.items():
prefix = k.split(':')[0]
if prefix in (PREFIX_W, PREFIX_P):
pw[k] = v
elif prefix in (PREFIX_SW_EI, PREFIX_SW_EO, PREFIX_SW_I):
sites[prefix][k] = v
else:
assert 0, 'Unknown delay: %s %s' % (k, prefix)
return pw, sites
def run(fns_in, fnout, tile_json_fn, verbose=False):
# modified in place
tilej = json.load(open(tile_json_fn, 'r'))
for fnin in fns_in:
Ads, bs = loadc_Ads_bs([fnin])
bounds = Ads2bounds(Ads, bs)
bounds_pw, bounds_sites = sep_bounds(bounds)
print(len(bounds), len(bounds_pw), len(bounds_sites))
add_pip_wire(tilej, bounds_pw)
add_sites(tilej, bounds_sites)
timfuz.tilej_stats(tilej)
json.dump(
tilej,
open(fnout, 'w'),
sort_keys=True,
indent=4,
separators=(',', ': '))
def main():
import argparse
parser = argparse.ArgumentParser(
description=
'Substitute timgrid timing model names for real timing values')
parser.add_argument(
'--timgrid-s',
default='../../timgrid/build/timgrid-s.json',
help='tilegrid timing delay symbolic input (timgrid-s.json)')
parser.add_argument(
'--out',
default='build/timgrid-vc.json',
help='tilegrid timing delay values at corner (timgrid-vc.json)')
parser.add_argument(
'fn_ins', nargs='+', help='Input flattened timing csv (flat.csv)')
args = parser.parse_args()
run(args.fn_ins, args.out, args.timgrid_s, verbose=False)
if __name__ == '__main__':
main()