vortex/hw/scripts/xilinx_async_bram_patch.tcl
tinebp 83ba1cc3dc
Some checks failed
CI / setup (push) Has been cancelled
CI / build (32) (push) Has been cancelled
CI / build (64) (push) Has been cancelled
CI / tests (cache, 32) (push) Has been cancelled
CI / tests (cache, 64) (push) Has been cancelled
CI / tests (config1, 32) (push) Has been cancelled
CI / tests (config1, 64) (push) Has been cancelled
CI / tests (config2, 32) (push) Has been cancelled
CI / tests (config2, 64) (push) Has been cancelled
CI / tests (debug, 32) (push) Has been cancelled
CI / tests (debug, 64) (push) Has been cancelled
CI / tests (opencl, 32) (push) Has been cancelled
CI / tests (opencl, 64) (push) Has been cancelled
CI / tests (regression, 32) (push) Has been cancelled
CI / tests (regression, 64) (push) Has been cancelled
CI / tests (scope, 32) (push) Has been cancelled
CI / tests (scope, 64) (push) Has been cancelled
CI / tests (stress, 32) (push) Has been cancelled
CI / tests (stress, 64) (push) Has been cancelled
CI / tests (synthesis, 32) (push) Has been cancelled
CI / tests (synthesis, 64) (push) Has been cancelled
CI / tests (vector, 32) (push) Has been cancelled
CI / tests (vector, 64) (push) Has been cancelled
CI / tests (vm, 32) (push) Has been cancelled
CI / tests (vm, 64) (push) Has been cancelled
CI / complete (push) Has been cancelled
minor update
2025-01-11 20:23:26 -08:00

718 lines
22 KiB
Tcl

