issue138 power w/gated clock feedback loops

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2023-03-06 16:20:58 -07:00
parent 6ad97c7562
commit 1e53cc3b5a
1 changed files with 46 additions and 65 deletions

View File

@ -299,16 +299,15 @@ class PropActivityVisitor : public VertexVisitor, StaState
public: public:
PropActivityVisitor(Power *power, PropActivityVisitor(Power *power,
BfsFwdIterator *bfs); BfsFwdIterator *bfs);
~PropActivityVisitor();
virtual VertexVisitor *copy() const; virtual VertexVisitor *copy() const;
virtual void visit(Vertex *vertex); virtual void visit(Vertex *vertex);
void init(); InstanceSet &visitedRegs() { return visited_regs_; }
bool foundRegWithoutActivity() const;
InstanceSet *stealVisitedRegs();
private: private:
InstanceSet *visited_regs_; bool setActivityCheck(const Pin *pin,
bool found_reg_without_activity_; PwrActivity &activity);
InstanceSet visited_regs_;
Power *power_; Power *power_;
BfsFwdIterator *bfs_; BfsFwdIterator *bfs_;
}; };
@ -316,44 +315,18 @@ private:
PropActivityVisitor::PropActivityVisitor(Power *power, PropActivityVisitor::PropActivityVisitor(Power *power,
BfsFwdIterator *bfs) : BfsFwdIterator *bfs) :
StaState(power), StaState(power),
visited_regs_(nullptr), visited_regs_(network_),
power_(power), power_(power),
bfs_(bfs) bfs_(bfs)
{ {
} }
PropActivityVisitor::~PropActivityVisitor()
{
delete visited_regs_;
}
VertexVisitor * VertexVisitor *
PropActivityVisitor::copy() const PropActivityVisitor::copy() const
{ {
return new PropActivityVisitor(power_, bfs_); return new PropActivityVisitor(power_, bfs_);
} }
void
PropActivityVisitor::init()
{
visited_regs_ = new InstanceSet(network_);
found_reg_without_activity_ = false;
}
InstanceSet *
PropActivityVisitor::stealVisitedRegs()
{
InstanceSet *visited_regs = visited_regs_;
visited_regs_ = nullptr;
return visited_regs;
}
bool
PropActivityVisitor::foundRegWithoutActivity() const
{
return found_reg_without_activity_;
}
void void
PropActivityVisitor::visit(Vertex *vertex) PropActivityVisitor::visit(Vertex *vertex)
{ {
@ -361,16 +334,14 @@ PropActivityVisitor::visit(Vertex *vertex)
Instance *inst = network_->instance(pin); Instance *inst = network_->instance(pin);
debugPrint(debug_, "power_activity", 3, "visit %s", debugPrint(debug_, "power_activity", 3, "visit %s",
vertex->name(network_)); vertex->name(network_));
bool input_without_activity = false; bool changed = false;
if (power_->hasUserActivity(pin)) { if (power_->hasUserActivity(pin)) {
PwrActivity &activity = power_->userActivity(pin); PwrActivity &activity = power_->userActivity(pin);
debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f", debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f",
vertex->name(network_), vertex->name(network_),
activity.activity(), activity.activity(),
activity.duty()); activity.duty());
if (!power_->hasActivity(pin)) changed = setActivityCheck(pin, activity);
input_without_activity = true;
power_->setActivity(pin, activity);
} }
else { else {
if (network_->isLoad(pin)) { if (network_->isLoad(pin)) {
@ -384,9 +355,7 @@ PropActivityVisitor::visit(Vertex *vertex)
PwrActivity to_activity(from_activity.activity(), PwrActivity to_activity(from_activity.activity(),
from_activity.duty(), from_activity.duty(),
PwrActivityOrigin::propagated); PwrActivityOrigin::propagated);
if (!power_->hasActivity(pin)) changed = setActivityCheck(pin, to_activity);
input_without_activity = true;
power_->setActivity(pin, to_activity);
} }
} }
} }
@ -395,9 +364,8 @@ PropActivityVisitor::visit(Vertex *vertex)
if (port) { if (port) {
FuncExpr *func = port->function(); FuncExpr *func = port->function();
if (func) { if (func) {
Instance *inst = network_->instance(pin);
PwrActivity activity = power_->evalActivity(func, inst); PwrActivity activity = power_->evalActivity(func, inst);
power_->setActivity(pin, activity); changed = setActivityCheck(pin, activity);
debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f", debugPrint(debug_, "power_activity", 3, "set %s %.2e %.2f",
vertex->name(network_), vertex->name(network_),
activity.activity(), activity.activity(),
@ -414,7 +382,7 @@ PropActivityVisitor::visit(Vertex *vertex)
PwrActivity activity(activity1.activity() * p2 + activity2.activity() * p1, PwrActivity activity(activity1.activity() * p2 + activity2.activity() * p1,
p1 * p2, p1 * p2,
PwrActivityOrigin::propagated); PwrActivityOrigin::propagated);
power_->setActivity(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.activity(),
@ -424,13 +392,13 @@ PropActivityVisitor::visit(Vertex *vertex)
} }
} }
} }
if (changed) {
LibertyCell *cell = network_->libertyCell(inst); LibertyCell *cell = network_->libertyCell(inst);
if (network_->isLoad(pin) && cell) { if (network_->isLoad(pin) && cell) {
if (cell->hasSequentials()) { if (cell->hasSequentials()) {
debugPrint(debug_, "power_activity", 3, "pending seq %s", debugPrint(debug_, "power_activity", 3, "pending seq %s",
network_->pathName(inst)); network_->pathName(inst));
visited_regs_->insert(inst); visited_regs_.insert(inst);
found_reg_without_activity_ |= input_without_activity;
} }
// Gated clock cells latch the enable so there is no EN->GCLK timing arc. // Gated clock cells latch the enable so there is no EN->GCLK timing arc.
if (cell->isClockGate()) { if (cell->isClockGate()) {
@ -443,6 +411,22 @@ PropActivityVisitor::visit(Vertex *vertex)
} }
} }
bfs_->enqueueAdjacentVertices(vertex); bfs_->enqueueAdjacentVertices(vertex);
}
}
// Return true if the activity changed.
bool
PropActivityVisitor::setActivityCheck(const Pin *pin,
PwrActivity &activity)
{
PwrActivity &prev_activity = power_->activity(pin);
if (abs(activity.activity() - prev_activity.activity()) > .001
|| abs(activity.duty() - prev_activity.duty()) > .001) {
power_->setActivity(pin, activity);
return true;
}
else
return false;
} }
void void
@ -568,24 +552,21 @@ Power::ensureActivities()
BfsFwdIterator bfs(BfsIndex::other, &activity_srch_pred, this); BfsFwdIterator bfs(BfsIndex::other, &activity_srch_pred, this);
seedActivities(bfs); seedActivities(bfs);
PropActivityVisitor visitor(this, &bfs); PropActivityVisitor visitor(this, &bfs);
visitor.init();
// Propagate activities through combinational logic. // Propagate activities through combinational logic.
bfs.visit(levelize_->maxLevel(), &visitor); bfs.visit(levelize_->maxLevel(), &visitor);
// Propagate activiities through registers. // Propagate activiities through registers.
while (visitor.foundRegWithoutActivity()) { InstanceSet regs = std::move(visitor.visitedRegs());
InstanceSet *regs = visitor.stealVisitedRegs(); while (!regs.empty()) {
InstanceSet::Iterator reg_iter(regs); InstanceSet::Iterator reg_iter(regs);
while (reg_iter.hasNext()) { while (reg_iter.hasNext()) {
const Instance *reg = reg_iter.next(); const Instance *reg = reg_iter.next();
// Propagate activiities across register D->Q. // Propagate activiities across register D->Q.
seedRegOutputActivities(reg, bfs); seedRegOutputActivities(reg, bfs);
} }
delete regs;
visitor.init();
// Propagate register output activities through // Propagate register output activities through
// combinational logic. // combinational logic.
bfs.visit(levelize_->maxLevel(), &visitor); bfs.visit(levelize_->maxLevel(), &visitor);
regs = std::move(visitor.visitedRegs());
} }
activities_valid_ = true; activities_valid_ = true;
} }