diff --git a/fuzzers/000-init-db/Makefile b/fuzzers/000-init-db/Makefile index 033ed9892..4b1e09a86 100644 --- a/fuzzers/000-init-db/Makefile +++ b/fuzzers/000-init-db/Makefile @@ -50,6 +50,7 @@ DB_SIMPLE=\ 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 5cce0a95b..3b663fbb9 100644 --- a/fuzzers/001-part-yaml/generate.tcl +++ b/fuzzers/001-part-yaml/generate.tcl @@ -11,7 +11,7 @@ proc extract_iobanks {filename} { 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]] @@ -29,13 +29,13 @@ create_project -force -part $::env(XRAY_PART) design design read_verilog ../../top.v synth_design -top top -set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk] -set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports di] -set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports do] -set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports stb] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS18" [get_ports clk] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS18" [get_ports di] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS18" [get_ports do] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS18" [get_ports stb] -set_property CFGBVS VCCO [current_design] -set_property CONFIG_VOLTAGE 3.3 [current_design] +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] set_param tcl.collectionResultDisplayLimit 0 set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] diff --git a/fuzzers/005-tilegrid/Makefile b/fuzzers/005-tilegrid/Makefile index f0ad42b5a..57716950e 100644 --- a/fuzzers/005-tilegrid/Makefile +++ b/fuzzers/005-tilegrid/Makefile @@ -49,6 +49,13 @@ endif # 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 @@ cfg/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID} 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 @@ clean: 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 @@ clean_part: 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 021f14f7c..e483f7709 100644 --- a/fuzzers/005-tilegrid/add_tdb.py +++ b/fuzzers/005-tilegrid/add_tdb.py @@ -94,7 +94,9 @@ def run(fn_in, fn_out, verbose=False): 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 @@ def run(fn_in, fn_out, verbose=False): ("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 4022edc0d..454f6486d 100644 --- a/fuzzers/005-tilegrid/generate_full.py +++ b/fuzzers/005-tilegrid/generate_full.py @@ -369,7 +369,7 @@ def propagate_IOB_SING(database, tiles_by_grid): 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 @@ def propagate_IOI_SING(database, tiles_by_grid): 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 000000000..9251dba84 --- /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 000000000..d4f790b8f --- /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 000000000..1e568cd98 --- /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 000000000..9f2ad5087 --- /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 000000000..3c705da90 --- /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 000000000..5cb360baa --- /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 000000000..9fd5b9419 --- /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 000000000..96e843af5 --- /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 000000000..be162cdbe --- /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 0f65e00a5..56e18ce5b 100644 --- a/fuzzers/005-tilegrid/util.py +++ b/fuzzers/005-tilegrid/util.py @@ -96,8 +96,8 @@ def add_tile_bits( 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 9ba176f60..284e0fe33 100644 --- a/fuzzers/030-iob/write_io_banks.tcl +++ b/fuzzers/030-iob/write_io_banks.tcl @@ -20,7 +20,10 @@ set fp [open "cmt_regions.csv" "w"] 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 000000000..a73872648 --- /dev/null +++ b/fuzzers/030-iob18/Makefile @@ -0,0 +1,41 @@ +# 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 := 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 000000000..102f0f699 --- /dev/null +++ b/fuzzers/030-iob18/README.md @@ -0,0 +1,2 @@ +# IOB18 Fuzzer + diff --git a/fuzzers/030-iob18/bits.dbf b/fuzzers/030-iob18/bits.dbf new file mode 100644 index 000000000..e69de29bb diff --git a/fuzzers/030-iob18/check_results.py b/fuzzers/030-iob18/check_results.py new file mode 100644 index 000000000..364110b72 --- /dev/null +++ b/fuzzers/030-iob18/check_results.py @@ -0,0 +1,235 @@ +#!/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 +""" 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 run) +2. Build the database again (e.g. make -j 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 000000000..c15173892 --- /dev/null +++ b/fuzzers/030-iob18/generate.py @@ -0,0 +1,302 @@ +#!/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 + +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): + # the fuzzers seem to find bits in frame 24 which seems + # to be used by other tile types + if frame < 30: + return False + return True + +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 000000000..a24d1dff6 --- /dev/null +++ b/fuzzers/030-iob18/generate.tcl @@ -0,0 +1,122 @@ +# 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 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 000000000..e69de29bb diff --git a/fuzzers/030-iob18/iostandards.py b/fuzzers/030-iob18/iostandards.py new file mode 100644 index 000000000..c6577639b --- /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/minitest/DRIVE.tcl b/fuzzers/030-iob18/minitest/DRIVE.tcl new file mode 100644 index 000000000..a4fa2d1e3 --- /dev/null +++ b/fuzzers/030-iob18/minitest/DRIVE.tcl @@ -0,0 +1,15 @@ +# 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(SRC_DIR)/template.tcl" + +# set vals "0 4 8 12 16 24" +# ERROR: [Common 17-69] Command failed: Illegal DRIVE_STRENGTH value '0' for standard 'LVCMOS33'. +# Legal values: 4, 8, 12, 16 +set prop DRIVE +set port [get_ports do] +source "$::env(SRC_DIR)/sweep.tcl" diff --git a/fuzzers/030-iob18/minitest/IOSTANDARD.tcl b/fuzzers/030-iob18/minitest/IOSTANDARD.tcl new file mode 100644 index 000000000..a054db6aa --- /dev/null +++ b/fuzzers/030-iob18/minitest/IOSTANDARD.tcl @@ -0,0 +1,12 @@ +# 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(SRC_DIR)/template.tcl" + +set prop IOSTANDARD +set port [get_ports do] +source "$::env(SRC_DIR)/sweep.tcl" diff --git a/fuzzers/030-iob18/minitest/Makefile b/fuzzers/030-iob18/minitest/Makefile new file mode 100644 index 000000000..9e63b66c8 --- /dev/null +++ b/fuzzers/030-iob18/minitest/Makefile @@ -0,0 +1,46 @@ +# 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 +all: build/env build/roi_io.diff \ + build/PULLTYPE/run.ok \ + build/SLEW/run.ok \ + build/DRIVE/run.ok \ + build/IOSTANDARD/run.ok \ + +clean: + rm -rf build + +# hard coded LOCs in .v +build/env: + test "$(XRAY_PART)" = "xc7k70tfbg676-2" + +# Didn't work +build/roi_io.diff: + $(MAKE) -f diff.mk OUT_DIFF=build/roi_io.diff PRJL=roi_io_a PRJR=roi_io_b + +# Didn't work +build/roi_prop.diff: + $(MAKE) -f diff.mk OUT_DIFF=build/roi_prop.diff PRJL=roi_prop_a PRJR=roi_prop_b + +build/PULLTYPE/run.ok: + PROJECT=PULLTYPE bash runme_tcl.sh + diff build/PULLTYPE/design_{PULLDOWN,KEEPER}.bits || true + diff build/PULLTYPE/design_{PULLDOWN,PULLUP}.bits || true + diff build/PULLTYPE/design_{PULLDOWN,NONE}.bits || true + +build/SLEW/run.ok: + PROJECT=SLEW bash runme_tcl.sh + +build/DRIVE/run.ok: + PROJECT=DRIVE bash runme_tcl.sh + +build/IOSTANDARD/run.ok: + PROJECT=IOSTANDARD bash runme_tcl.sh + +csv: + PROJECT=$@ bash runme.sh + diff --git a/fuzzers/030-iob18/minitest/PULLTYPE.tcl b/fuzzers/030-iob18/minitest/PULLTYPE.tcl new file mode 100644 index 000000000..28bf90c12 --- /dev/null +++ b/fuzzers/030-iob18/minitest/PULLTYPE.tcl @@ -0,0 +1,21 @@ +# 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(SRC_DIR)/template.tcl" + +set port [get_ports di] + +set_property PULLTYPE "" $port +write_checkpoint -force design_NONE.dcp +write_bitstream -force design_NONE.bit + +set vals "KEEPER PULLUP PULLDOWN" +foreach {val} $vals { + set_property PULLTYPE $val $port + write_checkpoint -force design_$val.dcp + write_bitstream -force design_$val.bit +} diff --git a/fuzzers/030-iob18/minitest/README.md b/fuzzers/030-iob18/minitest/README.md new file mode 100644 index 000000000..58566b0d0 --- /dev/null +++ b/fuzzers/030-iob18/minitest/README.md @@ -0,0 +1,56 @@ +# PULLTYPE + +PULLTYPE 38_98 39_97 39_97 +NONE X +KEEPER X X +PULLDOWN +PULLUP X X + + +# DRIVE + +Drive strength depends on current IOSTANDARD, e.g. + +LVCMOS18 +DRIVE 38_64 38_66 38_72 38_74 39_65 39_73 +4 X X X +8 X X X +12 X X X +16 X X X +24 X X X + +LVCMOS25 +DRIVE 38_64 38_66 38_72 38_74 39_65 39_73 +4 X X X +8 X +12 +16 X X X + +LVCMOS33 +DRIVE 38_64 38_66 38_72 38_74 39_65 39_73 +4 X X X +8 X X X +12 X X X +16 X X X + +The minitest contains a csv target which generates a csv with differences across all LVCMOS and LVTTL standards for all supported DRIVE strengths and both slew rates. + +# IOSTANDARD + +Effects bits, TBD exactly how +Sample output: + +diff LVCMOS33.bits LVTTL.bits +< bit_00020026_006_00 +> bit_00020026_006_08 + +diff LVCMOS33.bits PCI33_3.bits +< bit_00020026_006_02 +< bit_00020026_006_18 +< bit_00020026_006_22 +> bit_00020026_006_10 +> bit_00020026_006_16 +> bit_00020026_006_20 +> bit_00020027_006_11 +> bit_00020027_006_15 + diff --git a/fuzzers/030-iob18/minitest/SLEW.tcl b/fuzzers/030-iob18/minitest/SLEW.tcl new file mode 100644 index 000000000..3c6cc17e2 --- /dev/null +++ b/fuzzers/030-iob18/minitest/SLEW.tcl @@ -0,0 +1,14 @@ +# 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(SRC_DIR)/template.tcl" + +# set vals "SLOW MEDIUM FAST" +# ERROR: [Common 17-69] Command failed: Slew type 'MEDIUM' is not supported by I/O standard 'LVCMOS33' +set prop SLEW +set port [get_ports do] +source "$::env(SRC_DIR)/sweep.tcl" diff --git a/fuzzers/030-iob18/minitest/compare.py b/fuzzers/030-iob18/minitest/compare.py new file mode 100644 index 000000000..df7ff1f12 --- /dev/null +++ b/fuzzers/030-iob18/minitest/compare.py @@ -0,0 +1,172 @@ +#!/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 sys +import glob +import os +import re +import difflib + + +def get_file_pairs(): + pairs_list = list() + for path1 in glob.glob('*.bits'): + for path2 in glob.glob('*.bits'): + file1 = os.path.basename(path1) + file2 = os.path.basename(path2) + if file1 == file2: + continue + files_pair = [file1, file2] + files_pair.sort() + pairs_list.append(files_pair[0] + ":" + files_pair[1]) + pairs_set = set(pairs_list) + for pair in pairs_set: + file1, file2 = pair.split(":") + yield file1, file2 + + +def extract_parameters_string(basename): + params_str = re.search('^design_(.*).bits$', basename) + return params_str.group(1) + + +def extract_parameters(basename): + iostandard, slew, drive = extract_parameters_string(basename).split('_') + return iostandard, slew, drive + + +def generate_differing_bits(basename1, basename2): + with open(basename1, 'r') as path1: + with open(basename2, 'r') as path2: + diff = difflib.unified_diff( + path1.read().splitlines(), + path2.read().splitlines(), + fromfile='path1', + tofile='path2') + for line in diff: + if line.startswith('---'): + continue + if line.startswith('+++'): + continue + if line.startswith('@'): + continue + if line.startswith('-'): + yield extract_parameters_string(basename1), line.strip('-') + continue + if line.startswith('+'): + yield extract_parameters_string(basename2), line.strip('+') + continue + + +class Database(): + def __init__(self, convert_bits=False): + self.all_bits = set() + self.properties_bits = dict() + self.convert_bits = convert_bits + self.populate() + + def populate(self): + for file1, file2 in get_file_pairs(): + #print(file1 + " vs " + file2) + for property_str, bit in generate_differing_bits(file1, file2): + #print(property_str + " " + bit) + self.update_all_bits(bit) + if property_str in self.properties_bits: + self.properties_bits[property_str].add(bit) + else: + self.properties_bits[property_str] = set() + self.properties_bits[property_str].add(bit) + + def update_all_bits(self, bit): + self.all_bits.add(bit) + + def print_all_bits(self): + print(self.all_bits) + + def get_keys(self): + return self.properties_bits.keys() + + def print_bits(self, key): + if key in self.properties_bits: + print("%s: %s" % (key, self.properties_bits[key])) + else: + print("The specified property is not in the database") + + def convert_bit_format(self, item): + dummy, address, word, bit = item.split("_") + address = int(address[-2:], 16) + bit = int(word) % 4 * 32 + int(bit) + return "{address}_{bit}".format(address=address, bit=bit) + + def convert_header(self, header): + converted_bits = [] + for bit in header: + #print(bit + ":" + self.convert_bit_format(bit)) + converted_bits.append(self.convert_bit_format(bit)) + return converted_bits + + def get_csv_header(self): + header = list(self.all_bits) + header.sort() + self.csv_header = header + if self.convert_bits: + header = self.convert_header(header) + line = "property,v,i,r," + for title in header: + line += title + "," + return line + '\n' + + def extract_rvi_parameters(self, rvi): + iostandard, slew, drive = rvi.split("_") + if iostandard[-2:] == "12": + voltage = 1.2 + elif iostandard[-2:] == "15": + voltage = 1.5 + elif iostandard[-2:] == "18": + voltage = 1.8 + elif iostandard[-2:] == "25": + voltage = 2.5 + else: + voltage = 3.3 + resistance = voltage / (int(drive) * 0.001) + return "%.1f,%s,%.3f" % (voltage, drive, resistance) + + def get_csv_body(self): + lines = "" + keys = list(self.get_keys()) + keys.sort() + for properties_key in keys: + line = properties_key + "," + self.extract_rvi_parameters( + properties_key) + "," + for title in self.csv_header: + if title in self.properties_bits[properties_key]: + line += "X," + else: + line += " ," + line += '\n' + lines += line + return lines + + def write_csv(self, filename): + filename = os.getcwd() + "/" + filename + fp = open(filename, 'w') + fp.write(self.get_csv_header()) + fp.write(self.get_csv_body()) + fp.close() + print("Written results to %s file.\n" % filename) + + +def main(): + database = Database(True) + database.write_csv("differences.csv") + + +if __name__ == '__main__': + main() diff --git a/fuzzers/030-iob18/minitest/diff.mk b/fuzzers/030-iob18/minitest/diff.mk new file mode 100644 index 000000000..b2c2ff603 --- /dev/null +++ b/fuzzers/030-iob18/minitest/diff.mk @@ -0,0 +1,11 @@ +all: $(OUT_DIFF) + +$(OUT_DIFF): build/$(PRJL)/design.bits build/$(PRJR)/design.bits + diff build/$(PRJL)/design.bits build/$(PRJR)/design.bits >$(OUT_DIFF) || true + +build/$(PRJL)/design.bits: + PROJECT=$(PRJL) bash runme.sh + +build/$(PRJR)/design.bits: + PROJECT=$(PRJR) bash runme.sh + diff --git a/fuzzers/030-iob18/minitest/diff_tcl.mk b/fuzzers/030-iob18/minitest/diff_tcl.mk new file mode 100644 index 000000000..5c40cf3ac --- /dev/null +++ b/fuzzers/030-iob18/minitest/diff_tcl.mk @@ -0,0 +1,11 @@ +all: $(OUT_DIFF) + +$(OUT_DIFF): build/$(PRJL)/design.bits build/$(PRJR)/design.bits + diff build/$(PRJL)/design.bits build/$(PRJR)/design.bits >$(OUT_DIFF) || true + +build/$(PRJL)/design.bits: + PROJECT=$(PRJL) bash runme_tcl.sh + +build/$(PRJR)/design.bits: + PROJECT=$(PRJR) bash runme_tcl.sh + diff --git a/fuzzers/030-iob18/minitest/generate.tcl b/fuzzers/030-iob18/minitest/generate.tcl new file mode 100644 index 000000000..3131213a8 --- /dev/null +++ b/fuzzers/030-iob18/minitest/generate.tcl @@ -0,0 +1,131 @@ +# 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_X?Y? clk input + # IOB_X?Y? do[0] output + + set fp [open "$::env(SRC_DIR)/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" + foreach line $pin_lines { + puts "$line" + lassign $line site_str pin_str io cell_str + + # 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 iostandard [get_property IOSTANDARD $port] + + set_property -dict "PACKAGE_PIN $pin IOSTANDARD $iostandard" $port + } +} + +proc set_property_value_on_port {property value port} { + set_property $property $value $port + set got [get_property $property $port] + if {"$got" != "$value"} { + puts "Skipping: wanted $value, got $got" + return 1 + } + return 0 +} + +proc run {} { + create_project -force -part $::env(XRAY_PART) design design + read_verilog top.v + synth_design -top top + + # Mostly doesn't matter since IOB are special, but add anyway + create_pblock roi + add_cells_to_pblock [get_pblocks roi] [get_cells roi] + resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)" + + 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 + + loc_pins + place_design + route_design + set pin_lines [load_pin_lines] + # For HR Current Drive + set property_dictionary [dict create \ + LVCMOS12 \ + [dict create DRIVE [list 2 4 6 8] SLEW [list SLOW FAST]] \ + LVCMOS15 \ + [dict create DRIVE [list 2 4 6 8 12 16] SLEW [list SLOW FAST]] \ + LVCMOS18 \ + [dict create DRIVE [list 2 4 6 8 12 16] SLEW [list SLOW FAST]] \ + ] + #HSUL_12 no DRIVE support, only SLEW + #HSTL_I, HSTL_II, HSTL_I_18, HSTL_II_18 no drive support, only SLEW + #SSTL/18/135/ no drive support, only SLEW + + foreach iostandard [dict keys $property_dictionary] { + foreach slew [dict get $property_dictionary $iostandard SLEW] { + foreach drive [dict get $property_dictionary $iostandard DRIVE] { + foreach line $pin_lines { + lassign $line site_str pin_str io cell_str + set port [get_ports $pin_str] + + set_property IOSTANDARD $iostandard $port + + if {$io == "input"} continue + + if {[set_property_value_on_port SLEW $slew $port]} { + continue + } + + if {[set_property_value_on_port DRIVE $drive $port]} { + continue + } + } + if {[catch {write_bitstream -force design_${iostandard}_${slew}_${drive}.bit} issue]} { + puts "WARNING failed to write: $issue" + continue + } + # Only write checkpoints for acceptable bitstreams + write_checkpoint -force design_${iostandard}_${slew}_${drive}.dcp + } + } + } +} +run diff --git a/fuzzers/030-iob18/minitest/params.csv b/fuzzers/030-iob18/minitest/params.csv new file mode 100644 index 000000000..1787886cc --- /dev/null +++ b/fuzzers/030-iob18/minitest/params.csv @@ -0,0 +1,2 @@ +IOB_X1Y11,di[0],input,di_bufs[0].ibuf +IOB_X1Y7,do[0],output,do_bufs[0].obuf diff --git a/fuzzers/030-iob18/minitest/runme.sh b/fuzzers/030-iob18/minitest/runme.sh new file mode 100644 index 000000000..07863d00f --- /dev/null +++ b/fuzzers/030-iob18/minitest/runme.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# 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 + +set -ex + +: "${PROJECT:?Need to set PROJECT non-empty}" + +# Create build dir +export SRC_DIR=$PWD +export BUILD_DIR=build/$PROJECT +mkdir -p $BUILD_DIR +cd $BUILD_DIR +python3 ${SRC_DIR}/top.py > top.v + +${XRAY_VIVADO} -mode batch -source $SRC_DIR/generate.tcl +for x in design*.bit; do + ${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o ${x}s -z -y $x +done +test -z "$(fgrep CRITICAL vivado.log)" && touch run.ok +python3 ${SRC_DIR}/compare.py diff --git a/fuzzers/030-iob18/minitest/runme.tcl b/fuzzers/030-iob18/minitest/runme.tcl new file mode 100644 index 000000000..6a1b2de57 --- /dev/null +++ b/fuzzers/030-iob18/minitest/runme.tcl @@ -0,0 +1,37 @@ +# 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 +create_project -force -part $::env(XRAY_PART) design design +#read_verilog $::env(SRC_DIR)/$::env(PROJECT).v +read_verilog $::env(TOP_V) +synth_design -top top -flatten_hierarchy none -verilog_define ROI=$::env(PROJECT) + +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports stb] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports di] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports do] + +# set_property roi/dut + +create_pblock roi +set_property EXCLUDE_PLACEMENT 1 [get_pblocks roi] +add_cells_to_pblock [get_pblocks roi] [get_cells roi] +resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)" + +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] +set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] + +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] + +place_design +route_design + +write_checkpoint -force design.dcp + +# set_property BITSTREAM.GENERAL.DEBUGBITSTREAM Yes [current_design] +write_bitstream -force design.bit diff --git a/fuzzers/030-iob18/minitest/runme_tcl.sh b/fuzzers/030-iob18/minitest/runme_tcl.sh new file mode 100644 index 000000000..979cbb680 --- /dev/null +++ b/fuzzers/030-iob18/minitest/runme_tcl.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# 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 + +set -ex + +: "${PROJECT:?Need to set PROJECT non-empty}" + +# Create build dir +export SRC_DIR=$PWD +BUILD_DIR=build/$PROJECT +mkdir -p $BUILD_DIR +cd $BUILD_DIR + +export TOP_V=$SRC_DIR/tcl.v + +${XRAY_VIVADO} -mode batch -source $SRC_DIR/$PROJECT.tcl +for x in design*.bit; do + ${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o ${x}s -z -y $x +done +test -z "$(fgrep CRITICAL vivado.log)" +touch run.ok + diff --git a/fuzzers/030-iob18/minitest/sweep.tcl b/fuzzers/030-iob18/minitest/sweep.tcl new file mode 100644 index 000000000..8946be154 --- /dev/null +++ b/fuzzers/030-iob18/minitest/sweep.tcl @@ -0,0 +1,28 @@ +# 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 +# Sweep all values of $prop on given I/O $port +# Write out bitstream for all legal values + +set vals [list_property_value $prop $port] +foreach {val} $vals { + puts $val + # Not all listable properties are settable + # Its easiest to try setting and see if it sticks + set_property -quiet $prop $val $port + set got [get_property $prop $port] + if {"$got" != "$val"} { + puts " Skipping: wanted $val, got $got" + continue + } + if {[catch {write_bitstream -force design_$val.bit} issue]} { + puts "WARNING failed to write: $issue" + continue + } + # Only write checkpoints for acceptable bitstreams + write_checkpoint -force design_$val.dcp +} diff --git a/fuzzers/030-iob18/minitest/tcl.v b/fuzzers/030-iob18/minitest/tcl.v new file mode 100644 index 000000000..6535c2d80 --- /dev/null +++ b/fuzzers/030-iob18/minitest/tcl.v @@ -0,0 +1,39 @@ +module top(input clk, stb, di, output do); + localparam integer DIN_N = 256; + localparam integer DOUT_N = 256; + + reg [DIN_N-1:0] din; + wire [DOUT_N-1:0] dout; + + reg [DIN_N-1:0] din_shr; + reg [DOUT_N-1:0] dout_shr; + + always @(posedge clk) begin + din_shr <= {din_shr, di}; + dout_shr <= {dout_shr, din_shr[DIN_N-1]}; + if (stb) begin + din <= din_shr; + dout_shr <= dout; + end + end + + assign do = dout_shr[DOUT_N-1]; + + roi + roi ( + .clk(clk), + .din(din), + .dout(dout) + ); +endmodule + +module roi(input clk, input [255:0] din, output [255:0] dout); + assign dout = din; +endmodule + +/* +module top (input i, output o); + assign o = i; +endmodule +*/ + diff --git a/fuzzers/030-iob18/minitest/template.tcl b/fuzzers/030-iob18/minitest/template.tcl new file mode 100644 index 000000000..ce274b803 --- /dev/null +++ b/fuzzers/030-iob18/minitest/template.tcl @@ -0,0 +1,32 @@ +# 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 +# Create a simple design with a few IOs + +create_project -force -part $::env(XRAY_PART) design design +read_verilog $::env(TOP_V) +synth_design -top top -flatten_hierarchy none + +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS18" [get_ports clk] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS18" [get_ports stb] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS18" [get_ports di] +set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS18" [get_ports do] + +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] +set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] + +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] + +place_design +route_design +write_checkpoint -force design.dcp + +# set port [create_port -direction OUT myport] +# set_property -dict "PACKAGE_PIN D19 IOSTANDARD LVCMOS33" $port +# set_property PULLTYPE PULLUP $port +# set_property PULLTYPE PULLDOWN $port diff --git a/fuzzers/030-iob18/minitest/top.py b/fuzzers/030-iob18/minitest/top.py new file mode 100644 index 000000000..10dd3efb1 --- /dev/null +++ b/fuzzers/030-iob18/minitest/top.py @@ -0,0 +1,159 @@ +#!/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 +import sys +#random.seed(int(os.getenv("SEED"), 16)) +from prjxray import util +from prjxray import verilog + + +def gen_iobs(): + ''' + 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 + ''' + for _tile_name, site_name, site_type in util.get_roi().gen_sites( + #['IOB18', 'IOB18S', 'IOB18M']): + ['IOB18S']): + yield site_name, site_type + + +def write_pins(ports): + pinstr = '' + for site, (name, dir_, cell) in sorted(ports.items(), key=lambda x: x[1]): + # pinstr += 'set_property -dict "PACKAGE_PIN %s IOSTANDARD LVCMOS33" [get_ports %s]' % (packpin, port) + pinstr += '%s,%s,%s,%s\n' % (site, name, dir_, cell) + open('params.csv', 'w').write(pinstr) + + +def run(): + # All possible values + iosites = {} + for site_name, site_type in gen_iobs(): + iosites[site_name] = site_type + + # Assigned in this design + ports = {} + DIN_N = 0 + DOUT_N = 0 + + def remain_sites(): + return set(iosites.keys()) - set(ports.keys()) + + def rand_site(): + '''Get a random, unused site''' + return random.choice(list(remain_sites())) + + def get_site(): + return next(iter(remain_sites())) + + def assign_i(site, name): + nonlocal DIN_N + + assert site not in ports + cell = "di_bufs[%u].ibuf" % DIN_N + DIN_N += 1 + ports[site] = (name, 'input', cell) + + def assign_o(site, name): + nonlocal DOUT_N + + assert site not in ports + cell = "do_bufs[%u].obuf" % DOUT_N + DOUT_N += 1 + ports[site] = (name, 'output', cell) + + # Assign at least one di and one do + assign_i(get_site(), 'di[0]') + assign_o(get_site(), 'do[0]') + # Now assign the rest randomly + #while len(remain_sites()): + # assign_o(rand_site(), 'do[%u]' % DOUT_N) + + #write_pins(ports) + + print( + ''' +`define N_DI %u +`define N_DO %u + +module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do); + genvar i; + + //Instantiate BUFs so we can LOC them + + wire [`N_DI-1:0] di_buf; + generate + for (i = 0; i < `N_DI; i = i+1) begin:di_bufs + IBUF #( + ) ibuf(.I(di[i]), .O(di_buf[i])); + end + endgenerate + + wire [`N_DO-1:0] do_unbuf; + generate + for (i = 0; i < `N_DO; i = i+1) begin:do_bufs + OBUF #( + ) obuf(.I(do_unbuf[i]), .O(do[i])); + end + endgenerate + + roi roi(.di(di_buf), .do(do_unbuf)); +endmodule + +//Arbitrary terminate into LUTs +module roi(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do); + genvar i; + + generate + for (i = 0; i < `N_DI; i = i+1) begin:dis + (* KEEP, DONT_TOUCH *) + LUT6 #( + .INIT(64'h8000_0000_0000_0001) + ) lut ( + .I0(di[i]), + .I1(di[i]), + .I2(di[i]), + .I3(di[i]), + .I4(di[i]), + .I5(di[i]), + .O()); + end + endgenerate + + generate + for (i = 0; i < `N_DO; i = i+1) begin:dos + (* KEEP, DONT_TOUCH *) + LUT6 #( + .INIT(64'h8000_0000_0000_0001) + ) lut ( + .I0(), + .I1(), + .I2(), + .I3(), + .I4(), + .I5(), + .O(do[i])); + end + endgenerate +endmodule + ''' % (DIN_N, DOUT_N)) + + +if __name__ == '__main__': + run() diff --git a/fuzzers/030-iob18/minitest/top.v b/fuzzers/030-iob18/minitest/top.v new file mode 100644 index 000000000..462f7c3d4 --- /dev/null +++ b/fuzzers/030-iob18/minitest/top.v @@ -0,0 +1,183 @@ +/* +IOBUF + Not a primitive? + Looks like it has an OBUFT + + +Output buffer family: + OBUF + OBUFDS + OBUFT + OBUFTDS +*/ + +`ifndef ROI +ERROR: must set ROI +`endif + +module top(input clk, stb, di, output do); + localparam integer DIN_N = 256; + localparam integer DOUT_N = 256; + + reg [DIN_N-1:0] din; + wire [DOUT_N-1:0] dout; + + reg [DIN_N-1:0] din_shr; + reg [DOUT_N-1:0] dout_shr; + + always @(posedge clk) begin + din_shr <= {din_shr, di}; + dout_shr <= {dout_shr, din_shr[DIN_N-1]}; + if (stb) begin + din <= din_shr; + dout_shr <= dout; + end + end + + assign do = dout_shr[DOUT_N-1]; + + `ROI + roi ( + .clk(clk), + .din(din), + .dout(dout) + ); +endmodule + +module roi_io_a(input clk, input [255:0] din, output [255:0] dout); + assign dout[0] = din[0] & din[1]; + + IOBUF_DCIEN #( + .DRIVE(12), + .IBUF_LOW_PWR("TRUE"), + .IOSTANDARD("DEFAULT"), + .SLEW("SLOW"), + .USE_IBUFDISABLE("TRUE") + ) IOBUF_DCIEN_inst ( + .O(1'b0), + .IO(1'bz), + .I(dout[8]), + .IBUFDISABLE(1'b0), + .DCITERMDISABLE(1'b0), + .T(1'b1)); + +endmodule + +module roi_io_b(input clk, input [255:0] din, output [255:0] dout); + assign dout[0] = din[0] & din[1]; + + wire onet; + + IOBUF_DCIEN #( + .DRIVE(12), + .IBUF_LOW_PWR("FALSE"), + .IOSTANDARD("DEFAULT"), + .SLEW("SLOW"), + .USE_IBUFDISABLE("FALSE") + ) IOBUF_DCIEN_inst ( + .O(onet), + .IO(1'bz), + .I(dout[8]), + .IBUFDISABLE(1'b0), + .DCITERMDISABLE(1'b0), + .T(1'b1)); + + PULLUP PULLUP_inst ( + .O(onet) + ); + + IOBUF_DCIEN #( + .DRIVE(12), + .IBUF_LOW_PWR("FALSE"), + .IOSTANDARD("DEFAULT"), + .SLEW("SLOW"), + .USE_IBUFDISABLE("FALSE") + ) i2 ( + .O(), + .IO(1'bz), + .I(dout[8]), + .IBUFDISABLE(1'b0), + .DCITERMDISABLE(1'b0), + .T(1'b1)); + +endmodule + +/* +For some reason this doesn't diff +Was this optimized out? + +ERROR: [Place 30-69] Instance roi/dut/OBUFT (OBUFT) is unplaced after IO placer +ERROR: [Place 30-68] Instance roi/dut/OBUFT (OBUFT) is not placed +*/ + +/* +module roi_prop_a(input clk, input [255:0] din, output [255:0] dout); + assign dout[0] = din[0] & din[1]; + + //(* LOC="D19", KEEP, DONT_TOUCH *) + (* KEEP, DONT_TOUCH *) + IOBUF #( + .DRIVE(8), + .IBUF_LOW_PWR("TRUE"), + .IOSTANDARD("DEFAULT"), + .SLEW("SLOW") + ) dut ( + .O(dout[1]), + .I(din[0]), + .T(din[1])); +endmodule + +module roi_prop_b(input clk, input [255:0] din, output [255:0] dout); + assign dout[0] = din[0] & din[1]; + + //(* LOC="D19", KEEP, DONT_TOUCH *) + (* KEEP, DONT_TOUCH *) + IOBUF #( + .DRIVE(12), + .IBUF_LOW_PWR("TRUE"), + .IOSTANDARD("DEFAULT"), + .SLEW("SLOW") + ) dut ( + .O(dout[1]), + .I(din[0]), + .T(din[1])); +endmodule +*/ + +/* +ERROR: [DRC REQP-1581] obuf_loaded: OBUFT roi/dut pin O drives one or more invalid loads. The loads are: dout_shr[1]_i_1 +ERROR: [Place 30-69] Instance roi/dut (OBUFT) is unplaced after IO placer +hmm +Abandoning verilog approach +tcl seems to work well, just use it directly +*/ +module roi_prop_a(input clk, input [255:0] din, output [255:0] dout); + (* LOC="D19", KEEP, DONT_TOUCH *) + //(* KEEP, DONT_TOUCH *) + OBUFT #( + .DRIVE(8), + .IOSTANDARD("DEFAULT"), + .SLEW("SLOW") + ) dut ( + //.O(dout[1]), + .O(), + .I(din[0]), + .T(din[1])); +endmodule + +module roi_prop_b(input clk, input [255:0] din, output [255:0] dout); + (* LOC="D19", KEEP, DONT_TOUCH *) + //(* KEEP, DONT_TOUCH *) + (* KEEP, DONT_TOUCH *) + OBUFT #( + .DRIVE(12), + .IOSTANDARD("DEFAULT"), + .SLEW("SLOW") + ) dut ( + //.O(dout[1]), + .O(), + .I(din[0]), + .T(din[1])); +endmodule + + diff --git a/fuzzers/030-iob18/process_rdb.py b/fuzzers/030-iob18/process_rdb.py new file mode 100644 index 000000000..8d997ab15 --- /dev/null +++ b/fuzzers/030-iob18/process_rdb.py @@ -0,0 +1,251 @@ +#!/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 +""" 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', '', '']: + 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 000000000..83bfc45fa --- /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 000000000..337a2fc1d --- /dev/null +++ b/fuzzers/030-iob18/top.py @@ -0,0 +1,425 @@ +#!/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 +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 000000000..5e094924d --- /dev/null +++ b/fuzzers/030-iob18/write_io_banks.tcl @@ -0,0 +1,44 @@ +# 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 +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 398421331..bb643bb64 100644 --- a/fuzzers/035-iob-ilogic/Makefile +++ b/fuzzers/035-iob-ilogic/Makefile @@ -22,19 +22,29 @@ build/segbits_xioi3.db: build/segbits_xioi3.rdb ${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 ${XRAY_MERGEDB} rioi3 build/segbits_xioi3.db ${XRAY_MERGEDB} rioi3_tbytesrc build/segbits_xioi3.db ${XRAY_MERGEDB} rioi3_tbyteterm build/segbits_xioi3.db + ${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_lioi3 build/mask_xioi3.db ${XRAY_MERGEDB} mask_lioi3_tbytesrc build/mask_xioi3.db ${XRAY_MERGEDB} mask_lioi3_tbyteterm build/mask_xioi3.db ${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 + ${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 .PHONY: database pushdb diff --git a/fuzzers/035-iob-ilogic/generate.tcl b/fuzzers/035-iob-ilogic/generate.tcl index 18eaf708c..48dcb5281 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 000000000..04533ba08 --- /dev/null +++ b/fuzzers/035a-iob18-idelay/Makefile @@ -0,0 +1,29 @@ +# 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 := 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 000000000..46f87e1a9 --- /dev/null +++ b/fuzzers/035a-iob18-idelay/bits.dbf @@ -0,0 +1,14 @@ +34_08 34_14 ,IOI3.IDELAY_Y1.IDELAY_TYPE_FIXED +35_113 35_119 ,IOI3.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 000000000..b500632f4 --- /dev/null +++ b/fuzzers/035a-iob18-idelay/generate.py @@ -0,0 +1,87 @@ +#!/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 + +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 000000000..eecd48e6c --- /dev/null +++ b/fuzzers/035a-iob18-idelay/generate.tcl @@ -0,0 +1,31 @@ +# 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 +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 000000000..f87685ed5 --- /dev/null +++ b/fuzzers/035a-iob18-idelay/top.py @@ -0,0 +1,237 @@ +#!/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, 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 446482e35..8297e97cf 100644 --- a/fuzzers/035b-iob-iserdes/Makefile +++ b/fuzzers/035b-iob-iserdes/Makefile @@ -22,19 +22,30 @@ build/segbits_xioi3.db: build/segbits_xioi3.rdb ${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 ${XRAY_MERGEDB} rioi3 build/segbits_xioi3.db ${XRAY_MERGEDB} rioi3_tbytesrc build/segbits_xioi3.db ${XRAY_MERGEDB} rioi3_tbyteterm build/segbits_xioi3.db + ${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_lioi3 build/mask_xioi3.db ${XRAY_MERGEDB} mask_lioi3_tbytesrc build/mask_xioi3.db ${XRAY_MERGEDB} mask_lioi3_tbyteterm build/mask_xioi3.db ${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 + ${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 .PHONY: database pushdb diff --git a/fuzzers/036-iob18-ologic/Makefile b/fuzzers/036-iob18-ologic/Makefile new file mode 100644 index 000000000..c96dc6dd7 --- /dev/null +++ b/fuzzers/036-iob18-ologic/Makefile @@ -0,0 +1,29 @@ +# 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 := 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 000000000..8b0c1341d --- /dev/null +++ b/fuzzers/036-iob18-ologic/bits.dbf @@ -0,0 +1,8 @@ +31_92,IOB33.IOB_Y0.ODDR.DDR_CLK_EDGE.OPPOSITE_EDGE +30_35,IOB33.IOB_Y1.ODDR.DDR_CLK_EDGE.OPPOSITE_EDGE +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 000000000..35b7d445d --- /dev/null +++ b/fuzzers/036-iob18-ologic/generate.py @@ -0,0 +1,196 @@ +#!/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 + +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): + # TODO: do we need this here? + # this frame number limit does not seem + # to apply to 1.8V high speed banks + #if frame < 30 or frame > 37: + # return False + + return True + + +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 000000000..492dae824 --- /dev/null +++ b/fuzzers/036-iob18-ologic/generate.tcl @@ -0,0 +1,107 @@ +# 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 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 000000000..5b219cb98 --- /dev/null +++ b/fuzzers/036-iob18-ologic/top.py @@ -0,0 +1,474 @@ +#!/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 +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 000000000..284a9e00d --- /dev/null +++ b/fuzzers/037-iob18-pips/Makefile @@ -0,0 +1,58 @@ +# 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 +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)).*" + +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 000000000..e69de29bb diff --git a/fuzzers/037-iob18-pips/generate.py b/fuzzers/037-iob18-pips/generate.py new file mode 100644 index 000000000..5e0b37250 --- /dev/null +++ b/fuzzers/037-iob18-pips/generate.py @@ -0,0 +1,105 @@ +#!/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 + +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 000000000..2983f40d4 --- /dev/null +++ b/fuzzers/037-iob18-pips/generate.tcl @@ -0,0 +1,109 @@ +# 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 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 000000000..3138494da --- /dev/null +++ b/fuzzers/037-iob18-pips/ioi_pip_list.tcl @@ -0,0 +1,47 @@ +# 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 +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 000000000..10a4f97bb --- /dev/null +++ b/fuzzers/037-iob18-pips/output_cmt.tcl @@ -0,0 +1,18 @@ +# 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 +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 000000000..bc613da63 --- /dev/null +++ b/fuzzers/037-iob18-pips/top.py @@ -0,0 +1,391 @@ +#!/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 +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 ae18a3608..38b2b2412 100644 --- a/fuzzers/039-hclk-config/Makefile +++ b/fuzzers/039-hclk-config/Makefile @@ -9,7 +9,7 @@ N ?= 50 include ../fuzzer.mk -database: build/segbits_hclk_ioi3.db +database: build/segbits_hclk_ioi.db build/segbits_hclk_ioi3.rdb: $(SPECIMENS_OK) ${XRAY_SEGMATCH} -c 5 -o build/segbits_hclk_ioi3.rdb \ @@ -22,8 +22,16 @@ build/segbits_hclk_ioi3.db: build/segbits_hclk_ioi3.rdb ${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 +build/segbits_hclk_ioi.db: build/segbits_hclk_ioi3.db build/mask_hclk_ioi3.db + sed -e 's/HCLK_IOI3/HCLK_IOI/g' $< > $@ + cp build/mask_hclk_ioi3.db build/mask_hclk_ioi.db + pushdb: database ${XRAY_MERGEDB} hclk_ioi3 build/segbits_hclk_ioi3.db ${XRAY_MERGEDB} mask_hclk_ioi3 build/mask_hclk_ioi3.db + ${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/Makefile b/fuzzers/047-hclk-ioi18-pips/Makefile new file mode 100644 index 000000000..b0742130e --- /dev/null +++ b/fuzzers/047-hclk-ioi18-pips/Makefile @@ -0,0 +1,53 @@ +# 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 +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 000000000..8f1c36a5e --- /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 000000000..e69de29bb diff --git a/fuzzers/047-hclk-ioi18-pips/generate.py b/fuzzers/047-hclk-ioi18-pips/generate.py new file mode 100644 index 000000000..abcf00fcc --- /dev/null +++ b/fuzzers/047-hclk-ioi18-pips/generate.py @@ -0,0 +1,92 @@ +#!/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 + +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 000000000..ec7756a99 --- /dev/null +++ b/fuzzers/047-hclk-ioi18-pips/generate.tcl @@ -0,0 +1,358 @@ +# 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 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 000000000..f71fe1d8c --- /dev/null +++ b/fuzzers/047-hclk-ioi18-pips/hclk_ioi_pip_list.tcl @@ -0,0 +1,49 @@ +# 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 +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 000000000..40034830e --- /dev/null +++ b/fuzzers/047-hclk-ioi18-pips/output_cmt.tcl @@ -0,0 +1,18 @@ +# 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 +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 000000000..b00925b53 --- /dev/null +++ b/fuzzers/047-hclk-ioi18-pips/top.py @@ -0,0 +1,479 @@ +#!/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 +""" 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 94be82f34..a42438010 100644 --- a/fuzzers/071-ppips/generate.tcl +++ b/fuzzers/071-ppips/generate.tcl @@ -322,7 +322,7 @@ foreach tile_type {HCLK_IOI3} { } 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 {PCIE_INT_INTERFACE_L PCIE_INT_INTERFACE_R} { } } -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 ee43c9535..94a109491 100644 --- a/fuzzers/Makefile +++ b/fuzzers/Makefile @@ -113,6 +113,9 @@ $(eval $(call fuzzer,027-bram36-config,005-tilegrid,all)) $(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 @@ $(eval $(call fuzzer,034b-cmt-mmcm-pips,005-tilegrid 071-ppips,all)) 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,044-clk-bufg-pips,046-clk-bufg-muxed-pips,all)) $(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 542fcc853..c362bef1d 100644 --- a/prjxray/segmaker.py +++ b/prjxray/segmaker.py @@ -359,6 +359,8 @@ def name_default(): -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 @@ def name_default(): if tile_type_norm in ['LIOB33', 'RIOB33']: tile_type_norm = 'IOB33' - + if tile_type_norm in ['LIOB18', 'RIOB18']: + tile_type_norm = 'IOB18' if tile_type_norm in ['LIOI3', 'RIOI3']: tile_type_norm = 'IOI3' + 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 bb2efb065..615bf726f 100644 --- a/prjxray/util.py +++ b/prjxray/util.py @@ -86,8 +86,8 @@ def get_fabric(): 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 @@ def set_part_information(db_root, information): 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 @@ def set_part_resources(file_path, information): 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_fabric_for_part(db_root, part): 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_devices(db_root): 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 85a705ed3..9f41893c9 100644 --- a/settings/kintex7.sh +++ b/settings/kintex7.sh @@ -10,17 +10,17 @@ export XRAY_PART="xc7k70tfbg676-2" 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" +export XRAY_ROI="SLICE_X0Y50:SLICE_X19Y99 DSP48_X0Y20:DSP48_X0Y39 RAMB18_X0Y0:RAMB18_X3Y39 RAMB36_X0Y0:RAMB36_X3Y19 IOB_X0Y50:IOB_X0Y99 IOB_X1Y50:IOB_X1Y99" # Part of CMT X0Y1 export XRAY_ROI_GRID_X1="0" -export XRAY_ROI_GRID_X2="38" +export XRAY_ROI_GRID_X2="116" # 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 1af59cdd2..d62cc27b0 100644 --- a/tools/segmatch.cc +++ b/tools/segmatch.cc @@ -255,7 +255,7 @@ int main(int argc, char** argv) { 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 98383d4e0..eae4c6d6b 100755 --- a/utils/mergedb.sh +++ b/utils/mergedb.sh @@ -121,6 +121,9 @@ case "$1" in 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 @@ case "$1" in 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 @@ case "$1" in hclk_ioi3) cp "$2" "$tmp1" ;; + hclk_ioi) + cp "$2" "$tmp1" ;; + pcie_bot) cp "$2" "$tmp1" ;;