From f6dd2c1e7c65db0de85a12cbffac52066da34666 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Thu, 23 Apr 2020 16:27:06 +0200 Subject: [PATCH 1/5] Enhance 045 to solve FREQ_REF related PIPs Signed-off-by: Maciej Kurc --- fuzzers/045-hclk-cmt-pips/Makefile | 55 ++++++--------- fuzzers/045-hclk-cmt-pips/generate.py | 5 ++ fuzzers/045-hclk-cmt-pips/generate.tcl | 48 ++++++++++++- fuzzers/045-hclk-cmt-pips/top.py | 97 +++++++++++++++++++++++--- 4 files changed, 160 insertions(+), 45 deletions(-) diff --git a/fuzzers/045-hclk-cmt-pips/Makefile b/fuzzers/045-hclk-cmt-pips/Makefile index 949d0a55..d3ff3eb6 100644 --- a/fuzzers/045-hclk-cmt-pips/Makefile +++ b/fuzzers/045-hclk-cmt-pips/Makefile @@ -3,57 +3,44 @@ PIP_TYPE?=hclk_cmt PIPLIST_TCL=$(FUZDIR)/hclk_cmt_pip_list.tcl TODO_RE=".*" # Skipped pips: -# - FREQ_REF is only used by interconnect clocks, so low likelyhood of usage. -# A BUFR can be used to clock divide if needed # - PHSR PIPs are connected to PHASER sites, which are undocumented, so avoid # for now. -EXCLUDE_RE="(^.*LEAF)|(^.*BUFMR)|(^.*FREQ_REF)|(^.*PHSR)|(^.*CLK_PLL7)|(^.*CLK_MMCM13)" +EXCLUDE_RE="(^.*LEAF)|(^.*BUFMR)|(^.*PHSR)|(^.*CLK_PLL7)|(^.*CLK_MMCM13)" MAKETODO_FLAGS=--sides ",l" --pip-type ${PIP_TYPE} --seg-type ${PIP_TYPE} --re $(TODO_RE) --exclude-re $(EXCLUDE_RE) N = 100 -# These PIPs all appear to be either a 1 bit solutions. -SEGMATCH_FLAGS=-c 2 +# All PIPs seem to have 2 bits. An exception is FREQ_REF which cannot be +# decoupled from the others, hence it will always have 4 bits. +FOUR_BIT_PIPS="FREQ_REF" + SPECIMENS_DEPS=build/cmt_regions.csv A_PIPLIST=hclk_cmt.txt include ../pip_loop.mk -build/segbits_hclk_cmt.rdb: $(SPECIMENS_OK) - ${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_hclk_cmt.rdb \ - $(shell find build -name segdata_hclk_cmt.txt) +.PRECIOUS: build/%.rdb -build/segbits_hclk_cmt.db: build/segbits_hclk_cmt.rdb +build/%.rdb: $(SPECIMENS_OK) + $(XRAY_SEGMATCH) -c 4 -o $@.4 $(shell find build -name $(subst segbits,segdata,$(patsubst %.rdb,%.txt,$(notdir $@)))) + $(XRAY_SEGMATCH) -c 2 -o $@.2 $(shell find build -name $(subst segbits,segdata,$(patsubst %.rdb,%.txt,$(notdir $@)))) + grep ${FOUR_BIT_PIPS} $@.4 > $@ + grep -v ${FOUR_BIT_PIPS} $@.2 >> $@ + +build/%.db: build/%.rdb ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \ - --seg-fn-in build/segbits_hclk_cmt.rdb \ - --seg-fn-out build/segbits_hclk_cmt.db + --seg-fn-in $< \ + --seg-fn-out $@ # Keep a copy to track iter progress - cp build/segbits_hclk_cmt.rdb build/$(ITER)/segbits_hclk_cmt.rdb - - ${XRAY_MASKMERGE} build/mask_hclk_cmt.db \ - $(shell find build -name segdata_hclk_cmt.txt) - -build/segbits_hclk_cmt_l.rdb: $(SPECIMENS_OK) - ${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_hclk_cmt_l.rdb \ - $(shell find build -name segdata_hclk_cmt_l.txt) - -build/segbits_hclk_cmt_l.db: build/segbits_hclk_cmt_l.rdb - ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \ - --seg-fn-in build/segbits_hclk_cmt_l.rdb \ - --seg-fn-out build/segbits_hclk_cmt_l.db - - # Keep a copy to track iter progress - cp build/segbits_hclk_cmt_l.rdb build/$(ITER)/segbits_hclk_cmt_l.rdb - - - ${XRAY_MASKMERGE} build/mask_hclk_cmt_l.db \ - $(shell find build -name segdata_hclk_cmt_l.txt) + cp $< build/$(ITER)/$(notdir $<) + ${XRAY_MASKMERGE} $(subst segbits,mask,$@) \ + $(shell find build -name $(subst segbits,segdata,$(patsubst %.db,%.txt,$(notdir $@)))) database: build/segbits_hclk_cmt.db build/segbits_hclk_cmt_l.db # Clobber existing .db to eliminate potential conflicts - cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE} + cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits_hclk_cmt*.db build/database/${XRAY_DATABASE} XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} hclk_cmt build/segbits_hclk_cmt.db XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} hclk_cmt_l build/segbits_hclk_cmt_l.db @@ -62,9 +49,9 @@ build/cmt_regions.csv: output_cmt.tcl cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl pushdb: database - ${XRAY_MERGEDB} hclk_cmt build/segbits_hclk_cmt.db + ${XRAY_MERGEDB} hclk_cmt build/database/${XRAY_DATABASE}/segbits_hclk_cmt.db ${XRAY_MERGEDB} mask_hclk_cmt build/mask_hclk_cmt.db - ${XRAY_MERGEDB} hclk_cmt_l build/segbits_hclk_cmt_l.db + ${XRAY_MERGEDB} hclk_cmt_l build/database/${XRAY_DATABASE}/segbits_hclk_cmt_l.db ${XRAY_MERGEDB} mask_hclk_cmt_l build/mask_hclk_cmt_l.db .PHONY: database pushdb diff --git a/fuzzers/045-hclk-cmt-pips/generate.py b/fuzzers/045-hclk-cmt-pips/generate.py index 4c964b3a..dc96f2af 100644 --- a/fuzzers/045-hclk-cmt-pips/generate.py +++ b/fuzzers/045-hclk-cmt-pips/generate.py @@ -120,6 +120,11 @@ def main(): segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0) for port in tile_ports[tile_type]: + + # These ones do not have any outgoing connections from the tile. + if "FREQ_REF" in port: + continue + if port in tiledata[tile]["dsts"] or port in tiledata[tile]["srcs"]: segmk.add_tile_tag(tile, "{}_USED".format(port), 1) else: diff --git a/fuzzers/045-hclk-cmt-pips/generate.tcl b/fuzzers/045-hclk-cmt-pips/generate.tcl index fce56c46..a37a3120 100644 --- a/fuzzers/045-hclk-cmt-pips/generate.tcl +++ b/fuzzers/045-hclk-cmt-pips/generate.tcl @@ -197,6 +197,47 @@ proc route_todo {} { } } +proc make_manual_routes {filename} { + puts "MANROUTE: Loading routes from $filename" + + set fp [open $filename r] + foreach line [split [read $fp] "\n"] { + if {$line eq ""} { + continue + } + + puts "MANROUTE: Line: $line" + + # Parse the line + set fields [split $line " "] + set net_name [lindex $fields 0] + set wire_name [lindex $fields 1] + + # Check if that net exist + if {[get_nets $net_name] eq ""} { + puts "MANROUTE: net $net_name does not exist" + continue + } + + # Ripup it + route_design -unroute -nets [get_nets $net_name] + + # Make the route + set status [route_via $net_name [list $wire_name] 0] + + # Failure, skip manual routing of this net + if { $status != 1 } { + puts "MANROUTE: Manual routing failed!" + set net [get_nets $net_name] + set_property -quiet FIXED_ROUTE "" $net + set_property IS_ROUTE_FIXED 0 $net + continue + } + + puts "MANROUTE: Success!" + } +} + proc run {} { create_project -force -part $::env(XRAY_PART) design design read_verilog top.v @@ -220,10 +261,11 @@ proc run {} { set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets] - place_design - route_design + place_design -directive Quick + route_design -directive Quick route_todo - route_design + make_manual_routes routes.txt + route_design -directive Quick -preserve write_checkpoint -force design.dcp write_bitstream -force design.bit diff --git a/fuzzers/045-hclk-cmt-pips/top.py b/fuzzers/045-hclk-cmt-pips/top.py index e765f3e5..a60d26ec 100644 --- a/fuzzers/045-hclk-cmt-pips/top.py +++ b/fuzzers/045-hclk-cmt-pips/top.py @@ -2,6 +2,7 @@ import os import random random.seed(int(os.getenv("SEED"), 16)) +import re from prjxray import util from prjxray.lut_maker import LutMaker from prjxray.db import Database @@ -15,8 +16,45 @@ def read_site_to_cmt(): with open(os.path.join(os.getenv('FUZDIR'), 'build', 'cmt_regions.csv')) as f: for l in f: - site, cmt, _ = l.strip().split(',') - yield (site, cmt) + site, cmt, tile = l.strip().split(',') + yield (tile, site, cmt) + +def make_ccio_route_options(): + + # Read the PIP lists + piplist_path = os.path.join(os.getenv("FUZDIR"), "..", "piplist", "build", "hclk_cmt") + + pips = [] + for fname in os.listdir(piplist_path): + if not fname.endswith(".txt"): + continue + + fullname = os.path.join(piplist_path, fname) + with open(fullname, "r") as fp: + pips += [l.strip() for l in fp.readlines()] + + # Get PIPs that mention FREQ_REFn wires. These are the ones that we want + # force routing through. + pips = [p for p in pips if "FREQ_REF" in p] + + # Sort by tile type + options = {} + for pip in pips: + tile, dst, src = pip.split(".") + + for a, b in ((src, dst), (dst, src)): + match = re.match(r".*FREQ_REF([0-3]).*", a) + if match is not None: + n = int(match.group(1)) + + if tile not in options: + options[tile] = {} + if n not in options[tile]: + options[tile][n] = set() + + options[tile][n].add(b) + + return options class ClockSources(object): @@ -121,6 +159,14 @@ def get_paired_iobs(db, grid, tile_name): idx += 1 + # A map of y deltas to CCIO wire indices + CCIO_INDEX = { + -1: 0, + -3: 1, + +2: 3, + +4: 2 + } + # Move from HCLK_IOI column to IOB column idx += 1 @@ -134,7 +180,7 @@ def get_paired_iobs(db, grid, tile_name): for site, site_type in gridinfo.sites.items(): if site_type in ['IOB33M', 'IOB18M']: - yield tile_name, site, site_type[-3:-1] + yield tile_name, site, site_type[-3:-1], CCIO_INDEX[dy] def check_allowed(mmcm_pll_dir, cmt): @@ -176,7 +222,12 @@ def main(): clock_sources = ClockSources() adv_clock_sources = ClockSources() - site_to_cmt = dict(read_site_to_cmt()) + + tile_site_cmt = list(read_site_to_cmt()) + site_to_cmt = {tsc[1] : tsc[2] for tsc in tile_site_cmt} + cmt_to_hclk = {tsc[2] : tsc[0] for tsc in tile_site_cmt if tsc[0].startswith("HCLK_CMT_")} + + ccio_route_options = make_ccio_route_options() db = Database(util.get_db_root(), util.get_part()) grid = db.grid() @@ -208,11 +259,13 @@ def main(): have_iob_clocks = random.random() > .1 + iob_to_hclk = {} iob_clks = {} for tile_name in sorted(hclk_cmt_tiles): - for _, site, volt in get_paired_iobs(db, grid, tile_name): + for _, site, volt, ccio in get_paired_iobs(db, grid, tile_name): iob_clock = 'clock_IBUF_{site}'.format(site=site) + iob_to_hclk[site] = (tile_name, ccio) cmt = site_to_cmt[site] if cmt not in iob_clks: @@ -374,7 +427,7 @@ module top({inputs}); wire_name = clock_sources.get_random_source( site_to_cmt[site], uses_left_right_routing=True, - no_repeats=mmcm_pll_only) + no_repeats=mmcm_pll_only or have_iob_clocks) if wire_name is not None and 'BUFHCE' in wire_name: # Looping a BUFHCE to a BUFHCE requires using a hclk in the @@ -415,10 +468,32 @@ module top({inputs}); .O(O_{site}) );""".format(I=random.choice(iob_clks[site_to_cmt[site]]), site=site)) + route_file = open("routes.txt", "w") + + def fix_ccio_route(net): + + # Get the IOB site name + match = re.match(r".*_IBUF_(.*)", net) + assert match is not None, net + iob_site = match.group(1) + + # Get associated HCLK_CMT tile and CCIO wire index + hclk_tile_name, ccio = iob_to_hclk[iob_site] + + # Get HCLK_CMT tile type + hclk_tile = hclk_tile_name.rsplit("_", maxsplit=1)[0] + + # Pick a random route option + opts = list(ccio_route_options[hclk_tile][ccio]) + route = random.choice(opts) + route = "{}/{}".format(hclk_tile_name, route) + route_file.write("{} {}\n".format(net, route)) + + for _, site in gen_sites('PLLE2_ADV'): for cin in ('cin1', 'cin2', 'clkfbin'): if random.random() > .2: - src = adv_clock_sources.get_random_source(site_to_cmt[site]) + src = adv_clock_sources.get_random_source(site_to_cmt[site], no_repeats=have_iob_clocks) src_cmt = adv_clock_sources.source_to_cmt[src] @@ -430,6 +505,9 @@ module top({inputs}); if src is None: continue + if "IBUF" in src: + fix_ccio_route(src) + print( """ assign {cin}_{site} = {csrc}; @@ -438,7 +516,7 @@ module top({inputs}); for _, site in gen_sites('MMCME2_ADV'): for cin in ('cin1', 'cin2', 'clkfbin'): if random.random() > .2: - src = adv_clock_sources.get_random_source(site_to_cmt[site]) + src = adv_clock_sources.get_random_source(site_to_cmt[site], no_repeats=have_iob_clocks) src_cmt = adv_clock_sources.source_to_cmt[src] if 'IBUF' not in src and 'BUFR' not in src: @@ -449,6 +527,9 @@ module top({inputs}); if src is None: continue + if "IBUF" in src: + fix_ccio_route(src) + print( """ assign {cin}_{site} = {csrc}; From dedbfaa301445fe604bf8c0757c34f52465fe242 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Thu, 23 Apr 2020 19:26:08 +0200 Subject: [PATCH 2/5] Code formatting. Signed-off-by: Maciej Kurc --- fuzzers/045-hclk-cmt-pips/Makefile | 2 +- fuzzers/045-hclk-cmt-pips/top.py | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/fuzzers/045-hclk-cmt-pips/Makefile b/fuzzers/045-hclk-cmt-pips/Makefile index d3ff3eb6..b817a287 100644 --- a/fuzzers/045-hclk-cmt-pips/Makefile +++ b/fuzzers/045-hclk-cmt-pips/Makefile @@ -10,7 +10,7 @@ EXCLUDE_RE="(^.*LEAF)|(^.*BUFMR)|(^.*PHSR)|(^.*CLK_PLL7)|(^.*CLK_MMCM13)" MAKETODO_FLAGS=--sides ",l" --pip-type ${PIP_TYPE} --seg-type ${PIP_TYPE} --re $(TODO_RE) --exclude-re $(EXCLUDE_RE) N = 100 -# All PIPs seem to have 2 bits. An exception is FREQ_REF which cannot be +# All PIPs seem to have 2 bits. An exception is FREQ_REF which cannot be # decoupled from the others, hence it will always have 4 bits. FOUR_BIT_PIPS="FREQ_REF" diff --git a/fuzzers/045-hclk-cmt-pips/top.py b/fuzzers/045-hclk-cmt-pips/top.py index a60d26ec..5bd35a6a 100644 --- a/fuzzers/045-hclk-cmt-pips/top.py +++ b/fuzzers/045-hclk-cmt-pips/top.py @@ -19,10 +19,12 @@ def read_site_to_cmt(): site, cmt, tile = l.strip().split(',') yield (tile, site, cmt) + def make_ccio_route_options(): # Read the PIP lists - piplist_path = os.path.join(os.getenv("FUZDIR"), "..", "piplist", "build", "hclk_cmt") + piplist_path = os.path.join( + os.getenv("FUZDIR"), "..", "piplist", "build", "hclk_cmt") pips = [] for fname in os.listdir(piplist_path): @@ -160,12 +162,7 @@ def get_paired_iobs(db, grid, tile_name): idx += 1 # A map of y deltas to CCIO wire indices - CCIO_INDEX = { - -1: 0, - -3: 1, - +2: 3, - +4: 2 - } + CCIO_INDEX = {-1: 0, -3: 1, +2: 3, +4: 2} # Move from HCLK_IOI column to IOB column idx += 1 @@ -224,8 +221,12 @@ def main(): adv_clock_sources = ClockSources() tile_site_cmt = list(read_site_to_cmt()) - site_to_cmt = {tsc[1] : tsc[2] for tsc in tile_site_cmt} - cmt_to_hclk = {tsc[2] : tsc[0] for tsc in tile_site_cmt if tsc[0].startswith("HCLK_CMT_")} + site_to_cmt = {tsc[1]: tsc[2] for tsc in tile_site_cmt} + cmt_to_hclk = { + tsc[2]: tsc[0] + for tsc in tile_site_cmt + if tsc[0].startswith("HCLK_CMT_") + } ccio_route_options = make_ccio_route_options() @@ -489,11 +490,11 @@ module top({inputs}); route = "{}/{}".format(hclk_tile_name, route) route_file.write("{} {}\n".format(net, route)) - for _, site in gen_sites('PLLE2_ADV'): for cin in ('cin1', 'cin2', 'clkfbin'): if random.random() > .2: - src = adv_clock_sources.get_random_source(site_to_cmt[site], no_repeats=have_iob_clocks) + src = adv_clock_sources.get_random_source( + site_to_cmt[site], no_repeats=have_iob_clocks) src_cmt = adv_clock_sources.source_to_cmt[src] @@ -516,7 +517,8 @@ module top({inputs}); for _, site in gen_sites('MMCME2_ADV'): for cin in ('cin1', 'cin2', 'clkfbin'): if random.random() > .2: - src = adv_clock_sources.get_random_source(site_to_cmt[site], no_repeats=have_iob_clocks) + src = adv_clock_sources.get_random_source( + site_to_cmt[site], no_repeats=have_iob_clocks) src_cmt = adv_clock_sources.source_to_cmt[src] if 'IBUF' not in src and 'BUFR' not in src: From f28684c636d80f9e905fa85babe5e199664d6184 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Fri, 24 Apr 2020 09:31:50 +0200 Subject: [PATCH 3/5] Fixed a bug in makefile Signed-off-by: Maciej Kurc --- fuzzers/045-hclk-cmt-pips/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzers/045-hclk-cmt-pips/Makefile b/fuzzers/045-hclk-cmt-pips/Makefile index b817a287..3898d7db 100644 --- a/fuzzers/045-hclk-cmt-pips/Makefile +++ b/fuzzers/045-hclk-cmt-pips/Makefile @@ -40,7 +40,7 @@ build/%.db: build/%.rdb database: build/segbits_hclk_cmt.db build/segbits_hclk_cmt_l.db # Clobber existing .db to eliminate potential conflicts - cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits_hclk_cmt*.db build/database/${XRAY_DATABASE} + cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits_hclk_cmt*.db build/database/${XRAY_DATABASE} || true XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} hclk_cmt build/segbits_hclk_cmt.db XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} hclk_cmt_l build/segbits_hclk_cmt_l.db From 08e8d1b118bc8f276991141938daac4c174f60a1 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Mon, 27 Apr 2020 15:48:30 +0200 Subject: [PATCH 4/5] Fixed solution of CCIOn_USED bits. Signed-off-by: Maciej Kurc --- fuzzers/045-hclk-cmt-pips/generate.py | 8 ++++ fuzzers/045-hclk-cmt-pips/generate.tcl | 12 ++++-- fuzzers/045-hclk-cmt-pips/top.py | 57 +++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/fuzzers/045-hclk-cmt-pips/generate.py b/fuzzers/045-hclk-cmt-pips/generate.py index dc96f2af..ad6e992d 100644 --- a/fuzzers/045-hclk-cmt-pips/generate.py +++ b/fuzzers/045-hclk-cmt-pips/generate.py @@ -125,6 +125,14 @@ def main(): if "FREQ_REF" in port: continue + # It seems that CCIOn_USED is not enabled when a net goes through + # FREQ_REFn. Do not emit this tag if this happens. + if "CCIO" in port: + n = int(port[-1]) + dst = "HCLK_CMT_MUX_OUT_FREQ_REF{}".format(n) + if dst in tiledata[tile]["dsts"]: + continue + if port in tiledata[tile]["dsts"] or port in tiledata[tile]["srcs"]: segmk.add_tile_tag(tile, "{}_USED".format(port), 1) else: diff --git a/fuzzers/045-hclk-cmt-pips/generate.tcl b/fuzzers/045-hclk-cmt-pips/generate.tcl index a37a3120..bf158c07 100644 --- a/fuzzers/045-hclk-cmt-pips/generate.tcl +++ b/fuzzers/045-hclk-cmt-pips/generate.tcl @@ -219,16 +219,20 @@ proc make_manual_routes {filename} { continue } - # Ripup it - route_design -unroute -nets [get_nets $net_name] + set net [get_nets $net_name] + + # Rip it up + set_property -quiet FIXED_ROUTE "" $net + set_property IS_ROUTE_FIXED 0 $net + route_design -unroute -nets $net # Make the route - set status [route_via $net_name [list $wire_name] 0] + set nodes [get_nodes -of_objects [get_wires $wire_name]] + set status [route_via $net_name [list $nodes] 0] # Failure, skip manual routing of this net if { $status != 1 } { puts "MANROUTE: Manual routing failed!" - set net [get_nets $net_name] set_property -quiet FIXED_ROUTE "" $net set_property IS_ROUTE_FIXED 0 $net continue diff --git a/fuzzers/045-hclk-cmt-pips/top.py b/fuzzers/045-hclk-cmt-pips/top.py index 5bd35a6a..35721444 100644 --- a/fuzzers/045-hclk-cmt-pips/top.py +++ b/fuzzers/045-hclk-cmt-pips/top.py @@ -84,6 +84,21 @@ class ClockSources(object): self.sources[cmt].append(source) self.source_to_cmt[source] = cmt + def remove_clock_source(self, source, cmt="ANY"): + """ + Removes a clock source from the available clock sources list + """ + if source in self.source_to_cmt: + del self.source_to_cmt[source] + + if cmt == "ANY": + for sources in self.sources.values(): + if source in sources: + sources.remove(source) + else: + if source in self.sources[cmt]: + self.sources[cmt].remove(source) + def get_random_source( self, cmt, uses_left_right_routing=False, no_repeats=False): """ Get a random source that is routable to the specific CMT. @@ -423,12 +438,16 @@ module top({inputs}); hclks_used_by_cmt[src_cmt].add(src) return src + # Track used IOB sources + used_iob_clks = set() + if random.random() > .10: for tile_name, site in gen_sites('BUFHCE'): + wire_name = clock_sources.get_random_source( site_to_cmt[site], uses_left_right_routing=True, - no_repeats=mmcm_pll_only or have_iob_clocks) + no_repeats=mmcm_pll_only) if wire_name is not None and 'BUFHCE' in wire_name: # Looping a BUFHCE to a BUFHCE requires using a hclk in the @@ -440,6 +459,11 @@ module top({inputs}); if wire_name is None: continue + if "IBUF" in wire_name: + used_iob_clks.add(wire_name) + clock_sources.remove_clock_source(wire_name) + adv_clock_sources.remove_clock_source(wire_name) + print( """ assign I_{site} = {wire_name};""".format( @@ -458,8 +482,25 @@ module top({inputs}); print(bufhs.getvalue()) for _, site in gen_sites('BUFR'): + + # Do not use BUFR always + if random.random() < 0.50: + continue + + available_srcs = set(iob_clks[site_to_cmt[site]]) - used_iob_clks + if len(available_srcs) == 0: + continue + + src = random.choice(list(available_srcs)) + + if src != "": + used_iob_clks.add(src) + clock_sources.remove_clock_source(src) + adv_clock_sources.remove_clock_source(src) + adv_clock_sources.add_clock_source( 'O_{site}'.format(site=site), site_to_cmt[site]) + print( """ wire O_{site}; @@ -467,7 +508,7 @@ module top({inputs}); BUFR bufr_{site} ( .I({I}), .O(O_{site}) - );""".format(I=random.choice(iob_clks[site_to_cmt[site]]), site=site)) + );""".format(I=src, site=site)) route_file = open("routes.txt", "w") @@ -493,8 +534,8 @@ module top({inputs}); for _, site in gen_sites('PLLE2_ADV'): for cin in ('cin1', 'cin2', 'clkfbin'): if random.random() > .2: - src = adv_clock_sources.get_random_source( - site_to_cmt[site], no_repeats=have_iob_clocks) + + src = adv_clock_sources.get_random_source(site_to_cmt[site]) src_cmt = adv_clock_sources.source_to_cmt[src] @@ -507,6 +548,8 @@ module top({inputs}); continue if "IBUF" in src: + clock_sources.remove_clock_source(src) + adv_clock_sources.remove_clock_source(src) fix_ccio_route(src) print( @@ -517,8 +560,8 @@ module top({inputs}); for _, site in gen_sites('MMCME2_ADV'): for cin in ('cin1', 'cin2', 'clkfbin'): if random.random() > .2: - src = adv_clock_sources.get_random_source( - site_to_cmt[site], no_repeats=have_iob_clocks) + + src = adv_clock_sources.get_random_source(site_to_cmt[site]) src_cmt = adv_clock_sources.source_to_cmt[src] if 'IBUF' not in src and 'BUFR' not in src: @@ -530,6 +573,8 @@ module top({inputs}); continue if "IBUF" in src: + clock_sources.remove_clock_source(src) + adv_clock_sources.remove_clock_source(src) fix_ccio_route(src) print( From 317f8691f7d6248f71d03843f8748bc16c0f5421 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Mon, 4 May 2020 09:19:10 +0200 Subject: [PATCH 5/5] Disabled emission of HCLK_CMT_MUX_CLKINT_n_USED tags. Signed-off-by: Maciej Kurc --- fuzzers/045-hclk-cmt-pips/generate.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fuzzers/045-hclk-cmt-pips/generate.py b/fuzzers/045-hclk-cmt-pips/generate.py index ad6e992d..79b08435 100644 --- a/fuzzers/045-hclk-cmt-pips/generate.py +++ b/fuzzers/045-hclk-cmt-pips/generate.py @@ -125,6 +125,11 @@ def main(): if "FREQ_REF" in port: continue + # There seems to be no special bits related to use of + # HCLK_CMT_MUX_CLKINT_n wires. + if "HCLK_CMT_MUX_CLKINT" in port: + continue + # It seems that CCIOn_USED is not enabled when a net goes through # FREQ_REFn. Do not emit this tag if this happens. if "CCIO" in port: