diff --git a/fuzzers/041-clk-hrow-pips/Makefile b/fuzzers/041-clk-hrow-pips/Makefile index 5a370e1b..8612c58a 100644 --- a/fuzzers/041-clk-hrow-pips/Makefile +++ b/fuzzers/041-clk-hrow-pips/Makefile @@ -9,7 +9,7 @@ N = 50 # These PIPs all appear to be either a 2 bit solutions. SEGMATCH_FLAGS=-c 2 -SPECIMENS_DEPS=build/cmt_regions.csv +SPECIMENS_DEPS=build/dump.ok A_PIPLIST=clk_hrow_bot_r.txt include ../pip_loop.mk @@ -37,9 +37,18 @@ database: build/segbits_clk_hrow_bot_r.rdb build/segbits_clk_hrow_top_r.rdb XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} clk_hrow_bot_r build/segbits_clk_hrow_bot_r.db XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} clk_hrow_top_r build/segbits_clk_hrow_top_r.db -build/cmt_regions.csv: output_cmt.tcl +ifeq (${XRAY_DATABASE}, zynq7) +build/dump.ok: output_cmt.tcl output_pss_clocks.tcl mkdir -p build cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl + cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_pss_clocks.tcl + touch build/dump.ok +else +build/dump.ok: output_cmt.tcl + mkdir -p build + cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl + touch build/dump.ok +endif generate: $(SPECIMENS_OK) diff --git a/fuzzers/041-clk-hrow-pips/generate.tcl b/fuzzers/041-clk-hrow-pips/generate.tcl index 5f9277e1..21c4ffb9 100644 --- a/fuzzers/041-clk-hrow-pips/generate.tcl +++ b/fuzzers/041-clk-hrow-pips/generate.tcl @@ -246,9 +246,17 @@ proc run {} { set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets] place_design - route_design + + puts "Routing design #1" + route_design -directive Quick + write_checkpoint -force design_initially_routed.dcp + + puts "Routing TODOs" route_todo - route_design + write_checkpoint -force design_todo_routed.dcp + + puts "Routing design #2" + route_design -directive Quick write_checkpoint -force design.dcp write_bitstream -force design.bit diff --git a/fuzzers/041-clk-hrow-pips/output_cmt.tcl b/fuzzers/041-clk-hrow-pips/output_cmt.tcl index 06aba163..070e5884 100644 --- a/fuzzers/041-clk-hrow-pips/output_cmt.tcl +++ b/fuzzers/041-clk-hrow-pips/output_cmt.tcl @@ -3,7 +3,7 @@ set_property design_mode PinPlanning [current_fileset] open_io_design -name io_1 set fp [open "cmt_regions.csv" "w"] -foreach site_type {MMCME2_ADV PLLE2_ADV BUFHCE BUFR} { +foreach site_type {MMCME2_ADV PLLE2_ADV BUFHCE BUFR PS7} { foreach site [get_sites -filter "SITE_TYPE == $site_type"] { puts $fp "$site,[get_property CLOCK_REGION $site]" } diff --git a/fuzzers/041-clk-hrow-pips/output_pss_clocks.tcl b/fuzzers/041-clk-hrow-pips/output_pss_clocks.tcl new file mode 100644 index 00000000..22e26e72 --- /dev/null +++ b/fuzzers/041-clk-hrow-pips/output_pss_clocks.tcl @@ -0,0 +1,23 @@ +create_project -force -part $::env(XRAY_PART) design design +set_property design_mode PinPlanning [current_fileset] +open_io_design -name io_1 + +set fp [open "pss_clocks.csv" "w"] +puts $fp "pin,tile" + +# List all PSS_HCLK wires +set pss_clk_wires [get_wires *PSS_HCLK* -of_objects [get_tiles PSS*]] +foreach wire $pss_clk_wires { + # Get PIPs that mention the wire inside a CLK_HROW tile. + set pips [get_pips CLK_HROW_* -of_objects [get_nodes -of_objects $wire]] + # Get the CLK_HROW tile. + set tile [get_tiles -of_objects [lindex $pips 0]] + + # Get uphill PIP, parse its name to get the PS7 wire name. + set pip [get_pips -uphill -of_objects $wire] + set pin [lindex [split [lindex [split $pip "."] 1] "-"] 0] + + puts $fp "$pin,$tile" +} + +close $fp diff --git a/fuzzers/041-clk-hrow-pips/top.py b/fuzzers/041-clk-hrow-pips/top.py index ed38a7a7..dd991374 100644 --- a/fuzzers/041-clk-hrow-pips/top.py +++ b/fuzzers/041-clk-hrow-pips/top.py @@ -5,14 +5,19 @@ import re random.seed(int(os.getenv("SEED"), 16)) from prjxray import util from prjxray import verilog +from prjxray.grid_types import GridLoc from prjxray.db import Database from prjxray.lut_maker import LutMaker from io import StringIO +import csv +import sys CMT_XY_FUN = util.create_xy_fun(prefix='') BUFGCTRL_XY_FUN = util.create_xy_fun('BUFGCTRL_') BUFHCE_XY_FUN = util.create_xy_fun('BUFHCE_') +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) def gen_sites(desired_site_type): db = Database(util.get_db_root()) @@ -41,6 +46,10 @@ def gen_bufhce_sites(): if sites: yield tile_name, sorted(sites) +def get_cmt_loc(cmt_tile_name): + db = Database(util.get_db_root()) + grid = db.grid() + return grid.loc_of_tilename(cmt_tile_name) def read_site_to_cmt(): """ Yields clock sources and which CMT they route within. """ @@ -50,6 +59,11 @@ def read_site_to_cmt(): site, cmt = l.strip().split(',') yield (site, cmt) +def read_pss_clocks(): + with open(os.path.join(os.getenv('FUZDIR'), 'build', + 'pss_clocks.csv')) as f: + for l in csv.DictReader(f): + yield l class ClockSources(object): """ Class for tracking clock sources. @@ -147,7 +161,7 @@ class ClockSources(object): if src_loc is None: continue if src_loc.grid_y <= loc.grid_y: - bufg_sources.extend(cmt_sources) + bufg_sources.extend(cmt_sources) elif bottom: for src_loc, cmt_sources in self.sources_by_loc.items(): if src_loc is None: @@ -305,18 +319,23 @@ def main(): PLLE2_ADV BUFGCTRL Local INT connect - + PS7 (Zynq) """ print(''' +// SEED={} module top(); - ''') + '''.format(os.getenv('SEED'))) - site_to_cmt = dict(read_site_to_cmt()) is_zynq = os.getenv('XRAY_DATABASE') == 'zynq7' clock_sources = ClockSources() + site_to_cmt = dict(read_site_to_cmt()) + + if is_zynq: + pss_clocks = list(read_pss_clocks()) + # To ensure that all left or right sources are used, sometimes only MMCM/PLL # sources are allowed. The force of ODD/EVEN/BOTH further biases the # clock sources to the left or right column inputs. @@ -427,6 +446,42 @@ module top(); .O(O_{site}) );""".format(site=site)) + if is_zynq: + + clocks = [ + "PSS_FCLKCLK0", + "PSS_FCLKCLK1", + "PSS_FCLKCLK2", + "PSS_FCLKCLK3", + ] + + loc, _, site = next(gen_sites('PS7')) + + print("") + + for wire in clocks: + cmt = site_to_cmt[site] + cmt_tile = [d["tile"] for d in pss_clocks if d["pin"] == wire][0] + cmt_loc = get_cmt_loc(cmt_tile) + + clock_sources.add_clock_source(wire, cmt, cmt_loc) + print(" wire {};".format(wire)) + + print(""" + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + PS7 ps7_{site} ( + .FCLKCLK({{{fclk3}, {fclk2}, {fclk1}, {fclk0}}}) + ); + """.format( + site=site, + fclk0=clocks[0], + fclk1=clocks[1], + fclk2=clocks[2], + fclk3=clocks[3] + )) + + used_pss_clocks = set() + luts = LutMaker() bufhs = StringIO() bufgs = StringIO() @@ -497,6 +552,12 @@ module top(); if random.random() > .05: wire_name = clock_sources.get_random_source(site_to_cmt[site]) + if wire_name is not None and wire_name.startswith("PSS"): + if wire_name not in used_pss_clocks: + used_pss_clocks.add(wire_name) + else: + wire_name = None + if wire_name is None: continue @@ -532,28 +593,6 @@ module top(); break break - if is_zynq: - for loc, _, site in gen_sites('PS7'): - print(""" - (* KEEP, DONT_TOUCH, LOC = "{site}" *) - PS7 ps7_{site} ( - .FCLKCLK({fclk3, fclk2, fclk1, fclk0}), - .TESTPLLCLKOUT({testpllclkout2, testpllclkout1, testpllclkout0}), - .TESTPLLNEWCLK({testpllnewclk2, testpllnewclk1, testpllnewclk0}), - ); - """.format( - site=site, - fclk0=, - fclk1=, - fclk2=, - fclk3=, - testpllclkout2=, - testpllclkout1=, - testpllclkout0=, - testpllnewclk2=, - testpllnewclk1=, - testpllnewclk0=, - )) for l in luts.create_wires_and_luts(): @@ -569,7 +608,9 @@ module top(); if random.randint(0, 1): wire_name = clock_sources.get_bufg_source( loc, tile_type, site, todos, 1, used_only) - if wire_name is not None: + if wire_name is not None and wire_name not in used_pss_clocks: + if wire_name.startswith("PSS"): + used_pss_clocks.add(wire_name) print( """ assign I1_{site} = {wire_name};""".format( @@ -580,7 +621,9 @@ module top(); if random.randint(0, 1): wire_name = clock_sources.get_bufg_source( loc, tile_type, site, todos, 0, used_only) - if wire_name is not None: + if wire_name is not None and wire_name not in used_pss_clocks: + if wire_name.startswith("PSS"): + used_pss_clocks.add(wire_name) print( """ assign I0_{site} = {wire_name};""".format(