From 90715ab3e4e48d77d9cec93eb3f41dd72c1d5413 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Mon, 18 Mar 2019 15:59:54 -0700 Subject: [PATCH] Attempt to fix flaky 041 fuzzer. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fuzzers/041-clk-hrow-pips/Makefile | 11 +- .../041-clk-hrow-pips/clk_hrow_pip_list.tcl | 32 ++- fuzzers/041-clk-hrow-pips/generate.tcl | 258 ++++++++++++------ fuzzers/041-clk-hrow-pips/top.py | 22 ++ fuzzers/045-hclk-cmt-pips/Makefile | 3 +- .../045-hclk-cmt-pips/hclk_cmt_pip_list.tcl | 32 ++- 6 files changed, 248 insertions(+), 110 deletions(-) diff --git a/fuzzers/041-clk-hrow-pips/Makefile b/fuzzers/041-clk-hrow-pips/Makefile index df0a7b87..9bd3afc1 100644 --- a/fuzzers/041-clk-hrow-pips/Makefile +++ b/fuzzers/041-clk-hrow-pips/Makefile @@ -2,18 +2,9 @@ export FUZDIR=$(shell pwd) PIP_TYPE?=clk_hrow PIPLIST_TCL=$(FUZDIR)/clk_hrow_pip_list.tcl -ifeq (${XRAY_PART}, xc7z010clg400-1) -# xc7z010clg400-1 is missing some side clock connections, so these bits cannot -# be documented. -# FIXME: Use EXCLUDE_RE rather than complicated include RE. -TODO_RE="[^\.]+\.CLK_HROW_CK_MUX_OUT_[LR][0-9]+\.CLK_HROW_.*[KR_][0-9]+" -TODO_EXCLUDE_RE="^CLK_HROW_BOT_R.*CASCIN[0-9]+$$" -else TODO_RE=".*" -TODO_EXCLUDE_RE="^CLK_HROW_BOT_R.*CASCIN[0-9]+$$" -endif -MAKETODO_FLAGS=--sides "bot_r,top_r" --pip-type ${PIP_TYPE} --seg-type clk_hrow --re $(TODO_RE) --exclude-re $(TODO_EXCLUDE_RE) +MAKETODO_FLAGS=--sides "bot_r,top_r" --pip-type ${PIP_TYPE} --seg-type clk_hrow --re $(TODO_RE) N = 50 # These PIPs all appear to be either a 2 bit solutions. diff --git a/fuzzers/041-clk-hrow-pips/clk_hrow_pip_list.tcl b/fuzzers/041-clk-hrow-pips/clk_hrow_pip_list.tcl index 83872c61..692ad20d 100644 --- a/fuzzers/041-clk-hrow-pips/clk_hrow_pip_list.tcl +++ b/fuzzers/041-clk-hrow-pips/clk_hrow_pip_list.tcl @@ -1,12 +1,30 @@ proc print_tile_pips {tile_type filename} { - set tile [lindex [get_tiles -filter "TYPE == $tile_type"] 0] - puts "Dumping PIPs for tile $tile ($tile_type) to $filename." set fp [open $filename w] - foreach pip [lsort [get_pips -of_objects [get_tiles $tile]]] { - set src [get_wires -uphill -of_objects $pip] - set dst [get_wires -downhill -of_objects $pip] - if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1} { - puts $fp "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]" + set pips [dict create] + foreach tile [get_tiles -filter "TYPE == $tile_type"] { + puts "Dumping PIPs for tile $tile ($tile_type) to $filename." + foreach pip [lsort [get_pips -of_objects $tile]] { + set src [get_wires -uphill -of_objects $pip] + set dst [get_wires -downhill -of_objects $pip] + + # Skip pips with disconnected nodes + set src_node [get_nodes -of_objects $src] + if { $src_node == {} } { + continue + } + + set dst_node [get_nodes -of_objects $src] + if { $dst_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] { + puts $fp $pip_string + dict set pips $pip_string 1 + } + } } } close $fp diff --git a/fuzzers/041-clk-hrow-pips/generate.tcl b/fuzzers/041-clk-hrow-pips/generate.tcl index 09bcabd9..5f9277e1 100644 --- a/fuzzers/041-clk-hrow-pips/generate.tcl +++ b/fuzzers/041-clk-hrow-pips/generate.tcl @@ -24,119 +24,209 @@ proc write_pip_txtdata {filename} { } proc load_todo {} { - set fp [open "../../todo.txt" r] - set todo_lines {} + set fp [open "../../todo_all.txt" r] + + # Create map of pip destinations to remaining sources for that pip + set todo_map [dict create] for {gets $fp line} {$line != ""} {gets $fp line} { - lappend todo_lines [split $line .] + set parts [split $line .] + if ![string match "*CLK_HROW_CK_IN_*" [lindex $parts 2]] { + continue + } + dict lappend todo_map [lindex $parts 1] [list [lindex $parts 0] [lindex $parts 2]] } close $fp - return $todo_lines + return $todo_map } proc route_todo {} { puts "Checking TODO's" - set todo_lines [load_todo] - set srcs {} - foreach todo $todo_lines { - set src [lindex $todo 2] + set todo_map [load_todo] - if [string match "*CLK_HROW_CK_IN_*" $src] { - lappend srcs $src - } - } + set nets [get_nets] - set srcs [lsort -unique $srcs] + set todo_nets [dict create] + set used_destinations [dict create] - set nets [get_nets -hierarchical "*clock*"] - set found_wires {} - set remaining_nets {} foreach net $nets { - set wires [get_wires -of_objects $net] + # Check to see if this net is one we are interested in + set wires [get_wires -of_objects $net -filter {TILE_NAME =~ *CLK_HROW*}] + set is_gclk_net 0 foreach wire $wires { - if [regexp "CLK_HROW_CK_IN_\[LR\]\[0-9\]+" $wire] { - # Route already going where we want it, continue - puts "Checking wire $wire." - set wire [lindex [split $wire "/"] 1] - if {[lsearch -regexp $srcs "$wire$"] != -1} { - puts "Found in TODO list, removing from list." - lappend found_wires $wire - # Fix route that is using target net. - set_property is_route_fixed 1 $net - } else { - puts "Wire not in TODO list, adding to reroute list." - lappend remaining_nets $net - } - break - } - } - } - - set found_wires [lsort -unique $found_wires] - foreach wire $found_wires { - puts "Removing $wire" - set srcs [lsearch -regexp -all -inline -not $srcs "$wire$"] - } - - puts "Remaining TODOs:" - foreach src $srcs { - puts $src - } - - set remaining_nets [lsort -unique $remaining_nets] - set completed_todos {} - - foreach net $remaining_nets { - set wires [get_wires -of_objects $net] - - set clk_in_wire "" - foreach wire $wires { - if [regexp "CLK_HROW_CK_IN_(\[LR\])\[0-9\]+" $wire match lr] { - set clk_in_wire $wire + puts "Check wire $wire in $net" + if [string match "*CLK_HROW_CK_IN_*" $wire] { + set gclk_tile [lindex [split $wire /] 0] + set gclk_wire [lindex [split $wire /] 1] + set is_gclk_net 1 break } } - if {$clk_in_wire == ""} { - error "$net does not appear to be correct net for rerouting?" + if {$is_gclk_net == 0} { + puts "$net not going to a HCLK port, skipping." + continue } - puts "" - puts "Rerouting net $net at $clk_in_wire ($lr)" + puts "Net $net wires:" + foreach wire [get_wires -of_objects $net] { + puts " - $wire" + } - # Find an input in the todo list that this can can drive. - foreach src $srcs { - if {[lsearch -exact $completed_todos $src] != -1} { + foreach wire $wires { + set tile [lindex [split $wire /] 0] + set wire [lindex [split $wire /] 1] + if { $tile != $gclk_tile } { continue } - if [regexp "CLK_HROW_CK_IN_$lr\[0-9\]+" $src] { - puts "Found target pip $src for net $net." - set tile [get_tiles -of_objects $clk_in_wire] + set tile_type [get_property TILE_TYPE [get_tiles $tile]] - set target_wire [get_wires "$tile/$src"] - set target_node [get_nodes -of_objects $target_wire] - if {[llength $target_node] == 0} { - error "Failed to find node for $tile/$src." + if { ![dict exists $todo_map $wire] } { + continue + } + + set srcs [dict get $todo_map $wire] + + # This net is interesting, see if it is already going somewhere we + # want. + set found_target 0 + foreach other_wire $wires { + if { $found_target == 1 } { + break } - set origin_node [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]] - set destination_nodes [filter [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net]] {NAME =~ *CLK_HROW*}] - route_design -unroute -nets $net - set new_route [find_routing_path -to $target_node -from $origin_node] - puts "Origin node: $origin_node" - puts "Target wire: $target_wire" - puts "Target node: $target_node" - puts "Destination nodes: $destination_nodes" + set other_wire [lindex [split $other_wire /] 1] - # Only need to set route to one of the destinations. - # Router will handle the rest. - set_property FIXED_ROUTE [concat $new_route [lindex $destination_nodes 0]] $net + if { $wire == $other_wire } { + continue + } - # Remove wire, as we've found a clock to set - lappend completed_todos $src - break + foreach src $srcs { + set src_tile_type [lindex $src 0] + + if {$src_tile_type != $tile_type} { + continue + } + + set src_wire [lindex $src 1] + + if { $other_wire == $src_wire } { + set found_target 1 + puts "Interesting net $net already going from $wire to $other_wire." + set_property IS_ROUTE_FIXED 1 $net + dict set used_destinations "$tile/$src_wire" 1 + break + } + } } + + if { $found_target == 1 } { + # Net has an interesting + continue + } + + dict set todo_nets $net [list $tile $wire $gclk_wire] + puts "Interesting net $net (including $wire and $gclk_wire) is being rerouted." + } + } + + set routed_sources [dict create] + + dict for {net tile_wire} $todo_nets { + + if { [get_property IS_ROUTE_FIXED $net] == 1 } { + puts "Net $net is already routed, skipping." + continue + } + + set tile [lindex $tile_wire 0] + set wire [lindex $tile_wire 1] + set gclk_wire [lindex $tile_wire 2] + set srcs [dict get $todo_map $wire] + + puts "" + puts "Rerouting net $net at $tile / $gclk_wire (type $tile_type)" + + set tile_type [get_property TILE_TYPE [get_tiles $tile]] + regexp "CLK_HROW_CK_IN_(\[LR\])\[0-9\]+" $gclk_wire match lr + + set todos {} + foreach src $srcs { + set src_tile_type [lindex $src 0] + if {$src_tile_type != $tile_type} { + continue + } + + set src_wire [lindex $src 1] + + if [regexp "CLK_HROW_CK_IN_$lr\[0-9\]+" $src_wire] { + lappend todos $src_wire + } + } + + if {[llength $todos] == 0} { + puts "No inputs for net $net." + dict set used_destinations "$tile/$gclk_wire" 1 + continue + } + + puts "All todos for $tile_type / $wire" + foreach src_wire $todos { + puts " - $src_wire" + } + + + # Find an input in the todo list that this can can drive. + set set_new_route 0 + foreach src_wire $todos { + if { [dict exists $used_destinations "$tile/$src_wire"] } { + puts "Not routing to $tile / $src_wire, in use." + continue + } + + puts "Attempting to route to $src_wire for net $net." + + set target_wire [get_wires "$tile/$src_wire"] + set target_node [get_nodes -of_objects $target_wire] + if {[llength $target_node] == 0} { + continue + } + + set origin_node [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]] + + if [dict exists $routed_sources $origin_node] { + puts "Skip net $net, already routed." + continue + } + + route_design -unroute -nets $net + + set old_nets [get_nets -of_objects $target_node] + if { $old_nets != {} } { + puts "Unrouting $old_nets" + route_design -unroute -nets $old_nets + } + + set old_nets [get_nets -of_objects $origin_node] + if { $old_nets != {} } { + puts "Unrouting $old_nets" + route_design -unroute -nets $old_nets + } + + set new_route [find_routing_path -to $target_node -from $origin_node] + puts "Origin node: $origin_node" + puts "Target wire: $target_wire" + puts "Target node: $target_node" + + # Only need to set route to one of the destinations. + # Router will handle the rest. + set_property FIXED_ROUTE $new_route $net + + dict set used_destinations "$tile/$src_wire" 1 + dict set routed_sources "$origin_node" 1 + set set_new_route 1 + break } } } diff --git a/fuzzers/041-clk-hrow-pips/top.py b/fuzzers/041-clk-hrow-pips/top.py index 34badcff..c4ec2dc4 100644 --- a/fuzzers/041-clk-hrow-pips/top.py +++ b/fuzzers/041-clk-hrow-pips/top.py @@ -275,6 +275,25 @@ def bufhce_in_todo(todos, site): else: return True +def need_gclk_connection(todos, site): + x, y = BUFGCTRL_XY_FUN(site) + assert x == 0 + + src_wire = 'CLK_HROW_R_CK_GCLK{}'.format(y) + for srcs in todos.values(): + if src_wire in srcs: + return True + + return False + +def only_gclk_left(todos): + for srcs in todos.values(): + for src in srcs: + if 'GCLK' not in src: + return False + + return True + def main(): """ @@ -303,6 +322,9 @@ module top(); todos = read_todo() + if only_gclk_left(todos): + mmcm_pll_dir = 'NONE' + if not mmcm_pll_only: if need_int_connections(todos): for _ in range(10): diff --git a/fuzzers/045-hclk-cmt-pips/Makefile b/fuzzers/045-hclk-cmt-pips/Makefile index 06e27822..d0a9df82 100644 --- a/fuzzers/045-hclk-cmt-pips/Makefile +++ b/fuzzers/045-hclk-cmt-pips/Makefile @@ -3,12 +3,11 @@ PIP_TYPE?=hclk_cmt PIPLIST_TCL=$(FUZDIR)/hclk_cmt_pip_list.tcl TODO_RE=".*" # Skipped pips: -# - LEAF wires are disconnected # - 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)|(HCLK_CMT_L\.[^.]+\.HCLK_CMT_MUX_CLK_[0-9]+)|(HCLK_CMT\.[^.]+\.HCLK_CMT_CK_IN[0-9]+)|(^.*BUFMR)|(^.*FREQ_REF)|(^.*PHSR)|(^.*CLK_PLL7)|(^.*CLK_MMCM13)" +EXCLUDE_RE="(^.*BUFMR)|(^.*FREQ_REF)|(^.*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 = 50 diff --git a/fuzzers/045-hclk-cmt-pips/hclk_cmt_pip_list.tcl b/fuzzers/045-hclk-cmt-pips/hclk_cmt_pip_list.tcl index e3ff9cdf..a41b692b 100644 --- a/fuzzers/045-hclk-cmt-pips/hclk_cmt_pip_list.tcl +++ b/fuzzers/045-hclk-cmt-pips/hclk_cmt_pip_list.tcl @@ -1,12 +1,30 @@ proc print_tile_pips {tile_type filename} { - set tile [lindex [get_tiles -filter "TYPE == $tile_type"] 0] - puts "Dumping PIPs for tile $tile ($tile_type) to $filename." set fp [open $filename w] - foreach pip [lsort [get_pips -of_objects [get_tiles $tile]]] { - set src [get_wires -uphill -of_objects $pip] - set dst [get_wires -downhill -of_objects $pip] - if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1} { - puts $fp "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]" + set pips [dict create] + foreach tile [get_tiles -filter "TYPE == $tile_type"] { + puts "Dumping PIPs for tile $tile ($tile_type) to $filename." + foreach pip [lsort [get_pips -of_objects $tile]] { + set src [get_wires -uphill -of_objects $pip] + set dst [get_wires -downhill -of_objects $pip] + + # Skip pips with disconnected nodes + set src_node [get_nodes -of_objects $src] + if { $src_node == {} } { + continue + } + + set dst_node [get_nodes -of_objects $src] + if { $dst_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] { + puts $fp $pip_string + dict set pips $pip_string 1 + } + } } } close $fp