From 1bf9426e969166c3721edd060f3fe7ed65276a89 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 20 Dec 2025 09:11:41 -0700 Subject: [PATCH] power activity propagation thru reg/latch resolves #350 Signed-off-by: James Cherry --- power/Power.cc | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/power/Power.cc b/power/Power.cc index 4501bea8..8a9aed76 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -834,24 +834,34 @@ Power::seedRegOutputActivities(const Instance *reg, { const Pin *out_pin = network_->findPin(reg, output); if (!hasUserActivity(out_pin)) { - PwrActivity activity = evalActivity(seq->data(), reg); - // Register output activity cannnot exceed one transition per clock cycle, - // but latch output can. - 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()); - } + PwrActivity in_activity = evalActivity(seq->data(), reg); + float in_density = in_activity.density(); + float in_duty = in_activity.duty(); + // Default propagates input density/duty thru reg/latch. + float out_density = in_density; + float out_duty = in_duty; + PwrActivity clk_activity = evalActivity(seq->clock(), reg); + float clk_density = clk_activity.density(); + if (in_density > clk_density / 2) { + if (seq->isRegister()) + out_density = 2 * in_duty * (1 - in_duty) * clk_density; + else if (seq->isLatch()) { + PwrActivity clk_activity = evalActivity(seq->clock(), reg); + float clk_duty = clk_activity.duty(); + FuncExpr *clk_func = seq->clock(); + bool clk_invert = clk_func + && clk_func->op() == FuncExpr::op_not + && clk_func->left()->op() == FuncExpr::op_port; + if (clk_invert) + out_density = in_density * (1 - clk_duty); + else + out_density = in_density * clk_duty; } } if (invert) - activity.setDuty(1.0 - activity.duty()); - activity.setOrigin(PwrActivityOrigin::propagated); - setSeqActivity(reg, output, activity); + out_duty = 1.0 - out_duty; + PwrActivity out_activity(out_density, out_duty, PwrActivityOrigin::propagated); + setSeqActivity(reg, output, out_activity); } }