From d9251986509b5e6992c4a297c2344a63760102e2 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Mon, 18 Feb 2019 09:53:28 -0800 Subject: [PATCH 1/2] Simplify 042 routing fuzzing to be more robust. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fuzzers/042-clk-bufg-config/Makefile | 2 +- fuzzers/042-clk-bufg-config/generate.py | 35 +++----- fuzzers/042-clk-bufg-config/top.py | 113 +++++++++++++++--------- 3 files changed, 87 insertions(+), 63 deletions(-) diff --git a/fuzzers/042-clk-bufg-config/Makefile b/fuzzers/042-clk-bufg-config/Makefile index 86c076a5..489883b7 100644 --- a/fuzzers/042-clk-bufg-config/Makefile +++ b/fuzzers/042-clk-bufg-config/Makefile @@ -1,4 +1,4 @@ -N ?= 50 +N ?= 40 include ../fuzzer.mk diff --git a/fuzzers/042-clk-bufg-config/generate.py b/fuzzers/042-clk-bufg-config/generate.py index 4895b43e..7bc9b76e 100644 --- a/fuzzers/042-clk-bufg-config/generate.py +++ b/fuzzers/042-clk-bufg-config/generate.py @@ -29,29 +29,22 @@ def main(): segmk.add_site_tag( row['site'], '{}.{}'.format(base_name, param), row[param]) - if row['connect0'] and row['connect1']: - for param in ('PRESELECT_I0', ): - segmk.add_site_tag( - row['site'], '{}.Z{}'.format(base_name, param), - 1 ^ row[param]) + for param in ('PRESELECT_I0', ): + segmk.add_site_tag( + row['site'], '{}.Z{}'.format(base_name, param), + 1 ^ row[param]) - for param in ('PRESELECT_I1', ): - segmk.add_site_tag( - row['site'], '{}.{}'.format(base_name, param), row[param]) + for param in ('PRESELECT_I1', ): + segmk.add_site_tag( + row['site'], '{}.{}'.format(base_name, param), row[param]) - if row['connect0']: - for param, tag in (('IS_CE0_INVERTED', 'ZINV_CE0'), - ('IS_S0_INVERTED', 'ZINV_S0')): - segmk.add_site_tag( - row['site'], '{}.{}'.format(base_name, tag), - 1 ^ row[param]) - - if row['connect1']: - for param, tag in (('IS_CE1_INVERTED', 'ZINV_CE1'), - ('IS_S1_INVERTED', 'ZINV_S1')): - segmk.add_site_tag( - row['site'], '{}.{}'.format(base_name, tag), - 1 ^ row[param]) + for param, tag in (('IS_CE0_INVERTED', 'ZINV_CE0'), + ('IS_S0_INVERTED', 'ZINV_S0'), + ('IS_CE1_INVERTED', 'ZINV_CE1'), + ('IS_S1_INVERTED', 'ZINV_S1')): + segmk.add_site_tag( + row['site'], '{}.{}'.format(base_name, tag), + 1 ^ row[param]) segmk.compile() segmk.write() diff --git a/fuzzers/042-clk-bufg-config/top.py b/fuzzers/042-clk-bufg-config/top.py index 8d770d6b..56b310fa 100644 --- a/fuzzers/042-clk-bufg-config/top.py +++ b/fuzzers/042-clk-bufg-config/top.py @@ -28,6 +28,50 @@ def gen_sites(): if sites: yield tile_name, min(xs), min(ys), sorted(sites) +class StateGen(object): + def __init__(self, sites, states_per_site): + self.sites = sites + self.states_per_site = states_per_site + self.curr_site_idx = 0 + self.curr_state = None + self.states = None + self.curr_site = None + + def __iter__(self): + assert self.curr_state is None + assert self.states is None + assert self.curr_state is None + + self.curr_site_idx = 0 + self.curr_state = None + self.states = util.gen_fuzz_states(len(self.sites)*self.states_per_site) + self.curr_site = iter(self.sites) + return self + + def __next__(self): + next_site = next(self.curr_site) + self.curr_site_idx += 1 + + if self.curr_state is not None: + while self.curr_state < self.states_per_site: + self.next_state() + + assert self.curr_state == self.states_per_site, self.curr_state + + self.curr_state = 0 + + return next_site + + def next_state(self): + self.curr_state += 1 + + try: + state = next(self.states) + except StopIteration: + assert False, "Insufficent states, at state {} for site {}".format(self.curr_state, self.curr_site_idx) + + return state + def main(): print(''' @@ -35,57 +79,35 @@ module top(); ''') params_list = [] - for tile_name, x_min, y_min, sites in gen_sites(): - + state_gen = StateGen(list(gen_sites()), states_per_site=12*16) + for tile_name, x_min, y_min, sites in state_gen: for site, x, y in sites: params = {} params['tile'] = tile_name params['site'] = site params['x'] = x - x_min params['y'] = y - y_min - params['IN_USE'] = random.random() > .1 + params['IN_USE'] = state_gen.next_state() if params['IN_USE']: - params['INIT_OUT'] = random.randint(0, 1) - params['IS_CE0_INVERTED'] = random.randint(0, 1) - params['IS_CE1_INVERTED'] = random.randint(0, 1) - params['IS_S0_INVERTED'] = random.randint(0, 1) - params['IS_S1_INVERTED'] = random.randint(0, 1) - params['IS_IGNORE0_INVERTED'] = random.randint(0, 1) - params['IS_IGNORE1_INVERTED'] = random.randint(0, 1) - params['PRESELECT_I0'] = 0 - params['PRESELECT_I1'] = 0 + params['INIT_OUT'] = state_gen.next_state() + params['IS_CE0_INVERTED'] = state_gen.next_state() + params['IS_CE1_INVERTED'] = state_gen.next_state() + params['IS_S0_INVERTED'] = state_gen.next_state() + params['IS_S1_INVERTED'] = state_gen.next_state() + params['IS_IGNORE0_INVERTED'] = state_gen.next_state() + params['IS_IGNORE1_INVERTED'] = state_gen.next_state() - params['connect0'] = random.randint(0, 1) - - if params['connect0']: - params['connect1'] = random.randint(0, 1) + params['PRESELECT_I0'] = state_gen.next_state() + if not params['PRESELECT_I0']: + params['PRESELECT_I1'] = state_gen.next_state() else: - params['connect1'] = 1 + params['PRESELECT_I1'] = 0 - if params['connect0'] and params['connect1']: - params['PRESELECT_I0'] = random.randint(0, 1) - if not params['PRESELECT_I0']: - params['PRESELECT_I1'] = random.randint(0, 1) - else: - params['PRESELECT_I1'] = 0 - - params['connections'] = """ - .CE0(ce0_{site}), - .S0(s0_{site}), - .CE1(ce1_{site}), - .S1(s1_{site}) - """.format(site=site) - elif params['connect0']: - params['connections'] = """ - .CE0(ce0_{site}), - .S0(s0_{site}) - """.format(site=site) - elif params['connect1']: - params['connections'] = """ - .CE1(ce1_{site}), - .S1(s1_{site}) - """.format(site=site) + params['force_0_high'] = state_gen.next_state() + params['force_1_high'] = state_gen.next_state() + if params['force_0_high']: + params['force_1_high'] = 0 print( ''' @@ -110,6 +132,7 @@ module top(); LUT6 l3_{site} ( .O(s1_{site}) ); + (* KEEP, DONT_TOUCH, LOC = "{site}" *) BUFGCTRL #( .INIT_OUT({INIT_OUT}), @@ -122,12 +145,20 @@ module top(); .IS_IGNORE0_INVERTED({IS_IGNORE0_INVERTED}), .IS_IGNORE1_INVERTED({IS_IGNORE1_INVERTED}) ) buf_{site} ( - {connections} + .CE0(ce0_{site} | {force_0_high}), + .S0(s0_{site} | {force_0_high}), + .CE1(ce1_{site} | {force_1_high}), + .S1(s1_{site} | {force_1_high}) ); '''.format(**params)) params_list.append(params) + print(""" + (* KEEP, DONT_TOUCH *) + LUT6 dummy ( + );""") + print("endmodule") with open('params.json', 'w') as f: From 4be219f7e5fd1b594631936559e5a22af45d208b Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Mon, 18 Feb 2019 10:02:48 -0800 Subject: [PATCH 2/2] Move StateGen to own file, and ran make format. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fuzzers/042-clk-bufg-config/generate.py | 14 +++--- fuzzers/042-clk-bufg-config/top.py | 49 ++---------------- prjxray/state_gen.py | 66 +++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 54 deletions(-) create mode 100644 prjxray/state_gen.py diff --git a/fuzzers/042-clk-bufg-config/generate.py b/fuzzers/042-clk-bufg-config/generate.py index 7bc9b76e..749831c6 100644 --- a/fuzzers/042-clk-bufg-config/generate.py +++ b/fuzzers/042-clk-bufg-config/generate.py @@ -31,20 +31,18 @@ def main(): for param in ('PRESELECT_I0', ): segmk.add_site_tag( - row['site'], '{}.Z{}'.format(base_name, param), - 1 ^ row[param]) + row['site'], '{}.Z{}'.format(base_name, param), 1 ^ row[param]) for param in ('PRESELECT_I1', ): segmk.add_site_tag( row['site'], '{}.{}'.format(base_name, param), row[param]) - for param, tag in (('IS_CE0_INVERTED', 'ZINV_CE0'), - ('IS_S0_INVERTED', 'ZINV_S0'), - ('IS_CE1_INVERTED', 'ZINV_CE1'), - ('IS_S1_INVERTED', 'ZINV_S1')): + for param, tag in (('IS_CE0_INVERTED', 'ZINV_CE0'), ('IS_S0_INVERTED', + 'ZINV_S0'), + ('IS_CE1_INVERTED', 'ZINV_CE1'), ('IS_S1_INVERTED', + 'ZINV_S1')): segmk.add_site_tag( - row['site'], '{}.{}'.format(base_name, tag), - 1 ^ row[param]) + row['site'], '{}.{}'.format(base_name, tag), 1 ^ row[param]) segmk.compile() segmk.write() diff --git a/fuzzers/042-clk-bufg-config/top.py b/fuzzers/042-clk-bufg-config/top.py index 56b310fa..ed050c6b 100644 --- a/fuzzers/042-clk-bufg-config/top.py +++ b/fuzzers/042-clk-bufg-config/top.py @@ -2,8 +2,9 @@ import json import os import random random.seed(int(os.getenv("SEED"), 16)) -from prjxray import util from prjxray.db import Database +from prjxray import util +from prjxray.state_gen import StateGen def gen_sites(): @@ -28,50 +29,6 @@ def gen_sites(): if sites: yield tile_name, min(xs), min(ys), sorted(sites) -class StateGen(object): - def __init__(self, sites, states_per_site): - self.sites = sites - self.states_per_site = states_per_site - self.curr_site_idx = 0 - self.curr_state = None - self.states = None - self.curr_site = None - - def __iter__(self): - assert self.curr_state is None - assert self.states is None - assert self.curr_state is None - - self.curr_site_idx = 0 - self.curr_state = None - self.states = util.gen_fuzz_states(len(self.sites)*self.states_per_site) - self.curr_site = iter(self.sites) - return self - - def __next__(self): - next_site = next(self.curr_site) - self.curr_site_idx += 1 - - if self.curr_state is not None: - while self.curr_state < self.states_per_site: - self.next_state() - - assert self.curr_state == self.states_per_site, self.curr_state - - self.curr_state = 0 - - return next_site - - def next_state(self): - self.curr_state += 1 - - try: - state = next(self.states) - except StopIteration: - assert False, "Insufficent states, at state {} for site {}".format(self.curr_state, self.curr_site_idx) - - return state - def main(): print(''' @@ -79,7 +36,7 @@ module top(); ''') params_list = [] - state_gen = StateGen(list(gen_sites()), states_per_site=12*16) + state_gen = StateGen(list(gen_sites()), states_per_site=12 * 16) for tile_name, x_min, y_min, sites in state_gen: for site, x, y in sites: params = {} diff --git a/prjxray/state_gen.py b/prjxray/state_gen.py new file mode 100644 index 00000000..3a8d43fc --- /dev/null +++ b/prjxray/state_gen.py @@ -0,0 +1,66 @@ +from prjxray import util + + +class StateGen(object): + """ Manages fuzzer state generation across multiple sites. + + sites - List of sites. + states_per_site - Maximum number of states used per site. + + If states_per_site is too small, next_state may throw AssertionError. + + StateGen should be used as a iterator for the sites given. Call next_state + within each site output loop. Once 'next' is called on StateGen, StateGen + will advance state output to the correct position, even if next_state was + called less than states_per_site. + + """ + + def __init__(self, sites, states_per_site): + self.sites = sites + self.states_per_site = states_per_site + self.curr_site_idx = 0 + self.curr_state = None + self.states = None + self.curr_site = None + + def __iter__(self): + assert self.curr_state is None + assert self.states is None + assert self.curr_state is None + + self.curr_site_idx = 0 + self.curr_state = None + self.states = util.gen_fuzz_states( + len(self.sites) * self.states_per_site) + self.curr_site = iter(self.sites) + return self + + def __next__(self): + next_site = next(self.curr_site) + self.curr_site_idx += 1 + + if self.curr_state is not None: + while self.curr_state < self.states_per_site: + self.next_state() + + assert self.curr_state == self.states_per_site, self.curr_state + + self.curr_state = 0 + + return next_site + + def next_state(self): + """ Returns next state within site. + + Should only be called states_per_site for each site. + """ + self.curr_state += 1 + + try: + state = next(self.states) + except StopIteration: + assert False, "Insufficent states, at state {} for site {}".format( + self.curr_state, self.curr_site_idx) + + return state