Fix port-to-pin conversion for names containing slashes. (#463)
Use get_port_pin instead of find_pin on the port leaf name so escaped hierarchical port names like level1/level2/level3 resolve correctly. Also fix arglilst typo in get_port_pins_error. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d0526b524b
commit
3f4b337e30
|
|
@ -108,7 +108,7 @@ proc parse_connect_pin { arg } {
|
||||||
set port [$pin port]
|
set port [$pin port]
|
||||||
} elseif { $object_type == "Port" } {
|
} elseif { $object_type == "Port" } {
|
||||||
# Explicit port arg - convert to pin.
|
# Explicit port arg - convert to pin.
|
||||||
set pin [find_pin [get_name $arg]]
|
set pin [get_port_pin $arg]
|
||||||
set inst [$pin instance]
|
set inst [$pin instance]
|
||||||
set port [$pin port]
|
set port [$pin port]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ proc parse_clk_inst_port_pin_arg { objects clks_var insts_var pins_var } {
|
||||||
set ports {}
|
set ports {}
|
||||||
get_object_args $objects clks {} {} {} insts ports pins {} {} {}
|
get_object_args $objects clks {} {} {} insts ports pins {} {} {}
|
||||||
foreach port $ports {
|
foreach port $ports {
|
||||||
lappend pins [[top_instance] find_pin [get_name $port]]
|
lappend pins [get_port_pin $port]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,7 +238,7 @@ proc parse_clk_port_pin_arg { objects clks_var pins_var } {
|
||||||
set ports {}
|
set ports {}
|
||||||
get_object_args $objects clks {} {} {} {} ports pins {} {} {}
|
get_object_args $objects clks {} {} {} {} ports pins {} {} {}
|
||||||
foreach port $ports {
|
foreach port $ports {
|
||||||
lappend pins [[top_instance] find_pin [get_name $port]]
|
lappend pins [get_port_pin $port]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,7 +325,7 @@ proc parse_inst_port_pin_arg { objects insts_var pins_var } {
|
||||||
set ports {}
|
set ports {}
|
||||||
get_object_args $objects {} {} {} {} insts ports pins {} {} {}
|
get_object_args $objects {} {} {} {} insts ports pins {} {} {}
|
||||||
foreach port $ports {
|
foreach port $ports {
|
||||||
lappend pins [[top_instance] find_pin [get_name $port]]
|
lappend pins [get_port_pin $port]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,7 +347,7 @@ proc parse_inst_port_pin_net_arg { objects insts_var pins_var nets_var } {
|
||||||
set nets {}
|
set nets {}
|
||||||
get_object_args $objects {} {} {} {} insts ports pins nets {} {}
|
get_object_args $objects {} {} {} {} insts ports pins nets {} {}
|
||||||
foreach port $ports {
|
foreach port $ports {
|
||||||
lappend pins [[top_instance] find_pin [get_name $port]]
|
lappend pins [get_port_pin $port]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -368,7 +368,7 @@ proc parse_port_pin_net_arg { objects pins_var nets_var } {
|
||||||
get_object_args $objects {} {} {} {} {} ports pins nets {} {}
|
get_object_args $objects {} {} {} {} {} ports pins nets {} {}
|
||||||
|
|
||||||
foreach port $ports {
|
foreach port $ports {
|
||||||
lappend pins [[top_instance] find_pin [get_name $port]]
|
lappend pins [get_port_pin $port]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -857,7 +857,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
|
||||||
set pin $arg
|
set pin $arg
|
||||||
} elseif { $object_type == "Port" } {
|
} elseif { $object_type == "Port" } {
|
||||||
# Explicit port arg - convert to pin.
|
# Explicit port arg - convert to pin.
|
||||||
set pin [find_pin [get_name $arg]]
|
set pin [get_port_pin $arg]
|
||||||
} else {
|
} else {
|
||||||
sta_warn_error 129 $warn_error "$arg_name type '$object_type' is not a pin or port."
|
sta_warn_error 129 $warn_error "$arg_name type '$object_type' is not a pin or port."
|
||||||
}
|
}
|
||||||
|
|
@ -868,7 +868,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
|
||||||
if { $port == "NULL" } {
|
if { $port == "NULL" } {
|
||||||
set pin [find_pin $arg]
|
set pin [find_pin $arg]
|
||||||
} else {
|
} else {
|
||||||
set pin [$top_instance find_pin [get_name $port]]
|
set pin [get_port_pin $port]
|
||||||
}
|
}
|
||||||
if { $pin == "NULL" } {
|
if { $pin == "NULL" } {
|
||||||
sta_warn_error 130 $warn_error "pin $arg not found."
|
sta_warn_error 130 $warn_error "pin $arg not found."
|
||||||
|
|
@ -880,7 +880,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
|
||||||
proc get_port_pins_error { arg_name arglist } {
|
proc get_port_pins_error { arg_name arglist } {
|
||||||
set pins {}
|
set pins {}
|
||||||
# Copy backslashes that will be removed by foreach.
|
# Copy backslashes that will be removed by foreach.
|
||||||
set arglilst [string map {\\ \\\\} $arglist]
|
set arglist [string map {\\ \\\\} $arglist]
|
||||||
foreach arg $arglist {
|
foreach arg $arglist {
|
||||||
if {[llength $arg] > 1} {
|
if {[llength $arg] > 1} {
|
||||||
# Embedded list.
|
# Embedded list.
|
||||||
|
|
@ -891,7 +891,7 @@ proc get_port_pins_error { arg_name arglist } {
|
||||||
lappend pins $arg
|
lappend pins $arg
|
||||||
} elseif { $object_type == "Port" } {
|
} elseif { $object_type == "Port" } {
|
||||||
# Convert port to pin.
|
# Convert port to pin.
|
||||||
lappend pins [find_pin [get_name $arg]]
|
lappend pins [get_port_pin $arg]
|
||||||
} else {
|
} else {
|
||||||
sta_error 131 "$arg_name type '$object_type' is not a pin or port."
|
sta_error 131 "$arg_name type '$object_type' is not a pin or port."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ record_public_tests {
|
||||||
report_checks_src_attr
|
report_checks_src_attr
|
||||||
report_json1
|
report_json1
|
||||||
report_json2
|
report_json2
|
||||||
|
slash_port_test
|
||||||
suppress_msg
|
suppress_msg
|
||||||
user_properties
|
user_properties
|
||||||
vcd_begin_end_time
|
vcd_begin_end_time
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
get_ports *
|
||||||
|
a/b
|
||||||
|
level1/Y
|
||||||
|
level1/level2/level3
|
||||||
|
out
|
||||||
|
all_inputs
|
||||||
|
a/b
|
||||||
|
level1/Y
|
||||||
|
level1/level2/level3
|
||||||
|
all_outputs
|
||||||
|
out
|
||||||
|
get_pins *
|
||||||
|
a/A
|
||||||
|
a/Y
|
||||||
|
level1/A
|
||||||
|
level1/Y
|
||||||
|
u3/A
|
||||||
|
u3/B
|
||||||
|
u3/Y
|
||||||
|
u4/A
|
||||||
|
u4/Y
|
||||||
|
get_cells *
|
||||||
|
a
|
||||||
|
level1
|
||||||
|
u3
|
||||||
|
u4
|
||||||
|
get_nets *
|
||||||
|
a/b
|
||||||
|
and_out
|
||||||
|
buf_out
|
||||||
|
buf_out2
|
||||||
|
level1/Y
|
||||||
|
level1/level2/level3
|
||||||
|
out
|
||||||
|
get_ports * -filter direction==input
|
||||||
|
a/b
|
||||||
|
level1/Y
|
||||||
|
level1/level2/level3
|
||||||
|
get_ports * -filter direction==output
|
||||||
|
out
|
||||||
|
set_input_delay -clock clk 0 [all_inputs]
|
||||||
|
set_input_delay -clock clk 0 <Port 'level1/level2/level3'>
|
||||||
|
set_input_delay -clock clk 0 <Port 'a/b'>
|
||||||
|
set_input_delay -clock clk 0 <Port 'level1/Y'>
|
||||||
|
set_false_path -from [all_inputs] -to [all_outputs]
|
||||||
|
set_data_check -from <Port 'level1/level2/level3'> -to <Port 'a/b'> 0
|
||||||
|
set_case_analysis 0 <Port 'level1/level2/level3'>
|
||||||
|
set_case_analysis 0 <Port 'a/b'>
|
||||||
|
set_case_analysis 0 <Port 'level1/Y'>
|
||||||
|
report_checks
|
||||||
|
No paths found.
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Test: ports with escaped names containing slashes
|
||||||
|
# Exercises Port-to-Pin conversion paths with escaped Verilog identifiers
|
||||||
|
# like \level1/level2/level3 that contain hierarchy separators
|
||||||
|
read_liberty asap7_small.lib.gz
|
||||||
|
read_verilog slash_port_test.v
|
||||||
|
link_design slash_port_test
|
||||||
|
|
||||||
|
create_clock -name clk -period 500 [get_ports out]
|
||||||
|
|
||||||
|
puts {get_ports *}
|
||||||
|
report_object_full_names [get_ports *]
|
||||||
|
|
||||||
|
puts {all_inputs}
|
||||||
|
report_object_full_names [all_inputs]
|
||||||
|
|
||||||
|
puts {all_outputs}
|
||||||
|
report_object_full_names [all_outputs]
|
||||||
|
|
||||||
|
puts {get_pins *}
|
||||||
|
report_object_full_names [get_pins *]
|
||||||
|
|
||||||
|
puts {get_cells *}
|
||||||
|
report_object_full_names [get_cells *]
|
||||||
|
|
||||||
|
puts {get_nets *}
|
||||||
|
report_object_full_names [get_nets *]
|
||||||
|
|
||||||
|
puts {get_ports * -filter direction==input}
|
||||||
|
report_object_full_names [get_ports * -filter {direction == input}]
|
||||||
|
|
||||||
|
puts {get_ports * -filter direction==output}
|
||||||
|
report_object_full_names [get_ports * -filter {direction == output}]
|
||||||
|
|
||||||
|
# get_port_pins_error: Port objects via set_input_delay [all_inputs]
|
||||||
|
puts {set_input_delay -clock clk 0 [all_inputs]}
|
||||||
|
set_input_delay -clock clk 0 [all_inputs]
|
||||||
|
|
||||||
|
# get_port_pins_error: individual Port objects
|
||||||
|
foreach port [all_inputs] {
|
||||||
|
puts "set_input_delay -clock clk 0 <Port '[get_name $port]'>"
|
||||||
|
set_input_delay -clock clk 0 $port
|
||||||
|
}
|
||||||
|
|
||||||
|
# parse_clk_inst_port_pin_arg: Port objects via set_false_path
|
||||||
|
puts {set_false_path -from [all_inputs] -to [all_outputs]}
|
||||||
|
set_false_path -from [all_inputs] -to [all_outputs]
|
||||||
|
|
||||||
|
# get_port_pin_error (singular): set_data_check with Port objects
|
||||||
|
set input_ports [all_inputs]
|
||||||
|
set from_port [lindex $input_ports 0]
|
||||||
|
set to_port [lindex $input_ports 1]
|
||||||
|
puts "set_data_check -from <Port '[get_name $from_port]'> -to <Port '[get_name $to_port]'> 0"
|
||||||
|
set_data_check -from $from_port -to $to_port 0
|
||||||
|
|
||||||
|
# get_port_pin_error (singular): set_case_analysis with Port objects
|
||||||
|
foreach port [all_inputs] {
|
||||||
|
puts "set_case_analysis 0 <Port '[get_name $port]'>"
|
||||||
|
set_case_analysis 0 $port
|
||||||
|
}
|
||||||
|
|
||||||
|
puts {report_checks}
|
||||||
|
report_checks
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
module slash_port_test (
|
||||||
|
\level1/level2/level3 ,
|
||||||
|
\a/b ,
|
||||||
|
\level1/Y ,
|
||||||
|
out
|
||||||
|
);
|
||||||
|
input \level1/level2/level3 ;
|
||||||
|
input \a/b ;
|
||||||
|
input \level1/Y ;
|
||||||
|
output out;
|
||||||
|
|
||||||
|
wire buf_out, buf_out2, and_out;
|
||||||
|
|
||||||
|
// Instance named "level1" — collides with the prefix of port \level1/level2/level3
|
||||||
|
BUFx2_ASAP7_75t_R level1 (.A(\level1/level2/level3 ), .Y(buf_out));
|
||||||
|
// Instance named "a" — collides with the prefix of port \a/b
|
||||||
|
BUFx2_ASAP7_75t_R a (.A(\a/b ), .Y(buf_out2));
|
||||||
|
AND2x2_ASAP7_75t_R u3 (.A(buf_out), .B(buf_out2), .Y(and_out));
|
||||||
|
BUFx2_ASAP7_75t_R u4 (.A(and_out), .Y(out));
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue