| // Copyright 2020 Project U-Ray Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| proc make_driver_cell {name celltype loc pinname} { |
| create_net "${name}_net" |
| set net [get_nets "${name}_net"] |
| create_cell -reference $celltype "${name}_drv" |
| place_cell "${name}_drv" $loc |
| connect_net -net $net -objects [get_pins "${name}_drv/${pinname}"] |
| return [list [get_cells "${name}_drv"] $net] |
| } |
| |
| proc make_user_cell {name celltype loc pinname net} { |
| create_cell -reference $celltype "${name}_usr" |
| place_cell "${name}_usr" $loc |
| connect_net -net $net -objects [get_pins "${name}_usr/${pinname}"] |
| return [list [get_cells "${name}_usr"] $net] |
| } |
| |
| |
| proc make_site_pin_driver {pin} { |
| set site [get_sites -of_objects $pin] |
| if { $site == {} } { |
| return {} |
| } |
| set sitetype [get_property SITE_TYPE $site] |
| set pinname [lindex [split $pin "/"] 1] |
| set objname "${site}_${pinname}" |
| if {[get_cells -of_objects $site] != {}} { |
| return {} |
| } |
| if {$sitetype == "BUFCE_ROW" && $pinname == "CLK_OUT"} { |
| return [make_driver_cell $objname "BUFCE_ROW" "$site/BUFCE" "O"] |
| } elseif {$sitetype == "BUFCE_ROW_FSR" && $pinname == "CLK_OUT"} { |
| return [make_driver_cell $objname "BUFCE_ROW" "$site/BUFCE" "O"] |
| } elseif {$sitetype == "BUFCE_LEAF" && $pinname == "CLK_OUT"} { |
| return [make_driver_cell $objname "BUFCE_LEAF" "$site/BUFCE" "O"] |
| } elseif {$sitetype == "BUFGCE" && $pinname == "CLK_OUT"} { |
| return [make_driver_cell $objname "BUFGCE" "$site/BUFCE" "O"] |
| } elseif {$sitetype == "BUFGCE_HDIO" && $pinname == "CLK_OUT"} { |
| return [make_driver_cell $objname "BUFGCE" "$site/BUFCE" "O"] |
| } elseif {$sitetype == "BUFGCE_DIV" && $pinname == "CLK_OUT"} { |
| set result [make_driver_cell $objname "BUFGCE_DIV" "$site/BUFGCE_DIV" "O"] |
| set_property BUFGCE_DIVIDE 1 [lindex $result 0] |
| return $result |
| } elseif {$sitetype == "BUFGCTRL" && $pinname == "CLK_OUT"} { |
| return [make_driver_cell $objname "BUFGCTRL" "$site/BUFGCTRL" "O"] |
| } elseif {$sitetype == "BUFG_GT" && $pinname == "CLK_OUT"} { |
| return [make_driver_cell $objname "BUFG_GT" "$site/BUFG_GT" "O"] |
| } elseif {($sitetype == "SLICEL" || $sitetype == "SLICEM") && [string range $pinname 1 4] == "MUX"} { |
| set eighth [string range $pinname 0 0] |
| return [make_driver_cell $objname "LUT6" "$site/${eighth}6LUT" "O"] |
| } else { |
| return {} |
| } |
| } |
| |
| proc make_site_pin_user {pin net} { |
| set site [get_sites -of_objects $pin] |
| if { $site == {} } { |
| return {} |
| } |
| set sitetype [get_property SITE_TYPE $site] |
| set pinname [lindex [split $pin "/"] 1] |
| set objname "${site}_${pinname}" |
| if {[get_cells -of_objects $site] != {}} { |
| return {} |
| } |
| if {$sitetype == "BUFCE_LEAF" && $pinname == "CLK_IN"} { |
| return [make_user_cell $objname "BUFCE_LEAF" "$site/BUFCE" "I" $net] |
| } elseif {$sitetype == "BUFGCE" && $pinname == "CLK_IN"} { |
| return [make_user_cell $objname "BUFGCE" "$site/BUFCE" "I" $net] |
| } elseif {$sitetype == "BUFGCE_DIV" && $pinname == "CLK_IN"} { |
| set result [make_user_cell $objname "BUFGCE_DIV" "$site/BUFGCE_DIV" "I" $net] |
| set_property BUFGCE_DIVIDE 1 [lindex $result 0] |
| return $result |
| } elseif {$sitetype == "BUFGCTRL" && $pinname == "CLK_I0"} { |
| return [make_user_cell $objname "BUFGCTRL" "$site/BUFGCTRL" "I0" $net] |
| } elseif {$sitetype == "BUFGCTRL" && $pinname == "CLK_I1"} { |
| return [make_user_cell $objname "BUFGCTRL" "$site/BUFGCTRL" "I1" $net] |
| } elseif {$sitetype == "BUFG_GT" && $pinname == "CLK_IN"} { |
| return [make_user_cell $objname "BUFG_GT" "$site/BUFG_GT" "I" $net] |
| } elseif {$sitetype == "SLICEM" && $pinname == "LCLK"} { |
| return [make_user_cell $objname "SRL16E" "$site/H6LUT" "CLK" $net] |
| } elseif {($sitetype == "SLICEM" || $sitetype == "SLICEL") && $pinname == "CLK1"} { |
| return [make_user_cell $objname "FDRE" "$site/AFF" "C" $net] |
| } elseif {($sitetype == "SLICEM" || $sitetype == "SLICEL") && $pinname == "CLK2"} { |
| return [make_user_cell $objname "FDRE" "$site/EFF" "C" $net] |
| } elseif {$sitetype == "BITSLICE_RX_TX" && $pinname == "RX_CLK"} { |
| return [make_user_cell $objname "IDELAYE3" "$site/IDELAY" "CLK" $net] |
| } elseif {$sitetype == "BITSLICE_RX_TX" && $pinname == "RX_CLK_C"} { |
| return [make_user_cell $objname "ISERDESE3" "$site/ISERDES" "CLK" $net] |
| } else { |
| return {} |
| } |
| } |
| |
| proc route_via {net sink_pin pip} { |
| set success 0 |
| set src [lindex [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]] 0] |
| set sink [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net ]] |
| if {$sink == {}} { |
| set sink $sink_pin |
| } |
| set_property IS_ROUTE_FIXED 0 $net |
| #route_design -unroute -nets $net |
| |
| set from_node [get_nodes -uphill -of_objects $pip] |
| set to_node [get_nodes -downhill -of_objects $pip] |
| if {$src == $from_node} { |
| set route_a $from_node |
| } else { |
| if {[catch {set route_a [find_routing_path -max_nodes 15 -from $src -to $from_node]}]} { |
| return 0 |
| } |
| if {$route_a == ""} { |
| return 0 |
| } |
| } |
| if {$sink == $to_node} { |
| set route_b $to_node |
| } else { |
| if {[catch {set route_b [find_routing_path -max_nodes 15 -from $to_node -to $sink]}]} { |
| return 0 |
| } |
| if {$route_b == ""} { |
| return 0 |
| } |
| } |
| |
| if {[catch {set_property FIXED_ROUTE "$route_a $route_b" $net}]} { |
| return 0 |
| } |
| set_property IS_ROUTE_FIXED 1 $net |
| if {[get_property ROUTE_STATUS $net] != "ROUTED"} { |
| set_property IS_ROUTE_FIXED 0 $net |
| route_design -unroute -nets $net |
| return 0 |
| } |
| return 1 |
| } |
| |
| # https://wiki.tcl-lang.org/page/Shuffle+a+list |
| proc shuffle6 { list } { |
| set n [llength $list] |
| for { set i 1 } { $i < $n } { incr i } { |
| set j [expr { int( rand() * $n ) }] |
| set temp [lindex $list $i] |
| lset list $i [lindex $list $j] |
| lset list $j $temp |
| } |
| return $list |
| } |
| |
| set tile_types [list "CMT_L" "CMT_L" "CMT_L" "RCLK_BRAM_INTF_L" "RCLK_BRAM_INTF_TD_L" "RCLK_BRAM_INTF_TD_R"\ |
| "RCLK_CLEL_L_L" "RCLK_CLEL_L_R" "RCLK_CLEM_CLKBUF_L" "RCLK_CLEM_L" "RCLK_CLEM_R"\ |
| "RCLK_DSP_INTF_L" "RCLK_DSP_INTF_CLKBUF_L" "RCLK_INT_L" "RCLK_RCLK_XIPHY_INNER_FT"] |
| |
| set run $::argv |
| create_project -force -part xczu7ev-ffvf1517-2-e design${run} design${run} |
| |
| |
| link_design |
| create_cell -reference LUT6 "misc_lut" |
| place_design |
| route_design |
| |
| #remove_cell [get_cells] |
| #remove_net [get_nets] |
| |
| set count [expr {int(90 + rand()*70)}] |
| |
| for {set i 0} {$i < $count} {incr i} { |
| puts "$i/$count" |
| for {set j 0} {$j < 10} {incr j} { |
| set tt [lindex $tile_types [expr {int(rand()*[llength $tile_types])}]] |
| set tiles [get_tiles -filter "TILE_TYPE == $tt"] |
| set tile [lindex $tiles [expr {int(rand()*[llength $tiles])}]] |
| set tile_pips [get_pips -of_objects $tile -filter {NAME !~ "*VCC_WIRE*"}] |
| set pip [lindex $tile_pips [expr {int(rand()*[llength $tile_pips])}]] |
| set wavefront_bwd $pip |
| set driver {} |
| for {set k 0} {$k < 10} {incr k} { |
| set wavefront_bwd [get_nodes -uphill -of_objects $wavefront_bwd] |
| # Randomly skip to vary depth |
| if {rand() > 0.5} { |
| set wavefront_pins [shuffle6 [get_site_pins -of_objects $wavefront_bwd]] |
| foreach pin $wavefront_pins { |
| set driver [make_site_pin_driver $pin] |
| if {$driver != {}} { |
| break |
| } |
| } |
| } |
| if {$driver != {}} { |
| break |
| } |
| if {[llength $wavefront_bwd] > 20000} { |
| break |
| } |
| } |
| |
| if {$driver == {}} { |
| continue |
| } |
| |
| set drv_cell [lindex $driver 0] |
| set net [lindex $driver 1] |
| |
| set wavefront_fwd $pip |
| set user {} |
| for {set k 0} {$k < 10} {incr k} { |
| set wavefront_fwd [get_nodes -downhill -of_objects $wavefront_fwd] |
| # Randomly skip to vary depth |
| if {rand() > 0.5} { |
| set wavefront_pins [shuffle6 [get_site_pins -of_objects $wavefront_fwd]] |
| foreach pin $wavefront_pins { |
| set user [make_site_pin_user $pin $net] |
| set sink_pin $pin |
| if {$user != {}} { |
| break |
| } |
| } |
| } |
| if {$user != {}} { |
| break |
| } |
| if {[llength $wavefront_fwd] > 20000} { |
| break |
| } |
| } |
| |
| if {$user == {}} { |
| remove_cell $drv_cell |
| remove_net $net |
| continue |
| } |
| |
| set success [route_via $net $sink_pin $pip] |
| if { $success == 0 } { |
| remove_cell $drv_cell |
| remove_cell [lindex $user 0] |
| remove_net $net |
| } else { |
| break |
| } |
| } |
| } |
| |
| set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] |
| set_property SEVERITY {Warning} [get_drc_checks PDCN-*] |
| set_property SEVERITY {Warning} [get_drc_checks RTRES-*] |
| set_property SEVERITY {Warning} [get_drc_checks AVAL-*] |
| set_property SEVERITY {Warning} [get_drc_checks REQP-*] |
| set_property SEVERITY {Warning} [get_drc_checks BIVR-*] |
| set_property SEVERITY {Warning} [get_drc_checks PDRC-203] |
| set_property SEVERITY {Warning} [get_drc_checks ADEF-911] |
| |
| write_checkpoint -force ../specimen_clk/rclkroute${run}.dcp |
| write_edif -force ../specimen_clk/rclkroute${run}.edf |
| write_bitstream -force ../specimen_clk/rclkroute${run}.bit |
| |