set_power_activity -pins

This commit is contained in:
James Cherry 2020-08-05 07:23:38 -07:00
parent cafb7b9152
commit ae3da179e2
4 changed files with 112 additions and 79 deletions

View File

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

View File

@ -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_;

View File

@ -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

View File

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