Skip to content

Commit

Permalink
Basic ODELAY fuzzer
Browse files Browse the repository at this point in the history
Signed-off-by: David Shah <dave@ds0.me>
  • Loading branch information
gatecat committed Feb 16, 2020
1 parent f731da0 commit de0b27f
Show file tree
Hide file tree
Showing 7 changed files with 377 additions and 0 deletions.
22 changes: 22 additions & 0 deletions fuzzers/036a-iob-odelay/Makefile
@@ -0,0 +1,22 @@
N := 5
include ../fuzzer.mk

database: build/segbits_xiob18.db

build/segbits_xiob18.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -m 1 -M 1 -o build/segbits_xiob18.rdb $$(find -name segdata_?ioi.txt) $$(find -name segdata_?ioi_*.txt)

build/segbits_xiob18.db: build/segbits_xiob18.rdb
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
${XRAY_MASKMERGE} build/mask_xiob18.db $$(find -name segdata_?ioi.txt) $$(find -name segdata_?ioi_*.txt)

pushdb:
${XRAY_MERGEDB} rioi build/segbits_xiob18.db
${XRAY_MERGEDB} rioi_tbytesrc build/segbits_xiob18.db
${XRAY_MERGEDB} rioi_tbyteterm build/segbits_xiob18.db
${XRAY_MERGEDB} mask_rioi build/mask_xiob18.db
${XRAY_MERGEDB} mask_rioi_tbytesrc build/mask_xiob18.db
${XRAY_MERGEDB} mask_rioi_tbyteterm build/mask_xiob18.db

.PHONY: database pushdb

Empty file.
80 changes: 80 additions & 0 deletions fuzzers/036a-iob-odelay/generate.py
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
import json

from prjxray.segmaker import Segmaker, add_site_group_zero
from prjxray import verilog


def bitfilter(frame, word):
if frame < 26:
return False

return True


def main():
segmk = Segmaker("design.bits", verbose=True)

# Load tags
with open("params.json", "r") as fp:
data = json.load(fp)

odelay_types = ["FIXED", "VARIABLE", "VAR_LOAD"]
delay_srcs = ["ODATAIN"]

# Output tags
for params in data:
if params['ODELAY_BYPASS']:
prims = params['ODELAY_NOT_IN_USE'].split(" ")
segmk.add_site_tag(prims[0], 'IN_USE', False)
segmk.add_site_tag(prims[1], 'IN_USE', False)
continue
segmk.add_site_tag(params['ODELAY_IN_USE'], 'IN_USE', True)
segmk.add_site_tag(params['ODELAY_NOT_IN_USE'], 'IN_USE', False)

loc = verilog.unquote(params["LOC"])

# Delay type
value = verilog.unquote(params["ODELAY_TYPE"])
#value = value.replace(
# "_PIPE", "") # VAR_LOAD and VAR_LOAD_PIPE are the same
add_site_group_zero(
segmk, loc, "ODELAY_TYPE_", odelay_types, "FIXED", value)

