LibertyCell::internalPowers(port)
This commit is contained in:
parent
958a8577e5
commit
1d3ae30600
|
|
@ -20,6 +20,11 @@ Release 2.1.0 2020/04/05
|
|||
|
||||
All public headers files have been moved to include/sta.
|
||||
|
||||
The following iterators have been removed.
|
||||
Use range iteration on the returned collection shown next to them instead.
|
||||
LibertyCellInternalPowerIterator cell->internalPowers()
|
||||
LibertyCellLeakagePowerIterator cell->leakagePowers()
|
||||
|
||||
Release 2.0.18 2020/02/15
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ typedef Set<TimingArcSet*, TimingArcSetLess> TimingArcSetMap;
|
|||
typedef Map<LibertyPortPair, TimingArcSetSeq*,
|
||||
LibertyPortPairLess> LibertyPortPairTimingArcMap;
|
||||
typedef Vector<InternalPower*> InternalPowerSeq;
|
||||
typedef Map<const LibertyPort *, InternalPowerSeq> PortInternalPowerSeq;
|
||||
typedef Vector<LeakagePower*> LeakagePowerSeq;
|
||||
typedef Map<const LibertyPort*, TimingArcSetSeq*> LibertyPortTimingArcMap;
|
||||
typedef Map<const OperatingConditions*, LibertyCell*> ScaledCellMap;
|
||||
|
|
@ -419,12 +420,13 @@ public:
|
|||
TimingArcSet *findTimingArcSet(unsigned arc_set_index) const;
|
||||
bool hasTimingArcs(LibertyPort *port) const;
|
||||
|
||||
InternalPowerSeq *internalPowers() { return &internal_powers_; }
|
||||
InternalPowerSeq *internalPowers();
|
||||
InternalPowerSeq *internalPowers(const LibertyPort *port);
|
||||
LeakagePowerSeq *leakagePowers() { return &leakage_powers_; }
|
||||
void leakagePower(// Return values.
|
||||
float &leakage,
|
||||
bool &exists) const;
|
||||
bool leakagePowerEx() const { return leakage_power_exists_; }
|
||||
bool leakagePowerExists() const { return leakage_power_exists_; }
|
||||
|
||||
bool hasSequentials() const;
|
||||
// Find the sequential with the output connected to an (internal) port.
|
||||
|
|
@ -532,6 +534,7 @@ protected:
|
|||
TimingArcAttrsSeq timing_arc_attrs_;
|
||||
bool has_infered_reg_timing_arcs_;
|
||||
InternalPowerSeq internal_powers_;
|
||||
PortInternalPowerSeq port_internal_powers_;
|
||||
InternalPowerAttrsSeq internal_power_attrs_;
|
||||
LeakagePowerSeq leakage_powers_;
|
||||
SequentialSeq sequentials_;
|
||||
|
|
@ -611,20 +614,6 @@ public:
|
|||
SequentialSeq::ConstIterator(cell->sequentials_) {}
|
||||
};
|
||||
|
||||
class LibertyCellLeakagePowerIterator : public LeakagePowerSeq::Iterator
|
||||
{
|
||||
public:
|
||||
LibertyCellLeakagePowerIterator(LibertyCell *cell) :
|
||||
LeakagePowerSeq::Iterator(cell->leakagePowers()) {}
|
||||
};
|
||||
|
||||
class LibertyCellInternalPowerIterator : public InternalPowerSeq::Iterator
|
||||
{
|
||||
public:
|
||||
LibertyCellInternalPowerIterator(LibertyCell *cell) :
|
||||
InternalPowerSeq::Iterator(cell->internalPowers()) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
class LibertyPort : public ConcretePort
|
||||
|
|
|
|||
|
|
@ -1110,6 +1110,19 @@ void
|
|||
LibertyCell::addInternalPower(InternalPower *power)
|
||||
{
|
||||
internal_powers_.push_back(power);
|
||||
port_internal_powers_[power->port()].push_back(power);
|
||||
}
|
||||
|
||||
InternalPowerSeq *
|
||||
LibertyCell::internalPowers()
|
||||
{
|
||||
return &internal_powers_;
|
||||
}
|
||||
|
||||
InternalPowerSeq *
|
||||
LibertyCell::internalPowers(const LibertyPort *port)
|
||||
{
|
||||
return &port_internal_powers_[port];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
147
search/Power.cc
147
search/Power.cc
|
|
@ -551,78 +551,74 @@ Power::findInternalPower(const Pin *to_pin,
|
|||
units_->capacitanceUnit()->asString(load_cap));
|
||||
debugPrint0(debug_, "power", 2, " when act/ns duty energy power\n");
|
||||
float internal = 0.0;
|
||||
LibertyCellInternalPowerIterator pwr_iter(cell);
|
||||
while (pwr_iter.hasNext()) {
|
||||
InternalPower *pwr = pwr_iter.next();
|
||||
if (pwr->port() == to_port) {
|
||||
const char *related_pg_pin = pwr->relatedPgPin();
|
||||
const LibertyPort *from_port = pwr->relatedPort();
|
||||
FuncExpr *when = pwr->when();
|
||||
FuncExpr *infered_when = nullptr;
|
||||
if (from_port) {
|
||||
if (when == nullptr) {
|
||||
FuncExpr *func = to_port->function();
|
||||
if (func)
|
||||
infered_when = inferedWhen(func, from_port);
|
||||
}
|
||||
for (InternalPower *pwr : *cell->internalPowers(to_port)) {
|
||||
const char *related_pg_pin = pwr->relatedPgPin();
|
||||
const LibertyPort *from_port = pwr->relatedPort();
|
||||
FuncExpr *when = pwr->when();
|
||||
FuncExpr *infered_when = nullptr;
|
||||
if (from_port) {
|
||||
if (when == nullptr) {
|
||||
FuncExpr *func = to_port->function();
|
||||
if (func)
|
||||
infered_when = inferedWhen(func, from_port);
|
||||
}
|
||||
else
|
||||
from_port = to_port;
|
||||
// If all the "when" clauses exist VSS internal power is ignored.
|
||||
const Pin *from_pin = network_->findPin(inst, from_port);
|
||||
if (from_pin
|
||||
&& ((when && internalPowerMissingWhen(cell, to_port, related_pg_pin))
|
||||
|| pgNameVoltage(cell, related_pg_pin, dcalc_ap) != 0.0)) {
|
||||
Vertex *from_vertex = graph_->pinLoadVertex(from_pin);
|
||||
float duty;
|
||||
if (infered_when) {
|
||||
PwrActivity from_activity = findActivity(from_pin);
|
||||
PwrActivity to_activity = findActivity(to_pin);
|
||||
float duty1 = evalActivity(infered_when, inst).duty();
|
||||
if (to_activity.activity() == 0.0)
|
||||
duty = 0.0;
|
||||
else
|
||||
duty = from_activity.activity() / to_activity.activity() * duty1;
|
||||
}
|
||||
else if (when)
|
||||
duty = evalActivity(when, inst).duty();
|
||||
else if (search_->isClock(from_vertex))
|
||||
duty = 1.0;
|
||||
else
|
||||
duty = 0.5;
|
||||
float port_energy = 0.0;
|
||||
for (auto to_rf : RiseFall::range()) {
|
||||
// Should use unateness to find from_rf.
|
||||
RiseFall *from_rf = to_rf;
|
||||
float slew = delayAsFloat(graph_->slew(from_vertex,
|
||||
from_rf,
|
||||
dcalc_ap->index()));
|
||||
if (!fuzzyInf(slew)) {
|
||||
float table_energy = pwr->power(to_rf, pvt, slew, load_cap);
|
||||
float tr_energy = table_energy * duty;
|
||||
debugPrint4(debug_, "power", 3, " %s energy = %9.2e * %.2f = %9.2e\n",
|
||||
to_rf->shortName(),
|
||||
table_energy,
|
||||
duty,
|
||||
tr_energy);
|
||||
port_energy += tr_energy;
|
||||
}
|
||||
}
|
||||
float port_internal = port_energy * to_activity.activity();
|
||||
debugPrint8(debug_, "power", 2, " %s -> %s %s %.2f %.2f %9.2e %9.2e %s\n",
|
||||
from_port->name(),
|
||||
to_port->name(),
|
||||
when ? when->asString() : (infered_when ? infered_when->asString() : " "),
|
||||
to_activity.activity() * 1e-9,
|
||||
duty,
|
||||
port_energy,
|
||||
port_internal,
|
||||
related_pg_pin ? related_pg_pin : "no pg_pin");
|
||||
internal += port_internal;
|
||||
}
|
||||
if (infered_when)
|
||||
infered_when->deleteSubexprs();
|
||||
}
|
||||
else
|
||||
from_port = to_port;
|
||||
// If all the "when" clauses exist VSS internal power is ignored.
|
||||
const Pin *from_pin = network_->findPin(inst, from_port);
|
||||
if (from_pin
|
||||
&& ((when && internalPowerMissingWhen(cell, to_port, related_pg_pin))
|
||||
|| pgNameVoltage(cell, related_pg_pin, dcalc_ap) != 0.0)) {
|
||||
Vertex *from_vertex = graph_->pinLoadVertex(from_pin);
|
||||
float duty;
|
||||
if (infered_when) {
|
||||
PwrActivity from_activity = findActivity(from_pin);
|
||||
PwrActivity to_activity = findActivity(to_pin);
|
||||
float duty1 = evalActivity(infered_when, inst).duty();
|
||||
if (to_activity.activity() == 0.0)
|
||||
duty = 0.0;
|
||||
else
|
||||
duty = from_activity.activity() / to_activity.activity() * duty1;
|
||||
}
|
||||
else if (when)
|
||||
duty = evalActivity(when, inst).duty();
|
||||
else if (search_->isClock(from_vertex))
|
||||
duty = 1.0;
|
||||
else
|
||||
duty = 0.5;
|
||||
float port_energy = 0.0;
|
||||
for (auto to_rf : RiseFall::range()) {
|
||||
// Should use unateness to find from_rf.
|
||||
RiseFall *from_rf = to_rf;
|
||||
float slew = delayAsFloat(graph_->slew(from_vertex,
|
||||
from_rf,
|
||||
dcalc_ap->index()));
|
||||
if (!fuzzyInf(slew)) {
|
||||
float table_energy = pwr->power(to_rf, pvt, slew, load_cap);
|
||||
float tr_energy = table_energy * duty;
|
||||
debugPrint4(debug_, "power", 3, " %s energy = %9.2e * %.2f = %9.2e\n",
|
||||
to_rf->shortName(),
|
||||
table_energy,
|
||||
duty,
|
||||
tr_energy);
|
||||
port_energy += tr_energy;
|
||||
}
|
||||
}
|
||||
float port_internal = port_energy * to_activity.activity();
|
||||
debugPrint8(debug_, "power", 2, " %s -> %s %s %.2f %.2f %9.2e %9.2e %s\n",
|
||||
from_port->name(),
|
||||
to_port->name(),
|
||||
when ? when->asString() : (infered_when ? infered_when->asString() : " "),
|
||||
to_activity.activity() * 1e-9,
|
||||
duty,
|
||||
port_energy,
|
||||
port_internal,
|
||||
related_pg_pin ? related_pg_pin : "no pg_pin");
|
||||
internal += port_internal;
|
||||
}
|
||||
if (infered_when)
|
||||
infered_when->deleteSubexprs();
|
||||
}
|
||||
result.setInternal(result.internal() + internal);
|
||||
}
|
||||
|
|
@ -695,12 +691,9 @@ Power::internalPowerMissingWhen(LibertyCell *cell,
|
|||
{
|
||||
int when_input_count = 0;
|
||||
int when_count = 0;
|
||||
LibertyCellInternalPowerIterator pwr_iter(cell);
|
||||
while (pwr_iter.hasNext()) {
|
||||
auto pwr = pwr_iter.next();
|
||||
for (InternalPower *pwr : *cell->internalPowers(to_port)) {
|
||||
auto when = pwr->when();
|
||||
if (pwr->port() == to_port
|
||||
&& pwr->relatedPort() == nullptr
|
||||
if (pwr->relatedPort() == nullptr
|
||||
&& stringEqIf(pwr->relatedPgPin(), related_pg_pin)
|
||||
&& when) {
|
||||
when_count++;
|
||||
|
|
@ -732,9 +725,7 @@ Power::findLeakagePower(const Instance *,
|
|||
bool found_cond = false;
|
||||
float default_leakage = 0.0;
|
||||
bool found_default = false;
|
||||
LibertyCellLeakagePowerIterator pwr_iter(cell);
|
||||
while (pwr_iter.hasNext()) {
|
||||
LeakagePower *leak = pwr_iter.next();
|
||||
for (LeakagePower *leak : *cell->leakagePowers()) {
|
||||
FuncExpr *when = leak->when();
|
||||
if (when) {
|
||||
FuncExprPortIterator port_iter(when);
|
||||
|
|
|
|||
Loading…
Reference in New Issue