mirror of https://github.com/openXC7/prjxray.git
164 lines
5.5 KiB
Tcl
164 lines
5.5 KiB
Tcl
proc route_via { net nodes {assert 1} } {
|
|
# Route a simple source to dest net via one or more intermediate nodes
|
|
# the nodes do not have have to be directly reachable from each other
|
|
# net: net name string
|
|
# nodes: list of node or wires strings?
|
|
# Returns 1 on success (previously would silently failed with antenna nets)
|
|
|
|
set net [get_nets $net]
|
|
# fixed_route: list of nodes in the full route
|
|
# Begins at implicit node
|
|
set fixed_route [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]]
|
|
# Implicit end node. Route it at the end
|
|
lappend nodes [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net]]
|
|
|
|
puts "Routing net $net:"
|
|
|
|
foreach to_node $nodes {
|
|
# convert wire string to node object
|
|
set to_node [get_nodes -of_objects [get_wires $to_node]]
|
|
# Start at the last point
|
|
set from_node [lindex $fixed_route end]
|
|
# Make vivado do the hard work
|
|
puts " set route \[find_routing_path -quiet -from $from_node -to $to_node\]"
|
|
set route [find_routing_path -quiet -from $from_node -to $to_node]
|
|
# TODO: check for this
|
|
if {$route == ""} {
|
|
# This can also happen if you try to route to a node already in the route
|
|
if { [ lsearch $route $to_node ] >= 0 } {
|
|
puts " WARNING: route_via loop. $to_node is already in the path, ignoring"
|
|
} else {
|
|
puts " $from_node -> $to_node: no route found - assuming direct PIP"
|
|
lappend fixed_route $to_node
|
|
}
|
|
} {
|
|
puts " $from_node -> $to_node: $route"
|
|
set fixed_route [concat $fixed_route [lrange $route 1 end]]
|
|
}
|
|
set_property -quiet FIXED_ROUTE $fixed_route $net
|
|
}
|
|
|
|
# Earlier check should catch this now
|
|
set status [get_property ROUTE_STATUS $net]
|
|
if { $status != "ROUTED" } {
|
|
puts " Failed to route net $net, status $status, route: $fixed_route"
|
|
if { $assert } {
|
|
error "Failed to route net"
|
|
}
|
|
return 0
|
|
}
|
|
|
|
set_property -quiet FIXED_ROUTE $fixed_route $net
|
|
puts ""
|
|
return 1
|
|
}
|
|
|
|
proc tile_wire_pairs {tile1 tile2} {
|
|
set tile1 [get_tiles $tile1]
|
|
set tile2 [get_tiles $tile2]
|
|
|
|
foreach wire1 [lsort [get_wires -of_objects $tile1]] {
|
|
set wire2 [get_wires -quiet -filter "TILE_NAME == $tile2" -of_objects [get_nodes -quiet -of_objects $wire1]]
|
|
if {$wire2 != ""} {puts "$wire1 $wire2"}
|
|
}
|
|
}
|
|
|
|
proc randsample_list {num lst} {
|
|
set rlst {}
|
|
for {set i 0} {$i<$num} {incr i} {
|
|
set j [expr {int(rand()*[llength $lst])}]
|
|
lappend rlst [lindex $lst $j]
|
|
set lst [lreplace $lst $j $j]
|
|
}
|
|
return $rlst
|
|
}
|
|
|
|
proc randplace_pblock {num pblock} {
|
|
set sites [randsample_list $num [get_sites -filter {SITE_TYPE == SLICEL || SITE_TYPE == SLICEM} -of_objects [get_pblocks $pblock]]]
|
|
set cells [randsample_list $num [get_cells -hierarchical -filter "PBLOCK == [get_pblocks $pblock] && REF_NAME == LUT6"]]
|
|
for {set i 0} {$i<$num} {incr i} {
|
|
set site [lindex $sites $i]
|
|
set cell [lindex $cells $i]
|
|
set_property LOC $site $cell
|
|
}
|
|
}
|
|
|
|
proc roi_tiles {} {
|
|
return [get_tiles -filter "GRID_POINT_X >= $::env(XRAY_ROI_GRID_X1) && \
|
|
GRID_POINT_X < $::env(XRAY_ROI_GRID_X2) && \
|
|
GRID_POINT_Y >= $::env(XRAY_ROI_GRID_Y1) && \
|
|
GRID_POINT_Y < $::env(XRAY_ROI_GRID_Y2)"]
|
|
}
|
|
|
|
proc pblock_tiles {pblock} {
|
|
set clb_tiles [get_tiles -of_objects [get_sites -of_objects [get_pblocks $pblock]]]
|
|
set int_tiles [get_tiles [regsub -all {CLBL[LM]} $clb_tiles INT]]
|
|
return [get_tiles "$clb_tiles $int_tiles"]
|
|
}
|
|
|
|
# returns list of unique tile types
|
|
proc get_tile_types {} {
|
|
set all_tiles [get_tiles]
|
|
set types {}
|
|
foreach tile $all_tiles {
|
|
set type [get_property TYPE $tile]
|
|
#ignore empty tiles
|
|
if {$type == "NULL"} { continue }
|
|
if {[lsearch -exact $types $type] == -1} {lappend types $type}
|
|
}
|
|
return $types
|
|
}
|
|
|
|
proc lintersect {lst1 lst2} {
|
|
set rlst {}
|
|
foreach el $lst1 {
|
|
set idx [lsearch $lst2 $el]
|
|
if {$idx >= 0} {lappend rlst $el}
|
|
}
|
|
return $rlst
|
|
}
|
|
|
|
proc putl {lst} {
|
|
foreach line $lst {puts $line}
|
|
}
|
|
|
|
proc write_pip_txtdata {filename} {
|
|
puts "FUZ([pwd]): Writing $filename."
|
|
set fp [open $filename w]
|
|
set nets [get_nets -hierarchical]
|
|
set nnets [llength $nets]
|
|
set neti 0
|
|
foreach net $nets {
|
|
incr neti
|
|
if {($neti % 100) == 0 } {
|
|
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
|
|
}
|
|
foreach pip [get_pips -of_objects $net] {
|
|
set tile [get_tiles -of_objects $pip]
|
|
set src_wire [get_wires -uphill -of_objects $pip]
|
|
set dst_wire [get_wires -downhill -of_objects $pip]
|
|
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
|
|
set dir_prop [get_property IS_DIRECTIONAL $pip]
|
|
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
|
|
}
|
|
}
|
|
close $fp
|
|
}
|
|
|
|
# Generic non-ROI'd generate.tcl template
|
|
proc generate_top {} {
|
|
create_project -force -part $::env(XRAY_PART) design design
|
|
read_verilog top.v
|
|
synth_design -top top
|
|
|
|
set_property CFGBVS VCCO [current_design]
|
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
|
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
|
|
|
place_design
|
|
route_design
|
|
|
|
write_checkpoint -force design.dcp
|
|
write_bitstream -force design.bit
|
|
}
|