2018-11-26 18:15:52 +01:00
|
|
|
# OpenSTA, Static Timing Analyzer
|
2025-01-22 02:54:33 +01:00
|
|
|
# Copyright (c) 2025, Parallax Software, Inc.
|
2018-11-26 18:15:52 +01:00
|
|
|
#
|
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2022-01-04 18:17:08 +01:00
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2018-11-26 18:15:52 +01:00
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
2022-01-04 18:17:08 +01:00
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2025-01-22 02:54:33 +01:00
|
|
|
#
|
|
|
|
|
# The origin of this software must not be misrepresented; you must not
|
|
|
|
|
# claim that you wrote the original software.
|
|
|
|
|
#
|
|
|
|
|
# Altered source versions must be plainly marked as such, and must not be
|
|
|
|
|
# misrepresented as being the original software.
|
|
|
|
|
#
|
|
|
|
|
# This notice may not be removed or altered from any source distribution.
|
2018-11-26 18:15:52 +01:00
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
|
#
|
|
|
|
|
# Power commands.
|
|
|
|
|
#
|
|
|
|
|
################################################################
|
|
|
|
|
|
|
|
|
|
namespace eval sta {
|
|
|
|
|
|
|
|
|
|
define_cmd_args "report_power" \
|
|
|
|
|
{ [-instances instances]\
|
2025-02-04 18:10:48 +01:00
|
|
|
[-highest_power_instances count]\
|
2026-01-04 01:59:35 +01:00
|
|
|
[-scene scene]\
|
2018-11-26 18:15:52 +01:00
|
|
|
[-digits digits]\
|
2025-12-20 17:13:15 +01:00
|
|
|
[-format format]\
|
2018-11-26 18:15:52 +01:00
|
|
|
[> filename] [>> filename] }
|
|
|
|
|
|
|
|
|
|
proc_redirect report_power {
|
|
|
|
|
global sta_report_default_digits
|
|
|
|
|
|
2022-10-28 04:26:25 +02:00
|
|
|
parse_key_args "report_power" args \
|
2026-01-04 01:59:35 +01:00
|
|
|
keys {-instances -highest_power_instances -corner -scene -format -digits}\
|
|
|
|
|
flags {}
|
2018-11-26 18:15:52 +01:00
|
|
|
|
2022-10-29 03:10:29 +02:00
|
|
|
check_argc_eq0 "report_power" $args
|
2024-07-18 23:46:30 +02:00
|
|
|
|
|
|
|
|
if { ![liberty_libraries_exist] } {
|
|
|
|
|
sta_error 304 "No liberty libraries have been read."
|
|
|
|
|
}
|
2019-04-29 17:39:05 +02:00
|
|
|
if { [info exists keys(-digits)] } {
|
2018-11-26 18:15:52 +01:00
|
|
|
set digits $keys(-digits)
|
|
|
|
|
check_positive_integer "-digits" $digits
|
|
|
|
|
} else {
|
|
|
|
|
set digits $sta_report_default_digits
|
|
|
|
|
}
|
2026-01-04 01:59:35 +01:00
|
|
|
set scene [parse_scene keys]
|
2018-11-26 18:15:52 +01:00
|
|
|
|
2025-12-20 17:13:15 +01:00
|
|
|
if { [info exists keys(-format)] } {
|
|
|
|
|
set format $keys(-format)
|
|
|
|
|
if { $format != "text" && $format != "json" } {
|
|
|
|
|
sta_error 311 "unknown power report -format $format"
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
set format "text"
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-26 18:15:52 +01:00
|
|
|
if { [info exists keys(-instances)] } {
|
2019-02-17 00:31:39 +01:00
|
|
|
set insts [get_instances_error "-instances" $keys(-instances)]
|
2025-12-20 17:13:15 +01:00
|
|
|
if { $format == "json" } {
|
2026-01-04 01:59:35 +01:00
|
|
|
report_power_insts_json $insts $scene $digits
|
2025-12-20 17:13:15 +01:00
|
|
|
} else {
|
2026-01-04 01:59:35 +01:00
|
|
|
report_power_insts $insts $scene $digits
|
2025-12-20 17:13:15 +01:00
|
|
|
}
|
2025-02-04 18:10:48 +01:00
|
|
|
} elseif { [info exists keys(-highest_power_instances)] } {
|
|
|
|
|
set count $keys(-highest_power_instances)
|
|
|
|
|
check_positive_integer "-highest_power_instances" $count
|
2026-01-04 01:59:35 +01:00
|
|
|
set insts [highest_power_instances $count $scene]
|
2025-12-20 17:13:15 +01:00
|
|
|
if { $format == "json" } {
|
2026-01-04 01:59:35 +01:00
|
|
|
report_power_insts_json $insts $scene $digits
|
2025-12-20 17:13:15 +01:00
|
|
|
} else {
|
2026-01-04 01:59:35 +01:00
|
|
|
report_power_insts $insts $scene $digits
|
2025-12-20 17:13:15 +01:00
|
|
|
}
|
2018-11-26 18:15:52 +01:00
|
|
|
} else {
|
2025-12-20 17:13:15 +01:00
|
|
|
if { $format == "json" } {
|
2026-01-04 01:59:35 +01:00
|
|
|
report_power_design_json $scene $digits
|
2025-12-20 17:13:15 +01:00
|
|
|
} else {
|
2026-01-04 01:59:35 +01:00
|
|
|
report_power_design $scene $digits
|
2025-12-20 17:13:15 +01:00
|
|
|
}
|
2018-11-26 18:15:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-18 23:46:30 +02:00
|
|
|
proc liberty_libraries_exist {} {
|
|
|
|
|
set lib_iter [liberty_library_iterator]
|
|
|
|
|
set have_liberty 0
|
|
|
|
|
if { [$lib_iter has_next] } {
|
|
|
|
|
set have_liberty 1
|
|
|
|
|
}
|
|
|
|
|
$lib_iter finish
|
|
|
|
|
return $have_liberty
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-18 19:56:38 +01:00
|
|
|
################################################################
|
2018-11-26 18:15:52 +01:00
|
|
|
|
2019-04-29 17:39:05 +02:00
|
|
|
define_cmd_args "set_power_activity" { [-global]\
|
2026-01-04 01:59:35 +01:00
|
|
|
[-input]\
|
|
|
|
|
[-input_ports ports]\
|
|
|
|
|
[-pins pins]\
|
|
|
|
|
[-activity activity | -density density]\
|
|
|
|
|
[-duty duty]\
|
2025-01-17 21:02:13 +01:00
|
|
|
[-clock clock]}
|
2019-04-29 17:39:05 +02:00
|
|
|
|
|
|
|
|
proc set_power_activity { args } {
|
|
|
|
|
parse_key_args "set_power_activity" args \
|
2025-01-17 21:02:13 +01:00
|
|
|
keys {-input_ports -pins -activity -density -duty -clock} \
|
2022-10-28 04:26:25 +02:00
|
|
|
flags {-global -input}
|
2019-04-29 17:39:05 +02:00
|
|
|
|
2022-10-29 03:10:29 +02:00
|
|
|
check_argc_eq0 "set_power_activity" $args
|
2025-01-17 21:02:13 +01:00
|
|
|
if { [info exists keys(-activity)] && [info exists keys(-density)] \
|
|
|
|
|
|| ![info exists keys(-activity)] && ![info exists keys(-density)] } {
|
|
|
|
|
sta_error 306 "Specify -activity or -density."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set density 0.0
|
2019-04-29 17:39:05 +02:00
|
|
|
if { [info exists keys(-activity)] } {
|
|
|
|
|
set activity $keys(-activity)
|
2025-01-17 21:02:13 +01:00
|
|
|
check_positive_float "activity" $activity
|
|
|
|
|
if { [info exists keys(-clock)] } {
|
|
|
|
|
set clk [get_clock_warn "-clock" $keys(-clock)]
|
|
|
|
|
} else {
|
|
|
|
|
set clks [get_clocks]
|
|
|
|
|
if { $clks == {} } {
|
|
|
|
|
sta_error 307 "-activity requires a clock to be defined"
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-04 01:59:35 +01:00
|
|
|
set density [expr $activity / [clock_min_period [sta::cmd_mode]]]
|
2025-01-17 21:02:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if { [info exists keys(-density)] } {
|
|
|
|
|
set density $keys(-density)
|
|
|
|
|
check_positive_float "density" $density
|
|
|
|
|
set density [expr $density / [time_ui_sta 1.0]]
|
|
|
|
|
if { [info exists keys(-clock)] } {
|
2025-02-12 18:33:13 +01:00
|
|
|
sta_warn 308 "-clock ignored for -density"
|
2019-04-29 17:39:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set duty 0.5
|
|
|
|
|
if { [info exists keys(-duty)] } {
|
|
|
|
|
set duty $keys(-duty)
|
|
|
|
|
check_float "duty" $duty
|
2025-09-30 03:23:59 +02:00
|
|
|
if { $duty < 0.0 || $duty > 1.0 } {
|
2025-02-12 18:33:13 +01:00
|
|
|
sta_error 309 "duty should be 0.0 to 1.0"
|
2019-04-29 17:39:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-11-26 18:15:52 +01:00
|
|
|
|
2019-04-29 17:39:05 +02:00
|
|
|
if { [info exists flags(-global)] } {
|
2025-01-17 21:02:13 +01:00
|
|
|
set_power_global_activity $density $duty
|
2019-04-29 17:39:05 +02:00
|
|
|
}
|
|
|
|
|
if { [info exists flags(-input)] } {
|
2025-01-17 21:02:13 +01:00
|
|
|
set_power_input_activity $density $duty
|
2019-04-29 17:39:05 +02:00
|
|
|
}
|
|
|
|
|
if { [info exists keys(-input_ports)] } {
|
|
|
|
|
set ports [get_ports_error "input_ports" $keys(-input_ports)]
|
|
|
|
|
foreach port $ports {
|
2025-12-20 19:45:48 +01:00
|
|
|
if { [get_property $port "direction"] == "input" } {
|
2026-01-04 01:59:35 +01:00
|
|
|
if { [is_clock_src [sta::get_port_pin $port]] } {
|
2025-06-25 16:56:26 +02:00
|
|
|
sta_warn 310 "activity cannot be set on clock ports."
|
2022-12-29 00:30:08 +01:00
|
|
|
} else {
|
2025-01-17 21:02:13 +01:00
|
|
|
set_power_input_port_activity $port $density $duty
|
2022-12-29 00:30:08 +01:00
|
|
|
}
|
2019-04-29 17:39:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if { [info exists keys(-pins)] } {
|
2020-08-05 16:23:38 +02:00
|
|
|
set pins [get_pins $keys(-pins)]
|
2019-04-29 17:39:05 +02:00
|
|
|
foreach pin $pins {
|
2025-01-17 21:02:13 +01:00
|
|
|
set_power_pin_activity $pin $density $duty
|
2018-11-26 18:15:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 00:12:32 +02:00
|
|
|
################################################################
|
|
|
|
|
|
2025-06-25 16:56:26 +02:00
|
|
|
define_cmd_args "unset_power_activity" { [-global]\
|
|
|
|
|
[-input]\
|
|
|
|
|
[-input_ports ports]\
|
|
|
|
|
[-pins pins]\
|
|
|
|
|
[-clock clock]}
|
|
|
|
|
|
|
|
|
|
proc unset_power_activity { args } {
|
|
|
|
|
parse_key_args "unset_power_activity" args \
|
|
|
|
|
keys {-input_ports -pins -clock} \
|
|
|
|
|
flags {-global -input}
|
|
|
|
|
|
|
|
|
|
check_argc_eq0 "unset_power_activity" $args
|
|
|
|
|
|
|
|
|
|
if { [info exists flags(-global)] } {
|
|
|
|
|
unset_power_global_activity
|
|
|
|
|
}
|
|
|
|
|
if { [info exists flags(-input)] } {
|
|
|
|
|
unset_power_input_activity
|
|
|
|
|
}
|
|
|
|
|
if { [info exists keys(-input_ports)] } {
|
|
|
|
|
set ports [get_ports_error "input_ports" $keys(-input_ports)]
|
|
|
|
|
foreach port $ports {
|
|
|
|
|
if { [get_property $port "direction"] == "input" } {
|
2026-01-04 01:59:35 +01:00
|
|
|
if { [is_clock_src [sta::get_port_pin $port]] } {
|
2025-06-25 16:56:26 +02:00
|
|
|
sta_warn 303 "activity cannot be set on clock ports."
|
|
|
|
|
} else {
|
|
|
|
|
unset_power_input_port_activity $port
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if { [info exists keys(-pins)] } {
|
|
|
|
|
set pins [get_pins $keys(-pins)]
|
|
|
|
|
foreach pin $pins {
|
|
|
|
|
unset_power_pin_activity $pin
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
|
|
2024-12-31 22:59:20 +01:00
|
|
|
# Deprecated 9/2024
|
2022-10-30 21:26:16 +01:00
|
|
|
define_cmd_args "read_power_activities" { [-scope scope] -vcd filename }
|
2022-10-28 04:26:25 +02:00
|
|
|
|
|
|
|
|
proc read_power_activities { args } {
|
|
|
|
|
parse_key_args "read_power_activities" args \
|
2022-10-30 21:26:16 +01:00
|
|
|
keys {-scope} flags {-vcd}
|
2022-10-28 04:26:25 +02:00
|
|
|
|
2022-10-29 03:10:29 +02:00
|
|
|
check_argc_eq1 "set_power_activity" $args
|
2022-10-28 04:26:25 +02:00
|
|
|
set filename [file nativename [lindex $args 0]]
|
2022-10-30 21:26:16 +01:00
|
|
|
set scope ""
|
|
|
|
|
if { [info exists keys(-scope)] } {
|
|
|
|
|
set scope $keys(-scope)
|
|
|
|
|
}
|
2024-10-24 20:37:07 +02:00
|
|
|
sta_warn 305 "read_power_activities is deprecated. Use read_vcd."
|
2024-09-24 03:04:26 +02:00
|
|
|
read_vcd_file $filename $scope
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
|
|
2026-01-04 01:59:35 +01:00
|
|
|
define_cmd_args "read_vcd" { [-scope scope] [-mode mode_name] filename }
|
2024-09-24 03:04:26 +02:00
|
|
|
|
|
|
|
|
proc read_vcd { args } {
|
|
|
|
|
parse_key_args "read_vcd" args \
|
2026-01-04 01:59:35 +01:00
|
|
|
keys {-scope -mode_name} flags {}
|
2024-09-24 03:04:26 +02:00
|
|
|
|
|
|
|
|
check_argc_eq1 "read_vcd" $args
|
|
|
|
|
set filename [file nativename [lindex $args 0]]
|
|
|
|
|
set scope ""
|
|
|
|
|
if { [info exists keys(-scope)] } {
|
|
|
|
|
set scope $keys(-scope)
|
|
|
|
|
}
|
2026-01-04 01:59:35 +01:00
|
|
|
set mode_name [sta::cmd_mode]
|
|
|
|
|
if { [info exists keys(-mode)] } {
|
|
|
|
|
set mode_name $keys(-mode)
|
|
|
|
|
}
|
|
|
|
|
read_vcd_file $filename $scope $mode_name
|
2024-09-24 03:04:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
|
|
|
|
|
|
define_cmd_args "read_saif" { [-scope scope] filename }
|
|
|
|
|
|
|
|
|
|
proc read_saif { args } {
|
|
|
|
|
parse_key_args "read_saif" args keys {-scope} flags {}
|
|
|
|
|
|
|
|
|
|
check_argc_eq1 "read_saif" $args
|
|
|
|
|
set filename [file nativename [lindex $args 0]]
|
|
|
|
|
set scope ""
|
|
|
|
|
if { [info exists keys(-scope)] } {
|
|
|
|
|
set scope $keys(-scope)
|
|
|
|
|
}
|
|
|
|
|
read_saif_file $filename $scope
|
2022-10-28 04:26:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
################################################################
|
2022-10-28 00:12:32 +02:00
|
|
|
|
2025-01-16 00:20:21 +01:00
|
|
|
define_cmd_args "report_activity_annotation" { [-report_unannotated] \
|
|
|
|
|
[-report_annotated] }
|
|
|
|
|
|
|
|
|
|
proc_redirect report_activity_annotation {
|
|
|
|
|
parse_key_args "report_activity_annotation" args \
|
|
|
|
|
keys {} flags {-report_unannotated -report_annotated}
|
|
|
|
|
check_argc_eq0 "report_activity_annotation" $args
|
|
|
|
|
set report_unannotated [info exists flags(-report_unannotated)]
|
|
|
|
|
set report_annotated [info exists flags(-report_annotated)];
|
|
|
|
|
report_activity_annotation_cmd $report_unannotated $report_annotated
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
################################################################
|
|
|
|
|
|
2020-05-06 17:09:15 +02:00
|
|
|
proc power_find_nan { } {
|
2026-01-04 01:59:35 +01:00
|
|
|
set scene [cmd_scene]
|
2020-05-06 17:09:15 +02:00
|
|
|
foreach inst [network_leaf_instances] {
|
2026-01-04 01:59:35 +01:00
|
|
|
set power_result [instance_power $inst $scene]
|
2020-05-06 17:09:15 +02:00
|
|
|
lassign $power_result internal switching leakage total
|
|
|
|
|
if { [is_nan $internal] || [is_nan $switching] || [is_nan $leakage] } {
|
2020-12-26 01:55:46 +01:00
|
|
|
report_line "[get_full_name $inst] $internal $switching $leakage"
|
2020-05-06 17:09:15 +02:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-04 01:59:35 +01:00
|
|
|
proc is_nan { str } {
|
|
|
|
|
return [string match "*NaN" $str]
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-26 18:15:52 +01:00
|
|
|
# sta namespace end.
|
|
|
|
|
}
|