Automatic inference of CLK_HROW with PS7 clocks, use of todo list for PS7 clock sources.

Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
Maciej Kurc 2019-12-11 21:43:01 +01:00
parent fb65464c42
commit 24ccfb3bb5
3 changed files with 65 additions and 43 deletions

View File

@ -246,16 +246,8 @@ proc run {} {
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
place_design
puts "Routing design #1"
route_design -directive Quick
write_checkpoint -force design_initially_routed.dcp
puts "Routing TODOs"
route_todo
write_checkpoint -force design_todo_routed.dcp
puts "Routing design #2"
route_design -directive Quick
write_checkpoint -force design.dcp

View File

@ -3,21 +3,39 @@ set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
set fp [open "pss_clocks.csv" "w"]
puts $fp "pin,tile"
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.
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.
# 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,$tile"
puts $fp "$pin,$cmt_wire,$tile,$regions"
}
close $fp

View File

@ -16,9 +16,11 @@ 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()
@ -46,11 +48,13 @@ 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. """
with open(os.path.join(os.getenv('FUZDIR'), 'build',
@ -59,12 +63,14 @@ 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:
'pss_clocks.csv')) as f:
for l in csv.DictReader(f):
yield l
class ClockSources(object):
""" Class for tracking clock sources.
@ -161,7 +167,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:
@ -327,7 +333,6 @@ def main():
module top();
'''.format(os.getenv('SEED')))
is_zynq = os.getenv('XRAY_DATABASE') == 'zynq7'
clock_sources = ClockSources()
@ -448,37 +453,54 @@ module top();
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",
"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:
cmt_tile = [d["tile"] for d in pss_clocks if d["pin"] == wire][0]
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)
# FIXME: HACK
clock_sources.add_clock_source(wire, "X0Y0", cmt_loc)
# 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("""
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]
))
site=site,
fclk0=clocks[0],
fclk1=clocks[1],
fclk2=clocks[2],
fclk3=clocks[3]))
luts = LutMaker()
bufhs = StringIO()
@ -550,11 +572,6 @@ module top();
if random.random() > .05:
wire_name = clock_sources.get_random_source(site_to_cmt[site])
# FIXME: HACK
if wire_name is not None and wire_name.startswith("PSS"):
if "BOT" not in tile_name:
continue
if wire_name is None:
continue
@ -590,8 +607,6 @@ module top();
break
break
for l in luts.create_wires_and_luts():
print(l)
@ -605,7 +620,6 @@ 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:
print(
"""
@ -617,7 +631,6 @@ 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:
print(
"""
@ -628,6 +641,5 @@ module top();
print("endmodule")
if __name__ == '__main__':
main()