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