mirror of https://github.com/openXC7/prjxray.git
Solve orphan INT columns in Kintex7.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
ebe9a457cd
commit
b04598da26
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
N ?= 16
|
||||
GENERATE_ARGS?="--oneval 1 --design params.csv --dframe 9 --dword 0"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
Loading…
Reference in New Issue