mirror of https://github.com/openXC7/prjxray.git
Enhance 045 to solve FREQ_REF related PIPs
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
parent
1f23cb2d35
commit
f6dd2c1e7c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
Loading…
Reference in New Issue