power cudd support

commit 872e7f91b4ce2a475063296b85ba99a2c76f665c
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Nov 10 09:54:02 2023 -0700

    power cudd eval diff

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 908dfaa08b165d59a38c25b5f534db4ca02540d8
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Nov 8 19:13:33 2023 -0700

    Power::seqActivity

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 47a74dd6989dbd7cfe8127aa0be95dcf19a3cff4
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Nov 8 18:03:01 2023 -0700

    cudd default cache init

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 87890f699280e0f4aea6c5610a2f1949a46a07ae
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Nov 8 13:48:58 2023 -0700

    power buffer activity origin

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 584b8124ab98d3cd42e23383aa35edb33e26e9d2
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Nov 8 12:26:16 2023 -0700

    power use cudd

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2023-11-10 09:59:50 -07:00
parent f9abae51d8
commit 7845105f4f
6 changed files with 354 additions and 118 deletions

View File

@ -435,14 +435,14 @@ if (USE_CUDD)
find_library(CUDD_LIB
NAME cudd
PATHS ${CUDD_DIR}
PATH_SUFFIXES lib lib/cudd
PATH_SUFFIXES lib lib/cudd cudd/.libs
)
if (CUDD_LIB)
message(STATUS "CUDD library: ${CUDD_LIB}")
get_filename_component(CUDD_LIB_DIR "${CUDD_LIB}" PATH)
get_filename_component(CUDD_LIB_PARENT1 "${CUDD_LIB_DIR}" PATH)
find_file(CUDD_HEADER cudd.h
PATHS ${CUDD_LIB_PARENT1}/include ${CUDD_LIB_PARENT1}/include/cudd)
PATHS ${CUDD_LIB_PARENT1} ${CUDD_LIB_PARENT1}/include ${CUDD_LIB_PARENT1}/include/cudd)
if (CUDD_HEADER)
get_filename_component(CUDD_INCLUDE "${CUDD_HEADER}" PATH)
message(STATUS "CUDD header: ${CUDD_HEADER}")

View File

@ -43,6 +43,7 @@ public:
float duty() const { return duty_; }
void setDuty(float duty);
PwrActivityOrigin origin() { return origin_; }
void setOrigin(PwrActivityOrigin origin);
const char *originName() const;
void set(float activity,
float duty,

View File

@ -17,7 +17,7 @@
#include "Power.hh"
#include <algorithm> // max
#include <cmath> // aps
#include <cmath> // abs
#include "Debug.hh"
#include "EnumNameMap.hh"
@ -47,6 +47,13 @@
#include "Bfs.hh"
#include "ClkNetwork.hh"
#if CUDD
#include "cudd.h"
#else
#define Cudd_Init(ignore1, ignore2, ignore3, ignore4, ignore5) nullptr
#define Cudd_Quit(ignore1)
#endif
// Related liberty not supported:
// library
// default_cell_leakage_power : 0;
@ -71,15 +78,32 @@ isPositiveUnate(const LibertyCell *cell,
const LibertyPort *from,
const LibertyPort *to);
static EnumNameMap<PwrActivityOrigin> pwr_activity_origin_map =
{{PwrActivityOrigin::global, "global"},
{PwrActivityOrigin::input, "input"},
{PwrActivityOrigin::user, "user"},
{PwrActivityOrigin::vcd, "vcd"},
{PwrActivityOrigin::propagated, "propagated"},
{PwrActivityOrigin::clock, "clock"},
{PwrActivityOrigin::constant, "constant"},
{PwrActivityOrigin::defaulted, "defaulted"},
{PwrActivityOrigin::unknown, "unknown"}};
Power::Power(StaState *sta) :
StaState(sta),
global_activity_{0.0, 0.0, PwrActivityOrigin::unknown},
input_activity_{0.1, 0.5, PwrActivityOrigin::input},
seq_activity_map_(100, SeqPinHash(network_), SeqPinEqual()),
activities_valid_(false)
activities_valid_(false),
cudd_mgr_(Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0))
{
}
Power::~Power()
{
Cudd_Quit(cudd_mgr_);
}
void
Power::setGlobalActivity(float activity,
float duty)
@ -135,6 +159,11 @@ void
Power::setActivity(const Pin *pin,
PwrActivity &activity)
{
debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f %s",
network_->pathName(pin),
activity.activity(),
activity.duty(),
pwr_activity_origin_map.find(activity.origin()));
activity_map_[pin] = activity;
}
@ -168,7 +197,7 @@ Power::hasSeqActivity(const Instance *reg,
return seq_activity_map_.hasKey(SeqPin(reg, output));
}
PwrActivity
PwrActivity &
Power::seqActivity(const Instance *reg,
LibertyPort *output)
{
@ -331,7 +360,7 @@ private:
bool setActivityCheck(const Pin *pin,
PwrActivity &activity);
static constexpr float change_tolerance_ = .01;
static constexpr float change_tolerance_ = .001;
InstanceSet visited_regs_;
float max_change_;
Power *power_;
@ -370,10 +399,6 @@ PropActivityVisitor::visit(Vertex *vertex)
bool changed = false;
if (power_->hasUserActivity(pin)) {
PwrActivity &activity = power_->userActivity(pin);
debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f",
vertex->name(network_),
activity.activity(),
activity.duty());
changed = setActivityCheck(pin, activity);
}
else {
@ -397,12 +422,8 @@ PropActivityVisitor::visit(Vertex *vertex)
if (port) {
FuncExpr *func = port->function();
if (func) {
PwrActivity activity = power_->evalActivity(func, inst);
PwrActivity activity = power_->evalActivity(func, inst);
changed = setActivityCheck(pin, activity);
debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f",
vertex->name(network_),
activity.activity(),
activity.duty());
}
if (port->isClockGateOut()) {
const Pin *enable, *clk, *gclk;
@ -491,6 +512,210 @@ Power::clockGatePins(const Instance *inst,
delete pin_iter;
}
////////////////////////////////////////////////////////////////
#if CUDD
PwrActivity
Power::evalActivity(FuncExpr *expr,
const Instance *inst)
{
LibertyPort *func_port = expr->port();
if (func_port && func_port->direction()->isInternal())
return findSeqActivity(inst, func_port);
else {
DdNode *bdd = funcBdd(expr);
float duty = evalBddDuty(bdd, inst);
float activity = evalBddActivity(bdd, inst);
Cudd_RecursiveDeref(cudd_mgr_, bdd);
clearVarMap();
return PwrActivity(activity, duty, PwrActivityOrigin::propagated);
}
}
// Find duty when from_port is sensitized.
float
Power::evalDiffDuty(FuncExpr *expr,
LibertyPort *from_port,
const Instance *inst)
{
DdNode *bdd = funcBdd(expr);
DdNode *var_node = bdd_port_var_map_[from_port];
unsigned var_index = Cudd_NodeReadIndex(var_node);
DdNode *diff = Cudd_bddBooleanDiff(cudd_mgr_, bdd, var_index);
Cudd_Ref(diff);
float duty = evalBddDuty(diff, inst);
Cudd_RecursiveDeref(cudd_mgr_, diff);
Cudd_RecursiveDeref(cudd_mgr_, bdd);
clearVarMap();
return duty;
}
DdNode *
Power::funcBdd(const FuncExpr *expr)
{
DdNode *left = nullptr;
DdNode *right = nullptr;
DdNode *result = nullptr;
switch (expr->op()) {
case FuncExpr::op_port: {
LibertyPort *port = expr->port();
result = ensureNode(port);
break;
}
case FuncExpr::op_not:
left = funcBdd(expr->left());
if (left)
result = Cudd_Not(left);
break;
case FuncExpr::op_or:
left = funcBdd(expr->left());
right = funcBdd(expr->right());
if (left && right)
result = Cudd_bddOr(cudd_mgr_, left, right);
else if (left)
result = left;
else if (right)
result = right;
break;
case FuncExpr::op_and:
left = funcBdd(expr->left());
right = funcBdd(expr->right());
if (left && right)
result = Cudd_bddAnd(cudd_mgr_, left, right);
else if (left)
result = left;
else if (right)
result = right;
break;
case FuncExpr::op_xor:
left = funcBdd(expr->left());
right = funcBdd(expr->right());
if (left && right)
result = Cudd_bddXor(cudd_mgr_, left, right);
else if (left)
result = left;
else if (right)
result = right;
break;
case FuncExpr::op_one:
result = Cudd_ReadOne(cudd_mgr_);
break;
case FuncExpr::op_zero:
result = Cudd_ReadLogicZero(cudd_mgr_);
break;
default:
report_->critical(596, "unknown function operator");
}
if (result)
Cudd_Ref(result);
if (left)
Cudd_RecursiveDeref(cudd_mgr_, left);
if (right)
Cudd_RecursiveDeref(cudd_mgr_, right);
return result;
}
DdNode *
Power::ensureNode(LibertyPort *port)
{
DdNode *bdd = bdd_port_var_map_.findKey(port);
if (bdd == nullptr) {
bdd = Cudd_bddNewVar(cudd_mgr_);
bdd_port_var_map_[port] = bdd;
unsigned var_index = Cudd_NodeReadIndex(bdd);
bdd_var_idx_port_map_[var_index] = port;
Cudd_Ref(bdd);
debugPrint(debug_, "power_activity", 2, "%s var %d", port->name(), var_index);
}
return bdd;
}
void
Power::clearVarMap()
{
for (auto port_node : bdd_port_var_map_) {
DdNode *var_node = port_node.second;
Cudd_RecursiveDeref(cudd_mgr_, var_node);
}
bdd_port_var_map_.clear();
bdd_var_idx_port_map_.clear();
}
// As suggested by
// https://stackoverflow.com/questions/63326728/cudd-printminterm-accessing-the-individual-minterms-in-the-sum-of-products
float
Power::evalBddDuty(DdNode *bdd,
const Instance *inst)
{
if (Cudd_IsConstant(bdd)) {
if (bdd == Cudd_ReadOne(cudd_mgr_))
return 1.0;
else if (bdd == Cudd_ReadLogicZero(cudd_mgr_))
return 0.0;
else
criticalError(1100, "unknown cudd constant");
}
else {
float duty0 = evalBddDuty(Cudd_E(bdd), inst);
float duty1 = evalBddDuty(Cudd_T(bdd), inst);
unsigned int index = Cudd_NodeReadIndex(bdd);
int var_index = Cudd_ReadPerm(cudd_mgr_, index);
LibertyPort *port = bdd_var_idx_port_map_[var_index];
if (port->direction()->isInternal())
return findSeqActivity(inst, port).duty();
else {
const Pin *pin = findLinkPin(inst, port);
if (pin) {
PwrActivity var_activity = findActivity(pin);
float var_duty = var_activity.duty();
float duty = duty0 * (1.0 - var_duty) + duty1 * var_duty;
if (Cudd_IsComplement(bdd))
duty = 1.0 - duty;
return duty;
}
}
}
return 0.0;
}
// https://www.brown.edu/Departments/Engineering/Courses/engn2912/Lectures/LP-02-logic-power-est.pdf
// F(x0, x1, .. ) is sensitized when F(Xi=1) xor F(Xi=0)
// F(Xi=1), F(Xi=0) are the cofactors of F wrt Xi.
float
Power::evalBddActivity(DdNode *bdd,
const Instance *inst)
{
float activity = 0.0;
for (auto port_var : bdd_port_var_map_) {
LibertyPort *port = port_var.first;
const Pin *pin = findLinkPin(inst, port);
if (pin) {
PwrActivity var_activity = findActivity(pin);
DdNode *var_node = port_var.second;
unsigned int var_index = Cudd_NodeReadIndex(var_node);
DdNode *diff = Cudd_bddBooleanDiff(cudd_mgr_, bdd, var_index);
Cudd_Ref(diff);
float diff_duty = evalBddDuty(diff, inst);
Cudd_RecursiveDeref(cudd_mgr_, diff);
float var_act = var_activity.activity() * diff_duty;
activity += var_act;
const Clock *clk = findClk(pin);
float clk_period = clk ? clk->period() : 1.0;
debugPrint(debug_, "power_activity", 3, "var %s %.3e * %.3f = %.3e",
port->name(),
var_activity.activity() / clk_period,
diff_duty,
var_act / clk_period);
}
}
return activity;
}
#else
PwrActivity
Power::evalActivity(FuncExpr *expr,
const Instance *inst)
@ -519,8 +744,11 @@ Power::evalActivity(FuncExpr *expr,
return findSeqActivity(inst, port);
else {
Pin *pin = findLinkPin(inst, port);
if (pin)
return findActivity(pin);
if (pin) {
PwrActivity activity = findActivity(pin);
activity.setOrigin(PwrActivityOrigin::propagated);
return activity;
}
}
return PwrActivity(0.0, 0.0, PwrActivityOrigin::constant);
}
@ -539,7 +767,8 @@ Power::evalActivity(FuncExpr *expr,
float p1 = 1.0 - activity1.duty();
float p2 = 1.0 - activity2.duty();
return PwrActivity(activity1.activity() * p2 + activity2.activity() * p1,
1.0 - p1 * p2,
// d1 + d2 - d1 * d2
1.0 - p1 * p2,
PwrActivityOrigin::propagated);
}
case FuncExpr::op_and: {
@ -574,6 +803,23 @@ Power::evalActivity(FuncExpr *expr,
return PwrActivity();
}
// Eval activity of difference(expr) wrt cofactor port.
float
Power::evalDiffDuty(FuncExpr *expr,
LibertyPort *cofactor_port,
const Instance *inst)
{
// Activity of positive/negative cofactors.
PwrActivity pos = evalActivity(expr, inst, cofactor_port, true);
PwrActivity neg = evalActivity(expr, inst, cofactor_port, false);
// difference = xor(pos, neg).
float p1 = pos.duty() * (1.0 - neg.duty());
float p2 = neg.duty() * (1.0 - pos.duty());
return p1 + p2;
}
#endif // CUDD
////////////////////////////////////////////////////////////////
void
@ -684,6 +930,7 @@ Power::seedRegOutputActivities(const Instance *reg,
activity.setActivity(1.0);
if (invert)
activity.setDuty(1.0 - activity.duty());
activity.setOrigin(PwrActivityOrigin::propagated);
setSeqActivity(reg, output, activity);
}
}
@ -732,14 +979,14 @@ Power::findInternalPower(const Instance *inst,
InstancePinIterator *pin_iter = network_->pinIterator(inst);
while (pin_iter->hasNext()) {
const Pin *to_pin = pin_iter->next();
const LibertyPort *to_port = network_->libertyPort(to_pin);
LibertyPort *to_port = network_->libertyPort(to_pin);
if (to_port) {
float load_cap = to_port->direction()->isAnyOutput()
? graph_delay_calc_->loadCap(to_pin, dcalc_ap)
: 0.0;
PwrActivity activity = findClkedActivity(to_pin, inst_clk);
if (to_port->direction()->isAnyOutput())
findOutputInternalPower(to_pin, to_port, inst, cell, activity,
findOutputInternalPower(to_port, inst, cell, activity,
load_cap, corner, result);
if (to_port->direction()->isAnyInput())
findInputInternalPower(to_pin, to_port, inst, cell, activity,
@ -751,7 +998,7 @@ Power::findInternalPower(const Instance *inst,
void
Power::findInputInternalPower(const Pin *pin,
const LibertyPort *port,
LibertyPort *port,
const Instance *inst,
LibertyCell *cell,
PwrActivity &activity,
@ -792,13 +1039,13 @@ Power::findInputInternalPower(const Pin *pin,
float duty = 1.0; // fallback default
FuncExpr *when = pwr->when();
if (when) {
LibertyPort *out_corner_port = findExprOutPort(when);
const LibertyPort *out_corner_port = findExprOutPort(when);
if (out_corner_port) {
const LibertyPort *out_port = findLinkPort(cell, out_corner_port);
LibertyPort *out_port = findLinkPort(cell, out_corner_port);
if (out_port) {
FuncExpr *func = out_port->function();
if (func && func->hasPort(port))
duty = evalActivityDifference(func, inst, port).duty();
duty = evalDiffDuty(func, port, inst);
else
duty = evalActivity(when, inst).duty();
}
@ -867,26 +1114,8 @@ Power::findExprOutPort(FuncExpr *expr)
return nullptr;
}
// Eval activity of difference(expr) wrt cofactor port.
PwrActivity
Power::evalActivityDifference(FuncExpr *expr,
const Instance *inst,
const LibertyPort *cofactor_port)
{
// Activity of positive/negative cofactors.
PwrActivity pos = evalActivity(expr, inst, cofactor_port, true);
PwrActivity neg = evalActivity(expr, inst, cofactor_port, false);
// difference = 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,
Power::findOutputInternalPower(const LibertyPort *to_port,
const Instance *inst,
LibertyCell *cell,
PwrActivity &to_activity,
@ -907,25 +1136,31 @@ Power::findOutputInternalPower(const Pin *to_pin,
map<const char*, float, StringLessIf> pg_duty_sum;
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.
pg_duty_sum[related_pg_pin] += duty;
const LibertyPort *from_corner_port = pwr->relatedPort();
if (from_corner_port) {
const Pin *from_pin = findLinkPin(inst, from_corner_port);
float from_activity = findActivity(from_pin).activity();
float duty = findInputDuty(inst, func, pwr);
const char *related_pg_pin = pwr->relatedPgPin();
// Note related_pg_pin may be null.
pg_duty_sum[related_pg_pin] += from_activity * duty;
}
}
debugPrint(debug_, "power", 2,
" when act/ns duty wgt energy power");
" when act/ns duty wgt energy power");
float internal = 0.0;
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);
float duty = findInputDuty(inst, func, pwr);
Vertex *from_vertex = nullptr;
bool positive_unate = true;
const LibertyPort *from_corner_port = pwr->relatedPort();
const Pin *from_pin = nullptr;
if (from_corner_port) {
positive_unate = isPositiveUnate(corner_cell, from_corner_port, to_corner_port);
const Pin *from_pin = findLinkPin(inst, from_corner_port);
from_pin = findLinkPin(inst, from_corner_port);
if (from_pin)
from_vertex = graph_->pinLoadVertex(from_pin);
}
@ -949,11 +1184,13 @@ Power::findOutputInternalPower(const Pin *to_pin,
float weight = 0.0;
if (duty_sum_iter != pg_duty_sum.end()) {
float duty_sum = duty_sum_iter->second;
if (duty_sum != 0.0)
weight = duty / duty_sum;
if (duty_sum != 0.0 && from_pin) {
float from_activity = findActivity(from_pin).activity();
weight = from_activity * duty / duty_sum;
}
}
float port_internal = weight * energy * to_activity.activity();
debugPrint(debug_, "power", 2, "%3s -> %-3s %6s %.3f %.2f %.2f %9.2e %9.2e %s",
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(),
when ? when->asString() : "",
@ -969,33 +1206,21 @@ Power::findOutputInternalPower(const Pin *to_pin,
}
float
Power::findInputDuty(const Pin *to_pin,
const Instance *inst,
FuncExpr *func,
InternalPower *pwr)
Power::findInputDuty(const Instance *inst,
FuncExpr *func,
InternalPower *pwr)
{
const LibertyPort *from_corner_port = pwr->relatedPort();
if (from_corner_port) {
const LibertyPort *from_port = findLinkPort(network_->libertyCell(inst),
from_corner_port);
LibertyPort *from_port = findLinkPort(network_->libertyCell(inst),
from_corner_port);
const Pin *from_pin = network_->findPin(inst, from_port);
if (from_pin) {
FuncExpr *when = pwr->when();
Vertex *from_vertex = graph_->pinLoadVertex(from_pin);
if (func && func->hasPort(from_port)) {
float from_activity = findActivity(from_pin).activity();
float to_activity = findActivity(to_pin).activity();
float duty1 = evalActivityDifference(func, inst, from_port).duty();
float duty = 0.0;
if (to_activity != 0.0F) {
duty = from_activity * duty1 / to_activity;
// Activities can get very small from multiplying probabilities
// through deep chains of logic. Dividing by very close to zero values
// can result in NaN/Inf depending on numerator.
if (!isnormal(duty))
duty = 0.0;
}
float duty = evalDiffDuty(func, from_port, inst);
return duty;
}
else if (when)
@ -1220,7 +1445,7 @@ Power::findSeqActivity(const Instance *inst,
if (global_activity_.isSet())
return global_activity_;
else if (hasSeqActivity(inst, port)) {
PwrActivity activity = seqActivity(inst, port);
PwrActivity &activity = seqActivity(inst, port);
if (activity.origin() != PwrActivityOrigin::unknown)
return activity;
}
@ -1314,17 +1539,6 @@ PowerResult::incr(PowerResult &result)
////////////////////////////////////////////////////////////////
static EnumNameMap<PwrActivityOrigin> pwr_activity_origin_map =
{{PwrActivityOrigin::global, "global"},
{PwrActivityOrigin::input, "input"},
{PwrActivityOrigin::user, "user"},
{PwrActivityOrigin::vcd, "vcd"},
{PwrActivityOrigin::propagated, "propagated"},
{PwrActivityOrigin::clock, "clock"},
{PwrActivityOrigin::constant, "constant"},
{PwrActivityOrigin::defaulted, "defaulted"},
{PwrActivityOrigin::unknown, "unknown"}};
PwrActivity::PwrActivity(float activity,
float duty,
PwrActivityOrigin origin) :
@ -1354,6 +1568,12 @@ PwrActivity::setDuty(float duty)
duty_ = duty;
}
void
PwrActivity::setOrigin(PwrActivityOrigin origin)
{
origin_ = origin;
}
void
PwrActivity::set(float activity,
float duty,

View File

@ -18,12 +18,16 @@
#include <utility>
#include "StaConfig.hh" // CUDD
#include "UnorderedMap.hh"
#include "Network.hh"
#include "SdcClass.hh"
#include "PowerClass.hh"
#include "StaState.hh"
struct DdNode;
struct DdManager;
namespace sta {
class Sta;
@ -34,6 +38,8 @@ class BfsFwdIterator;
class Vertex;
typedef std::pair<const Instance*, LibertyPort*> SeqPin;
typedef Map<LibertyPort*, DdNode*> BddPortVarMap;
typedef Map<unsigned, LibertyPort*> BddVarIdxPortMap;
class SeqPinHash
{
@ -62,6 +68,7 @@ class Power : public StaState
{
public:
Power(StaState *sta);
~Power();
void power(const Corner *corner,
// Return values.
PowerResult &total,
@ -100,8 +107,8 @@ protected:
PwrActivity &activity);
bool hasSeqActivity(const Instance *reg,
LibertyPort *output);
PwrActivity seqActivity(const Instance *reg,
LibertyPort *output);
PwrActivity &seqActivity(const Instance *reg,
LibertyPort *output);
bool hasActivity(const Pin *pin);
void setActivity(const Pin *pin,
PwrActivity &activity);
@ -116,7 +123,7 @@ protected:
// Return values.
PowerResult &result);
void findInputInternalPower(const Pin *to_pin,
const LibertyPort *to_port,
LibertyPort *to_port,
const Instance *inst,
LibertyCell *cell,
PwrActivity &to_activity,
@ -124,8 +131,7 @@ protected:
const Corner *corner,
// Return values.
PowerResult &result);
void findOutputInternalPower(const Pin *to_pin,
const LibertyPort *to_port,
void findOutputInternalPower(const LibertyPort *to_port,
const Instance *inst,
LibertyCell *cell,
PwrActivity &to_activity,
@ -175,13 +181,12 @@ protected:
const LibertyPort *cofactor_port,
bool cofactor_positive);
LibertyPort *findExprOutPort(FuncExpr *expr);
float findInputDuty(const Pin *to_pin,
const Instance *inst,
float findInputDuty(const Instance *inst,
FuncExpr *func,
InternalPower *pwr);
PwrActivity evalActivityDifference(FuncExpr *expr,
const Instance *inst,
const LibertyPort *cofactor_port);
float evalDiffDuty(FuncExpr *expr,
LibertyPort *from_port,
const Instance *inst);
LibertyPort *findLinkPort(const LibertyCell *cell,
const LibertyPort *corner_port);
Pin *findLinkPin(const Instance *inst,
@ -192,6 +197,14 @@ protected:
const Pin *&clk,
const Pin *&gclk) const;
DdNode *funcBdd(const FuncExpr *expr);
DdNode *ensureNode(LibertyPort *port);
void clearVarMap();
float evalBddActivity(DdNode *bdd,
const Instance *inst);
float evalBddDuty(DdNode *bdd,
const Instance *inst);
private:
// Port/pin activities set by set_pin_activity.
// set_pin_activity -global
@ -204,6 +217,11 @@ private:
PwrActivityMap activity_map_;
PwrSeqActivityMap seq_activity_map_;
bool activities_valid_;
DdManager *cudd_mgr_;
BddPortVarMap bdd_port_var_map_;
BddVarIdxPortMap bdd_var_idx_port_map_;
static constexpr int max_activity_passes_ = 100;
friend class PropActivityVisitor;

View File

@ -60,15 +60,14 @@ Sim::Sim(StaState *sta) :
invalid_load_pins_(network_),
instances_with_const_pins_(network_),
instances_to_annotate_(network_),
// cacheSize = 2^15
cudd_manager_(Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, 32768, 0))
cudd_mgr_(Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0))
{
}
Sim::~Sim()
{
delete observer_;
Cudd_Quit(cudd_manager_);
Cudd_Quit(cudd_mgr_);
}
#if CUDD
@ -88,11 +87,11 @@ Sim::functionSense(const FuncExpr *expr,
LibertyPort *input_port = network_->libertyPort(input_pin);
DdNode *input_node = ensureNode(input_port);
unsigned int input_index = Cudd_NodeReadIndex(input_node);
increasing = (Cudd_Increasing(cudd_manager_, bdd, input_index)
== Cudd_ReadOne(cudd_manager_));
decreasing = (Cudd_Decreasing(cudd_manager_, bdd, input_index)
== Cudd_ReadOne(cudd_manager_));
Cudd_RecursiveDeref(cudd_manager_, bdd);
increasing = (Cudd_Increasing(cudd_mgr_, bdd, input_index)
== Cudd_ReadOne(cudd_mgr_));
decreasing = (Cudd_Decreasing(cudd_mgr_, bdd, input_index)
== Cudd_ReadOne(cudd_mgr_));
Cudd_RecursiveDeref(cudd_mgr_, bdd);
clearSymtab();
}
TimingSense sense;
@ -113,7 +112,7 @@ Sim::clearSymtab() const
{
for (auto name_node : symtab_) {
DdNode *sym_node = name_node.second;
Cudd_RecursiveDeref(cudd_manager_, sym_node);
Cudd_RecursiveDeref(cudd_mgr_, sym_node);
}
symtab_.clear();
}
@ -125,12 +124,12 @@ Sim::evalExpr(const FuncExpr *expr,
UniqueLock lock(cudd_lock_);
DdNode *bdd = funcBdd(expr, inst);
LogicValue value = LogicValue::unknown;
if (bdd == Cudd_ReadLogicZero(cudd_manager_))
if (bdd == Cudd_ReadLogicZero(cudd_mgr_))
value = LogicValue::zero;
else if (bdd == Cudd_ReadOne(cudd_manager_))
else if (bdd == Cudd_ReadOne(cudd_mgr_))
value = LogicValue::one;
if (bdd) {
Cudd_RecursiveDeref(cudd_manager_, bdd);
Cudd_RecursiveDeref(cudd_mgr_, bdd);
clearSymtab();
}
return value;
@ -153,10 +152,10 @@ Sim::funcBdd(const FuncExpr *expr,
LogicValue value = logicValue(pin);
switch (value) {
case LogicValue::zero:
result = Cudd_ReadLogicZero(cudd_manager_);
result = Cudd_ReadLogicZero(cudd_mgr_);
break;
case LogicValue::one:
result = Cudd_ReadOne(cudd_manager_);
result = Cudd_ReadOne(cudd_mgr_);
break;
default:
result = ensureNode(port);
@ -174,7 +173,7 @@ Sim::funcBdd(const FuncExpr *expr,
left = funcBdd(expr->left(), inst);
right = funcBdd(expr->right(), inst);
if (left && right)
result = Cudd_bddOr(cudd_manager_, left, right);
result = Cudd_bddOr(cudd_mgr_, left, right);
else if (left)
result = left;
else if (right)
@ -184,7 +183,7 @@ Sim::funcBdd(const FuncExpr *expr,
left = funcBdd(expr->left(), inst);
right = funcBdd(expr->right(), inst);
if (left && right)
result = Cudd_bddAnd(cudd_manager_, left, right);
result = Cudd_bddAnd(cudd_mgr_, left, right);
else if (left)
result = left;
else if (right)
@ -194,17 +193,17 @@ Sim::funcBdd(const FuncExpr *expr,
left = funcBdd(expr->left(), inst);
right = funcBdd(expr->right(), inst);
if (left && right)
result = Cudd_bddXor(cudd_manager_, left, right);
result = Cudd_bddXor(cudd_mgr_, left, right);
else if (left)
result = left;
else if (right)
result = right;
break;
case FuncExpr::op_one:
result = Cudd_ReadOne(cudd_manager_);
result = Cudd_ReadOne(cudd_mgr_);
break;
case FuncExpr::op_zero:
result = Cudd_ReadLogicZero(cudd_manager_);
result = Cudd_ReadLogicZero(cudd_mgr_);
break;
default:
report_->critical(596, "unknown function operator");
@ -212,9 +211,9 @@ Sim::funcBdd(const FuncExpr *expr,
if (result)
Cudd_Ref(result);
if (left)
Cudd_RecursiveDeref(cudd_manager_, left);
Cudd_RecursiveDeref(cudd_mgr_, left);
if (right)
Cudd_RecursiveDeref(cudd_manager_, right);
Cudd_RecursiveDeref(cudd_mgr_, right);
return result;
}
@ -224,7 +223,7 @@ Sim::ensureNode(LibertyPort *port) const
const char *port_name = port->name();
DdNode *node = symtab_.findKey(port_name);
if (node == nullptr) {
node = Cudd_bddNewVar(cudd_manager_);
node = Cudd_bddNewVar(cudd_mgr_);
symtab_[port_name] = node;
Cudd_Ref(node);
}

View File

@ -129,16 +129,14 @@ protected:
InstanceSet instances_with_const_pins_;
InstanceSet instances_to_annotate_;
#ifdef CUDD
DdNode *funcBdd(const FuncExpr *expr,
const Instance *inst) const;
DdNode *ensureNode(LibertyPort *port) const;
void clearSymtab() const;
DdManager *cudd_manager_;
DdManager *cudd_mgr_;
mutable BddSymbolTable symtab_;
mutable std::mutex cudd_lock_;
#endif // CUDD
};
// Abstract base class for Sim value change observer.