# Copyright © 2019-2023
#
# 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.
namespace eval vortex {
variable debug 0
proc print_error {msg {do_exit 1}} {
if {$do_exit} {
puts "ERROR: $msg"
exit -1
} else {
variable debug
if {$debug} {puts "WARNING: $msg"}
}
}
proc str_replace {str match repl} {
set result ""
regsub $match $str $repl result
return $result
}
proc regex_escape {str} {
return [string map {
\\ \\\\
^ \\^
. \\.
\[ \\\[
\] \\\]
\$ \\\$
\( \\\(
\) \\\)
| \\|
* \\*
+ \\+
? \\?
\{ \\\{
\} \\\}
} $str]
}
proc unique_cell_name {name} {
if {[get_cells -quiet $name] == {}} { return $name }
set index 0
while {[get_cells -quiet ${name}_${index}] != {}} { incr index }
return ${name}_${index}
}
proc unique_net_name {name} {
if {[get_nets -quiet $name] == {}} { return $name }
set index 0
while {[get_nets -quiet ${name}_${index}] != {}} { incr index }
return ${name}_${index}
}
proc build_parent_child_map {all_cells} {
set parent_child_map {}
foreach cell $all_cells {
set parent [get_property PARENT $cell]
if {$parent ne ""} {
if {[dict exists $parent_child_map $parent]} {
dict lappend parent_child_map $parent $cell
} else {
dict set parent_child_map $parent [list $cell]
}
}
}
return $parent_child_map
}
proc find_cell_descendants_recursive {parent_cell parent_child_map} {
set descendants {}
if {[dict exists $parent_child_map $parent_cell]} {
set children [dict get $parent_child_map $parent_cell]
foreach child $children {
# Add the child to the list
lappend descendants $child
# Recursively add its descendants
set sub_descendants [find_cell_descendants_recursive $child $parent_child_map]
lappend descendants {*}$sub_descendants
}
}
return $descendants
}
proc find_cell_descendants {parent_cell} {
set all_cells [get_cells -hierarchical]
set parent_child_map [build_parent_child_map $all_cells]
return [find_cell_descendants_recursive $parent_cell $parent_child_map]
}
proc find_nested_cells {parent_cell name_match {should_exist 1}} {
set hier_sep [get_hierarchy_separator]
set matching_cells {}
foreach cell [find_cell_descendants $parent_cell] {
set parent_name [get_property PARENT $cell]
set cell_name [get_property NAME $cell]
set name_prefix [regex_escape "${parent_name}${hier_sep}"]
set pattern "${name_prefix}${name_match}"
if {[regexp $pattern $cell_name]} {
lappend matching_cells $cell
}
}
if {[llength $matching_cells] == 0} {
print_error "No matching cell found for '$parent_cell' matching '$name_match'." $should_exist
}
return $matching_cells
}
proc find_cell_nets {cell name_match {should_exist 1}} {
set matching_nets {}
foreach net [get_nets -hierarchical -filter "PARENT_CELL == $cell"] {
set name [get_property NAME $net]
if {[regexp $name_match $name]} {
lappend matching_nets $net
}
}
if {[llength $matching_nets] == 0} {
print_error "No matching net found for '$cell' matching '$name_match'." $should_exist
}
return $matching_nets
}
proc find_cell_net {cell name_match {should_exist 1}} {
set nets [find_cell_nets $cell $name_match $should_exist]
if {[llength $nets] == 0} {
return ""
} elseif {[llength $nets] > 1} {
puts "ERROR: Multiple matching nets found for '$cell' matching '$name_match'."
exit -1
}
return [lindex $nets 0]
}
proc get_cell_net {cell name} {
set net [get_nets -hierarchical -filter "PARENT_CELL == $cell && NAME == $name"]
if {[llength $net] == 0} {
puts "ERROR: No matching net found for '$cell' matching '$name'."
exit -1
}
return $net;
}
proc find_cell_pins {cell name_match {should_exist 1}} {
set hier_sep [get_hierarchy_separator]
set matching_pins {}
foreach pin [get_pins -of_objects $cell] {
set name [get_property NAME $pin]
set name_prefix [regex_escape "${cell}${hier_sep}"]
set pattern "${name_prefix}${name_match}"
if {[regexp $pattern $name]} {
lappend matching_pins $pin
}
}
if {[llength $matching_pins] == 0} {
print_error "No matching pin found for '$cell' matching '$name_match'." $should_exist
}
return $matching_pins
}
proc get_cell_pin {cell name} {
set pin [get_pins -of_objects $cell -filter "NAME == $name"]
if {[llength $pin] == 0} {
puts "ERROR: No matching pin found for '$cell' matching '$name'."
exit -1
}
return $pin
}
proc remove_cell_from_netlist {cell} {
variable debug
# Disconnect all pins of the cell
foreach pin [get_pins -quiet -of_objects $cell] {
foreach net [get_nets -quiet -of_objects $pin] {
disconnect_net -net $net -objects $pin
if {$debug} {puts "DEBUG: Disconnected net '$net' from pin '$pin'."}
}
}
# Remove the cell
remove_cell $cell
if {$debug} {puts "DEBUG: Cell '$cell' was removed successfully."}
}
proc find_net_driver {taregt_net {should_exist 1}} {
set driverPins [get_pins -quiet -leaf -of_objects $taregt_net -filter {DIRECTION == "OUT"}]
if {[llength $driverPins] == 0} {
set driverPorts [get_ports -quiet -of_objects $taregt_net -filter {DIRECTION == "IN"}]
if {[llength $driverPorts] == 0} {
print_error "No driver found for '$taregt_net'." $should_exist
} elseif {[llength $driverPorts] > 1} {
puts "WARNING: Multiple driver ports found for '$taregt_net'."
return [lindex $driverPorts 0]
}
return $driverPorts
} elseif {[llength $driverPins] > 1} {
puts "WARNING: Multiple driver pins found for '$taregt_net'."
return [lindex $driverPins 0]
}
return $driverPins
}
proc find_pin_driver {target_pin {should_exist 1}} {
set net [get_nets -quiet -of_objects $target_pin]
if {[llength $net] == 0} {
print_error "No net connected to pin '$target_pin'." $should_exist
return ""
} elseif {[llength $net] > 1} {
puts "ERROR: Multiple nets connected to pin '$target_pin'."
exit -1
}
return [find_net_driver $net]
}
proc create_register_next {parent reg_cell raddr_reset} {
variable debug
set hier_sep [get_hierarchy_separator]
set reg_d_pin [get_pins "${reg_cell}${hier_sep}D"]
if {[llength $reg_d_pin] == 0} {
puts "ERROR: No D pin found on register cell '$reg_cell'."
exit -1
} elseif {[llength $reg_d_pin] > 1} {
puts "ERROR: Multiple D pins found on register cell '$reg_cell'."
exit -1
}
if {$debug} {puts "DEBUG: reg_d_pin: '$reg_d_pin'"}
set reg_d_src_pin [find_pin_driver $reg_d_pin]
if {$reg_d_src_pin == ""} {
puts "ERROR: No source pin found connected to '$reg_d_pin'."
exit -1
}
if {$debug} {puts "DEBUG: reg_d_src_pin: '$reg_d_src_pin'"}
if {$raddr_reset == ""} {
return $reg_d_src_pin
}
set reg_r_src_pin ""
set register_type [get_property REF_NAME $reg_cell]
if {$register_type == "FDRE"} {
set reg_r_pin [get_pins "${reg_cell}${hier_sep}R"]
if {[llength $reg_r_pin] == 0} {
puts "ERROR: No R pin found on FDRE cell '$reg_cell'."
exit -1
} elseif {[llength $reg_r_pin] > 1} {
puts "ERROR: Multiple R pins found on FDRE cell '$reg_cell'."
exit -1
}
if {$debug} {puts "DEBUG: reg_r_pin: '$reg_r_pin'"}
set reg_r_src_pin [find_pin_driver $reg_r_pin]
if {$reg_r_src_pin == ""} {
puts "ERROR: No source pin found connected to '$reg_r_pin'."
exit -1
}
} elseif {$register_type == "FDSE"} {
set reg_s_pin [get_pins "${reg_cell}${hier_sep}S"]
if {[llength $reg_s_pin] == 0} {
puts "ERROR: No S pin found on FDSE cell '$reg_cell'."
exit -1
} elseif {[llength $reg_s_pin] > 1} {
puts "ERROR: Multiple S pins found on FDSE cell '$reg_cell'."
exit -1
}
if {$debug} {puts "DEBUG: reg_s_pin: '$reg_s_pin'"}
set reg_r_src_pin [find_pin_driver $reg_s_pin]
if {$reg_r_src_pin == ""} {
puts "ERROR: No source pin found connected to '$reg_s_pin'."
exit -1
}
} else {
puts "ERROR: Unsupported register type: '$register_type'."
exit 1
}
if {$debug} {puts "DEBUG: reg_r_src_pin: '$reg_r_src_pin'"}
set reg_d_src_net [get_nets -of_objects $reg_d_src_pin]
if {[llength $reg_d_src_net] == 0} {
puts "ERROR: Unable to get source nets for pins."
exit -1
} elseif {[llength $reg_d_src_net] > 1} {
puts "ERROR: Multiple source nets found for pins."
exit -1
}
set reg_r_src_net [get_nets -of_objects $reg_r_src_pin]
if {[llength $reg_r_src_net] == 0} {
puts "ERROR: Unable to get source nets for pins."
exit -1
} elseif {[llength $reg_r_src_net] > 1} {
puts "ERROR: Multiple source nets found for pins."
exit -1
}
# Create a MUX cell to implement register next value
# Use a 2x1 LUT to describe the logic:
# FDRE: O = I1 ? 0 : I0; where I0=D, I1=R
# FDSE: O = I1 ? 1 : I0; where I0=D, I1=S
set lut_name [unique_cell_name "${parent}${hier_sep}raddr_next"]
set lut_cell [create_cell -reference LUT2 $lut_name]
if {$debug} {puts "DEBUG: Created lut cell: '$lut_cell'"}
if {$register_type == "FDRE"} {
set_property INIT 4'b0010 $lut_cell
} elseif {$register_type == "FDSE"} {
set_property INIT 4'b1110 $lut_cell
} else {
puts "ERROR: Unsupported register type: '$register_type'."
exit 1
}
set lut_i0_pin [get_pins "${lut_cell}${hier_sep}I0"]
if {[llength $lut_i0_pin] == 0} {
puts "ERROR: No I0 pin found on FDSE cell '$lut_cell'."
exit -1
} elseif {[llength $lut_i0_pin] > 1} {
puts "ERROR: Multiple I0 pins found on FDSE cell '$lut_cell'."
exit -1
}
set lut_i1_pin [get_pins "${lut_cell}${hier_sep}I1"]
if {[llength $lut_i1_pin] == 0} {
puts "ERROR: No I1 pin found on FDSE cell '$lut_cell'."
exit -1
} elseif {[llength $lut_i1_pin] > 1} {
puts "ERROR: Multiple I1 pins found on FDSE cell '$lut_cell'."
exit -1
}
set lut_o_pin [get_pins "${lut_cell}${hier_sep}O"]
if {[llength $lut_o_pin] == 0} {
puts "ERROR: No O pin found on FDSE cell '$lut_cell'."
exit -1
} elseif {[llength $lut_o_pin] > 1} {
puts "ERROR: Multiple O pins found on FDSE cell '$lut_cell'."
exit -1
}
connect_net -net $reg_d_src_net -objects $lut_i0_pin -hierarchical
if {$debug} {puts "DEBUG: Connected net '$reg_d_src_net' to pin '$lut_i0_pin'."}
connect_net -net $reg_r_src_net -objects $lut_i1_pin -hierarchical
if {$debug} {puts "DEBUG: Connected net '$reg_r_src_net' to pin '$lut_i1_pin'."}
return $lut_o_pin
}
proc getOrCreateVCCPin {parent} {
variable debug
set hier_sep [get_hierarchy_separator]
set cell_name "${parent}${hier_sep}VCC"
set vcc_cell [get_cells -quiet $cell_name]
if {[llength $vcc_cell] == 0} {
set vcc_cell [create_cell -reference VCC $cell_name]
if {$debug} {puts "DEBUG: Created VCC cell: '$vcc_cell'"}
} elseif {[llength $vcc_cell] > 1} {
puts "ERROR: Multiple VCC cells found with name '$cell_name'."
exit -1
}
set vcc_pin [get_pins "${vcc_cell}${hier_sep}P"]
if {[llength $vcc_pin] == 0} {
puts "ERROR: No VCC pin found on VCC cell '$vcc_cell'."
exit -1
} elseif {[llength $vcc_pin] > 1} {
puts "ERROR: Multiple VCC pins found on VCC cell '$vcc_cell'."
exit -1
}
return $vcc_pin
}
proc getOrCreateGNDPin {parent} {
variable debug
set hier_sep [get_hierarchy_separator]
set cell_name "${parent}${hier_sep}GND"
set gnd_cell [get_cells -quiet $cell_name]
if {[llength $gnd_cell] == 0} {
set gnd_cell [create_cell -reference GND $cell_name]
if {$debug} {puts "DEBUG: Created GND cell: '$gnd_cell'"}
} elseif {[llength $gnd_cell] > 1} {
puts "ERROR: Multiple GND cells found with name '$cell_name'."
exit -1
}
set gnd_pin [get_pins "${gnd_cell}${hier_sep}G"]
if {[llength $gnd_pin] == 0} {
puts "ERROR: No GND pin found on GND cell '$gnd_cell'."
exit -1
} elseif {[llength $gnd_pin] > 1} {
puts "ERROR: Multiple GND pins found on GND cell '$gnd_cell'."
exit -1
}
return $gnd_pin
}
proc find_net_sinks {source_net {should_exist 1}} {
set sink_pins {}
# Iterate through all pins connected to the source net
foreach pin [get_pins -quiet -of_objects $source_net] {
set direction [get_property DIRECTION $pin]
# Input pins of nested cells
if {$direction == "IN"} {
lappend sink_pins $pin
}
# Output pins of the parent cell
set pin_cell [get_cells -of_objects $pin]
set is_primitive [get_property IS_PRIMITIVE $pin_cell]
if {$direction == "OUT" && !$is_primitive} {
lappend sink_pins $pin
}
}
# Add any top-module output ports connected to the source net
foreach port [get_ports -quiet -of_objects $source_net -filter {DIRECTION == "OUT"}] {
lappend sink_pins $port
}
if {[llength $sink_pins] == 0} {
print_error "No sink found for '$source_net'." $should_exist
}
return $sink_pins
}
proc find_matching_nets {cell nets match repl} {
set matching_nets {}
foreach net $nets {
set net_name [str_replace $net $match $repl]
set matching_net [get_cell_net $cell $net_name]
if {$matching_net != ""} {
lappend matching_nets $matching_net
}
}
if {[llength $matching_nets] == 0} {
puts "ERROR: No matching nets found for '$nets'."
exit -1
} elseif {[llength $matching_nets] != [llength $nets]} {
puts "ERROR: Mismatch in number of matching nets."
exit -1
}
return $matching_nets
}
proc find_matching_pins {cell pins match repl} {
set matching_pins {}
foreach pin $pins {
set pin_name [str_replace $pin $match $repl]
set matching_pin [get_cell_pin $cell $pin_name]
if {$matching_pin != ""} {
lappend matching_pins $matching_pin
}
}
if {[llength $matching_pins] == 0} {
puts "ERROR: No matching pins found for '$pins'."
exit -1
} elseif {[llength $matching_pins] != [llength $pins]} {
puts "ERROR: Mismatch in number of matching pins."
exit -1
}
return $matching_pins
}
proc replace_net_source {net source_pin} {
variable debug
foreach pin [find_net_sinks $net 0] {
# disconnect net from pin
disconnect_net -net $net -objects $pin
if {$debug} {puts "DEBUG: Disconnected net '$net' from pin '$pin'."}
# find/create source net
set source_net [get_nets -quiet -of_objects $source_pin]
if {[llength $source_net] == 0} {
# Create a new net (in source_cell's parent) if none exists
set source_cell [get_cells -of_objects $source_pin]
set net_name [unique_net_name "${source_cell}_tmp_net"]
set source_net [create_net $net_name]
if {$debug} {puts "DEBUG: Created source_net: '$source_net'"}
# Connect the source pin to the new net
connect_net -net $source_net -objects $source_pin -hierarchical
if {$debug} {puts "DEBUG: Connected net '$source_net' to pin '$source_pin'."}
} elseif {[llength $source_net] > 1} {
puts "ERROR: Multiple nets connected to pin '$source_pin'."
exit -1
}
set external_net [get_nets -of_objects $pin]
if {[llength $external_net] == 0} {
# Connect pin to source net
connect_net -net $source_net -objects $pin -hierarchical
if {$debug} {puts "DEBUG: Connected net '$source_net' to pin '$pin'."}
} elseif {[llength $external_net] == 1} {
foreach external_pin [get_pins -of_objects $external_net] {
# disconnect external net from pin
disconnect_net -net $external_net -objects $pin
if {$debug} {puts "DEBUG: Disconnected net '$external_net' from pin '$pin'."}
# recurse-connect external net's pins to source_pin
replace_net_source $external_net $source_pin
}
} else {
puts "ERROR: Multiple nets connected to pin '$pin'."
exit -1
}
}
}
proc resolve_async_bram {inst} {
variable debug
puts "INFO: Resolving asynchronous BRAM patch: '$inst'."
set hier_sep [get_hierarchy_separator]
set raddr_w_nets [find_cell_nets $inst "raddr_w(\\\[\\d+\\\])?$"]
set read_s_net [find_cell_net $inst "read_s$"]
if {$debug} {puts "DEBUG: read_s_net: '$read_s_net'"}
set is_raddr_reg_net [find_cell_net $inst "g_async_ram.is_raddr_reg$" 0]
if {$debug} {puts "DEBUG: is_raddr_reg_net: '$is_raddr_reg_net'"}
set raddr_s_nets [find_matching_nets $inst $raddr_w_nets "raddr_w(\\\[\\d+\\\])?$" "raddr_s\\1"]
set reg_next_pins {}
set reg_ce_src_pin ""
set raddr_reset_net [find_cell_net $inst "raddr_reset$" 0]
if {$debug} {puts "DEBUG: raddr_reset: '$raddr_reset_net'"}
# Process each raddr_w net
foreach raddr_w_net $raddr_w_nets {
if {$debug} {puts "DEBUG: Processing raddr_w net: '$raddr_w_net'"}
# Find raddr_w_net's driver pin
set raddr_src_pin [find_net_driver $raddr_w_net]
if {$debug} {puts "DEBUG: raddr_src_pin: '$raddr_src_pin'"}
if {[get_ports -quiet $raddr_src_pin] ne ""} {
puts "WARNING: Net '$raddr_w_net' is not registered, driver_type=port"
break
}
# Get the driver cell
set raddr_src_cell [get_cells -of_objects $raddr_src_pin]
if {[llength $raddr_src_cell] == 0} {
puts "ERROR: No source cell found connected to pin '$raddr_src_pin'."
exit -1
} elseif {[llength $raddr_src_cell] > 1} {
puts "ERROR: Multiple source cells found connected to pin '$raddr_src_pin'."
exit -1
}
# Check driver type
set driver_type [get_property REF_NAME $raddr_src_cell]
if {$driver_type == "FDRE" || $driver_type == "FDSE"} {
if {$debug} {puts "DEBUG: Net '$raddr_w_net' is registered, driver_type='$driver_type'"}
} else {
puts "WARNING: Net '$raddr_w_net' is not registered, driver_type='$driver_type'"
break
}
# Create register next cell and return output pin
set reg_next_pin [create_register_next $inst $raddr_src_cell $raddr_reset_net]
if {$reg_next_pin == ""} {
puts "ERROR: failed to create register next value for '$raddr_src_cell'."
exit -1
}
if {$debug} {puts "DEBUG: reg_next_pin: '$reg_next_pin'"}
lappend reg_next_pins $reg_next_pin
# Find the CE pin on raddr_src_cell
if {$reg_ce_src_pin == ""} {
set reg_ce_pin [get_pins "${raddr_src_cell}${hier_sep}CE"]
if {[llength $reg_ce_pin] == 0} {
puts "ERROR: No CE pin found on register cell '$raddr_src_cell'."
exit -1
} elseif {[llength $reg_ce_pin] > 1} {
puts "ERROR: Multiple CE pins found on register cell '$raddr_src_cell'."
exit -1
}
if {$debug} {puts "DEBUG: reg_ce_pin: '$reg_ce_pin'"}
set reg_ce_src_pin [find_pin_driver $reg_ce_pin]
if {$reg_ce_src_pin == ""} {
puts "ERROR: No source pin found connected to '$reg_ce_pin'."
exit -1
}
if {$debug} {puts "DEBUG: reg_ce_src_pin: '$reg_ce_src_pin'"}
}
}
set addr_width [llength $raddr_w_nets]
# do we have a fully registered read address?
if {[llength $reg_next_pins] == $addr_width} {
if {$debug} {puts "DEBUG: Fully registered read address detected."}
# Connect all reg_next_pins to all input pins attached to raddr_s_nets
for {set addr_idx 0} {$addr_idx < $addr_width} {incr addr_idx} {
set raddr_s_net [lindex $raddr_s_nets $addr_idx]
set reg_next_pin [lindex $reg_next_pins $addr_idx]
if {$debug} {puts "DEBUG: Connecting pin '$reg_next_pin' net to '$raddr_s_net's pins."}
replace_net_source $raddr_s_net $reg_next_pin
}
# Connect reg_ce_src_pin to all input pins attached to read_s_net
if {$debug} {puts "DEBUG: Connecting pin '$reg_ce_src_pin' net to '$read_s_net's pins."}
replace_net_source $read_s_net $reg_ce_src_pin
if {$is_raddr_reg_net != ""} {
# Create Const<1>'s pin
set vcc_pin [getOrCreateVCCPin $inst]
# Connect vcc_pin to all input pins attached to is_raddr_reg_net
if {$debug} {puts "DEBUG: Connecting pin '$vcc_pin' to net '$is_raddr_reg_net's pins."}
replace_net_source $is_raddr_reg_net $vcc_pin
}
} else {
if {$is_raddr_reg_net == ""} {
puts "ERROR: read address not fully registered!"
exit -1
} else {
puts "WARNING: read address not fully registered!"
}
# Create Const<0>'s pin
set gnd_pin [getOrCreateGNDPin $inst]
# Connect GND to all input pins attached to raddr_s_nets
for {set addr_idx 0} {$addr_idx < $addr_width} {incr addr_idx} {
set raddr_s_net [lindex $raddr_s_nets $addr_idx]
if {$debug} {puts "DEBUG: Connecting pin '$gnd_pin' net to '$raddr_s_net's pins."}
replace_net_source $raddr_s_net $gnd_pin
}
# Connect GND to all input pins attached to read_s_net
if {$debug} {puts "DEBUG: Connecting pin '$gnd_pin' net to '$read_s_net's pins."}
replace_net_source $read_s_net $gnd_pin
# Connect gnd_pin to all input pins attached to is_raddr_reg_net
if {$debug} {puts "DEBUG: Connecting pin '$gnd_pin' to net '$is_raddr_reg_net's pins."}
replace_net_source $is_raddr_reg_net $gnd_pin
}
# Remove placeholder cells
foreach cell [find_nested_cells $inst "placeholder1$"] {
remove_cell_from_netlist $cell
}
if {$is_raddr_reg_net != ""} {
foreach cell [find_nested_cells $inst "g_async_ram.placeholder2$"] {
remove_cell_from_netlist $cell
}
}
}
proc resolve_async_brams {} {
variable debug
set bram_patch_cells {}
foreach cell [get_cells -hierarchical -filter {REF_NAME =~ "*VX_async_ram_patch*"}] {
if {$debug} {puts "DEBUG: Found async BRAM patch cell: '$cell'."}
lappend bram_patch_cells $cell
}
if {[llength $bram_patch_cells] != 0} {
foreach cell $bram_patch_cells {
resolve_async_bram $cell
}
} else {
puts "INFO: No async BRAM patch cells found in the design."
}
}
proc dump_async_bram_cells {} {
set bram_patch_cells [get_cells -hierarchical -filter {REF_NAME =~ "*VX_async_ram_patch*"}]
if {[llength $bram_patch_cells] != 0} {
foreach cell $bram_patch_cells {
puts "INFO: Found async BRAM patch cell: '$cell'."
set child_cells [find_cell_descendants $cell]
foreach child $child_cells {
set type [get_property REF_NAME $child]
puts "INFO: child cell: '$child', type: '$type'"
}
}
} else {
puts "INFO: No async BRAM patch cells found in the design."
}
}
}
# Invoke the procedure to resolve async BRAM
vortex::resolve_async_brams
# dump async bram cells
#vortex::dump_async_bram_cells