power reg activity prop
This commit is contained in:
parent
e0dad2ea19
commit
325e284441
187
search/Power.cc
187
search/Power.cc
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
23
tcl/Cmds.tcl
23
tcl/Cmds.tcl
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
23
tcl/Sta.tcl
23
tcl/Sta.tcl
|
|
@ -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}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue