From 7845105f4fcfce7f001f9ce55a6bafcd2ea98870 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 10 Nov 2023 09:59:50 -0700 Subject: [PATCH] power cudd support commit 872e7f91b4ce2a475063296b85ba99a2c76f665c Author: James Cherry Date: Fri Nov 10 09:54:02 2023 -0700 power cudd eval diff Signed-off-by: James Cherry commit 908dfaa08b165d59a38c25b5f534db4ca02540d8 Author: James Cherry Date: Wed Nov 8 19:13:33 2023 -0700 Power::seqActivity Signed-off-by: James Cherry commit 47a74dd6989dbd7cfe8127aa0be95dcf19a3cff4 Author: James Cherry Date: Wed Nov 8 18:03:01 2023 -0700 cudd default cache init Signed-off-by: James Cherry commit 87890f699280e0f4aea6c5610a2f1949a46a07ae Author: James Cherry Date: Wed Nov 8 13:48:58 2023 -0700 power buffer activity origin Signed-off-by: James Cherry commit 584b8124ab98d3cd42e23383aa35edb33e26e9d2 Author: James Cherry Date: Wed Nov 8 12:26:16 2023 -0700 power use cudd Signed-off-by: James Cherry Signed-off-by: James Cherry --- CMakeLists.txt | 4 +- include/sta/PowerClass.hh | 1 + power/Power.cc | 382 ++++++++++++++++++++++++++++++-------- power/Power.hh | 38 +++- search/Sim.cc | 43 +++-- search/Sim.hh | 4 +- 6 files changed, 354 insertions(+), 118 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e5353c0..9900ea38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}") diff --git a/include/sta/PowerClass.hh b/include/sta/PowerClass.hh index f7946979..57c9ad0a 100644 --- a/include/sta/PowerClass.hh +++ b/include/sta/PowerClass.hh @@ -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, diff --git a/power/Power.cc b/power/Power.cc index dee8e206..5350a331 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -17,7 +17,7 @@ #include "Power.hh" #include // max -#include // aps +#include // 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 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 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 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, diff --git a/power/Power.hh b/power/Power.hh index 7dd08827..f3075fb8 100644 --- a/power/Power.hh +++ b/power/Power.hh @@ -18,12 +18,16 @@ #include +#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 SeqPin; +typedef Map BddPortVarMap; +typedef Map 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; diff --git a/search/Sim.cc b/search/Sim.cc index e18bdf08..24c98e2b 100644 --- a/search/Sim.cc +++ b/search/Sim.cc @@ -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); } diff --git a/search/Sim.hh b/search/Sim.hh index 5344e77a..4f0a6690 100644 --- a/search/Sim.hh +++ b/search/Sim.hh @@ -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.