From c42acca94f82108d9bae88b03c0937427c3208e6 Mon Sep 17 00:00:00 2001 From: Natalia Date: Mon, 24 Nov 2025 02:33:59 -0800 Subject: [PATCH] Support input and output internal power --- include/sta/PowerClass.hh | 6 ++++++ power/Power.cc | 29 +++++++++++++++++++++++++++++ power/Power.i | 17 +++++++++++++++++ power/Power.tcl | 13 +++++++++++++ 4 files changed, 65 insertions(+) diff --git a/include/sta/PowerClass.hh b/include/sta/PowerClass.hh index ed4a4860a..357d8767d 100644 --- a/include/sta/PowerClass.hh +++ b/include/sta/PowerClass.hh @@ -78,16 +78,22 @@ public: PowerResult(); void clear(); float internal() const { return internal_; } + float inputinternal() const { return inputinternal_; } + float outputinternal() const { return outputinternal_; } float switching() const { return switching_; } float leakage() const { return leakage_; } float total() const; void incr(PowerResult &result); void incrInternal(float pwr); + void incrInputInternal(float pwr); + void incrOutputInternal(float pwr); void incrSwitching(float pwr); void incrLeakage(float pwr); private: float internal_; + float inputinternal_; + float outputinternal_; float switching_; float leakage_; }; diff --git a/power/Power.cc b/power/Power.cc index f50fb67d7..f6c095fc3 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -1011,6 +1011,7 @@ Power::findInputInternalPower(const Pin *pin, internal += port_internal; } result.incrInternal(internal); + result.incrInputInternal(internal); } } } @@ -1102,7 +1103,9 @@ Power::findOutputInternalPower(const LibertyPort *to_port, FuncExpr *func = to_port->function(); map pg_duty_sum; + int numArcs = 0; for (InternalPower *pwr : corner_cell->internalPowers(to_corner_port)) { + numArcs += 1; const LibertyPort *from_corner_port = pwr->relatedPort(); if (from_corner_port) { const Pin *from_pin = findLinkPin(inst, from_corner_port); @@ -1113,10 +1116,13 @@ Power::findOutputInternalPower(const LibertyPort *to_port, pg_duty_sum[related_pg_pin] += from_density * duty; } } + // The number of pins that consume internal power in total + float numInternalPowerPins = numArcs / (float) pg_duty_sum.size(); debugPrint(debug_, "power", 2, " when act/ns duty wgt energy power"); float internal = 0.0; + float out_internal = 0.0; for (InternalPower *pwr : corner_cell->internalPowers(to_corner_port)) { FuncExpr *when = pwr->when(); const char *related_pg_pin = pwr->relatedPgPin(); @@ -1157,6 +1163,7 @@ Power::findOutputInternalPower(const LibertyPort *to_port, } } float port_internal = weight * energy * to_activity.density(); + float avg_arc_internal = energy * to_activity.density(); debugPrint(debug_, "power", 2, "%3s -> %-3s %6s %.3f %.3f %.3f %9.2e %9.2e %s", from_corner_port ? from_corner_port->name() : "-" , to_port->name(), @@ -1168,8 +1175,13 @@ Power::findOutputInternalPower(const LibertyPort *to_port, port_internal, related_pg_pin ? related_pg_pin : "no pg_pin"); internal += port_internal; + out_internal += avg_arc_internal; } result.incrInternal(internal); + if (numInternalPowerPins) + result.incrOutputInternal(out_internal / numInternalPowerPins); + else + result.incrOutputInternal(0.0); } float @@ -1603,6 +1615,8 @@ Power::deletePinBefore(const Pin *) PowerResult::PowerResult() : internal_(0.0), + inputinternal_(0.0), + outputinternal_(0.0), switching_(0.0), leakage_(0.0) { @@ -1612,6 +1626,8 @@ void PowerResult::clear() { internal_ = 0.0; + inputinternal_ = 0.0; + outputinternal_ = 0.0; switching_ = 0.0; leakage_ = 0.0; } @@ -1627,6 +1643,17 @@ PowerResult::incrInternal(float pwr) { internal_ += pwr; } +void +PowerResult::incrInputInternal(float pwr) +{ + inputinternal_ += pwr; +} + +void +PowerResult::incrOutputInternal(float pwr) +{ + outputinternal_ += pwr; +} void PowerResult::incrSwitching(float pwr) @@ -1644,6 +1671,8 @@ void PowerResult::incr(PowerResult &result) { internal_ += result.internal_; + inputinternal_ += result.inputinternal_; + outputinternal_ += result.outputinternal_; switching_ += result.switching_; leakage_ += result.leakage_; } diff --git a/power/Power.i b/power/Power.i index cdc59840b..75b9d2ba3 100644 --- a/power/Power.i +++ b/power/Power.i @@ -46,6 +46,13 @@ pushPowerResultFloats(PowerResult &power, powers.push_back(power.leakage()); powers.push_back(power.total()); } +static void +pushInternalPowerComponents(PowerResult &power, + FloatSeq &powers) +{ + powers.push_back(power.inputinternal()); + powers.push_back(power.outputinternal()); +} FloatSeq design_power(const Corner *corner) @@ -62,6 +69,16 @@ design_power(const Corner *corner) return powers; } +FloatSeq +internal_power_components(const Corner *corner) +{ + PowerResult total, sequential, combinational, clock, macro, pad; + Sta::sta()->power(corner, total, sequential, combinational, clock, macro, pad); + FloatSeq powers; + pushInternalPowerComponents(total, powers); + return powers; +} + FloatSeq instance_power(Instance *inst, const Corner *corner) diff --git a/power/Power.tcl b/power/Power.tcl index 420a97a99..70f19b5c5 100644 --- a/power/Power.tcl +++ b/power/Power.tcl @@ -69,6 +69,19 @@ proc_redirect report_power { } } +define_cmd_args "report_internal_power_components" { [> filename] [>> filename] } +proc_redirect report_internal_power_components { + global sta_report_default_digits + # Set the default corner + set corner [cmd_corner] + if { ![liberty_libraries_exist] } { + sta_error 304 "No liberty libraries have been read." + } + set power_result [internal_power_components $corner] + report_line $power_result +} + + proc liberty_libraries_exist {} { set lib_iter [liberty_library_iterator] set have_liberty 0