power reg activity prop

This commit is contained in:
James Cherry 2019-04-30 18:17:36 -07:00
parent e0dad2ea19
commit 325e284441
4 changed files with 150 additions and 89 deletions

View File

@ -103,6 +103,12 @@ Power::pinActivity(const Pin *pin)
return activity_map_[pin]; return activity_map_[pin];
} }
bool
Power::hasPinActivity(const Pin *pin)
{
return activity_map_.hasKey(pin);
}
void void
Power::setPinActivity(const Pin *pin, Power::setPinActivity(const Pin *pin,
float activity, float activity,
@ -218,10 +224,16 @@ class PropActivityVisitor : public VertexVisitor, StaState
public: public:
PropActivityVisitor(Power *power, PropActivityVisitor(Power *power,
BfsFwdIterator *bfs); BfsFwdIterator *bfs);
~PropActivityVisitor();
virtual VertexVisitor *copy(); virtual VertexVisitor *copy();
virtual void visit(Vertex *vertex); virtual void visit(Vertex *vertex);
void init();
bool foundRegWithoutActivity() const;
InstanceSet *stealVisitedRegs();
private: private:
InstanceSet *visited_regs_;
bool found_reg_without_activity_;
Power *power_; Power *power_;
BfsFwdIterator *bfs_; BfsFwdIterator *bfs_;
}; };
@ -229,17 +241,88 @@ private:
PropActivityVisitor::PropActivityVisitor(Power *power, PropActivityVisitor::PropActivityVisitor(Power *power,
BfsFwdIterator *bfs) : BfsFwdIterator *bfs) :
StaState(power), StaState(power),
visited_regs_(nullptr),
power_(power), power_(power),
bfs_(bfs) bfs_(bfs)
{ {
} }
PropActivityVisitor::~PropActivityVisitor()
{
delete visited_regs_;
}
VertexVisitor * VertexVisitor *
PropActivityVisitor::copy() PropActivityVisitor::copy()
{ {
return new PropActivityVisitor(power_, bfs_); return new PropActivityVisitor(power_, bfs_);
} }
void
PropActivityVisitor::init()
{
visited_regs_ = new InstanceSet;
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
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);
}
}
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();
Instance *inst = network_->instance(pin);
PwrActivity activity = power_->evalActivity(func, inst);
power_->setPinActivity(pin, activity);
}
}
bfs_->enqueueAdjacentVertices(vertex);
}
PwrActivity PwrActivity
Power::evalActivity(FuncExpr *expr, Power::evalActivity(FuncExpr *expr,
const Instance *inst) const Instance *inst)
@ -292,39 +375,6 @@ Power::evalActivity(FuncExpr *expr,
return PwrActivity(); return PwrActivity();
} }
void
PropActivityVisitor::visit(Vertex *vertex)
{
auto pin = vertex->pin();
debugPrint1(debug_, "power", 3, "activity %s\n",
vertex->name(network_));
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);
power_->setPinActivity(pin, to_activity);
}
}
}
if (network_->isDriver(pin)) {
LibertyPort *port = network_->libertyPort(pin);
if (port) {
FuncExpr *func = port->function();
Instance *inst = network_->instance(pin);
PwrActivity activity = power_->evalActivity(func, inst);
power_->setPinActivity(pin, activity);
}
}
bfs_->enqueueAdjacentVertices(vertex);
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void
@ -342,10 +392,19 @@ 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();
bfs.visit(levelize_->maxLevel(), &visitor); bfs.visit(levelize_->maxLevel(), &visitor);
// Propagate activiities across register D->Q. while (visitor.foundRegWithoutActivity()) {
seedRegOutputActivities(bfs); InstanceSet *regs = visitor.stealVisitedRegs();
bfs.visit(levelize_->maxLevel(), &visitor); InstanceSet::Iterator reg_iter(regs);
while (reg_iter.hasNext()) {
auto reg = reg_iter.next();
// Propagate activiities across register D->Q.
seedRegOutputActivities(reg, bfs);
}
visitor.init();
bfs.visit(levelize_->maxLevel(), &visitor);
}
activities_valid_ = true; activities_valid_ = true;
} }
} }
@ -357,54 +416,54 @@ Power::seedActivities(BfsFwdIterator &bfs)
for (auto vertex : levelize_->roots()) { for (auto vertex : levelize_->roots()) {
const Pin *pin = vertex->pin(); const Pin *pin = vertex->pin();
// Clock activities are baked in. // Clock activities are baked in.
if (!sdc_->isVertexPinClock(pin)) { if (!sdc_->isVertexPinClock(pin)
&& network_->direction(pin) != PortDirection::internal()) {
PwrActivity &activity = pinActivity(pin); PwrActivity &activity = pinActivity(pin);
PwrActivityOrigin origin = activity.origin(); PwrActivityOrigin origin = activity.origin();
// Default inputs without explicit activities to the input default. // Default inputs without explicit activities to the input default.
if (origin != PwrActivityOrigin::user) if (origin != PwrActivityOrigin::user)
setPinActivity(pin, input_activity_); setPinActivity(pin, input_activity_);
Vertex *vertex = graph_->pinDrvrVertex(pin); Vertex *vertex = graph_->pinDrvrVertex(pin);
debugPrint1(debug_, "power_activity", 3, "seed %s\n",
vertex->name(network_));
bfs.enqueueAdjacentVertices(vertex); bfs.enqueueAdjacentVertices(vertex);
} }
} }
} }
void void
Power::seedRegOutputActivities(BfsFwdIterator &bfs) Power::seedRegOutputActivities(const Instance *inst,
BfsFwdIterator &bfs)
{ {
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator(); auto cell = network_->libertyCell(inst);
while (leaf_iter->hasNext()) { LibertyCellSequentialIterator seq_iter(cell);
auto inst = leaf_iter->next(); while (seq_iter.hasNext()) {
auto cell = network_->libertyCell(inst); Sequential *seq = seq_iter.next();
if (cell) { seedRegOutputActivities(inst, seq, seq->output(), false);
LibertyCellSequentialIterator seq_iter(cell); seedRegOutputActivities(inst, seq, seq->outputInv(), true);
while (seq_iter.hasNext()) { // Enqueue register output pins with functions that reference
Sequential *seq = seq_iter.next(); // the sequential internal pins (IQ, IQN).
seedRegOutputActivities(inst, seq, seq->output(), false); InstancePinIterator *pin_iter = network_->pinIterator(inst);
seedRegOutputActivities(inst, seq, seq->outputInv(), true); while (pin_iter->hasNext()) {
// Enqueue register output pins with functions that reference auto pin = pin_iter->next();
// the sequential internal pins (IQ, IQN). auto port = network_->libertyPort(pin);
InstancePinIterator *pin_iter = network_->pinIterator(inst); auto func = port->function();
while (pin_iter->hasNext()) { if (func) {
auto pin = pin_iter->next(); Vertex *vertex = graph_->pinDrvrVertex(pin);
auto port = network_->libertyPort(pin); if (func->port() == seq->output()
auto func = port->function(); || func->port() == seq->outputInv()) {
if (func) { debugPrint1(debug_, "power_activity", 3, "enqueue reg output %s\n",
Vertex *vertex = graph_->pinDrvrVertex(pin); vertex->name(network_));
if (func->port() == seq->output() bfs.enqueue(vertex);
|| func->port() == seq->outputInv())
bfs.enqueue(vertex);
}
} }
delete pin_iter;
} }
} }
delete pin_iter;
} }
delete leaf_iter;
} }
void void
Power::seedRegOutputActivities(Instance *reg, Power::seedRegOutputActivities(const Instance *reg,
Sequential *seq, Sequential *seq,
LibertyPort *output, LibertyPort *output,
bool invert) bool invert)

