blob: 5aaf81d476e89335a19ae6937af18a05e1fe42cc [file] [log] [blame] [edit]
// 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