Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 83 additions & 26 deletions power/Power.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ define_cmd_args "report_power" \
[-highest_power_instances count]\
[-corner corner]\
[-digits digits]\
[-format format]\
[> filename] [>> filename] }

proc_redirect report_power {
global sta_report_default_digits

parse_key_args "report_power" args \
keys {-instances -highest_power_instances -corner -digits} flags {}
keys {-instances -highest_power_instances -corner -digits -format} flags {}

check_argc_eq0 "report_power" $args

Expand All @@ -56,16 +57,23 @@ proc_redirect report_power {
}
set corner [parse_corner keys]

if { ![info exists keys(-format)] } {
set keys(-format) "text"
}
if { $keys(-format) != "text" && $keys(-format) != "json" } {
sta_error 311 "unknown power report -format $keys(-format)"
}

if { [info exists keys(-instances)] } {
set insts [get_instances_error "-instances" $keys(-instances)]
report_power_insts $insts $corner $digits
report_power_insts $insts $corner $digits $keys(-format)
} elseif { [info exists keys(-highest_power_instances)] } {
set count $keys(-highest_power_instances)
check_positive_integer "-highest_power_instances" $count
set insts [highest_power_instances $count $corner]
report_power_insts $insts $corner $digits
report_power_insts $insts $corner $digits $keys(-format)
} else {
report_power_design $corner $digits
report_power_design $corner $digits $keys(-format)
}
}

Expand All @@ -79,7 +87,7 @@ proc liberty_libraries_exist {} {
return $have_liberty
}

