mirror of https://github.com/openXC7/prjxray.git
timfuz: make rref deterministic
Signed-off-by: John McMaster <johndmcmaster@gmail.com>
This commit is contained in:
parent
7c0828e6c2
commit
ee3ef206ad
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from timfuz import Benchmark, Ar_di2np, loadc_Ads_b, index_names, A_ds2np, simplify_rows
|
||||
from timfuz import Benchmark, Ar_di2np, loadc_Ads_b, index_names, A_ds2np, simplify_rows, OrderedSet
|
||||
import numpy as np
|
||||
import glob
|
||||
import math
|
||||
|
|
@ -27,14 +27,15 @@ class State(object):
|
|||
self.names = index_names(self.Ads)
|
||||
|
||||
# known zero delay elements
|
||||
self.drop_names = set(drop_names)
|
||||
self.drop_names = OrderedSet(drop_names)
|
||||
# active names in rows
|
||||
# includes sub variables, excludes variables that have been substituted out
|
||||
self.base_names = set(self.names)
|
||||
self.base_names = OrderedSet(self.names)
|
||||
#self.names = OrderedSet(self.base_names)
|
||||
self.names = set(self.base_names)
|
||||
# List of variable substitutions
|
||||
# k => dict of v:n entries that it came from
|
||||
self.subs = {}
|
||||
self.subs = OrderedDict()
|
||||
self.verbose = True
|
||||
|
||||
def print_stats(self):
|
||||
|
|
@ -63,11 +64,16 @@ class State(object):
|
|||
|
||||
def write_state(state, fout):
|
||||
j = {
|
||||
'names': dict([(x, None) for x in state.names]),
|
||||
'drop_names': list(state.drop_names),
|
||||
'base_names': list(state.base_names),
|
||||
'subs': dict([(name, values) for name, values in state.subs.items()]),
|
||||
'pivots': state.pivots,
|
||||
'names':
|
||||
OrderedDict([(x, None) for x in state.names]),
|
||||
'drop_names':
|
||||
list(state.drop_names),
|
||||
'base_names':
|
||||
list(state.base_names),
|
||||
'subs':
|
||||
OrderedDict([(name, values) for name, values in state.subs.items()]),
|
||||
'pivots':
|
||||
state.pivots,
|
||||
}
|
||||
json.dump(j, fout, sort_keys=True, indent=4, separators=(',', ': '))
|
||||
|
||||
|
|
@ -89,7 +95,7 @@ def Anp2matrix(Anp):
|
|||
|
||||
|
||||
def row_np2ds(rownp, names):
|
||||
ret = {}
|
||||
ret = OrderedDict()
|
||||
assert len(rownp) == len(names), (len(rownp), len(names))
|
||||
for namei, name in enumerate(names):
|
||||
v = rownp[namei]
|
||||
|
|
@ -102,7 +108,7 @@ def row_sym2dsf(rowsym, names):
|
|||
'''Convert a sympy row into a dictionary of keys to (numerator, denominator) tuples'''
|
||||
from sympy import fraction
|
||||
|
||||
ret = {}
|
||||
ret = OrderedDict()
|
||||
assert len(rowsym) == len(names), (len(rowsym), len(names))
|
||||
for namei, name in enumerate(names):
|
||||
v = rowsym[namei]
|
||||
|
|
@ -145,7 +151,7 @@ def state_rref(state, verbose=False):
|
|||
print('rref')
|
||||
sympy.pprint(rref)
|
||||
|
||||
state.pivots = {}
|
||||
state.pivots = OrderedDict()
|
||||
|
||||
def row_solved(rowsym, row_pivot):
|
||||
for ci, c in enumerate(rowsym):
|
||||
|
|
@ -177,7 +183,7 @@ def state_rref(state, verbose=False):
|
|||
state.names.add(group_name)
|
||||
# Remove substituted variables
|
||||
# Note: variables may appear multiple times
|
||||
state.names.difference_update(set(rowdsf.keys()))
|
||||
state.names.difference_update(OrderedSet(rowdsf.keys()))
|
||||
pivot_name = names[row_pivot]
|
||||
state.pivots[group_name] = pivot_name
|
||||
if verbose:
|
||||
|
|
|
|||
|
|
@ -192,7 +192,8 @@ def main():
|
|||
|
||||
parser.add_argument('--verbose', action='store_true', help='')
|
||||
parser.add_argument('--massage', action='store_true', help='')
|
||||
parser.add_argument('--bounds-csv', help='Previous solve result starting point')
|
||||
parser.add_argument(
|
||||
'--bounds-csv', help='Previous solve result starting point')
|
||||
parser.add_argument(
|
||||
'--sub-json', help='Group substitutions to make fully ranked')
|
||||
parser.add_argument('--corner', required=True, default="slow_max", help='')
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import json
|
|||
|
||||
|
||||
def run_types(tilej, verbose=False):
|
||||
|
||||
def process(etype):
|
||||
# dict[model] = set((tile, wire/pip))
|
||||
zeros = {}
|
||||
|
|
@ -19,7 +18,9 @@ def run_types(tilej, verbose=False):
|
|||
zeros.setdefault(emodel, set()).add((tilek, ename))
|
||||
# Print out delay model instances
|
||||
print('%s ZERO types: %u, %s' % (etype, len(zeros), zeros.keys()))
|
||||
print('%s ZERO instances: %u' % (etype, sum([len(x) for x in zeros.values()])))
|
||||
print(
|
||||
'%s ZERO instances: %u' %
|
||||
(etype, sum([len(x) for x in zeros.values()])))
|
||||
for model in sorted(zeros.keys()):
|
||||
modelv = zeros[model]
|
||||
print('Model: %s' % model)
|
||||
|
|
@ -30,8 +31,8 @@ def run_types(tilej, verbose=False):
|
|||
print('')
|
||||
process('pips')
|
||||
|
||||
def run_prefix(tilej, verbose=False):
|
||||
|
||||
def run_prefix(tilej, verbose=False):
|
||||
def process(etype):
|
||||
prefixes = set()
|
||||
print('Processing %s' % etype)
|
||||
|
|
@ -48,6 +49,7 @@ def run_prefix(tilej, verbose=False):
|
|||
print('')
|
||||
process('pips')
|
||||
|
||||
|
||||
def run(fnin, verbose=False):
|
||||
tilej = json.load((open(fnin, 'r')))
|
||||
run_types(tilej)
|
||||
|
|
@ -55,11 +57,16 @@ def run(fnin, verbose=False):
|
|||
print('')
|
||||
run_prefix(tilej)
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='Solve timing solution')
|
||||
parser.add_argument('fnin', default="../timgrid/build/timgrid-s.json", nargs='?', help='input timgrid JSON')
|
||||
parser.add_argument(
|
||||
'fnin',
|
||||
default="../timgrid/build/timgrid-s.json",
|
||||
nargs='?',
|
||||
help='input timgrid JSON')
|
||||
args = parser.parse_args()
|
||||
|
||||
run(args.fnin, verbose=False)
|
||||
|
|
|
|||
|
|
@ -13,10 +13,76 @@ import sys
|
|||
import random
|
||||
import glob
|
||||
from fractions import Fraction
|
||||
import collections
|
||||
|
||||
from benchmark import Benchmark
|
||||
|
||||
NAME_ZERO = set(
|
||||
|
||||
# Equations are filtered out until nothing is left
|
||||
class SimplifiedToZero(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# http://code.activestate.com/recipes/576694/
|
||||
class OrderedSet(collections.MutableSet):
|
||||
def __init__(self, iterable=None):
|
||||
self.end = end = []
|
||||
end += [None, end, end] # sentinel node for doubly linked list
|
||||
self.map = {} # key --> [key, prev, next]
|
||||
if iterable is not None:
|
||||
self |= iterable
|
||||
|
||||
def __len__(self):
|
||||
return len(self.map)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.map
|
||||
|
||||
def add(self, key):
|
||||
if key not in self.map:
|
||||
end = self.end
|
||||
curr = end[1]
|
||||
curr[2] = end[1] = self.map[key] = [key, curr, end]
|
||||
|
||||
def discard(self, key):
|
||||
if key in self.map:
|
||||
key, prev, next = self.map.pop(key)
|
||||
prev[2] = next
|
||||
next[1] = prev
|
||||
|
||||
def __iter__(self):
|
||||
end = self.end
|
||||
curr = end[2]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[2]
|
||||
|
||||
def __reversed__(self):
|
||||
end = self.end
|
||||
curr = end[1]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[1]
|
||||
|
||||
def pop(self, last=True):
|
||||
if not self:
|
||||
raise KeyError('set is empty')
|
||||
key = self.end[1][0] if last else self.end[2][0]
|
||||
self.discard(key)
|
||||
return key
|
||||
|
||||
def __repr__(self):
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__, )
|
||||
return '%s(%r)' % (self.__class__.__name__, list(self))
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, OrderedSet):
|
||||
return len(self) == len(other) and list(self) == list(other)
|
||||
return set(self) == set(other)
|
||||
|
||||
|
||||
NAME_ZERO = OrderedSet(
|
||||
[
|
||||
"BSW_CLK_ZERO",
|
||||
"BSW_ZERO",
|
||||
|
|
@ -40,11 +106,6 @@ corner_s2i = OrderedDict(
|
|||
])
|
||||
|
||||
|
||||
# Equations are filtered out until nothing is left
|
||||
class SimplifiedToZero(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def allow_zero_eqns():
|
||||
return os.getenv('ALLOW_ZERO_EQN', 'N') == 'Y'
|
||||
|
||||
|
|
@ -148,7 +209,7 @@ def check_feasible(A_ub, b_ub):
|
|||
def Ab_ub_dt2d(eqns):
|
||||
'''Convert dict using the rows as keys into a list of dicts + b_ub list (ie return A_ub, b_ub)'''
|
||||
#return [dict(rowt) for rowt in eqns]
|
||||
rows = [(dict(rowt), b) for rowt, b in eqns.items()]
|
||||
rows = [(OrderedDict(rowt), b) for rowt, b in eqns.items()]
|
||||
A_ubd, b_ub = zip(*rows)
|
||||
return list(A_ubd), list(b_ub)
|
||||
|
||||
|
|
@ -411,7 +472,7 @@ def derive_eq_by_col(A_ubd, b_ub, verbose=0):
|
|||
b_ub[row_refi] /= v
|
||||
knowns[k] = b_ub[row_refi]
|
||||
print(' done')
|
||||
#knowns_set = set(knowns.keys())
|
||||
#knowns_set = OrderedSet(knowns.keys())
|
||||
print('%d constrained' % len(knowns))
|
||||
'''
|
||||
Now see what we can do
|
||||
|
|
@ -648,7 +709,7 @@ def loadc_Ads_raw(fns):
|
|||
|
||||
|
||||
def index_names(Ads):
|
||||
names = set()
|
||||
names = OrderedSet()
|
||||
for row_ds in Ads:
|
||||
for k1 in row_ds.keys():
|
||||
names.add(k1)
|
||||
|
|
@ -740,7 +801,7 @@ def run_sub_json(Ads, sub_json, strict=False, verbose=False):
|
|||
ncols_new = 0
|
||||
|
||||
print('Subbing %u rows' % len(Ads))
|
||||
prints = set()
|
||||
prints = OrderedSet()
|
||||
|
||||
for rowi, row in enumerate(Ads):
|
||||
if 0 and verbose:
|
||||
|
|
|
|||
Loading…
Reference in New Issue