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]
|
||||
} elseif { $object_type == "Port" } {
|
||||
# Explicit port arg - convert to pin.
|
||||
set pin [find_pin [get_name $arg]]
|
||||
set pin [get_port_pin $arg]
|
||||
set inst [$pin instance]
|
||||
set port [$pin port]
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ proc parse_clk_inst_port_pin_arg { objects clks_var insts_var pins_var } {
|
|||
set ports {}
|
||||
get_object_args $objects clks {} {} {} insts ports pins {} {} {}
|
||||
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 {}
|
||||
get_object_args $objects clks {} {} {} {} ports pins {} {} {}
|
||||
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 {}
|
||||
get_object_args $objects {} {} {} {} insts ports pins {} {} {}
|
||||
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 {}
|
||||
get_object_args $objects {} {} {} {} insts ports pins nets {} {}
|
||||
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 {} {}
|
||||
|
||||
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
|
||||
} elseif { $object_type == "Port" } {
|
||||
# Explicit port arg - convert to pin.
|
||||
set pin [find_pin [get_name $arg]]
|
||||
set pin [get_port_pin $arg]
|
||||
} else {
|
||||
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" } {
|
||||
set pin [find_pin $arg]
|
||||
} else {
|
||||
set pin [$top_instance find_pin [get_name $port]]
|
||||
set pin [get_port_pin $port]
|
||||
}
|
||||
if { $pin == "NULL" } {
|
||||
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 } {
|
||||
set pins {}
|
||||
# Copy backslashes that will be removed by foreach.
|
||||
set arglilst [string map {\\ \\\\} $arglist]
|
||||
set arglist [string map {\\ \\\\} $arglist]
|
||||
foreach arg $arglist {
|
||||
if {[llength $arg] > 1} {
|
||||
# Embedded list.
|
||||
|
|
@ -891,7 +891,7 @@ proc get_port_pins_error { arg_name arglist } {
|
|||
lappend pins $arg
|
||||
} elseif { $object_type == "Port" } {
|
||||
# Convert port to pin.
|
||||
lappend pins [find_pin [get_name $arg]]
|
||||
lappend pins [get_port_pin $arg]
|
||||
} else {
|
||||
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_json1
|
||||
report_json2
|
||||
slash_port_test
|
||||
suppress_msg
|
||||
user_properties
|
||||
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