OpenSTA/tcl/Power.tcl

216 lines
6.8 KiB
Tcl
Raw Normal View History

2018-11-26 18:15:52 +01:00
# OpenSTA, Static Timing Analyzer
2019-01-01 21:26:11 +01:00
# Copyright (c) 2019, 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
################################################################
#
# Power commands.
#
################################################################
namespace eval sta {
define_cmd_args "report_power" \
{ [-instances instances]\
2019-02-16 21:07:59 +01:00
[-corner corner_name]\
2018-11-26 18:15:52 +01:00
[-digits digits]\
[> filename] [>> filename] }
proc_redirect report_power {
global sta_report_default_digits
parse_key_args "report_power" args keys {-instances -corner -digits} flags {} 1
if [info exists keys(-digits)] {
set digits $keys(-digits)
check_positive_integer "-digits" $digits
} else {
set digits $sta_report_default_digits
}
set corner [parse_corner keys]
if { [info exists keys(-instances)] } {
2019-02-17 00:31:39 +01:00
set insts [get_instances_error "-instances" $keys(-instances)]
2019-02-18 19:56:38 +01:00
report_power_insts $insts $corner $digits
2018-11-26 18:15:52 +01:00
} else {
report_power_design $corner $digits
}
}
proc report_power_design { corner digits } {
set power_result [design_power $corner]
2018-12-11 21:34:03 +01:00
set totals [lrange $power_result 0 3]
set sequential [lrange $power_result 4 7]
set combinational [lrange $power_result 8 11]
set macro [lrange $power_result 12 15]
set pad [lrange $power_result 16 end]
2018-12-14 08:53:17 +01:00
lassign $totals design_internal design_switching design_leakage design_total
2019-02-18 19:56:38 +01:00
2019-03-29 22:18:08 +01:00
set field_width [max [expr $digits + 6] 10]
report_power_title5 "Group" "Internal" "Switching" "Leakage" "Total" $field_width
report_power_title5 " " "Power" "Power" "Power" "Power" $field_width
report_title_dashes5 $field_width
report_power_row "Sequential" $sequential $design_total $field_width $digits
report_power_row "Combinational" $combinational $design_total $field_width $digits
report_power_row "Macro" $macro $design_total $field_width $digits
report_power_row "Pad" $pad $design_total $field_width $digits
report_title_dashes5 $field_width
report_power_row "Total" $power_result $design_total $field_width $digits
puts -nonewline [format "%-20s" ""]
report_power_col_percent $design_internal $design_total $field_width
report_power_col_percent $design_switching $design_total $field_width
report_power_col_percent $design_leakage $design_total $field_width
2018-11-26 18:15:52 +01:00
puts ""
}
2019-03-29 22:18:08 +01:00
proc max { x y } {
if { $x >= $y } {
return $x
} else {
return $y
}
}
proc report_power_title5 { title1 title2 title3 title4 title5 field_width } {
puts -nonewline [format "%-20s" $title1]
report_power_title4 $title2 $title3 $title4 $title5 $field_width
}
proc report_power_title4 { title1 title2 title3 title4 field_width } {
puts -nonewline [format " %${field_width}s" $title1]
puts -nonewline [format " %${field_width}s" $title2]
puts -nonewline [format " %${field_width}s" $title3]
puts [format " %${field_width}s" $title4]
}
proc report_title_dashes5 { field_width } {
set count [expr 20 + ($field_width + 1) * 4]
report_title_dashes $count
}
proc report_title_dashes4 { field_width } {
set count [expr ($field_width + 1) * 4]
report_title_dashes $count
}
proc report_title_dashes { count } {
for {set i 0} {$i < $count} {incr i} {
puts -nonewline "-"
}
puts ""
}
proc report_power_row { type row_result design_total field_width digits } {
2018-12-11 21:34:03 +01:00
lassign $row_result internal switching leakage total
2018-12-11 19:47:04 +01:00
if { $design_total == 0.0 } {
set percent 0.0
} else {
set percent [expr $total / $design_total * 100]
}
2018-11-26 18:15:52 +01:00
puts -nonewline [format "%-20s" $type]
2019-03-29 22:18:08 +01:00
report_power_col $internal $field_width $digits
report_power_col $switching $field_width $digits
report_power_col $leakage $field_width $digits
report_power_col $total $field_width $digits
2018-11-26 18:15:52 +01:00
puts [format " %5.1f%%" $percent]
}
2019-03-29 22:18:08 +01:00
proc report_power_col { pwr field_width digits } {
puts -nonewline [format " %$field_width.${digits}e" $pwr]
2018-11-26 18:15:52 +01:00
}
2019-03-29 22:18:08 +01:00
proc report_power_col_percent { col_total total field_width } {
2018-12-11 19:47:04 +01:00
if { $total == 0.0 } {
set percent 0.0
} else {
2018-12-11 21:34:03 +01:00
set percent [expr $col_total / $total * 100]
2018-12-11 19:47:04 +01:00
}
2019-03-29 22:18:08 +01:00
puts -nonewline [format "%$field_width.1f%%" $percent]
2018-11-26 18:15:52 +01:00
}
2019-02-18 19:56:38 +01:00
proc report_power_line { type pwr digits } {
2019-03-29 22:18:08 +01:00
puts [format "%-16s %.${digits}e" $type $pwr]
2019-02-18 19:56:38 +01:00
}
proc report_power_insts { insts corner digits } {
set inst_pwrs {}
foreach inst $insts {
set power_result [instance_power $inst $corner]
lappend inst_pwrs [list $inst $power_result]
}
set inst_pwrs [lsort -command inst_pwr_cmp $inst_pwrs]
2019-02-19 01:24:41 +01:00
2019-03-29 22:18:08 +01:00
set field_width [max [expr $digits + 6] 10]
report_power_title4 "Internal" "Switching" "Leakage" "Total" $field_width
report_power_title4 "Power" "Power" "Power" "Power" $field_width
report_title_dashes4 $field_width
2019-02-19 01:24:41 +01:00
2019-02-18 19:56:38 +01:00
foreach inst_pwr $inst_pwrs {
set inst [lindex $inst_pwr 0]
set power [lindex $inst_pwr 1]
2019-03-29 22:18:08 +01:00
report_power_inst $inst $power $field_width $digits
2019-02-18 19:56:38 +01:00
}
}
proc inst_pwr_cmp { inst_pwr1 inst_pwr2 } {
set pwr1 [lindex $inst_pwr1 1]
set pwr2 [lindex $inst_pwr2 1]
lassign $pwr1 internal1 switching1 leakage1 total1
lassign $pwr2 internal2 switching2 leakage2 total2
if { $total1 < $total2 } {
return 1
} elseif { $total1 == $total2 } {
return 0
} else {
return -1
}
}
2019-03-29 22:18:08 +01:00
proc report_power_inst { inst power_result field_width digits } {
2019-02-19 01:24:41 +01:00
lassign $power_result internal switching leakage total
2019-03-29 22:18:08 +01:00
report_power_col $internal $field_width $digits
report_power_col $switching $field_width $digits
report_power_col $leakage $field_width $digits
report_power_col $total $field_width $digits
2019-02-19 01:24:41 +01:00
puts " [get_full_name $inst]"
2018-11-26 18:15:52 +01:00
}
2019-02-18 19:56:38 +01:00
################################################################
2018-11-26 18:15:52 +01:00
set ::power_default_signal_toggle_rate 0.1
trace variable ::power_default_signal_toggle_rate "rw" \
sta::trace_power_default_signal_toggle_rate
proc trace_power_default_signal_toggle_rate { name1 name2 op } {
global power_default_signal_toggle_rate
if { $op == "r" } {
set power_default_signal_toggle_rate [power_default_signal_toggle_rate]
} elseif { $op == "w" } {
if { [string is double $power_default_signal_toggle_rate] \
&& $power_default_signal_toggle_rate >= 0.0 } {
set_power_default_signal_toggle_rate $power_default_signal_toggle_rate
} else {
sta_error "power_default_signal_toggle_rate must be a positive float."
}
}
}
# sta namespace end.
}