mirror of https://github.com/openXC7/prjxray.git
Basic ODELAY fuzzer
Signed-off-by: David Shah <dave@ds0.me> Signed-off-by: Hans Baier <hansfbaier@gmail.com>
This commit is contained in:
parent
53b9fe1ccd
commit
dd2415365e
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (C) 2017-2023 The Project X-Ray Authors.
|
||||
#
|
||||
# Use of this source code is governed by a ISC-style
|
||||
# license that can be found in the LICENSE file or at
|
||||
# https://opensource.org/licenses/ISC
|
||||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
N := 5
|
||||
include ../fuzzer.mk
|
||||
|
||||
database: build/segbits_riob18.db
|
||||
|
||||
build/segbits_riob18.rdb: $(SPECIMENS_OK)
|
||||
${XRAY_SEGMATCH} -m 1 -M 1 -o build/segbits_riob18.rdb $$(find -name segdata_*.txt)
|
||||
|
||||
build/segbits_riob18.db: build/segbits_riob18.rdb
|
||||
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
|
||||
${XRAY_MASKMERGE} build/mask_riob18.db $$(find -name segdata_*.txt)
|
||||
|
||||
pushdb:
|
||||
${XRAY_MERGEDB} rioi build/segbits_riob18.db
|
||||
${XRAY_MERGEDB} rioi_tbytesrc build/segbits_riob18.db
|
||||
${XRAY_MERGEDB} rioi_tbyteterm build/segbits_riob18.db
|
||||
${XRAY_MERGEDB} mask_rioi build/mask_riob18.db
|
||||
${XRAY_MERGEDB} mask_rioi_tbytesrc build/mask_riob18.db
|
||||
${XRAY_MERGEDB} mask_rioi_tbyteterm build/mask_riob18.db
|
||||
|
||||
.PHONY: database pushdb
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2017-2023 The Project X-Ray Authors.
|
||||
#
|
||||
# Use of this source code is governed by a ISC-style
|
||||
# license that can be found in the LICENSE file or at
|
||||
# https://opensource.org/licenses/ISC
|
||||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
import json
|
||||
|
||||
from prjxray.segmaker import Segmaker, add_site_group_zero
|
||||
from prjxray import verilog
|
||||
|
||||
|
||||
def bitfilter(frame, word):
|
||||
return frame >= 27
|
||||
|
||||
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
|
||||
# VAR_LOAD and VAR_LOAD_PIPE are the same
|
||||
value = verilog.unquote(params["ODELAY_TYPE"])
|
||||
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)
|
||||
|
||||
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()
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Copyright (C) 2017-2023 The Project X-Ray Authors
|
||||
#
|
||||
# Use of this source code is governed by a ISC-style
|
||||
# license that can be found in the LICENSE file or at
|
||||
# https://opensource.org/licenses/ISC
|
||||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
create_project -force -part $::env(XRAY_PART) design design
|
||||
read_verilog top.v
|
||||
synth_design -top top
|
||||
|
||||
set_property CFGBVS GND [current_design]
|
||||
set_property CONFIG_VOLTAGE 1.8 [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
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2017-2023 The Project X-Ray Authors.
|
||||
#
|
||||
# Use of this source code is governed by a ISC-style
|
||||
# license that can be found in the LICENSE file or at
|
||||
# https://opensource.org/licenses/ISC
|
||||
#
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
import os, random
|
||||
random.seed(int(os.getenv("SEED"), 16))
|
||||
|
||||
import sys
|
||||
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('RIOB18_')
|
||||
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("IOB18", suffix)
|
||||
ioi_gridinfo = grid.gridinfo_at_loc(
|
||||
grid.loc_of_tilename(ioi_tile_name))
|
||||
break
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
iob18s = [k for k, v in iob_gridinfo.sites.items() if v == "IOB18S"][0]
|
||||
iob18m = [k for k, v in iob_gridinfo.sites.items() if v == "IOB18M"][0]
|
||||
odelay_s = iob18s.replace("IOB", "ODELAY")
|
||||
odelay_m = iob18m.replace("IOB", "ODELAY")
|
||||
|
||||
yield iob18m, odelay_m, iob18s, 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_inuse = sites[0]
|
||||
iob_other = sites[2]
|
||||
odelay_inuse = sites[1]
|
||||
odelay_other = sites[3]
|
||||
else:
|
||||
iob_inuse = sites[2]
|
||||
iob_other = sites[0]
|
||||
odelay_inuse = sites[3]
|
||||
odelay_other = sites[1]
|
||||
|
||||
use_obuf = obuf_idx is not None
|
||||
|
||||
if not use_obuf:
|
||||
continue
|
||||
|
||||
params = {
|
||||
"LOC":
|
||||
"\"" + odelay_inuse + "\"",
|
||||
"ODELAY_TYPE":
|
||||
"\"" + random.choice(
|
||||
["FIXED", "VARIABLE", "VAR_LOAD"]) + "\"",
|
||||
"ODELAY_VALUE":
|
||||
random.randint(0, 31),
|
||||
"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_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_inuse)
|
||||
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_inuse + " " + odelay_other
|
||||
else:
|
||||
print('')
|
||||
print('(* LOC="%s", KEEP, DONT_TOUCH *)' % iob_inuse)
|
||||
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_inuse
|
||||
params["ODELAY_NOT_IN_USE"] = odelay_other
|
||||
|
||||
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 = "ODATAIN";
|
||||
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()
|
||||
|
|
@ -329,6 +329,7 @@ class Segmaker:
|
|||
'RAMB18': name_bram18,
|
||||
'IOB': name_y0y1,
|
||||
'IDELAY': name_y0y1,
|
||||
'ODELAY': name_y0y1,
|
||||
'ILOGIC': name_y0y1,
|
||||
'OLOGIC': name_y0y1,
|
||||
'IBUFDS_GTE2': name_y0y1,
|
||||
|
|
@ -391,6 +392,13 @@ class Segmaker:
|
|||
if 'GTP_INT_INTERFACE' in tile_type_norm:
|
||||
tile_type_norm = 'GTP_INT_INTERFACE'
|
||||
|
||||
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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue