power activity propagation thru reg/latch resolves #350

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-12-20 09:11:41 -07:00
parent 323906cb1a
commit 1bf9426e96
1 changed files with 25 additions and 15 deletions

View File

@ -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);
}
}