# Delay value
value = int(params["ODELAY_VALUE"])
for i in range(5):
segmk.add_site_tag(
loc, "ODELAY_VALUE[%01d]" % i, ((value >> i) & 1) != 0)
segmk.add_site_tag(
loc, "ZODELAY_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["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 and verilog.unquote(params["CINVCTRL_SEL"]) != "TRUE":
segmk.add_site_tag(
loc, "IS_C_INVERTED", int(params["IS_C_INVERTED"]))
segmk.add_site_tag(loc, "ZINV_C", 1 ^ int(params["IS_C_INVERTED"]))

value = verilog.unquote(params["HIGH_PERFORMANCE_MODE"])
segmk.add_site_tag(
loc, "HIGH_PERFORMANCE_MODE", int(value == "TRUE"))

segmk.add_site_tag(
loc, "ZINV_ODATAIN", 1 ^ int(params["IS_ODATAIN_INVERTED"]))

segmk.compile(bitfilter=bitfilter)
segmk.write()


if __name__ == "__main__":
main()
24 changes: 24 additions & 0 deletions fuzzers/036a-iob-odelay/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
232 changes: 232 additions & 0 deletions fuzzers/036a-iob-odelay/top.py
@@ -0,0 +1,232 @@
#!/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(), util.get_part())
grid = db.grid()

tile_list = []
for tile_name in sorted(grid.tiles()):
if "IOB18" not in tile_name or "SING" in tile_name:
continue
tile_list.append(tile_name)

get_xy = util.create_xy_fun('[LR]IOB\\d\\d_')
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 ["IOI", "IOI_TBYTESRC", "IOI_TBYTETERM"]:
try:
ioi_tile_name = iob_tile_name.replace("IOB33", suffix)
ioi_tile_name = iob_tile_name.replace("IOB18", 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 in ("IOB33S", "IOB18S")][0]
iob33m = [k for k, v in iob_gridinfo.sites.items() if v in ("IOB33M", "IOB18M")][0]
odelay_s = iob33s.replace("IOB", "ODELAY")
odelay_m = iob33m.replace("IOB", "ODELAY")

yield iob33m, odelay_m, iob33s, odelay_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"))

ninputs = 0
do_idx = []
for i, sites in enumerate(tiles):
if random.randint(0, 1):
do_idx.append(ninputs)
ninputs += 1
else:
do_idx.append(None)

print(
'''
module top (
(* CLOCK_BUFFER_TYPE = "NONE" *)
input wire clk,
output wire [{N}:0] do
);
wire clk_buf = clk;
wire [{N}:0] do_buf;
'''.format(N=ninputs - 1))

# LOCes IOBs
data = []
for i, (sites, obuf_idx) in enumerate(zip(tiles, do_idx)):

if random.randint(0, 1):
iob_i = sites[0]
iob_o = sites[2]
odelay = sites[1]
other_odelay = sites[3]
else:
iob_i = sites[2]
iob_o = sites[0]
odelay = sites[3]
other_odelay = sites[1]

use_obuf = obuf_idx is not None

if not use_obuf:
continue

DELAY_SRC = "ODATAIN"

params = {
"LOC":
"\"" + odelay + "\"",
"ODELAY_TYPE":
"\"" + random.choice(
["FIXED", "VARIABLE", "VAR_LOAD"]) + "\"",
"ODELAY_VALUE":
random.randint(0, 31),
"DELAY_SRC":
"\"" + DELAY_SRC + "\"",
"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_ODATAIN_INVERTED":
random.randint(0, 1),
}

if params["ODELAY_TYPE"] != "\"VAR_LOAD_PIPE\"":
params["PIPE_SEL"] = "\"FALSE\""

# The datasheet says that for these two modes the delay is set to 0
if params["ODELAY_TYPE"] == "\"VAR_LOAD\"":
params["ODELAY_VALUE"] = 0
if params["ODELAY_TYPE"] == "\"VAR_LOAD_PIPE\"":
params["ODELAY_VALUE"] = 0

if params["ODELAY_TYPE"] == "\"FIXED\"":
params["IS_C_INVERTED"] = 0

param_str = ",".join(".%s(%s)" % (k, v) for k, v in params.items())

if random.randint(0, 5) == 0:
print('')
print('(* LOC="%s", KEEP, DONT_TOUCH *)' % iob_i)
print(
'OBUF obuf_%03d (.I(%d), .O(do[%3d]));' %
(obuf_idx, random.randint(0, 1), obuf_idx))
params['ODELAY_BYPASS'] = True
params["ODELAY_NOT_IN_USE"] = odelay + " " + other_odelay
else:
print('')
print('(* LOC="%s", KEEP, DONT_TOUCH *)' % iob_i)
print(
'OBUF obuf_%03d (.I(do_buf[%3d]), .O(do[%3d]));' %
(obuf_idx, obuf_idx, obuf_idx))
print(
'mod #(%s) mod_%03d (.clk(clk_buf), .O(do_buf[%3d]));' %
(param_str, i, obuf_idx))
params['ODELAY_BYPASS'] = False
params["ODELAY_IN_USE"] = odelay
params["ODELAY_NOT_IN_USE"] = other_odelay

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,
output wire O
);
parameter LOC = "";
parameter ODELAY_TYPE = "FIXED";
parameter ODELAY_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_ODATAIN_INVERTED = 0;
wire x;
wire lut;
(* KEEP, DONT_TOUCH *)
LUT2 l( .O(lut) );
// ODELAY
(* LOC=LOC, KEEP, DONT_TOUCH *)
ODELAYE2 #(
.ODELAY_TYPE(ODELAY_TYPE),
.ODELAY_VALUE(ODELAY_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_ODATAIN_INVERTED(IS_ODATAIN_INVERTED)
)
odelay
(
.C(clk),
.REGRST(),
.LD(),
.CE(),
.INC(),
.CINVCTRL(),
.CNTVALUEIN(),
.ODATAIN(lut),
.LDPIPEEN(),
.DATAOUT(O),
.CNTVALUEOUT()
);
endmodule
''')


run()
10 changes: 10 additions & 0 deletions prjxray/segmaker.py
Expand Up @@ -318,6 +318,7 @@ def name_default():
'RAMB18': name_bram18,
'IOB': name_y0y1,
'IDELAY': name_y0y1,
'ODELAY': name_y0y1,
'ILOGIC': name_y0y1,
'OLOGIC': name_y0y1,
}.get(site_prefix, name_default)()
Expand Down Expand Up @@ -354,6 +355,8 @@ def name_default():

if tile_type_norm in ['LIOB33', 'RIOB33']:
tile_type_norm = 'IOB33'
if tile_type_norm in ['LIOB18', 'RIOB18']:
tile_type_norm = 'IOB18'

if tile_type_norm in ['LIOI3', 'RIOI3']:
tile_type_norm = 'IOI3'
Expand All @@ -362,6 +365,13 @@ def name_default():
if tile_type_norm in ['LIOI3_TBYTETERM', 'RIOI3_TBYTETERM']:
tile_type_norm = 'IOI3'

if tile_type_norm in ['LIOI', 'RIOI']:
tile_type_norm = 'IOI'
if tile_type_norm in ['LIOI_TBYTESRC', 'RIOI_TBYTESRC']:
tile_type_norm = 'IOI'
if tile_type_norm in ['LIOI_TBYTETERM', 'RIOI_TBYTETERM']:
tile_type_norm = 'IOI'

# ignore dummy tiles (ex: VBRK)
if len(tiledata['bits']) == 0:
if self.verbose:
Expand Down

0 comments on commit de0b27f

Please sign in to comment.