diff --git a/fuzzers/007-timing/solve_leastsq.py b/fuzzers/007-timing/solve_leastsq.py index fde102c2..bbb20ecc 100644 --- a/fuzzers/007-timing/solve_leastsq.py +++ b/fuzzers/007-timing/solve_leastsq.py @@ -20,16 +20,52 @@ import scipy.optimize as optimize from scipy.optimize import least_squares def mkestimate(Anp, b): + ''' + Ballpark upper bound estimate assuming variables contribute all of the delay in their respective row + Return the min of all of the occurances + + XXX: should this be corner adjusted? + ''' cols = len(Anp[0]) x0 = np.array([1e3 for _x in range(cols)]) for row_np, row_b in zip(Anp, b): for coli, val in enumerate(row_np): if val: + # Scale by number occurances ub = row_b / val if ub >= 0: x0[coli] = min(x0[coli], ub) return x0 +def save(outfn, res, names): + # ballpark minimum actual observed delay is around 7 (carry chain) + # anything less than one is probably a solver artifact + delta = 0.5 + + print('Writing resutls') + skips = 0 + with open(outfn, 'w') as fout: + # write as one variable per line + # this natively forms a bound if fed into linprog solver + fout.write('ico,fast_max fast_min slow_max slow_min,rows...\n') + for xval, name in zip(res.x, names): + row_ico = 1 + + # FIXME: only report for the given corner? + # also review ceil vs floor choice for min vs max + # lets be more conservative for now + if xval < delta: + #print('Skipping %s: %0.6f' % (name, xval)) + skips += 1 + continue + #xvali = round(xval) + xvali = math.ceil(xval) + corners = [xvali for _ in range(4)] + items = [str(row_ico), ' '.join([str(x) for x in corners])] + items.append('%u %s' % (1, name)) + fout.write(','.join(items) + '\n') + print('Wrote: skip %u => %u / %u valid delays' % (skips, len(names) - skips, len(names))) + def run_corner(Anp, b, names, verbose=False, opts={}, meta={}, outfn=None): # Given timing scores for above delays (-ps) assert type(Anp[0]) is np.ndarray, type(Anp[0]) @@ -93,59 +129,20 @@ def run_corner(Anp, b, names, verbose=False, opts={}, meta={}, outfn=None): #x0 = np.array([1000.0 for _x in range(cols)]) print('Creating x0 estimate') x0 = mkestimate(Anp, b) - #print('x0', x0) - if 0: - x, cov_x, infodict, mesg, ier = optimize.leastsq(func, x0, args=(), full_output=True) - print('x', x) - print('cov_x', cov_x) - print('infodictx', infodict) - print('mesg', mesg) - print('ier', ier) - print(' Solution found: %s' % (ier in (1, 2, 3, 4))) - else: - print('Solving') - res = least_squares(func, x0, bounds=(0, float('inf'))) - if 0: - print(res) - print('') - print(res.x) - print('Done') - if outfn: - # ballpark minimum actual observed delay is around 7 (carry chain) - # anything less than one is probably a solver artifact - delta = 0.5 + print('Solving') + res = least_squares(func, x0, bounds=(0, float('inf'))) + print('Done') - print('Writing resutls') - skips = 0 - with open(outfn, 'w') as fout: - # write as one variable per line - # this natively forms a bound if fed into linprog solver - fout.write('ico,fast_max fast_min slow_max slow_min,rows...\n') - for xval, name in zip(res.x, names): - row_ico = 1 - - # FIXME: only report for the given corner? - # also review ceil vs floor choice for min vs max - # lets be more conservative for now - if xval < delta: - #print('Skipping %s: %0.6f' % (name, xval)) - skips += 1 - continue - #xvali = round(xval) - xvali = math.ceil(xval) - corners = [xvali for _ in range(4)] - items = [str(row_ico), ' '.join([str(x) for x in corners])] - items.append('%u %s' % (1, name)) - fout.write(','.join(items) + '\n') - print('Wrote: skip %u => %u / %u valid delays' % (skips, len(names) - skips, len(names))) + if outfn: + save(outfn, res, names) def main(): import argparse parser = argparse.ArgumentParser( description= - 'Solve timing solution' + 'Solve timing solution using least squares objective function' ) parser.add_argument('--verbose', action='store_true', help='') diff --git a/fuzzers/007-timing/solve_linprog.py b/fuzzers/007-timing/solve_linprog.py index ec25474c..c33cd34a 100644 --- a/fuzzers/007-timing/solve_linprog.py +++ b/fuzzers/007-timing/solve_linprog.py @@ -140,7 +140,7 @@ def main(): parser = argparse.ArgumentParser( description= - 'Solve timing solution' + 'Solve timing solution using linear programming inequalities' ) parser.add_argument('--verbose', action='store_true', help='') diff --git a/fuzzers/007-timing/timfuz_solve.py b/fuzzers/007-timing/timfuz_solve.py index 5b66ad35..c9af58b1 100644 --- a/fuzzers/007-timing/timfuz_solve.py +++ b/fuzzers/007-timing/timfuz_solve.py @@ -106,9 +106,11 @@ def run(fns_in, corner, run_corner, sub_json=None, sub_csv=None, dedup=True, mas else: names = index_names(Ads) - # post substitution csv - # actually this might not be strictly necessary since subs would just not apply - # however, I wanted to do some filtering based on expected form + ''' + Substitution .csv + Special .csv containing one variable per line + Used primarily for multiple optimization passes, such as different algorithms or additional constraints + ''' if sub_csv: Ads2, b2 = loadc_Ads_b([sub_csv], corner, ico=True) bounds = Ads2bounds(Ads2, b2)