diff --git a/fuzzers/049-int-imux-gfan/Makefile b/fuzzers/049-int-imux-gfan/Makefile new file mode 100644 index 00000000..31a3087b --- /dev/null +++ b/fuzzers/049-int-imux-gfan/Makefile @@ -0,0 +1,4 @@ +N = 5 +MAKETODO_FLAGS=--re "^INT_[LR].IMUX[^\.]+\.GFAN[01]$$" +include ../int_loop.mk + diff --git a/fuzzers/049-int-imux-gfan/generate.py b/fuzzers/049-int-imux-gfan/generate.py new file mode 100644 index 00000000..379d57cd --- /dev/null +++ b/fuzzers/049-int-imux-gfan/generate.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +import re +import os + +from prjxray.segmaker import Segmaker +from prjxray.bitfilter import get_bitfilter + +segmk = Segmaker("design.bits") + +tiledata = dict() +pipdata = dict() +ignpip = set() + +print("Loading tags from design.txt.") +with open("design.txt", "r") as f: + for line in f: + tile, pip, src, dst, pnum, pdir = line.split() + + if not tile.startswith('INT_'): + continue + + _, pip = pip.split(".") + _, src = src.split("/") + _, dst = dst.split("/") + pnum = int(pnum) + pdir = int(pdir) + + if tile not in tiledata: + tiledata[tile] = {"pips": set(), "srcs": set(), "dsts": set()} + + if pip in pipdata: + assert pipdata[pip] == (src, dst) + else: + pipdata[pip] = (src, dst) + + tiledata[tile]["pips"].add(pip) + tiledata[tile]["srcs"].add(src) + tiledata[tile]["dsts"].add(dst) + + if pdir == 0: + tiledata[tile]["srcs"].add(dst) + tiledata[tile]["dsts"].add(src) + + imux = re.match('^IMUX(_L)?[0-9]+$', dst) is not None + + if not imux: + ignpip.add(pip) + +for tile, pips_srcs_dsts in tiledata.items(): + pips = pips_srcs_dsts["pips"] + srcs = pips_srcs_dsts["srcs"] + dsts = pips_srcs_dsts["dsts"] + + for pip, src_dst in pipdata.items(): + src, dst = src_dst + if pip in ignpip: + pass + else: + if re.match('^GFAN[01]', src): + print(tile, src, dst, pip in pips) + segmk.add_tile_tag(tile, "%s.%s" % (dst, src), pip in pips) + +segmk.compile(bitfilter=get_bitfilter(os.getenv('XRAY_DATABASE'), 'INT')) +segmk.write() diff --git a/fuzzers/049-int-imux-gfan/generate.tcl b/fuzzers/049-int-imux-gfan/generate.tcl new file mode 100644 index 00000000..2e56b7aa --- /dev/null +++ b/fuzzers/049-int-imux-gfan/generate.tcl @@ -0,0 +1,4 @@ +source "$::env(XRAY_DIR)/utils/utils.tcl" + +generate_top +write_pip_txtdata design.txt diff --git a/fuzzers/049-int-imux-gfan/top.py b/fuzzers/049-int-imux-gfan/top.py new file mode 100644 index 00000000..c1be7709 --- /dev/null +++ b/fuzzers/049-int-imux-gfan/top.py @@ -0,0 +1,91 @@ +import os +import random +import itertools +from prjxray import util +from prjxray.db import Database +random.seed(int(os.getenv("SEED"), 16)) + + +def gen_sites(lr): + db = Database(util.get_db_root()) + grid = db.grid() + + for tile_name in grid.tiles(): + loc = grid.loc_of_tilename(tile_name) + gridinfo = grid.gridinfo_at_loc(loc) + + if gridinfo.tile_type[-1] != lr: + continue + + + sites = [] + for site_name, site_type in gridinfo.sites.items(): + if site_type in ['SLICEL', 'SLICEM']: + sites.append(site_name) + + if not sites: + continue + + print('// ', gridinfo.tile_type) + + yield sorted(sites) + +def yield_bits(bits, nvals): + for i in range(nvals): + mask = (1 << i) + yield int(bool(bits & mask)) + +NUM_IMUX_INPUTS = 2*6*4 +NUM_TILES = 20 + +def emit_luts(choices, spec_idx, lr): + for idx, sites in enumerate(itertools.islice(gen_sites(lr), 0, NUM_TILES)): + + cidx = idx+spec_idx*NUM_TILES + if cidx < len(choices): + bits = choices[cidx] + else: + bits = random.randint(0, 2**NUM_IMUX_INPUTS-1) + + itr = yield_bits(bits, nvals=NUM_IMUX_INPUTS) + + for site in sites: + for lut in range(4): + print(''' + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + LUT6 {site}_lut{lut} ( + .I0({I0}), + .I1({I1}), + .I2({I2}), + .I3({I3}), + .I4({I4}), + .I5({I5}) + );'''.format( + site=site, + lut=lut, + I0=next(itr), + I1=next(itr), + I2=next(itr), + I3=next(itr), + I4=next(itr), + I5=next(itr), + )) + + +def run(): + + print(''' +module top(); +''') + + choices = util.gen_fuzz_choices(nvals=NUM_IMUX_INPUTS) + spec_idx = util.specn()-1 + + emit_luts(choices, spec_idx, 'L') + emit_luts(choices, spec_idx, 'R') + + print("endmodule") + + +if __name__ == '__main__': + run() diff --git a/fuzzers/050-pip-seed/Makefile b/fuzzers/050-pip-seed/Makefile index dbb7c091..759b49d0 100644 --- a/fuzzers/050-pip-seed/Makefile +++ b/fuzzers/050-pip-seed/Makefile @@ -84,7 +84,7 @@ run: # Because 056 cannot solve IMUX and LOGIC_OUTS, force zero entries for the # LOGIC_OUTS or IMUX entries. XRAY_DIR=${XRAY_DIR} MAKE="$(MAKE)" QUICK=$(QUICK) $(XRAY_DIR)/fuzzers/int_loop.sh \ - --check-args "--max-iters 12 --min-progress 50 --zero-entries --zero-entries-filter (IMUX.*GFAN)" + --check-args "--max-iters 12 --min-progress 50" touch run.ok clean: diff --git a/fuzzers/050-pip-seed/generate.py b/fuzzers/050-pip-seed/generate.py index 8b317d40..482b3d11 100644 --- a/fuzzers/050-pip-seed/generate.py +++ b/fuzzers/050-pip-seed/generate.py @@ -42,7 +42,6 @@ with open("design.txt", "r") as f: tiledata[tile]["srcs"].add(dst) tiledata[tile]["dsts"].add(src) - fan_alt_dst = re.match('^FAN_ALT[0-9]$', dst) is not None gfan_src = re.match('^GFAN', src) is not None # Okay: BYP_ALT0.VCC_WIRE @@ -51,7 +50,7 @@ with open("design.txt", "r") as f: src == "VCC_WIRE" or \ re.match(r"^(L[HV]B?|G?CLK)(_L)?(_B)?[0-9]", src) or \ re.match(r"^(L[HV]B?|G?CLK)(_L)?(_B)?[0-9]", dst) or \ - (fan_alt_dst and gfan_src) or \ + gfan_src or \ re.match(r"^(CTRL|GFAN)(_L)?[0-9]", dst): ignpip.add(pip) diff --git a/fuzzers/054-pip-fan-alt/Makefile b/fuzzers/054-pip-fan-alt/Makefile index f4e6e8a0..0183bbfe 100644 --- a/fuzzers/054-pip-fan-alt/Makefile +++ b/fuzzers/054-pip-fan-alt/Makefile @@ -1,4 +1,4 @@ -MAKETODO_FLAGS=--re "^INT_[LR].FAN_ALT.*GFAN" +MAKETODO_FLAGS=--re "^INT_[LR].(?!IMUX)[^\.]+.\.GFAN[0-9]$$" GENERATE_FLAGS=--todo ../todo.txt N = 48 SEGMATCH_FLAGS=-m 30 -M 45 -c 2 diff --git a/fuzzers/054-pip-fan-alt/README.md b/fuzzers/054-pip-fan-alt/README.md index 670d7cc7..11b14713 100644 --- a/fuzzers/054-pip-fan-alt/README.md +++ b/fuzzers/054-pip-fan-alt/README.md @@ -1,5 +1,5 @@ -Fuzzer for the ALT_FAN.*GFAN PIPs +Fuzzer for the ALT_FAN.*GFAN PIPs and BYP_ALT.*GFAN PIPs --------------------------------- This fuzzer solves the ALT_FAN.GFAN PIPs which had collisions with the GFAN PIPs. diff --git a/fuzzers/056-pip-rem/Makefile b/fuzzers/056-pip-rem/Makefile index a7f1dff3..2c063f8f 100644 --- a/fuzzers/056-pip-rem/Makefile +++ b/fuzzers/056-pip-rem/Makefile @@ -1,6 +1,6 @@ MAKETODO_FLAGS=--re ".*" --not-endswith ".VCC_WIRE" GENERATE_FLAGS=--todo ../todo.txt -N = 48 +N = 24 SEGMATCH_FLAGS=-m 20 -M 45 include ../int_loop.mk diff --git a/fuzzers/Makefile b/fuzzers/Makefile index 5405869e..e9e0992e 100644 --- a/fuzzers/Makefile +++ b/fuzzers/Makefile @@ -75,13 +75,14 @@ $(eval $(call fuzzer,041-clk-hrow-pips,005-tilegrid)) # 042 fuzzer is unstable, issue #657 #$(eval $(call fuzzer,042-clk-bufg-config,005-tilegrid)) $(eval $(call fuzzer,043-clk-rebuf-pips,005-tilegrid)) +$(eval $(call fuzzer,049-int-imux-gfan,005-tilegrid)) $(eval $(call fuzzer,050-pip-seed,005-tilegrid)) -$(eval $(call fuzzer,051-pip-imuxlout-bypalts,050-pip-seed)) -$(eval $(call fuzzer,052-pip-clkin,050-pip-seed)) -$(eval $(call fuzzer,053-pip-ctrlin,050-pip-seed)) -$(eval $(call fuzzer,054-pip-fan-alt,050-pip-seed)) -$(eval $(call fuzzer,055-pip-gnd,050-pip-seed)) -$(eval $(call fuzzer,056-pip-rem,051-pip-imuxlout-bypalts 052-pip-clkin 053-pip-ctrlin 054-pip-fan-alt 055-pip-gnd)) +$(eval $(call fuzzer,051-pip-imuxlout-bypalts,005-tilegrid)) +$(eval $(call fuzzer,052-pip-clkin,005-tilegrid)) +$(eval $(call fuzzer,053-pip-ctrlin,005-tilegrid)) +$(eval $(call fuzzer,054-pip-fan-alt,005-tilegrid)) +$(eval $(call fuzzer,055-pip-gnd,005-tilegrid)) +$(eval $(call fuzzer,056-pip-rem,049-int-imux-gfan 050-pip-seed 051-pip-imuxlout-bypalts 052-pip-clkin 053-pip-ctrlin 054-pip-fan-alt 055-pip-gnd)) $(eval $(call fuzzer,057-pip-bi,056-pip-rem)) ifneq ($(QUICK),Y) $(eval $(call fuzzer,058-pip-hclk,056-pip-rem)) diff --git a/prjxray/util.py b/prjxray/util.py index 0e27027a..8401e5f5 100644 --- a/prjxray/util.py +++ b/prjxray/util.py @@ -215,26 +215,7 @@ def specn(): return int(re.match(".*specimen_([0-9]*)", specdir).group(1), 10) -def gen_fuzz_states(nvals): - ''' - Generates an optimal encoding to solve single bits as quickly as possible - - tilegrid's initial solve for 4 bits works like this: - Initial reference value of all 0s: - 0000 - Then one-hot for each: - 0001 - 0010 - 0100 - 1000 - Which requires 5 samples total to diff these - - However, using correlation instead its possible to resolve n bits using ceil(log(n, 2)) + 1 samples - With 4 positions it takes only 3 samples: - 0000 - 0101 - 1010 - ''' +def gen_fuzz_choices(nvals): next_p2_states = 2**math.ceil(math.log(nvals, 2)) n = next_p2_states @@ -261,10 +242,35 @@ def gen_fuzz_states(nvals): choices.extend(invert_choices) + return choices + +def gen_fuzz_states(nvals): + ''' + Generates an optimal encoding to solve single bits as quickly as possible + + tilegrid's initial solve for 4 bits works like this: + Initial reference value of all 0s: + 0000 + Then one-hot for each: + 0001 + 0010 + 0100 + 1000 + Which requires 5 samples total to diff these + + However, using correlation instead its possible to resolve n bits using ceil(log(n, 2)) + 1 samples + With 4 positions it takes only 3 samples: + 0000 + 0101 + 1010 + ''' + + choices = gen_fuzz_choices(nvals) spec_idx = specn() - 1 if spec_idx < len(choices): bits = choices[spec_idx] else: + next_p2_states = 2**math.ceil(math.log(nvals, 2)) bits = random.randint(0, 2**next_p2_states) for i in range(nvals):