diff --git a/fuzzers/035a-iob-idelay/Makefile b/fuzzers/035a-iob-idelay/Makefile new file mode 100644 index 00000000..09fd9a31 --- /dev/null +++ b/fuzzers/035a-iob-idelay/Makefile @@ -0,0 +1,20 @@ +N := 5 +include ../fuzzer.mk + +database: build/segbits_xiob33.db + +build/segbits_xiob33.rdb: $(SPECIMENS_OK) + ${XRAY_SEGMATCH} -m 1 -M 1 -o build/segbits_xiob33.rdb $$(find -name segdata_*.txt) + +build/segbits_xiob33.db: build/segbits_xiob33.rdb + ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@ + ${XRAY_MASKMERGE} build/mask_xiob33.db $$(find -name segdata_*.txt) + +pushdb: + ${XRAY_MERGEDB} lioi3 build/segbits_xiob33.db + ${XRAY_MERGEDB} rioi3 build/segbits_xiob33.db + ${XRAY_MERGEDB} mask_lioi3 build/mask_xiob33.db + ${XRAY_MERGEDB} mask_rioi3 build/mask_xiob33.db + +.PHONY: database pushdb + diff --git a/fuzzers/035a-iob-idelay/bits.dbf b/fuzzers/035a-iob-idelay/bits.dbf new file mode 100644 index 00000000..e69de29b diff --git a/fuzzers/035a-iob-idelay/generate.py b/fuzzers/035a-iob-idelay/generate.py new file mode 100644 index 00000000..f93950ff --- /dev/null +++ b/fuzzers/035a-iob-idelay/generate.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +import json + +from prjxray.segmaker import Segmaker +from prjxray import util +from prjxray import verilog + +segmk = Segmaker("design.bits", verbose=True) + +# Load tags +with open("params.json", "r") as fp: + data = json.load(fp) + +idelay_types = ["FIXED", "VARIABLE", "VAR_LOAD"] +delay_srcs = ["IDATAIN", "DATAIN"] + +# Output tags +for params in data: + loc = verilog.unquote(params["LOC"]) + + # Delay type + value = verilog.unquote(params["IDELAY_TYPE"]) + value = value.replace( + "_PIPE", "") # VAR_LOAD and VAR_LOAD_PIPE are the same + for x in idelay_types: + segmk.add_site_tag(loc, "IDELAY_TYPE_%s" % x, int(value == x)) + + # Delay value + value = int(params["IDELAY_VALUE"]) + for i in range(5): + segmk.add_site_tag( + loc, "IDELAY_VALUE[%01d]" % i, ((value >> i) & 1) != 0) + + # Delay source + value = verilog.unquote(params["DELAY_SRC"]) + for x in delay_srcs: + segmk.add_site_tag(loc, "DELAY_SRC_%s" % x, int(value == x)) + + value = verilog.unquote(params["HIGH_PERFORMANCE_MODE"]) + segmk.add_site_tag(loc, "HIGH_PERFORMANCE_MODE", int(value == "TRUE")) + + value = verilog.unquote(params["CINVCTRL_SEL"]) + segmk.add_site_tag(loc, "CINVCTRL_SEL", int(value == "TRUE")) + + value = verilog.unquote(params["PIPE_SEL"]) + segmk.add_site_tag(loc, "PIPE_SEL", int(value == "TRUE")) + + if "IS_C_INVERTED" in params: + segmk.add_site_tag(loc, "IS_C_INVERTED", int(params["IS_C_INVERTED"])) + + segmk.add_site_tag( + loc, "IS_DATAIN_INVERTED", int(params["IS_DATAIN_INVERTED"])) + segmk.add_site_tag( + loc, "IS_IDATAIN_INVERTED", int(params["IS_IDATAIN_INVERTED"])) + + +def bitfilter(frame_idx, bit_idx): + return True + + +segmk.compile(bitfilter=bitfilter) +segmk.write() diff --git a/fuzzers/035a-iob-idelay/generate.tcl b/fuzzers/035a-iob-idelay/generate.tcl new file mode 100644 index 00000000..15aa2de7 --- /dev/null +++ b/fuzzers/035a-iob-idelay/generate.tcl @@ -0,0 +1,24 @@ +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_param tcl.collectionResultDisplayLimit 0 + +set_property IS_ENABLED 0 [get_drc_checks {NSTD-1}] +set_property IS_ENABLED 0 [get_drc_checks {UCIO-1}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-79}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-81}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-84}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-85}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-87}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-85}] +set_property IS_ENABLED 0 [get_drc_checks {AVAL-28}] + +place_design +route_design + +write_checkpoint -force design.dcp +write_bitstream -force design.bit diff --git a/fuzzers/035a-iob-idelay/top.py b/fuzzers/035a-iob-idelay/top.py new file mode 100644 index 00000000..2ba01d59 --- /dev/null +++ b/fuzzers/035a-iob-idelay/top.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python3 + +import os, random +random.seed(int(os.getenv("SEED"), 16)) + +import re +import json + +from prjxray import util +from prjxray.db import Database + +# ============================================================================= + + +def gen_sites(): + db = Database(util.get_db_root()) + grid = db.grid() + + tile_list = [] + for tile_name in sorted(grid.tiles()): + if "IOB33" not in tile_name or "SING" in tile_name: + continue + tile_list.append(tile_name) + + get_xy = util.create_xy_fun('[LR]IOB33_') + tile_list.sort(key=get_xy) + + for iob_tile_name in tile_list: + iob_gridinfo = grid.gridinfo_at_loc( + grid.loc_of_tilename(iob_tile_name)) + + # Find IOI tile adjacent to IOB + for suffix in ["IOI3", "IOI3_TBYTESRC", "IOI3_TBYTETERM"]: + try: + ioi_tile_name = iob_tile_name.replace("IOB33", suffix) + ioi_gridinfo = grid.gridinfo_at_loc( + grid.loc_of_tilename(ioi_tile_name)) + break + except KeyError: + pass + + iob33s = [k for k, v in iob_gridinfo.sites.items() if v == "IOB33S"][0] + iob33m = [k for k, v in iob_gridinfo.sites.items() if v == "IOB33M"][0] + idelay_s = iob33s.replace("IOB", "IDELAY") + idelay_m = iob33m.replace("IOB", "IDELAY") + + yield iob33m, idelay_m, iob33s, idelay_s + + +def run(): + + # Get all [LR]IOI3 tiles + tiles = list(gen_sites()) + + # Header + print("// Tile count: %d" % len(tiles)) + print("// Seed: '%s'" % os.getenv("SEED")) + print( + ''' +module top ( + (* CLOCK_BUFFER_TYPE = "NONE" *) + input wire clk, + input wire [{N}:0] di, + output wire [{N}:0] do +); + +wire clk_buf = clk; + +wire [{N}:0] di_buf; +wire [{N}:0] do_buf; + '''.format(**{"N": len(tiles) - 1})) + + # LOCes IOBs + data = [] + for i, sites in enumerate(tiles): + + if random.randint(0, 1): + iob_i = sites[0] + iob_o = sites[2] + idelay = sites[1] + else: + iob_i = sites[2] + iob_o = sites[0] + idelay = sites[3] + + params = { + "LOC": + "\"" + idelay + "\"", + "IDELAY_TYPE": + "\"" + random.choice( + ["FIXED", "VARIABLE", "VAR_LOAD", "VAR_LOAD_PIPE"]) + "\"", + "IDELAY_VALUE": + random.randint(0, 31), + "DELAY_SRC": + "\"" + random.choice(["IDATAIN", "DATAIN"]) + "\"", + "HIGH_PERFORMANCE_MODE": + "\"" + random.choice(["TRUE", "FALSE"]) + "\"", + "CINVCTRL_SEL": + "\"" + random.choice(["TRUE", "FALSE"]) + "\"", + "PIPE_SEL": + "\"" + random.choice(["TRUE", "FALSE"]) + "\"", + "IS_C_INVERTED": + random.randint(0, 1), + "IS_DATAIN_INVERTED": + random.randint(0, 1), + "IS_IDATAIN_INVERTED": + random.randint(0, 1), + } + + if params["IDELAY_TYPE"] != "\"VAR_LOAD_PIPE\"": + params["PIPE_SEL"] = "\"FALSE\"" + + # The datasheet says that for these two modes the delay is set to 0 + if params["IDELAY_TYPE"] == "\"VAR_LOAD\"": + params["IDELAY_VALUE"] = 0 + if params["IDELAY_TYPE"] == "\"VAR_LOAD_PIPE\"": + params["IDELAY_VALUE"] = 0 + + if params["IDELAY_TYPE"] == "\"FIXED\"": + params["IS_C_INVERTED"] = 0 + + param_str = ",".join(".%s(%s)" % (k, v) for k, v in params.items()) + + print('') + print('(* LOC="%s", KEEP, DONT_TOUCH *)' % iob_i) + print('IBUF ibuf_%03d (.I(di[%3d]), .O(di_buf[%3d]));' % (i, i, i)) + print('(* LOC="%s", KEEP, DONT_TOUCH *)' % iob_o) + print('OBUF obuf_%03d (.I(do_buf[%3d]), .O(do[%3d]));' % (i, i, i)) + print( + 'mod #(%s) mod_%03d (.clk(clk_buf), .I(di_buf[%3d]), .O(do_buf[%3d]));' + % (param_str, i, i, i)) + + data.append(params) + + # Store params + with open("params.json", "w") as fp: + json.dump(data, fp, sort_keys=True, indent=1) + + print( + ''' +// IDELAYCTRL +(* KEEP, DONT_TOUCH *) +IDELAYCTRL idelayctrl(); + +endmodule + +(* KEEP, DONT_TOUCH *) +module mod( + input wire clk, + input wire I, + output wire O +); + +parameter LOC = ""; +parameter IDELAY_TYPE = "FIXED"; +parameter IDELAY_VALUE = 0; +parameter DELAY_SRC = "IDATAIN"; +parameter HIGH_PERFORMANCE_MODE = "TRUE"; +parameter SIGNAL_PATTERN = "DATA"; +parameter CINVCTRL_SEL = "FALSE"; +parameter PIPE_SEL = "FALSE"; +parameter IS_C_INVERTED = 0; +parameter IS_DATAIN_INVERTED = 0; +parameter IS_IDATAIN_INVERTED = 0; + +wire x; + +// IDELAY +(* LOC=LOC, KEEP, DONT_TOUCH *) +IDELAYE2 #( + .IDELAY_TYPE(IDELAY_TYPE), + .IDELAY_VALUE(IDELAY_VALUE), + .DELAY_SRC(DELAY_SRC), + .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE), + .SIGNAL_PATTERN(SIGNAL_PATTERN), + .CINVCTRL_SEL(CINVCTRL_SEL), + .PIPE_SEL(PIPE_SEL), + .IS_C_INVERTED(IS_C_INVERTED), + .IS_DATAIN_INVERTED(IS_DATAIN_INVERTED), + .IS_IDATAIN_INVERTED(IS_IDATAIN_INVERTED) +) +idelay +( + .C(clk), + .REGRST(), + .LD(), + .CE(), + .INC(), + .CINVCTRL(), + .CNTVALUEIN(), + .IDATAIN(I), + .DATAIN(), + .LDPIPEEN(), + .DATAOUT(x), + .CNTVALUEOUT() +); + +// A LUT +(* KEEP, DONT_TOUCH *) +LUT6 #(.INIT(32'hDEADBEEF)) lut ( + .I0(x), + .I1(x), + .I2(x), + .I3(x), + .I4(x), + .I5(x), + .O(O) +); + +endmodule + ''') + + +run() diff --git a/fuzzers/Makefile b/fuzzers/Makefile index ae5ff042..c515cde3 100644 --- a/fuzzers/Makefile +++ b/fuzzers/Makefile @@ -86,6 +86,7 @@ $(eval $(call fuzzer,030-iob,005-tilegrid)) $(eval $(call fuzzer,032-cmt-pll,005-tilegrid)) $(eval $(call fuzzer,034-cmt-pll-pips,005-tilegrid)) $(eval $(call fuzzer,035-iob-ilogic,005-tilegrid)) +$(eval $(call fuzzer,035a-iob-idelay,005-tilegrid)) $(eval $(call fuzzer,036-iob-ologic,005-tilegrid)) $(eval $(call fuzzer,038-cfg,005-tilegrid)) $(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid)) diff --git a/prjxray/segmaker.py b/prjxray/segmaker.py index 8ce64dca..375714db 100644 --- a/prjxray/segmaker.py +++ b/prjxray/segmaker.py @@ -311,6 +311,9 @@ class Segmaker: 'SLICE': name_slice, 'RAMB18': name_bram18, 'IOB': name_y0y1, + 'IDELAY': name_y0y1, + 'ILOGIC': name_y0y1, + 'OLOGIC': name_y0y1, }.get(site_prefix, name_default)() self.verbose and print( 'site %s w/ %s prefix => tag %s' % @@ -337,6 +340,7 @@ class Segmaker: -CENTER_INTER_R => CENTER_INTER -CLK_HROW_TOP_R => CLK_HROW -LIOB33 => IOB33 + -LIOI3 => IOI3 ''' tile_type_norm = re.sub("(_TOP|_BOT|LL|LM)?_[LR]$", "", tile_type) tile_type_norm = re.sub( @@ -345,6 +349,13 @@ class Segmaker: if tile_type_norm in ['LIOB33', 'RIOB33']: tile_type_norm = 'IOB33' + if tile_type_norm in ['LIOI3', 'RIOI3']: + tile_type_norm = 'IOI3' + if tile_type_norm in ['LIOI3_TBYTESRC', 'RIOI3_TBYTESRC']: + tile_type_norm = 'IOI3' + if tile_type_norm in ['LIOI3_TBYTETERM', 'RIOI3_TBYTETERM']: + tile_type_norm = 'IOI3' + # ignore dummy tiles (ex: VBRK) if len(tiledata['bits']) == 0: if self.verbose: diff --git a/utils/mergedb.sh b/utils/mergedb.sh index 553ea3b5..f5217ee3 100755 --- a/utils/mergedb.sh +++ b/utils/mergedb.sh @@ -114,6 +114,12 @@ case "$1" in riob33) sed < "$2" > "$tmp1" -e 's/^IOB33\./RIOB33./' ;; + lioi3) + sed < "$2" > "$tmp1" -e 's/^IOI3\./LIOI3./' ;; + + rioi3) + sed < "$2" > "$tmp1" -e 's/^IOI3\./RIOI3./' ;; + cmt_top_r_upper_t) sed < "$2" > "$tmp1" -e 's/^CMT_UPPER_T\./CMT_TOP_R_UPPER_T./' ;;