005-tilegrid/gtx_int_interface fuzzer works

Signed-off-by: Hans Baier <foss@hans-baier.de>
diff --git a/fuzzers/005-tilegrid/gtx_int_interface/Makefile b/fuzzers/005-tilegrid/gtx_int_interface/Makefile
new file mode 100644
index 0000000..eb459dc
--- /dev/null
+++ b/fuzzers/005-tilegrid/gtx_int_interface/Makefile
@@ -0,0 +1,17 @@
+# Copyright (C) 2017-2020  The Project X-Ray Authors.
+#
+# Use of this source code is governed 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 ?= 8
+GENERATE_ARGS?="--oneval 1 --design params.csv --dframe 1b --dword 0 --dbit 4"
+include ../fuzzaddr/common.mk
+SEGBITS=$(BUILD_DIR)/segbits_tilegrid.tdb
+$(SEGBITS): $(SPECIMENS_OK)
+	# multiple bits match for the changes, but all of those except the ones with addresses ending with 0x9b are known
+	# and not related to GTX_INT_INTERFACE
+	${XRAY_SEGMATCH} -c 6 -o $(BUILD_DIR)/segbits_tilegrid.tdb $$(find $(BUILD_DIR) -name "segdata_tilegrid.txt")
+	tr ' ' '\n' < $(SEGBITS) | grep -E 'GTX|9B' | paste -d " " - - > $(SEGBITS).tmp
+	mv -fv $(SEGBITS).tmp $(SEGBITS)
diff --git a/fuzzers/005-tilegrid/gtx_int_interface/generate.tcl b/fuzzers/005-tilegrid/gtx_int_interface/generate.tcl
new file mode 100644
index 0000000..798d66b
--- /dev/null
+++ b/fuzzers/005-tilegrid/gtx_int_interface/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 parse_csv {} {
+    set fp [open "params.csv"]
+    set file_data [read $fp]
+    close $fp
+
+    set file_data [split $file_data "\n"]
+
+    set params_map [dict create]
+
+    set is_first_line true
+    foreach line $file_data {
+        if { $is_first_line } {
+            set is_first_line false
+            continue
+        }
+
+        # Skip empty lines
+        if { $line == "" } {
+            continue
+        }
+
+        set parts [split $line ","]
+
+        dict lappend params_map [lindex $parts 2] [lindex $parts 1]
+    }
+
+    return $params_map
+}
+
+
+proc route_through_delay {} {
+    set params_map [parse_csv]
+
+    dict for { key value } $params_map {
+        if { $value == 0 } {
+            continue
+        }
+
+        set net_name "QPLLLOCKEN_$key"
+        set net [get_nets $net_name]
+
+        set wire [get_wires -of_objects $net -filter {TILE_NAME =~ "*GTX_INT_INTERFACE*" && NAME =~ "*IMUX_OUT24*"}]
+        set wire_parts [split $wire "/"]
+
+        set gtx_int_tile [lindex $wire_parts 0]
+        set node [get_nodes -of_object [get_tiles $gtx_int_tile] -filter { NAME =~ "*DELAY24" }]
+
+        route_design -unroute -nets $net
+        puts "Attempting to route net $net through $node."
+        route_via $net [list $node]
+    }
+}
+
+
+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]
+
+    # Disable MMCM frequency etc sanity checks
+    set_property IS_ENABLED 0 [get_drc_checks {REQP-47}]
+    set_property IS_ENABLED 0 [get_drc_checks {REQP-48}]
+
+    place_design
+    route_design
+
+    route_through_delay
+
+    write_checkpoint -force design.dcp
+    write_bitstream -force design.bit
+}
+
+run
diff --git a/fuzzers/005-tilegrid/gtx_int_interface/top.py b/fuzzers/005-tilegrid/gtx_int_interface/top.py
new file mode 100644
index 0000000..2ee27e0
--- /dev/null
+++ b/fuzzers/005-tilegrid/gtx_int_interface/top.py
@@ -0,0 +1,104 @@
+#!/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 re
+import random
+random.seed(int(os.getenv("SEED"), 16))
+from prjxray import util
+from prjxray.db import Database
+from prjxray.grid_types import GridLoc
+
+GTX_INT_Y_RE = re.compile("GTX_INT_INTERFACE.*X[0-9]+Y([0-9]+)")
+
+
+def get_gtx_int_tile(clock_region, grid):
+    for tile_name in sorted(grid.tiles()):
+        if not tile_name.startswith("GTX_INT_INTERFACE"):
+            continue
+
+        loc = grid.loc_of_tilename(tile_name)
+
+        left_gridinfo = grid.gridinfo_at_loc(
+            GridLoc(loc.grid_x - 1, loc.grid_y))
+        right_gridinfo = grid.gridinfo_at_loc(
+            GridLoc(loc.grid_x + 1, loc.grid_y))
+
+        if left_gridinfo.tile_type in ["INT_L", "INT_R"]:
+            cmt = left_gridinfo.clock_region
+        elif right_gridinfo.tile_type in ["INT_L", "INT_R"]:
+            cmt = right_gridinfo.clock_region
+        else:
+            assert False
+
+        gridinfo = grid.gridinfo_at_loc(loc)
+
+        m = GTX_INT_Y_RE.match(tile_name)
+
+        assert m
+
+        int_y = int(m.group(1))
+
+        if clock_region == cmt and int_y % 50 == 26:
+            return tile_name
+
+
+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)
+
+        for site_name, site_type in gridinfo.sites.items():
+            if site_type in ['GTXE2_COMMON']:
+                gtx_int_tile = get_gtx_int_tile(gridinfo.clock_region, grid)
+
+                yield gtx_int_tile, site_name
+
+
+def write_params(params):
+    pinstr = 'tile,val,site\n'
+    for tile, (site, val) in sorted(params.items()):
+        pinstr += '%s,%s,%s\n' % (tile, val, site)
+    open('params.csv', 'w').write(pinstr)
+
+
+def run():
+    print('''
+module top();
+    ''')
+
+    params = {}
+
+    sites = list(gen_sites())
+    for gtx_int_tile, site_name in sites:
+        isone = random.randint(0, 1)
+
+        params[gtx_int_tile] = (site_name, isone)
+
+        print(
+            '''
+wire QPLLLOCKEN_{site};
+
+(* KEEP, DONT_TOUCH *)
+LUT1 lut_{site} (.O(QPLLLOCKEN_{site}));
+
+(* KEEP, DONT_TOUCH, LOC = "{site}" *)
+GTXE2_COMMON gtxe2_common_{site} (
+    .QPLLLOCKEN(QPLLLOCKEN_{site})
+);'''.format(site=site_name))
+
+    print("endmodule")
+    write_params(params)
+
+
+if __name__ == '__main__':
+    run()