Merge pull request #1174 from antmicro/zynq_ps7_clocks

Zynq PS7 clocks
This commit is contained in:
litghost 2019-12-12 13:05:29 -08:00 committed by GitHub
commit cc9e00da8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 137 additions and 14 deletions

View File

@ -39,12 +39,14 @@ DB_SIMPLE=\
$(addsuffix _r, $(DB_SIMPLE_LR) $(DB_SIMPLE_R)) \
segbits_cmt_top_l_upper_t \
segbits_cmt_top_r_upper_t \
segbits_lioi3 \
segbits_rioi3 \
segbits_liob33 \
segbits_riob33 \
segbits_hclk_ioi3 \
ifneq (${XRAY_DATABASE}, zynq7)
DB_SIMPLE += segbits_lioi3 segbits_liob33
endif
BLOCK_RAM_EXTRA_FOR=\
mask_bram \
segbits_bram

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

@ -28,11 +28,6 @@ proc print_tile_pips {tile_type filename} {
continue
}
# TODO: Support CLK sources from PS7 hardblock
if [string match *PSS_HCLK* $src_node] {
continue
}
if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1} {
set pip_string "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
if ![dict exists $pips $pip_string] {

View File

@ -246,9 +246,9 @@ proc run {} {
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
place_design
route_design
route_design -directive Quick
route_todo
route_design
route_design -directive Quick
write_checkpoint -force design.dcp
write_bitstream -force design.bit

View File

@ -0,0 +1,41 @@
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,wire,tile,clock_regions"
# 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. Take the first one.
set pips [get_pips CLK_HROW_* -of_objects [get_nodes -of_objects $wire]]
set pip [lindex $pips 0]
# Get the CLK_HROW tile.
set tile [get_tiles -of_objects $pip]
# Get the name of the input wire of the CLK_HROW tile. This is different
# than the name of the PSS clock wire. Do it by parsing the PIP name
set cmt_wire [lindex [split [lindex [split $pip "-"] 0] "."] 1]
# Get clock regions of the tile. CLK_HROW tiles span two regions.
set regions [dict create]
foreach site [get_sites -of_objects $tile] {
set region [get_property CLOCK_REGION $site]
dict incr regions $region
}
set regions [dict keys $regions]
# Get uphill PIP, parse its name to get the PS7 wire name. This will be
# actually the wire of the PSS tile but the important part of the name
# is the same.
set pip [get_pips -uphill -of_objects $wire]
set pin [lindex [split [lindex [split $pip "."] 1] "-"] 0]
puts $fp "$pin,$cmt_wire,$tile,$regions"
}
close $fp

View File

@ -5,15 +5,22 @@ 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())
grid = db.grid()
@ -42,6 +49,12 @@ def gen_bufhce_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. """
with open(os.path.join(os.getenv('FUZDIR'), 'build',
@ -51,6 +64,13 @@ def read_site_to_cmt():
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.
@ -305,16 +325,21 @@ def main():
PLLE2_ADV
BUFGCTRL
Local INT connect
PS7 (Zynq)
"""
print('''
// SEED={}
module top();
''')
'''.format(os.getenv('SEED')))
is_zynq = os.getenv('XRAY_DATABASE') == 'zynq7'
clock_sources = ClockSources()
site_to_cmt = dict(read_site_to_cmt())
clock_sources = ClockSources()
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
@ -426,6 +451,57 @@ module top();
.O(O_{site})
);""".format(site=site))
if is_zynq:
# FCLK clocks. Those are generated by the PS and go directly to one of
# the CLK_HROW tile.
clocks = [
"PSS_FCLKCLK0",
"PSS_FCLKCLK1",
"PSS_FCLKCLK2",
"PSS_FCLKCLK3",
]
loc, _, site = next(gen_sites('PS7'))
print("")
# Add clock sources and generate wires
for wire in clocks:
clock_info = [d for d in pss_clocks if d["pin"] == wire][0]
# CMT tile
cmt_tile = clock_info["tile"]
cmt_loc = get_cmt_loc(cmt_tile)
# Add only if the input wire is in the todo list
dsts = [k for k, v in todos.items() if clock_info["wire"] in v]
if len(dsts) > 0:
# Wire source clock region. The PS7 is always left of the
# CLK_HROW tile, but it does not matter here.
regions = clock_info["clock_regions"].split()
regions = sorted([(int(r[1]), int(r[3])) for r in regions])
# Add the clock source
cmt = "X{}Y{}".format(regions[0][0], regions[0][1])
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]))
luts = LutMaker()
bufhs = StringIO()
bufgs = StringIO()