Report power as JSON (#342)

* fix power_json.tcl

* get rid of the if/else statements throughout
This commit is contained in:
nataliakokoromyti 2025-12-20 18:13:15 +02:00 committed by GitHub
parent 1bf9426e96
commit 56e4bd8ce1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 125 additions and 5 deletions

View File

@ -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
@ -56,16 +57,37 @@ proc_redirect report_power {
}
set corner [parse_corner keys]
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"
}
if { [info exists keys(-instances)] } {
set insts [get_instances_error "-instances" $keys(-instances)]
report_power_insts $insts $corner $digits
if { $format == "json" } {
report_power_insts_json $insts $corner $digits
} else {
report_power_insts $insts $corner $digits
}
} 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
if { $format == "json" } {
report_power_insts_json $insts $corner $digits
} else {
report_power_insts $insts $corner $digits
}
} else {
report_power_design $corner $digits
if { $format == "json" } {
report_power_design_json $corner $digits
} else {
report_power_design $corner $digits
}
}
}
@ -104,6 +126,35 @@ proc report_power_design { corner 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]"
}
proc report_power_design_json { corner digits } {
set power_result [design_power $corner]
set totals [lrange $power_result 0 3]
set sequential [lrange $power_result 4 7]
set combinational [lrange $power_result 8 11]
set clock [lrange $power_result 12 15]
set macro [lrange $power_result 16 19]
set pad [lrange $power_result 20 end]
report_line "\{"
report_power_row_json "Sequential" $sequential $digits ","
report_power_row_json "Combinational" $combinational $digits ","
report_power_row_json "Clock" $clock $digits ","
report_power_row_json "Macro" $macro $digits ","
report_power_row_json "Pad" $pad $digits ","
report_power_row_json "Total" $totals $digits ""
report_line "\}"
}
proc report_power_row_json { name row_result digits separator } {
lassign $row_result internal switching leakage total
report_line " \"$name\": \{"
report_line " \"internal\": [format %.${digits}e $internal],"
report_line " \"switching\": [format %.${digits}e $switching],"
report_line " \"leakage\": [format %.${digits}e $leakage],"
report_line " \"total\": [format %.${digits}e $total]"
report_line " \}$separator"
}
proc max { x y } {
if { $x >= $y } {
return $x
@ -206,6 +257,40 @@ proc report_power_insts { insts corner digits } {
}
}
proc report_power_insts_json { 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]
report_line "\["
set first 1
foreach inst_pwr $inst_pwrs {
set inst [lindex $inst_pwr 0]
set power [lindex $inst_pwr 1]
if { !$first } {
report_line ","
}
set first 0
report_power_inst_json $inst $power $digits
}
report_line "\]"
}
proc report_power_inst_json { inst power digits } {
lassign $power internal switching leakage total
set inst_name [get_full_name $inst]
report_line "\{"
report_line " \"name\": \"$inst_name\","
report_line " \"internal\": [format %.${digits}e $internal],"
report_line " \"switching\": [format %.${digits}e $switching],"
report_line " \"leakage\": [format %.${digits}e $leakage],"
report_line " \"total\": [format %.${digits}e $total]"
report_line "\}"
}
proc inst_pwr_cmp { inst_pwr1 inst_pwr2 } {
set pwr1 [lindex $inst_pwr1 1]
set pwr2 [lindex $inst_pwr2 1]
@ -287,7 +372,7 @@ proc set_power_activity { args } {
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" } {
if { [get_property $port "direction"] == "input" || [get_property $port "direction"] == "in" } {
if { [is_clock_src [sta::get_port_pin $port]] } {
sta_warn 310 "activity cannot be set on clock ports."
} else {

View File

@ -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 } {

24
test/power_json.tcl Normal file
View File

@ -0,0 +1,24 @@
# report_power reg1_asap7
set sta_report_default_digits 4
read_liberty ../examples/asap7_small.lib.gz
read_verilog ../examples/reg1_asap7.v
link_design top
create_clock -name clk1 -period 500 clk1
create_clock -name clk2 -period 500 clk2
create_clock -name clk3 -period 500 clk3
set_input_delay -clock clk1 1 {in1 in2}
set_input_delay -clock clk2 1 {in1 in2}
set_input_delay -clock clk3 1 {in1 in2}
set_input_transition 10 {in1 in2 clk1 clk2 clk3}
set_propagated_clock {clk1 clk2 clk3}
read_spef ../examples/reg1_asap7.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*"]"