proc report_power_design { corner digits } {
proc report_power_design { corner digits {report_format "text"} } {
set power_result [design_power $corner]
set totals [lrange $power_result 0 3]
set sequential [lrange $power_result 4 7]
Expand All @@ -90,18 +98,29 @@ proc report_power_design { corner digits } {
lassign $totals design_internal design_switching design_leakage design_total

set field_width [max [expr $digits + 6] 10]
report_power_title5 "Group" "Internal" "Switching" "Leakage" "Total" $field_width
report_power_title5_units " " "Power" "Power" "Power" "Power" "(Watts)" $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 "Clock" $clock $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

report_line "[format %-20s {}][power_col_percent $design_internal $design_total $field_width][power_col_percent $design_switching $design_total $field_width][power_col_percent $design_leakage $design_total $field_width]"
if { $report_format == "text" } {
report_power_title5 "Group" "Internal" "Switching" "Leakage" "Total" $field_width
report_power_title5_units " " "Power" "Power" "Power" "Power" "(Watts)" $field_width
report_title_dashes5 $field_width
} elseif { $report_format == "json" } {
report_line "\{"
}

set last_row_var ""
report_power_row "Sequential" $sequential $design_total $field_width $digits $report_format last_row_var
report_power_row "Combinational" $combinational $design_total $field_width $digits $report_format last_row_var
report_power_row "Clock" $clock $design_total $field_width $digits $report_format last_row_var
report_power_row "Macro" $macro $design_total $field_width $digits $report_format last_row_var
report_power_row "Pad" $pad $design_total $field_width $digits $report_format last_row_var
if { $report_format == "text" } {
report_title_dashes5 $field_width
}
report_power_row "Total" $power_result $design_total $field_width $digits $report_format last_row_var
if { $report_format == "text" } {
report_line "[format %-20s {}][power_col_percent $design_internal $design_total $field_width][power_col_percent $design_switching $design_total $field_width][power_col_percent $design_leakage $design_total $field_width]"
} elseif { $report_format == "json" } {
report_line "\}"
}
}

proc max { x y } {
Expand Down Expand Up @@ -146,14 +165,28 @@ proc report_title_dashes { count } {
report_line $line
}

proc report_power_row { type row_result design_total field_width digits } {
proc report_power_row { type row_result design_total field_width digits {report_format "text"} {last_row_var ""} } {
lassign $row_result internal switching leakage total
if { $design_total == 0.0 || [is_nan $design_total] } {
set percent 0.0
} else {
set percent [expr $total / $design_total * 100]
}
report_line "[format %-20s $type][power_col $internal $field_width $digits][power_col $switching $field_width $digits][power_col $leakage $field_width $digits][power_col $total $field_width $digits] [format %5.1f $percent]%"
if { "$report_format" == "json" } {
upvar_opt 1 $last_row_var last_row
if { $last_row != "" } {
report_line " ,"
}
report_line " \"$type\": {"
report_line " \"internal\":[power_col $internal $field_width $digits],"
report_line " \"switching\":[power_col $switching $field_width $digits],"
report_line " \"leakage\":[power_col $leakage $field_width $digits],"
report_line " \"total\":[power_col $total $field_width $digits]"
report_line " }"
set last_row $type
} else {
report_line "[format %-20s $type][power_col $internal $field_width $digits][power_col $switching $field_width $digits][power_col $leakage $field_width $digits][power_col $total $field_width $digits] [format %5.1f $percent]%"
}
}

proc is_nan { str } {
Expand Down Expand Up @@ -185,7 +218,7 @@ proc report_power_line { type pwr digits } {
}
}

proc report_power_insts { insts corner digits } {
proc report_power_insts { insts corner digits {report_format "text"} } {
set inst_pwrs {}
foreach inst $insts {
set power_result [instance_power $inst $corner]
Expand All @@ -195,14 +228,23 @@ proc report_power_insts { insts corner digits } {

set field_width [max [expr $digits + 6] 10]

report_power_title4 "Internal" "Switching" "Leakage" "Total" $field_width
report_power_title4_units "Power" "Power" "Power" "Power" "(Watts)" $field_width
report_title_dashes4 $field_width
if { $report_format == "text" } {
report_power_title4 "Internal" "Switching" "Leakage" "Total" $field_width
report_power_title4_units "Power" "Power" "Power" "Power" "(Watts)" $field_width
report_title_dashes4 $field_width
} else {
report_line {[}
}

set last_inst_var ""
foreach inst_pwr $inst_pwrs {
set inst [lindex $inst_pwr 0]
set power [lindex $inst_pwr 1]
report_power_inst $inst $power $field_width $digits
report_power_inst $inst $power $field_width $digits $report_format last_inst_var
}

if { $report_format == "json" } {
report_line {]}
}
}

Expand All @@ -220,9 +262,24 @@ proc inst_pwr_cmp { inst_pwr1 inst_pwr2 } {
}
}

proc report_power_inst { inst power_result field_width digits } {
proc report_power_inst { inst power_result field_width digits {report_format "text"} {last_inst_var ""}} {
lassign $power_result internal switching leakage total
report_line "[power_col $internal $field_width $digits][power_col $switching $field_width $digits][power_col $leakage $field_width $digits][power_col $total $field_width $digits] [get_full_name $inst]"
if { $report_format == "json" } {
upvar_opt 1 $last_inst_var last_inst
if { $last_inst != "" } {
report_line ","
}
report_line "{"
report_line " \"name\": \"[get_full_name $inst]\","
report_line " \"internal\":[power_col $internal $field_width $digits],"
report_line " \"switching\":[power_col $switching $field_width $digits],"
report_line " \"leakage\":[power_col $leakage $field_width $digits],"
report_line " \"total\":[power_col $total $field_width $digits]"
report_line "}"
set last_inst $inst
} elseif { $report_format == "text" } {
report_line "[power_col $internal $field_width $digits][power_col $switching $field_width $digits][power_col $leakage $field_width $digits][power_col $total $field_width $digits] [get_full_name $inst]"
}
}

################################################################
Expand Down
11 changes: 11 additions & 0 deletions tcl/Util.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ proc define_hidden_cmd_args { cmd arglist } {
namespace export $cmd
}

# "Optional Upvar"
# If $other_var is not empty, the upvar is executed.
# Otherwise, $my_var is set to empty.
proc upvar_opt { level other_var my_var } {
if { $other_var != "" } {
uplevel 1 "upvar $level $other_var $my_var"
} else {
uplevel 1 "set $my_var \"\""
}
}

################################################################

proc sta_warn { msg_id msg } {
Expand Down
85 changes: 85 additions & 0 deletions test/power_json.ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
Warning: ../examples/gcd_sky130hd.v line 527, module sky130_fd_sc_hd__tapvpwrvgnd_1 not found. Creating black box for TAP_11.
{
"Sequential": {
"internal": 3.0660e-04,
"switching": 4.7564e-05,
"leakage": 2.9607e-10,
"total": 3.5417e-04
}
,
"Combinational": {
"internal": 1.5871e-04,
"switching": 2.0511e-04,
"leakage": 6.8590e-10,
"total": 3.6381e-04
}
,
"Clock": {
"internal": 4.6828e-05,
"switching": 1.2049e-04,
"leakage": 2.3004e-11,
"total": 1.6732e-04
}
,
"Macro": {
"internal": 0.0000e+00,
"switching": 0.0000e+00,
"leakage": 0.0000e+00,
"total": 0.0000e+00
}
,
"Pad": {
"internal": 0.0000e+00,
"switching": 0.0000e+00,
"leakage": 0.0000e+00,
"total": 0.0000e+00
}
,
"Total": {
"internal": 5.1214e-04,
"switching": 3.7316e-04,
"leakage": 1.0050e-09,
"total": 8.8530e-04
}
}
[
{
"name": "clkbuf_2_3__f_clk",
"internal": 9.3880e-06,
"switching": 2.5721e-05,
"leakage": 4.6007e-12,
"total": 3.5109e-05
}
,
{
"name": "clkbuf_2_0__f_clk",
"internal": 9.3814e-06,
"switching": 2.5163e-05,
"leakage": 4.6007e-12,
"total": 3.4544e-05
}
,
{
"name": "clkbuf_2_1__f_clk",
"internal": 9.3672e-06,
"switching": 2.3965e-05,
"leakage": 4.6007e-12,
"total": 3.3332e-05
}
,
{
"name": "clkbuf_2_2__f_clk",
"internal": 9.3592e-06,
"switching": 2.3293e-05,
"leakage": 4.6007e-12,
"total": 3.2652e-05
}
,
{
"name": "clkbuf_0_clk",
"internal": 9.3319e-06,
"switching": 2.2346e-05,
"leakage": 4.6007e-12,
"total": 3.1678e-05
}
]
14 changes: 14 additions & 0 deletions test/power_json.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# report_power gcd
set sta_report_default_digits 4
read_liberty ../examples/sky130hd_tt.lib.gz
read_verilog ../examples/gcd_sky130hd.v
link_design gcd

read_sdc ../examples/gcd_sky130hd.sdc
set_propagated_clock clk
read_spef ../examples/gcd_sky130hd.spef
set_power_activity -input -activity .1
set_power_activity -input_port reset -activity 0

report_power -format json
report_power -format json -instances "[get_cells -filter "name=~clkbuf*"]"
4 changes: 4 additions & 0 deletions test/regression_vars.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,11 @@ record_sta_tests {
package_require
path_group_names
prima3
<<<<<<< HEAD
report_checks_sorted
=======
power_json
>>>>>>> a4e3726b (JSON power reports)
report_checks_src_attr
report_json1
report_json2
Expand Down