mirror of https://github.com/openXC7/prjxray.git
Make MMCM pip fuzzer more robust.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
af6700a692
commit
4e4bcae418
|
|
@ -220,9 +220,6 @@ def main():
|
|||
|
||||
tags_to_remove = set()
|
||||
for tag, bits in segbits.items():
|
||||
if len(bits) == 0:
|
||||
tags_to_remove.add(tag)
|
||||
|
||||
if 'REBUF' in tag and 'ACTIVE' not in tag:
|
||||
# FIXME: Removing REBUF pips for now.
|
||||
tags_to_remove.add(tag)
|
||||
|
|
@ -232,15 +229,14 @@ def main():
|
|||
|
||||
for tag in segbits.keys():
|
||||
if tag.endswith("_ACTIVE") and 'FREQ_BB' in tag:
|
||||
if 'FREQ_BB_REBUF' in tag:
|
||||
m = re.search('FREQ_BB_REBUF([0-9])', tag)
|
||||
else:
|
||||
m = re.search('FREQ_BB_NS([0-9])', tag)
|
||||
assert m is not None, tag
|
||||
|
||||
prefix = '.CMT_R_LOWER_B_CLK_FREQ_BB{}'.format(m.group(1))
|
||||
tags_to_mask = [t for t in segbits.keys() if t.endswith(prefix)]
|
||||
mask_out_bits(segbits, segbits[tag], tags_to_mask)
|
||||
for idx in range(4):
|
||||
prefix1 = '.CMT_L_LOWER_B_CLK_FREQ_BB{}'.format(idx)
|
||||
prefix2 = '.CMT_R_LOWER_B_CLK_FREQ_BB{}'.format(idx)
|
||||
tags_to_mask = [
|
||||
t for t in segbits.keys()
|
||||
if t.endswith(prefix1) or t.endswith(prefix2)
|
||||
]
|
||||
mask_out_bits(segbits, segbits[tag], tags_to_mask)
|
||||
|
||||
# Find common bits
|
||||
bit_groups = find_common_bits_for_tag_groups(segbits, tag_groups)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,116 @@ proc write_used_wires {filename} {
|
|||
close $fp
|
||||
}
|
||||
|
||||
proc load_route {line} {
|
||||
puts "MANROUTE: Line: $line"
|
||||
|
||||
# Parse the line
|
||||
set fields [split $line " "]
|
||||
set tile_name [lindex $fields 0]
|
||||
set site_name [lindex $fields 1]
|
||||
set pin_name [lindex $fields 2]
|
||||
set route_dir [lindex $fields 3]
|
||||
set wires [lrange $fields 4 end]
|
||||
|
||||
# Get net
|
||||
set tile [get_tiles $tile_name]
|
||||
set site [get_sites -of_objects $tile $site_name]
|
||||
set pin [get_site_pins -of_objects $site "*/$pin_name"]
|
||||
set net [get_nets -quiet -of_objects $pin]
|
||||
|
||||
if {$net eq "" } {
|
||||
puts "MANROUTE: No net for pin $pin_name found! Skipping..."
|
||||
return
|
||||
}
|
||||
|
||||
set source_pin [get_pins -of $net -filter "DIRECTION == OUT"]
|
||||
if { [llength $source_pin] == 0 } {
|
||||
error "Failed to find source pin of net $net"
|
||||
}
|
||||
|
||||
set source_site_pins [get_site_pins -of $source_pin]
|
||||
puts "MANROUTE: Possible site pins for net $net: $source_site_pins"
|
||||
|
||||
# Fixed part read from file
|
||||
set route_list {}
|
||||
if { [string first / $wires] != -1 } {
|
||||
# Route list is just intermediate node and final node, fill it in
|
||||
if { [llength $wires] != 2} {
|
||||
error "Expected only 2 wires, found [llength $wires]"
|
||||
}
|
||||
|
||||
set intermediate_node [get_nodes [lindex $wires 0]]
|
||||
set dest_node [get_nodes -of_objects [get_wires -of_objects $tile "*/[lindex $wires 1]"]]
|
||||
if [catch {find_routing_path -from $intermediate_node -to $dest_node} route_list] {
|
||||
puts "MANROUTE: Failed to find routing path from $intermediate_node to $dest_node for net $net\nError: $route_list"
|
||||
return
|
||||
}
|
||||
|
||||
if { [llength $route_list] == 0 } {
|
||||
puts "MANROUTE: Failed to find routing path from $intermediate_node to $dest_node for net $net"
|
||||
return
|
||||
}
|
||||
} else {
|
||||
foreach wire $wires {
|
||||
lappend route_list [get_nodes -of_objects [get_wires -of_objects $tile "*/$wire"]]
|
||||
}
|
||||
}
|
||||
|
||||
# Complete the route
|
||||
if {$route_dir eq "up"} {
|
||||
set node_to [lindex $route_list 0]
|
||||
set node_from [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]]
|
||||
|
||||
set rpart [find_routing_path -from $node_from -to $node_to]
|
||||
if {$rpart eq ""} {
|
||||
puts "MANROUTE: No possible route continuation for net $net"
|
||||
return
|
||||
}
|
||||
|
||||
set route_list [concat [lrange $rpart 0 end-1] $route_list]
|
||||
}
|
||||
|
||||
if {$route_dir eq "down"} {
|
||||
set node_from [lindex $route_list e]
|
||||
set node_to [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net]]
|
||||
|
||||
set rpart [find_routing_path -from $node_from -to $node_to]
|
||||
if {$rpart eq ""} {
|
||||
puts "MANROUTE: No possible route continuation for net $net"
|
||||
return
|
||||
}
|
||||
set route_list [concat $route_list [lrange $rpart 1 end]]
|
||||
}
|
||||
|
||||
# Set the fixed route
|
||||
puts "MANROUTE: Net: $net, Route: $route_list. routing..."
|
||||
regsub -all {{}} $route_list "" route
|
||||
if [catch {set_property FIXED_ROUTE $route $net} result] {
|
||||
puts "MANROUTE: Net $net failed to set FIXED_ROUTE, ripping up...\nError: $result"
|
||||
set_property FIXED_ROUTE "" $net
|
||||
set_property IS_ROUTE_FIXED 0 $net
|
||||
route_design -unroute -nets $net
|
||||
}
|
||||
|
||||
# Route the single net. Needed to detect conflicts when evaluating
|
||||
# other ones
|
||||
puts "Running route design"
|
||||
route_design -quiet -directive Quick -nets $net
|
||||
puts "Done running route design"
|
||||
|
||||
# Check for conflicts.
|
||||
set status [get_property ROUTE_STATUS $net]
|
||||
if {$status ne "ROUTED"} {
|
||||
# Ripup and discard the fixed route.
|
||||
set_property FIXED_ROUTE "" $net
|
||||
route_design -unroute -nets $net
|
||||
puts "MANROUTE: Net $net status $status, ripping up..."
|
||||
} else {
|
||||
set_property IS_ROUTE_FIXED 1 $net
|
||||
puts "MANROUTE: Successful manual route for $net"
|
||||
}
|
||||
}
|
||||
|
||||
proc load_routes {filename} {
|
||||
puts "MANROUTE: Loading routes from $filename"
|
||||
|
||||
|
|
@ -56,86 +166,7 @@ proc load_routes {filename} {
|
|||
continue
|
||||
}
|
||||
|
||||
puts "MANROUTE: Line: $line"
|
||||
|
||||
# Parse the line
|
||||
set fields [split $line " "]
|
||||
set tile_name [lindex $fields 0]
|
||||
set site_name [lindex $fields 1]
|
||||
set pin_name [lindex $fields 2]
|
||||
set route_dir [lindex $fields 3]
|
||||
set wires [lrange $fields 4 end]
|
||||
|
||||
# Get net
|
||||
set tile [get_tiles $tile_name]
|
||||
set site [get_sites -of_objects $tile $site_name]
|
||||
set pin [get_site_pins -of_objects $site "*/$pin_name"]
|
||||
set net [get_nets -quiet -of_objects $pin]
|
||||
|
||||
if {$net eq "" } {
|
||||
puts "MANROUTE: No net for pin $pin_name found! Skipping..."
|
||||
continue
|
||||
}
|
||||
|
||||
# Fixed part read from file
|
||||
set route_list {}
|
||||
foreach wire $wires {
|
||||
lappend route_list [get_nodes -of_objects [get_wires -of_objects $tile "*/$wire"]]
|
||||
}
|
||||
|
||||
# Complete the route
|
||||
if {$route_dir eq "up"} {
|
||||
set node_to [lindex $route_list 0]
|
||||
set node_from [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]]
|
||||
|
||||
set rpart [find_routing_path -from $node_from -to $node_to]
|
||||
if {$rpart eq ""} {
|
||||
puts "MANROUTE: No possible route continuation for net $net"
|
||||
continue
|
||||
}
|
||||
|
||||
set route_list [concat [lrange $rpart 0 end-1] $route_list]
|
||||
}
|
||||
|
||||
if {$route_dir eq "down"} {
|
||||
set node_from [lindex $route_list e]
|
||||
set node_to [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net]]
|
||||
|
||||
set rpart [find_routing_path -from $node_from -to $node_to]
|
||||
if {$rpart eq ""} {
|
||||
puts "MANROUTE: No possible route continuation for net $net"
|
||||
continue
|
||||
}
|
||||
set route_list [concat $route_list [lrange $rpart 1 end]]
|
||||
}
|
||||
|
||||
# Set the fixed route
|
||||
puts "MANROUTE: Net: $net, Route: $route_list. routing..."
|
||||
regsub -all {{}} $route_list "" route
|
||||
if [catch {set_property FIXED_ROUTE $route $net} ] {
|
||||
puts "MANROUTE: Net $net failed to set FIXED_ROUTE, ripping up..."
|
||||
set_property FIXED_ROUTE "" $net
|
||||
set_property IS_ROUTE_FIXED 0 $net
|
||||
route_design -unroute -nets $net
|
||||
}
|
||||
|
||||
# Route the single net. Needed to detect conflicts when evaluating
|
||||
# other ones
|
||||
puts "Running route design"
|
||||
route_design -quiet -directive Quick -nets $net
|
||||
puts "Done running route design"
|
||||
|
||||
# Check for conflicts.
|
||||
set status [get_property ROUTE_STATUS $net]
|
||||
if {$status ne "ROUTED"} {
|
||||
# Ripup and discard the fixed route.
|
||||
set_property FIXED_ROUTE "" $net
|
||||
route_design -unroute -nets $net
|
||||
puts "MANROUTE: Net $net status $status, ripping up..."
|
||||
} else {
|
||||
set_property IS_ROUTE_FIXED 1 $net
|
||||
puts "MANROUTE: Successful manual route for $net"
|
||||
}
|
||||
load_route $line
|
||||
}
|
||||
|
||||
close $fp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_IN3_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_IN3_INT
|
||||
|
||||
CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_IN1_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_IN1_INT
|
||||
|
||||
CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_IN2_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_IN2_INT
|
||||
|
||||
CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_IN3_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_IN3_INT
|
||||
|
||||
CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_IN1_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_IN1_INT
|
||||
|
||||
CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_IN2_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_IN2_INT
|
||||
|
|
@ -84,6 +84,20 @@ def find_phasers_for_mmcm(grid, loc):
|
|||
return phasers
|
||||
|
||||
|
||||
def find_hclk_ref_wires_for_mmcm(grid, loc):
|
||||
tilename = grid.tilename_at_loc((loc[0], loc[1] - 17))
|
||||
gridinfo = grid.gridinfo_at_tilename(tilename)
|
||||
|
||||
assert gridinfo.tile_type in ['HCLK_CMT_L', 'HCLK_CMT']
|
||||
|
||||
# HCLK_CMT_MUX_OUT_FREQ_REF[0-3]
|
||||
wires = []
|
||||
for idx in range(4):
|
||||
wires.append('{}/HCLK_CMT_MUX_OUT_FREQ_REF{}'.format(tilename, idx))
|
||||
|
||||
return wires
|
||||
|
||||
|
||||
def gen_sites():
|
||||
db = Database(util.get_db_root(), util.get_part())
|
||||
grid = db.grid()
|
||||
|
|
@ -94,11 +108,12 @@ def gen_sites():
|
|||
for site_name, site_type in gridinfo.sites.items():
|
||||
if site_type in ['MMCME2_ADV']:
|
||||
phasers = find_phasers_for_mmcm(grid, loc)
|
||||
yield tile_name, site_name, phasers
|
||||
hclk_wires = find_hclk_ref_wires_for_mmcm(grid, loc)
|
||||
yield tile_name, site_name, phasers, hclk_wires
|
||||
|
||||
|
||||
def get_random_route_from_site_pin(
|
||||
pip_list, tile_name, site_pin, direction, occupied_wires):
|
||||
pip_list, tile_name, site_pin, direction, occupied_wires, hclk_wires):
|
||||
|
||||
# A map of MMCM site pins to wires they are connected to.
|
||||
pin_to_wire = {
|
||||
|
|
@ -138,6 +153,9 @@ def get_random_route_from_site_pin(
|
|||
# The first wire
|
||||
wire = pin_to_wire[tile_type][site_pin]
|
||||
|
||||
if site_pin in ["CLKIN1", "CLKIN2", "CLKFBIN"] and random.random() < .2:
|
||||
return [random.choice(hclk_wires), wire]
|
||||
|
||||
# Walk randomly.
|
||||
route = []
|
||||
while True:
|
||||
|
|
@ -199,7 +217,7 @@ module top(
|
|||
count = 0
|
||||
mmcms = sorted(gen_sites(), key=lambda x: x[0])
|
||||
random.shuffle(mmcms)
|
||||
for tile, site, phasers in mmcms:
|
||||
for tile, site, phasers, hclk_wires in mmcms:
|
||||
in_use = random.randint(0, 2) > 0
|
||||
count += 1
|
||||
|
||||
|
|
@ -219,20 +237,20 @@ module top(
|
|||
|
||||
# Sometimes manually randomized route for CLKOUTx conflicts with
|
||||
# the verilog design.
|
||||
('CLKOUT0', 'down'),
|
||||
('CLKOUT1', 'down'),
|
||||
('CLKOUT2', 'down'),
|
||||
('CLKOUT3', 'down'),
|
||||
('CLKOUT4', 'down'),
|
||||
('CLKOUT5', 'down'),
|
||||
('CLKOUT6', 'down'),
|
||||
#('CLKOUT0', 'down'),
|
||||
#('CLKOUT1', 'down'),
|
||||
#('CLKOUT2', 'down'),
|
||||
#('CLKOUT3', 'down'),
|
||||
#('CLKOUT4', 'down'),
|
||||
#('CLKOUT5', 'down'),
|
||||
#('CLKOUT6', 'down'),
|
||||
]
|
||||
|
||||
occupied_wires = set()
|
||||
for pin, dir in pins:
|
||||
|
||||
route = get_random_route_from_site_pin(
|
||||
pip_list, tile, pin, dir, occupied_wires)
|
||||
pip_list, tile, pin, dir, occupied_wires, hclk_wires)
|
||||
if route is None:
|
||||
endpoints[pin] = ""
|
||||
continue
|
||||
|
|
@ -248,11 +266,10 @@ module top(
|
|||
# Store them in a random order so the TCL script will try to route
|
||||
# them also in the random order.
|
||||
lines = []
|
||||
for pin, (
|
||||
route,
|
||||
dir,
|
||||
) in routes.items():
|
||||
|
||||
pins = sorted(routes.keys())
|
||||
random.shuffle(pins)
|
||||
for pin in pins:
|
||||
(route, dir) = routes[pin]
|
||||
route_str = " ".join(route)
|
||||
lines.append(
|
||||
'{} {} {} {} {}\n'.format(tile, site, pin, dir, route_str))
|
||||
|
|
|
|||
Loading…
Reference in New Issue