diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 21ec4552..5fa83783 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -734,6 +734,7 @@ public: bool isDisabledConstraint() const { return is_disabled_constraint_; } void setIsDisabledConstraint(bool is_disabled); LibertyPort *cornerPort(int ap_index); + const LibertyPort *cornerPort(int ap_index) const; void setCornerPort(LibertyPort *corner_port, int ap_index); const char *relatedGroundPin() const { return related_ground_pin_; } diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 0be65a33..4b0f8d16 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -2351,6 +2351,17 @@ LibertyPort::cornerPort(int ap_index) return this; } +const LibertyPort * +LibertyPort::cornerPort(int ap_index) const +{ + if (ap_index < static_cast(corner_ports_.size())) { + LibertyPort *corner_port = corner_ports_[ap_index]; + if (corner_port) + return corner_port; + } + return this; +} + void LibertyPort::setCornerPort(LibertyPort *corner_port, int ap_index) diff --git a/search/Power.cc b/search/Power.cc index dc3e2344..9d30b53d 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -606,17 +606,16 @@ Power::power(const Instance *inst, : 0.0; PwrActivity activity = findClkedActivity(to_pin, inst_clk); if (to_port->direction()->isAnyOutput()) { - findSwitchingPower(cell, to_port, activity, load_cap, - dcalc_ap, result); + findSwitchingPower(cell, to_port, activity, load_cap, corner, result); findOutputInternalPower(to_pin, to_port, inst, cell, activity, - load_cap, dcalc_ap, result); + load_cap, corner, result); } if (to_port->direction()->isAnyInput()) findInputInternalPower(to_pin, to_port, inst, cell, activity, - load_cap, dcalc_ap, result); + load_cap, corner, result); } delete pin_iter; - findLeakagePower(inst, cell, result); + findLeakagePower(inst, cell, corner, result); } const Clock * @@ -641,21 +640,25 @@ Power::findInputInternalPower(const Pin *pin, LibertyCell *cell, PwrActivity &activity, float load_cap, - const DcalcAnalysisPt *dcalc_ap, + const Corner *corner, // Return values. PowerResult &result) { - auto internal_pwrs = cell->internalPowers(port); + int lib_ap_index = corner->libertyIndex(MinMax::max()); + LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); + const LibertyPort *corner_port = port->cornerPort(lib_ap_index); + auto internal_pwrs = corner_cell->internalPowers(corner_port); if (!internal_pwrs->empty()) { debugPrint3(debug_, "power", 2, "internal input %s/%s (%s)\n", network_->pathName(inst), port->name(), - cell->name()); + corner_cell->name()); + const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(MinMax::max()); const Pvt *pvt = dcalc_ap->operatingConditions(); Vertex *vertex = graph_->pinLoadVertex(pin); debugPrint1(debug_, "power", 2, " cap = %s\n", units_->capacitanceUnit()->asString(load_cap)); - debugPrint0(debug_, "power", 2, " when act/ns duty energy power\n"); + debugPrint0(debug_, "power", 2, " whena act/ns duty energy power\n"); float internal = 0.0; for (InternalPower *pwr : *internal_pwrs) { const char *related_pg_pin = pwr->relatedPgPin(); @@ -675,8 +678,9 @@ Power::findInputInternalPower(const Pin *pin, float duty = .5; // fallback default FuncExpr *when = pwr->when(); if (when) { - LibertyPort *out_port = findExprOutPort(when); - if (out_port) { + LibertyPort *out_corner_port = findExprOutPort(when); + if (out_corner_port) { + const LibertyPort *out_port = cell->findLibertyPort(out_corner_port->name()); FuncExpr *func = out_port->function(); if (func && func->hasPort(port)) duty = evalActivityDifference(func, inst, port).duty(); @@ -757,7 +761,7 @@ Power::findOutputInternalPower(const Pin *to_pin, LibertyCell *cell, PwrActivity &to_activity, float load_cap, - const DcalcAnalysisPt *dcalc_ap, + const Corner *corner, // Return values. PowerResult &result) { @@ -765,13 +769,17 @@ Power::findOutputInternalPower(const Pin *to_pin, network_->pathName(inst), to_port->name(), cell->name()); + const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(MinMax::max()); const Pvt *pvt = dcalc_ap->operatingConditions(); + int lib_ap_index = corner->libertyIndex(MinMax::max()); + LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); + const LibertyPort *to_corner_port = to_port->cornerPort(lib_ap_index); debugPrint1(debug_, "power", 2, " cap = %s\n", units_->capacitanceUnit()->asString(load_cap)); FuncExpr *func = to_port->function(); map pg_duty_sum; - for (InternalPower *pwr : *cell->internalPowers(to_port)) { + for (InternalPower *pwr : *corner_cell->internalPowers(to_corner_port)) { float duty = findInputDuty(to_pin, inst, func, pwr); const char *related_pg_pin = pwr->relatedPgPin(); // Note related_pg_pin may be null. @@ -779,25 +787,27 @@ Power::findOutputInternalPower(const Pin *to_pin, } float internal = 0.0; - for (InternalPower *pwr : *cell->internalPowers(to_port)) { + for (InternalPower *pwr : *corner_cell->internalPowers(to_corner_port)) { FuncExpr *when = pwr->when(); const char *related_pg_pin = pwr->relatedPgPin(); float duty = findInputDuty(to_pin, inst, func, pwr); - const LibertyPort *from_port = pwr->relatedPort(); Vertex *from_vertex = nullptr; - if (from_port) { + bool positive_unate = true; + const LibertyPort *from_corner_port = pwr->relatedPort(); + if (from_corner_port) { + const LibertyPort *from_port = cell->findLibertyPort(from_corner_port->name()); + positive_unate = isPositiveUnate(corner_cell, from_port, to_port); const Pin *from_pin = network_->findPin(inst, from_port); - if (from_pin) + if (from_pin) { from_vertex = graph_->pinLoadVertex(from_pin); + } } float energy = 0.0; int tr_count = 0; debugPrint0(debug_, "power", 2, " when act/ns duty wgt energy power\n"); for (auto to_rf : RiseFall::range()) { // Use unateness to find from_rf. - RiseFall *from_rf = isPositiveUnate(cell, from_port, to_port) - ? to_rf - : to_rf->opposite(); + RiseFall *from_rf = positive_unate ? to_rf : to_rf->opposite(); float slew = from_vertex ? delayAsFloat(graph_->slew(from_vertex, from_rf, dcalc_ap->index())) @@ -819,7 +829,7 @@ Power::findOutputInternalPower(const Pin *to_pin, } float port_internal = weight * energy * to_activity.activity(); debugPrint9(debug_, "power", 2, "%3s -> %-3s %6s %.2f %.2f %.2f %9.2e %9.2e %s\n", - from_port->name(), + from_corner_port->name(), to_port->name(), when ? when->asString() : "", to_activity.activity() * 1e-9, @@ -891,14 +901,17 @@ isPositiveUnate(const LibertyCell *cell, void Power::findLeakagePower(const Instance *, LibertyCell *cell, + const Corner *corner, // Return values. PowerResult &result) { + int lib_ap_index = corner->libertyIndex(MinMax::max()); + LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); float cond_leakage = 0.0; bool found_cond = false; float default_leakage = 0.0; bool found_default = false; - for (LeakagePower *leak : *cell->leakagePowers()) { + for (LeakagePower *leak : *corner_cell->leakagePowers()) { FuncExpr *when = leak->when(); if (when) { FuncExprPortIterator port_iter(when); @@ -950,11 +963,15 @@ Power::findSwitchingPower(LibertyCell *cell, const LibertyPort *to_port, PwrActivity &activity, float load_cap, - const DcalcAnalysisPt *dcalc_ap, + const Corner *corner, // Return values. PowerResult &result) { - float volt = portVoltage(cell, to_port, dcalc_ap); + MinMax *mm = MinMax::max(); + const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(mm); + int lib_ap_index = corner->libertyIndex(MinMax::max()); + LibertyCell *corner_cell = cell->cornerCell(lib_ap_index); + float volt = portVoltage(corner_cell, to_port, dcalc_ap); float switching = .5 * load_cap * volt * volt * activity.activity(); debugPrint5(debug_, "power", 2, "switching %s/%s activity = %.2e volt = %.2f %.3e\n", cell->name(), diff --git a/search/Power.hh b/search/Power.hh index aa6b7c3e..d8d2fe8e 100644 --- a/search/Power.hh +++ b/search/Power.hh @@ -110,7 +110,7 @@ protected: LibertyCell *cell, PwrActivity &to_activity, float load_cap, - const DcalcAnalysisPt *dcalc_ap, + const Corner *corner, // Return values. PowerResult &result); void findOutputInternalPower(const Pin *to_pin, @@ -119,18 +119,19 @@ protected: LibertyCell *cell, PwrActivity &to_activity, float load_cap, - const DcalcAnalysisPt *dcalc_ap, + const Corner *corner, // Return values. PowerResult &result); void findLeakagePower(const Instance *inst, LibertyCell *cell, + const Corner *corner, // Return values. PowerResult &result); void findSwitchingPower(LibertyCell *cell, const LibertyPort *to_port, PwrActivity &activity, float load_cap, - const DcalcAnalysisPt *dcalc_ap, + const Corner *corner, // Return values. PowerResult &result); const Clock *findInstClk(const Instance *inst);