diff --git a/fuzzers/005-tilegrid/Makefile b/fuzzers/005-tilegrid/Makefile index 4eea3fb1..98566187 100644 --- a/fuzzers/005-tilegrid/Makefile +++ b/fuzzers/005-tilegrid/Makefile @@ -36,6 +36,7 @@ ifeq (${XRAY_DATABASE}, artix7) TILEGRID_TDB_DEPENDENCIES += pcie/$(BUILD_FOLDER)/segbits_tilegrid.tdb TILEGRID_TDB_DEPENDENCIES += gtp_common/$(BUILD_FOLDER)/segbits_tilegrid.tdb TILEGRID_TDB_DEPENDENCIES += gtp_channel/$(BUILD_FOLDER)/segbits_tilegrid.tdb +TILEGRID_TDB_DEPENDENCIES += gtp_int_interface/$(BUILD_FOLDER)/segbits_tilegrid.tdb endif ifeq (${XRAY_DATABASE}, zynq7) @@ -148,6 +149,9 @@ gtp_common/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID} gtp_channel/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID} cd gtp_channel && $(MAKE) +gtp_int_interface/$(BUILD_FOLDER)/segbits_tilegrid.tdb: ${BASICDB_TILEGRID} + cd gtp_int_interface && $(MAKE) + $(BUILD_FOLDER)/tilegrid_tdb.json: add_tdb.py $(TILEGRID_TDB_DEPENDENCIES) python3 add_tdb.py \ --fn-in ${BASICDB_TILEGRID} \ @@ -190,6 +194,7 @@ clean: cd pcie && $(MAKE) clean cd gtp_common && $(MAKE) clean cd gtp_channel && $(MAKE) clean + cd gtp_int_interface && $(MAKE) clean clean_all: rm -rf build_* run.*.ok @@ -219,6 +224,7 @@ clean_all: cd pcie && $(MAKE) clean_all cd gtp_common && $(MAKE) clean_all cd gtp_channel && $(MAKE) clean_all + cd gtp_int_interface && $(MAKE) clean_all .PHONY: database pushdb clean clean_all run diff --git a/fuzzers/005-tilegrid/add_tdb.py b/fuzzers/005-tilegrid/add_tdb.py index b98526e7..f293d00d 100644 --- a/fuzzers/005-tilegrid/add_tdb.py +++ b/fuzzers/005-tilegrid/add_tdb.py @@ -109,6 +109,7 @@ def run(fn_in, fn_out, verbose=False): ("hclk_ioi", 42, 1), ("pcie", 36, 101), ("gtp_common", 42, 101), + ("gtp_int_interface", int_frames, int_words), ("clb_int", int_frames, int_words), ("iob_int", int_frames, int_words), ("bram_int", int_frames, int_words), diff --git a/fuzzers/005-tilegrid/generate_full.py b/fuzzers/005-tilegrid/generate_full.py index f5a8be4e..5fc1978c 100644 --- a/fuzzers/005-tilegrid/generate_full.py +++ b/fuzzers/005-tilegrid/generate_full.py @@ -221,6 +221,99 @@ def propagate_INT_bits_in_column(database, tiles_by_grid): tile = database[tile_name] +def propagate_INT_INTERFACE_bits_in_column( + database, tiles_by_grid, int_interface_name): + """ Propigate INT offsets up and down INT columns. + + INT columns appear to be fairly regular, where starting from offset 0, + INT tiles next to INT tiles increase the word offset by 2. The HCLK tile + is surrounded above and sometimes below by an INT tile. Because the HCLK + tile only useds one word, the offset increase by one at the HCLK. + + """ + + seen_int = set() + + int_frames, int_words, _ = localutil.get_entry('INT', 'CLB_IO_CLK') + hclk_frames, hclk_words, _ = localutil.get_entry('HCLK', 'CLB_IO_CLK') + + for tile_name in sorted(database.keys()): + tile = database[tile_name] + + if not tile['type'].startswith(int_interface_name): + continue + + if not tile['bits']: + continue + + if tile_name in seen_int: + continue + + # Walk down INT column + down_tile = tile + down_tile_name = tile_name + while True: + seen_int.add(down_tile_name) + + baseaddr = int(down_tile['bits']['CLB_IO_CLK']['baseaddr'], 0) + offset = down_tile['bits']['CLB_IO_CLK']['offset'] + extra_offset = 0 + + next_tile = tiles_by_grid[( + down_tile['grid_x'], down_tile['grid_y'] + 1)] + if next_tile.startswith("HCLK"): + next_tile = tiles_by_grid[( + down_tile['grid_x'], down_tile['grid_y'] + 2)] + extra_offset = hclk_words + + next_tile_type = database[next_tile]['type'] + + if next_tile_type != tile['type']: + break + + if next_tile_type == down_tile['type']: + # INT next to INT + offset -= (int_words + extra_offset) + localutil.add_tile_bits( + next_tile, database[next_tile], baseaddr, offset, + int_frames, int_words) + + down_tile_name = next_tile + down_tile = database[down_tile_name] + + # Walk up INT column + up_tile = tile + up_tile_name = tile_name + while True: + seen_int.add(up_tile_name) + + baseaddr = int(up_tile['bits']['CLB_IO_CLK']['baseaddr'], 0) + offset = up_tile['bits']['CLB_IO_CLK']['offset'] + extra_offset = 0 + + next_tile = tiles_by_grid[( + up_tile['grid_x'], up_tile['grid_y'] - 1)] + if next_tile.startswith("HCLK"): + next_tile = tiles_by_grid[( + up_tile['grid_x'], up_tile['grid_y'] - 2)] + extra_offset = hclk_words + + next_tile_type = database[next_tile]['type'] + + if next_tile_type != tile['type']: + break + + if next_tile_type == up_tile['type']: + # INT next to INT + offset += (int_words + extra_offset) + localutil.add_tile_bits( + next_tile, database[next_tile], baseaddr, offset, + int_frames, int_words) + + up_tile_name = next_tile + up_tile = database[up_tile_name] + + def propagate_rebuf(database, tiles_by_grid): """ Writing a fuzzer for the CLK_BUFG_REBUF tiles is hard, so propigate from CLK_HROW tiles. @@ -454,6 +547,8 @@ def run(json_in_fn, json_out_fn, verbose=False): propagate_INT_lr_bits(database, tiles_by_grid, verbose=verbose) propagate_INT_bits_in_column(database, tiles_by_grid) + propagate_INT_INTERFACE_bits_in_column( + database, tiles_by_grid, "GTP_INT_INTERFACE") propagate_rebuf(database, tiles_by_grid) propagate_IOB_SING(database, tiles_by_grid) propagate_IOI_SING(database, tiles_by_grid) diff --git a/fuzzers/005-tilegrid/gtp_int_interface/Makefile b/fuzzers/005-tilegrid/gtp_int_interface/Makefile new file mode 100644 index 00000000..aa8911ce --- /dev/null +++ b/fuzzers/005-tilegrid/gtp_int_interface/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 ?= 8 +GENERATE_ARGS?="--oneval 1 --design params.csv --dword 0 --auto-frame" +include ../fuzzaddr/common.mk diff --git a/fuzzers/005-tilegrid/gtp_int_interface/generate.tcl b/fuzzers/005-tilegrid/gtp_int_interface/generate.tcl new file mode 100644 index 00000000..c682d573 --- /dev/null +++ b/fuzzers/005-tilegrid/gtp_int_interface/generate.tcl @@ -0,0 +1,87 @@ +# Copyright (C) 2017-2020 The Project X-Ray Authors +# +# Use of this source code is governed 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 + } + + set parts [split $line ","] + + dict lappend params_map [lindex $parts 2] [lindex $parts 1] + } + + puts $params_map + return $params_map +} + + +proc route_through_delay {} { + set params_map [parse_csv] + + dict for { key value } $params_map { + if { $value == 0 } { + continue + } + + if { $key == "" } { + puts "Dictionary key is incorrect, continuing" + continue + } + + set net_name "PLL0LOCKEN_$key" + set net [get_nets $net_name] + + set wire [get_wires -of_objects $net -filter {TILE_NAME =~ "*GTP_INT_INTERFACE*" && NAME =~ "*IMUX_OUT42*"}] + set wire_parts [split $wire "/"] + + set gtp_int_tile [lindex $wire_parts 0] + set node [get_nodes -of_object [get_tiles $gtp_int_tile] -filter { NAME =~ "*DELAY42" }] + + 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/gtp_int_interface/top.py b/fuzzers/005-tilegrid/gtp_int_interface/top.py new file mode 100644 index 00000000..8c5548ff --- /dev/null +++ b/fuzzers/005-tilegrid/gtp_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 + +GTP_INT_Y_RE = re.compile("GTP_INT_INTERFACE.*X[0-9]+Y([0-9]+)") + + +def get_gtp_int_tile(clock_region, grid): + for tile_name in sorted(grid.tiles()): + if not tile_name.startswith("GTP_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 = GTP_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 ['GTPE2_COMMON']: + gtp_int_tile = get_gtp_int_tile(gridinfo.clock_region, grid) + + yield gtp_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 gtp_int_tile, site_name in sites: + isone = random.randint(0, 1) + + params[gtp_int_tile] = (site_name, isone) + + print( + ''' +wire PLL0LOCKEN_{site}; + +(* KEEP, DONT_TOUCH *) +LUT1 lut_{site} (.O(PLL0LOCKEN_{site})); + +(* KEEP, DONT_TOUCH, LOC = "{site}" *) +GTPE2_COMMON gtpe2_common_{site} ( + .PLL0LOCKEN(PLL0LOCKEN_{site}) +);'''.format(site=site_name)) + + print("endmodule") + write_params(params) + + +if __name__ == '__main__': + run()