issue138 power w/gated clock feedback loops
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
6ad97c7562
commit
1e53cc3b5a
111
power/Power.cc
111
power/Power.cc
|
|
@ -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,25 +392,41 @@ PropActivityVisitor::visit(Vertex *vertex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LibertyCell *cell = network_->libertyCell(inst);
|
if (changed) {
|
||||||
if (network_->isLoad(pin) && cell) {
|
LibertyCell *cell = network_->libertyCell(inst);
|
||||||
if (cell->hasSequentials()) {
|
if (network_->isLoad(pin) && cell) {
|
||||||
debugPrint(debug_, "power_activity", 3, "pending seq %s",
|
if (cell->hasSequentials()) {
|
||||||
network_->pathName(inst));
|
debugPrint(debug_, "power_activity", 3, "pending seq %s",
|
||||||
visited_regs_->insert(inst);
|
network_->pathName(inst));
|
||||||
found_reg_without_activity_ |= input_without_activity;
|
visited_regs_.insert(inst);
|
||||||
}
|
}
|
||||||
// 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()) {
|
||||||
const Pin *enable, *clk, *gclk;
|
const Pin *enable, *clk, *gclk;
|
||||||
power_->clockGatePins(inst, enable, clk, gclk);
|
power_->clockGatePins(inst, enable, clk, gclk);
|
||||||
if (gclk) {
|
if (gclk) {
|
||||||
Vertex *gclk_vertex = graph_->pinDrvrVertex(gclk);
|
Vertex *gclk_vertex = graph_->pinDrvrVertex(gclk);
|
||||||
bfs_->enqueue(gclk_vertex);
|
bfs_->enqueue(gclk_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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue