Merge pull request #2046 from kintex-chatter/k7-iob18
add support for the kintex/virtex high performance banks
diff --git a/.github/workflows/Pipeline.yml b/.github/workflows/Pipeline.yml
index 96aef1a..3653ed9 100644
--- a/.github/workflows/Pipeline.yml
+++ b/.github/workflows/Pipeline.yml
@@ -13,6 +13,7 @@
container: ubuntu:focal
runs-on: [self-hosted, Linux, X64]
+ timeout-minutes: 600
strategy:
fail-fast: false
diff --git a/fuzzers/000-init-db/Makefile b/fuzzers/000-init-db/Makefile
index 033ed98..4b1e09a 100644
--- a/fuzzers/000-init-db/Makefile
+++ b/fuzzers/000-init-db/Makefile
@@ -50,6 +50,7 @@
segbits_cmt_top_r_lower_b \
segbits_rioi3 \
segbits_riob33 \
+ segbits_riob18 \
segbits_hclk_cmt \
segbits_hclk_ioi3 \
diff --git a/fuzzers/001-part-yaml/generate.tcl b/fuzzers/001-part-yaml/generate.tcl
index 5cce0a9..a140980 100644
--- a/fuzzers/001-part-yaml/generate.tcl
+++ b/fuzzers/001-part-yaml/generate.tcl
@@ -11,7 +11,7 @@
set sample_site [lindex [get_sites -of $iobank] 0]
if {[llength $sample_site] == 0} continue
set clock_region [get_property CLOCK_REGION $sample_site]
- foreach tile [get_tiles -filter {TYPE=~HCLK_IOI3}] {
+ foreach tile [concat [get_tiles -filter {TYPE=~HCLK_IOI3}] [get_tiles -filter {TYPE=~HCLK_IOI}]] {
set tile_sites [get_sites -of_object $tile]
if {[llength $tile_sites] == 0} continue
set hclk_tile_clock_region [get_property CLOCK_REGION [lindex [get_sites -of_object $tile] 0]]
diff --git a/fuzzers/005-tilegrid/Makefile b/fuzzers/005-tilegrid/Makefile
index f0ad42b..5771695 100644
--- a/fuzzers/005-tilegrid/Makefile
+++ b/fuzzers/005-tilegrid/Makefile
@@ -49,6 +49,13 @@
# Kintex7 only fuzzers
ifeq (${XRAY_DATABASE}, kintex7)
+# xc7k420t/xc7k480t have no high performance banks
+ifneq (${XRAY_FABRIC}, $(filter ${XRAY_FABRIC}, xc7k480t))
+TILEGRID_TDB_DEPENDENCIES += iob18/$(BUILD_FOLDER)/segbits_tilegrid.tdb
+TILEGRID_TDB_DEPENDENCIES += iob18_int/$(BUILD_FOLDER)/segbits_tilegrid.tdb
+TILEGRID_TDB_DEPENDENCIES += ioi18/$(BUILD_FOLDER)/segbits_tilegrid.tdb
+endif
+
# These kintex parts give an empty design
ifneq (${XRAY_FABRIC}, $(filter ${XRAY_FABRIC}, xc7k160t xc7k325t xc7k480t))
TILEGRID_TDB_DEPENDENCIES += orphan_int_column/$(BUILD_FOLDER)/segbits_tilegrid.tdb
@@ -85,12 +92,21 @@
iob/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
cd iob && $(MAKE)
+iob18/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
+ cd iob18 && $(MAKE)
+
iob_int/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
cd iob_int && $(MAKE)
+iob18_int/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
+ cd iob18_int && $(MAKE)
+
ioi/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
cd ioi && $(MAKE)
+ioi18/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
+ cd ioi18 && $(MAKE)
+
mmcm/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID}
cd mmcm && $(MAKE)
@@ -177,8 +193,11 @@
cd clb_int && $(MAKE) clean
cd cfg && $(MAKE) clean
cd iob && $(MAKE) clean
+ cd iob18 && $(MAKE) clean
cd iob_int && $(MAKE) clean
+ cd iob18_int && $(MAKE) clean
cd ioi && $(MAKE) clean
+ cd ioi18 && $(MAKE) clean
cd mmcm && $(MAKE) clean
cd pll && $(MAKE) clean
cd ps7_int && $(MAKE) clean
@@ -208,8 +227,11 @@
cd clb_int && $(MAKE) clean_part
cd cfg && $(MAKE) clean_part
cd iob && $(MAKE) clean_part
+ cd iob18 && $(MAKE) clean_part
cd iob_int && $(MAKE) clean_part
+ cd iob18_int && $(MAKE) clean_part
cd ioi && $(MAKE) clean_part
+ cd ioi18 && $(MAKE) clean_part
cd mmcm && $(MAKE) clean_part
cd pll && $(MAKE) clean_part
cd ps7_int && $(MAKE) clean_part
diff --git a/fuzzers/005-tilegrid/add_tdb.py b/fuzzers/005-tilegrid/add_tdb.py
index 021f14f..e483f77 100644
--- a/fuzzers/005-tilegrid/add_tdb.py
+++ b/fuzzers/005-tilegrid/add_tdb.py
@@ -94,7 +94,9 @@
int_frames, int_words = localutil.get_int_params()
tdb_fns = [
("iob", 42, 4),
+ ("iob18", 42, 4),
("ioi", 42, 4),
+ ("ioi18", 42, 4),
("mmcm", 30, 49),
("pll", 30, 27),
("monitor", 30, 101),
@@ -112,6 +114,7 @@
("gtp_channel", 32, 22),
("clb_int", int_frames, int_words),
("iob_int", int_frames, int_words),
+ ("iob18_int", int_frames, int_words),
("bram_int", int_frames, int_words),
("dsp_int", int_frames, int_words),
("fifo_int", int_frames, int_words),
diff --git a/fuzzers/005-tilegrid/generate_full.py b/fuzzers/005-tilegrid/generate_full.py
index 4022edc..454f648 100644
--- a/fuzzers/005-tilegrid/generate_full.py
+++ b/fuzzers/005-tilegrid/generate_full.py
@@ -369,7 +369,7 @@
if tile in seen_iobs:
continue
- if database[tile]["type"] not in ["LIOB33", "RIOB33"]:
+ if database[tile]["type"] not in ["LIOB33", "RIOB33", "RIOB18"]:
continue
while True:
@@ -439,7 +439,7 @@
if tile in seen_iois:
continue
- if database[tile]["type"] not in ["LIOI3", "RIOI3"]:
+ if database[tile]["type"] not in ["LIOI3", "RIOI3", "RIOI"]:
continue
while True:
diff --git a/fuzzers/005-tilegrid/iob18/Makefile b/fuzzers/005-tilegrid/iob18/Makefile
new file mode 100644
index 0000000..9251dba
--- /dev/null
+++ b/fuzzers/005-tilegrid/iob18/Makefile
@@ -0,0 +1,10 @@
+# Copyright (C) 2017-2020 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 ?= 30
+GENERATE_ARGS?="--oneval 1 --design params.csv --dframe 26 --dword 0"
+include ../fuzzaddr/common.mk
diff --git a/fuzzers/005-tilegrid/iob18/generate.tcl b/fuzzers/005-tilegrid/iob18/generate.tcl
new file mode 100644
index 0000000..d4f790b
--- /dev/null
+++ b/fuzzers/005-tilegrid/iob18/generate.tcl
@@ -0,0 +1,86 @@
+# Copyright (C) 2017-2020 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
+source "$::env(XRAY_DIR)/utils/utils.tcl"
+
+proc make_io_pin_sites {} {
+ # get all possible IOB pins
+ foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
+ set site [get_sites -of_objects $pad]
+ if {[llength $site] == 0} {
+ continue
+ }
+ if [string match IOB18* [get_property SITE_TYPE $site]] {
+ dict append io_pin_sites $site $pad
+ }
+ }
+ return $io_pin_sites
+}
+
+proc load_pin_lines {} {
+ # IOB_X0Y103 clk input
+ # IOB_X0Y129 do[0] output
+
+ set fp [open "params.csv" r]
+ gets $fp line
+
+ set pin_lines {}
+ for {gets $fp line} {$line != ""} {gets $fp line} {
+ lappend pin_lines [split $line ","]
+ }
+ close $fp
+ return $pin_lines
+}
+
+proc loc_pins {} {
+ set pin_lines [load_pin_lines]
+ set io_pin_sites [make_io_pin_sites]
+
+ puts "Looping"
+ for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
+ set line [lindex $pin_lines $idx]
+ puts "$line"
+
+ set site_str [lindex $line 2]
+ set pin_str [lindex $line 3]
+
+ # Have: site
+ # Want: pin for site
+
+ set site [get_sites $site_str]
+ set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
+ # set port [get_ports -of_objects $site]
+ set port [get_ports $pin_str]
+ set tile [get_tiles -of_objects $site]
+
+ set pin [dict get $io_pin_sites $site]
+ set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS18" $port
+ }
+}
+
+proc run {} {
+ create_project -force -part $::env(XRAY_PART) design design
+ read_verilog top.v
+ synth_design -top top
+
+ loc_pins
+
+ set_property CFGBVS GND [current_design]
+ set_property CONFIG_VOLTAGE 1.8 [current_design]
+ set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-79}]
+ set_property IS_ENABLED 0 [get_drc_checks {NSTD-1}]
+ set_property IS_ENABLED 0 [get_drc_checks {UCIO-1}]
+
+ place_design
+ route_design
+
+ write_checkpoint -force design.dcp
+ write_bitstream -force design.bit
+}
+
+run
diff --git a/fuzzers/005-tilegrid/iob18/top.py b/fuzzers/005-tilegrid/iob18/top.py
new file mode 100644
index 0000000..1e568cd
--- /dev/null
+++ b/fuzzers/005-tilegrid/iob18/top.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2020 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
+import random
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray.db import Database
+
+
+def gen_sites():
+ '''
+ IOB18S: main IOB of a diff pair
+ IOB18M: secondary IOB of a diff pair
+ IOB18: not a diff pair. Relatively rare (at least in ROI...2 of them?)
+ Focus on IOB18S to start
+ '''
+ db = Database(util.get_db_root(), util.get_part())
+ grid = db.grid()
+ for tile_name in sorted(grid.tiles()):
+ loc = grid.loc_of_tilename(tile_name)
+ gridinfo = grid.gridinfo_at_loc(loc)
+
+ for site_name, site_type in gridinfo.sites.items():
+ if site_type == 'IOB18S':
+ yield tile_name, site_name
+
+
+def write_params(params):
+ pinstr = 'tile,val,site,pin\n'
+ for tile, (site, val, pin) in sorted(params.items()):
+ pinstr += '%s,%s,%s,%s\n' % (tile, val, site, pin)
+ open('params.csv', 'w').write(pinstr)
+
+
+def run():
+ sites = list(gen_sites())
+ print(
+ '''
+`define N_DI {}
+
+module top(input wire [`N_DI-1:0] di);
+ wire [`N_DI-1:0] di_buf;
+ '''.format(len(sites)))
+
+ params = {}
+ print('''
+ (* KEEP, DONT_TOUCH *)
+ LUT6 dummy_lut();''')
+
+ for idx, ((tile_name, site_name), isone) in enumerate(zip(
+ sites, util.gen_fuzz_states(len(sites)))):
+ params[tile_name] = (site_name, isone, "di[%u]" % idx)
+ print(
+ '''
+ (* KEEP, DONT_TOUCH *)
+ IBUF #(
+ ) ibuf_{site_name} (
+ .I(di[{idx}]),
+ .O(di_buf[{idx}])
+ );'''.format(site_name=site_name, idx=idx))
+
+ if isone:
+ print(
+ '''
+ (* KEEP, DONT_TOUCH *)
+ PULLUP #(
+ ) pullup_{site_name} (
+ .O(di[{idx}])
+ );'''.format(site_name=site_name, idx=idx))
+
+ print("endmodule")
+ write_params(params)
+
+
+if __name__ == '__main__':
+ run()
diff --git a/fuzzers/005-tilegrid/iob18_int/Makefile b/fuzzers/005-tilegrid/iob18_int/Makefile
new file mode 100644
index 0000000..9f2ad50
--- /dev/null
+++ b/fuzzers/005-tilegrid/iob18_int/Makefile
@@ -0,0 +1,10 @@
+# Copyright (C) 2017-2020 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 ?= 16
+GENERATE_ARGS?="--oneval 0 --design params.csv --dframe 14 --dword 1"
+include ../fuzzaddr/common.mk
diff --git a/fuzzers/005-tilegrid/iob18_int/generate.tcl b/fuzzers/005-tilegrid/iob18_int/generate.tcl
new file mode 100644
index 0000000..3c705da
--- /dev/null
+++ b/fuzzers/005-tilegrid/iob18_int/generate.tcl
@@ -0,0 +1,82 @@
+# Copyright (C) 2017-2020 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
+source "$::env(XRAY_DIR)/utils/utils.tcl"
+
+proc make_io_pin_sites {} {
+ # get all possible IOB pins
+ foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
+ set site [get_sites -of_objects $pad]
+ if {[llength $site] == 0} {
+ continue
+ }
+ if [string match IOB18* [get_property SITE_TYPE $site]] {
+ dict append io_pin_sites $site $pad
+ }
+ }
+ return $io_pin_sites
+}
+
+proc load_pin_lines {} {
+ # IOB_X0Y103 clk input
+ # IOB_X0Y129 do[0] output
+
+ set fp [open "params.csv" r]
+ set pin_lines {}
+ for {gets $fp line} {$line != ""} {gets $fp line} {
+ lappend pin_lines [split $line ","]
+ }
+ close $fp
+ return $pin_lines
+}
+
+proc loc_pins {} {
+ set pin_lines [load_pin_lines]
+ set io_pin_sites [make_io_pin_sites]
+
+ puts "Looping"
+ for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
+ set line [lindex $pin_lines $idx]
+ puts "$line"
+
+ set site_str [lindex $line 3]
+ set pin_str [lindex $line 4]
+
+ # Have: site
+ # Want: pin for site
+
+ set site [get_sites $site_str]
+ set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
+ # set port [get_ports -of_objects $site]
+ set port [get_ports $pin_str]
+ set tile [get_tiles -of_objects $site]
+
+ set pin [dict get $io_pin_sites $site]
+ set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS18" $port
+ }
+}
+
+proc run {} {
+ create_project -force -part $::env(XRAY_PART) design design
+ read_verilog top.v
+ synth_design -top top
+
+ loc_pins
+
+ set_property CFGBVS GND [current_design]
+ set_property CONFIG_VOLTAGE 1.8 [current_design]
+ set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-79}]
+
+ place_design
+ route_design
+
+ write_checkpoint -force design.dcp
+ write_bitstream -force design.bit
+}
+
+run
diff --git a/fuzzers/005-tilegrid/iob18_int/top.py b/fuzzers/005-tilegrid/iob18_int/top.py
new file mode 100644
index 0000000..5cb360b
--- /dev/null
+++ b/fuzzers/005-tilegrid/iob18_int/top.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2020 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
+'''
+Generate a primitive to place at every I/O
+Unlike CLB tests, the LFSR for this is inside the ROI, not driving it
+'''
+
+import os
+import random
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray.db import Database
+import re
+
+
+def gen_sites():
+ '''
+ IOB18S: main IOB of a diff pair
+ IOB18M: secondary IOB of a diff pair
+ IOB18: not a diff pair. Relatively rare (at least in ROI...2 of them?)
+ Focus on IOB18S to start
+ '''
+ db = Database(util.get_db_root(), util.get_part())
+ grid = db.grid()
+ for tile_name in sorted(grid.tiles()):
+ loc = grid.loc_of_tilename(tile_name)
+ gridinfo = grid.gridinfo_at_loc(loc)
+
+ sites = []
+ for site_name, site_type in gridinfo.sites.items():
+ if site_type == 'IDELAYE2_FINEDELAY':
+ sites.append(site_name)
+
+ if len(sites) == 0:
+ continue
+
+ sites_y = [
+ int(re.match('IDELAY_X[0-9]+Y([0-9]+)', site).group(1))
+ for site in sites
+ ]
+
+ sites, _ = zip(*sorted(zip(sites, sites_y), key=lambda x: x[1]))
+
+ if gridinfo.tile_type[0] == 'L':
+ int_grid_x = loc.grid_x + 3
+ pad_grid_x = loc.grid_x - 1
+ int_tile_type = 'INT_L'
+ else:
+ int_grid_x = loc.grid_x - 3
+ pad_grid_x = loc.grid_x + 1
+ int_tile_type = 'INT_R'
+
+ int_tile_locs = [
+ (int_grid_x, loc.grid_y),
+ ]
+
+ pad_gridinfo = grid.gridinfo_at_loc((pad_grid_x, loc.grid_y))
+
+ pad_sites = pad_gridinfo.sites.keys()
+ pad_sites_y = [
+ int(re.match('IOB_X[0-9]+Y([0-9]+)', site).group(1))
+ for site in pad_sites
+ ]
+ pad_sites, _ = zip(
+ *sorted(zip(pad_sites, pad_sites_y), key=lambda x: x[1]))
+
+ if not gridinfo.tile_type.endswith("_SING"):
+ int_tile_locs.append((int_grid_x, loc.grid_y - 1))
+
+ assert len(sites) == len(int_tile_locs), (
+ tile_name, sites, int_tile_locs)
+ assert len(sites) == len(pad_sites), (sites, pad_sites)
+
+ for site_name, pad_site, int_tile_loc in zip(sites, pad_sites,
+ int_tile_locs):
+ int_tile_name = grid.tilename_at_loc(int_tile_loc)
+ assert int_tile_name.startswith(int_tile_type), (
+ int_tile_name, site_name, int_tile_loc)
+ yield int_tile_name, site_name, pad_site
+
+
+def write_params(params):
+ pinstr = ''
+ for tile, (site, val, pad_site_name, pin) in sorted(params.items()):
+ pinstr += '%s,%s,%s,%s,%s\n' % (tile, val, site, pad_site_name, pin)
+ open('params.csv', 'w').write(pinstr)
+
+
+def run():
+ sites = list(gen_sites())
+ print(
+ '''
+`define N_DI {}
+
+module top(input wire [`N_DI-1:0] di);
+ wire [`N_DI-1:0] di_buf;
+
+ (* KEEP, DONT_TOUCH, IODELAY_GROUP = "iodelays" *)
+ IDELAYCTRL idelayctrl (
+ .REFCLK()
+ );
+ '''.format(len(sites)))
+
+ params = {}
+
+ for idx, ((tile_name, site_name, pad_site_name), isone) in enumerate(zip(
+ sites, util.gen_fuzz_states(len(sites)))):
+ params[tile_name] = (site_name, isone, pad_site_name, "di[%u]" % idx)
+
+ # Force HARD0 -> GFAN1 with CNTVALUEIN4 = 0
+ # Toggle 1 pip with CNTVALUEIN3 = ?
+ print(
+ '''
+
+ // Solving for {3}
+ (* KEEP, DONT_TOUCH *)
+ IBUF ibuf_{0}(.I(di[{2}]), .O(di_buf[{2}]));
+
+ (* KEEP, DONT_TOUCH, LOC = "{0}", IODELAY_GROUP = "iodelays" *)
+ IDELAYE2 idelay_{0} (
+ .CNTVALUEIN(5'b0{1}111),
+ .IDATAIN(di_buf[{2}])
+ );
+'''.format(site_name, isone, idx, tile_name))
+
+ print("endmodule")
+ write_params(params)
+
+
+if __name__ == '__main__':
+ run()
diff --git a/fuzzers/005-tilegrid/ioi18/Makefile b/fuzzers/005-tilegrid/ioi18/Makefile
new file mode 100644
index 0000000..9fd5b94
--- /dev/null
+++ b/fuzzers/005-tilegrid/ioi18/Makefile
@@ -0,0 +1,10 @@
+# Copyright (C) 2017-2020 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 ?= 24
+GENERATE_ARGS?="--oneval 1 --design params.csv --dframe 20 --dword 3"
+include ../fuzzaddr/common.mk
diff --git a/fuzzers/005-tilegrid/ioi18/generate.tcl b/fuzzers/005-tilegrid/ioi18/generate.tcl
new file mode 100644
index 0000000..96e843a
--- /dev/null
+++ b/fuzzers/005-tilegrid/ioi18/generate.tcl
@@ -0,0 +1,88 @@
+# Copyright (C) 2017-2020 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
+source "$::env(XRAY_DIR)/utils/utils.tcl"
+
+proc make_io_pin_sites {} {
+ # get all possible IOB pins
+ foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
+ set site [get_sites -of_objects $pad]
+ if {[llength $site] == 0} {
+ continue
+ }
+ if [string match IOB18* [get_property SITE_TYPE $site]] {
+ dict append io_pin_sites $site $pad
+ }
+ }
+ return $io_pin_sites
+}
+
+proc load_pin_lines {} {
+ # IOB_X0Y103 clk input
+ # IOB_X0Y129 do[0] output
+
+ set fp [open "params.csv" r]
+ gets $fp line
+
+ set pin_lines {}
+ for {gets $fp line} {$line != ""} {gets $fp line} {
+ lappend pin_lines [split $line ","]
+ }
+ close $fp
+ return $pin_lines
+}
+
+proc loc_pins {} {
+ set pin_lines [load_pin_lines]
+ set io_pin_sites [make_io_pin_sites]
+ set package_pin_keys [dict keys $io_pin_sites]
+
+ puts "Looping"
+ for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
+ set line [lindex $pin_lines $idx]
+ puts "$line"
+
+ set site_str [lindex $line 2]
+ set pin_str [lindex $line 3]
+ set pad_str [lindex $line 4]
+
+ # Have: site
+ # Want: pin for site
+
+ set site [get_sites $site_str]
+ set port [get_ports $pin_str]
+ set tile [get_tiles -of_objects $site]
+
+
+ set pin [dict get $io_pin_sites $pad_str]
+ set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS18" $port
+ }
+}
+
+proc run {} {
+ create_project -force -part $::env(XRAY_PART) design design
+ read_verilog top.v
+ synth_design -top top
+
+ #loc_pins
+
+ set_property CFGBVS GND [current_design]
+ set_property CONFIG_VOLTAGE 1.8 [current_design]
+ set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-79}]
+ set_property SEVERITY {Warning} [get_drc_checks NSTD-1]
+ set_property SEVERITY {Warning} [get_drc_checks UCIO-1]
+ #set_property IS_ENABLED 0 [get_drc_checks {REQP-83}]
+
+ place_design
+ route_design
+
+ write_checkpoint -force design.dcp
+ write_bitstream -force design.bit
+}
+
+run
diff --git a/fuzzers/005-tilegrid/ioi18/top.py b/fuzzers/005-tilegrid/ioi18/top.py
new file mode 100644
index 0000000..be162cd
--- /dev/null
+++ b/fuzzers/005-tilegrid/ioi18/top.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2020 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
+import io
+import os
+import random
+import re
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray import lut_maker
+from prjxray import verilog
+from prjxray.db import Database
+
+
+def gen_sites():
+ db = Database(util.get_db_root(), util.get_part())
+ grid = db.grid()
+ for tile_name in sorted(grid.tiles()):
+ loc = grid.loc_of_tilename(tile_name)
+ gridinfo = grid.gridinfo_at_loc(loc)
+ if gridinfo.tile_type.endswith("_SING"):
+ continue
+ # Y9 tiles have frame address 1 frame higher than the rest
+ # Need to investigate what is so special about them
+ if tile_name.endswith("Y9"):
+ continue
+
+ sites = []
+ for site_name, site_type in gridinfo.sites.items():
+ if site_type == 'IDELAYE2_FINEDELAY':
+ yield tile_name, site_name
+
+
+def write_params(params):
+ pinstr = 'tile,isone,site\n'
+ for vals in params:
+ pinstr += ','.join(map(str, vals)) + '\n'
+
+ open('params.csv', 'w').write(pinstr)
+
+
+def use_idelay(p, luts, connects):
+ print(
+ '''
+ wire idelay_{site};
+
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ IDELAYE2_FINEDELAY #(
+ .HIGH_PERFORMANCE_MODE("{param}"),
+ .DELAY_SRC("DATAIN")
+ ) idelay_site_{site} (
+ .DATAIN({onet}),
+ .DATAOUT(idelay_{site})
+ );
+ assign {net} = idelay_{site};
+ '''.format(
+ onet=luts.get_next_output_net(),
+ net=luts.get_next_input_net(),
+ param="TRUE" if p['isone'] else "FALSE",
+ **p),
+ file=connects)
+
+
+def run():
+ luts = lut_maker.LutMaker()
+ connects = io.StringIO()
+
+ tile_params = []
+ params = []
+ sites = sorted(list(gen_sites()))
+ for idx, ((tile, site), isone) in enumerate(zip(
+ sites, util.gen_fuzz_states(len(sites)))):
+
+ p = {}
+ p['tile'] = tile
+ p['site'] = site
+ p['isone'] = isone
+ params.append(p)
+ tile_params.append((tile, p['isone'], site))
+
+ write_params(tile_params)
+
+ print('''
+module top();
+ ''')
+
+ # Always output a LUT6 to make placer happy.
+ print('''
+ (* KEEP, DONT_TOUCH *)
+ LUT6 dummy_lut();
+ ''')
+
+ # Need IDELAYCTRL for IDEALAYs
+ print('''
+ (* KEEP, DONT_TOUCH *)
+ IDELAYCTRL();
+ ''')
+
+ for p in params:
+ use_idelay(p, luts, connects)
+
+ for l in luts.create_wires_and_luts():
+ print(l)
+
+ print(connects.getvalue())
+
+ print("endmodule")
+
+
+if __name__ == '__main__':
+ run()
diff --git a/fuzzers/005-tilegrid/util.py b/fuzzers/005-tilegrid/util.py
index 0f65e00..56e18ce 100644
--- a/fuzzers/005-tilegrid/util.py
+++ b/fuzzers/005-tilegrid/util.py
@@ -96,8 +96,8 @@
max_frames = tile_frames.get_tile_frames(baseaddr)
if frames > max_frames:
print(
- "Warning: The number of frames specified for the tile {} ({}) exceeds the maximum allowed value ({}). Falling back to the maximum value."
- .format(tile_name, frames, max_frames))
+ "Warning: The number of frames for base address {} specified for the tile {} ({}) exceeds the maximum allowed value ({}). Falling back to the maximum value."
+ .format(hex(baseaddr), tile_name, frames, max_frames))
frames = max_frames
# If frames count is None then use the maximum
if frames is None:
diff --git a/fuzzers/030-iob/write_io_banks.tcl b/fuzzers/030-iob/write_io_banks.tcl
index 9ba176f..284e0fe 100644
--- a/fuzzers/030-iob/write_io_banks.tcl
+++ b/fuzzers/030-iob/write_io_banks.tcl
@@ -20,7 +20,10 @@
foreach site_type { IOB33M IOB33S IDELAYCTRL} {
foreach site [get_sites -filter "SITE_TYPE == $site_type"] {
set tile [get_tiles -of $site]
- puts $fp "$site,$tile,[get_property CLOCK_REGION $site]"
+ # exclude IDELAYCTRL from high speed banks
+ if {![string match "*_IOI_*" $tile]} {
+ puts $fp "$site,$tile,[get_property CLOCK_REGION $site]"
+ }
}
}
close $fp
diff --git a/fuzzers/030-iob18/Makefile b/fuzzers/030-iob18/Makefile
new file mode 100644
index 0000000..f90dbfd
--- /dev/null
+++ b/fuzzers/030-iob18/Makefile
@@ -0,0 +1,41 @@
+# Copyright (C) 2017-2022 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 := 80
+SPECIMENS_DEPS := build/iobanks.txt
+include ../fuzzer.mk
+
+database: build/segbits_riob18.db build/segbits_hclk_ioi.db
+
+build/iobanks.txt: write_io_banks.tcl
+ mkdir -p build
+ cd build/ && ${XRAY_VIVADO} -mode batch -source ../write_io_banks.tcl
+
+build/segbits_riob18.rdb: $(SPECIMENS_OK)
+ ${XRAY_SEGMATCH} -c 23 -o build/segbits_riob18.rdb $$(find -name segdata_riob18.txt)
+
+build/segbits_riob18.db: build/segbits_riob18.rdb process_rdb.py bits.dbf
+# delete the Y1 LVDS tags because they are empty anyway and are missing the DRIVE tag which upsets process_rdb.py
+ sed '/IOB18.IOB_Y1.LVDS/d' -i build/segbits_riob18.rdb
+ python3 process_rdb.py build/segbits_riob18.rdb > build/segbits_riob18_processed.rdb
+ ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --groups tag_groups.txt --seg-fn-in build/segbits_riob18_processed.rdb --seg-fn-out $@
+ ${XRAY_MASKMERGE} build/mask_riob18.db $$(find -name segdata_riob18.txt)
+
+build/segbits_hclk_ioi.rdb: $(SPECIMENS_OK)
+ ${XRAY_SEGMATCH} -c 10 -o build/segbits_hclk_ioi.rdb $$(find -name segdata_hclk_ioi.txt)
+
+build/segbits_hclk_ioi.db: build/segbits_hclk_ioi.rdb
+ ${XRAY_DBFIXUP} --db-root build --zero-db hclk_bits.dbf --seg-fn-in build/segbits_hclk_ioi.rdb --seg-fn-out $@
+
+pushdb:
+ ${XRAY_MERGEDB} riob18 build/segbits_riob18.db
+ ${XRAY_MERGEDB} mask_riob18 build/mask_riob18.db
+
+ ${XRAY_MERGEDB} hclk_ioi build/segbits_hclk_ioi.db
+
+.PHONY: database pushdb
+
diff --git a/fuzzers/030-iob18/README.md b/fuzzers/030-iob18/README.md
new file mode 100644
index 0000000..8b62051
--- /dev/null
+++ b/fuzzers/030-iob18/README.md
@@ -0,0 +1,20 @@
+# IOB18 Fuzzer
+
+This fuzzer solves the bits related to the IO pads in the
+high performance banks, which are present in most of the
+Kintex and Virtex devices (a notable exception are K420T and K480T)
+using bank numbers of 30 and above.
+
+These banks have a maximum voltage of 1.8V which is the reason
+why many of the BEL names end in 18 (as opposed to 33 for the
+high range banks, which run on a maximum voltage of 3.3V).
+
+Currently the focus is on supporting the most used IO standards;
+On most boards, the high performance banks are connected to DDR3
+memory and this mandates the support of single ended and differential
+SSTL15.
+Of course, all the LVCMOS variants and LVDS are a must have too.
+
+Currently unsupported are digitally controlled impedance
+(usually indicated by the regular IO standard names with a
+_DCI and _T_DCI suffix).
diff --git a/fuzzers/030-iob18/bits.dbf b/fuzzers/030-iob18/bits.dbf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fuzzers/030-iob18/bits.dbf
diff --git a/fuzzers/030-iob18/check_results.py b/fuzzers/030-iob18/check_results.py
new file mode 100644
index 0000000..5a66bfd
--- /dev/null
+++ b/fuzzers/030-iob18/check_results.py
@@ -0,0 +1,235 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+""" Sanity checks FASM output from IOB fuzzer.
+The IOB fuzzer is fairly complicated, and it's output is hard to verify by
+inspection. For this reason, check_results.py was written to compare the
+specimen's generated and their FASM output. The FASM output does pose a
+chicken and egg issue. The test procedure is a follows:
+
+1. Build the database (e.g. make -j<N> run)
+2. Build the database again (e.g. make -j<N> run)
+3. Run check_results.py
+
+The second time that the database is run, the FASM files in the specimen's
+will have the bits documented by fuzzer.
+
+"""
+import argparse
+import os
+import os.path
+from prjxray import verilog
+import json
+import generate
+
+
+def process_parts(parts):
+ if len(parts) == 0:
+ return
+
+ if parts[-1] == 'IN_ONLY':
+ yield 'type', ['IBUF', 'IBUFDS']
+
+ if len(parts) > 2 and parts[-2] == 'SLEW':
+ yield 'SLEW', verilog.quote(parts[-1])
+
+ if parts[0] == 'PULLTYPE':
+ yield 'PULLTYPE', verilog.quote(parts[1])
+
+ if len(parts) > 1 and parts[1] == 'IN':
+ yield 'IOSTANDARDS', parts[0].split('_')
+ yield 'IN', True
+
+ if len(parts) > 1 and parts[1] == 'IN_DIFF':
+ yield 'IOSTANDARDS', parts[0].split('_')
+ yield 'IN_DIFF', True
+
+ if len(parts) > 1 and parts[1] == 'DRIVE':
+ yield 'IOSTANDARDS', parts[0].split('_')
+
+ if parts[2] == 'I_FIXED':
+ yield 'DRIVES', [None]
+ else:
+ yield 'DRIVES', parts[2].split('_')
+
+
+def create_sites_from_fasm(fasm_file):
+ sites = {}
+
+ diff_tiles = set()
+
+ with open(fasm_file) as f:
+ for l in f:
+ if 'IOB18' not in l:
+ continue
+
+ parts = l.strip().split('.')
+ tile = parts[0]
+ site = parts[1]
+
+ if 'OUT_DIFF' == site:
+ diff_tiles.add(tile)
+ continue
+
+ if (tile, site) not in sites:
+ sites[(tile, site)] = {
+ 'tile': tile,
+ 'site_key': site,
+ }
+
+ if len(parts) > 3 and 'IN_DIFF' == parts[3]:
+ diff_tiles.add(tile)
+
+ for key, value in process_parts(parts[2:]):
+ sites[(tile, site)][key] = value
+
+ for key in sites:
+ if 'type' not in sites[key]:
+ if 'IOSTANDARDS' not in sites[key]:
+ sites[key]['type'] = [None]
+ else:
+ assert 'IOSTANDARDS' in sites[key], sites[key]
+ assert 'DRIVES' in sites[key], sites[key]
+
+ if 'IN' in sites[key]:
+ sites[key]['type'] = ['IOBUF', 'IOBUF_DCIEN']
+ else:
+ sites[key]['type'] = [
+ "OBUF",
+ "OBUFDS",
+ "OBUFTDS",
+ "OBUFDS_DUAL_BUF",
+ "OBUFTDS_DUAL_BUF",
+ ]
+
+ return sites, diff_tiles
+
+
+def process_specimen(fasm_file, params_json):
+ sites, diff_tiles = create_sites_from_fasm(fasm_file)
+
+ with open(params_json) as f:
+ params = json.load(f)
+
+ count = 0
+ for p in params['tiles']:
+ tile = p['tile']
+ for site in p['site'].split(' '):
+ site_y = int(site[site.find('Y') + 1:]) % 2
+
+ if generate.skip_broken_tiles(p):
+ continue
+
+ site_key = 'IOB_Y{}'.format(site_y)
+
+ if (tile, site_key) not in sites:
+ assert p['type'] is None, p
+ continue
+
+ site_from_fasm = sites[(tile, site_key)]
+
+ if site_y == 0 or tile not in diff_tiles:
+ assert p['type'] in site_from_fasm['type'], (
+ tile, site_key, p['type'], site_from_fasm['type'])
+ else:
+ # Y1 on DIFF tiles is always none.
+ assert p['type'] is None, p
+
+ if p['type'] is None:
+ continue
+
+ assert 'PULLTYPE' in p, p
+ assert 'PULLTYPE' in site_from_fasm, site_from_fasm
+
+ if verilog.unquote(p['PULLTYPE']) == '':
+ # Default is None.
+ pulltype = verilog.quote('NONE')
+ else:
+ pulltype = p['PULLTYPE']
+
+ assert pulltype == site_from_fasm['PULLTYPE'], (
+ tile, site_key, p, site_from_fasm)
+
+ assert 'IOSTANDARDS' in site_from_fasm, (tile, site)
+
+ iostandard = verilog.unquote(p['IOSTANDARD'])
+ if iostandard.startswith('DIFF_'):
+ iostandard = iostandard[5:]
+
+ assert iostandard in site_from_fasm['IOSTANDARDS'], (
+ p['IOSTANDARD'],
+ site_from_fasm['IOSTANDARDS'],
+ )
+
+ if p['type'] not in ['IBUF', 'IBUFDS']:
+ if verilog.unquote(p['SLEW']) == '':
+ # Default is None.
+ slew = verilog.quote('SLOW')
+ else:
+ slew = p['SLEW']
+
+ assert slew == site_from_fasm['SLEW'], (
+ tile, site_key, p, site_from_fasm)
+
+ assert 'DRIVES' not in p, p
+ assert 'DRIVES' in site_from_fasm, (
+ tile, site, p['type'], site_from_fasm)
+
+ if p['DRIVE'] is None:
+ assert None in site_from_fasm['DRIVES'], (
+ tile, site_key, p['DRIVE'], site_from_fasm['DRIVES'])
+ elif p['DRIVE'] == '':
+ if None in site_from_fasm['DRIVES']:
+ # IOSTANDARD has not DRIVE setting, ignore
+ pass
+ else:
+ # Check that drive is at default
+ assert 'I12' in site_from_fasm['DRIVES'], (
+ tile, site_key, p['DRIVE'],
+ site_from_fasm['DRIVES'])
+ else:
+ assert 'I{}'.format(
+ p['DRIVE']) in site_from_fasm['DRIVES'], (
+ tile, site_key, p['DRIVE'],
+ site_from_fasm['DRIVES'])
+
+ count += 1
+
+ return count
+
+
+def scan_specimens():
+ for root, dirs, files in os.walk('build'):
+ if os.path.basename(root).startswith('specimen_'):
+ print('Processing', os.path.basename(root))
+ process_specimen(
+ fasm_file=os.path.join(root, 'design.fasm'),
+ params_json=os.path.join(root, 'params.json'))
+
+ print('No errors found!')
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Verify IOB FASM vs BELs.")
+
+ parser.add_argument('--fasm')
+ parser.add_argument('--params')
+
+ args = parser.parse_args()
+
+ if not args.fasm and not args.params:
+ scan_specimens()
+ else:
+ count = process_specimen(fasm_file=args.fasm, params_json=args.params)
+ print('No errors found in {} IO sites'.format(count))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/030-iob18/generate.py b/fuzzers/030-iob18/generate.py
new file mode 100644
index 0000000..fc0af32
--- /dev/null
+++ b/fuzzers/030-iob18/generate.py
@@ -0,0 +1,298 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+
+from prjxray.segmaker import Segmaker
+from prjxray import segmaker
+from prjxray import verilog
+import os
+import json
+import csv
+
+from iostandards import *
+
+def bitfilter(frame, word):
+ return 38 <= frame
+
+def mk_drive_opt(iostandard, drive):
+ if drive is None:
+ drive = '_FIXED'
+ return '{}.DRIVE.I{}'.format(iostandard, drive)
+
+def drives_for_iostandard(iostandard):
+ if iostandard in ['LVCMOS18', 'LVCMOS15']:
+ drives = [2, 4, 6, 8, 12, 16]
+ elif iostandard == 'LVCMOS12':
+ drives = [2, 4, 6, 8]
+ elif iostandard in SSTL + DIFF_SSTL:
+ return ['_FIXED']
+ else:
+ assert False, "this line should be unreachable"
+
+ return drives
+
+STEPDOWN_IOSTANDARDS = LVCMOS + SSTL
+IBUF_LOW_PWR_SUPPORTED = LVDS + DIFF_SSTL
+ONLY_DIFF_IOSTANDARDS = LVDS
+
+
+def main():
+ # Create map of iobank -> sites
+ iobanks = {}
+ site_to_iobank = {}
+ iobank_iostandards = {}
+ with open(os.path.join(os.getenv('FUZDIR'), 'build', 'iobanks.txt')) as f:
+ for l in f:
+ iob_site, iobank = l.strip().split(',')
+ iobank = int(iobank)
+
+ if iobank not in iobanks:
+ iobanks[iobank] = set()
+
+ iobanks[iobank].add(iob_site)
+ assert iob_site not in site_to_iobank
+ site_to_iobank[iob_site] = iobank
+
+ for iobank in iobanks:
+ iobank_iostandards[iobank] = set()
+
+ # Load a list of PUDC_B pin function tiles. They are configured differently
+ # by the vendor tools so need to be skipped
+ pudc_tiles = set()
+ with open(os.path.join(os.getenv('FUZDIR'), 'build',
+ 'pudc_sites.csv')) as f:
+ for l in csv.DictReader(f):
+ pudc_tiles.add(l["tile"])
+
+ print("Loading tags")
+ segmk = Segmaker("design.bits")
+ '''
+ port,site,tile,pin,slew,drive,pulltype
+ di[0],IOB_X1Y107,RIOB18_X1Y107,AF4,PULLDOWN
+ di[10],IOB_X1Y147,RIOB18_X1Y147,U5,PULLUP
+ '''
+ with open('params.json', 'r') as f:
+ design = json.load(f)
+
+ diff_pairs = set()
+ for d in design['tiles']:
+ iostandard = verilog.unquote(d['IOSTANDARD'])
+ if iostandard.startswith('DIFF_'):
+ diff_pairs.add(d['pair_site'])
+
+ for d in design['tiles']:
+ site = d['site']
+ tile = d['tile']
+
+ if tile in pudc_tiles:
+ continue
+
+ if site in diff_pairs:
+ continue
+
+ iostandard = verilog.unquote(d['IOSTANDARD'])
+ if iostandard.startswith('DIFF_'):
+ iostandard = iostandard[5:]
+
+ iobank_iostandards[site_to_iobank[site]].add(iostandard)
+
+ only_diff_io = iostandard in ONLY_DIFF_IOSTANDARDS
+
+ if d['type'] is None:
+ segmk.add_site_tag(site, 'INOUT', 0)
+ segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.IN_ONLY'.format(iostandard), 0)
+ elif d['type'] == 'IBUF':
+ segmk.add_site_tag(site, 'INOUT', 0)
+ segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN_DIFF'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.IN_ONLY'.format(iostandard), 1)
+ segmk.add_tile_tag(tile, 'IN_DIFF', 0)
+
+ if iostandard in IBUF_LOW_PWR_SUPPORTED:
+ segmk.add_site_tag(site, 'IBUF_LOW_PWR', d['IBUF_LOW_PWR'])
+ segmk.add_site_tag(site, 'ZIBUF_LOW_PWR', 1 ^ d['IBUF_LOW_PWR'])
+
+ elif d['type'] == 'IBUFDS':
+ psite = d['pair_site']
+ segmk.add_site_tag(site, 'INOUT', 0)
+ segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN_DIFF'.format(iostandard), 1)
+ segmk.add_site_tag(psite, '{}.IN_DIFF'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.IN_ONLY'.format(iostandard), 1)
+ segmk.add_tile_tag(tile, 'IN_DIFF', 1)
+
+ if iostandard in IBUF_LOW_PWR_SUPPORTED:
+ segmk.add_tile_tag(tile, 'DIFF.IBUF_LOW_PWR', d['IBUF_LOW_PWR'])
+ segmk.add_tile_tag(tile, 'DIFF.ZIBUF_LOW_PWR', 1 ^ d['IBUF_LOW_PWR'])
+
+ elif d['type'] == 'OBUF':
+ segmk.add_site_tag(site, 'INOUT', 0)
+ segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
+ segmk.add_tile_tag(tile, 'OUT_DIFF', 0)
+
+ elif d['type'] == 'OBUFDS':
+ segmk.add_site_tag(site, 'INOUT', 0)
+ segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
+ segmk.add_tile_tag(tile, 'OUT_DIFF', 1 and not only_diff_io)
+ segmk.add_tile_tag(tile, 'OUT_TDIFF', 0)
+
+ elif d['type'] == 'OBUFTDS':
+ segmk.add_site_tag(site, 'INOUT', 0)
+ segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN'.format(iostandard), 0)
+ segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
+ segmk.add_tile_tag(tile, 'OUT_DIFF', 1 and not only_diff_io)
+ segmk.add_tile_tag(tile, 'OUT_TDIFF', 1 and not only_diff_io)
+
+ elif d['type'] == 'IOBUF_DCIEN':
+ segmk.add_site_tag(site, 'INOUT', 1)
+ segmk.add_site_tag(site, '{}.IN_USE'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.IN'.format(iostandard), 1)
+ segmk.add_site_tag(site, '{}.OUT'.format(iostandard), 1)
+
+
+ if d['type'] is not None:
+ segmaker.add_site_group_zero(
+ segmk, site, "PULLTYPE.",
+ ("NONE", "KEEPER", "PULLDOWN", "PULLUP"), "PULLDOWN",
+ verilog.unquote(d['PULLTYPE']))
+
+ if d['type'] in [None, 'IBUF', 'IBUFDS']:
+ continue
+
+ drive_opts = set()
+ for opt in LVCMOS:
+ for drive_opt in ("2", "4", "6", "8", "12", "16"):
+ if drive_opt in ["12", "16"] and opt == "LVCMOS12":
+ continue
+
+ drive_opts.add(mk_drive_opt(opt, drive_opt))
+
+ for sstl in SSTL:
+ drive_opts.add(mk_drive_opt(sstl, None))
+
+ drive_opts.add(mk_drive_opt("LVDS", None))
+
+ segmaker.add_site_group_zero(
+ segmk, site, '', drive_opts, mk_drive_opt('LVCMOS25', '12'),
+ mk_drive_opt(iostandard, d['DRIVE']))
+
+ if d['SLEW']:
+ for opt in ["SLOW", "FAST"]:
+ segmk.add_site_tag(
+ site, iostandard + ".SLEW." + opt,
+ opt == verilog.unquote(d['SLEW']))
+
+ if 'ibufdisable_wire' in d:
+ segmk.add_site_tag(
+ site, 'IBUFDISABLE.I', d['ibufdisable_wire'] != '0')
+
+ if 'dcitermdisable_wire' in d:
+ segmk.add_site_tag(
+ site, 'DCITERMDISABLE.I', d['dcitermdisable_wire'] != '0')
+
+ site_to_cmt = {}
+ site_to_tile = {}
+ tile_to_cmt = {}
+ cmt_to_idelay = {}
+ with open(os.path.join(os.getenv('FUZDIR'), 'build', 'cmt_regions.csv')) as f:
+ for l in f:
+ site, tile, cmt = l.strip().split(',')
+ site_to_tile[site] = tile
+
+ site_to_cmt[site] = cmt
+ tile_to_cmt[tile] = cmt
+
+ # Given IDELAYCTRL's are only located in HCLK_IOI tiles, and
+ # there is only on HCLK_IOI tile per CMT, update
+ # CMT -> IDELAYCTRL / tile map.
+ if 'IDELAYCTRL' in site:
+ assert cmt not in cmt_to_idelay
+ cmt_to_idelay[cmt] = site, tile
+
+ # For each IOBANK with an active VREF set the feature
+ cmt_vref_active = set()
+ with open('iobank_vref.csv') as f:
+ for l in f:
+ iobank, vref = l.strip().split(',')
+ iobank = int(iobank)
+
+ cmt = None
+ for cmt_site in iobanks[iobank]:
+ if cmt_site in site_to_cmt:
+ cmt = site_to_cmt[cmt_site]
+ break
+
+ if cmt is None:
+ continue
+
+ cmt_vref_active.add(cmt)
+
+ _, hclk_cmt_tile = cmt_to_idelay[cmt]
+
+ opt = 'VREF.V_{:d}_MV'.format(int(float(vref) * 1000))
+ segmk.add_tile_tag(hclk_cmt_tile, opt, 1)
+
+ for iobank in iobank_iostandards:
+ if len(iobank_iostandards[iobank]) == 0:
+ continue
+
+ for cmt_site in iobanks[iobank]:
+ if cmt_site in site_to_cmt:
+ cmt = site_to_cmt[cmt_site]
+ break
+
+ if cmt is None:
+ continue
+
+ _, hclk_cmt_tile = cmt_to_idelay[cmt]
+
+ assert len(iobank_iostandards[iobank]) == 1, iobank_iostandards[iobank]
+
+ iostandard = list(iobank_iostandards[iobank])[0]
+ for only_diff_io in ONLY_DIFF_IOSTANDARDS:
+ segmk.add_tile_tag(
+ hclk_cmt_tile, '{}_IN_USE'.format(only_diff_io),
+ iostandard == only_diff_io)
+
+ segmk.add_tile_tag(
+ hclk_cmt_tile, 'ONLY_DIFF_IN_USE',
+ iostandard in ONLY_DIFF_IOSTANDARDS)
+
+ # For IOBANK's with no active VREF, clear all VREF options.
+ for cmt, (_, hclk_cmt_tile) in cmt_to_idelay.items():
+ if cmt in cmt_vref_active:
+ continue
+
+ for vref in (
+ .600,
+ .675,
+ .75,
+ .90,
+ ):
+ opt = 'VREF.V_{:d}_MV'.format(int(vref * 1000))
+ segmk.add_tile_tag(hclk_cmt_tile, opt, 0)
+
+ segmk.compile(bitfilter=bitfilter)
+ segmk.write(allow_empty=True)
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/030-iob18/generate.tcl b/fuzzers/030-iob18/generate.tcl
new file mode 100644
index 0000000..9534624
--- /dev/null
+++ b/fuzzers/030-iob18/generate.tcl
@@ -0,0 +1,122 @@
+# Copyright (C) 2017-2022 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
+source "$::env(XRAY_DIR)/utils/utils.tcl"
+
+proc make_io_pin_sites {} {
+ # get all possible IOB pins
+ foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
+ set site [get_sites -of_objects $pad]
+ if {[llength $site] == 0} {
+ continue
+ }
+ if [string match IOB18* [get_property SITE_TYPE $site]] {
+ dict append io_pin_sites $site $pad
+ }
+ }
+ return $io_pin_sites
+}
+
+proc load_pin_lines {} {
+ # IOB_X0Y103 clk input
+ # IOB_X0Y129 do[0] output
+
+ set fp [open "params.csv" r]
+ gets $fp line
+
+ set pin_lines {}
+ for {gets $fp line} {$line != ""} {gets $fp line} {
+ lappend pin_lines [split $line ","]
+ }
+ close $fp
+ return $pin_lines
+}
+
+proc loc_pins {} {
+ set pin_lines [load_pin_lines]
+ set io_pin_sites [make_io_pin_sites]
+
+ puts "Looping"
+ for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
+ set line [lindex $pin_lines $idx]
+ puts "$line"
+
+ set site_str [lindex $line 1]
+ set pin_str [lindex $line 2]
+ set iostandard [lindex $line 3]
+ set drive [lindex $line 4]
+ set slew [lindex $line 5]
+ set pulltype [lindex $line 6]
+
+ # Have: site
+ # Want: pin for site
+
+ set site [get_sites $site_str]
+ set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
+ # set port [get_ports -of_objects $site]
+ set port [get_ports $pin_str]
+ set tile [get_tiles -of_objects $site]
+
+ set pin [dict get $io_pin_sites $site]
+
+ set props {}
+ lappend props PACKAGE_PIN $pin
+ lappend props IOSTANDARD $iostandard
+ lappend props PULLTYPE $pulltype
+
+ if {$drive != "None"} {
+ lappend props DRIVE $drive
+ }
+
+ if {$slew != "None"} {
+ lappend props SLEW $slew
+ }
+
+ puts $props
+
+ set_property -dict "$props" $port
+ }
+}
+
+proc set_vref {} {
+ set fp [open "iobank_vref.csv" r]
+ for {gets $fp line} {$line != ""} {gets $fp line} {
+ set parts [split $line ","]
+ set iobank [lindex $parts 0]
+ set vref [lindex $parts 1]
+ puts "setting $iobank ([get_iobanks $iobank]) to INTERNAL_VREF $vref"
+ set_property INTERNAL_VREF $vref [get_iobanks $iobank]
+ }
+}
+
+proc run {} {
+ create_project -force -part $::env(XRAY_PART) design design
+ read_verilog top.v
+ synth_design -top top
+
+ loc_pins
+ set_vref
+
+ set_property CFGBVS GND [current_design]
+ set_property CONFIG_VOLTAGE 1.8 [current_design]
+ set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
+ 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-144}]
+ set_property IS_ENABLED 0 [get_drc_checks {AVAL-74}]
+
+ write_checkpoint -force design_pre_place.dcp
+
+ place_design
+ route_design
+
+ write_checkpoint -force design.dcp
+ write_bitstream -force design.bit
+}
+
+run
diff --git a/fuzzers/030-iob18/hclk_bits.dbf b/fuzzers/030-iob18/hclk_bits.dbf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fuzzers/030-iob18/hclk_bits.dbf
diff --git a/fuzzers/030-iob18/iostandards.py b/fuzzers/030-iob18/iostandards.py
new file mode 100644
index 0000000..c657763
--- /dev/null
+++ b/fuzzers/030-iob18/iostandards.py
@@ -0,0 +1,17 @@
+LVCMOS = ['LVCMOS12', 'LVCMOS15', 'LVCMOS18']
+
+# TODO: add support for digitally controlled impedance (_DCI) and termination (_T)
+SSTL = ['SSTL15', #'SSTL15_DCI', 'SSTL15_T_DCI'
+ 'SSTL135', #'SSTL135_DCI', 'SSTL135_T_DCI'
+ 'SSTL12', #'SSTL12_DCI', 'SSTL12_T_DCI'
+ ]
+
+# TODO: add support for digitally controlled impedance (_DCI) and termination (_T)
+DIFF_SSTL15 = ['DIFF_SSTL15', ] # 'DIFF_SSTL15_DCI', 'DIFF_SSTL15_T_DCI']
+DIFF_SSTL135 = ['DIFF_SSTL135', ] # 'DIFF_SSTL135_DCI', 'DIFF_SSTL135_T_DCI']
+DIFF_SSTL12 = ['DIFF_SSTL12', ] # 'DIFF_SSTL12_DCI', 'DIFF_SSTL12_T_DCI']
+DIFF_SSTL = DIFF_SSTL15 + DIFF_SSTL135 + DIFF_SSTL12
+
+LVDS = ['LVDS']
+
+DIFF = DIFF_SSTL + LVDS
\ No newline at end of file
diff --git a/fuzzers/030-iob18/process_rdb.py b/fuzzers/030-iob18/process_rdb.py
new file mode 100644
index 0000000..2cacb46
--- /dev/null
+++ b/fuzzers/030-iob18/process_rdb.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+""" IOB bits are more complicated than can be easily expressed to segmaker.
+There are couple cases that need to be handled here:
+
+- There are some bits that are always set for IN-only ports, but are cleared
+ selectively for OUT and INOUT ports.
+- There are bits per each IOSTANDARD, in addition to drive patterns. These
+ can be merged to provide unique "(IOSTANDARD, DRIVE)" bit sets.
+"""
+import argparse
+
+
+def get_name(l):
+ parts = l.strip().split(' ')
+ return parts[0]
+
+
+def get_site(l):
+ return get_name(l).split('.')[1]
+
+
+def parse_bits(l):
+ parts = l.strip().split(' ')
+ if parts[1] in ['<0', '<const0>', '<const1>']:
+ return frozenset()
+ else:
+ return frozenset(parts[1:])
+
+
+def filter_negbits(site, feature, bits):
+ lvds_bits = frozenset(['!38_24', "!38_48", "!39_33", '!39_47', '!39_49'])
+ if "IOB_Y0" in feature and not "LVDS" in feature:
+ bits = bits.difference(lvds_bits)
+ if feature.endswith("IOB_Y0.LVCMOS12_LVCMOS15_LVCMOS18.IN"):
+ bits = bits.difference(frozenset(['!39_01']))
+ if feature.endswith("IOB_Y1.LVCMOS12_LVCMOS15_LVCMOS18.IN"):
+ bits = bits.difference(frozenset(['!38_126']))
+
+ return bits
+
+
+def process_features_sets(iostandard_lines):
+ sites = {}
+
+ for iostd_type, iostd_list in iostandard_lines.items():
+ for iostd_line in iostd_list:
+ feature = get_name(iostd_line)
+ feature_parts = feature.split('.')
+ site = get_site(iostd_line)
+ iostandard = feature_parts[2]
+
+ bits = parse_bits(iostd_line)
+
+ key = (site, iostd_type)
+ if key not in sites:
+ sites[key] = {}
+
+ group = feature_parts[3]
+ if group not in sites[key]:
+ sites[key][group] = {}
+
+ if group in ['DRIVE', 'SLEW']:
+ enum = feature_parts[4]
+ sites[key][group][(iostandard, enum)] = bits
+ elif group in ['IN', 'IN_DIFF', 'IN_ONLY', 'IN_USE', 'OUT',
+ 'STEPDOWN', 'ZIBUF_LOW_PWR']:
+ sites[key][group][(iostandard, None)] = bits
+ else:
+ assert False, group
+
+ for site in sites:
+ for iostandard, enum in sites[site]['DRIVE']:
+ sites[site]['DRIVE'][(iostandard, enum)] |= sites[site]['OUT'][(
+ iostandard, None)]
+
+ for iostandard, enum in sites[site]['IN']:
+ sites[site]['IN_ONLY'][(iostandard, enum)] -= sites[site]['IN'][(
+ iostandard, enum)]
+
+ common_bits = {}
+ for site, iostd_type in sites:
+ for group in sites[(site, iostd_type)]:
+ if (site, group) not in common_bits:
+ common_bits[(site, group)] = set()
+
+ for bits in sites[(site, iostd_type)][group].values():
+ common_bits[(site, group)] |= bits
+
+ slew_in_drives = {}
+
+ for site, iostd_type in sites:
+ common_bits[(site, 'IN')] |= common_bits[(site, 'IN_DIFF')]
+ common_bits[(site, 'IN_DIFF')] |= common_bits[(site, 'IN')]
+
+ # Only DIFF IOSTANDARDS such as LVDS or TMDS do not have DRIVE or SLEW features
+ if iostd_type == "NORMAL":
+ key = (site, iostd_type)
+ common_bits[(site, 'DRIVE')] -= common_bits[(site, 'SLEW')]
+ common_bits[(site, 'IN_ONLY')] |= common_bits[(site, 'DRIVE')]
+
+ for iostandard, enum in sites[key]['DRIVE']:
+ slew_in_drive = common_bits[
+ (site, 'SLEW')] & sites[key]['DRIVE'][(iostandard, enum)]
+ if slew_in_drive:
+ if (key, iostandard) not in slew_in_drives:
+ slew_in_drives[(key, iostandard)] = set()
+
+ slew_in_drives[(key, iostandard)] |= slew_in_drive
+ sites[key]['DRIVE'][(iostandard, enum)] -= slew_in_drive
+
+ for site, iostandard in slew_in_drives:
+ for _, enum in sites[site]['SLEW']:
+ sites[site]['SLEW'][(iostandard,
+ enum)] |= slew_in_drives[(site, iostandard)]
+
+ for site in sites:
+ for iostandard, enum in sites[site]['DRIVE']:
+ sites[site]['DRIVE'][(iostandard, enum)] |= sites[site]['IN_USE'][(
+ iostandard, None)]
+
+ for iostandard, enum in sites[site]['IN']:
+ _, iostd_type = site
+ if iostd_type == "ONLY_DIFF":
+ sites[site]['IN_DIFF'][(iostandard, enum)] = \
+ sites[site]['IN'][(iostandard, enum)]
+ elif sites[site]['IN_DIFF'][(iostandard, enum)]:
+ sites[site]['IN_DIFF'][(iostandard, enum)] |= \
+ sites[site]['IN'][(iostandard, enum)]
+
+ for site, iostd_type in sites:
+ if iostd_type == "NORMAL":
+ del sites[(site, iostd_type)]['OUT']
+
+ allow_zero = ['SLEW']
+
+ common_groups = dict()
+ for site, iostd_type in sites:
+ if site not in common_groups:
+ common_groups[site] = dict()
+
+ key = (site, iostd_type)
+ for group in sites[key]:
+ if iostd_type == "ONLY_DIFF" and group == "IN":
+ continue
+
+ # Merge features that are identical.
+ #
+ # For example:
+ #
+ # IOB18.IOB_Y1.LVCMOS15.IN 38_42 39_41
+ # IOB18.IOB_Y1.LVCMOS18.IN 38_42 39_41
+ #
+ # Must be grouped.
+ for (iostandard, enum), bits in sites[key][group].items():
+ if (bits, group) not in common_groups[site]:
+ common_groups[site][(bits, group)] = {
+ 'IOSTANDARDS': set(),
+ 'enums': set(),
+ }
+
+ common_groups[site][(bits,
+ group)]['IOSTANDARDS'].add(iostandard)
+ if enum is not None:
+ common_groups[site][(bits, group)]['enums'].add(enum)
+
+ visited_iostandards = list()
+ for site, groups in common_groups.items():
+ for (bits, group), v in groups.items():
+ iostandards = v['IOSTANDARDS']
+ enums = v['enums']
+
+ # It happens that some features appear only in one of the IOB sites and not
+ # in the other. This makes it hard to assign the correct features to the correct
+ # site in the P&R toolchain.
+ #
+ # The following code makes sure that the same set of iostandards
+ # (even if not really present at a site location) appears for each site
+ for visited_iostandard, visited_group, visited_enums in visited_iostandards:
+ same_enum = enums == visited_enums
+ same_group = group == visited_group
+ compatible_iostd = any(
+ x in iostandards for x in visited_iostandard)
+ take_visited_iostd = len(visited_iostandard) > len(iostandards)
+ if same_enum and same_group and compatible_iostd and take_visited_iostd:
+ iostandards = visited_iostandard
+ break
+
+ visited_iostandards.append((iostandards, group, enums))
+
+ iostandards_string = '_'.join(sorted(iostandards))
+
+ if enums:
+ feature = 'IOB18.{site}.{iostandards}.{group}.{enums}'.format(
+ site=site,
+ iostandards=iostandards_string,
+ group=group,
+ enums='_'.join(sorted(enums)),
+ )
+ else:
+ feature = 'IOB18.{site}.{iostandards}.{group}'.format(
+ site=site,
+ iostandards=iostandards_string,
+ group=group,
+ )
+
+ if not bits and group not in allow_zero:
+ continue
+
+ neg_bits = frozenset(
+ '!{}'.format(b) for b in (common_bits[(site, group)] - bits))
+ neg_bits = filter_negbits(site, feature, neg_bits)
+ print('{} {}'.format(feature, ' '.join(sorted(bits | neg_bits))))
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Convert IOB rdb into good rdb."
+ "")
+ parser.add_argument('input_rdb')
+
+ args = parser.parse_args()
+
+ iostandard_lines = {
+ "NORMAL": list(),
+ "ONLY_DIFF": list(),
+ }
+
+ with open(args.input_rdb) as f:
+ for l in f:
+ if ('.SSTL' in l or '.LVCMOS' in l
+ or '.LVTTL' in l) and 'IOB_' in l:
+ iostandard_lines["NORMAL"].append(l)
+ elif ('.TMDS' in l or 'LVDS' in l):
+ iostandard_lines["ONLY_DIFF"].append(l)
+ else:
+ print(l.strip())
+
+ process_features_sets(iostandard_lines)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/030-iob18/tag_groups.txt b/fuzzers/030-iob18/tag_groups.txt
new file mode 100644
index 0000000..83bfc45
--- /dev/null
+++ b/fuzzers/030-iob18/tag_groups.txt
@@ -0,0 +1,2 @@
+IOB18.IOB_Y0.PULLTYPE.KEEPER IOB18.IOB_Y0.PULLTYPE.NONE IOB18.IOB_Y0.PULLTYPE.PULLDOWN IOB18.IOB_Y0.PULLTYPE.PULLUP
+IOB18.IOB_Y1.PULLTYPE.KEEPER IOB18.IOB_Y1.PULLTYPE.NONE IOB18.IOB_Y1.PULLTYPE.PULLDOWN IOB18.IOB_Y1.PULLTYPE.PULLUP
diff --git a/fuzzers/030-iob18/top.py b/fuzzers/030-iob18/top.py
new file mode 100644
index 0000000..e8f3980
--- /dev/null
+++ b/fuzzers/030-iob18/top.py
@@ -0,0 +1,425 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+import io
+import os
+import random
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray import lut_maker
+from prjxray import verilog
+from prjxray.db import Database
+
+from iostandards import *
+
+def gen_sites():
+ '''
+ IOB18S: main IOB of a diff pair
+ IOB18M: secondary IOB of a diff pair
+ IOB18: not a diff pair. Relatively rare (at least in ROI...2 of them?)
+ Focus on IOB18S to start
+ '''
+ db = Database(util.get_db_root(), util.get_part())
+ grid = db.grid()
+ for tile_name in sorted(grid.tiles()):
+ loc = grid.loc_of_tilename(tile_name)
+ gridinfo = grid.gridinfo_at_loc(loc)
+
+ sites = {}
+ for site_name, site_type in gridinfo.sites.items():
+ if site_type in ['IOB18S', 'IOB18M']:
+ sites[site_type] = site_name
+
+ if sites:
+ yield tile_name, sites
+
+
+def write_params(params):
+ pinstr = 'tile,site,pin,iostandard,drive,slew,pulltype\n'
+ for vals in params:
+ pinstr += ','.join(map(str, vals)) + '\n'
+
+ open('params.csv', 'w').write(pinstr)
+
+
+def run():
+ tile_types = ['IBUF', 'OBUF', 'IOBUF_DCIEN', None, None]
+
+ i_idx = 0
+ o_idx = 0
+ io_idx = 0
+
+ iostandards = LVCMOS + SSTL + LVDS
+
+ diff_map = {
+ "SSTL15": DIFF_SSTL15,
+ "SSTL135": DIFF_SSTL135,
+ "SSTL12": DIFF_SSTL12,
+ }
+
+ only_diff_map = {
+ "LVDS": ["LVDS"],
+ }
+
+ slews = ['FAST', 'SLOW']
+ pulls = ["NONE", "KEEPER", "PULLDOWN", "PULLUP"]
+
+ luts = lut_maker.LutMaker()
+
+ connects = io.StringIO()
+
+ tile_params = []
+ params = {
+ "tiles": [],
+ 'INTERNAL_VREF': {},
+ }
+
+ with open(os.path.join(os.getenv('FUZDIR'), 'build', 'iobanks.txt')) as f:
+ iobanks = set()
+ iob_sites = dict()
+ for l in f:
+ fields = l.split(',')
+ iob_site = fields[0]
+ iobank = fields[1].rstrip()
+
+ iobanks.add(iobank)
+ iob_sites[iob_site] = iobank
+
+ params['iobanks'] = iobanks
+
+ iostandard_map = dict()
+ for iobank in iobanks:
+ iostandard = random.choice(iostandards)
+ if iostandard in SSTL:
+ params['INTERNAL_VREF'][iobank] = random.choice(
+ (
+ .600,
+ .675,
+ .75,
+ .90,
+ ))
+
+ iostandard_map[iobank] = iostandard
+
+ params['iobanks'] = list(iobanks)
+
+ any_idelay = False
+ for tile, sites in gen_sites():
+ iostandard = None
+
+ site_bels = {}
+ for site_type, site_name in sites.items():
+ iobank = iob_sites[site_name]
+ iostandard = iostandard_map[iobank]
+
+ if iostandard in ['LVCMOS12']:
+ drives = [2, 4, 6, 8]
+ elif iostandard in ['LVCMOS15', 'LVCMOS18']:
+ drives = [2, 4, 6, 8, 12, 16]
+ elif iostandard in LVDS + SSTL:
+ drives = None
+ else:
+ assert False, f"Unhandled iostandard: {iostandard}"
+
+ if site_type.endswith('M'):
+ if iostandard in diff_map:
+ site_bels[site_type] = random.choice(
+ tile_types + ['IBUFDS', 'OBUFDS', 'OBUFTDS'])
+ elif iostandard in only_diff_map:
+ site_bels[site_type] = random.choice(
+ ['IBUFDS', 'OBUFDS', 'OBUFTDS', None, None])
+ else:
+ site_bels[site_type] = random.choice(tile_types)
+ is_m_diff = site_bels[site_type] is not None and site_bels[
+ site_type].endswith('DS')
+ else:
+ site_bels[site_type] = random.choice(tile_types)
+
+ if is_m_diff or iostandard in only_diff_map:
+ site_bels['IOB18S'] = None
+
+ for site_type, site in sites.items():
+ p = {}
+ p['tile'] = tile
+ p['site'] = site
+ p['type'] = site_bels[site_type]
+
+ if p['type'] is not None and p['type'].endswith('DS'):
+ if iostandard in diff_map:
+ iostandard_site = random.choice(diff_map[iostandard])
+ elif iostandard in only_diff_map:
+ iostandard_site = random.choice(only_diff_map[iostandard])
+ p['pair_site'] = sites['IOB18S']
+ else:
+ iostandard_site = iostandard
+
+ p['IOSTANDARD'] = verilog.quote(iostandard_site)
+ p['PULLTYPE'] = verilog.quote(random.choice(pulls))
+
+ if p['type'] is None:
+ p['pad_wire'] = None
+ elif p['type'] == 'IBUF':
+ p['pad_wire'] = 'di[{}]'.format(i_idx)
+ p['IDELAY_ONLY'] = random.randint(0, 1)
+ if not p['IDELAY_ONLY']:
+ p['owire'] = luts.get_next_input_net()
+ else:
+ any_idelay = True
+ p['owire'] = 'idelay_{site}'.format(**p)
+
+ p['DRIVE'] = None
+ p['SLEW'] = None
+ p['IBUF_LOW_PWR'] = random.randint(0, 1)
+ i_idx += 1
+ elif p['type'] == 'IBUFDS':
+ p['pad_wire'] = 'di[{}]'.format(i_idx)
+ i_idx += 1
+ p['bpad_wire'] = 'di[{}]'.format(i_idx)
+ i_idx += 1
+
+ p['IDELAY_ONLY'] = random.randint(0, 1)
+ p['DIFF_TERM'] = random.randint(0, 1) if iostandard in LVDS else 0
+ if not p['IDELAY_ONLY']:
+ p['owire'] = luts.get_next_input_net()
+ else:
+ any_idelay = True
+ p['owire'] = 'idelay_{site}'.format(**p)
+
+ p['DRIVE'] = None
+ p['SLEW'] = None
+ p['IBUF_LOW_PWR'] = random.randint(0, 1)
+
+ elif p['type'] == 'OBUF':
+ p['pad_wire'] = 'do[{}]'.format(o_idx)
+ p['iwire'] = luts.get_next_output_net()
+ if drives is not None:
+ p['DRIVE'] = random.choice(drives)
+ else:
+ p['DRIVE'] = None
+ p['SLEW'] = verilog.quote(random.choice(slews))
+
+ o_idx += 1
+ elif p['type'] == 'OBUFDS':
+ p['pad_wire'] = 'do[{}]'.format(o_idx)
+ o_idx += 1
+ p['bpad_wire'] = 'do[{}]'.format(o_idx)
+ o_idx += 1
+ p['iwire'] = luts.get_next_output_net()
+ if drives is not None:
+ p['DRIVE'] = random.choice(drives)
+ else:
+ p['DRIVE'] = None
+ p['SLEW'] = verilog.quote(random.choice(slews))
+ elif p['type'] == 'OBUFTDS':
+ p['pad_wire'] = 'do[{}]'.format(o_idx)
+ o_idx += 1
+ p['bpad_wire'] = 'do[{}]'.format(o_idx)
+ o_idx += 1
+ p['tristate_wire'] = random.choice(
+ ('0', luts.get_next_output_net()))
+ p['iwire'] = luts.get_next_output_net()
+ if drives is not None:
+ p['DRIVE'] = random.choice(drives)
+ else:
+ p['DRIVE'] = None
+ p['SLEW'] = verilog.quote(random.choice(slews))
+ elif p['type'] == 'IOBUF_DCIEN':
+ p['pad_wire'] = 'dio[{}]'.format(io_idx)
+ p['iwire'] = luts.get_next_output_net()
+ p['owire'] = luts.get_next_input_net()
+ if drives is not None:
+ p['DRIVE'] = random.choice(drives)
+ else:
+ p['DRIVE'] = None
+ p['SLEW'] = verilog.quote(random.choice(slews))
+ p['tristate_wire'] = random.choice(
+ ('0', luts.get_next_output_net()))
+ p['ibufdisable_wire'] = random.choice(
+ ('0', luts.get_next_output_net()))
+ p['dcitermdisable_wire'] = random.choice(
+ ('0', luts.get_next_output_net()))
+ io_idx += 1
+
+ if 'DRIVE' in p:
+ if p['DRIVE'] is not None:
+ p['DRIVE_STR'] = '.DRIVE({}),'.format(p['DRIVE'])
+ else:
+ p['DRIVE_STR'] = ''
+
+ if 'SLEW' in p:
+ p['SLEW_STR'] = ''
+ if iostandard in only_diff_map:
+ p['SLEW'] = None
+ elif p['DRIVE'] is not None:
+ p['SLEW_STR'] = '.SLEW({}),'.format(p['SLEW'])
+
+ if p['type'] is not None:
+ tile_params.append(
+ (
+ tile,
+ site,
+ p['pad_wire'],
+ iostandard_site,
+ p['DRIVE'],
+ verilog.unquote(p['SLEW']) if p['SLEW'] else None,
+ verilog.unquote(p['PULLTYPE']),
+ ))
+ params['tiles'].append(p)
+
+ write_params(tile_params)
+
+ with open('iobank_vref.csv', 'w') as f:
+ for iobank, vref in params['INTERNAL_VREF'].items():
+ f.write('{},{}\n'.format(iobank, vref))
+
+ print(
+ '''
+`define N_DI {n_di}
+`define N_DO {n_do}
+`define N_DIO {n_dio}
+
+module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do, inout wire [`N_DIO-1:0] dio, input refclk);
+ '''.format(n_di=i_idx, n_do=o_idx, n_dio=io_idx))
+
+ if any_idelay:
+ print('''
+ (* KEEP, DONT_TOUCH *)
+ IDELAYCTRL(.REFCLK(refclk));''')
+
+ # Always output a LUT6 to make placer happy.
+ print('''
+ (* KEEP, DONT_TOUCH *)
+ LUT6 dummy_lut();''')
+
+ for p in params['tiles']:
+ if p['type'] is None:
+ continue
+ elif p['type'] == 'IBUF':
+ print(
+ '''
+ wire idelay_{site};
+
+ (* KEEP, DONT_TOUCH *)
+ IBUF #(
+ .IBUF_LOW_PWR({IBUF_LOW_PWR}),
+ .IOSTANDARD({IOSTANDARD})
+ ) ibuf_{site} (
+ .I({pad_wire}),
+ .O({owire})
+ );'''.format(**p),
+ file=connects)
+ if p['IDELAY_ONLY']:
+ print(
+ """
+ (* KEEP, DONT_TOUCH *)
+ IDELAYE2 idelay_site_{site} (
+ .IDATAIN(idelay_{site})
+ );""".format(**p),
+ file=connects)
+
+ elif p['type'] == 'IBUFDS':
+ print(
+ '''
+ wire idelay_{site};
+
+ (* KEEP, DONT_TOUCH *)
+ IBUFDS #(
+ .IBUF_LOW_PWR({IBUF_LOW_PWR}),
+ .DIFF_TERM({DIFF_TERM}),
+ .IOSTANDARD({IOSTANDARD})
+ ) ibuf_{site} (
+ .I({pad_wire}),
+ .IB({bpad_wire}),
+ .O({owire})
+ );'''.format(**p),
+ file=connects)
+ if p['IDELAY_ONLY']:
+ print(
+ """
+ (* KEEP, DONT_TOUCH *)
+ IDELAYE2 idelay_site_{site} (
+ .IDATAIN(idelay_{site})
+ );""".format(**p),
+ file=connects)
+
+ elif p['type'] == 'OBUF':
+ print(
+ '''
+ (* KEEP, DONT_TOUCH *)
+ OBUF #(
+ {DRIVE_STR}
+ {SLEW_STR}
+ .IOSTANDARD({IOSTANDARD})
+ ) obuf_{site} (
+ .O({pad_wire}),
+ .I({iwire})
+ );'''.format(**p),
+ file=connects)
+ elif p['type'] == 'OBUFDS':
+ print(
+ '''
+ (* KEEP, DONT_TOUCH *)
+ OBUFDS #(
+ {DRIVE_STR}
+ {SLEW_STR}
+ .IOSTANDARD({IOSTANDARD})
+ ) obufds_{site} (
+ .O({pad_wire}),
+ .OB({bpad_wire}),
+ .I({iwire})
+ );'''.format(**p),
+ file=connects)
+ elif p['type'] == 'OBUFTDS':
+ print(
+ '''
+ (* KEEP, DONT_TOUCH *)
+ OBUFTDS #(
+ {DRIVE_STR}
+ {SLEW_STR}
+ .IOSTANDARD({IOSTANDARD})
+ ) obufds_{site} (
+ .O({pad_wire}),
+ .OB({bpad_wire}),
+ .T({tristate_wire}),
+ .I({iwire})
+ );'''.format(**p),
+ file=connects)
+ elif p['type'] == 'IOBUF_DCIEN':
+ print(
+ '''
+ (* KEEP, DONT_TOUCH *)
+ IOBUF_DCIEN #(
+ {DRIVE_STR}
+ {SLEW_STR}
+ .IOSTANDARD({IOSTANDARD})
+ ) ibuf_{site} (
+ .IO({pad_wire}),
+ .I({iwire}),
+ .O({owire}),
+ .T({tristate_wire}),
+ .IBUFDISABLE({ibufdisable_wire}),
+ .DCITERMDISABLE({dcitermdisable_wire})
+ );'''.format(**p),
+ file=connects)
+
+ for l in luts.create_wires_and_luts():
+ print(l)
+
+ print(connects.getvalue())
+
+ print("endmodule")
+
+ with open('params.json', 'w') as f:
+ json.dump(params, f, indent=2)
+
+
+if __name__ == '__main__':
+ run()
diff --git a/fuzzers/030-iob18/write_io_banks.tcl b/fuzzers/030-iob18/write_io_banks.tcl
new file mode 100644
index 0000000..eac330d
--- /dev/null
+++ b/fuzzers/030-iob18/write_io_banks.tcl
@@ -0,0 +1,44 @@
+# Copyright (C) 2017-2022 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
+set_property design_mode PinPlanning [current_fileset]
+open_io_design -name io_1
+set fp [open "iobanks.txt" "w"]
+foreach iobank [get_iobanks] {
+ foreach site [get_sites -of $iobank] {
+ puts $fp "$site,$iobank"
+ }
+}
+close $fp
+
+set fp [open "cmt_regions.csv" "w"]
+foreach site_type { IOB18M IOB18S IDELAYCTRL} {
+ foreach site [get_sites -filter "SITE_TYPE == $site_type"] {
+ set tile [get_tiles -of $site]
+ if {![string match "*IOI3*" $tile]} {
+ puts $fp "$site,$tile,[get_property CLOCK_REGION $site]"
+ }
+ }
+}
+close $fp
+
+set fp [open "pudc_sites.csv" "w"]
+puts $fp "tile,site"
+foreach tile [get_tiles *IOB18*] {
+ foreach site [get_sites -of_objects $tile] {
+ set site_type [get_property SITE_TYPE $site]
+
+ set pin [get_package_pins -of_objects $site]
+ set pin_func [get_property PIN_FUNC $pin]
+
+ if {[string first "PUDC_B" $pin_func] != -1} {
+ puts $fp "$tile,$site,$site_type"
+ }
+ }
+}
+close $fp
diff --git a/fuzzers/035-iob-ilogic/Makefile b/fuzzers/035-iob-ilogic/Makefile
index 3984213..8ac9380 100644
--- a/fuzzers/035-iob-ilogic/Makefile
+++ b/fuzzers/035-iob-ilogic/Makefile
@@ -22,7 +22,11 @@
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --groups tag_groups.txt --seg-fn-in $^ --seg-fn-out $@
${XRAY_MASKMERGE} build/mask_xioi3.db $$(find -name segdata_*)
-pushdb:
+# fuzzers of the RIOI tiles give near identical results, so reuse these
+build/segbits_rioi.db: build/segbits_xioi3.db
+ sed 's/IOI3/IOI/g' < $< > $@
+
+pushdb: build/segbits_rioi.db
${XRAY_MERGEDB} lioi3 build/segbits_xioi3.db
${XRAY_MERGEDB} lioi3_tbytesrc build/segbits_xioi3.db
${XRAY_MERGEDB} lioi3_tbyteterm build/segbits_xioi3.db
@@ -35,6 +39,13 @@
${XRAY_MERGEDB} mask_rioi3 build/mask_xioi3.db
${XRAY_MERGEDB} mask_rioi3_tbytesrc build/mask_xioi3.db
${XRAY_MERGEDB} mask_rioi3_tbyteterm build/mask_xioi3.db
+ifeq ($(XRAY_DATABASE),kintex7)
+ ${XRAY_MERGEDB} rioi build/segbits_rioi.db
+ ${XRAY_MERGEDB} rioi_tbytesrc build/segbits_rioi.db
+ ${XRAY_MERGEDB} rioi_tbyteterm build/segbits_rioi.db
+ ${XRAY_MERGEDB} mask_rioi build/mask_xioi3.db
+ ${XRAY_MERGEDB} mask_rioi_tbytesrc build/mask_xioi3.db
+ ${XRAY_MERGEDB} mask_rioi_tbyteterm build/mask_xioi3.db
+endif
.PHONY: database pushdb
-
diff --git a/fuzzers/035-iob-ilogic/generate.tcl b/fuzzers/035-iob-ilogic/generate.tcl
index 18eaf70..48dcb52 100644
--- a/fuzzers/035-iob-ilogic/generate.tcl
+++ b/fuzzers/035-iob-ilogic/generate.tcl
@@ -1,1416 +1,3 @@
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
-# Copyright (C) 2017-2020 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
# Copyright (C) 2017-2020 The Project X-Ray Authors
#
diff --git a/fuzzers/035a-iob18-idelay/Makefile b/fuzzers/035a-iob18-idelay/Makefile
new file mode 100644
index 0000000..44365e4
--- /dev/null
+++ b/fuzzers/035a-iob18-idelay/Makefile
@@ -0,0 +1,29 @@
+# Copyright (C) 2017-2022 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
+
diff --git a/fuzzers/035a-iob18-idelay/bits.dbf b/fuzzers/035a-iob18-idelay/bits.dbf
new file mode 100644
index 0000000..059168f
--- /dev/null
+++ b/fuzzers/035a-iob18-idelay/bits.dbf
@@ -0,0 +1,14 @@
+34_08 34_14 ,IOI.IDELAY_Y1.IDELAY_TYPE_FIXED
+35_113 35_119 ,IOI.IDELAY_Y0.IDELAY_TYPE_FIXED
+34_120 34_122
+34_114 34_116
+34_108 34_110
+34_100 34_102
+34_94 34_96
+35_05 35_07
+35_11 35_13
+35_17 35_19
+35_25 35_27
+35_31 35_33
+34_72 35_69
+34_58 35_55
diff --git a/fuzzers/035a-iob18-idelay/generate.py b/fuzzers/035a-iob18-idelay/generate.py
new file mode 100644
index 0000000..5c4bf4d
--- /dev/null
+++ b/fuzzers/035a-iob18-idelay/generate.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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):
+ 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)
+
+ idelay_types = ["FIXED", "VARIABLE", "VAR_LOAD"]
+ delay_srcs = ["IDATAIN", "DATAIN"]
+
+ # Output tags
+ for params in data:
+ segmk.add_site_tag(params['IDELAY_IN_USE'], 'IN_USE', True)
+ segmk.add_site_tag(params['IDELAY_NOT_IN_USE'], 'IN_USE', False)
+
+ 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
+ add_site_group_zero(
+ segmk, loc, "IDELAY_TYPE_", idelay_types, "FIXED", value)
+
+ # 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)
+ segmk.add_site_tag(
+ loc, "ZIDELAY_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:
+ 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"]))
+
+ segmk.add_site_tag(
+ loc, "IS_DATAIN_INVERTED", int(params["IS_DATAIN_INVERTED"]))
+ if params['IBUF_IN_USE']:
+ value = verilog.unquote(params["HIGH_PERFORMANCE_MODE"])
+ segmk.add_site_tag(
+ loc, "HIGH_PERFORMANCE_MODE", int(value == "TRUE"))
+
+ segmk.add_site_tag(
+ loc, "IS_IDATAIN_INVERTED", int(params["IS_IDATAIN_INVERTED"]))
+
+ segmk.compile(bitfilter=bitfilter)
+ segmk.write()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/035a-iob18-idelay/generate.tcl b/fuzzers/035a-iob18-idelay/generate.tcl
new file mode 100644
index 0000000..b2de3dc
--- /dev/null
+++ b/fuzzers/035a-iob18-idelay/generate.tcl
@@ -0,0 +1,31 @@
+# Copyright (C) 2017-2022 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
diff --git a/fuzzers/035a-iob18-idelay/top.py b/fuzzers/035a-iob18-idelay/top.py
new file mode 100644
index 0000000..3c48130
--- /dev/null
+++ b/fuzzers/035a-iob18-idelay/top.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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 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('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]
+ idelay_s = iob18s.replace("IOB", "IDELAY")
+ idelay_m = iob18m.replace("IOB", "IDELAY")
+
+ yield iob18m, idelay_m, iob18s, 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"))
+
+ ninputs = 0
+ di_idx = []
+ for i, sites in enumerate(tiles):
+ if random.randint(0, 1):
+ di_idx.append(ninputs)
+ ninputs += 1
+ else:
+ di_idx.append(None)
+
+ print(
+ '''
+module top (
+ (* CLOCK_BUFFER_TYPE = "NONE" *)
+ input wire clk,
+ input wire [{N}:0] di
+);
+
+wire clk_buf = clk;
+
+wire [{N}:0] di_buf;
+ '''.format(N=ninputs - 1))
+
+ # LOCes IOBs
+ data = []
+ for i, (sites, ibuf_idx) in enumerate(zip(tiles, di_idx)):
+
+ if random.randint(0, 1):
+ iob_i = sites[0]
+ iob_o = sites[2]
+ idelay = sites[1]
+ other_idelay = sites[3]
+ else:
+ iob_i = sites[2]
+ iob_o = sites[0]
+ idelay = sites[3]
+ other_idelay = sites[1]
+
+ use_ibuf = ibuf_idx is not None
+
+ DELAY_SRC = random.choice(["IDATAIN", "DATAIN"])
+ if not use_ibuf:
+ DELAY_SRC = 'DATAIN'
+
+ params = {
+ "LOC":
+ "\"" + idelay + "\"",
+ "IDELAY_TYPE":
+ "\"" + random.choice(
+ ["FIXED", "VARIABLE", "VAR_LOAD", "VAR_LOAD_PIPE"]) + "\"",
+ "IDELAY_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_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())
+
+ if use_ibuf:
+ print('')
+ print('(* LOC="%s", KEEP, DONT_TOUCH *)' % iob_i)
+ print(
+ 'IBUF ibuf_%03d (.I(di[%3d]), .O(di_buf[%3d]));' %
+ (ibuf_idx, ibuf_idx, ibuf_idx))
+ print(
+ 'mod #(%s) mod_%03d (.clk(clk_buf), .I(di_buf[%3d]));' %
+ (param_str, i, ibuf_idx))
+ else:
+ print('mod #(%s) mod_%03d (.clk(clk_buf), .I());' % (param_str, i))
+
+ params['IBUF_IN_USE'] = use_ibuf
+ params["IDELAY_IN_USE"] = idelay
+ params["IDELAY_NOT_IN_USE"] = other_idelay
+
+ 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
+);
+
+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;
+wire lut;
+
+(* KEEP, DONT_TOUCH *)
+LUT2 l( .O(lut) );
+
+// 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(lut),
+ .LDPIPEEN(),
+ .DATAOUT(x),
+ .CNTVALUEOUT()
+);
+
+endmodule
+ ''')
+
+
+run()
diff --git a/fuzzers/035b-iob-iserdes/Makefile b/fuzzers/035b-iob-iserdes/Makefile
index 446482e..a803305 100644
--- a/fuzzers/035b-iob-iserdes/Makefile
+++ b/fuzzers/035b-iob-iserdes/Makefile
@@ -22,7 +22,12 @@
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --groups tag_groups.txt --seg-fn-in $^ --seg-fn-out $@
${XRAY_MASKMERGE} build/mask_xioi3.db $$(find -name segdata_*.txt)
-pushdb:
+# running the fuzzers for RIOI tiles yields mostly identical
+# results, so reuse the results of IOI3 tiles
+build/segbits_rioi.db: build/segbits_xioi3.db
+ sed 's/IOI3/IOI/g' < $< > $@
+
+pushdb: build/segbits_rioi.db
${XRAY_MERGEDB} lioi3 build/segbits_xioi3.db
${XRAY_MERGEDB} lioi3_tbytesrc build/segbits_xioi3.db
${XRAY_MERGEDB} lioi3_tbyteterm build/segbits_xioi3.db
@@ -35,6 +40,14 @@
${XRAY_MERGEDB} mask_rioi3 build/mask_xioi3.db
${XRAY_MERGEDB} mask_rioi3_tbytesrc build/mask_xioi3.db
${XRAY_MERGEDB} mask_rioi3_tbyteterm build/mask_xioi3.db
+ifeq ($(XRAY_DATABASE),kintex7)
+ ${XRAY_MERGEDB} rioi build/segbits_rioi.db
+ ${XRAY_MERGEDB} rioi_tbytesrc build/segbits_rioi.db
+ ${XRAY_MERGEDB} rioi_tbyteterm build/segbits_rioi.db
+ ${XRAY_MERGEDB} mask_rioi build/mask_xioi3.db
+ ${XRAY_MERGEDB} mask_rioi_tbytesrc build/mask_xioi3.db
+ ${XRAY_MERGEDB} mask_rioi_tbyteterm build/mask_xioi3.db
+endif
.PHONY: database pushdb
diff --git a/fuzzers/036-iob18-ologic/Makefile b/fuzzers/036-iob18-ologic/Makefile
new file mode 100644
index 0000000..8c10625
--- /dev/null
+++ b/fuzzers/036-iob18-ologic/Makefile
@@ -0,0 +1,29 @@
+# Copyright (C) 2017-2022 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 := 40
+include ../fuzzer.mk
+
+database: build/segbits_rioi.db
+
+build/segbits_rioi.rdb: $(SPECIMENS_OK)
+ ${XRAY_SEGMATCH} -c 7 -o build/segbits_rioi.rdb $$(find -name segdata_*)
+
+build/segbits_rioi.db: build/segbits_rioi.rdb
+ ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
+ ${XRAY_MASKMERGE} build/mask_rioi.db $$(find -name segdata_*)
+
+pushdb:
+ ${XRAY_MERGEDB} rioi build/segbits_rioi.db
+ ${XRAY_MERGEDB} rioi_tbytesrc build/segbits_rioi.db
+ ${XRAY_MERGEDB} rioi_tbyteterm build/segbits_rioi.db
+ ${XRAY_MERGEDB} mask_rioi build/mask_rioi.db
+ ${XRAY_MERGEDB} mask_rioi_tbytesrc build/mask_rioi.db
+ ${XRAY_MERGEDB} mask_rioi_tbyteterm build/mask_rioi.db
+
+.PHONY: database pushdb
+
diff --git a/fuzzers/036-iob18-ologic/bits.dbf b/fuzzers/036-iob18-ologic/bits.dbf
new file mode 100644
index 0000000..8e902b0
--- /dev/null
+++ b/fuzzers/036-iob18-ologic/bits.dbf
@@ -0,0 +1,6 @@
+33_91 33_93
+32_36 32_34
+33_61 32_58 33_57
+32_70 32_66 33_69
+30_95 30_99 30_127 31_126 31_124 30_121 31_120 30_123 31_116 31_100
+31_00 30_01 30_03 31_06 30_07 31_04 30_11 31_28 31_32 30_29 30_27
diff --git a/fuzzers/036-iob18-ologic/generate.py b/fuzzers/036-iob18-ologic/generate.py
new file mode 100644
index 0000000..5590af5
--- /dev/null
+++ b/fuzzers/036-iob18-ologic/generate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+
+from prjxray.segmaker import Segmaker
+from prjxray import verilog
+import json
+
+# Set to true to enable additional tags useful for tracing bit toggles.
+DEBUG_FUZZER = False
+
+
+def bitfilter(frame, word):
+ return 30 <= frame and frame <= 33
+
+def handle_data_width(segmk, d):
+ if 'DATA_WIDTH' not in d:
+ return
+
+ site = d['ologic_loc']
+
+ data_rate = verilog.unquote(d['DATA_RATE_OQ'])
+ segmk.add_site_tag(
+ site, 'OSERDES.DATA_WIDTH.{}.W{}'.format(data_rate, d['DATA_WIDTH']),
+ 1)
+
+
+def no_oserdes(segmk, site):
+ for mode in ['SDR', 'DDR']:
+ if mode == 'SDR':
+ widths = [2, 3, 4, 5, 6, 7, 8]
+ else:
+ assert mode == 'DDR'
+ widths = [4, 6, 8]
+
+ for opt in widths:
+ segmk.add_site_tag(
+ site, 'OSERDES.DATA_WIDTH.{}.W{}'.format(mode, opt), 0)
+
+
+def main():
+ print("Loading tags")
+ segmk = Segmaker("design.bits")
+
+ with open('params.jl', 'r') as f:
+ design = json.load(f)
+
+ for d in design:
+ site = d['ologic_loc']
+
+ handle_data_width(segmk, d)
+
+ segmk.add_site_tag(site, 'OSERDES.IN_USE', d['use_oserdese2'])
+
+ if d['use_oserdese2']:
+ segmk.add_site_tag(site, 'OQUSED', 1)
+
+ for opt in ['SDR', 'DDR']:
+ segmk.add_site_tag(
+ site, 'OSERDES.DATA_RATE_OQ.{}'.format(opt),
+ verilog.unquote(d['DATA_RATE_OQ']) == opt)
+
+ data_rate_tq = verilog.unquote(d['DATA_RATE_TQ'])
+ segmk.add_site_tag(
+ site, 'OSERDES.DATA_RATE_TQ.{}'.format(data_rate_tq), 1)
+ for opt in ['BUF', 'SDR', 'DDR']:
+ segmk.add_site_tag(
+ site, 'OSERDES.DATA_RATE_TQ.{}'.format(opt),
+ opt == data_rate_tq)
+
+ for opt in ['SRVAL_OQ', 'SRVAL_TQ', 'INIT_OQ', 'INIT_TQ']:
+ segmk.add_site_tag(site, opt, d[opt])
+ segmk.add_site_tag(site, 'Z' + opt, 1 ^ d[opt])
+
+ for opt in ['CLK', 'CLKDIV']:
+ if d['{}_USED'.format(opt)]:
+ k = 'IS_{}_INVERTED'.format(opt)
+ segmk.add_site_tag(site, k, d[k])
+ segmk.add_site_tag(
+ site, 'ZINV_{}'.format(opt), 1 ^ d[k])
+
+ if d['io']:
+ for idx in range(4):
+ k = 'IS_T{}_INVERTED'.format(idx + 1)
+ segmk.add_site_tag(site, k, d[k])
+ segmk.add_site_tag(
+ site, 'ZINV_T{}'.format(idx + 1), 1 ^ d[k])
+
+ for idx in range(8):
+ k = 'IS_D{}_INVERTED'.format(idx + 1)
+ segmk.add_site_tag(site, k, d[k])
+ segmk.add_site_tag(
+ site, 'ZINV_D{}'.format(idx + 1), 1 ^ d[k])
+
+ for tristate_width in [1, 4]:
+ segmk.add_site_tag(
+ site,
+ 'OSERDES.TRISTATE_WIDTH.W{}'.format(tristate_width),
+ d['TRISTATE_WIDTH'] == tristate_width)
+
+ for opt in ['MASTER', 'SLAVE']:
+ segmk.add_site_tag(
+ site, 'OSERDES.SERDES_MODE.{}'.format(opt),
+ opt == verilog.unquote(d['OSERDES_MODE']))
+
+ if 'o_sr_used' in d:
+ if d['o_sr_used'] in ['S', 'R']:
+ segmk.add_site_tag(site, 'ODDR.SRUSED', 1)
+ segmk.add_site_tag(site, 'ODDR.ZSRUSED', 0)
+ else:
+ assert d['o_sr_used'] == 'None'
+ segmk.add_site_tag(site, 'ODDR.SRUSED', 0)
+ segmk.add_site_tag(site, 'ODDR.ZSRUSED', 1)
+
+ if 't_sr_used' in d:
+ if d['t_sr_used'] in ['S', 'R']:
+ segmk.add_site_tag(site, 'TDDR.SRUSED', 1)
+ segmk.add_site_tag(site, 'TDDR.ZSRUSED', 0)
+ else:
+ assert d['t_sr_used'] == 'None'
+ segmk.add_site_tag(site, 'TDDR.SRUSED', 0)
+ segmk.add_site_tag(site, 'TDDR.ZSRUSED', 1)
+
+ if d['oddr_mux_config'] == 'direct':
+ segmk.add_site_tag(site, 'ODDR_TDDR.IN_USE', 1)
+
+ if d['tddr_mux_config'] == 'direct':
+ segmk.add_site_tag(site, 'ODDR_TDDR.IN_USE', 1)
+
+ if d['oddr_mux_config'] == 'direct' and d[
+ 'tddr_mux_config'] == 'direct':
+ segmk.add_site_tag(site, 'ZINV_CLK', 1 ^ d['IS_CLK_INVERTED'])
+
+ if d['IS_CLK_INVERTED'] == 0:
+ for opt in ['OPPOSITE_EDGE', 'SAME_EDGE']:
+ segmk.add_site_tag(
+ site, 'ODDR.DDR_CLK_EDGE.{}'.format(opt),
+ verilog.unquote(d['ODDR_CLK_EDGE']) == opt)
+
+ segmk.add_site_tag(
+ site, 'TDDR.DDR_CLK_EDGE.INV',
+ d['ODDR_CLK_EDGE'] != d['TDDR_CLK_EDGE'])
+ segmk.add_site_tag(
+ site, 'TDDR.DDR_CLK_EDGE.ZINV',
+ d['ODDR_CLK_EDGE'] == d['TDDR_CLK_EDGE'])
+
+ if 'SRTYPE' in d:
+ for opt in ['ASYNC', 'SYNC']:
+ segmk.add_site_tag(
+ site, 'OSERDES.SRTYPE.{}'.format(opt),
+ verilog.unquote(d['SRTYPE']) == opt)
+
+ for opt in ['ASYNC', 'SYNC']:
+ segmk.add_site_tag(
+ site, 'OSERDES.TSRTYPE.{}'.format(opt),
+ verilog.unquote(d['TSRTYPE']) == opt)
+
+ if not d['use_oserdese2']:
+ no_oserdes(segmk, site)
+ if d['oddr_mux_config'] == 'lut':
+ segmk.add_site_tag(site, 'ODDR_TDDR.IN_USE', 0)
+ segmk.add_site_tag(site, 'OMUX.D1', 1)
+ segmk.add_site_tag(site, 'OQUSED', 1)
+ elif d['oddr_mux_config'] == 'direct':
+ segmk.add_site_tag(site, 'OMUX.D1', 0)
+ elif d['oddr_mux_config'] == 'none' and not d['io']:
+ segmk.add_site_tag(site, 'OQUSED', 0)
+
+ segmk.add_site_tag(site, 'TQUSED', d['io'])
+
+ if DEBUG_FUZZER:
+ for k in d:
+ segmk.add_site_tag(
+ site, 'param_' + k + '_' + str(d[k]).replace(
+ ' ', '').replace('\n', ''), 1)
+
+ segmk.compile(bitfilter=bitfilter)
+ segmk.write(allow_empty=True)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/036-iob18-ologic/generate.tcl b/fuzzers/036-iob18-ologic/generate.tcl
new file mode 100644
index 0000000..413215b
--- /dev/null
+++ b/fuzzers/036-iob18-ologic/generate.tcl
@@ -0,0 +1,107 @@
+# Copyright (C) 2017-2022 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
+source "$::env(XRAY_DIR)/utils/utils.tcl"
+
+proc make_io_pin_sites {} {
+ # get all possible IOB pins
+ foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
+ set site [get_sites -of_objects $pad]
+ if {[llength $site] == 0} {
+ continue
+ }
+ if [string match IOB18* [get_property SITE_TYPE $site]] {
+ dict append io_pin_sites $site $pad
+ }
+ }
+ return $io_pin_sites
+}
+
+proc load_pin_lines {} {
+ # IOB_X0Y103 clk input
+ # IOB_X0Y129 do[0] output
+
+ set fp [open "params.csv" r]
+ gets $fp line
+
+ set pin_lines {}
+ for {gets $fp line} {$line != ""} {gets $fp line} {
+ lappend pin_lines [split $line ","]
+ }
+ close $fp
+ return $pin_lines
+}
+
+proc loc_pins {} {
+ set pin_lines [load_pin_lines]
+ set io_pin_sites [make_io_pin_sites]
+
+ puts "Looping"
+ for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
+ set line [lindex $pin_lines $idx]
+ puts "$line"
+
+ set site_str [lindex $line 1]
+ set pin_str [lindex $line 2]
+ set iostandard [lindex $line 3]
+ set drive [lindex $line 4]
+ set slew [lindex $line 5]
+ set pulltype [lindex $line 6]
+
+ # Have: site
+ # Want: pin for site
+
+ set site [get_sites $site_str]
+ set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
+ # set port [get_ports -of_objects $site]
+ set port [get_ports $pin_str]
+ set tile [get_tiles -of_objects $site]
+
+ set pin [dict get $io_pin_sites $site]
+
+ set props {}
+ #lappend props PACKAGE_PIN $pin
+ lappend props IOSTANDARD $iostandard
+ lappend props PULLTYPE $pulltype
+
+ if {$drive != "None"} {
+ lappend props DRIVE $drive
+ }
+
+ if {$slew != "None"} {
+ lappend props SLEW $slew
+ }
+
+ puts $props
+
+ set_property -dict "$props" $port
+ }
+}
+
+proc run {} {
+ create_project -force -part $::env(XRAY_PART) design design
+ read_verilog top.v
+ synth_design -top top
+
+ loc_pins
+
+ set_property CFGBVS GND [current_design]
+ set_property CONFIG_VOLTAGE 1.8 [current_design]
+ set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-79}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-144}]
+
+ write_checkpoint -force design_pre_place.dcp
+
+ place_design
+ route_design
+
+ write_checkpoint -force design.dcp
+ write_bitstream -force design.bit
+}
+
+run
diff --git a/fuzzers/036-iob18-ologic/top.py b/fuzzers/036-iob18-ologic/top.py
new file mode 100644
index 0000000..4491956
--- /dev/null
+++ b/fuzzers/036-iob18-ologic/top.py
@@ -0,0 +1,474 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+import io
+import os
+import random
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray import lut_maker
+from prjxray import verilog
+from prjxray.db import Database
+
+
+def gen_sites():
+ '''
+ IOB18S: main IOB of a diff pair
+ IOB18M: secondary IOB of a diff pair
+ IOB18: not a diff pair. Relatively rare (at least in ROI...2 of them?)
+ Focus on IOB18S to start
+ '''
+ db = Database(util.get_db_root(), util.get_part())
+ grid = db.grid()
+ for tile_name in sorted(grid.tiles()):
+ loc = grid.loc_of_tilename(tile_name)
+ gridinfo = grid.gridinfo_at_loc(loc)
+
+ for site_name, site_type in gridinfo.sites.items():
+ if site_type in ['IOB18S', 'IOB18M']:
+ yield tile_name, site_name
+
+
+def write_params(params):
+ pinstr = 'tile,site,pin,iostandard,drive,slew\n'
+ for vals in params:
+ pinstr += ','.join(map(str, vals)) + '\n'
+
+ open('params.csv', 'w').write(pinstr)
+
+
+def use_oserdese2(p, luts, connects):
+
+ p['oddr_mux_config'] = 'none'
+ p['tddr_mux_config'] = 'none'
+
+ p['DATA_RATE_OQ'] = verilog.quote(random.choice((
+ 'SDR',
+ 'DDR',
+ )))
+
+ p['DATA_RATE_TQ'] = verilog.quote(random.choice((
+ 'BUF',
+ 'SDR',
+ 'DDR',
+ )))
+
+ if verilog.unquote(p['DATA_RATE_OQ']) == 'SDR':
+ data_widths = [2, 3, 4, 5, 6, 7, 8]
+ else:
+ data_widths = [4, 6, 8]
+
+ p['DATA_WIDTH'] = random.choice(data_widths)
+
+ if p['DATA_WIDTH'] == 4 and verilog.unquote(
+ p['DATA_RATE_OQ']) == 'DDR' and verilog.unquote(
+ p['DATA_RATE_TQ']) == 'DDR':
+ tristate_width = 4
+ else:
+ tristate_width = 1
+ p['SERDES_MODE'] = verilog.quote(random.choice(('MASTER', 'SLAVE')))
+
+ p['TRISTATE_WIDTH'] = tristate_width
+ p['OSERDES_MODE'] = verilog.quote(random.choice(('MASTER', 'SLAVE')))
+
+ if p['io']:
+ p['TFB'] = '.TFB(tfb_{site}),'.format(**p)
+ p['TQ'] = '.TQ({twire}),'.format(**p)
+ p['t1net'] = luts.get_next_output_net()
+ p['t2net'] = luts.get_next_output_net()
+ p['t3net'] = luts.get_next_output_net()
+ p['t4net'] = luts.get_next_output_net()
+ p['tcenet'] = luts.get_next_output_net()
+
+ for idx in range(4):
+ p['IS_T{}_INVERTED'.format(idx + 1)] = random.randint(0, 1)
+ else:
+ p['TFB'] = '.TFB(),'
+ p['TQ'] = '.TQ(),'
+ p['t1net'] = ''
+ p['t2net'] = ''
+ p['t3net'] = ''
+ p['t4net'] = ''
+ p['tcenet'] = ''
+
+ for idx in range(4):
+ p['IS_T{}_INVERTED'.format(idx + 1)] = 0
+
+ p['SRVAL_OQ'] = random.randint(0, 1)
+ p['SRVAL_TQ'] = random.randint(0, 1)
+ p['INIT_OQ'] = random.randint(0, 1)
+ p['INIT_TQ'] = random.randint(0, 1)
+
+ for idx in range(8):
+ p['IS_D{}_INVERTED'.format(idx + 1)] = random.randint(0, 1)
+
+ p['IS_CLK_INVERTED'] = random.randint(0, 1)
+ p['IS_CLKDIV_INVERTED'] = random.randint(0, 1)
+
+ clk_connections = ''
+ p['CLK_USED'] = random.randint(0, 1)
+ p['CLKDIV_USED'] = random.randint(0, 1)
+ if p['CLK_USED']:
+ clk_connections += '''
+ .CLK({}),'''.format(luts.get_next_output_net())
+ if p['CLKDIV_USED']:
+ clk_connections += '''
+ .CLKDIV({}),'''.format(luts.get_next_output_net())
+
+ print(
+ '''
+ (* KEEP, DONT_TOUCH, LOC = "{ologic_loc}" *)
+ OSERDESE2 #(
+ .SERDES_MODE({OSERDES_MODE}),
+ .DATA_RATE_TQ({DATA_RATE_TQ}),
+ .DATA_RATE_OQ({DATA_RATE_OQ}),
+ .DATA_WIDTH({DATA_WIDTH}),
+ .TRISTATE_WIDTH({TRISTATE_WIDTH}),
+ .SRVAL_OQ({SRVAL_OQ}),
+ .SRVAL_TQ({SRVAL_TQ}),
+ .INIT_OQ({INIT_OQ}),
+ .INIT_TQ({INIT_TQ}),
+ .IS_T1_INVERTED({IS_T1_INVERTED}),
+ .IS_T2_INVERTED({IS_T2_INVERTED}),
+ .IS_T3_INVERTED({IS_T3_INVERTED}),
+ .IS_T4_INVERTED({IS_T4_INVERTED}),
+ .IS_D1_INVERTED({IS_D1_INVERTED}),
+ .IS_D2_INVERTED({IS_D2_INVERTED}),
+ .IS_D3_INVERTED({IS_D3_INVERTED}),
+ .IS_D4_INVERTED({IS_D4_INVERTED}),
+ .IS_D5_INVERTED({IS_D5_INVERTED}),
+ .IS_D6_INVERTED({IS_D6_INVERTED}),
+ .IS_D7_INVERTED({IS_D7_INVERTED}),
+ .IS_D8_INVERTED({IS_D8_INVERTED}),
+ .IS_CLK_INVERTED({IS_CLK_INVERTED}),
+ .IS_CLKDIV_INVERTED({IS_CLKDIV_INVERTED})
+ ) oserdese2_{site} (
+ .OQ({owire}),
+ {TFB}
+ {TQ}
+ {clk_connections}
+ .D1({d1net}),
+ .D2({d2net}),
+ .D3({d3net}),
+ .D4({d4net}),
+ .D5({d5net}),
+ .D6({d6net}),
+ .D7({d7net}),
+ .D8({d8net}),
+ .OCE({ocenet}),
+ .RST({rstnet}),
+ .T1({t1net}),
+ .T2({t2net}),
+ .T3({t3net}),
+ .T4({t4net}),
+ .TCE({tcenet})
+ );'''.format(
+ clk_connections=clk_connections,
+ rstnet=luts.get_next_output_net(),
+ d1net=luts.get_next_output_net(),
+ d2net=luts.get_next_output_net(),
+ d3net=luts.get_next_output_net(),
+ d4net=luts.get_next_output_net(),
+ d5net=luts.get_next_output_net(),
+ d6net=luts.get_next_output_net(),
+ d7net=luts.get_next_output_net(),
+ d8net=luts.get_next_output_net(),
+ ocenet=luts.get_next_output_net(),
+ ofb_wire=luts.get_next_input_net(),
+ **p),
+ file=connects)
+
+
+def use_direct_and_oddr(p, luts, connects):
+ p['oddr_mux_config'] = random.choice((
+ 'direct',
+ 'lut',
+ 'none',
+ ))
+
+ if p['io']:
+ if p['oddr_mux_config'] != 'lut':
+ p['tddr_mux_config'] = random.choice((
+ 'direct',
+ 'lut',
+ 'none',
+ ))
+ else:
+ p['tddr_mux_config'] = random.choice((
+ 'lut',
+ 'none',
+ ))
+ else:
+ p['tddr_mux_config'] = 'none'
+
+ # toddr and oddr share the same clk
+ if random.randint(0, 1):
+ clknet = luts.get_next_output_net()
+ p['IS_CLK_INVERTED'] = 0
+ else:
+ clknet = 'bufg_o'
+ p['IS_CLK_INVERTED'] = random.randint(0, 1)
+
+ if p['tddr_mux_config'] == 'direct':
+ p['TINIT'] = random.randint(0, 1)
+ p['TSRTYPE'] = verilog.quote(random.choice(('SYNC', 'ASYNC')))
+ p['TDDR_CLK_EDGE'] = verilog.quote('OPPOSITE_EDGE')
+
+ # Note: it seems that CLK_EDGE setting is ignored for TDDR
+ p['TDDR_CLK_EDGE'] = verilog.quote(
+ random.choice(('OPPOSITE_EDGE', 'SAME_EDGE')))
+
+ p['t_sr_used'] = random.choice(('None', 'S', 'R'))
+ if p['t_sr_used'] == 'None':
+ p['t_srnet'] = ''
+ elif p['t_sr_used'] == 'S':
+ p['srnet'] = luts.get_next_output_net()
+ p['t_srnet'] = '.S({}),\n'.format(p['srnet'])
+ elif p['t_sr_used'] == 'R':
+ p['srnet'] = luts.get_next_output_net()
+ p['t_srnet'] = '.R({}),\n'.format(p['srnet'])
+
+ print(
+ '''
+ (* KEEP, DONT_TOUCH, LOC = "{ologic_loc}" *)
+ ODDR #(
+ .INIT({TINIT}),
+ .SRTYPE({TSRTYPE}),
+ .DDR_CLK_EDGE({TDDR_CLK_EDGE}),
+ .IS_C_INVERTED({IS_CLK_INVERTED})
+ ) toddr_{site} (
+ .C({cnet}),
+ .D1({d1net}),
+ .D2({d2net}),
+ .CE({cenet}),
+ {t_srnet}
+ .Q(tddr_d_{site})
+ );
+ '''.format(
+ cnet=clknet,
+ d1net=luts.get_next_output_net(),
+ d2net=luts.get_next_output_net(),
+ cenet=luts.get_next_output_net(),
+ **p),
+ file=connects)
+
+ if p['tddr_mux_config'] == 'direct':
+ print(
+ '''
+ assign {twire} = tddr_d_{site};'''.format(**p, ),
+ file=connects)
+ elif p['tddr_mux_config'] == 'lut':
+ print(
+ '''
+ assign {twire} = {lut};'''.format(lut=luts.get_next_output_net(), **p),
+ file=connects)
+ pass
+ elif p['tddr_mux_config'] == 'none':
+ pass
+ else:
+ assert False, p['tddr_mux_config']
+
+ if p['oddr_mux_config'] == 'direct':
+ p['QINIT'] = random.randint(0, 1)
+ p['SRTYPE'] = verilog.quote(random.choice(('SYNC', 'ASYNC')))
+ p['ODDR_CLK_EDGE'] = verilog.quote(
+ random.choice((
+ 'OPPOSITE_EDGE',
+ 'SAME_EDGE',
+ )))
+
+ p['o_sr_used'] = random.choice(('None', 'S', 'R'))
+ if p['o_sr_used'] == 'None':
+ p['o_srnet'] = ''
+ elif p['o_sr_used'] == 'S':
+ if 'srnet' not in p:
+ p['srnet'] = luts.get_next_output_net()
+ p['o_srnet'] = '.S({}),\n'.format(p['srnet'])
+ elif p['o_sr_used'] == 'R':
+ if 'srnet' not in p:
+ p['srnet'] = luts.get_next_output_net()
+ p['o_srnet'] = '.R({}),\n'.format(p['srnet'])
+
+ print(
+ '''
+ (* KEEP, DONT_TOUCH, LOC = "{ologic_loc}" *)
+ ODDR #(
+ .INIT({QINIT}),
+ .SRTYPE({SRTYPE}),
+ .DDR_CLK_EDGE({ODDR_CLK_EDGE}),
+ .IS_C_INVERTED({IS_CLK_INVERTED})
+ ) oddr_{site} (
+ .C({cnet}),
+ .D1({d1net}),
+ .D2({d2net}),
+ .CE({cenet}),
+ {o_srnet}
+ .Q(oddr_d_{site})
+ );
+ '''.format(
+ cnet=clknet,
+ d1net=luts.get_next_output_net(),
+ d2net=luts.get_next_output_net(),
+ cenet=luts.get_next_output_net(),
+ **p),
+ file=connects)
+
+ if p['oddr_mux_config'] == 'direct':
+ print(
+ '''
+ assign {owire} = oddr_d_{site};'''.format(**p, ),
+ file=connects)
+ elif p['oddr_mux_config'] == 'lut':
+ print(
+ '''
+ assign {owire} = {lut};'''.format(lut=luts.get_next_output_net(), **p),
+ file=connects)
+ pass
+ elif p['oddr_mux_config'] == 'none':
+ pass
+ else:
+ assert False, p['oddr_mux_config']
+
+
+def run():
+ iostandards = [
+ 'LVCMOS12', 'LVCMOS15', 'LVCMOS18'
+ ]
+ iostandard = random.choice(iostandards)
+
+ if iostandard in ['LVCMOS12']:
+ drives = [2, 4, 6, 8]
+ elif iostandard in ['LVCMOS15', 'LVCMOS18']:
+ drives = [2, 4, 6, 8, 12, 16]
+ else:
+ assert False, "This should be unreachable"
+
+ slews = ['FAST', 'SLOW']
+ pulls = ["NONE", "KEEPER", "PULLDOWN", "PULLUP"]
+
+ luts = lut_maker.LutMaker()
+
+ connects = io.StringIO()
+
+ tile_params = []
+ params = []
+
+ ndio = 0
+ ndo = 0
+ for idx, (tile, site) in enumerate(gen_sites()):
+ if idx == 0:
+ continue
+
+ p = {}
+ p['tile'] = tile
+ p['site'] = site
+ p['ilogic_loc'] = site.replace('IOB', 'ILOGIC')
+ p['ologic_loc'] = site.replace('IOB', 'OLOGIC')
+ p['IOSTANDARD'] = verilog.quote(iostandard)
+ p['PULLTYPE'] = verilog.quote(random.choice(pulls))
+ p['DRIVE'] = random.choice(drives)
+ p['SLEW'] = verilog.quote(random.choice(slews))
+
+ p['io'] = random.randint(0, 1)
+ p['owire'] = 'do_buf[{}]'.format(idx - 1)
+
+ if p['io']:
+ p['pad_wire'] = 'dio[{}]'.format(ndio)
+ ndio += 1
+
+ p['iwire'] = 'di_buf[{}]'.format(idx - 1)
+ p['twire'] = 't[{}]'.format(idx - 1)
+ else:
+ p['pad_wire'] = 'do[{}]'.format(ndo)
+ ndo += 1
+
+ params.append(p)
+ tile_params.append(
+ (
+ tile, site, p['pad_wire'], iostandard, p['DRIVE'],
+ verilog.unquote(p['SLEW']) if p['SLEW'] else None,
+ verilog.unquote(p['PULLTYPE'])))
+
+ write_params(tile_params)
+
+ print(
+ '''
+`define N_DO {n_do}
+`define N_DIO {n_dio}
+
+module top(input clk, output wire [`N_DO-1:0] do, inout wire [`N_DIO-1:0] dio);
+ wire [(`N_DIO+`N_DO)-1:0] di_buf;
+ wire [(`N_DIO+`N_DO)-1:0] do_buf;
+ wire [(`N_DIO+`N_DO)-1:0] t;
+ '''.format(n_dio=ndio, n_do=ndo))
+
+ # Always output a LUT6 to make placer happy.
+ print(
+ '''
+ (* KEEP, DONT_TOUCH *)
+ LUT6 dummy_lut();
+
+ wire bufg_o;
+ (* KEEP, DONT_TOUCH *)
+ BUFG (.O(bufg_o));
+ ''')
+
+ for p in params:
+ if p['io']:
+ print(
+ '''
+ wire oddr_d_{site};
+
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ IOBUF #(
+ .IOSTANDARD({IOSTANDARD})
+ ) obuf_{site} (
+ .IO({pad_wire}),
+ .I({owire}),
+ .O({iwire}),
+ .T({twire})
+ );
+ '''.format(**p),
+ file=connects)
+ else:
+ print(
+ '''
+ wire oddr_d_{site};
+
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ OBUF #(
+ .IOSTANDARD({IOSTANDARD})
+ ) obuf_{site} (
+ .O({pad_wire}),
+ .I({owire})
+ );
+ '''.format(**p),
+ file=connects)
+
+ p['use_oserdese2'] = random.randint(0, 1)
+ if p['use_oserdese2']:
+ use_oserdese2(p, luts, connects)
+ else:
+ use_direct_and_oddr(p, luts, connects)
+
+ for l in luts.create_wires_and_luts():
+ print(l)
+
+ print(connects.getvalue())
+
+ print("endmodule")
+
+ with open('params.jl', 'w') as f:
+ json.dump(params, f, indent=2)
+
+
+if __name__ == '__main__':
+ run()
diff --git a/fuzzers/037-iob18-pips/Makefile b/fuzzers/037-iob18-pips/Makefile
new file mode 100644
index 0000000..cef6198
--- /dev/null
+++ b/fuzzers/037-iob18-pips/Makefile
@@ -0,0 +1,58 @@
+# Copyright (C) 2017-2022 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
+export FUZDIR=$(shell pwd)
+PIP_TYPE?=ioi
+PIPLIST_TCL=$(FUZDIR)/ioi_pip_list.tcl
+
+TODO_RE=".*"
+EXCLUDE_RE=".*((PHASER)|(CLKDIVF)|(CLKDIVP)|(CLKDIVB)|(IOI_ILOGIC[01]_O)|(IOI_OLOGIC[01]_CLKB?\.)|(IOI_IMUX_RC)|(IOI_OLOGIC[01]_[OT]FB)|(OCLKM.*IMUX31)|IOI_ODELAY[01]_CLKIN.IOI_OCLK_[01]|RIOI_O[01].RIOI_ODELAY[01]_DATAOUT|RIOI_O[01].RIOI_OLOGIC[01]_OQ).*"
+
+MAKETODO_FLAGS=--pip-type ${PIP_TYPE} --seg-type $(PIP_TYPE) --re $(TODO_RE) --sides "xr" --exclude-re $(EXCLUDE_RE)
+N = 120
+
+SPECIMENS_DEPS=build/cmt_regions.csv
+
+include ../pip_loop.mk
+
+SIX_BIT_PIPS="OLOGIC[01]_CLKDIV"
+
+build/segbits_ioi_x.rdb: $(SPECIMENS_OK)
+ # Most pips are 3 bits, force a 3 bit solution
+ ${XRAY_SEGMATCH} -c 3 -m 20 -M 50 -o build/segbits_ioi_x_match_3.rdb \
+ $(shell find build -name segdata_rioi*.txt)
+ # Some are 6 bit solutions, solve for 6 bits and merge respectively
+ ${XRAY_SEGMATCH} -c 6 -m 20 -M 50 -o build/segbits_ioi_x_match_6.rdb \
+ $(shell find build -name segdata_rioi*.txt)
+ grep -v ${SIX_BIT_PIPS} build/segbits_ioi_x_match_3.rdb > build/segbits_ioi_x.rdb
+ grep ${SIX_BIT_PIPS} build/segbits_ioi_x_match_6.rdb >> build/segbits_ioi_x.rdb
+
+RDBS = build/segbits_ioi_x.rdb
+
+database: ${RDBS}
+ ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
+ --seg-fn-in build/segbits_ioi_x.rdb \
+ --seg-fn-out build/segbits_ioi_x.db
+
+ # Keep a copy to track iter progress
+ cp build/segbits_ioi_x.rdb build/$(ITER)/segbits_ioi_x.rdb
+ cp build/segbits_ioi_x.db build/$(ITER)/segbits_ioi_x.db
+
+ # Clobber existing .db to eliminate potential conflicts
+ cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
+ XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} rioi build/segbits_ioi_x.db
+
+build/cmt_regions.csv: output_cmt.tcl
+ mkdir -p build
+ cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl
+
+pushdb: database
+ ${XRAY_MERGEDB} rioi build/segbits_ioi_x.db
+ ${XRAY_MERGEDB} rioi_tbytesrc build/segbits_ioi_x.db
+ ${XRAY_MERGEDB} rioi_tbyteterm build/segbits_ioi_x.db
+
+.PHONY: database pushdb
diff --git a/fuzzers/037-iob18-pips/bits.dbf b/fuzzers/037-iob18-pips/bits.dbf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fuzzers/037-iob18-pips/bits.dbf
diff --git a/fuzzers/037-iob18-pips/generate.py b/fuzzers/037-iob18-pips/generate.py
new file mode 100644
index 0000000..b21218c
--- /dev/null
+++ b/fuzzers/037-iob18-pips/generate.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+
+from prjxray.segmaker import Segmaker
+import os, re
+import os.path
+
+
+def bitfilter(frame, word):
+ if frame < 28:
+ return False
+ return True
+
+
+def main():
+ segmk = Segmaker("design.bits")
+
+ tiledata = {}
+ pipdata = {}
+ ignpip = set()
+
+ with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
+ 'ioi', 'rioi.txt')) as f:
+ for l in f:
+ tile_type, dst, src = l.strip().split('.')
+ if tile_type not in pipdata:
+ pipdata[tile_type] = []
+
+ pipdata[tile_type].append((src, dst))
+
+ print("Loading tags from design.txt.")
+ with open("design.txt", "r") as f:
+ for line in f:
+ tile, pip, src, dst, pnum, pdir = line.split()
+ if not tile.startswith('RIOI') or "X43Y9" in tile:
+ continue
+
+ log = open("log.txt", "a")
+ print(line, file=log)
+ pip_prefix, _ = pip.split(".")
+ tile_from_pip, tile_type = pip_prefix.split('/')
+
+ _, src = src.split("/")
+ _, dst = dst.split("/")
+ pnum = int(pnum)
+ pdir = int(pdir)
+
+ if tile not in tiledata:
+ tiledata[tile] = {
+ "type": tile_type,
+ "pips": set(),
+ "srcs": set(),
+ "dsts": set(),
+ }
+
+ tiledata[tile]["pips"].add((src, dst))
+ tiledata[tile]["srcs"].add(src)
+ tiledata[tile]["dsts"].add(dst)
+
+ if pdir == 0:
+ tiledata[tile]["srcs"].add(dst)
+ tiledata[tile]["dsts"].add(src)
+
+ for tile, pips_srcs_dsts in tiledata.items():
+ tile_type = pips_srcs_dsts["type"]
+
+ if tile_type.startswith('RIOI'):
+ tile_type = 'RIOI'
+
+ for src, dst in pipdata[tile_type]:
+ if (src, dst) in ignpip:
+ pass
+ if re.match(r'.*PHASER.*', src) or re.match(r'.*CLKDIV[PFB].*',
+ dst):
+ pass
+ elif (src, dst) in tiledata[tile]["pips"]:
+ segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 1)
+ elif dst not in tiledata[tile]["dsts"]:
+ disable_pip = True
+
+ if dst == 'IOI_OCLKM_0' and 'IOI_OCLK_0' in tiledata[tile][
+ "dsts"]:
+ disable_pip = False
+
+ if dst == 'IOI_OCLKM_1' and 'IOI_OCLK_1' in tiledata[tile][
+ "dsts"]:
+ disable_pip = False
+
+ if disable_pip:
+ segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0)
+
+ segmk.compile(bitfilter=bitfilter)
+ segmk.write()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/037-iob18-pips/generate.tcl b/fuzzers/037-iob18-pips/generate.tcl
new file mode 100644
index 0000000..65d692d
--- /dev/null
+++ b/fuzzers/037-iob18-pips/generate.tcl
@@ -0,0 +1,109 @@
+# Copyright (C) 2017-2022 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
+source "$::env(XRAY_DIR)/utils/utils.tcl"
+
+proc write_pip_txtdata {filename} {
+ puts "FUZ([pwd]): Writing $filename."
+ set fp [open $filename w]
+ set nets [get_nets -hierarchical]
+ set nnets [llength $nets]
+ set neti 0
+ foreach net $nets {
+ incr neti
+ if {($neti % 100) == 0 } {
+ puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
+ }
+ foreach pip [get_pips -of_objects $net] {
+ set tile [get_tiles -of_objects $pip]
+ set src_wire [get_wires -uphill -of_objects $pip]
+ set dst_wire [get_wires -downhill -of_objects $pip]
+ set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
+ set dir_prop [get_property IS_DIRECTIONAL $pip]
+ puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
+ }
+ }
+ close $fp
+}
+
+proc make_manual_routes {filename} {
+ puts "MANROUTE: Loading routes from $filename"
+
+ set fp [open $filename r]
+ foreach line [split [read $fp] "\n"] {
+ if {$line eq ""} {
+ continue
+ }
+
+ puts "MANROUTE: Line: $line"
+
+ # Parse the line
+ set fields [split $line " "]
+ set net_name [lindex $fields 0]
+ set wire_name [lindex $fields 1]
+
+ # Check if that net exists
+ if {[get_nets $net_name] eq ""} {
+ puts "MANROUTE: net $net_name does not exist"
+ continue
+ }
+
+ set net [get_nets $net_name]
+
+ # Rip it up
+ set_property -quiet FIXED_ROUTE "" $net
+ set_property IS_ROUTE_FIXED 0 $net
+ route_design -unroute -nets $net
+
+ # Make the route
+ set nodes [get_nodes -of_objects [get_wires $wire_name]]
+ set status [route_via $net_name [list $nodes] 0]
+
+ # Failure, skip manual routing of this net
+ if { $status != 1 } {
+ puts "MANROUTE: Manual routing failed!"
+ set_property -quiet FIXED_ROUTE "" $net
+ set_property IS_ROUTE_FIXED 0 $net
+ continue
+ }
+
+ puts "MANROUTE: Success!"
+ }
+}
+
+proc run {} {
+ 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_property IS_ENABLED 0 [get_drc_checks {AVAL-74}]
+ set_property IS_ENABLED 0 [get_drc_checks {PDRC-26}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-4}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-5}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-13}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-98}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-99}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-105}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-115}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-144}]
+
+ set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
+
+ place_design -directive Quick
+ write_checkpoint -force design_before_route.dcp
+ make_manual_routes routes.txt
+ route_design -directive Quick -preserve
+ write_checkpoint -force design.dcp
+
+ write_bitstream -force design.bit
+ write_pip_txtdata design.txt
+}
+
+run
diff --git a/fuzzers/037-iob18-pips/ioi_pip_list.tcl b/fuzzers/037-iob18-pips/ioi_pip_list.tcl
new file mode 100644
index 0000000..854873c
--- /dev/null
+++ b/fuzzers/037-iob18-pips/ioi_pip_list.tcl
@@ -0,0 +1,47 @@
+# Copyright (C) 2017-2022 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
+proc print_tile_pips {tile_type filename} {
+ set fp [open $filename w]
+ set pips [dict create]
+ foreach tile [get_tiles -filter "TYPE == $tile_type"] {
+ foreach pip [lsort [get_pips -of_objects $tile]] {
+ set src [get_wires -uphill -of_objects $pip]
+ set dst [get_wires -downhill -of_objects $pip]
+
+ # Skip pips with disconnected nodes
+ set src_node [get_nodes -of_objects $src]
+
+ if { $src_node == {} } {
+ continue
+ }
+
+ set dst_node [get_nodes -of_objects $src]
+ if { $dst_node == {} } {
+ continue
+ }
+
+ set src_wire [regsub {.*/} $src ""]
+ set src_match [regexp {IOI_OCLKM?_[01]} $src_wire]
+
+ if { [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1 || $src_match } {
+ set pip_string "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
+ if ![dict exists $pips $pip_string] {
+ puts $fp $pip_string
+ dict set pips $pip_string 1
+ }
+ }
+ }
+ }
+ close $fp
+}
+
+create_project -force -part $::env(XRAY_PART) design design
+set_property design_mode PinPlanning [current_fileset]
+open_io_design -name io_1
+
+print_tile_pips RIOI rioi.txt
diff --git a/fuzzers/037-iob18-pips/output_cmt.tcl b/fuzzers/037-iob18-pips/output_cmt.tcl
new file mode 100644
index 0000000..9ab8cf8
--- /dev/null
+++ b/fuzzers/037-iob18-pips/output_cmt.tcl
@@ -0,0 +1,18 @@
+# Copyright (C) 2017-2022 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
+set_property design_mode PinPlanning [current_fileset]
+open_io_design -name io_1
+
+set fp [open "cmt_regions.csv" "w"]
+foreach site_type {MMCME2_ADV BUFHCE BUFR BUFMRCE BUFIO ILOGICE2 OLOGICE2 IDELAYE2 IDELAYCTRL PLLE2_ADV} {
+ foreach site [get_sites -filter "SITE_TYPE == $site_type"] {
+ puts $fp "$site,[get_property CLOCK_REGION $site]"
+ }
+}
+close $fp
diff --git a/fuzzers/037-iob18-pips/top.py b/fuzzers/037-iob18-pips/top.py
new file mode 100644
index 0000000..f7ecea0
--- /dev/null
+++ b/fuzzers/037-iob18-pips/top.py
@@ -0,0 +1,391 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+import random
+import math
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray import verilog
+from prjxray import lut_maker
+from prjxray.db import Database
+
+NOT_INCLUDED_TILES = ['RIOI_SING']
+
+SITE_TYPES = ['OLOGICE2', 'ILOGICE2']
+
+
+def read_site_to_cmt():
+ """ Yields clock sources and which CMT they route within. """
+ with open(os.path.join(os.getenv('FUZDIR'), 'build',
+ 'cmt_regions.csv')) as f:
+ for l in f:
+ site, cmt = l.strip().split(',')
+ yield (site, cmt)
+
+
+def gen_sites():
+ ''' Return dict of ISERDES/OSERDES locations. '''
+ db = Database(util.get_db_root(), util.get_part())
+ grid = db.grid()
+
+ xy_fun = util.create_xy_fun('\S+')
+
+ tiles = grid.tiles()
+
+ for tile_name in sorted(tiles):
+ loc = grid.loc_of_tilename(tile_name)
+ gridinfo = grid.gridinfo_at_loc(loc)
+ tile_type = gridinfo.tile_type
+
+ tile = {'tile': tile_name, 'tile_type': tile_type, 'ioi_sites': {}}
+
+ for site_name, site_type in gridinfo.sites.items():
+ if site_type in SITE_TYPES:
+ xy = xy_fun(site_name)
+ if xy not in tile['ioi_sites']:
+ tile['ioi_sites'][xy] = {}
+
+ tile['ioi_sites'][xy][site_type] = site_name
+
+ yield tile
+
+
+class ClockSources(object):
+ def __init__(self):
+ self.site_to_cmt = dict(read_site_to_cmt())
+
+ self.leaf_gclks = {}
+ self.ioclks = {}
+ self.rclks = {}
+ self.selected_leaf_gclks = {}
+ self.lut_maker = lut_maker.LutMaker()
+
+ for cmt in set(self.site_to_cmt.values()):
+ self.leaf_gclks[cmt] = []
+ self.ioclks[cmt] = []
+ self.rclks[cmt] = []
+
+ def init_clocks(self):
+ """ Initialize all IOI clock sources. """
+ for site, cmt in self.site_to_cmt.items():
+ clk = 'clk_' + site
+ if 'BUFHCE' in site:
+ print(
+ """
+ wire {clk};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ BUFH bufh_{site}(
+ .O({clk})
+ );
+ """.format(
+ clk=clk,
+ site=site,
+ ))
+
+ self.leaf_gclks[cmt].append(clk)
+
+ if 'BUFIO' in site:
+ print(
+ """
+ wire {clk};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ BUFIO bufio_{site}(
+ .O({clk})
+ );
+ """.format(
+ clk=clk,
+ site=site,
+ ))
+
+ self.ioclks[cmt].append(clk)
+
+ if 'BUFR' in site:
+ print(
+ """
+ wire {clk};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ BUFR bufr_{site}(
+ .O({clk})
+ );
+ """.format(
+ clk=clk,
+ site=site,
+ ))
+
+ self.rclks[cmt].append(clk)
+
+ # Choose 6 leaf_gclks to be used in each CMT.
+ for cmt in self.leaf_gclks:
+ self.selected_leaf_gclks[cmt] = random.sample(
+ self.leaf_gclks[cmt], 6)
+
+ def get_clock(
+ self,
+ site,
+ allow_ioclks,
+ allow_rclks,
+ allow_fabric=True,
+ allow_empty=True):
+ cmt = self.site_to_cmt[site]
+ choices = []
+ if allow_fabric:
+ choices.append('lut')
+
+ if allow_empty:
+ choices.append('')
+
+ choices.extend(self.selected_leaf_gclks[cmt])
+ if allow_ioclks:
+ choices.extend(self.ioclks[cmt])
+
+ if allow_rclks:
+ choices.extend(self.rclks[cmt])
+
+ clock = random.choice(choices)
+ is_lut = False
+ if clock == "lut":
+ clock = self.lut_maker.get_next_output_net()
+ is_lut = True
+ return clock, is_lut
+
+
+def add_port(ports, port, signal):
+ ports.append('.{}({})'.format(port, signal))
+
+
+def run():
+ print("module top();")
+
+ clocks = ClockSources()
+ clocks.init_clocks()
+ """
+
+ ISERDESE2 clock sources:
+
+ CLK/CLKB:
+ - Allows LEAF_GCLK, IOCLKS, RCLKS and fabric
+ - Dedicated pips
+
+ CLKDIV:
+ - No dedicated pips, uses fabric clock in.
+
+ CLKDIVP:
+ - Has pips, MIG only, PHASER or fabric.
+
+ OCLK/OCLKB:
+ - Allows LEAF_GCLK, IOCLKS, RCLKS and fabric
+ - Must match OSERDESE2:CLK/CLKB
+
+ OSERDESE2 clock sources:
+
+ CLKDIV/CLKDIVB:
+ - Allows LEAF_GCLK and RCLKS and fabric
+ - Dedicated pips
+
+ CLKDIVF/CLKDIVFB:
+ - Allows LEAF_GCLK and RCLKS and fabric
+ - No explicit port, follows CLKDIV/CLKDIVB?
+ """
+
+ output = []
+ route_file = open("routes.txt", "w")
+
+ for tile in gen_sites():
+ if tile['tile_type'] in NOT_INCLUDED_TILES:
+ continue
+
+ for xy in tile['ioi_sites']:
+ ilogic_site_type = random.choice([None, 'ISERDESE2', 'IDDR'])
+ use_oserdes = random.randint(0, 1)
+
+ ilogic_site = tile['ioi_sites'][xy]['ILOGICE2']
+ ologic_site = tile['ioi_sites'][xy]['OLOGICE2']
+
+ if use_oserdes:
+ oclk, _ = clocks.get_clock(
+ ologic_site, allow_ioclks=True, allow_rclks=True)
+
+ oclkb = oclk
+ else:
+ oclk, is_lut = clocks.get_clock(
+ ilogic_site, allow_ioclks=True, allow_rclks=True)
+
+ if random.randint(0, 1):
+ oclkb = oclk
+ else:
+ if random.randint(0, 1):
+ oclkb, _ = clocks.get_clock(
+ ilogic_site,
+ allow_ioclks=True,
+ allow_rclks=True,
+ allow_fabric=not is_lut)
+ else:
+ # Explicitly provide IMUX stimulus to resolve IMUX pips
+ oclk = random.randint(0, 1)
+ oclkb = random.randint(0, 1)
+
+ DATA_RATE = random.choice(['DDR', 'SDR'])
+ clk, clk_is_lut = clocks.get_clock(
+ ilogic_site,
+ allow_ioclks=True,
+ allow_rclks=True,
+ allow_empty=DATA_RATE == 'SDR')
+
+ clkb = clk
+ while clkb == clk:
+ clkb, clkb_is_lut = clocks.get_clock(
+ ilogic_site,
+ allow_ioclks=True,
+ allow_rclks=True,
+ allow_empty=False)
+
+ imux_available = {
+ 0: set(("IOI_IMUX20_0", "IOI_IMUX22_0")),
+ 1: set(("IOI_IMUX20_1", "IOI_IMUX22_1")),
+ }
+
+ # Force CLK route through IMUX when connected to a LUT
+ if clk_is_lut:
+ y = (xy[1] + 1) % 2
+
+ route = random.choice(list(imux_available[y]))
+ imux_available[y].remove(route)
+
+ route = "{}/{}".format(tile["tile"], route)
+ route_file.write("{} {}\n".format(clk, route))
+
+ # Force CLKB route through IMUX when connected to a LUT
+ if clkb_is_lut:
+ y = (xy[1] + 1) % 2
+
+ route = random.choice(list(imux_available[y]))
+ imux_available[y].remove(route)
+
+ route = "{}/{}".format(tile["tile"], route)
+ route_file.write("{} {}\n".format(clkb, route))
+
+ if ilogic_site_type is None:
+ pass
+
+ elif ilogic_site_type == 'ISERDESE2':
+ INTERFACE_TYPE = random.choice(
+ [
+ 'MEMORY',
+ 'MEMORY_DDR3',
+ 'MEMORY_QDR',
+ 'NETWORKING',
+ 'OVERSAMPLE',
+ ])
+ ports = []
+
+ add_port(ports, 'CLK', clk)
+ add_port(ports, 'CLKB', clkb)
+ add_port(ports, 'OCLK', oclk)
+ add_port(ports, 'OCLKB', oclkb)
+
+ output.append(
+ """
+ (* KEEP, DONT_TOUCH, LOC="{site}" *)
+ ISERDESE2 #(
+ .DATA_RATE({DATA_RATE}),
+ .INTERFACE_TYPE({INTERFACE_TYPE}),
+ .IS_CLK_INVERTED({IS_CLK_INVERTED}),
+ .IS_CLKB_INVERTED({IS_CLKB_INVERTED}),
+ .IS_OCLK_INVERTED({IS_OCLK_INVERTED}),
+ .IS_OCLKB_INVERTED({IS_OCLKB_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})
+ ) iserdes_{site}(
+ {ports});""".format(
+ site=ilogic_site,
+ ports=',\n'.join(ports),
+ DATA_RATE=verilog.quote(DATA_RATE),
+ INTERFACE_TYPE=verilog.quote(INTERFACE_TYPE),
+ IS_CLK_INVERTED=random.randint(0, 1),
+ IS_CLKB_INVERTED=random.randint(0, 1),
+ IS_OCLK_INVERTED=random.randint(0, 1),
+ IS_OCLKB_INVERTED=random.randint(0, 1),
+ 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),
+ ))
+ elif ilogic_site_type == 'IDDR':
+ ports = []
+ add_port(ports, 'C', clk)
+ add_port(ports, 'CB', clkb)
+
+ output.append(
+ """
+ (* KEEP, DONT_TOUCH, LOC="{site}" *)
+ IDDR_2CLK #(
+ .INIT_Q1({INIT_Q1}),
+ .INIT_Q2({INIT_Q2}),
+ .SRTYPE({SRTYPE})
+ ) iserdes_{site}(
+ {ports});""".format(
+ site=ilogic_site,
+ ports=',\n'.join(ports),
+ INIT_Q1=random.randint(0, 1),
+ INIT_Q2=random.randint(0, 1),
+ SRTYPE=verilog.quote(random.choice(['ASYNC', 'SYNC'])),
+ ))
+ else:
+ assert False, ilogic_site_type
+
+ if use_oserdes:
+ ports = []
+
+ add_port(
+ ports, 'CLKDIV',
+ clocks.get_clock(
+ ologic_site,
+ allow_ioclks=False,
+ allow_rclks=True,
+ )[0])
+
+ add_port(ports, 'CLK', oclk)
+
+ output.append(
+ """
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ OSERDESE2 #(
+ .IS_CLK_INVERTED({IS_CLK_INVERTED}),
+ .DATA_RATE_OQ("SDR"),
+ .DATA_RATE_TQ("SDR")
+ ) oserdes_{site} (
+ {ports});""".format(
+ IS_CLK_INVERTED=random.randint(0, 1),
+ site=ologic_site,
+ ports=',\n'.join(ports),
+ ))
+
+ for s in clocks.lut_maker.create_wires_and_luts():
+ print(s)
+
+ for s in output:
+ print(s)
+
+ print("endmodule")
+
+
+if __name__ == '__main__':
+ run()
diff --git a/fuzzers/039-hclk-config/Makefile b/fuzzers/039-hclk-config/Makefile
index ae18a36..4828018 100644
--- a/fuzzers/039-hclk-config/Makefile
+++ b/fuzzers/039-hclk-config/Makefile
@@ -9,7 +9,11 @@
include ../fuzzer.mk
+ifeq ($(XRAY_DATABASE),kintex7)
+database: build/segbits_hclk_ioi.db
+else
database: build/segbits_hclk_ioi3.db
+endif
build/segbits_hclk_ioi3.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -c 5 -o build/segbits_hclk_ioi3.rdb \
@@ -22,8 +26,20 @@
${XRAY_MASKMERGE} build/mask_hclk_ioi3.db \
$(addsuffix /segdata_hclk_ioi3.txt,$(SPECIMENS))
+# The fuzzer results for the high performance banks
+# are identical, so just copy those
+ifeq ($(XRAY_DATABASE),kintex7)
+build/segbits_hclk_ioi.db: build/segbits_hclk_ioi3.db
+ sed -e 's/HCLK_IOI3/HCLK_IOI/g' $< > $@
+ cp build/mask_hclk_ioi3.db build/mask_hclk_ioi.db
+endif
+
pushdb: database
${XRAY_MERGEDB} hclk_ioi3 build/segbits_hclk_ioi3.db
${XRAY_MERGEDB} mask_hclk_ioi3 build/mask_hclk_ioi3.db
+ifeq ($(XRAY_DATABASE),kintex7)
+ ${XRAY_MERGEDB} hclk_ioi build/segbits_hclk_ioi.db
+ ${XRAY_MERGEDB} mask_hclk_ioi build/mask_hclk_ioi.db
+endif
.PHONY: database pushdb
diff --git a/fuzzers/047-hclk-ioi18-pips/Makefile b/fuzzers/047-hclk-ioi18-pips/Makefile
new file mode 100644
index 0000000..3d04344
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/Makefile
@@ -0,0 +1,53 @@
+# Copyright (C) 2017-2022 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
+export FUZDIR=$(shell pwd)
+PIP_TYPE?=hclk_ioi
+PIPLIST_TCL=$(FUZDIR)/hclk_ioi_pip_list.tcl
+TODO_RE=".*"
+# FIXME Modify fuzzer to solve PIPs that drive the BUFIO and BUFR from ILOGIC clock or through the IOI tile.
+EXCLUDE_RE=".*\.HCLK_IOI_((I2IOCLK)|(IDELAYCTRL))"
+
+MAKETODO_FLAGS= --sides "" --pip-type ${PIP_TYPE} --seg-type ${PIP_TYPE} --re $(TODO_RE) --exclude-re $(EXCLUDE_RE)
+N = 499
+
+SEGMATCH_FLAGS=-c 4 -m 4 -M 4
+SPECIMENS_DEPS=build/cmt_regions.csv
+A_PIPLIST=hclk_ioi.txt
+
+include ../pip_loop.mk
+
+build/segbits_hclk_ioi.rdb: $(SPECIMENS_OK)
+ ${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_hclk_ioi.rdb \
+ $(shell find build -name segdata_hclk_ioi.txt)
+
+build/segbits_hclk_ioi.db: build/segbits_hclk_ioi.rdb
+ ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
+ --seg-fn-in build/segbits_hclk_ioi.rdb \
+ --seg-fn-out build/segbits_hclk_ioi.db
+
+ # Keep a copy to track iter progress
+ cp build/segbits_hclk_ioi.rdb build/$(ITER)/segbits_hclk_ioi.rdb
+
+
+ ${XRAY_MASKMERGE} build/mask_hclk_ioi.db \
+ $(shell find build -name segdata_hclk_ioi.txt)
+
+database: build/segbits_hclk_ioi.db
+ # Clobber existing .db to eliminate potential conflicts
+ cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
+ XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} hclk_ioi build/segbits_hclk_ioi.db
+
+build/cmt_regions.csv: output_cmt.tcl
+ mkdir -p build
+ cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl
+
+pushdb: database
+ ${XRAY_MERGEDB} hclk_ioi build/segbits_hclk_ioi.db
+ ${XRAY_MERGEDB} mask_hclk_ioi build/mask_hclk_ioi.db
+
+.PHONY: database pushdb
diff --git a/fuzzers/047-hclk-ioi18-pips/README.md b/fuzzers/047-hclk-ioi18-pips/README.md
new file mode 100644
index 0000000..8f1c36a
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/README.md
@@ -0,0 +1,3 @@
+# HCLK_IOI interconnect fuzzer
+
+Solves pips located within the HCLK_IOI switch box.
diff --git a/fuzzers/047-hclk-ioi18-pips/bits.dbf b/fuzzers/047-hclk-ioi18-pips/bits.dbf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/bits.dbf
diff --git a/fuzzers/047-hclk-ioi18-pips/generate.py b/fuzzers/047-hclk-ioi18-pips/generate.py
new file mode 100644
index 0000000..eef904e
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/generate.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+
+from prjxray.segmaker import Segmaker
+import os
+import os.path
+
+
+def bitfilter(frame, word):
+ if frame < 26:
+ return False
+ return True
+
+
+def main():
+ segmk = Segmaker("design.bits")
+
+ tiledata = {}
+ pipdata = {}
+ ignpip = set()
+ tile_ports = {}
+
+ with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
+ 'hclk_ioi', 'hclk_ioi.txt')) as f:
+ for l in f:
+ tile_type, dst, src = l.strip().split('.')
+ if tile_type not in pipdata:
+ pipdata[tile_type] = []
+ tile_ports[tile_type] = set()
+
+ pipdata[tile_type].append((src, dst))
+ tile_ports[tile_type].add(src)
+ tile_ports[tile_type].add(dst)
+
+ print("Loading tags from design.txt.")
+ with open("design.txt", "r") as f:
+ for line in f:
+ tile, pip, src, dst, pnum, pdir = line.split()
+
+ if not tile.startswith('HCLK_IOI_'):
+ continue
+
+ pip_prefix, _ = pip.split(".")
+ tile_from_pip, tile_type = pip_prefix.split('/')
+ assert tile == tile_from_pip
+ _, src = src.split("/")
+ _, dst = dst.split("/")
+ pnum = int(pnum)
+ pdir = int(pdir)
+
+ if tile not in tiledata:
+ tiledata[tile] = {
+ "type": tile_type,
+ "pips": set(),
+ "srcs": set(),
+ "dsts": set()
+ }
+
+ tiledata[tile]["pips"].add((src, dst))
+ tiledata[tile]["srcs"].add(src)
+ tiledata[tile]["dsts"].add(dst)
+
+ if pdir == 0:
+ tiledata[tile]["srcs"].add(dst)
+ tiledata[tile]["dsts"].add(src)
+
+ for tile, pips_srcs_dsts in tiledata.items():
+ tile_type = pips_srcs_dsts["type"]
+ pips = pips_srcs_dsts["pips"]
+
+ for src, dst in pipdata[tile_type]:
+ if (src, dst) in ignpip:
+ pass
+ elif (src, dst) in pips:
+ segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 1)
+ elif dst not in tiledata[tile]["dsts"]:
+ segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0)
+
+ segmk.compile(bitfilter=bitfilter)
+ segmk.write()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/fuzzers/047-hclk-ioi18-pips/generate.tcl b/fuzzers/047-hclk-ioi18-pips/generate.tcl
new file mode 100644
index 0000000..f75db3c
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/generate.tcl
@@ -0,0 +1,358 @@
+# Copyright (C) 2017-2022 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
+source "$::env(XRAY_DIR)/utils/utils.tcl"
+
+proc load_todo {{dir "dst"}} {
+ set fp [open "../../todo_all.txt" r]
+
+ # Create map of pip source to remaining destinations for that pip
+ set todo_map [dict create]
+ for {gets $fp line} {$line != ""} {gets $fp line} {
+ set parts [split $line .]
+ if {$dir == "dsts"} {
+ dict lappend todo_map [lindex $parts 2] [list [lindex $parts 0] [lindex $parts 1]]
+ } elseif {$dir == "srcs"} {
+ dict lappend todo_map [lindex $parts 1] [list [lindex $parts 0] [lindex $parts 2]]
+ } else {
+ error "Incorrect argument. Available options: src, dst"
+ }
+ }
+ close $fp
+ return $todo_map
+}
+
+proc shuffle_list {list} {
+ set l [llength $list]
+ for {set i 0} {$i<=$l} {incr i} {
+ set x [lindex $list [set p [expr {int(rand()*$l)}]]]
+ set list [lreplace $list $p $p]
+ set list [linsert $list [expr {int(rand()*$l)}] $x]
+ }
+
+ return $list
+}
+
+# Get the dictionary of nets with one corresponding source wire
+# of a PIP from the todo list
+proc get_nets_with_todo_pip_wires {direction net_regexp wire_regexp used_destinations {verbose false}} {
+ set todo_map [load_todo $direction]
+ puts $todo_map
+ set nets [get_nets]
+ set todo_nets [dict create]
+
+ foreach net $nets {
+ if {![regexp $net_regexp $net]} {
+ continue
+ }
+ # Check to see if this net is one we are interested in*
+ set wires [get_wires -of_objects $net -filter {TILE_NAME =~ "*HCLK_IOI*" } -quiet]
+
+ set wire_found 0
+ foreach wire $wires {
+ if [regexp $wire_regexp $wire] {
+ set wire_found 1
+ break
+ }
+ }
+
+ if {$wire_found == 0} {
+ if {$verbose} {
+ puts "$net not going to a HCLK port, skipping."
+ }
+ continue
+ }
+
+ set tile [lindex [split $wire /] 0]
+ set wire [lindex [split $wire /] 1]
+ set tile_type [get_property TILE_TYPE [get_tiles $tile]]
+
+
+ if { ![dict exists $todo_map $wire] } {
+ continue
+ }
+
+ set candidates [dict get $todo_map $wire]
+
+ # This net is interesting, see if it is already going somewhere we
+ # want.
+ set found_target 0
+ foreach other_wire $wires {
+ if { $found_target == 1 } {
+ break
+ }
+
+ set other_wire [lindex [split $other_wire /] 1]
+
+ if { $wire == $other_wire } {
+ continue
+ }
+
+ foreach candidate $candidates {
+ set candidate_tile_type [lindex $candidate 0]
+
+ if {$candidate_tile_type != $tile_type} {
+ continue
+ }
+
+ set candidate_wire [lindex $candidate 1]
+
+ if { $other_wire == $candidate } {
+ set found_target 1
+ if {$verbose} {
+ puts "Interesting net $net already going from $wire to $other_wire."
+ }
+ set_property IS_ROUTE_FIXED 1 $net
+ dict set used_destinations "$tile/$candidate_wire" 1
+ break
+ }
+ }
+ }
+
+ if { $found_target == 1 } {
+ # Net already has an interesting feature - don't reroute.
+ continue
+ }
+
+ dict set todo_nets $net [list $tile $wire]
+ if {$verbose} {
+ puts "Interesting net $net (including $wire) is being rerouted."
+ }
+ }
+ return $todo_nets
+}
+
+proc route_todo {} {
+ set used_destinations [dict create]
+ set todo_map [load_todo "dsts"]
+ set serdes_nets [get_nets_with_todo_pip_wires "dsts" "serdes_clk_ILOGIC" "HCLK_IOI_CK_IGCLK" $used_destinations]
+ puts "Serdes nets: $serdes_nets"
+ dict for {net tile_wire} $serdes_nets {
+ set tile [lindex $tile_wire 0]
+ set wire [lindex $tile_wire 1]
+ set dsts [dict get $todo_map $wire]
+ set tile_type [get_property TILE_TYPE [get_tiles $tile]]
+ set todos {}
+
+ set old_target_wire [get_wires -of_objects $net -filter {TILE_NAME =~ "*HCLK_IOI*" && NAME =~ "*HCLK_IOI_LEAF_GCLK_*"}]
+ if {$old_target_wire == {}} {
+ continue
+ }
+ if {[dict exists $used_destinations $old_target_wire]} {
+ puts "Not routing to $old_target_wire, in use."
+ continue
+ }
+ puts "Rerouting net $net at $tile / $wire (type $tile_type)"
+ puts "Previous target wire: $old_target_wire"
+ set old_target_node [get_nodes -of_objects $old_target_wire]
+ if [regexp "HCLK_IOI_LEAF_GCLK_\(\(TOP\)|\(BOT\)\).*" $old_target_wire match group] {
+ set old_target_side $group
+ }
+ foreach dst $dsts {
+ set dst_tile_type [lindex $dst 0]
+ if {$dst_tile_type != $tile_type} {
+ continue
+ }
+
+ set dst_wire [lindex $dst 1]
+
+ set is_gclk_net 0
+ if [regexp "HCLK_IOI_LEAF_GCLK_\(\(TOP\)|\(BOT\)\).*" $dst_wire match group] {
+ set is_gclk_net 1
+ set dst_side $group
+ }
+
+ if {$is_gclk_net == 0 || $dst_side != $old_target_side} {
+ continue
+ }
+
+ lappend todos $dst_wire
+ }
+
+ set todos_length [llength $todos]
+ if {$todos_length == 0} {
+ continue
+ }
+
+ puts "All todos for $tile_type / $wire"
+ foreach dst_wire $todos {
+ puts " - $dst_wire"
+ }
+
+ set todos [shuffle_list $todos]
+
+ set origin_node [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]]
+ puts "Origin node: $origin_node"
+ route_design -unroute -nets $net
+
+ # Find an input in the todo list that this can can drive.
+ foreach dst_wire $todos {
+ if { [dict exists $used_destinations "$tile/$dst_wire"] } {
+ puts "Not routing to $tile / $dst_wire, in use."
+ continue
+ }
+
+ set target_wire [get_wires "$tile/$dst_wire"]
+ set target_node [get_nodes -of_objects $target_wire]
+ if {[llength $target_node] == 0} {
+ error "Failed to find node for $tile/$dst_wire."
+ }
+
+ set old_net [get_nets -of_objects $target_node -quiet]
+ if {$old_net == {}} {
+ continue
+ }
+ puts "Unrouting the old net: $old_net"
+ route_design -unroute -nets $old_net
+ set old_origin_node [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $old_net]]
+
+ # Route the net through the desired node
+ puts "Attempting to route to $target_node for net $net."
+ route_via $net [list $target_node]
+
+ puts "Attempting to route to $old_target_node for net $old_net."
+ # Route the old net through the old target node
+ route_via $old_net [list $old_target_node ]
+
+ puts "Origin node: $origin_node, Old origin node: $old_origin_node"
+ puts "Target wire: $target_wire, Old target wire: $old_target_wire"
+ puts "Target node: $target_node, Old target node: $old_target_node"
+
+ dict set used_destinations "$target_wire" 1
+ dict set used_destinations "$old_target_wire" 1
+
+ break
+ }
+ }
+
+ set todo_map [load_todo "srcs"]
+ set before_div_nets [get_nets_with_todo_pip_wires "srcs" "I_BUFR" "HCLK_IOI_RCLK_BEFORE_DIV" $used_destinations]
+ puts "Before div nets: $before_div_nets"
+ dict for {net tile_wire} $before_div_nets {
+ set tile [lindex $tile_wire 0]
+ set wire [lindex $tile_wire 1]
+ set srcs [dict get $todo_map $wire]
+ set tile_type [get_property TILE_TYPE [get_tiles $tile]]
+ set todos {}
+
+ set old_origin_wire [get_wires -of_objects $net -filter {TILE_NAME =~ "*HCLK_IOI*" && NAME =~ "*HCLK_IOI_RCLK_IMUX*"}]
+ if {$old_origin_wire == {}} {
+ continue
+ }
+
+ puts "Rerouting net $net at $tile / $wire (type $tile_type)"
+ puts "Previous target wire: $old_origin_wire"
+
+ set old_origin_node [get_nodes -of_objects $old_origin_wire]
+ if [regexp "HCLK_IOI_RCLK_IMUX.*" $old_origin_wire match group] {
+ set old_target_side $group
+ }
+ foreach src $srcs {
+ set src_tile_type [lindex $src 0]
+ if {$src_tile_type != $tile_type} {
+ continue
+ }
+
+ set src_wire [lindex $src 1]
+
+ set is_gclk_net 0
+ if [regexp "HCLK_IOI_RCLK_IMUX.*" $src_wire match group] {
+ set is_gclk_net 1
+ }
+
+ if {$is_gclk_net == 0} {
+ continue
+ }
+
+ lappend todos $src_wire
+ }
+
+ set todos_length [llength $todos]
+ if {$todos_length == 0} {
+ continue
+ }
+
+ puts "All todos for $tile_type / $wire"
+ foreach src_wire $todos {
+ puts " - $src_wire"
+ }
+
+ set todos [shuffle_list $todos]
+
+ set target_node [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net]]
+ puts "Target node: $target_node"
+ route_design -unroute -nets $net
+
+ # Find an output in the todo list that can drive.
+ foreach src_wire $todos {
+ if { [dict exists $used_destinations "$tile/$src_wire"] } {
+ puts "Not routing to $tile / $src_wire, in use."
+ continue
+ }
+
+ set origin_wire [get_wires "$tile/$src_wire"]
+ set origin_node [get_nodes -of_objects $origin_wire]
+ if {[llength $origin_node] == 0} {
+ error "Failed to find node for $tile/$src_wire."
+ }
+
+ set old_net [get_nets -of_objects $origin_node -quiet]
+ if {$old_net != {}} {
+ puts "Unrouting the old net: $old_net"
+ route_design -unroute -nets $old_net
+ }
+
+ # Route the net through the desired node
+ puts "Attempting to route to $src_wire for net $net."
+ route_via $net [list $origin_node]
+
+ puts "Target node: $target_node"
+ puts "Origin wire: $origin_wire, Old origin wire: $old_origin_wire"
+ puts "Origin node: $origin_node, Old origin node: $old_origin_node"
+
+ dict set used_destinations "$origin_wire" 1
+
+ break
+ }
+ }
+}
+
+proc run {} {
+ 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_property IS_ENABLED 0 [get_drc_checks {PDRC-29}]
+ set_property IS_ENABLED 0 [get_drc_checks {PDRC-38}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-13}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-123}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-161}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-1575}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-1684}]
+ set_property IS_ENABLED 0 [get_drc_checks {REQP-1712}]
+ set_property IS_ENABLED 0 [get_drc_checks {AVAL-50}]
+ set_property IS_ENABLED 0 [get_drc_checks {AVAL-78}]
+ set_property IS_ENABLED 0 [get_drc_checks {AVAL-81}]
+
+
+ set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
+
+ place_design
+ route_design
+ route_todo
+ route_design
+
+
+ write_checkpoint -force design.dcp
+ write_bitstream -force design.bit
+ write_pip_txtdata design.txt
+}
+
+run
diff --git a/fuzzers/047-hclk-ioi18-pips/hclk_ioi_pip_list.tcl b/fuzzers/047-hclk-ioi18-pips/hclk_ioi_pip_list.tcl
new file mode 100644
index 0000000..555f10c
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/hclk_ioi_pip_list.tcl
@@ -0,0 +1,49 @@
+# Copyright (C) 2017-2022 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
+proc print_tile_pips {tile_type filename} {
+ set fp [open $filename w]
+ set pips [dict create]
+ foreach tile [get_tiles -filter "TYPE == $tile_type"] {
+ puts "Dumping PIPs for tile $tile ($tile_type) to $filename."
+ foreach pip [lsort [get_pips -of_objects $tile]] {
+ set src [get_wires -uphill -of_objects $pip]
+ set dst [get_wires -downhill -of_objects $pip]
+
+ # Skip pips with disconnected nodes
+ set src_node [get_nodes -of_objects $src]
+ if { $src_node == {} } {
+ continue
+ }
+
+ set dst_node [get_nodes -of_objects $dst]
+ if { $dst_node == {} } {
+ continue
+ }
+
+ set dst_wire [regsub {.*/} $dst ""]
+ set dst_match [regexp {HCLK_IOI_CK_IGCLK[0-9]+} $dst_wire]
+
+ if {[llength [get_nodes -uphill -of_objects $dst_node]] > 1 || $dst_match} {
+ set pip_string "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
+ if ![dict exists $pips $pip_string] {
+ puts $fp $pip_string
+ dict set pips $pip_string 1
+ }
+ } else {
+ puts "Ignoring PIP: $pip"
+ }
+ }
+ }
+ close $fp
+}
+
+create_project -force -part $::env(XRAY_PART) design design
+set_property design_mode PinPlanning [current_fileset]
+open_io_design -name io_1
+
+print_tile_pips HCLK_IOI hclk_ioi.txt
diff --git a/fuzzers/047-hclk-ioi18-pips/output_cmt.tcl b/fuzzers/047-hclk-ioi18-pips/output_cmt.tcl
new file mode 100644
index 0000000..7bb9e52
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/output_cmt.tcl
@@ -0,0 +1,18 @@
+# Copyright (C) 2017-2022 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
+set_property design_mode PinPlanning [current_fileset]
+open_io_design -name io_1
+
+set fp [open "cmt_regions.csv" "w"]
+foreach site_type {MMCME2_ADV PLLE2_ADV BUFHCE IOB18M BUFR BUFMRCE BUFIO ILOGICE2 IDELAYCTRL} {
+ foreach site [get_sites -filter "SITE_TYPE == $site_type"] {
+ puts $fp "$site,[get_property CLOCK_REGION $site]"
+ }
+}
+close $fp
diff --git a/fuzzers/047-hclk-ioi18-pips/top.py b/fuzzers/047-hclk-ioi18-pips/top.py
new file mode 100644
index 0000000..bf84a50
--- /dev/null
+++ b/fuzzers/047-hclk-ioi18-pips/top.py
@@ -0,0 +1,479 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2017-2022 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
+""" Emits top.v's for various BUFHCE routing inputs. """
+import os
+import random
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray.lut_maker import LutMaker
+from prjxray.db import Database
+from io import StringIO
+
+CMT_XY_FUN = util.create_xy_fun(prefix='')
+
+
+def read_site_to_cmt():
+ """ Yields clock sources and which CMT they route within. """
+ with open(os.path.join(os.getenv('FUZDIR'), 'build',
+ 'cmt_regions.csv')) as f:
+ for l in f:
+ site, cmt = l.strip().split(',')
+ yield (site, cmt)
+
+
+class ClockSources(object):
+ """ Class for tracking clock sources.
+ """
+
+ def __init__(self, limit=14):
+ self.sources = {}
+ self.source_to_cmt = {}
+ self.used_sources_from_cmt = {}
+ self.limit = limit
+
+ def add_clock_source(self, source, cmt):
+ """ Adds a source from a specific CMT.
+
+ cmt='ANY' indicates that this source can be routed to any CMT.
+ """
+ if cmt not in self.sources:
+ self.sources[cmt] = []
+
+ self.sources[cmt].append(source)
+ self.source_to_cmt[source] = cmt
+
+ def get_random_source(self, cmt, no_repeats=False):
+ """ Get a random source that is routable to the specific CMT.
+
+ get_random_source will return a source that is either cmt='ANY',
+ cmt equal to the input CMT, or the adjecent CMT.
+
+ """
+
+ choices = []
+
+ if cmt in self.sources:
+ choices.extend(self.sources[cmt])
+
+ random.shuffle(choices)
+ for source in choices:
+
+ source_cmt = self.source_to_cmt[source]
+
+ if source_cmt not in self.used_sources_from_cmt:
+ self.used_sources_from_cmt[source_cmt] = set()
+
+ if no_repeats and source in self.used_sources_from_cmt[source_cmt]:
+ continue
+
+ if len(self.used_sources_from_cmt[source_cmt]) >= self.limit:
+ continue
+
+ self.used_sources_from_cmt[source_cmt].add(source)
+ return source
+
+ return None
+
+
+def main():
+ """
+ HCLK_IOI has the following inputs:
+
+ 12 (east) BUFH from the right side of the HROW
+ 12 (west) Bounce PIPs from one BUFH to any of 6 GCLK_BOT and 6 GCLK_TOP
+ 4 (east) PHSR_PERFCLK (IOCLK_PLL) from HCLK_CLB to input of BUFIO
+ 8 (4 north and 4 south) BUFR CLR and CE
+ 2 (south) I2IOCLK to input of BUFR
+ 2 (north) I2IOCLK to input of BUFR
+ 2 RCLK IMUX (IMUX0 and IMUX1) choosing input of BUFR
+
+ outputs:
+ 4 (east) BUFRCLK - from BUFR to HROW
+ 4 (north) BUFR2IO - from BUFR
+ 4 (north) IOCLK from BUFIO
+
+ """
+
+ global_clock_sources = ClockSources()
+ cmt_clock_sources = ClockSources()
+ cmt_fast_clock_sources = ClockSources(4)
+ bufr_clock_sources = ClockSources()
+ bufio_clock_sources = ClockSources()
+ site_to_cmt = dict(read_site_to_cmt())
+ clock_region_limit = dict()
+ clock_region_serdes_location = dict()
+
+ db = Database(util.get_db_root(), util.get_part())
+ grid = db.grid()
+
+ def gen_sites(desired_site_type):
+ for tile_name in sorted(grid.tiles()):
+ loc = grid.loc_of_tilename(tile_name)
+ gridinfo = grid.gridinfo_at_loc(loc)
+ for site, site_type in gridinfo.sites.items():
+ if site_type == desired_site_type:
+ yield tile_name, site
+
+ def serdes_relative_location(tile, site):
+ (serdes_loc_x, serdes_loc_y) = grid.loc_of_tilename(tile)
+ serdes_clk_reg = site_to_cmt[site]
+ for tile_name in sorted(grid.tiles()):
+ if 'HCLK_IOI' in tile_name:
+ (hclk_tile_loc_x,
+ hclk_tile_loc_y) = grid.loc_of_tilename(tile_name)
+ if hclk_tile_loc_x == serdes_loc_x:
+ gridinfo = grid.gridinfo_at_loc(
+ (hclk_tile_loc_x, hclk_tile_loc_y))
+ random_site = next(iter(gridinfo.sites.keys()))
+ hclk_clk_reg = site_to_cmt[random_site]
+ if hclk_clk_reg == serdes_clk_reg:
+ if serdes_loc_y < hclk_tile_loc_y:
+ return "TOP"
+ elif serdes_loc_y > hclk_tile_loc_y:
+ return "BOTTOM"
+ else:
+ assert False
+
+ clock_region_sites = set()
+
+ def get_clock_region_site(site_type, clk_reg):
+ for site_name, reg in site_to_cmt.items():
+ if site_name.startswith(site_type) and reg in clk_reg:
+ if site_name not in clock_region_sites:
+ clock_region_sites.add(site_name)
+ return site_name
+
+ print(
+ '''
+module top();
+ (* KEEP, DONT_TOUCH *)
+ LUT6 dummy();
+ ''')
+
+ luts = LutMaker()
+ bufs = StringIO()
+
+ for _, site in gen_sites('MMCME2_ADV'):
+ mmcm_clocks = [
+ 'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx)
+ for idx in range(13)
+ ]
+
+ for idx, clk in enumerate(mmcm_clocks):
+ if idx < 4:
+ cmt_fast_clock_sources.add_clock_source(clk, site_to_cmt[site])
+ else:
+ cmt_clock_sources.add_clock_source(clk, site_to_cmt[site])
+
+ print(
+ """
+ wire cin1_{site}, cin2_{site}, clkfbin_{site}, {c0}, {c1}, {c2}, {c3}, {c4}, {c5};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ MMCME2_ADV pll_{site} (
+ .CLKIN1(cin1_{site}),
+ .CLKIN2(cin2_{site}),
+ .CLKFBIN(clkfbin_{site}),
+ .CLKOUT0({c0}),
+ .CLKOUT0B({c4}),
+ .CLKOUT1({c1}),
+ .CLKOUT1B({c5}),
+ .CLKOUT2({c2}),
+ .CLKOUT2B({c6}),
+ .CLKOUT3({c3}),
+ .CLKOUT3B({c7}),
+ .CLKOUT4({c8}),
+ .CLKOUT5({c9}),
+ .CLKOUT6({c10}),
+ .CLKFBOUT({c11}),
+ .CLKFBOUTB({c12})
+ );
+ """.format(
+ site=site,
+ c0=mmcm_clocks[0],
+ c1=mmcm_clocks[1],
+ c2=mmcm_clocks[2],
+ c3=mmcm_clocks[3],
+ c4=mmcm_clocks[4],
+ c5=mmcm_clocks[5],
+ c6=mmcm_clocks[6],
+ c7=mmcm_clocks[7],
+ c8=mmcm_clocks[8],
+ c9=mmcm_clocks[9],
+ c10=mmcm_clocks[10],
+ c11=mmcm_clocks[11],
+ c12=mmcm_clocks[12],
+ ))
+
+ for _, site in gen_sites('PLLE2_ADV'):
+ pll_clocks = [
+ 'pll_clock_{site}_{idx}'.format(site=site, idx=idx)
+ for idx in range(7)
+ ]
+
+ for clk in pll_clocks:
+ cmt_clock_sources.add_clock_source(clk, site_to_cmt[site])
+
+ print(
+ """
+ wire cin1_{site}, cin2_{site}, clkfbin_{site}, {c0}, {c1}, {c2}, {c3}, {c4}, {c5}, {c6};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ PLLE2_ADV pll_{site} (
+ .CLKIN1(cin1_{site}),
+ .CLKIN2(cin2_{site}),
+ .CLKFBIN(clkfbin_{site}),
+ .CLKOUT0({c0}),
+ .CLKOUT1({c1}),
+ .CLKOUT2({c2}),
+ .CLKOUT3({c3}),
+ .CLKOUT4({c4}),
+ .CLKOUT5({c5}),
+ .CLKFBOUT({c6})
+ );
+ """.format(
+ site=site,
+ c0=pll_clocks[0],
+ c1=pll_clocks[1],
+ c2=pll_clocks[2],
+ c3=pll_clocks[3],
+ c4=pll_clocks[4],
+ c5=pll_clocks[5],
+ c6=pll_clocks[6],
+ ))
+
+ for tile_name, site in gen_sites('BUFHCE'):
+ print(
+ """
+ wire I_{site};
+ wire O_{site};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ BUFHCE buf_{site} (
+ .I(I_{site}),
+ .O(O_{site})
+ );""".format(site=site),
+ file=bufs)
+ global_clock_sources.add_clock_source(
+ 'O_{site}'.format(site=site), site_to_cmt[site])
+
+ hclks_used_by_clock_region = {}
+ for cmt in site_to_cmt.values():
+ hclks_used_by_clock_region[cmt] = set()
+
+ def check_hclk_src(src, src_cmt):
+ if len(hclks_used_by_clock_region[src_cmt]
+ ) >= 12 and src not in hclks_used_by_clock_region[src_cmt]:
+ return None
+ else:
+ hclks_used_by_clock_region[src_cmt].add(src)
+ return src
+
+ cmt_clks_used_by_clock_region = {}
+ for cmt in site_to_cmt.values():
+ cmt_clks_used_by_clock_region[cmt] = list()
+
+ def check_cmt_clk_src(src, src_clock_region):
+ print(
+ "//src: {}, clk_reg: {}, len {}".format(
+ src, src_clock_region,
+ len(cmt_clks_used_by_clock_region[src_clock_region])))
+ if len(cmt_clks_used_by_clock_region[src_clock_region]) >= 4:
+ return None
+ else:
+ cmt_clks_used_by_clock_region[src_clock_region].append(src)
+ return src
+
+ #Add IDELAYCTRL
+ idelayctrl_in_clock_region = {}
+ for cmt in site_to_cmt.values():
+ idelayctrl_in_clock_region[cmt] = False
+ for _, site in gen_sites('IDELAYCTRL'):
+ if random.random() < 0.5:
+ wire_name = global_clock_sources.get_random_source(
+ site_to_cmt[site], no_repeats=False)
+ if wire_name is None:
+ continue
+ src_cmt = global_clock_sources.source_to_cmt[wire_name]
+ wire_name = check_hclk_src(wire_name, src_cmt)
+
+ if wire_name is None:
+ continue
+ idelayctrl_in_clock_region[src_cmt] = True
+ print(
+ """
+ assign I_{site} = {clock_source};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ IDELAYCTRL idelay_ctrl_{site} (
+ .RDY(),
+ .REFCLK(I_{site}),
+ .RST()
+ );""".format(site=site, clock_source=wire_name))
+
+ # Add SERDES driven by BUFH or MMCM
+ for tile, site in gen_sites('ILOGICE2'):
+ wire_name = None
+ clock_region = site_to_cmt[site]
+ if clock_region not in clock_region_limit:
+ # Select serdes limit and relative location per clock region
+ serdes_location = random.choice(["TOP", "BOTTOM", "ANY"])
+ if serdes_location in "ANY":
+ #We want TOP and BOTTOM IGCLK PIPs occupied but leave one slot for IDELAYCTRL
+ if idelayctrl_in_clock_region[clock_region]:
+ clock_region_limit[clock_region] = 0 if random.random(
+ ) < 0.2 else 11
+ else:
+ clock_region_limit[clock_region] = 0 if random.random(
+ ) < 0.2 else 12
+ else:
+ if idelayctrl_in_clock_region[clock_region]:
+ clock_region_limit[clock_region] = 0 if random.random(
+ ) < 0.2 else 5
+ else:
+ clock_region_limit[clock_region] = 0 if random.random(
+ ) < 0.2 else 6
+
+ clock_region_serdes_location[clock_region] = serdes_location
+
+ # We reached the limit of hclks in this clock region
+ if clock_region_limit[clock_region] == 0:
+ continue
+
+ # Add a serdes if it's located at the correct side from the HCLK_IOI tile
+ if clock_region_serdes_location[clock_region] not in "ANY" and \
+ serdes_relative_location(tile, site) != clock_region_serdes_location[clock_region]:
+ continue
+ if random.random() > 0.3:
+ wire_name = global_clock_sources.get_random_source(
+ site_to_cmt[site], no_repeats=True)
+ if wire_name is None:
+ continue
+ src_cmt = global_clock_sources.source_to_cmt[wire_name]
+ wire_name = check_hclk_src(wire_name, src_cmt)
+ if wire_name is None:
+ print("//wire is None")
+ continue
+ clock_region_limit[clock_region] -= 1
+ print(
+ """
+ assign serdes_clk_{site} = {clock_source};""".format(
+ site=site, clock_source=wire_name))
+ else:
+ wire_name = cmt_fast_clock_sources.get_random_source(
+ site_to_cmt[site], no_repeats=False)
+ if wire_name is None:
+ continue
+ src_cmt = cmt_fast_clock_sources.source_to_cmt[wire_name]
+ wire_name = check_cmt_clk_src(wire_name, src_cmt)
+ if wire_name is None:
+ continue
+ bufio_site = get_clock_region_site("BUFIO", clock_region)
+ if bufio_site is None:
+ continue
+ print(
+ """
+ assign serdes_clk_{serdes_loc} = O_{site};
+ assign I_{site} = {clock_source};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ BUFIO bufio_{site} (
+ .O(O_{site}),
+ .I(I_{site})
+ );""".format(site=bufio_site, clock_source=wire_name, serdes_loc=site))
+
+ print(
+ "// clock_region: {} {}".format(
+ clock_region, clock_region_serdes_location[clock_region]))
+ print(
+ """
+ (* KEEP, DONT_TOUCH, LOC = "{loc}" *)
+ ISERDESE2 #(
+ .DATA_RATE("SDR"),
+ .DATA_WIDTH(4),
+ .DYN_CLKDIV_INV_EN("FALSE"),
+ .DYN_CLK_INV_EN("FALSE"),
+ .INIT_Q1(1'b0),
+ .INIT_Q2(1'b0),
+ .INIT_Q3(1'b0),
+ .INIT_Q4(1'b0),
+ .INTERFACE_TYPE("OVERSAMPLE"),
+ .IOBDELAY("NONE"),
+ .NUM_CE(2),
+ .OFB_USED("FALSE"),
+ .SERDES_MODE("MASTER"),
+ .SRVAL_Q1(1'b0),
+ .SRVAL_Q2(1'b0),
+ .SRVAL_Q3(1'b0),
+ .SRVAL_Q4(1'b0)
+ )
+ ISERDESE2_inst_{loc} (
+ .CLK(serdes_clk_{loc}),
+ .CLKB(),
+ .CLKDIV(),
+ .D(1'b0),
+ .DDLY(),
+ .OFB(),
+ .OCLKB(),
+ .RST(),
+ .SHIFTIN1(),
+ .SHIFTIN2()
+ );
+ """.format(loc=site, clock_source=wire_name))
+
+ # BUFRs
+ for _, site in gen_sites('BUFR'):
+ if random.random() < 0.5:
+ if random.random() < 0.5:
+ wire_name = luts.get_next_output_net()
+ else:
+ wire_name = cmt_fast_clock_sources.get_random_source(
+ site_to_cmt[site], no_repeats=False)
+ if wire_name is None:
+ continue
+ src_cmt = cmt_fast_clock_sources.source_to_cmt[wire_name]
+ wire_name = check_cmt_clk_src(wire_name, src_cmt)
+ if wire_name is None:
+ continue
+ bufr_clock_sources.add_clock_source(
+ 'O_{site}'.format(site=site), site_to_cmt[site])
+
+ # Add DIVIDE
+ divide = "BYPASS"
+ if random.random() < 0.8:
+ divide = "{}".format(random.randint(2, 8))
+
+ print(
+ """
+ assign I_{site} = {clock_source};
+ (* KEEP, DONT_TOUCH, LOC = "{site}" *)
+ BUFR #(.BUFR_DIVIDE("{divide}")) bufr_{site} (
+ .O(O_{site}),
+ .I(I_{site})
+ );""".format(site=site, clock_source=wire_name, divide=divide),
+ file=bufs)
+
+ for _, site in gen_sites('MMCME2_ADV'):
+ wire_name = bufr_clock_sources.get_random_source(
+ site_to_cmt[site], no_repeats=True)
+
+ if wire_name is None:
+ continue
+ print(
+ """
+ assign cin1_{site} = {wire_name};""".format(
+ site=site, wire_name=wire_name))
+
+ print(bufs.getvalue())
+
+ for l in luts.create_wires_and_luts():
+ print(l)
+
+ print("endmodule")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/fuzzers/071-ppips/generate.tcl b/fuzzers/071-ppips/generate.tcl
index 94be82f..a424380 100644
--- a/fuzzers/071-ppips/generate.tcl
+++ b/fuzzers/071-ppips/generate.tcl
@@ -322,7 +322,7 @@
}
foreach tile_type {RIOI3 LIOI3 LIOI3_TBYTETERM RIOI3_TBYTETERM \
- LIOI3_TBYTESRC RIOI3_TBYTESRC LIOI3_SING RIOI3_SING} {
+ LIOI3_TBYTESRC RIOI3_TBYTESRC LIOI3_SING RIOI3_SING RIOI RIOI_SING RIOI_TBYTESRC RIOI_TBYTETERM} {
set tiles [get_tiles -filter "TILE_TYPE == $tile_type"]
if {[llength $tiles] != 0} {
set tile [lindex $tiles 0]
@@ -392,7 +392,7 @@
}
}
-foreach tile_type {RIOB33 LIOB33 RIOB33_SING LIOB33_SING} {
+foreach tile_type {RIOB33 LIOB33 RIOB33_SING LIOB33_SING RIOB18 RIOB18_SING} {
set tiles [get_tiles -filter "TILE_TYPE == $tile_type"]
if {[llength $tiles] != 0} {
set tile [lindex $tiles 0]
diff --git a/fuzzers/Makefile b/fuzzers/Makefile
index ee43c95..94a1094 100644
--- a/fuzzers/Makefile
+++ b/fuzzers/Makefile
@@ -113,6 +113,9 @@
$(eval $(call fuzzer,028-fifo-config,005-tilegrid,all))
$(eval $(call fuzzer,029-bram-fifo-config,005-tilegrid,all))
$(eval $(call fuzzer,030-iob,005-tilegrid,all))
+ifeq ($(XRAY_DATABASE),kintex7)
+$(eval $(call fuzzer,030-iob18,005-tilegrid,all))
+endif
$(eval $(call fuzzer,031-cmt-mmcm,005-tilegrid,all))
$(eval $(call fuzzer,032-cmt-pll,005-tilegrid,all))
$(eval $(call fuzzer,034-cmt-pll-pips,005-tilegrid 071-ppips,all))
@@ -123,9 +126,18 @@
endif
$(eval $(call fuzzer,035-iob-ilogic,005-tilegrid,all))
$(eval $(call fuzzer,035a-iob-idelay,005-tilegrid,all))
+ifeq ($(XRAY_DATABASE),kintex7)
+$(eval $(call fuzzer,035a-iob18-idelay,005-tilegrid,all))
+endif
$(eval $(call fuzzer,035b-iob-iserdes,005-tilegrid,all))
$(eval $(call fuzzer,036-iob-ologic,005-tilegrid,all))
+ifeq ($(XRAY_DATABASE),kintex7)
+$(eval $(call fuzzer,036-iob18-ologic,005-tilegrid,all))
+endif
$(eval $(call fuzzer,037-iob-pips,005-tilegrid 035b-iob-iserdes,all))
+ifeq ($(XRAY_DATABASE),kintex7)
+$(eval $(call fuzzer,037-iob18-pips,005-tilegrid 035b-iob-iserdes,all))
+endif
$(eval $(call fuzzer,038-cfg,005-tilegrid,all))
$(eval $(call fuzzer,039-hclk-config,005-tilegrid,all))
$(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid,all))
@@ -136,6 +148,9 @@
$(eval $(call fuzzer,045-hclk-cmt-pips,005-tilegrid,all))
$(eval $(call fuzzer,046-clk-bufg-muxed-pips,005-tilegrid,all))
$(eval $(call fuzzer,047-hclk-ioi-pips,005-tilegrid,all))
+ifeq ($(XRAY_DATABASE),kintex7)
+$(eval $(call fuzzer,047-hclk-ioi18-pips,005-tilegrid,all))
+endif
$(eval $(call fuzzer,047a-hclk-idelayctrl-pips,047-hclk-ioi-pips,all))
$(eval $(call fuzzer,048-int-piplist,005-tilegrid,all))
$(eval $(call fuzzer,049-int-imux-gfan,048-int-piplist,all))
diff --git a/prjxray/segmaker.py b/prjxray/segmaker.py
index 542fcc8..c362bef 100644
--- a/prjxray/segmaker.py
+++ b/prjxray/segmaker.py
@@ -359,6 +359,8 @@
-CLK_HROW_TOP_R => CLK_HROW
-LIOB33 => IOB33
-LIOI3 => IOI3
+ -RIOB18 => IOB18
+ -RIOI => IOI
'''
tile_type_norm = re.sub("(_TOP|_BOT|LL|LM)?_[LR]$", "", tile_type)
tile_type_norm = re.sub(
@@ -366,13 +368,20 @@
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'
+ if tile_type_norm in ['LIOI', 'RIOI']:
+ tile_type_norm = 'IOI'
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'
+ 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'
if tile_type_norm in ['CMT_TOP_L_LOWER_B', 'CMT_TOP_R_LOWER_B']:
tile_type_norm = 'CMT_LOWER_B'
if 'GTP_CHANNEL' in tile_type_norm:
diff --git a/prjxray/util.py b/prjxray/util.py
index bb2efb0..615bf72 100644
--- a/prjxray/util.py
+++ b/prjxray/util.py
@@ -86,8 +86,8 @@
def get_part_information(db_root, part):
filename = os.path.join(db_root, "mapping", "parts.yaml")
assert os.path.isfile(filename), \
- "Mapping file {} does not exists".format(filename)
- with OpenSafeFile(filename, 'r') as stream:
+ "Mapping file {} does not exist".format(filename)
+ with open(filename, 'r') as stream:
part_mapping = yaml.load(stream, Loader=yaml.FullLoader)
part = part_mapping.get(part, None)
assert part, "Part {} not found in {}".format(part, part_mapping)
@@ -99,14 +99,14 @@
with OpenSafeFile(filename, 'w+') as stream:
yaml.dump(information, stream)
assert os.path.isfile(filename), \
- "Mapping file {} does not exists".format(filename)
+ "Mapping file {} does not exist".format(filename)
def get_part_resources(file_path, part):
filename = os.path.join(file_path, "resources.yaml")
assert os.path.isfile(filename), \
- "Mapping file {} does not exists".format(filename)
- with OpenSafeFile(filename, 'r') as stream:
+ "Mapping file {} does not exist".format(filename)
+ with open(filename, 'r') as stream:
res_mapping = yaml.load(stream, Loader=yaml.FullLoader)
res = res_mapping.get(part, None)
assert res, "Part {} not found in {}".format(part, part_mapping)
@@ -118,13 +118,13 @@
with OpenSafeFile(filename, 'w+') as stream:
yaml.dump(information, stream)
assert os.path.isfile(filename), \
- "Mapping file {} does not exists".format(filename)
+ "Mapping file {} does not exist".format(filename)
def get_fabric_for_part(db_root, part):
filename = os.path.join(db_root, "mapping", "devices.yaml")
assert os.path.isfile(filename), \
- "Mapping file {} does not exists".format(filename)
+ "Mapping file {} does not exist".format(filename)
part = get_part_information(db_root, part)
with OpenSafeFile(filename, 'r') as stream:
device_mapping = yaml.load(stream, Loader=yaml.FullLoader)
@@ -137,8 +137,8 @@
def get_devices(db_root):
filename = os.path.join(db_root, "mapping", "devices.yaml")
assert os.path.isfile(filename), \
- "Mapping file {} does not exists".format(filename)
- with OpenSafeFile(filename, 'r') as stream:
+ "Mapping file {} does not exist".format(filename)
+ with open(filename, 'r') as stream:
device_mapping = yaml.load(stream, Loader=yaml.FullLoader)
return device_mapping
@@ -146,8 +146,8 @@
def get_parts(db_root):
filename = os.path.join(db_root, "mapping", "parts.yaml")
assert os.path.isfile(filename), \
- "Mapping file {} does not exists".format(filename)
- with OpenSafeFile(filename, 'r') as stream:
+ "Mapping file {} does not exist".format(filename)
+ with open(filename, 'r') as stream:
part_mapping = yaml.load(stream, Loader=yaml.FullLoader)
return part_mapping
diff --git a/settings/kintex7.sh b/settings/kintex7.sh
index 85a705e..66e8199 100644
--- a/settings/kintex7.sh
+++ b/settings/kintex7.sh
@@ -10,17 +10,17 @@
export XRAY_ROI_FRAMES="0x00000000:0xffffffff"
# FIXME: make entire part
-export XRAY_ROI_TILEGRID="SLICE_X0Y50:SLICE_X19Y99 DSP48_X0Y20:DSP48_X0Y39 RAMB18_X0Y20:RAMB18_X0Y39 RAMB36_X0Y10:RAMB36_X0Y19"
+export XRAY_ROI_TILEGRID="SLICE_X0Y50:SLICE_X19Y99 DSP48_X0Y20:DSP48_X0Y39 RAMB18_X0Y0:RAMB18_X3Y39 RAMB36_X0Y0:RAMB36_X3Y19"
export XRAY_EXCLUDE_ROI_TILEGRID=""
-export XRAY_IOI3_TILES="LIOI3_X0Y9"
+export XRAY_IOI3_TILES="LIOI3_X0Y9 RIOI_X43Y9"
# These settings must remain in sync
-export XRAY_ROI="SLICE_X0Y50:SLICE_X19Y99 DSP48_X0Y20:DSP48_X0Y39 RAMB18_X0Y20:RAMB18_X0Y39 RAMB36_X0Y10:RAMB36_X0Y19 IOB_X0Y50:IOB_X0Y99"
-# Part of CMT X0Y1
+export XRAY_ROI="SLICE_X0Y50:SLICE_X23Y99 DSP48_X0Y20:DSP48_X0Y39 RAMB18_X0Y0:RAMB18_X3Y39 RAMB36_X0Y0:RAMB36_X3Y19 IOB_X0Y50:IOB_X0Y99 IOB_X1Y50:IOB_X1Y99"
+# CMT X0Y1
export XRAY_ROI_GRID_X1="0"
-export XRAY_ROI_GRID_X2="38"
+export XRAY_ROI_GRID_X2="65"
# Include VBRK / VTERM
export XRAY_ROI_GRID_Y1="104"
export XRAY_ROI_GRID_Y2="156"
diff --git a/tools/segmatch.cc b/tools/segmatch.cc
index 1af59cd..d62cc27 100644
--- a/tools/segmatch.cc
+++ b/tools/segmatch.cc
@@ -255,7 +255,7 @@
read_input(f, argv[optind]);
}
} else {
- printf("Reading from stding.\n");
+ printf("Reading from stdin...\n");
read_input(std::cin, "stdin");
}
diff --git a/utils/mergedb.sh b/utils/mergedb.sh
index 98383d4..eae4c6d 100755
--- a/utils/mergedb.sh
+++ b/utils/mergedb.sh
@@ -121,6 +121,9 @@
riob33)
sed < "$2" > "$tmp1" -e 's/^IOB33\./RIOB33./' ;;
+ riob18)
+ sed < "$2" > "$tmp1" -e 's/^IOB18\./RIOB18./' ;;
+
lioi3)
sed < "$2" > "$tmp1" -e 's/^IOI3\./LIOI3./' ;;
@@ -133,12 +136,21 @@
rioi3)
sed < "$2" > "$tmp1" -e 's/^IOI3\./RIOI3./' ;;
+ rioi)
+ sed < "$2" > "$tmp1" -e 's/^IOI\./RIOI./' ;;
+
rioi3_tbytesrc)
sed < "$2" > "$tmp1" -e 's/^IOI3\./RIOI3_TBYTESRC./' ;;
+ rioi_tbytesrc)
+ sed < "$2" > "$tmp1" -e 's/^IOI\./RIOI_TBYTESRC./' ;;
+
rioi3_tbyteterm)
sed < "$2" > "$tmp1" -e 's/^IOI3\./RIOI3_TBYTETERM./' ;;
+ rioi_tbyteterm)
+ sed < "$2" > "$tmp1" -e 's/^IOI\./RIOI_TBYTETERM./' ;;
+
cmt_top_r_upper_t)
sed < "$2" > "$tmp1" -e 's/^CMT_UPPER_T\./CMT_TOP_R_UPPER_T./' ;;
@@ -157,6 +169,9 @@
hclk_ioi3)
cp "$2" "$tmp1" ;;
+ hclk_ioi)
+ cp "$2" "$tmp1" ;;
+
pcie_bot)
cp "$2" "$tmp1" ;;