From 0edc3facde743f7425c46facf681b44b3967982a Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Fri, 1 Feb 2019 13:33:57 -0800 Subject: [PATCH] Add initial FIFO configuration. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fuzzers/028-fifo-config/Makefile | 22 +++ fuzzers/028-fifo-config/bits.dbf | 0 fuzzers/028-fifo-config/generate.py | 47 +++++++ fuzzers/028-fifo-config/generate.tcl | 18 +++ fuzzers/028-fifo-config/top.py | 191 +++++++++++++++++++++++++++ fuzzers/071-ppips/generate.tcl | 14 +- fuzzers/Makefile | 5 +- 7 files changed, 289 insertions(+), 8 deletions(-) create mode 100644 fuzzers/028-fifo-config/Makefile create mode 100644 fuzzers/028-fifo-config/bits.dbf create mode 100644 fuzzers/028-fifo-config/generate.py create mode 100644 fuzzers/028-fifo-config/generate.tcl create mode 100644 fuzzers/028-fifo-config/top.py diff --git a/fuzzers/028-fifo-config/Makefile b/fuzzers/028-fifo-config/Makefile new file mode 100644 index 00000000..b732d64a --- /dev/null +++ b/fuzzers/028-fifo-config/Makefile @@ -0,0 +1,22 @@ +# read/write width is relatively slow to resolve +# Even slower with multi bit masks... +N ?= 20 + +include ../fuzzer.mk + +database: build/segbits_bramx.db + +build/segbits_bramx.rdb: $(SPECIMENS_OK) + ${XRAY_SEGMATCH} -o build/segbits_bramx.rdb $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS)) + +build/segbits_bramx.db: build/segbits_bramx.rdb + ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@ + ${XRAY_MASKMERGE} build/mask_bramx.db $(addsuffix /segdata_bram_[lr].txt,$(SPECIMENS)) + +pushdb: + ${XRAY_MERGEDB} bram_l build/segbits_bramx.db + ${XRAY_MERGEDB} bram_r build/segbits_bramx.db + ${XRAY_MERGEDB} mask_bram_l build/mask_bramx.db + ${XRAY_MERGEDB} mask_bram_r build/mask_bramx.db + +.PHONY: database pushdb diff --git a/fuzzers/028-fifo-config/bits.dbf b/fuzzers/028-fifo-config/bits.dbf new file mode 100644 index 00000000..e69de29b diff --git a/fuzzers/028-fifo-config/generate.py b/fuzzers/028-fifo-config/generate.py new file mode 100644 index 00000000..5e904f9b --- /dev/null +++ b/fuzzers/028-fifo-config/generate.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +import json + +from prjxray.segmaker import Segmaker +from prjxray import verilog + + +def add_enum_bits(segmk, params, key, options): + for opt in options: + segmk.add_site_tag(params['site'], '{}_{}'.format(key, opt), params[key] == opt) + +def output_integer_tags(segmk, params, key, invert=False): + site = params['site'] + bits = verilog.parse_bitstr(params[key]) + for bit, tag_val in enumerate(bits): + if not invert: + segmk.add_site_tag(site, "{}[{}]".format(key, len(bits)-bit-1), tag_val) + else: + segmk.add_site_tag(site, "Z{}[{}]".format(key, len(bits)-bit-1), 0 if tag_val else 1) + +def main(): + segmk = Segmaker("design.bits") + + print("Loading tags") + with open('params.json') as f: + params = json.load(f) + + for tile_param in params: + #add_enum_bits(segmk, tile_param, 'DATA_WIDTH', [4, 9, 18, 36]) + #add_enum_bits(segmk, tile_param, 'FIFO_MODE', ['FIFO18', 'FIFO18_36']) + if tile_param['EN_SYN'] and tile_param['DATA_WIDTH'] == 4: + output_integer_tags(segmk, tile_param, 'ALMOST_EMPTY_OFFSET', invert=True) + output_integer_tags(segmk, tile_param, 'ALMOST_FULL_OFFSET', invert=True) + #output_integer_tags(segmk, tile_param, 'INIT', 36, invert=True) + #output_integer_tags(segmk, tile_param, 'SRVAL', 36, invert=True) + + for param in ('EN_SYN', 'FIRST_WORD_FALL_THROUGH'): + segmk.add_site_tag( + tile_param['site'], param, tile_param[param]) + + segmk.compile() + segmk.write() + + +if __name__ == '__main__': + main() diff --git a/fuzzers/028-fifo-config/generate.tcl b/fuzzers/028-fifo-config/generate.tcl new file mode 100644 index 00000000..0a07fd14 --- /dev/null +++ b/fuzzers/028-fifo-config/generate.tcl @@ -0,0 +1,18 @@ +proc run {} { + create_project -force -part $::env(XRAY_PART) design design + read_verilog top.v + synth_design -top top + + set_property CFGBVS VCCO [current_design] + set_property CONFIG_VOLTAGE 3.3 [current_design] + set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] + set_property IS_ENABLED 0 [get_drc_checks {REQP-38}] + + place_design + route_design + + write_checkpoint -force design.dcp + write_bitstream -force design.bit +} + +run diff --git a/fuzzers/028-fifo-config/top.py b/fuzzers/028-fifo-config/top.py new file mode 100644 index 00000000..83d179b9 --- /dev/null +++ b/fuzzers/028-fifo-config/top.py @@ -0,0 +1,191 @@ +import json +import math +import os +import functools +import random +random.seed(int(os.getenv("SEED"), 16)) +from prjxray import util +from prjxray import verilog +from prjxray.verilog import vrandbits +from prjxray.db import Database + +def gen_sites(): + db = Database(util.get_db_root()) + grid = db.grid() + for tile_name in sorted(grid.tiles()): + loc = grid.loc_of_tilename(tile_name) + gridinfo = grid.gridinfo_at_loc(loc) + + if gridinfo.tile_type not in ['BRAM_L', 'BRAM_R']: + continue + + sites = {} + for site_name, site_type in gridinfo.sites.items(): + sites[site_type] = site_name + + yield tile_name, sites + +@functools.lru_cache(maxsize=None) +def prepare_rand_int_choices(minval, maxval): + """ Creates list ints between minval and maxval to allow fuzzer to uniquely identify all bits.""" + assert minval >= 0 + assert maxval >= minval + + min_p2 = math.floor(math.log(max(minval, 1), 2)) + max_p2 = math.ceil(math.log(maxval+1, 2)) + + if 2**max_p2 > maxval: + max_search_p2 = max_p2 - 1 + else: + max_search_p2 = max_p2 + + choices = set([minval, maxval, 2**(min_p2+1)-1, 2**(max_search_p2)-1]) + + lb = min_p2 + ub = max_search_p2 + + while lb < ub: + ub = int(round(ub / 2.)) + + val = 2**ub - 1 + + lowval = val + if lowval < minval: + lowval |= (1 << max_search_p2) + assert lowval >= minval, (val, ub) + choices.add(lowval) + + highval = val << (max_search_p2 - ub) + if highval > minval: + assert highval <= maxval, (val, ub) + choices.add(highval) + + for bit in range(max_search_p2): + if 2**bit > minval: + choices.add(2**bit) + else: + choices.add(2**bit | 2**max_search_p2) + choices.add(2**bit | 2**(max_search_p2-1)) + + zeros = set() + ones = set() + + for choice in choices: + assert choice >= minval, choice + assert choice <= maxval, choice + + for bit in range(max_p2): + if (1 << bit) & choice: + ones.add(bit) + else: + zeros.add(bit) + + assert len(ones) == max_p2 + assert len(zeros) == max_p2 + + return tuple(sorted(choices)) + +def rand_int(minval, maxval): + return random.choice(prepare_rand_int_choices(minval, maxval)) + +def main(): + print(''' +module top(); + ''') + + params_list = [] + for tile_name, sites in gen_sites(): + params = {} + params['site'] = sites['RAMBFIFO36E1'] + + params['DATA_WIDTH'] = random.choice([4, 9, 18, 36, 72]) + params['EN_SYN'] = random.randint(0, 1) + params['DO_REG'] = 1 + if params['EN_SYN']: + params['FIRST_WORD_FALL_THROUGH'] = 0 + else: + params['FIRST_WORD_FALL_THROUGH'] = random.randint(0, 1) + + if params['EN_SYN']: + MIN_ALMOST_FULL_OFFSET = 1 + if params['DATA_WIDTH'] == 4: + MAX_ALMOST_FULL_OFFSET = 8190 + elif params['DATA_WIDTH'] == 9: + MAX_ALMOST_FULL_OFFSET = 4094 + elif params['DATA_WIDTH'] == 18: + MAX_ALMOST_FULL_OFFSET = 2046 + elif params['DATA_WIDTH'] == 36: + MAX_ALMOST_FULL_OFFSET = 1022 + elif params['DATA_WIDTH'] == 72: + MAX_ALMOST_FULL_OFFSET = 510 + else: + assert False + + MIN_ALMOST_EMPTY_OFFSET = MIN_ALMOST_FULL_OFFSET + MAX_ALMOST_EMPTY_OFFSET = MAX_ALMOST_FULL_OFFSET + else: + MIN_ALMOST_FULL_OFFSET = 4 + if params['DATA_WIDTH'] == 4: + MAX_ALMOST_FULL_OFFSET = 8185 + elif params['DATA_WIDTH'] == 9: + MAX_ALMOST_FULL_OFFSET = 4089 + elif params['DATA_WIDTH'] == 18: + MAX_ALMOST_FULL_OFFSET = 2041 + elif params['DATA_WIDTH'] == 36: + MAX_ALMOST_FULL_OFFSET = 1017 + elif params['DATA_WIDTH'] == 72: + MAX_ALMOST_FULL_OFFSET = 505 + else: + assert False + + if params['FIRST_WORD_FALL_THROUGH']: + MIN_ALMOST_EMPTY_OFFSET = MIN_ALMOST_FULL_OFFSET + 2 + MAX_ALMOST_EMPTY_OFFSET = MAX_ALMOST_FULL_OFFSET + 2 + else: + MIN_ALMOST_EMPTY_OFFSET = MIN_ALMOST_FULL_OFFSET + 1 + MAX_ALMOST_EMPTY_OFFSET = MAX_ALMOST_FULL_OFFSET + 1 + + ALMOST_EMPTY_OFFSET = rand_int(MIN_ALMOST_EMPTY_OFFSET, MAX_ALMOST_EMPTY_OFFSET) + ALMOST_FULL_OFFSET = rand_int(MIN_ALMOST_FULL_OFFSET, MAX_ALMOST_FULL_OFFSET) + params['ALMOST_EMPTY_OFFSET'] = "13'b{:013b}".format(ALMOST_EMPTY_OFFSET) + params['ALMOST_FULL_OFFSET'] = "13'b{:013b}".format(ALMOST_FULL_OFFSET) + + if params['DATA_WIDTH'] == 36: + params['FIFO_MODE'] = verilog.quote('FIFO36_72') + else: + params['FIFO_MODE'] = verilog.quote('FIFO36_72')#verilog.quote('FIFO18') #verilog.quote(random.choice(('FIFO18', 'FIFO18_36'))) + + params['INIT'] = '0' #vrandbits(36) + params['SRVAL'] = '0' #vrandbits(36) + + print( + ''' + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + FIFO36E1 #( + .ALMOST_EMPTY_OFFSET({ALMOST_EMPTY_OFFSET}), + .ALMOST_FULL_OFFSET({ALMOST_FULL_OFFSET}), + .DATA_WIDTH({DATA_WIDTH}), + .DO_REG({DO_REG}), + .EN_SYN({EN_SYN}), + .FIFO_MODE({FIFO_MODE}), + .FIRST_WORD_FALL_THROUGH({FIRST_WORD_FALL_THROUGH}), + .INIT({INIT}), + .SRVAL({SRVAL}) + ) fifo_{site} ( + ); + '''.format( + **params, + )) + + params['FIFO_MODE'] = verilog.unquote(params['FIFO_MODE']) + + params_list.append(params) + + print("endmodule") + + with open('params.json', 'w') as f: + json.dump(params_list, f, indent=2) + + +if __name__ == '__main__': + main() diff --git a/fuzzers/071-ppips/generate.tcl b/fuzzers/071-ppips/generate.tcl index f68450fd..86e0503e 100644 --- a/fuzzers/071-ppips/generate.tcl +++ b/fuzzers/071-ppips/generate.tcl @@ -70,13 +70,13 @@ proc write_bram_ppips_db {filename tile} { if {[get_pips -uphill -of_objects [get_nodes -of_objects $dst_wire]] == $pip} { set src_wire [get_wires -uphill -of_objects $pip] puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always" - } - - # LOGIC_OUTS pips appear to be always, even thought multiple inputs to - # the pip junction. Best guess is that the underlying hardware is - # actually just one wire, and there is no actually junction. - if [string match "*LOGIC_OUTS*" dst_wire] { - puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always" + } elseif [string match "*LOGIC_OUTS*" $dst_wire] { + # LOGIC_OUTS pips appear to be always, even thought multiple inputs to + # the pip junction. Best guess is that the underlying hardware is + # actually just one wire, and there is no actually junction. + foreach src_wire [get_wires -uphill -of_objects $pip] { + puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always" + } } } diff --git a/fuzzers/Makefile b/fuzzers/Makefile index 95996bfb..60242c40 100644 --- a/fuzzers/Makefile +++ b/fuzzers/Makefile @@ -38,6 +38,8 @@ $(eval $(call fuzzer,018-clb-ram,005-tilegrid)) $(eval $(call fuzzer,019-clb-ndi1mux,005-tilegrid)) $(eval $(call fuzzer,025-bram-config,005-tilegrid)) $(eval $(call fuzzer,026-bram-data,005-tilegrid)) +$(eval $(call fuzzer,027-bram36-config,005-tilegrid)) +$(eval $(call fuzzer,028-fifo-config,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)) @@ -47,7 +49,8 @@ $(eval $(call fuzzer,056-pip-rem,051-pip-imuxlout-bypalts 052-pip-clkin 053-pip- $(eval $(call fuzzer,057-pip-bi,056-pip-rem)) ifneq ($(QUICK),Y) $(eval $(call fuzzer,058-pip-hclk,056-pip-rem)) -$(eval $(call fuzzer,071-ppips,057-pip-bi 058-pip-hclk)) +$(eval $(call fuzzer,060-bram-cascades,005-tilegrid)) +$(eval $(call fuzzer,071-ppips,057-pip-bi 058-pip-hclk 060-bram-cascades)) ifneq ($(BITONLY),Y) $(eval $(call fuzzer,072-ordered_wires,)) $(eval $(call fuzzer,073-get_counts,))