diff --git a/fuzzers/035b-iob-iserdes/Makefile b/fuzzers/035b-iob-iserdes/Makefile new file mode 100644 index 00000000..1c3d2d23 --- /dev/null +++ b/fuzzers/035b-iob-iserdes/Makefile @@ -0,0 +1,22 @@ +N := 50 +include ../fuzzer.mk + +database: build/segbits_xiob33.db + +build/segbits_xiob33_msk.rdb: $(SPECIMENS_OK) + #${XRAY_SEGMATCH} -c -1 -m 1 -M 1 -o build/segbits_xiob33.rdb $$(find -name segdata_*.txt) + #python3 ~/Work/segmask.py -i build/segbits_xiob33.rdb -o build/segbits_xiob33_msk.rdb -m IN_USE + python3 ~/Work/lms_solver.py -o build/segbits_xiob33_msk.rdb -m IN_USE $$(find -name segdata_*.txt) + +build/segbits_xiob33.db: build/segbits_xiob33_msk.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} liob33 build/segbits_xiob33.db + ${XRAY_MERGEDB} riob33 build/segbits_xiob33.db + ${XRAY_MERGEDB} mask_liob33 build/mask_xiob33.db + ${XRAY_MERGEDB} mask_riob33 build/mask_xiob33.db + +.PHONY: database pushdb + diff --git a/fuzzers/035b-iob-iserdes/bits.dbf b/fuzzers/035b-iob-iserdes/bits.dbf new file mode 100644 index 00000000..e69de29b diff --git a/fuzzers/035b-iob-iserdes/generate.py b/fuzzers/035b-iob-iserdes/generate.py new file mode 100644 index 00000000..55f31edf --- /dev/null +++ b/fuzzers/035b-iob-iserdes/generate.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +import json +import re + +from prjxray.segmaker import Segmaker +from prjxray import util +from prjxray import verilog + +segmk = Segmaker("design.bits") + +# Load tags +with open("params.json", "r") as fp: + data = json.load(fp) + +iface_types = ["NETWORKING", "OVERSAMPLE", "MEMORY", "MEMORY_DDR3", "MEMORY_QDR"] +data_rates = ["SDR", "DDR"] +data_widths = [2, 3, 4, 5, 6, 7, 8, 10, 14] + +# Output tags +loc_to_tile_site_map = {} +for params in data: + loc = verilog.unquote(params["_LOC"]) + loc = loc.replace("ILOGIC", "IOB") + + get_xy = util.create_xy_fun('IOB_') + x, y = get_xy(loc) + + loc_to_tile_site_map[loc] = params["TILE"] + ".IOB_X0Y%d" % (y % 2) + + # Serdes not used at all + if not params["IS_USED"]: + + segmk.add_site_tag(loc, "ISERDES.IN_USE", 0) + + segmk.add_site_tag(loc, "ISERDES.MODE.MASTER", 0) + segmk.add_site_tag(loc, "ISERDES.MODE.SLAVE", 0) + + for i in iface_types: + if i == "NETWORKING": + for j in data_rates: + for k in data_widths: + tag = "ISERDES.%s.%s.%s" % (i, j, k) + segmk.add_site_tag(loc, tag, 0) + else: + for j in data_rates: + segmk.add_site_tag(loc, "ISERDES.%s.%s.4" % (i, j), 0) + + segmk.add_site_tag(loc, "ISERDES.NUM_CE.1", 0) + segmk.add_site_tag(loc, "ISERDES.NUM_CE.2", 0) + + for i in range(1, 4+1): + segmk.add_site_tag(loc, "IFF.ZINIT_Q%d" % i, 0) + + for i in range(1, 4+1): + segmk.add_site_tag(loc, "IFF.ZSRVAL_Q%d" % i, 0) + + segmk.add_site_tag(loc, "ZINV_D", 0) + + segmk.add_site_tag(loc, "ISERDES.DYN_CLKDIV_INV_EN", 0) + segmk.add_site_tag(loc, "ISERDES.DYN_CLK_INV_EN", 0) + + segmk.add_site_tag(loc, "IFFDELMUXE3.0", 1) + segmk.add_site_tag(loc, "IFFDELMUXE3.1", 0) + segmk.add_site_tag(loc, "IDELMUXE3.0", 1) + segmk.add_site_tag(loc, "IDELMUXE3.1", 0) + + segmk.add_site_tag(loc, "ISERDES.OFB_USED", 0) + + # Serdes used + else: + + segmk.add_site_tag(loc, "ISERDES.IN_USE", 1) + + if "SERDES_MODE" in params: + value = verilog.unquote(params["SERDES_MODE"]) + if value == "MASTER": + segmk.add_site_tag(loc, "ISERDES.MODE.MASTER", 1) + segmk.add_site_tag(loc, "ISERDES.MODE.SLAVE", 0) + if value == "SLAVE": + segmk.add_site_tag(loc, "ISERDES.MODE.MASTER", 0) + segmk.add_site_tag(loc, "ISERDES.MODE.SLAVE", 1) + + iface_type = verilog.unquote(params["INTERFACE_TYPE"]) + data_rate = verilog.unquote(params["DATA_RATE"]) + data_width = int(params["DATA_WIDTH"]) + + for i in iface_types: + for j in data_rates: + for k in data_widths: + tag = "ISERDES.%s.%s.%s" % (i, j, k) + + if i == iface_type: + if j == data_rate: + if k == data_width: + segmk.add_site_tag(loc, tag, 1) + + if "NUM_CE" in params: + value = params["NUM_CE"] + if value == 1: + segmk.add_site_tag(loc, "ISERDES.NUM_CE.1", 1) + segmk.add_site_tag(loc, "ISERDES.NUM_CE.2", 0) + if value == 2: + segmk.add_site_tag(loc, "ISERDES.NUM_CE.1", 0) + segmk.add_site_tag(loc, "ISERDES.NUM_CE.2", 1) + + for i in range(1, 4+1): + if ("INIT_Q%d" % i) in params: + segmk.add_site_tag(loc, "IFF.ZINIT_Q%d" % i, not params["INIT_Q%d" % i]) + + for i in range(1, 4+1): + if ("SRVAL_Q%d" % i) in params: + segmk.add_site_tag(loc, "IFF.ZSRVAL_Q%d" % i, not params["SRVAL_Q%d" % i]) + + if "IS_D_INVERTED" in params: + segmk.add_site_tag(loc, "ZINV_D", int(params["IS_D_INVERTED"] == 0)) + + if "DYN_CLKDIV_INV_EN" in params: + value = verilog.unquote(params["DYN_CLKDIV_INV_EN"]) + segmk.add_site_tag(loc, "ISERDES.DYN_CLKDIV_INV_EN", int(value == "TRUE")) + if "DYN_CLK_INV_EN" in params: + value = verilog.unquote(params["DYN_CLK_INV_EN"]) + segmk.add_site_tag(loc, "ISERDES.DYN_CLK_INV_EN", int(value == "TRUE")) + + # This parameter actually controls muxes used both in ILOGIC and + # ISERDES mode. + if "IOBDELAY" in params: + value = verilog.unquote(params["IOBDELAY"]) + if value == "NONE": + #segmk.add_site_tag(loc, "IOBDELAY_NONE", 1) + segmk.add_site_tag(loc, "IFFDELMUXE3.0", 0) + segmk.add_site_tag(loc, "IFFDELMUXE3.1", 1) + segmk.add_site_tag(loc, "IDELMUXE3.0", 0) + segmk.add_site_tag(loc, "IDELMUXE3.1", 1) + if value == "IBUF": + #segmk.add_site_tag(loc, "IOBDELAY_IBUF", 1) + segmk.add_site_tag(loc, "IFFDELMUXE3.0", 0) + segmk.add_site_tag(loc, "IFFDELMUXE3.1", 1) + segmk.add_site_tag(loc, "IDELMUXE3.0", 1) + segmk.add_site_tag(loc, "IDELMUXE3.1", 0) + if value == "IFD": + #segmk.add_site_tag(loc, "IOBDELAY_IFD" , 1) + segmk.add_site_tag(loc, "IFFDELMUXE3.0", 1) + segmk.add_site_tag(loc, "IFFDELMUXE3.1", 0) + segmk.add_site_tag(loc, "IDELMUXE3.0", 0) + segmk.add_site_tag(loc, "IDELMUXE3.1", 1) + if value == "BOTH": + #segmk.add_site_tag(loc, "IOBDELAY_BOTH", 1) + segmk.add_site_tag(loc, "IFFDELMUXE3.0", 1) + segmk.add_site_tag(loc, "IFFDELMUXE3.1", 0) + segmk.add_site_tag(loc, "IDELMUXE3.0", 1) + segmk.add_site_tag(loc, "IDELMUXE3.1", 0) + + if "OFB_USED" in params: + value = verilog.unquote(params["OFB_USED"]) + if value == "TRUE": + segmk.add_site_tag(loc, "ISERDES.OFB_USED", 1) + +# Write segments and tags for later check +with open("tags.json", "w") as fp: + tags = {loc_to_tile_site_map[l]: {k: int(v) for k, v in d.items()} for l, d in segmk.site_tags.items()} + json.dump(tags, fp, sort_keys=True, indent=1) + + +def bitfilter(frame_idx, bit_idx): + if frame_idx < 25 or frame_idx > 31: + return False + return True + +segmk.compile(bitfilter=bitfilter) +segmk.write() diff --git a/fuzzers/035b-iob-iserdes/generate.tcl b/fuzzers/035b-iob-iserdes/generate.tcl new file mode 100644 index 00000000..8ba63a89 --- /dev/null +++ b/fuzzers/035b-iob-iserdes/generate.tcl @@ -0,0 +1,24 @@ +set_param general.maxThreads 1 + +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-98}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-109}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-111}] +set_property IS_ENABLED 0 [get_drc_checks {REQP-103}] +set_property IS_ENABLED 0 [get_drc_checks {PDRC-26}] + +place_design +route_design + +write_checkpoint -force design.dcp +write_bitstream -force design.bit diff --git a/fuzzers/035b-iob-iserdes/top.py b/fuzzers/035b-iob-iserdes/top.py new file mode 100644 index 00000000..58ffd3fd --- /dev/null +++ b/fuzzers/035b-iob-iserdes/top.py @@ -0,0 +1,283 @@ +#!/usr/bin/env python3 + +import os, random +random.seed(int(os.getenv("SEED"), 16)) + +import re +import json + +from prjxray import util +from prjxray import verilog +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] + ilogic_s = iob33s.replace("IOB", "ILOGIC") + ilogic_m = iob33m.replace("IOB", "ILOGIC") + + yield iob_tile_name, iob33m, ilogic_m, iob33s, ilogic_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 clk1, + (* CLOCK_BUFFER_TYPE = "NONE" *) + input wire clk2, + input wire [{N}:0] di, + output wire [{N}:0] do +); + +wire [{N}:0] di_buf; +wire [{N}:0] do_buf; + '''.format(**{"N": len(tiles) - 1})) + + # LOCes IOBs + data = [] + for i, sites in enumerate(tiles): + tile_name = sites[0] + + # Bottom site + if random.randint(0, 1): + iob_i = sites[1] + iob_o = sites[3] + ilogic = sites[2] + # Top site + else: + iob_i = sites[3] + iob_o = sites[1] + ilogic = sites[4] + + # Site params + params = { + "_LOC": verilog.quote(ilogic), + "IS_USED": int(random.randint(0, 10) > 0), # Make it used more often + "INIT_Q1": random.randint(0, 1), + "INIT_Q2": random.randint(0, 1), + "INIT_Q3": random.randint(0, 1), + "INIT_Q4": random.randint(0, 1), + "SRVAL_Q1": random.randint(0, 1), + "SRVAL_Q2": random.randint(0, 1), + "SRVAL_Q3": random.randint(0, 1), + "SRVAL_Q4": random.randint(0, 1), + "NUM_CE": random.randint(1, 2), + # The following one shows negative correlation (0 - not inverted) + "IS_D_INVERTED": random.randint(0, 1), + # No bits were found for parameters below + #"IS_OCLKB_INVERTED": random.randint(0, 1), + #"IS_OCLK_INVERTED": random.randint(0, 1), + #"IS_CLKDIVP_INVERTED": random.randint(0, 1), + #"IS_CLKDIV_INVERTED": random.randint(0, 1), + #"IS_CLKB_INVERTED": random.randint(0, 1), + #"IS_CLK_INVERTED": random.randint(0, 1), + "DYN_CLKDIV_INV_EN": verilog.quote(random.choice(["TRUE", "FALSE"])), + "DYN_CLK_INV_EN": verilog.quote(random.choice(["TRUE", "FALSE"])), + "IOBDELAY": verilog.quote(random.choice(["NONE", "IBUF", "IFD", "BOTH"])), + "OFB_USED": verilog.quote(random.choice(["TRUE"] + ["FALSE"]*9)), # Force more FALSEs + } + + iface_type = random.choice(["NETWORKING", "OVERSAMPLE", "MEMORY", "MEMORY_DDR3", "MEMORY_QDR"]) + data_rate = random.choice(["SDR", "DDR"]) + serdes_mode = random.choice(["MASTER", "SLAVE"]) + + params["INTERFACE_TYPE"] = verilog.quote(iface_type) + params["DATA_RATE"] = verilog.quote(data_rate) + params["SERDES_MODE"] = verilog.quote(serdes_mode) + + # Networking mode + if iface_type == "NETWORKING": + data_widths = { + "SDR": [2, 3, 4, 5, 6, 7, 8], + "DDR": [4, 6, 8, 10, 14], + } + params["DATA_WIDTH"] = random.choice(data_widths[data_rate]) + + # Others + else: + params["DATA_WIDTH"] = 4 + + if verilog.unquote(params["OFB_USED"]) == "TRUE": + params["IOBDELAY"] = verilog.quote("NONE") + + # Instantiate cell + 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( + 'iserdes_single #(%s) iserdes_%03d (.clk1(clk1), .clk2(clk2), .I(di_buf[%3d]), .O(do_buf[%3d]));' + % (param_str, i, i, i)) + + params["TILE"] = tile_name + data.append(params) + + # Store params + with open("params.json", "w") as fp: + json.dump(data, fp, sort_keys=True, indent=1) + + print( + ''' +endmodule + +(* KEEP, DONT_TOUCH *) +module iserdes_single( + input wire clk1, + input wire clk2, + input wire I, + output wire O +); + +parameter _LOC = ""; +parameter IS_USED = 1; +parameter INTERFACE_TYPE = "NETWORKING"; +parameter DATA_RATE = "DDR"; +parameter DATA_WIDTH = 4; +parameter SERDES_MODE = "MASTER"; +parameter NUM_CE = 2; +parameter INIT_Q1 = 0; +parameter INIT_Q2 = 0; +parameter INIT_Q3 = 0; +parameter INIT_Q4 = 0; +parameter SRVAL_Q1 = 0; +parameter SRVAL_Q2 = 0; +parameter SRVAL_Q3 = 0; +parameter SRVAL_Q4 = 0; +parameter IS_D_INVERTED = 0; +parameter IS_OCLK_INVERTED = 0; +parameter IS_OCLKB_INVERTED = 0; +parameter IS_CLK_INVERTED = 0; +parameter IS_CLKB_INVERTED = 0; +parameter IS_CLKDIV_INVERTED = 0; +parameter IS_CLKDIVP_INVERTED = 0; +parameter DYN_CLKDIV_INV_EN = "FALSE"; +parameter DYN_CLK_INV_EN = "FALSE"; +parameter IOBDELAY = "NONE"; +parameter OFB_USED = "FALSE"; + +(* KEEP, DONT_TOUCH *) +wire [7:0] x; + +generate if (IS_USED) begin + + // Single ISERDES + (* LOC=_LOC, KEEP, DONT_TOUCH *) + ISERDESE2 # + ( + .INTERFACE_TYPE(INTERFACE_TYPE), + .DATA_RATE(DATA_RATE), + .DATA_WIDTH(DATA_WIDTH), + .SERDES_MODE(SERDES_MODE), + .NUM_CE(NUM_CE), + .IS_D_INVERTED(IS_D_INVERTED), + .IS_OCLK_INVERTED(IS_OCLK_INVERTED), + .IS_OCLKB_INVERTED(IS_OCLKB_INVERTED), + .IS_CLK_INVERTED(IS_CLK_INVERTED), + .IS_CLKB_INVERTED(IS_CLKB_INVERTED), + .IS_CLKDIV_INVERTED(IS_CLKDIV_INVERTED), + .IS_CLKDIVP_INVERTED(IS_CLKDIVP_INVERTED), + .INIT_Q1(INIT_Q1), + .INIT_Q2(INIT_Q2), + .INIT_Q3(INIT_Q3), + .INIT_Q4(INIT_Q4), + .SRVAL_Q1(SRVAL_Q1), + .SRVAL_Q2(SRVAL_Q2), + .SRVAL_Q3(SRVAL_Q3), + .SRVAL_Q4(SRVAL_Q4), + .DYN_CLKDIV_INV_EN(DYN_CLKDIV_INV_EN), + .DYN_CLK_INV_EN(DYN_CLK_INV_EN), + .IOBDELAY(IOBDELAY), + .OFB_USED(OFB_USED) + ) + isedres + ( + .D(I), + .DDLY(), + .OFB(), + //.TFB(), + .CE1(), + .CE2(), + .DYNCLKSEL(), + .CLK(clk1), + .CLKB(clk2), + .OCLK(), + .DYNCLKDIVSEL(), + .CLKDIV(), + .CLKDIVP(), + .RST(), + .BITSLIP(), + .O(), + .Q1(x[0]), + .Q2(x[1]), + .Q3(x[2]), + .Q4(x[3]), + .Q5(x[4]), + .Q6(x[5]), + .Q7(x[6]), + .Q8(x[7]), + .SHIFTOUT1(), + .SHIFTOUT2() + ); + +end else begin + + assign x[0] = I; + assign x[1] = I; + assign x[2] = I; + assign x[3] = I; + assign x[4] = I; + assign x[5] = I; + assign x[6] = I; + assign x[7] = I; + +end endgenerate + +// Output +assign O = |x; + +endmodule + ''') + + +run()