Modified fuzzer 041 to solve Zynq PS7 FCLK clocks.

Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
Maciej Kurc 2019-12-11 16:25:45 +01:00
parent 7bd13efdcb
commit 6086e6d6f5
5 changed files with 116 additions and 33 deletions

View File

@ -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)

View File

@ -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

View File

@ -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]"
}

View File

@ -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

View File

@ -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(