From ae3da179e2bd5243a88702a906340196614e7472 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 5 Aug 2020 07:23:38 -0700 Subject: [PATCH] set_power_activity -pins --- search/Power.cc | 149 ++++++++++++++++++++++++++++-------------------- search/Power.hh | 36 +++++++----- tcl/Power.tcl | 2 +- tcl/StaTcl.i | 4 +- 4 files changed, 112 insertions(+), 79 deletions(-) diff --git a/search/Power.cc b/search/Power.cc index 367a8dc3..3e274280 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -97,41 +97,52 @@ Power::setInputPortActivity(const Port *input_port, Instance *top_inst = network_->topInstance(); const Pin *pin = network_->findPin(top_inst, input_port); if (pin) { - activity_map_[pin] = {activity, duty, PwrActivityOrigin::user}; + user_activity_map_[pin] = {activity, duty, PwrActivityOrigin::user}; activities_valid_ = false; } } +void +Power::setUserActivity(const Pin *pin, + float activity, + float duty, + PwrActivityOrigin origin) +{ + user_activity_map_[pin] = {activity, duty, origin}; + activities_valid_ = false; +} + PwrActivity & -Power::pinActivity(const Pin *pin) +Power::userActivity(const Pin *pin) +{ + return user_activity_map_[pin]; +} + +bool +Power::hasUserActivity(const Pin *pin) +{ + return user_activity_map_.hasKey(pin); +} + +void +Power::setActivity(const Pin *pin, + PwrActivity &activity) +{ + activity_map_[pin] = activity; +} + +PwrActivity & +Power::activity(const Pin *pin) { return activity_map_[pin]; } bool -Power::hasPinActivity(const Pin *pin) +Power::hasActivity(const Pin *pin) { return activity_map_.hasKey(pin); } -void -Power::setPinActivity(const Pin *pin, - PwrActivity &activity) -{ - activity_map_[pin] = activity; - activities_valid_ = false; -} - -void -Power::setPinActivity(const Pin *pin, - float activity, - float duty, - PwrActivityOrigin origin) -{ - activity_map_[pin] = {activity, duty, origin}; - activities_valid_ = false; -} - // Sequential internal pins may not be in the netlist so their // activities are stored by instance/liberty_port pairs. void @@ -332,44 +343,48 @@ PropActivityVisitor::visit(Vertex *vertex) auto pin = vertex->pin(); debugPrint1(debug_, "power_activity", 3, "visit %s\n", vertex->name(network_)); - bool input_without_activity = false; - if (network_->isLoad(pin)) { - VertexInEdgeIterator edge_iter(vertex, graph_); - if (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (edge->isWire()) { - Vertex *from_vertex = edge->from(graph_); - const Pin *from_pin = from_vertex->pin(); - PwrActivity &from_activity = power_->pinActivity(from_pin); - PwrActivity to_activity(from_activity.activity(), - from_activity.duty(), - PwrActivityOrigin::propagated); - if (!power_->hasPinActivity(pin)) - input_without_activity = true; - power_->setPinActivity(pin, to_activity); + if (power_->hasUserActivity(pin)) + power_->setActivity(pin, power_->userActivity(pin)); + else { + bool input_without_activity = false; + if (network_->isLoad(pin)) { + VertexInEdgeIterator edge_iter(vertex, graph_); + if (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (edge->isWire()) { + Vertex *from_vertex = edge->from(graph_); + const Pin *from_pin = from_vertex->pin(); + PwrActivity &from_activity = power_->activity(from_pin); + PwrActivity to_activity(from_activity.activity(), + from_activity.duty(), + PwrActivityOrigin::propagated); + if (!power_->hasActivity(pin)) + input_without_activity = true; + power_->setActivity(pin, to_activity); + } + } + Instance *inst = network_->instance(pin); + auto cell = network_->libertyCell(inst); + if (cell && cell->hasSequentials()) { + debugPrint1(debug_, "power_activity", 3, "pending reg %s\n", + network_->pathName(inst)); + visited_regs_->insert(inst); + found_reg_without_activity_ = input_without_activity; } } - Instance *inst = network_->instance(pin); - auto cell = network_->libertyCell(inst); - if (cell && cell->hasSequentials()) { - debugPrint1(debug_, "power_activity", 3, "pending reg %s\n", - network_->pathName(inst)); - visited_regs_->insert(inst); - found_reg_without_activity_ = input_without_activity; - } - } - if (network_->isDriver(pin)) { - LibertyPort *port = network_->libertyPort(pin); - if (port) { - FuncExpr *func = port->function(); - if (func) { - Instance *inst = network_->instance(pin); - PwrActivity activity = power_->evalActivity(func, inst); - power_->setPinActivity(pin, activity); - debugPrint3(debug_, "power_activity", 3, "set %s %.2e %.2f\n", - vertex->name(network_), - activity.activity(), - activity.duty()); + if (network_->isDriver(pin)) { + LibertyPort *port = network_->libertyPort(pin); + if (port) { + FuncExpr *func = port->function(); + if (func) { + Instance *inst = network_->instance(pin); + PwrActivity activity = power_->evalActivity(func, inst); + power_->setActivity(pin, activity); + debugPrint3(debug_, "power_activity", 3, "set %s %.2e %.2f\n", + vertex->name(network_), + activity.activity(), + activity.duty()); + } } } } @@ -469,14 +484,21 @@ Power::preamble() void Power::ensureActivities() { + // No need to propagate activites if global activity is set. if (!global_activity_.isSet()) { if (!activities_valid_) { + // Clear existing activities. + activity_map_.clear(); + seq_activity_map_.clear(); + ActivitySrchPred activity_srch_pred(this); BfsFwdIterator bfs(BfsIndex::other, &activity_srch_pred, this); seedActivities(bfs); PropActivityVisitor visitor(this, &bfs); visitor.init(); + // Propagate activities through combinational logic. bfs.visit(levelize_->maxLevel(), &visitor); + // Propagate activiities through registers. while (visitor.foundRegWithoutActivity()) { InstanceSet *regs = visitor.stealVisitedRegs(); InstanceSet::Iterator reg_iter(regs); @@ -486,7 +508,10 @@ Power::ensureActivities() seedRegOutputActivities(reg, bfs); } delete regs; + visitor.init(); + // Propagate register output activities through + // combinational logic. bfs.visit(levelize_->maxLevel(), &visitor); } activities_valid_ = true; @@ -504,11 +529,11 @@ Power::seedActivities(BfsFwdIterator &bfs) && !network_->direction(pin)->isInternal()) { debugPrint1(debug_, "power_activity", 3, "seed %s\n", vertex->name(network_)); - PwrActivity &activity = pinActivity(pin); - PwrActivityOrigin origin = activity.origin(); - // Default inputs without explicit activities to the input default. - if (origin != PwrActivityOrigin::user) - setPinActivity(pin, input_activity_); + if (hasUserActivity(pin)) + setActivity(pin, userActivity(pin)); + else + // Default inputs without explicit activities to the input default. + setActivity(pin, input_activity_); Vertex *vertex = graph_->pinDrvrVertex(pin); bfs.enqueueAdjacentVertices(vertex); } diff --git a/search/Power.hh b/search/Power.hh index d83a5ddc..ec51b5d8 100644 --- a/search/Power.hh +++ b/search/Power.hh @@ -75,14 +75,19 @@ public: void setInputPortActivity(const Port *input_port, float activity, float duty); - PwrActivity &pinActivity(const Pin *pin); - bool hasPinActivity(const Pin *pin); - void setPinActivity(const Pin *pin, - PwrActivity &activity); - void setPinActivity(const Pin *pin, - float activity, - float duty, - PwrActivityOrigin origin); + PwrActivity &activity(const Pin *pin); + void setUserActivity(const Pin *pin, + float activity, + float duty, + PwrActivityOrigin origin); + // Activity is toggles per second. + PwrActivity findClkedActivity(const Pin *pin); + +protected: + void preamble(); + void ensureActivities(); + bool hasUserActivity(const Pin *pin); + PwrActivity &userActivity(const Pin *pin); void setSeqActivity(const Instance *reg, LibertyPort *output, PwrActivity &activity); @@ -90,12 +95,9 @@ public: LibertyPort *output); PwrActivity seqActivity(const Instance *reg, LibertyPort *output); - // Activity is toggles per second. - PwrActivity findClkedActivity(const Pin *pin); - -protected: - void preamble(); - void ensureActivities(); + bool hasActivity(const Pin *pin); + void setActivity(const Pin *pin, + PwrActivity &activity); void power(const Instance *inst, LibertyCell *cell, @@ -167,8 +169,14 @@ protected: const LibertyPort *cofactor_port); private: + // Port/pin activities set by set_pin_activity. + // set_pin_activity -global PwrActivity global_activity_; + // set_pin_activity -input PwrActivity input_activity_; + // set_pin_activity -input_ports -pins + PwrActivityMap user_activity_map_; + // Propagated activities. PwrActivityMap activity_map_; PwrSeqActivityMap seq_activity_map_; bool activities_valid_; diff --git a/tcl/Power.tcl b/tcl/Power.tcl index 840801ba..d8bfaaa3 100644 --- a/tcl/Power.tcl +++ b/tcl/Power.tcl @@ -247,7 +247,7 @@ proc set_power_activity { args } { } } if { [info exists keys(-pins)] } { - set ports [get_pins_error "pins" $keys(-pins)] + set pins [get_pins $keys(-pins)] foreach pin $pins { if { [get_property $pin "direction"] == "input" } { set_power_pin_activity $pin $activity $duty diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 65cd5cce..0e4c5f31 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -4830,8 +4830,8 @@ set_power_pin_activity(const Pin *pin, float activity, float duty) { - return Sta::sta()->power()->setPinActivity(pin, activity, duty, - PwrActivityOrigin::user); + return Sta::sta()->power()->setUserActivity(pin, activity, duty, + PwrActivityOrigin::user); } ////////////////////////////////////////////////////////////////