power use density instead of activity
commit f9ac0ee51e238b30c4ace2d925344da612ccccee
Author: James Cherry <cherry@parallaxsw.com>
Date: Fri Jan 17 13:00:30 2025 -0700
doc
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 4619c083ef70c19e4cae71b351ccf25190983f11
Author: James Cherry <cherry@parallaxsw.com>
Date: Fri Jan 17 10:02:50 2025 -0700
activity -> density
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit aad7d4c03a9138f0b00a9d7a756bf183760df8eb
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Jan 16 22:14:39 2025 -0700
power all but 2 regressions
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 2d9465c6e5035d221fc4d3ec32f4997a28aa9877
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Jan 16 16:22:32 2025 -0700
power activity -> densiity
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 5d3c6ef2c3b178cf8f4958fcc6cdc37ccac4a067
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Jan 16 11:54:05 2025 -0700
power1 passes
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit f8344e412eb398067d83387fec52b352bbd7eb06
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Jan 16 10:30:04 2025 -0700
set_power_activity -density
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
fbb4b8c6e6
commit
b2646a96d0
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -38,17 +38,17 @@ class PwrActivity
|
|||
{
|
||||
public:
|
||||
PwrActivity();
|
||||
PwrActivity(float activity,
|
||||
PwrActivity(float density,
|
||||
float duty,
|
||||
PwrActivityOrigin origin);
|
||||
float activity() const { return activity_; }
|
||||
void setActivity(float activity);
|
||||
float density() const { return density_; }
|
||||
void setDensity(float density);
|
||||
float duty() const { return duty_; }
|
||||
void setDuty(float duty);
|
||||
PwrActivityOrigin origin() const { return origin_; }
|
||||
void setOrigin(PwrActivityOrigin origin);
|
||||
const char *originName() const;
|
||||
void set(float activity,
|
||||
void set(float density,
|
||||
float duty,
|
||||
PwrActivityOrigin origin);
|
||||
bool isSet() const;
|
||||
|
|
@ -56,12 +56,11 @@ public:
|
|||
private:
|
||||
void check();
|
||||
|
||||
// In general activity is per clock cycle, NOT per second.
|
||||
float activity_;
|
||||
float duty_;
|
||||
float density_; // transitions / second
|
||||
float duty_; // probability signal is high
|
||||
PwrActivityOrigin origin_;
|
||||
|
||||
static constexpr float min_activity = 1E-10;
|
||||
static constexpr float min_density = 1E-10;
|
||||
};
|
||||
|
||||
class PowerResult
|
||||
|
|
|
|||
|
|
@ -1292,7 +1292,7 @@ public:
|
|||
PowerResult &pad);
|
||||
PowerResult power(const Instance *inst,
|
||||
const Corner *corner);
|
||||
PwrActivity findClkedActivity(const Pin *pin);
|
||||
PwrActivity activity(const Pin *pin);
|
||||
|
||||
void writeTimingModel(const char *lib_name,
|
||||
const char *cell_name,
|
||||
|
|
|
|||
181
power/Power.cc
181
power/Power.cc
|
|
@ -59,13 +59,12 @@
|
|||
// input_voltage : default_VDD_VSS_input;
|
||||
// pin
|
||||
// output_voltage : default_VDD_VSS_output;
|
||||
//
|
||||
// transition_density = activity / clock_period
|
||||
|
||||
namespace sta {
|
||||
|
||||
using std::abs;
|
||||
using std::max;
|
||||
using std::min;
|
||||
using std::isnormal;
|
||||
|
||||
static bool
|
||||
|
|
@ -87,8 +86,8 @@ static EnumNameMap<PwrActivityOrigin> pwr_activity_origin_map =
|
|||
|
||||
Power::Power(StaState *sta) :
|
||||
StaState(sta),
|
||||
global_activity_{0.0, 0.0, PwrActivityOrigin::unknown},
|
||||
input_activity_{0.1, 0.5, PwrActivityOrigin::input},
|
||||
global_activity_(),
|
||||
input_activity_(), // default set in ensureActivities()
|
||||
seq_activity_map_(100, SeqPinHash(network_), SeqPinEqual()),
|
||||
activities_valid_(false),
|
||||
bdd_(sta)
|
||||
|
|
@ -96,41 +95,41 @@ Power::Power(StaState *sta) :
|
|||
}
|
||||
|
||||
void
|
||||
Power::setGlobalActivity(float activity,
|
||||
Power::setGlobalActivity(float density,
|
||||
float duty)
|
||||
{
|
||||
global_activity_.set(activity, duty, PwrActivityOrigin::global);
|
||||
global_activity_.set(density, duty, PwrActivityOrigin::global);
|
||||
activities_valid_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
Power::setInputActivity(float activity,
|
||||
Power::setInputActivity(float density,
|
||||
float duty)
|
||||
{
|
||||
input_activity_.set(activity, duty, PwrActivityOrigin::input);
|
||||
input_activity_.set(density, duty, PwrActivityOrigin::input);
|
||||
activities_valid_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
Power::setInputPortActivity(const Port *input_port,
|
||||
float activity,
|
||||
float density,
|
||||
float duty)
|
||||
{
|
||||
Instance *top_inst = network_->topInstance();
|
||||
const Pin *pin = network_->findPin(top_inst, input_port);
|
||||
if (pin) {
|
||||
user_activity_map_[pin] = {activity, duty, PwrActivityOrigin::user};
|
||||
user_activity_map_[pin] = {density, duty, PwrActivityOrigin::user};
|
||||
activities_valid_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Power::setUserActivity(const Pin *pin,
|
||||
float activity,
|
||||
float density,
|
||||
float duty,
|
||||
PwrActivityOrigin origin)
|
||||
{
|
||||
user_activity_map_[pin] = {activity, duty, origin};
|
||||
user_activity_map_[pin] = {density, duty, origin};
|
||||
activities_valid_ = false;
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +151,7 @@ Power::setActivity(const Pin *pin,
|
|||
{
|
||||
debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f %s",
|
||||
network_->pathName(pin),
|
||||
activity.activity(),
|
||||
activity.density(),
|
||||
activity.duty(),
|
||||
pwr_activity_origin_map.find(activity.origin()));
|
||||
activity_map_[pin] = activity;
|
||||
|
|
@ -403,7 +402,7 @@ PropActivityVisitor::visit(Vertex *vertex)
|
|||
Vertex *from_vertex = edge->from(graph_);
|
||||
const Pin *from_pin = from_vertex->pin();
|
||||
PwrActivity &from_activity = power_->activity(from_pin);
|
||||
PwrActivity to_activity(from_activity.activity(),
|
||||
PwrActivity to_activity(from_activity.density(),
|
||||
from_activity.duty(),
|
||||
PwrActivityOrigin::propagated);
|
||||
changed = setActivityCheck(pin, to_activity);
|
||||
|
|
@ -426,13 +425,13 @@ PropActivityVisitor::visit(Vertex *vertex)
|
|||
PwrActivity activity2 = power_->findActivity(enable);
|
||||
float p1 = activity1.duty();
|
||||
float p2 = activity2.duty();
|
||||
PwrActivity activity(activity1.activity() * p2 + activity2.activity() * p1,
|
||||
PwrActivity activity(activity1.density() * p2 + activity2.density() * p1,
|
||||
p1 * p2,
|
||||
PwrActivityOrigin::propagated);
|
||||
changed = setActivityCheck(gclk, activity);
|
||||
debugPrint(debug_, "power_activity", 3, "gated_clk %s %.2e %.2f",
|
||||
network_->pathName(gclk),
|
||||
activity.activity(),
|
||||
activity.density(),
|
||||
activity.duty());
|
||||
}
|
||||
}
|
||||
|
|
@ -467,16 +466,16 @@ PropActivityVisitor::setActivityCheck(const Pin *pin,
|
|||
PwrActivity &activity)
|
||||
{
|
||||
float min_rf_slew = power_->getMinRfSlew(pin);
|
||||
float max_activity = (min_rf_slew > 0.0) ? 1.0 / min_rf_slew : INF;
|
||||
if (activity.activity() > max_activity)
|
||||
activity.setActivity(max_activity);
|
||||
float max_density = (min_rf_slew > 0.0) ? 1.0 / min_rf_slew : INF;
|
||||
if (activity.density() > max_density)
|
||||
activity.setDensity(max_density);
|
||||
PwrActivity &prev_activity = power_->activity(pin);
|
||||
float activity_delta = abs(activity.activity() - prev_activity.activity());
|
||||
float density_delta = abs(activity.density() - prev_activity.density());
|
||||
float duty_delta = abs(activity.duty() - prev_activity.duty());
|
||||
if (activity_delta > change_tolerance_
|
||||
if (density_delta > change_tolerance_
|
||||
|| duty_delta > change_tolerance_
|
||||
|| activity.origin() != prev_activity.origin()) {
|
||||
max_change_ = max(max_change_, activity_delta);
|
||||
max_change_ = max(max_change_, density_delta);
|
||||
max_change_ = max(max_change_, duty_delta);
|
||||
power_->setActivity(pin, activity);
|
||||
return true;
|
||||
|
|
@ -521,11 +520,11 @@ Power::evalActivity(FuncExpr *expr,
|
|||
else {
|
||||
DdNode *bdd = bdd_.funcBdd(expr);
|
||||
float duty = evalBddDuty(bdd, inst);
|
||||
float activity = evalBddActivity(bdd, inst);
|
||||
float density = evalBddActivity(bdd, inst);
|
||||
|
||||
Cudd_RecursiveDeref(bdd_.cuddMgr(), bdd);
|
||||
bdd_.clearVarMap();
|
||||
return PwrActivity(activity, duty, PwrActivityOrigin::propagated);
|
||||
return PwrActivity(density, duty, PwrActivityOrigin::propagated);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -592,7 +591,7 @@ float
|
|||
Power::evalBddActivity(DdNode *bdd,
|
||||
const Instance *inst)
|
||||
{
|
||||
float activity = 0.0;
|
||||
float density = 0.0;
|
||||
for (const auto [port, var_node] : bdd_.portVarMap()) {
|
||||
const Pin *pin = findLinkPin(inst, port);
|
||||
if (pin) {
|
||||
|
|
@ -602,21 +601,16 @@ Power::evalBddActivity(DdNode *bdd,
|
|||
Cudd_Ref(diff);
|
||||
float diff_duty = evalBddDuty(diff, inst);
|
||||
Cudd_RecursiveDeref(bdd_.cuddMgr(), diff);
|
||||
float var_act = var_activity.activity() * diff_duty;
|
||||
activity += var_act;
|
||||
if (debug_->check("power_activity", 3)) {
|
||||
const Clock *clk = findClk(pin);
|
||||
float clk_period = clk ? clk->period() : 1.0;
|
||||
debugPrint(debug_, "power_activity", 3, "var %s%s %.3e * %.3f = %.3e",
|
||||
float var_density = var_activity.density() * diff_duty;
|
||||
density += var_density;
|
||||
debugPrint(debug_, "power_activity", 3, "var %s %.3e * %.3f = %.3e",
|
||||
port->name(),
|
||||
clk ? "" : " (unclocked)",
|
||||
var_activity.activity() / clk_period,
|
||||
var_activity.density(),
|
||||
diff_duty,
|
||||
var_act / clk_period);
|
||||
var_density);
|
||||
}
|
||||
}
|
||||
}
|
||||
return activity;
|
||||
return density;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -632,6 +626,13 @@ Power::ensureActivities()
|
|||
activity_map_.clear();
|
||||
seq_activity_map_.clear();
|
||||
|
||||
// Initialize default input activity (after sdc is defined)
|
||||
// unless it has been set by command.
|
||||
if (input_activity_.density() == 0.0) {
|
||||
float min_period = clockMinPeriod();
|
||||
float density = 0.1 / (min_period != 0.0 ? min_period : 0.0);
|
||||
input_activity_.set(density, 0.5, PwrActivityOrigin::input);
|
||||
}
|
||||
ActivitySrchPred activity_srch_pred(this);
|
||||
BfsFwdIterator bfs(BfsIndex::other, &activity_srch_pred, this);
|
||||
seedActivities(bfs);
|
||||
|
|
@ -726,9 +727,17 @@ Power::seedRegOutputActivities(const Instance *reg,
|
|||
PwrActivity activity = evalActivity(seq->data(), reg);
|
||||
// Register output activity cannnot exceed one transition per clock cycle,
|
||||
// but latch output can.
|
||||
if (seq->isRegister()
|
||||
&& activity.activity() > 1.0)
|
||||
activity.setActivity(1.0);
|
||||
if (seq->isRegister()) {
|
||||
FuncExpr *clk_func = seq->clock();
|
||||
if (clk_func->port()) {
|
||||
const Pin *pin = network_->findPin(reg, clk_func->port());
|
||||
const Clock *clk = findClk(pin);
|
||||
if (clk) {
|
||||
if (activity.density() > 1.0 / clk->period())
|
||||
activity.setDensity(1.0 / clk->period());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invert)
|
||||
activity.setDuty(1.0 - activity.duty());
|
||||
activity.setOrigin(PwrActivityOrigin::propagated);
|
||||
|
|
@ -744,9 +753,8 @@ Power::power(const Instance *inst,
|
|||
const Corner *corner)
|
||||
{
|
||||
PowerResult result;
|
||||
const Clock *inst_clk = findInstClk(inst);
|
||||
findInternalPower(inst, cell, corner, inst_clk, result);
|
||||
findSwitchingPower(inst, cell, corner, inst_clk, result);
|
||||
findInternalPower(inst, cell, corner, result);
|
||||
findSwitchingPower(inst, cell, corner, result);
|
||||
findLeakagePower(inst, cell, corner, result);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -772,7 +780,6 @@ void
|
|||
Power::findInternalPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Corner *corner,
|
||||
const Clock *inst_clk,
|
||||
// Return values.
|
||||
PowerResult &result)
|
||||
{
|
||||
|
|
@ -785,7 +792,7 @@ Power::findInternalPower(const Instance *inst,
|
|||
float load_cap = to_port->direction()->isAnyOutput()
|
||||
? graph_delay_calc_->loadCap(to_pin, dcalc_ap)
|
||||
: 0.0;
|
||||
PwrActivity activity = findClkedActivity(to_pin, inst_clk);
|
||||
PwrActivity activity = findActivity(to_pin);
|
||||
if (to_port->direction()->isAnyOutput())
|
||||
findOutputInternalPower(to_port, inst, cell, activity,
|
||||
load_cap, corner, result);
|
||||
|
|
@ -854,11 +861,11 @@ Power::findInputInternalPower(const Pin *pin,
|
|||
else
|
||||
duty = evalActivity(when, inst).duty();
|
||||
}
|
||||
float port_internal = energy * duty * activity.activity();
|
||||
float port_internal = energy * duty * activity.density();
|
||||
debugPrint(debug_, "power", 2, " %3s %6s %.2f %.2f %9.2e %9.2e %s",
|
||||
port->name(),
|
||||
when ? when->asString() : "",
|
||||
activity.activity() * 1e-9,
|
||||
activity.density() * 1e-9,
|
||||
duty,
|
||||
energy,
|
||||
port_internal,
|
||||
|
|
@ -961,11 +968,11 @@ Power::findOutputInternalPower(const LibertyPort *to_port,
|
|||
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 from_density = findActivity(from_pin).density();
|
||||
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;
|
||||
pg_duty_sum[related_pg_pin] += from_density * duty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1007,16 +1014,16 @@ Power::findOutputInternalPower(const LibertyPort *to_port,
|
|||
if (duty_sum_iter != pg_duty_sum.end()) {
|
||||
float duty_sum = duty_sum_iter->second;
|
||||
if (duty_sum != 0.0 && from_pin) {
|
||||
float from_activity = findActivity(from_pin).activity();
|
||||
weight = from_activity * duty / duty_sum;
|
||||
float from_density = findActivity(from_pin).density();
|
||||
weight = from_density * duty / duty_sum;
|
||||
}
|
||||
}
|
||||
float port_internal = weight * energy * to_activity.activity();
|
||||
float port_internal = weight * energy * to_activity.density();
|
||||
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() : "",
|
||||
to_activity.activity() * 1e-9,
|
||||
to_activity.density() * 1e-9,
|
||||
duty,
|
||||
weight,
|
||||
energy,
|
||||
|
|
@ -1048,7 +1055,7 @@ Power::findInputDuty(const Instance *inst,
|
|||
else if (when)
|
||||
return evalActivity(when, inst).duty();
|
||||
else if (search_->isClock(from_vertex))
|
||||
return 1.0;
|
||||
return 0.5;
|
||||
return 0.5;
|
||||
}
|
||||
}
|
||||
|
|
@ -1093,7 +1100,6 @@ void
|
|||
Power::findSwitchingPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Corner *corner,
|
||||
const Clock *inst_clk,
|
||||
// Return values.
|
||||
PowerResult &result)
|
||||
{
|
||||
|
|
@ -1107,14 +1113,14 @@ Power::findSwitchingPower(const Instance *inst,
|
|||
float load_cap = to_port->direction()->isAnyOutput()
|
||||
? graph_delay_calc_->loadCap(to_pin, dcalc_ap)
|
||||
: 0.0;
|
||||
PwrActivity activity = findClkedActivity(to_pin, inst_clk);
|
||||
PwrActivity activity = findActivity(to_pin);
|
||||
if (to_port->direction()->isAnyOutput()) {
|
||||
float volt = portVoltage(corner_cell, to_port, dcalc_ap);
|
||||
float switching = .5 * load_cap * volt * volt * activity.activity();
|
||||
float switching = .5 * load_cap * volt * volt * activity.density();
|
||||
debugPrint(debug_, "power", 2, "switching %s/%s activity = %.2e volt = %.2f %.3e",
|
||||
cell->name(),
|
||||
to_port->name(),
|
||||
activity.activity(),
|
||||
activity.density(),
|
||||
volt,
|
||||
switching);
|
||||
result.incrSwitching(switching);
|
||||
|
|
@ -1188,31 +1194,12 @@ Power::findLeakagePower(const Instance *inst,
|
|||
result.incrLeakage(leakage);
|
||||
}
|
||||
|
||||
// External.
|
||||
PwrActivity
|
||||
Power::findClkedActivity(const Pin *pin)
|
||||
Power::pinActivity(const Pin *pin)
|
||||
{
|
||||
const Instance *inst = network_->instance(pin);
|
||||
const Clock *inst_clk = findInstClk(inst);
|
||||
ensureActivities();
|
||||
return findClkedActivity(pin, inst_clk);
|
||||
}
|
||||
|
||||
PwrActivity
|
||||
Power::findClkedActivity(const Pin *pin,
|
||||
const Clock *inst_clk)
|
||||
{
|
||||
PwrActivity activity = findActivity(pin);
|
||||
const Clock *clk = findClk(pin);
|
||||
if (clk == nullptr)
|
||||
clk = inst_clk;
|
||||
if (clk) {
|
||||
float period = clk->period();
|
||||
if (period > 0.0)
|
||||
return PwrActivity(activity.activity() / period,
|
||||
activity.duty(),
|
||||
activity.origin());
|
||||
}
|
||||
return activity;
|
||||
return findActivity(pin);
|
||||
}
|
||||
|
||||
PwrActivity
|
||||
|
|
@ -1229,7 +1216,7 @@ Power::findActivity(const Pin *pin)
|
|||
}
|
||||
const Clock *clk = findClk(pin);
|
||||
float duty = clockDuty(clk);
|
||||
return PwrActivity(2.0, duty, PwrActivityOrigin::clock);
|
||||
return PwrActivity(2.0 / clk->period(), duty, PwrActivityOrigin::clock);
|
||||
}
|
||||
else if (global_activity_.isSet())
|
||||
return global_activity_;
|
||||
|
|
@ -1438,6 +1425,20 @@ Power::pinCount()
|
|||
return count;
|
||||
}
|
||||
|
||||
float
|
||||
Power::clockMinPeriod()
|
||||
{
|
||||
ClockSeq *clks = sdc_->clocks();
|
||||
if (clks && !clks->empty()) {
|
||||
float min_period = INF;
|
||||
for (const Clock *clk : *clks)
|
||||
min_period = min(min_period, clk->period());
|
||||
return min_period;
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PowerResult::PowerResult() :
|
||||
|
|
@ -1489,17 +1490,17 @@ PowerResult::incr(PowerResult &result)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PwrActivity::PwrActivity(float activity,
|
||||
PwrActivity::PwrActivity(float density,
|
||||
float duty,
|
||||
PwrActivityOrigin origin) :
|
||||
activity_(activity),
|
||||
density_(density),
|
||||
duty_(duty),
|
||||
origin_(origin)
|
||||
{
|
||||
}
|
||||
|
||||
PwrActivity::PwrActivity() :
|
||||
activity_(0.0),
|
||||
density_(0.0),
|
||||
duty_(0.0),
|
||||
origin_(PwrActivityOrigin::unknown)
|
||||
{
|
||||
|
|
@ -1507,9 +1508,9 @@ PwrActivity::PwrActivity() :
|
|||
}
|
||||
|
||||
void
|
||||
PwrActivity::setActivity(float activity)
|
||||
PwrActivity::setDensity(float density)
|
||||
{
|
||||
activity_ = activity;
|
||||
density_ = density;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1525,11 +1526,11 @@ PwrActivity::setOrigin(PwrActivityOrigin origin)
|
|||
}
|
||||
|
||||
void
|
||||
PwrActivity::set(float activity,
|
||||
PwrActivity::set(float density,
|
||||
float duty,
|
||||
PwrActivityOrigin origin)
|
||||
{
|
||||
activity_ = activity;
|
||||
density_ = density;
|
||||
duty_ = duty;
|
||||
origin_ = origin;
|
||||
check();
|
||||
|
|
@ -1538,11 +1539,11 @@ PwrActivity::set(float activity,
|
|||
void
|
||||
PwrActivity::check()
|
||||
{
|
||||
// Activities can get very small from multiplying probabilities
|
||||
// Densities can get very small from multiplying probabilities
|
||||
// through deep chains of logic. Clip them to prevent floating
|
||||
// point anomalies.
|
||||
if (abs(activity_) < min_activity)
|
||||
activity_ = 0.0;
|
||||
if (abs(density_) < min_density)
|
||||
density_ = 0.0;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -84,17 +84,17 @@ public:
|
|||
void setInputPortActivity(const Port *input_port,
|
||||
float activity,
|
||||
float duty);
|
||||
PwrActivity &activity(const Pin *pin);
|
||||
PwrActivity pinActivity(const Pin *pin);
|
||||
void setUserActivity(const Pin *pin,
|
||||
float activity,
|
||||
float duty,
|
||||
PwrActivityOrigin origin);
|
||||
// Activity is toggles per second.
|
||||
PwrActivity findClkedActivity(const Pin *pin);
|
||||
void reportActivityAnnotation(bool report_unannotated,
|
||||
bool report_annotated);
|
||||
float clockMinPeriod();
|
||||
|
||||
protected:
|
||||
PwrActivity &activity(const Pin *pin);
|
||||
bool inClockNetwork(const Instance *inst);
|
||||
void powerInside(const Instance *hinst,
|
||||
const Corner *corner,
|
||||
|
|
@ -112,6 +112,7 @@ protected:
|
|||
bool hasActivity(const Pin *pin);
|
||||
void setActivity(const Pin *pin,
|
||||
PwrActivity &activity);
|
||||
PwrActivity findActivity(const Pin *pin);
|
||||
|
||||
PowerResult power(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
|
|
@ -119,7 +120,6 @@ protected:
|
|||
void findInternalPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Corner *corner,
|
||||
const Clock *inst_clk,
|
||||
// Return values.
|
||||
PowerResult &result);
|
||||
void findInputInternalPower(const Pin *to_pin,
|
||||
|
|
@ -147,7 +147,6 @@ protected:
|
|||
void findSwitchingPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Corner *corner,
|
||||
const Clock *inst_clk,
|
||||
// Return values.
|
||||
PowerResult &result);
|
||||
float getSlew(Vertex *vertex,
|
||||
|
|
@ -157,9 +156,6 @@ protected:
|
|||
const Clock *findInstClk(const Instance *inst);
|
||||
const Clock *findClk(const Pin *to_pin);
|
||||
float clockDuty(const Clock *clk);
|
||||
PwrActivity findClkedActivity(const Pin *pin,
|
||||
const Clock *inst_clk);
|
||||
PwrActivity findActivity(const Pin *pin);
|
||||
PwrActivity findSeqActivity(const Instance *inst,
|
||||
LibertyPort *port);
|
||||
float portVoltage(LibertyCell *cell,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
%{
|
||||
#include "Sta.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "power/Power.hh"
|
||||
#include "power/VcdReader.hh"
|
||||
#include "power/SaifReader.hh"
|
||||
|
|
@ -101,6 +102,13 @@ set_power_pin_activity(const Pin *pin,
|
|||
return power->setUserActivity(pin, activity, duty, PwrActivityOrigin::user);
|
||||
}
|
||||
|
||||
float
|
||||
clock_min_period()
|
||||
{
|
||||
Power *power = Sta::sta()->power();
|
||||
return power->clockMinPeriod();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -217,46 +217,67 @@ define_cmd_args "set_power_activity" { [-global]\
|
|||
[-input]\
|
||||
[-input_ports ports]\
|
||||
[-pins pins]\
|
||||
[-activity activity]\
|
||||
[-duty duty] }
|
||||
[-activity activity | -density density]\
|
||||
[-duty duty]\
|
||||
[-clock clock]}
|
||||
|
||||
proc set_power_activity { args } {
|
||||
parse_key_args "set_power_activity" args \
|
||||
keys {-input_ports -pins -activity -duty} \
|
||||
keys {-input_ports -pins -activity -density -duty -clock} \
|
||||
flags {-global -input}
|
||||
|
||||
check_argc_eq0 "set_power_activity" $args
|
||||
set activity 0.0
|
||||
if { [info exists keys(-activity)] && [info exists keys(-density)] \
|
||||
|| ![info exists keys(-activity)] && ![info exists keys(-density)] } {
|
||||
sta_error 306 "Specify -activity or -density."
|
||||
}
|
||||
|
||||
set density 0.0
|
||||
if { [info exists keys(-activity)] } {
|
||||
set activity $keys(-activity)
|
||||
check_float "activity" $activity
|
||||
if { $activity < 0.0 } {
|
||||
sta_warn 301 "activity should be 0.0 to 1.0 or 2.0"
|
||||
check_positive_float "activity" $activity
|
||||
if { [info exists keys(-clock)] } {
|
||||
set clk [get_clock_warn "-clock" $keys(-clock)]
|
||||
} else {
|
||||
set clks [get_clocks]
|
||||
if { $clks == {} } {
|
||||
sta_error 307 "-activity requires a clock to be defined"
|
||||
}
|
||||
}
|
||||
set density [expr $activity / [clock_min_period]]
|
||||
}
|
||||
|
||||
if { [info exists keys(-density)] } {
|
||||
set density $keys(-density)
|
||||
check_positive_float "density" $density
|
||||
set density [expr $density / [time_ui_sta 1.0]]
|
||||
if { [info exists keys(-clock)] } {
|
||||
sta_warn 302 "-clock ignored for -density"
|
||||
}
|
||||
}
|
||||
set duty 0.5
|
||||
if { [info exists keys(-duty)] } {
|
||||
set duty $keys(-duty)
|
||||
check_float "duty" $duty
|
||||
if { $duty < 0.0 || $duty > 1.0 } {
|
||||
sta_warn 302 "duty should be 0.0 to 1.0"
|
||||
if { $duty < 0.0 || $duty > 1.0 } {i
|
||||
sta_error 302 "duty should be 0.0 to 1.0"
|
||||
}
|
||||
}
|
||||
|
||||
if { [info exists flags(-global)] } {
|
||||
set_power_global_activity $activity $duty
|
||||
set_power_global_activity $density $duty
|
||||
}
|
||||
if { [info exists flags(-input)] } {
|
||||
set_power_input_activity $activity $duty
|
||||
set_power_input_activity $density $duty
|
||||
}
|
||||
if { [info exists keys(-input_ports)] } {
|
||||
set ports [get_ports_error "input_ports" $keys(-input_ports)]
|
||||
foreach port $ports {
|
||||
if { [get_property $port "direction"] == "input" } {
|
||||
if { [sta::is_clock_src [sta::get_port_pin $port]] } {
|
||||
if { [is_clock_src [sta::get_port_pin $port]] } {
|
||||
sta_warn 303 "activity cannot be set on clock ports."
|
||||
} else {
|
||||
set_power_input_port_activity $port $activity $duty
|
||||
set_power_input_port_activity $port $density $duty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -264,7 +285,7 @@ proc set_power_activity { args } {
|
|||
if { [info exists keys(-pins)] } {
|
||||
set pins [get_pins $keys(-pins)]
|
||||
foreach pin $pins {
|
||||
set_power_pin_activity $pin $activity $duty
|
||||
set_power_pin_activity $pin $density $duty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ SaifReader::SaifReader(const char *filename,
|
|||
escape_('\\'),
|
||||
timescale_(1.0E-9F), // default units of ns
|
||||
duration_(0.0),
|
||||
clk_period_(0.0),
|
||||
in_scope_level_(0),
|
||||
power_(sta->power())
|
||||
{
|
||||
|
|
@ -79,10 +78,6 @@ SaifReader::read()
|
|||
// Use zlib to uncompress gzip'd files automagically.
|
||||
stream_ = gzopen(filename_, "rb");
|
||||
if (stream_) {
|
||||
clk_period_ = INF;
|
||||
for (Clock *clk : *sdc_->clocks())
|
||||
clk_period_ = min(static_cast<double>(clk->period()), clk_period_);
|
||||
|
||||
saif_scope_.clear();
|
||||
in_scope_level_ = 0;
|
||||
annotated_pins_.clear();
|
||||
|
|
@ -185,16 +180,16 @@ SaifReader::setNetDurations(const char *net_name,
|
|||
double t1 = durations[static_cast<int>(SaifState::T1)];
|
||||
float duty = t1 / duration_;
|
||||
double tc = durations[static_cast<int>(SaifState::TC)];
|
||||
float activity = tc / (duration_ * timescale_ / clk_period_);
|
||||
float density = tc / (duration_ * timescale_);
|
||||
debugPrint(debug_, "read_saif", 2,
|
||||
"%s duty %.0f / %" PRIu64 " = %.2f tc %.0f activity %.2f",
|
||||
"%s duty %.0f / %" PRIu64 " = %.2f tc %.0f density %.2f",
|
||||
sdc_network_->pathName(pin),
|
||||
t1,
|
||||
duration_,
|
||||
duty,
|
||||
tc,
|
||||
activity);
|
||||
power_->setUserActivity(pin, activity, duty, PwrActivityOrigin::saif);
|
||||
density);
|
||||
power_->setUserActivity(pin, density, duty, PwrActivityOrigin::saif);
|
||||
annotated_pins_.insert(pin);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ private:
|
|||
char escape_;
|
||||
double timescale_;
|
||||
int64_t duration_;
|
||||
double clk_period_;
|
||||
|
||||
vector<string> saif_scope_; // Scope during parsing.
|
||||
size_t in_scope_level_;
|
||||
|
|
|
|||
|
|
@ -345,7 +345,6 @@ private:
|
|||
const char *filename_;
|
||||
VcdCountReader vcd_reader_;
|
||||
VcdParse vcd_parse_;
|
||||
double clk_period_;
|
||||
|
||||
Power *power_;
|
||||
std::set<const Pin*> annotated_pins_;
|
||||
|
|
@ -369,7 +368,6 @@ ReadVcdActivities::ReadVcdActivities(const char *filename,
|
|||
filename_(filename),
|
||||
vcd_reader_(scope, sdc_network_, report_, debug_),
|
||||
vcd_parse_(report_, debug_),
|
||||
clk_period_(0.0),
|
||||
power_(sta->power())
|
||||
{
|
||||
}
|
||||
|
|
@ -380,9 +378,6 @@ ReadVcdActivities::readActivities()
|
|||
ClockSeq *clks = sdc_->clocks();
|
||||
if (clks->empty())
|
||||
report_->error(805, "No clocks have been defined.");
|
||||
clk_period_ = INF;
|
||||
for (Clock *clk : *clks)
|
||||
clk_period_ = min(static_cast<double>(clk->period()), clk_period_);
|
||||
|
||||
vcd_parse_.read(filename_, &vcd_reader_);
|
||||
|
||||
|
|
@ -403,19 +398,19 @@ ReadVcdActivities::setActivities()
|
|||
double transition_count = vcd_count.transitionCount();
|
||||
VcdTime high_time = vcd_count.highTime(time_max);
|
||||
float duty = static_cast<double>(high_time) / time_max;
|
||||
float activity = transition_count / (time_max * time_scale / clk_period_);
|
||||
float density = transition_count / (time_max * time_scale);
|
||||
if (debug_->check("read_vcd_activities", 1)) {
|
||||
for (const Pin *pin : vcd_count.pins()) {
|
||||
debugPrint(debug_, "read_vcd_activities", 1,
|
||||
"%s transitions %.1f activity %.2f duty %.2f",
|
||||
sdc_network_->pathName(pin),
|
||||
transition_count,
|
||||
activity,
|
||||
density,
|
||||
duty);
|
||||
}
|
||||
}
|
||||
for (const Pin *pin : vcd_count.pins()) {
|
||||
power_->setUserActivity(pin, activity, duty, PwrActivityOrigin::vcd);
|
||||
power_->setUserActivity(pin, density, duty, PwrActivityOrigin::vcd);
|
||||
if (sdc_->isLeafPinClock(pin))
|
||||
checkClkPeriod(pin, transition_count);
|
||||
annotated_pins_.insert(pin);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ proc_redirect read_sdf {
|
|||
################################################################
|
||||
|
||||
define_cmd_args "report_annotated_delay" \
|
||||
{[-cell] [-net] [-from_in_ports] [-to_out_ports] [-max_lines liness]\
|
||||
{[-cell] [-net] [-from_in_ports] [-to_out_ports] [-max_lines lines]\
|
||||
[-list_annotated] [-list_not_annotated] [-constant_arcs]}
|
||||
|
||||
proc_redirect report_annotated_delay {
|
||||
|
|
@ -92,7 +92,7 @@ proc_redirect report_annotated_delay {
|
|||
|
||||
define_cmd_args "report_annotated_check" \
|
||||
{[-setup] [-hold] [-recovery] [-removal] [-nochange] [-width] [-period]\
|
||||
[-max_skew] [-max_lines liness] [-list_annotated] [-list_not_annotated]\
|
||||
[-max_skew] [-max_lines lines] [-list_annotated] [-list_not_annotated]\
|
||||
[-constant_arcs]}
|
||||
|
||||
proc_redirect report_annotated_check {
|
||||
|
|
|
|||
|
|
@ -780,7 +780,7 @@ getProperty(const Port *port,
|
|||
else if (stringEqual(property, "activity")) {
|
||||
const Instance *top_inst = network->topInstance();
|
||||
const Pin *pin = network->findPin(top_inst, port);
|
||||
PwrActivity activity = sta->findClkedActivity(pin);
|
||||
PwrActivity activity = sta->activity(pin);
|
||||
return PropertyValue(&activity);
|
||||
}
|
||||
|
||||
|
|
@ -998,7 +998,7 @@ getProperty(const Pin *pin,
|
|||
return PropertyValue(&clks);
|
||||
}
|
||||
else if (stringEqual(property, "activity")) {
|
||||
PwrActivity activity = sta->findClkedActivity(pin);
|
||||
PwrActivity activity = sta->activity(pin);
|
||||
return PropertyValue(&activity);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5696,10 +5696,10 @@ Sta::power(const Instance *inst,
|
|||
}
|
||||
|
||||
PwrActivity
|
||||
Sta::findClkedActivity(const Pin *pin)
|
||||
Sta::activity(const Pin *pin)
|
||||
{
|
||||
powerPreamble();
|
||||
return power_->findClkedActivity(pin);
|
||||
return power_->pinActivity(pin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1370,7 +1370,7 @@ using namespace sta;
|
|||
Tcl_Obj *obj;
|
||||
const char *str;
|
||||
|
||||
str = stringPrintTmp("%.5e", activity.activity());
|
||||
str = stringPrintTmp("%.5e", activity.density());
|
||||
obj = Tcl_NewStringObj(str, strlen(str));
|
||||
Tcl_ListObjAppendElement(interp, list, obj);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ Warning: gcd_sky130hd.v line 527, module sky130_fd_sc_hd__tapvpwrvgnd_1 not foun
|
|||
Group Internal Switching Leakage Total
|
||||
Power Power Power Power (Watts)
|
||||
----------------------------------------------------------------
|
||||
Sequential 3.07e-04 4.75e-05 2.96e-10 3.54e-04 40.1%
|
||||
Combinational 1.58e-04 2.04e-04 6.86e-10 3.62e-04 41.0%
|
||||
Sequential 3.07e-04 4.76e-05 2.96e-10 3.54e-04 40.0%
|
||||
Combinational 1.59e-04 2.05e-04 6.86e-10 3.64e-04 41.1%
|
||||
Clock 4.68e-05 1.20e-04 2.30e-11 1.67e-04 18.9%
|
||||
Macro 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%
|
||||
Pad 0.00e+00 0.00e+00 0.00e+00 0.00e+00 0.0%
|
||||
----------------------------------------------------------------
|
||||
Total 5.11e-04 3.72e-04 1.00e-09 8.84e-04 100.0%
|
||||
57.9% 42.1% 0.0%
|
||||
Total 5.12e-04 3.73e-04 1.00e-09 8.85e-04 100.0%
|
||||
57.8% 42.2% 0.0%
|
||||
|
|
|
|||
Loading…
Reference in New Issue