diff --git a/dcalc/DmpCeff.cc b/dcalc/DmpCeff.cc index 1e08662b..ffe4e666 100644 --- a/dcalc/DmpCeff.cc +++ b/dcalc/DmpCeff.cc @@ -1683,7 +1683,10 @@ DmpCeffDelayCalc::ceff(const LibertyCell *drvr_cell, gateDelay(drvr_cell, arc, in_slew, load_cap, drvr_parasitic, related_out_cap, pvt, dcalc_ap, gate_delay, drvr_slew); - return ceff(); + if (dmp_alg_) + return static_cast(dmp_alg_->ceff()); + else + return load_cap; } void @@ -1706,7 +1709,7 @@ DmpCeffDelayCalc::reportGateDelay(const LibertyCell *drvr_cell, GateTimingModel *model = gateModel(arc, dcalc_ap); float c_eff = 0.0; if (drvr_parasitic_ && dmp_alg_) { - c_eff = ceff(); + c_eff = dmp_alg_->ceff(); const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary(); const Units *units = drvr_library->units(); const Unit *cap_unit = units->capacitanceUnit(); @@ -1772,15 +1775,6 @@ DmpCeffDelayCalc::loadDelaySlew(const Pin *load_pin, dmp_alg_->loadDelaySlew(load_pin, elmore, delay, slew); } -float -DmpCeffDelayCalc::ceff() const -{ - if (dmp_alg_) - return static_cast(dmp_alg_->ceff()); - else - return 0.0; -} - // Notify algorithm components. void DmpCeffDelayCalc::copyState(const StaState *sta) diff --git a/dcalc/DmpCeff.hh b/dcalc/DmpCeff.hh index 58cb5d9e..95062d48 100644 --- a/dcalc/DmpCeff.hh +++ b/dcalc/DmpCeff.hh @@ -87,7 +87,6 @@ protected: double c2, double rpi, double c1); - float ceff() const; bool input_port_; static bool unsuppored_model_warned_; diff --git a/search/Power.cc b/search/Power.cc index 8956e580..2850a7d4 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -50,6 +50,9 @@ namespace sta { +typedef std::pair SumCount; +typedef Map SupplySumCounts; + Power::Power(Sta *sta) : StaState(sta), sta_(sta), @@ -141,7 +144,7 @@ Power::power(const Instance *inst, findSwitchingPower(cell, to_port, activity1, load_cap, dcalc_ap, result); } - findInternalPower(inst, cell, to_port, activity1, is_clk, + findInternalPower(inst, cell, to_port, activity1, load_cap, dcalc_ap, result); } delete pin_iter; @@ -153,55 +156,44 @@ Power::findInternalPower(const Instance *inst, LibertyCell *cell, const LibertyPort *to_port, float activity, - bool is_clk, float load_cap, const DcalcAnalysisPt *dcalc_ap, // Return values. PowerResult &result) { - debugPrint3(debug_, "power", 2, "internal %s/%s %ss\n", + debugPrint3(debug_, "power", 2, "internal %s/%s (%s)\n", network_->pathName(inst), to_port->name(), cell->name()); - float port_internal = 0.0; + SupplySumCounts supply_sum_counts; const Pvt *pvt = dcalc_ap->operatingConditions(); - float volt = voltage(cell, to_port, dcalc_ap); - const char *pwr_pin = to_port->relatedPowerPin(); - float duty = is_clk ? 1.0 : .5; - debugPrint3(debug_, "power", 2, "cap = %s activity = %.2f/ns duty = %.1f\n", + float duty = 1.0; + debugPrint2(debug_, "power", 2, " cap = %s duty = %.1f\n", units_->capacitanceUnit()->asString(load_cap), - activity * 1e-9, duty); LibertyCellInternalPowerIterator pwr_iter(cell); while (pwr_iter.hasNext()) { InternalPower *pwr = pwr_iter.next(); const char *related_pg_pin = pwr->relatedPgPin(); - if (pwr->port() == to_port - && ((related_pg_pin == NULL || pwr_pin == NULL) - || stringEqual(related_pg_pin, pwr_pin))) { - const LibertyPort *from_port = pwr->relatedPort(); + const LibertyPort *from_port = pwr->relatedPort(); + if (pwr->port() == to_port) { if (from_port == NULL) from_port = to_port; const Pin *from_pin = network_->findPin(inst, from_port); Vertex *from_vertex = graph_->pinLoadVertex(from_pin); + float port_internal = 0.0; TransRiseFallIterator tr_iter; while (tr_iter.hasNext()) { TransRiseFall *to_tr = tr_iter.next(); - // Need unateness to find from_tr. + // Should use unateness to find from_tr. float slew = delayAsFloat(sta_->vertexSlew(from_vertex, to_tr, dcalc_ap)); - float energy, tr_internal; - if (from_port) { - float energy1 = pwr->power(to_tr, pvt, slew, load_cap); - // Scale by voltage and rise/fall transition count. - energy = energy1 * volt / 2.0; - } - else { - float energy1 = pwr->power(to_tr, pvt, 0.0, 0.0); - // Scale by voltage and rise/fall transition count. - energy = energy1 * volt / 2.0; - } - tr_internal = energy * activity * duty; + float energy; + if (from_port) + energy = pwr->power(to_tr, pvt, slew, load_cap); + else + energy = pwr->power(to_tr, pvt, 0.0, 0.0); + float tr_internal = energy * activity * duty; port_internal += tr_internal; debugPrint5(debug_, "power", 2, " %s -> %s %s %s (%s)\n", from_port->name(), @@ -209,15 +201,30 @@ Power::findInternalPower(const Instance *inst, to_port->name(), pwr->when() ? pwr->when()->asString() : "", related_pg_pin ? related_pg_pin : ""); - debugPrint3(debug_, "power", 2, " slew = %s energy = %.5g pwr = %.5g\n", + debugPrint4(debug_, "power", 2, " slew = %s activity = %.2f/ns energy = %.5g pwr = %.5g\n", units_->timeUnit()->asString(slew), + activity * 1e-9, energy, tr_internal); } + // Sum/count internal power arcs by supply to average across conditions. + SumCount &supply_sum_count = supply_sum_counts[related_pg_pin]; + // Average rise/fall internal power. + supply_sum_count.first += port_internal / 2.0; + supply_sum_count.second++; } } - debugPrint1(debug_, "power", 2, " internal = %.5g\n", port_internal); - result.setInternal(result.internal() + port_internal); + float internal = 0.0; + SupplySumCounts::Iterator supply_iter(supply_sum_counts); + while (supply_iter.hasNext()) { + const SumCount &supply_cum_count = supply_iter.next(); + float supply_internal = supply_cum_count.first; + int supply_count = supply_cum_count.second; + internal += supply_internal / (supply_count > 0 ? supply_count : 1); + } + + debugPrint1(debug_, "power", 2, " internal = %.5g\n", internal); + result.setInternal(result.internal() + internal); } float diff --git a/search/Power.hh b/search/Power.hh index afa036a7..6f253448 100644 --- a/search/Power.hh +++ b/search/Power.hh @@ -53,7 +53,6 @@ protected: LibertyCell *cell, const LibertyPort *to_port, float activity, - bool is_clk, float load_cap, const DcalcAnalysisPt *dcalc_ap, // Return values. diff --git a/tcl/Power.tcl b/tcl/Power.tcl index cd86b201..73bff6c3 100644 --- a/tcl/Power.tcl +++ b/tcl/Power.tcl @@ -43,10 +43,7 @@ proc_redirect report_power { if { [info exists keys(-instances)] } { set insts [get_instances_error "-instances" $keys(-instances)] - foreach inst $insts { - report_power_inst $inst $corner $digits - puts "" - } + report_power_insts $insts $corner $digits } else { report_power_design $corner $digits } @@ -54,16 +51,16 @@ proc_redirect report_power { proc report_power_design { corner digits } { set power_result [design_power $corner] - puts "Group Internal Switching Leakage Total" - puts " Power Power Power Power (mW)" - puts "-------------------------------------------------------------------" - 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] lassign $totals design_internal design_switching design_leakage design_total + + puts "Group Internal Switching Leakage Total" + puts " Power Power Power Power (mW)" + puts "-------------------------------------------------------------------" report_power_row "Sequential" $sequential $design_total $digits report_power_row "Combinational" $combinational $design_total $digits report_power_row "Macro" $macro $design_total $digits @@ -106,14 +103,46 @@ proc report_power_col_percent { col_total total } { puts -nonewline [format "%9.1f%%" $percent] } -proc report_power_inst { inst corner digits } { +proc report_power_line { type pwr digits } { + puts [format "%-16s %.${digits}fmW" $type [expr $pwr * 1e+3]] +} + +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] + foreach inst_pwr $inst_pwrs { + set inst [lindex $inst_pwr 0] + set power [lindex $inst_pwr 1] + report_power_inst $inst $power $digits + puts "" + } +} + +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 + } +} + +proc report_power_inst { inst power_result digits } { puts "Instance: [get_full_name $inst]" set cell [get_property $inst "liberty_cell"] if { $cell != "NULL" } { puts "Cell: [get_name $cell]" set library [get_property $cell "library"] puts "Library file: [get_property $library filename]" - set power_result [instance_power $inst $corner] lassign $power_result internal switching leakage total report_power_line "Internal power" $internal $digits report_power_line "Switching power" $switching $digits @@ -124,9 +153,7 @@ proc report_power_inst { inst corner digits } { } } -proc report_power_line { type pwr digits } { - puts [format "%-16s %.${digits}fmW" $type [expr $pwr * 1e+3]] -} +################################################################ set ::power_default_signal_toggle_rate 0.1