View File

@ -88,6 +88,7 @@ public:
float activity, float activity,
float duty); float duty);
PwrActivity &pinActivity(const Pin *pin); PwrActivity &pinActivity(const Pin *pin);
bool hasPinActivity(const Pin *pin);
void setPinActivity(const Pin *pin, void setPinActivity(const Pin *pin,
float activity, float activity,
float duty, float duty,
@ -133,11 +134,12 @@ protected:
const LibertyPort *port, const LibertyPort *port,
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
void seedActivities(BfsFwdIterator &bfs); void seedActivities(BfsFwdIterator &bfs);
void seedRegOutputActivities(BfsFwdIterator &bfs); void seedRegOutputActivities(const Instance *reg,
void seedRegOutputActivities(Instance *reg,
Sequential *seq, Sequential *seq,
LibertyPort *output, LibertyPort *output,
bool invert); bool invert);
void seedRegOutputActivities(const Instance *inst,
BfsFwdIterator &bfs);
PwrActivity evalActivity(FuncExpr *expr, PwrActivity evalActivity(FuncExpr *expr,
const Instance *inst); const Instance *inst);

View File

@ -22,6 +22,29 @@
namespace eval sta { namespace eval sta {
proc report_clock1 { clk } {
global sta_report_default_digits
if { [$clk waveform_valid] } {
set digits $sta_report_default_digits
puts -nonewline [format "%-20s" [get_name $clk]]
puts -nonewline [format "%10s" [format_time [$clk period] $digits]]
puts -nonewline " "
set waveform [$clk waveform]
if { $waveform == {} } {
puts -nonewline " "
} else {
foreach edge $waveform {
puts -nonewline [format "%10s" [format_time $edge $digits]]
}
}
if {[$clk is_generated]} {
puts -nonewline " (generated)"
}
puts ""
}
}
proc_redirect read_parasitics { proc_redirect read_parasitics {
variable native variable native

View File

@ -944,29 +944,6 @@ proc_redirect report_clock_properties {
} }
} }
proc report_clock1 { clk } {
global sta_report_default_digits
if { [$clk waveform_valid] } {
set digits $sta_report_default_digits
puts -nonewline [format "%-20s" [$clk name]]
puts -nonewline [format "%10s" [format_time [$clk period] $digits]]
puts -nonewline " "
set waveform [$clk waveform]
if { $waveform == {} } {
puts -nonewline " "
} else {
foreach edge $waveform {
puts -nonewline [format "%10s" [format_time $edge $digits]]
}
}
if {[$clk is_generated]} {
puts -nonewline " (generated)"
}
puts ""
}
}
################################################################ ################################################################
define_sta_cmd_args "report_object_full_names" {[-verbose] objects} define_sta_cmd_args "report_object_full_names" {[-verbose] objects}