Merge pull request #946 from antmicro/idelay-fuzzer

Fuzzer for IDELAY
This commit is contained in:
litghost 2019-07-22 10:04:36 -07:00 committed by GitHub
commit ae526981a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 338 additions and 0 deletions

View File

@ -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

View File

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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))

View File

@ -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:

View File

@ -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./' ;;