diff --git a/fuzzers/005-tilegrid/gtx_int_interface/Makefile b/fuzzers/005-tilegrid/gtx_int_interface/Makefile new file mode 100644 index 00000000..eb459dc8 --- /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 00000000..798d66b9 --- /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 00000000..2ee27e0d --- /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()