power use cofactor activity for internal power
This commit is contained in:
parent
60eaa584d4
commit
bb4ceacd4d
|
|
@ -155,19 +155,18 @@ protected:
|
|||
BfsFwdIterator &bfs);
|
||||
PwrActivity evalActivity(FuncExpr *expr,
|
||||
const Instance *inst);
|
||||
bool internalPowerMissingWhen(LibertyCell *cell,
|
||||
const LibertyPort *to_port,
|
||||
const char *related_pg_pin);
|
||||
FuncExpr *inferedWhen(FuncExpr *expr,
|
||||
const LibertyPort *port);
|
||||
PwrActivity evalActivity(FuncExpr *expr,
|
||||
const Instance *inst,
|
||||
const LibertyPort *cofactor_port,
|
||||
bool cofactor_positive);
|
||||
LibertyPort *findExprOutPort(FuncExpr *expr);
|
||||
void findInputDuty(const Pin *to_pin,
|
||||
const Instance *inst,
|
||||
FuncExpr *func,
|
||||
InternalPower *pwr,
|
||||
// Return values.
|
||||
float &duty,
|
||||
FuncExpr *&infered_when);
|
||||
float findInputDuty(const Pin *to_pin,
|
||||
const Instance *inst,
|
||||
FuncExpr *func,
|
||||
InternalPower *pwr);
|
||||
PwrActivity evalActivityDifference(FuncExpr *expr,
|
||||
const Instance *inst,
|
||||
const LibertyPort *cofactor_port);
|
||||
|
||||
private:
|
||||
PwrActivity global_activity_;
|
||||
|
|
|
|||
175
search/Power.cc
175
search/Power.cc
|
|
@ -59,8 +59,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
static int
|
||||
funcExprPortCount(FuncExpr *expr);
|
||||
static bool
|
||||
isPositiveUnate(const LibertyCell *cell,
|
||||
const LibertyPort *from,
|
||||
|
|
@ -338,24 +336,45 @@ PropActivityVisitor::visit(Vertex *vertex)
|
|||
PwrActivity
|
||||
Power::evalActivity(FuncExpr *expr,
|
||||
const Instance *inst)
|
||||
{
|
||||
return evalActivity(expr, inst, nullptr, true);
|
||||
}
|
||||
|
||||
// Eval activity thru expr.
|
||||
// With cofactor_port eval the positive/negative cofactor of expr wrt cofactor_port.
|
||||
PwrActivity
|
||||
Power::evalActivity(FuncExpr *expr,
|
||||
const Instance *inst,
|
||||
const LibertyPort *cofactor_port,
|
||||
bool cofactor_positive)
|
||||
{
|
||||
switch (expr->op()) {
|
||||
case FuncExpr::op_port: {
|
||||
Pin *pin = network_->findPin(inst, expr->port()->name());
|
||||
LibertyPort *port = expr->port();
|
||||
if (port == cofactor_port) {
|
||||
if (cofactor_positive)
|
||||
return PwrActivity(0.0, 1.0, PwrActivityOrigin::constant);
|
||||
else
|
||||
return PwrActivity(0.0, 0.0, PwrActivityOrigin::constant);
|
||||
}
|
||||
Pin *pin = network_->findPin(inst, port->name());
|
||||
if (pin)
|
||||
return findActivity(pin);
|
||||
else
|
||||
return PwrActivity(0.0, 0.0, PwrActivityOrigin::constant);
|
||||
}
|
||||
case FuncExpr::op_not: {
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst);
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
||||
cofactor_port, cofactor_positive);
|
||||
return PwrActivity(activity1.activity(),
|
||||
1.0 - activity1.duty(),
|
||||
PwrActivityOrigin::propagated);
|
||||
}
|
||||
case FuncExpr::op_or: {
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst);
|
||||
PwrActivity activity2 = evalActivity(expr->right(), inst);
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
||||
cofactor_port, cofactor_positive);
|
||||
PwrActivity activity2 = evalActivity(expr->right(), inst,
|
||||
cofactor_port, cofactor_positive);
|
||||
float p1 = 1.0 - activity1.duty();
|
||||
float p2 = 1.0 - activity2.duty();
|
||||
return PwrActivity(activity1.activity() * p2
|
||||
|
|
@ -364,8 +383,10 @@ Power::evalActivity(FuncExpr *expr,
|
|||
PwrActivityOrigin::propagated);
|
||||
}
|
||||
case FuncExpr::op_and: {
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst);
|
||||
PwrActivity activity2 = evalActivity(expr->right(), inst);
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
||||
cofactor_port, cofactor_positive);
|
||||
PwrActivity activity2 = evalActivity(expr->right(), inst,
|
||||
cofactor_port, cofactor_positive);
|
||||
float p1 = activity1.duty();
|
||||
float p2 = activity2.duty();
|
||||
return PwrActivity(activity1.activity() * p2 + activity2.activity() * p1,
|
||||
|
|
@ -373,8 +394,10 @@ Power::evalActivity(FuncExpr *expr,
|
|||
PwrActivityOrigin::propagated);
|
||||
}
|
||||
case FuncExpr::op_xor: {
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst);
|
||||
PwrActivity activity2 = evalActivity(expr->right(), inst);
|
||||
PwrActivity activity1 = evalActivity(expr->left(), inst,
|
||||
cofactor_port, cofactor_positive);
|
||||
PwrActivity activity2 = evalActivity(expr->right(), inst,
|
||||
cofactor_port, cofactor_positive);
|
||||
float p1 = activity1.duty() * (1.0 - activity2.duty());
|
||||
float p2 = activity2.duty() * (1.0 - activity1.duty());
|
||||
return PwrActivity(activity1.activity() * p1 + activity2.activity() * p2,
|
||||
|
|
@ -587,12 +610,8 @@ Power::findInputInternalPower(const Pin *pin,
|
|||
LibertyPort *out_port = findExprOutPort(when);
|
||||
if (out_port) {
|
||||
FuncExpr *func = out_port->function();
|
||||
// eval cofactor of func wrt input
|
||||
FuncExpr *sensitize_expr = inferedWhen(func, port);
|
||||
if (sensitize_expr) {
|
||||
duty = evalActivity(sensitize_expr, inst).duty();
|
||||
sensitize_expr->deleteSubexprs();
|
||||
}
|
||||
if (func->hasPort(port))
|
||||
duty = evalActivityDifference(func, inst, port).duty();
|
||||
else
|
||||
duty = evalActivity(when, inst).duty();
|
||||
}
|
||||
|
|
@ -645,6 +664,21 @@ Power::findExprOutPort(FuncExpr *expr)
|
|||
}
|
||||
}
|
||||
|
||||
PwrActivity
|
||||
Power::evalActivityDifference(FuncExpr *expr,
|
||||
const Instance *inst,
|
||||
const LibertyPort *cofactor_port)
|
||||
{
|
||||
PwrActivity pos = evalActivity(expr, inst, cofactor_port, true);
|
||||
PwrActivity neg = evalActivity(expr, inst, cofactor_port, false);
|
||||
// difference(expr) wrt cofactor port = xor(pos, neg).
|
||||
float p1 = pos.duty() * (1.0 - neg.duty());
|
||||
float p2 = neg.duty() * (1.0 - pos.duty());
|
||||
return PwrActivity(pos.activity() * p1 + neg.activity() * p2,
|
||||
p1 + p2,
|
||||
PwrActivityOrigin::propagated);
|
||||
}
|
||||
|
||||
void
|
||||
Power::findOutputInternalPower(const Pin *to_pin,
|
||||
const LibertyPort *to_port,
|
||||
|
|
@ -667,24 +701,16 @@ Power::findOutputInternalPower(const Pin *to_pin,
|
|||
|
||||
map<const char*, float, StringLessIf> pg_duty_sum;
|
||||
for (InternalPower *pwr : *cell->internalPowers(to_port)) {
|
||||
float duty;
|
||||
FuncExpr *infered_when;
|
||||
findInputDuty(to_pin, inst, func, pwr,
|
||||
duty, infered_when);
|
||||
float duty = findInputDuty(to_pin, inst, func, pwr);
|
||||
const char *related_pg_pin = pwr->relatedPgPin();
|
||||
pg_duty_sum[related_pg_pin] += duty;
|
||||
if (infered_when)
|
||||
infered_when->deleteSubexprs();
|
||||
}
|
||||
|
||||
float internal = 0.0;
|
||||
for (InternalPower *pwr : *cell->internalPowers(to_port)) {
|
||||
FuncExpr *when = pwr->when();
|
||||
const char *related_pg_pin = pwr->relatedPgPin();
|
||||
float duty;
|
||||
FuncExpr *infered_when;
|
||||
findInputDuty(to_pin, inst, func, pwr,
|
||||
duty, infered_when);
|
||||
float duty = findInputDuty(to_pin, inst, func, pwr);
|
||||
const LibertyPort *from_port = pwr->relatedPort();
|
||||
const Pin *from_pin = network_->findPin(inst, from_port);
|
||||
Vertex *from_vertex = graph_->pinLoadVertex(from_pin);
|
||||
|
|
@ -711,7 +737,7 @@ Power::findOutputInternalPower(const Pin *to_pin,
|
|||
debugPrint9(debug_, "power", 2, "%3s -> %-3s %6s %.2f %.2f %.2f %9.2e %9.2e %s\n",
|
||||
from_port->name(),
|
||||
to_port->name(),
|
||||
when ? when->asString() : (infered_when ? infered_when->asString() : ""),
|
||||
when ? when->asString() : "",
|
||||
to_activity.activity() * 1e-9,
|
||||
duty,
|
||||
weight,
|
||||
|
|
@ -719,44 +745,36 @@ Power::findOutputInternalPower(const Pin *to_pin,
|
|||
port_internal,
|
||||
related_pg_pin ? related_pg_pin : "no pg_pin");
|
||||
internal += port_internal;
|
||||
if (infered_when)
|
||||
infered_when->deleteSubexprs();
|
||||
}
|
||||
result.internal() += internal;
|
||||
}
|
||||
|
||||
void
|
||||
float
|
||||
Power::findInputDuty(const Pin *to_pin,
|
||||
const Instance *inst,
|
||||
FuncExpr *func,
|
||||
InternalPower *pwr,
|
||||
// Return values.
|
||||
float &duty,
|
||||
FuncExpr *&infered_when)
|
||||
InternalPower *pwr)
|
||||
|
||||
{
|
||||
const char *related_pg_pin = pwr->relatedPgPin();
|
||||
const LibertyPort *from_port = pwr->relatedPort();
|
||||
FuncExpr *when = pwr->when();
|
||||
infered_when = (when == nullptr && func)
|
||||
? inferedWhen(func, from_port)
|
||||
: nullptr;
|
||||
const Pin *from_pin = network_->findPin(inst, from_port);
|
||||
Vertex *from_vertex = graph_->pinLoadVertex(from_pin);
|
||||
duty = 0.5;
|
||||
if (infered_when) {
|
||||
if (func->hasPort(from_port)) {
|
||||
PwrActivity from_activity = findActivity(from_pin);
|
||||
PwrActivity to_activity = findActivity(to_pin);
|
||||
float duty1 = evalActivity(infered_when, inst).duty();
|
||||
float duty1 = evalActivityDifference(func, inst, from_port).duty();
|
||||
if (to_activity.activity() == 0.0)
|
||||
duty = 0.0;
|
||||
return 0.0;
|
||||
else
|
||||
duty = from_activity.activity() / to_activity.activity() * duty1;
|
||||
return from_activity.activity() / to_activity.activity() * duty1;
|
||||
}
|
||||
else if (when)
|
||||
duty = evalActivity(when, inst).duty();
|
||||
return evalActivity(when, inst).duty();
|
||||
else if (search_->isClock(from_vertex))
|
||||
duty = 1.0;
|
||||
return 1.0;
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -796,77 +814,8 @@ negate(FuncExpr *expr)
|
|||
return FuncExpr::makeNot(expr->copy());
|
||||
}
|
||||
|
||||
// Positive shannon cofactor of expr wrt port.
|
||||
FuncExpr *
|
||||
Power::inferedWhen(FuncExpr *expr,
|
||||
const LibertyPort *port)
|
||||
{
|
||||
switch (expr->op()) {
|
||||
case FuncExpr::op_port: {
|
||||
if (expr->port() == port)
|
||||
return FuncExpr::makeOne();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
case FuncExpr::op_not:
|
||||
return inferedWhen(expr->left(), port);
|
||||
case FuncExpr::op_or:
|
||||
case FuncExpr::op_xor: {
|
||||
if (isPortRef(expr->left(), port))
|
||||
return negate(expr->right());
|
||||
if (isPortRef(expr->right(), port))
|
||||
return negate(expr->left());
|
||||
break;
|
||||
}
|
||||
case FuncExpr::op_and: {
|
||||
if (isPortRef(expr->left(), port))
|
||||
return expr->right()->copy();
|
||||
if (isPortRef(expr->right(), port))
|
||||
return expr->left()->copy();
|
||||
break;
|
||||
}
|
||||
case FuncExpr::op_one:
|
||||
case FuncExpr::op_zero:
|
||||
return expr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Return true if some a "when" clause for the internal power to_port
|
||||
// is missing.
|
||||
bool
|
||||
Power::internalPowerMissingWhen(LibertyCell *cell,
|
||||
const LibertyPort *to_port,
|
||||
const char *related_pg_pin)
|
||||
{
|
||||
int when_input_count = 0;
|
||||
int when_count = 0;
|
||||
for (InternalPower *pwr : *cell->internalPowers(to_port)) {
|
||||
auto when = pwr->when();
|
||||
if (pwr->relatedPort() == nullptr
|
||||
&& stringEqIf(pwr->relatedPgPin(), related_pg_pin)
|
||||
&& when) {
|
||||
when_count++;
|
||||
when_input_count = funcExprPortCount(when);
|
||||
}
|
||||
}
|
||||
return when_count != (1 << when_input_count);
|
||||
}
|
||||
|
||||
static int
|
||||
funcExprPortCount(FuncExpr *expr)
|
||||
{
|
||||
int port_count = 0;
|
||||
FuncExprPortIterator port_iter(expr);
|
||||
while (port_iter.hasNext()) {
|
||||
port_iter.next();
|
||||
port_count++;
|
||||
}
|
||||
return port_count;
|
||||
}
|
||||
|
||||
void
|
||||
Power::findLeakagePower(const Instance *,
|
||||
LibertyCell *cell,
|
||||
|
|
|
|||
Loading…
Reference in New Issue