From b04598da2616f02b7a56a5ff54bdce737d3d1b99 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Thu, 7 Feb 2019 15:00:00 -0800 Subject: [PATCH] Solve orphan INT columns in Kintex7. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fuzzers/005-tilegrid/Makefile | 5 + fuzzers/005-tilegrid/add_tdb.py | 3 + .../005-tilegrid/orphan_int_column/Makefile | 3 + .../orphan_int_column/generate.tcl | 60 ++++ fuzzers/005-tilegrid/orphan_int_column/top.py | 339 ++++++++++++++++++ 5 files changed, 410 insertions(+) create mode 100644 fuzzers/005-tilegrid/orphan_int_column/Makefile create mode 100644 fuzzers/005-tilegrid/orphan_int_column/generate.tcl create mode 100644 fuzzers/005-tilegrid/orphan_int_column/top.py diff --git a/fuzzers/005-tilegrid/Makefile b/fuzzers/005-tilegrid/Makefile index e310f765..46edf091 100644 --- a/fuzzers/005-tilegrid/Makefile +++ b/fuzzers/005-tilegrid/Makefile @@ -25,6 +25,7 @@ TILEGRID_TDB_DEPENDENCIES += mmcm/build/segbits_tilegrid.tdb endif ifeq (${XRAY_DATABASE}, kintex7) +TILEGRID_TDB_DEPENDENCIES += orphan_int_column/build/segbits_tilegrid.tdb else # Disable DSP INT fuzzer on kintex7. It doesn't work, and isn't required. TILEGRID_TDB_DEPENDENCIES += dsp_int/build/segbits_tilegrid.tdb @@ -92,6 +93,9 @@ fifo_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json cfg_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json cd cfg_int && $(MAKE) +orphan_int_column/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json + cd orphan_int_column && $(MAKE) + build/tilegrid_tdb.json: add_tdb.py $(TILEGRID_TDB_DEPENDENCIES) python3 add_tdb.py \ --fn-in build/basicdb/tilegrid.json \ @@ -124,6 +128,7 @@ clean: cd monitor && $(MAKE) clean cd monitor_int && $(MAKE) clean cd cfg_int && $(MAKE) clean + cd orphan_int_column && $(MAKE) clean .PHONY: database pushdb clean run diff --git a/fuzzers/005-tilegrid/add_tdb.py b/fuzzers/005-tilegrid/add_tdb.py index 72b6c549..a98e6a68 100644 --- a/fuzzers/005-tilegrid/add_tdb.py +++ b/fuzzers/005-tilegrid/add_tdb.py @@ -92,6 +92,9 @@ def run(fn_in, fn_out, verbose=False): ("ps7_int/build/segbits_tilegrid.tdb", int_frames, int_words), ("cfg_int/build/segbits_tilegrid.tdb", int_frames, int_words), ("monitor_int/build/segbits_tilegrid.tdb", int_frames, int_words), + ( + "orphan_int_column/build/segbits_tilegrid.tdb", int_frames, + int_words), ] for (tdb_fn, frames, words) in tdb_fns: diff --git a/fuzzers/005-tilegrid/orphan_int_column/Makefile b/fuzzers/005-tilegrid/orphan_int_column/Makefile new file mode 100644 index 00000000..10b04809 --- /dev/null +++ b/fuzzers/005-tilegrid/orphan_int_column/Makefile @@ -0,0 +1,3 @@ +N ?= 16 +GENERATE_ARGS?="--oneval 1 --design params.csv --dframe 9 --dword 0" +include ../fuzzaddr/common.mk diff --git a/fuzzers/005-tilegrid/orphan_int_column/generate.tcl b/fuzzers/005-tilegrid/orphan_int_column/generate.tcl new file mode 100644 index 00000000..41aeaf39 --- /dev/null +++ b/fuzzers/005-tilegrid/orphan_int_column/generate.tcl @@ -0,0 +1,60 @@ +source "$::env(XRAY_DIR)/utils/utils.tcl" + +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] + + place_design + route_design + + write_checkpoint -force design.dcp + write_bitstream -force design.bit + write_pip_txtdata design.txt + + set fp [open top.txt] + set int_tiles [split [read $fp] "\n"] + close $fp + + set fp [open design.txt] + set pips [split [read $fp] "\n"] + close $fp + + set found_int_tiles {} + foreach pip $pips { + set parts [split $pip " "] + set tile_idx [lsearch -exact $int_tiles [lindex $parts 0]] + + if {$tile_idx == -1} { + continue + } + + set tile [lindex $int_tiles $tile_idx] + set pip_of_interest "$tile/INT_L.EL1END1->>EE2BEG1" + if { $pip_of_interest == [lindex $parts 1] } { + lappend found_int_tiles $tile + } + } + + set fp [open params.csv "w"] + puts $fp "tile,val" + foreach tile $int_tiles { + if {$tile == ""} { + continue + } + + set pip_active [lsearch -exact $found_int_tiles $tile] + if {$pip_active != -1} { + puts $fp "$tile,1" + } else { + puts $fp "$tile,0" + } + } + close $fp +} + +run diff --git a/fuzzers/005-tilegrid/orphan_int_column/top.py b/fuzzers/005-tilegrid/orphan_int_column/top.py new file mode 100644 index 00000000..ff960e7b --- /dev/null +++ b/fuzzers/005-tilegrid/orphan_int_column/top.py @@ -0,0 +1,339 @@ +import os +import random +random.seed(int(os.getenv("SEED"), 16)) +from prjxray import util +from prjxray.db import Database + +INT_TILE_TYPES = ['INT_L', 'INT_R'] +HCLK_TILE_TYPES = ['HCLK_L', 'HCLK_R', 'HCLK_L_BOT_UTURN', 'HCLK_R_BOT_UTURN'] + + +def get_int_column_roots(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 not in INT_TILE_TYPES: + continue + + next_gridinfo = grid.gridinfo_at_loc((loc.grid_x, loc.grid_y + 1)) + + if next_gridinfo.tile_type in INT_TILE_TYPES: + continue + + if next_gridinfo.tile_type in HCLK_TILE_TYPES: + continue + + assert next_gridinfo.tile_type in [ + 'B_TERM_INT', 'BRKH_INT', 'BRKH_B_TERM_INT' + ], next_gridinfo.tile_type + + yield tile_name + + +def build_int_columns(grid): + + int_columns = {} + + for root_tile_name in get_int_column_roots(grid): + assert root_tile_name not in int_columns + int_columns[root_tile_name] = [] + + tile_name = root_tile_name + gridinfo = grid.gridinfo_at_tilename(tile_name) + + # Walk up INT column. + while gridinfo.tile_type in INT_TILE_TYPES: + int_columns[root_tile_name].append(tile_name) + + loc = grid.loc_of_tilename(tile_name) + tile_name = grid.tilename_at_loc((loc.grid_x, loc.grid_y - 1)) + gridinfo = grid.gridinfo_at_tilename(tile_name) + + if gridinfo.tile_type in HCLK_TILE_TYPES: + loc = grid.loc_of_tilename(tile_name) + tile_name = grid.tilename_at_loc((loc.grid_x, loc.grid_y - 1)) + gridinfo = grid.gridinfo_at_tilename(tile_name) + + assert gridinfo.tile_type in [ + 'T_TERM_INT', 'BRKH_INT', 'BRKH_TERM_INT' + ], gridinfo.tile_type + + return int_columns + + +def pair_int_tiles(grid, int_tiles): + tiles_left = set(int_tiles) + + while tiles_left: + tile_name = tiles_left.pop() + + gridinfo = grid.gridinfo_at_tilename(tile_name) + loc = grid.loc_of_tilename(tile_name) + + assert gridinfo.tile_type in INT_TILE_TYPES + + if gridinfo.tile_type == 'INT_L': + other_int_tile = 'INT_R' + other_loc = (loc.grid_x + 1, loc.grid_y) + else: + other_int_tile = 'INT_L' + other_loc = (loc.grid_x - 1, loc.grid_y) + + paired_tile_name = grid.tilename_at_loc(other_loc) + paired_gridinfo = grid.gridinfo_at_tilename(paired_tile_name) + assert paired_gridinfo.tile_type == other_int_tile, paired_gridinfo.tile_type + + tiles_left.remove(paired_tile_name) + + yield sorted([tile_name, paired_tile_name]) + + +def is_orphan_int_row(grid, int_l, int_r): + """ Returns true if given INT pair have no adjcent sites. """ + + loc = grid.loc_of_tilename(int_l) + + if grid.gridinfo_at_loc( + (loc.grid_x - 1, loc.grid_y)).tile_type != 'INT_INTERFACE_L': + return False + + if grid.gridinfo_at_loc( + (loc.grid_x - 2, loc.grid_y)).tile_type != 'VFRAME': + return False + + loc = grid.loc_of_tilename(int_r) + + if grid.gridinfo_at_loc( + (loc.grid_x + 1, loc.grid_y)).tile_type != 'INT_INTERFACE_R': + return False + + if grid.gridinfo_at_loc( + (loc.grid_x + 2, + loc.grid_y)).tile_type not in ['CLK_FEED', 'CLK_BUFG_REBUF', 'NULL']: + return False + + return True + + +def gen_orphan_ints(grid): + int_columns = build_int_columns(grid) + + for int_l_column, int_r_column in sorted(pair_int_tiles( + grid, int_columns.keys())): + found_site = False + for int_l, int_r in zip(int_columns[int_l_column], + int_columns[int_r_column]): + if not is_orphan_int_row(grid, int_l, int_r): + found_site = True + break + + if not found_site: + yield int_columns[int_l_column], int_columns[int_r_column] + + +def write_params(params): + pinstr = 'tile,val\n' + for tile, (val) in sorted(params.items()): + pinstr += '%s,%s\n' % (tile, val) + open('params.csv', 'w').write(pinstr) + + +def build_cross_int(params, grid, int_l, int_r): + """ Toggles INT_R.ER1BEG1.EE4END0 """ + + loc = grid.loc_of_tilename(int_r) + + origin_tile = grid.tilename_at_loc((loc.grid_x - 4, loc.grid_y)) + origin_gridinfo = grid.gridinfo_at_tilename(origin_tile) + assert origin_gridinfo.tile_type == 'CLBLL_R' + origin_site = sorted(origin_gridinfo.sites.keys())[random.randint(0, 1)] + + dest_tile = grid.tilename_at_loc((loc.grid_x + 4, loc.grid_y)) + dest_gridinfo = grid.gridinfo_at_tilename(dest_tile) + assert dest_gridinfo.tile_type == 'CLBLL_L' + dest_site = sorted(dest_gridinfo.sites.keys())[0] + + dest2_tile = grid.tilename_at_loc((loc.grid_x + 4, loc.grid_y + 1)) + dest2_gridinfo = grid.gridinfo_at_tilename(dest2_tile) + assert dest2_gridinfo.tile_type == 'CLBLL_L', dest2_gridinfo.tile_type + dest2_site = sorted(dest2_gridinfo.sites.keys())[1] + + if random.randint(0, 1): + dest_wire = 'origin_wire_{origin_site}'.format(origin_site=origin_site) + else: + dest_wire = '1' + + if random.randint(0, 1): + dest_wire2 = 'origin_wire_{origin_site}'.format( + origin_site=origin_site) + else: + dest_wire2 = '1' + + if random.randint(0, 1): + dest_wire3 = 'origin_wire_{origin_site}'.format( + origin_site=origin_site) + else: + dest_wire3 = '1' + + if random.randint(0, 1): + dest_wire4 = 'origin_wire_{origin_site}'.format( + origin_site=origin_site) + else: + dest_wire4 = '1' + + # origin_site.AQ -> dest_tile.D6 enables INT_R.ER1BEG1.EE4END0 + print( + """ + // Force origin FF into A position with MUXF7_L and MUXF8 + wire origin_wire_{origin_site}; + + wire f7_to_lo_{origin_site}; + wire lut_to_f7_{origin_site}; + (* KEEP, DONT_TOUCH, LOC = "{origin_site}" *) + LUT6_L #( + .INIT(0) + ) lut_rom_{origin_site} ( + .I0(1), + .I1(origin_wire_{origin_site}), + .I2(0), + .I3(1), + .I4(1), + .I5(1), + .LO(lut_to_f7_{origin_site}) + ); + (* KEEP, DONT_TOUCH, LOC = "{origin_site}" *) + MUXF7_D f7_{origin_site} ( + .I0(lut_to_f7_{origin_site}), + .LO(f7_to_lo_{origin_site}), + .O(origin_wire_{origin_site}) + ); + (* KEEP, DONT_TOUCH, LOC = "{origin_site}" *) + MUXF8 f8_{origin_site} ( + .I1(f7_to_lo_{origin_site}) + ); + + wire dest_wire_{dest_site}; + wire dest_wire2_{dest_site}; + + wire d_lut_to_f7_{dest_site}, f7_to_f8_{dest_site}; + // Force destination LUT into D position with MUXF7_L and MUXF8 + (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) + LUT6_L #( + .INIT(0) + ) d_lut_rom_{dest_site} ( + .I0(1), + .I1(1), + .I2(0), + .I3(1), + .I4(1), + .I5(dest_wire_{dest_site}), + .LO(d_lut_to_f7_{dest_site}) + ); + + wire c_lut_to_f7_{dest_site}; + // Force destination LUT into C position with MUXF7_L and MUXF8 + (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) + LUT6_L #( + .INIT(0) + ) c_lut_rom_{dest_site} ( + .I0(1), + .I1(1), + .I2(0), + .I3(1), + .I4(1), + .I5(dest_wire2_{dest_site}), + .LO(c_lut_to_f7_{dest_site}) + ); + (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) + MUXF7_L f7_{dest_site} ( + .I0(d_lut_to_f7_{dest_site}), + .I1(c_lut_to_f7_{dest_site}), + .LO(f7_to_f8_{dest_site}) + ); + (* KEEP, DONT_TOUCH, LOC = "{dest_site}" *) + MUXF8 f8_{dest_site} ( + .I0(f7_to_f8_{dest_site}) + ); + + assign dest_wire_{dest_site} = {dest_wire}; + assign dest_wire2_{dest_site} = {dest_wire2}; + + wire dest_wire3_{dest_site2}; + wire dest_wire4_{dest_site2}; + wire lut_to_f7_{dest_site2}, f7_to_f8_{dest_site2}; + // Force destination LUT into D position with MUXF7_L and MUXF8 + (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) + LUT6_L #( + .INIT(0) + ) d_lut_rom_{dest_site2} ( + .I0(dest_wire3_{dest_site2}), + .I1(1), + .I2(0), + .I3(1), + .I4(1), + .I5(), + .LO(lut_to_f7_{dest_site2}) + ); + + // Force destination LUT into C position with MUXF7_L and MUXF8 + wire c_lut_to_f7_{dest_site2}; + (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) + LUT6_L #( + .INIT(0) + ) c_lut_rom_{dest_site2} ( + .I0(dest_wire4_{dest_site2}), + .I1(1), + .I2(0), + .I3(1), + .I4(1), + .I5(1), + .LO(c_lut_to_f7_{dest_site2}) + ); + (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) + MUXF7_L f7_{dest_site2} ( + .I0(lut_to_f7_{dest_site2}), + .I1(c_lut_to_f7_{dest_site2}), + .LO(f7_to_f8_{dest_site2}) + ); + (* KEEP, DONT_TOUCH, LOC = "{dest_site2}" *) + MUXF8 f8_{dest_site2} ( + .I0(f7_to_f8_{dest_site2}) + ); + + assign dest_wire3_{dest_site2} = {dest_wire3}; + assign dest_wire4_{dest_site2} = {dest_wire4}; + """.format( + dest_site=dest_site, + dest_site2=dest2_site, + origin_site=origin_site, + dest_wire=dest_wire, + dest_wire2=dest_wire2, + dest_wire3=dest_wire3, + dest_wire4=dest_wire4, + )) + + +def run(): + print(''' +module top(); + ''') + + int_tiles = [] + + db = Database(util.get_db_root()) + grid = db.grid() + params = {} + for int_l_column, int_r_column in gen_orphan_ints(grid): + for int_l, int_r in zip(int_l_column[1:6:2], int_r_column[1:6:2]): + build_cross_int(params, grid, int_l, int_r) + int_tiles.append(int_l) + + print("endmodule") + with open('top.txt', 'w') as f: + for tile in int_tiles: + print(tile, file=f) + + +if __name__ == '__main__': + run()