report -min/max fanout, capacitance

This commit is contained in:
James Cherry 2020-06-02 11:08:48 -07:00
parent 6ff05e580b
commit 4c74fcfb65
12 changed files with 1211 additions and 78 deletions

View File

@ -152,6 +152,8 @@ set(STA_SOURCE
search/CheckMaxSkews.cc search/CheckMaxSkews.cc
search/CheckMinPeriods.cc search/CheckMinPeriods.cc
search/CheckMinPulseWidths.cc search/CheckMinPulseWidths.cc
search/CheckCapacitanceLimits.cc
search/CheckFanoutLimits.cc
search/CheckSlewLimits.cc search/CheckSlewLimits.cc
search/CheckTiming.cc search/CheckTiming.cc
search/ClkInfo.cc search/ClkInfo.cc
@ -511,6 +513,9 @@ install(DIRECTORY include/sta DESTINATION include)
################################################################ ################################################################
add_custom_target(tags etags -o TAGS ${STA_SOURCE} */*.hh include/sta/*.hh ${SWIG_TCL_FILES} add_custom_target(tags etags -o TAGS
${STA_SOURCE}
*/*.hh include/sta/*.hh
${STA_TCL_FILES} ${SWIG_TCL_FILES}
WORKING_DIRECTORY ${STA_HOME} WORKING_DIRECTORY ${STA_HOME}
) )

View File

@ -45,6 +45,8 @@ class ReportPath;
class CheckTiming; class CheckTiming;
class DcalcAnalysisPt; class DcalcAnalysisPt;
class CheckSlewLimits; class CheckSlewLimits;
class CheckFanoutLimits;
class CheckCapacitanceLimits;
class CheckMinPulseWidths; class CheckMinPulseWidths;
class CheckMinPeriods; class CheckMinPeriods;
class CheckMaxSkews; class CheckMaxSkews;
@ -612,6 +614,7 @@ public:
// Return value. // Return value.
ClockSet &clks); ClockSet &clks);
void checkSlewLimitPreamble();
// Return the pin with the min/max slew limit slack. // Return the pin with the min/max slew limit slack.
// corner=nullptr checks all corners. // corner=nullptr checks all corners.
Pin *pinMinSlewLimitSlack(const Corner *corner, Pin *pinMinSlewLimitSlack(const Corner *corner,
@ -636,6 +639,50 @@ public:
Slew &slew, Slew &slew,
float &limit, float &limit,
float &slack); float &slack);
void checkFanoutLimitPreamble();
// Return the pin with the min/max fanout limit slack.
Pin *pinMinFanoutLimitSlack(const MinMax *min_max);
// Return all pins with min/max fanout violations.
PinSeq *pinFanoutLimitViolations(const MinMax *min_max);
void reportFanoutLimitShortHeader();
void reportFanoutLimitShort(Pin *pin,
const MinMax *min_max);
void reportFanoutLimitVerbose(Pin *pin,
const MinMax *min_max);
void checkFanouts(const Pin *pin,
const MinMax *min_max,
// Return values.
float &fanout,
float &limit,
float &slack);
void checkCapacitanceLimitPreamble();
// Return the pin with the min/max capacitance limit slack.
// corner=nullptr checks all corners.
Pin *pinMinCapacitanceLimitSlack(const Corner *corner,
const MinMax *min_max);
// Return all pins with min/max capacitance violations.
// corner=nullptr checks all corners.
PinSeq *pinCapacitanceLimitViolations(const Corner *corner,
const MinMax *min_max);
void reportCapacitanceLimitShortHeader();
void reportCapacitanceLimitShort(Pin *pin,
const Corner *corner,
const MinMax *min_max);
void reportCapacitanceLimitVerbose(Pin *pin,
const Corner *corner,
const MinMax *min_max);
void checkCapacitances(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
const Corner *&corner1,
const RiseFall *&tr,
float &capacitance,
float &limit,
float &slack);
// Min pulse width check with the least slack. // Min pulse width check with the least slack.
// corner=nullptr checks all corners. // corner=nullptr checks all corners.
MinPulseWidthCheck *minPulseWidthSlack(const Corner *corner); MinPulseWidthCheck *minPulseWidthSlack(const Corner *corner);
@ -1227,6 +1274,8 @@ protected:
virtual void makeLatches(); virtual void makeLatches();
virtual void makeCheckTiming(); virtual void makeCheckTiming();
virtual void makeCheckSlewLimits(); virtual void makeCheckSlewLimits();
virtual void makeCheckFanoutLimits();
virtual void makeCheckCapacitanceLimits();
virtual void makeCheckMinPulseWidths(); virtual void makeCheckMinPulseWidths();
virtual void makeCheckMinPeriods(); virtual void makeCheckMinPeriods();
virtual void makeCheckMaxSkews(); virtual void makeCheckMaxSkews();
@ -1268,7 +1317,6 @@ protected:
Edge *d_q_edge, Edge *d_q_edge,
const ClockEdge *en_clk_edge); const ClockEdge *en_clk_edge);
void clockSlewChanged(Clock *clk); void clockSlewChanged(Clock *clk);
void checkSlewLimitPreamble();
void minPulseWidthPreamble(); void minPulseWidthPreamble();
void minPeriodPreamble(); void minPeriodPreamble();
void maxSkewPreamble(); void maxSkewPreamble();
@ -1324,6 +1372,8 @@ protected:
Corner *cmd_corner_; Corner *cmd_corner_;
CheckTiming *check_timing_; CheckTiming *check_timing_;
CheckSlewLimits *check_slew_limits_; CheckSlewLimits *check_slew_limits_;
CheckFanoutLimits *check_fanout_limits_;
CheckCapacitanceLimits *check_capacitance_limits_;
CheckMinPulseWidths *check_min_pulse_widths_; CheckMinPulseWidths *check_min_pulse_widths_;
CheckMinPeriods *check_min_periods_; CheckMinPeriods *check_min_periods_;
CheckMaxSkews *check_max_skews_; CheckMaxSkews *check_max_skews_;

View File

@ -0,0 +1,306 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2020, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "CheckCapacitanceLimits.hh"
#include "Fuzzy.hh"
#include "Liberty.hh"
#include "Network.hh"
#include "Sdc.hh"
#include "DcalcAnalysisPt.hh"
#include "StaState.hh"
#include "Corner.hh"
#include "PortDirection.hh"
namespace sta {
class PinCapacitanceLimitSlackLess
{
public:
PinCapacitanceLimitSlackLess(const Corner *corner,
const MinMax *min_max,
CheckCapacitanceLimits *check_capacitance_limit,
const StaState *sta);
bool operator()(Pin *pin1,
Pin *pin2) const;
private:
const Corner *corner_;
const MinMax *min_max_;
CheckCapacitanceLimits *check_capacitance_limit_;
const StaState *sta_;
};
PinCapacitanceLimitSlackLess::PinCapacitanceLimitSlackLess(const Corner *corner,
const MinMax *min_max,
CheckCapacitanceLimits *check_capacitance_limit,
const StaState *sta) :
corner_(corner),
min_max_(min_max),
check_capacitance_limit_(check_capacitance_limit),
sta_(sta)
{
}
bool
PinCapacitanceLimitSlackLess::operator()(Pin *pin1,
Pin *pin2) const
{
const Corner *corner1, *corner2;
const RiseFall *rf1, *rf2;
float capacitance1, capacitance2;
float limit1, limit2, slack1, slack2;
check_capacitance_limit_->checkCapacitance(pin1, corner_, min_max_,
corner1, rf1, capacitance1,
limit1, slack1);
check_capacitance_limit_->checkCapacitance(pin2, corner_, min_max_,
corner2, rf2, capacitance2,
limit2, slack2);
return fuzzyLess(slack1, slack2)
|| (fuzzyEqual(slack1, slack2)
// Break ties for the sake of regression stability.
&& sta_->network()->pinLess(pin1, pin2));
}
////////////////////////////////////////////////////////////////
CheckCapacitanceLimits::CheckCapacitanceLimits(const StaState *sta) :
sta_(sta)
{
}
void
CheckCapacitanceLimits::init(const MinMax *min_max)
{
const Network *network = sta_->network();
Cell *top_cell = network->cell(network->topInstance());
float top_limit;
bool top_limit_exists;
sta_->sdc()->capacitanceLimit(top_cell, min_max,
top_limit, top_limit_exists);
top_limit_= top_limit;
top_limit_exists_ = top_limit_exists;
}
void
CheckCapacitanceLimits::checkCapacitance(const Pin *pin,
const Corner *corner1,
const MinMax *min_max,
// Return values.
const Corner *&corner,
const RiseFall *&rf,
float &capacitance,
float &limit,
float &slack) const
{
corner = nullptr;
rf = nullptr;
capacitance = 0.0;
limit = 0.0;
slack = MinMax::min()->initValue();
if (corner1)
checkCapacitance1(pin, corner1, min_max,
corner, rf, capacitance, limit, slack);
else {
for (auto corner1 : *sta_->corners()) {
checkCapacitance1(pin, corner1, min_max,
corner, rf, capacitance, limit, slack);
}
}
}
void
CheckCapacitanceLimits::checkCapacitance1(const Pin *pin,
const Corner *corner1,
const MinMax *min_max,
// Return values.
const Corner *&corner,
const RiseFall *&rf,
float &capacitance,
float &limit,
float &slack) const
{
float limit1;
bool limit1_exists;
findLimit(pin, min_max, limit1, limit1_exists);
if (limit1_exists) {
for (auto rf1 : RiseFall::range()) {
checkCapacitance(pin, corner1, min_max, rf1, limit1,
corner, rf, capacitance, slack, limit);
}
}
}
void
CheckCapacitanceLimits::findLimit(const Pin *pin,
const MinMax *min_max,
// Return values.
float &limit,
bool &exists) const
{
exists = false;
const Network *network = sta_->network();
Sdc *sdc = sta_->sdc();
if (network->isTopLevelPort(pin)) {
Port *port = network->port(pin);
sdc->capacitanceLimit(port, min_max, limit, exists);
if (!exists) {
limit = top_limit_;
exists = top_limit_exists_;
}
}
else {
Cell *cell = network->cell(network->instance(pin));
sdc->capacitanceLimit(cell, min_max,
limit, exists);
if (!exists) {
LibertyPort *port = network->libertyPort(pin);
if (port) {
port->capacitanceLimit(min_max, limit, exists);
if (!exists
&& port->direction()->isAnyOutput())
port->libertyLibrary()->defaultMaxCapacitance(limit, exists);
}
}
}
}
void
CheckCapacitanceLimits::checkCapacitance(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
const RiseFall *rf1,
float limit1,
// Return values.
const Corner *&corner1,
const RiseFall *&rf,
float &capacitance,
float &slack,
float &limit) const
{
const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
Sdc *sdc = sta_->sdc();
float pin_cap, wire_cap, fanout;
bool has_set_load;
sdc->connectedCap(pin, rf1, op_cond, corner, min_max,
pin_cap, wire_cap, fanout, has_set_load);
float cap = pin_cap + wire_cap;
float slack1 = (min_max == MinMax::max())
? limit1 - cap : cap - limit1;
if (corner == nullptr
|| (slack1 < slack
// Break ties for the sake of regression stability.
|| (fuzzyEqual(slack1, slack)
&& rf1->index() < rf->index()))) {
corner1 = corner;
rf = rf1;
capacitance = cap;
slack = slack1;
limit = limit1;
}
}
PinSeq *
CheckCapacitanceLimits::pinCapacitanceLimitViolations(const Corner *corner,
const MinMax *min_max)
{
init(min_max);
const Network *network = sta_->network();
PinSeq *violators = new PinSeq;
LeafInstanceIterator *inst_iter = network->leafInstanceIterator();
while (inst_iter->hasNext()) {
Instance *inst = inst_iter->next();
pinCapacitanceLimitViolations(inst, corner, min_max, violators);
}
delete inst_iter;
// Check top level ports.
pinCapacitanceLimitViolations(network->topInstance(), corner, min_max, violators);
sort(violators, PinCapacitanceLimitSlackLess(corner, min_max, this, sta_));
return violators;
}
void
CheckCapacitanceLimits::pinCapacitanceLimitViolations(Instance *inst,
const Corner *corner,
const MinMax *min_max,
PinSeq *violators)
{
const Network *network = sta_->network();
InstancePinIterator *pin_iter = network->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
if (network->direction(pin)->isAnyOutput()) {
const Corner *corner1;
const RiseFall *rf;
float capacitance, limit, slack;
checkCapacitance(pin, corner, min_max, corner1, rf, capacitance, limit, slack );
if (rf && slack < 0.0)
violators->push_back(pin);
}
}
delete pin_iter;
}
Pin *
CheckCapacitanceLimits::pinMinCapacitanceLimitSlack(const Corner *corner,
const MinMax *min_max)
{
init(min_max);
const Network *network = sta_->network();
Pin *min_slack_pin = 0;
float min_slack = MinMax::min()->initValue();
LeafInstanceIterator *inst_iter = network->leafInstanceIterator();
while (inst_iter->hasNext()) {
Instance *inst = inst_iter->next();
pinMinCapacitanceLimitSlack(inst, corner, min_max, min_slack_pin, min_slack);
}
delete inst_iter;
// Check top level ports.
pinMinCapacitanceLimitSlack(network->topInstance(), corner, min_max,
min_slack_pin, min_slack);
return min_slack_pin;
}
void
CheckCapacitanceLimits::pinMinCapacitanceLimitSlack(Instance *inst,
const Corner *corner,
const MinMax *min_max,
// Return values.
Pin *&min_slack_pin,
float &min_slack)
{
const Network *network = sta_->network();
InstancePinIterator *pin_iter = network->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
const Corner *corner1;
const RiseFall *rf;
float capacitance, limit, slack;
checkCapacitance(pin, corner, min_max, corner1, rf, capacitance, limit, slack);
if (rf
&& (min_slack_pin == 0
|| slack < min_slack)) {
min_slack_pin = pin;
min_slack = slack;
}
}
delete pin_iter;
}
} // namespace

View File

@ -0,0 +1,95 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2020, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include "MinMax.hh"
#include "Transition.hh"
#include "NetworkClass.hh"
#include "SdcClass.hh"
namespace sta {
class StaState;
class Corner;
class CheckCapacitanceLimits
{
public:
CheckCapacitanceLimits(const StaState *sta);
void init(const MinMax *min_max);
// Requires init().
// corner=nullptr checks all corners.
void checkCapacitance(const Pin *pin,
const Corner *corner1,
const MinMax *min_max,
// Return values.
// Corner is nullptr for no capacitance limit.
const Corner *&corner,
const RiseFall *&rf,
float &capacitance,
float &limit,
float &slack) const;
// corner=nullptr checks all corners.
PinSeq *pinCapacitanceLimitViolations(const Corner *corner,
const MinMax *min_max);
// corner=nullptr checks all corners.
Pin *pinMinCapacitanceLimitSlack(const Corner *corner,
const MinMax *min_max);
protected:
void checkCapacitance(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
const RiseFall *rf1,
float limit1,
// Return values.
const Corner *&corner1,
const RiseFall *&rf,
float &capacitance,
float &slack,
float &limit) const;
void checkCapacitance1(const Pin *pin,
const Corner *corner1,
const MinMax *min_max,
// Return values.
const Corner *&corner,
const RiseFall *&rf,
float &capacitance,
float &limit,
float &slack) const;
void findLimit(const Pin *pin,
const MinMax *min_max,
// Return values.
float &limit,
bool &limit_exists) const;
void pinCapacitanceLimitViolations(Instance *inst,
const Corner *corner,
const MinMax *min_max,
PinSeq *violators);
void pinMinCapacitanceLimitSlack(Instance *inst,
const Corner *corner,
const MinMax *min_max,
// Return values.
Pin *&min_slack_pin,
float &min_slack);
float top_limit_;
bool top_limit_exists_;
const StaState *sta_;
};
} // namespace

258
search/CheckFanoutLimits.cc Normal file
View File

@ -0,0 +1,258 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2020, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "CheckFanoutLimits.hh"
#include "Fuzzy.hh"
#include "Liberty.hh"
#include "Network.hh"
#include "Sdc.hh"
#include "PortDirection.hh"
namespace sta {
class PinFanoutLimitSlackLess
{
public:
PinFanoutLimitSlackLess(const MinMax *min_max,
CheckFanoutLimits *check_fanout_limit,
const StaState *sta);
bool operator()(Pin *pin1,
Pin *pin2) const;
private:
const MinMax *min_max_;
CheckFanoutLimits *check_fanout_limit_;
const StaState *sta_;
};
PinFanoutLimitSlackLess::PinFanoutLimitSlackLess(const MinMax *min_max,
CheckFanoutLimits *check_fanout_limit,
const StaState *sta) :
min_max_(min_max),
check_fanout_limit_(check_fanout_limit),
sta_(sta)
{
}
bool
PinFanoutLimitSlackLess::operator()(Pin *pin1,
Pin *pin2) const
{
float fanout1, fanout2;
float limit1, limit2, slack1, slack2;
check_fanout_limit_->checkFanout(pin1, min_max_,
fanout1, limit1, slack1);
check_fanout_limit_->checkFanout(pin2, min_max_,
fanout2, limit2, slack2);
return fuzzyLess(slack1, slack2)
|| (fuzzyEqual(slack1, slack2)
// Break ties for the sake of regression stability.
&& sta_->network()->pinLess(pin1, pin2));
}
////////////////////////////////////////////////////////////////
CheckFanoutLimits::CheckFanoutLimits(const StaState *sta) :
sta_(sta)
{
}
void
CheckFanoutLimits::init(const MinMax *min_max)
{
const Network *network = sta_->network();
Cell *top_cell = network->cell(network->topInstance());
float top_limit;
bool top_limit_exists;
sta_->sdc()->fanoutLimit(top_cell, min_max,
top_limit, top_limit_exists);
top_limit_= top_limit;
top_limit_exists_ = top_limit_exists;
}
void
CheckFanoutLimits::checkFanout(const Pin *pin,
const MinMax *min_max,
// Return values.
float &fanout,
float &limit,
float &slack) const
{
fanout = 0.0;
limit = 0.0;
slack = MinMax::min()->initValue();
float limit1;
bool limit1_exists;
findLimit(pin, min_max, limit1, limit1_exists);
if (limit1_exists) {
checkFanout(pin, min_max, limit1,
fanout, slack, limit);
}
}
void
CheckFanoutLimits::findLimit(const Pin *pin,
const MinMax *min_max,
// Return values.
float &limit,
bool &exists) const
{
exists = false;
const Network *network = sta_->network();
Sdc *sdc = sta_->sdc();
if (network->isTopLevelPort(pin)) {
Port *port = network->port(pin);
sdc->fanoutLimit(port, min_max, limit, exists);
if (!exists) {
limit = top_limit_;
exists = top_limit_exists_;
}
}
else {
Cell *cell = network->cell(network->instance(pin));
sdc->fanoutLimit(cell, min_max,
limit, exists);
if (!exists) {
LibertyPort *port = network->libertyPort(pin);
if (port) {
port->fanoutLimit(min_max, limit, exists);
if (!exists
&& port->direction()->isAnyOutput())
port->libertyLibrary()->defaultMaxFanout(limit, exists);
}
}
}
}
void
CheckFanoutLimits::checkFanout(const Pin *pin,
const MinMax *min_max,
float limit1,
// Return values.
float &fanout,
float &slack,
float &limit) const
{
float fanout1 = this->fanout(pin);
float slack1 = (min_max == MinMax::max())
? limit1 - fanout1
: fanout1 - limit1;
if (fuzzyLessEqual(slack1, slack)) {
fanout = fanout1;
slack = slack1;
limit = limit1;
}
}
float
CheckFanoutLimits::fanout(const Pin *pin) const
{
float fanout = 0;
const Network *network = sta_->network();
Net *net = network->net(pin);
NetPinIterator *pin_iter = network->pinIterator(net);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
if (network->isLoad(pin))
fanout++;
}
delete pin_iter;
return fanout;
}
PinSeq *
CheckFanoutLimits::pinFanoutLimitViolations(const MinMax *min_max)
{
init(min_max);
const Network *network = sta_->network();
PinSeq *violators = new PinSeq;
LeafInstanceIterator *inst_iter = network->leafInstanceIterator();
while (inst_iter->hasNext()) {
Instance *inst = inst_iter->next();
pinFanoutLimitViolations(inst, min_max, violators);
}
delete inst_iter;
// Check top level ports.
pinFanoutLimitViolations(network->topInstance(), min_max, violators);
sort(violators, PinFanoutLimitSlackLess(min_max, this, sta_));
return violators;
}
void
CheckFanoutLimits::pinFanoutLimitViolations(Instance *inst,
const MinMax *min_max,
PinSeq *violators)
{
const Network *network = sta_->network();
InstancePinIterator *pin_iter = network->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
float fanout;
float limit, slack;
checkFanout(pin, min_max, fanout, limit, slack );
if (slack < 0.0)
violators->push_back(pin);
}
delete pin_iter;
}
Pin *
CheckFanoutLimits::pinMinFanoutLimitSlack(const MinMax *min_max)
{
init(min_max);
const Network *network = sta_->network();
Pin *min_slack_pin = 0;
float min_slack = MinMax::min()->initValue();
LeafInstanceIterator *inst_iter = network->leafInstanceIterator();
while (inst_iter->hasNext()) {
Instance *inst = inst_iter->next();
pinMinFanoutLimitSlack(inst, min_max, min_slack_pin, min_slack);
}
delete inst_iter;
// Check top level ports.
pinMinFanoutLimitSlack(network->topInstance(), min_max,
min_slack_pin, min_slack);
return min_slack_pin;
}
void
CheckFanoutLimits::pinMinFanoutLimitSlack(Instance *inst,
const MinMax *min_max,
// Return values.
Pin *&min_slack_pin,
float &min_slack)
{
const Network *network = sta_->network();
InstancePinIterator *pin_iter = network->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
float fanout;
float limit, slack;
checkFanout(pin, min_max, fanout, limit, slack);
if (min_slack_pin == 0
|| slack < min_slack) {
min_slack_pin = pin;
min_slack = slack;
}
}
delete pin_iter;
}
} // namespace

View File

@ -0,0 +1,70 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2020, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include "MinMax.hh"
#include "NetworkClass.hh"
#include "SdcClass.hh"
namespace sta {
class StaState;
class CheckFanoutLimits
{
public:
CheckFanoutLimits(const StaState *sta);
void init(const MinMax *min_max);
// Requires init().
void checkFanout(const Pin *pin,
const MinMax *min_max,
// Return values.
float &fanout,
float &limit,
float &slack) const;
PinSeq *pinFanoutLimitViolations(const MinMax *min_max);
Pin *pinMinFanoutLimitSlack(const MinMax *min_max);
protected:
void checkFanout(const Pin *pin,
const MinMax *min_max,
float limit1,
// Return values.
float &fanout,
float &slack,
float &limit) const;
void findLimit(const Pin *pin,
const MinMax *min_max,
// Return values.
float &limit,
bool &limit_exists) const;
void pinFanoutLimitViolations(Instance *inst,
const MinMax *min_max,
PinSeq *violators);
void pinMinFanoutLimitSlack(Instance *inst,
const MinMax *min_max,
// Return values.
Pin *&min_slack_pin,
float &min_slack);
float fanout(const Pin *pin) const;
float top_limit_;
bool top_limit_exists_;
const StaState *sta_;
};
} // namespace

View File

@ -1549,21 +1549,22 @@ ReportPath::reportSkewClkPath(const char *arrival_msg,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void
ReportPath::reportSlewLimitShortHeader() ReportPath::reportLimitShortHeader(const char *what)
{ {
string result; string result;
reportSlewLimitShortHeader(result); reportLimitShortHeader(what, result);
report_->print(result); report_->print(result);
} }
void void
ReportPath::reportSlewLimitShortHeader(string &result) ReportPath::reportLimitShortHeader(const char *what,
string &result)
{ {
reportDescription("Pin", result); reportDescription("Pin", result);
result += ' '; result += ' ';
reportField("Limit", field_slew_, result); reportField("Limit", field_slew_, result);
result += ' '; result += ' ';
reportField("Trans", field_slew_, result); reportField(what, field_slew_, result);
result += ' '; result += ' ';
reportField("Slack", field_slew_, result); reportField("Slack", field_slew_, result);
reportEndOfLine(result); reportEndOfLine(result);
@ -1572,21 +1573,21 @@ ReportPath::reportSlewLimitShortHeader(string &result)
} }
void void
ReportPath::reportSlewLimitShort(Pin *pin, ReportPath::reportLimitShort(const char *what,
const RiseFall *rf, Pin *pin,
Slew slew, float value,
float limit, float limit,
float slack) float slack)
{ {
string result; string result;
reportSlewLimitShort(pin, rf, slew, limit, slack, result); reportLimitShort(what, pin, value, limit, slack, result);
report_->print(result); report_->print(result);
} }
void void
ReportPath::reportSlewLimitShort(Pin *pin, ReportPath::reportLimitShort(const char *what,
const RiseFall *, Pin *pin,
Slew slew, float value,
float limit, float limit,
float slack, float slack,
string &result) string &result)
@ -1594,29 +1595,29 @@ ReportPath::reportSlewLimitShort(Pin *pin,
const char *pin_name = cmd_network_->pathName(pin); const char *pin_name = cmd_network_->pathName(pin);
reportDescription(pin_name, result); reportDescription(pin_name, result);
reportSpaceFieldTime(limit, result); reportSpaceFieldTime(limit, result);
reportSpaceFieldDelay(slew, EarlyLate::late(), result); reportSpaceFieldDelay(value, EarlyLate::late(), result);
reportSpaceSlack(slack, result); reportSpaceSlack(slack, result);
} }
void void
ReportPath::reportSlewLimitVerbose(Pin *pin, ReportPath::reportLimitVerbose(const char *what,
const Corner *corner, Pin *pin,
const RiseFall *rf, const RiseFall *rf,
Slew slew, float value,
float limit, float limit,
float slack, float slack,
const MinMax *min_max) const MinMax *min_max)
{ {
string result; string result;
reportSlewLimitVerbose(pin, corner, rf, slew, limit, slack, min_max, result); reportLimitVerbose(what, pin, rf, value, limit, slack, min_max, result);
report_->print(result); report_->print(result);
} }
void void
ReportPath::reportSlewLimitVerbose(Pin *pin, ReportPath::reportLimitVerbose(const char *what,
const Corner *, Pin *pin,
const RiseFall *rf, const RiseFall *rf,
Slew slew, float value,
float limit, float limit,
float slack, float slack,
const MinMax *min_max, const MinMax *min_max,
@ -1625,20 +1626,25 @@ ReportPath::reportSlewLimitVerbose(Pin *pin,
result += "Pin "; result += "Pin ";
result += cmd_network_->pathName(pin); result += cmd_network_->pathName(pin);
result += ' '; result += ' ';
if (rf)
result += rf->shortName(); result += rf->shortName();
else
result += " ";
reportEndOfLine(result); reportEndOfLine(result);
result += min_max->asString(); result += min_max->asString();
result += "_transition "; result += " ";
result += what;
result += " ";
reportSpaceFieldTime(limit, result); reportSpaceFieldTime(limit, result);
reportEndOfLine(result); reportEndOfLine(result);
result += "transition_time "; result += what;
reportField(delayAsFloat(slew), field_slew_, result); result += " ";
reportField(value, field_slew_, result);
reportEndOfLine(result); reportEndOfLine(result);
reportDashLine(strlen("transition_time") + field_slew_->width() + 1, reportDashLine(strlen(what) + field_slew_->width() + 6, result);
result);
result += "Slack "; result += "Slack ";
reportSpaceSlack(slack, result); reportSpaceSlack(slack, result);

View File

@ -137,30 +137,31 @@ public:
void reportVerbose(MaxSkewCheck *check, void reportVerbose(MaxSkewCheck *check,
string &result); string &result);
void reportSlewLimitShortHeader(); void reportLimitShortHeader(const char *what);
void reportSlewLimitShortHeader(string &result); void reportLimitShortHeader(const char *what,
void reportSlewLimitShort(Pin *pin, string &result);
const RiseFall *rf, void reportLimitShort(const char *what,
Slew slew, Pin *pin,
float value,
float limit, float limit,
float slack); float slack);
void reportSlewLimitShort(Pin *pin, const void reportLimitShort(const char *what,
RiseFall *rf, Pin *pin,
Slew slew, float value,
float limit, float limit,
float slack, float slack,
string &result); string &result);
void reportSlewLimitVerbose(Pin *pin, void reportLimitVerbose(const char *what,
const Corner *corner, Pin *pin,
const RiseFall *rf, const RiseFall *rf,
Slew slew, float value,
float limit, float limit,
float slack, float slack,
const MinMax *min_max); const MinMax *min_max);
void reportSlewLimitVerbose(Pin *pin, void reportLimitVerbose(const char *what,
const Corner *corner, Pin *pin,
const RiseFall *rf, const RiseFall *rf,
Slew slew, float value,
float limit, float limit,
float slack, float slack,
const MinMax *min_max, const MinMax *min_max,

View File

@ -55,6 +55,8 @@
#include "PathGroup.hh" #include "PathGroup.hh"
#include "CheckTiming.hh" #include "CheckTiming.hh"
#include "CheckSlewLimits.hh" #include "CheckSlewLimits.hh"
#include "CheckFanoutLimits.hh"
#include "CheckCapacitanceLimits.hh"
#include "CheckMinPulseWidths.hh" #include "CheckMinPulseWidths.hh"
#include "CheckMinPeriods.hh" #include "CheckMinPeriods.hh"
#include "CheckMaxSkews.hh" #include "CheckMaxSkews.hh"
@ -256,6 +258,8 @@ Sta::Sta() :
current_instance_(nullptr), current_instance_(nullptr),
check_timing_(nullptr), check_timing_(nullptr),
check_slew_limits_(nullptr), check_slew_limits_(nullptr),
check_fanout_limits_(nullptr),
check_capacitance_limits_(nullptr),
check_min_pulse_widths_(nullptr), check_min_pulse_widths_(nullptr),
check_min_periods_(nullptr), check_min_periods_(nullptr),
check_max_skews_(nullptr), check_max_skews_(nullptr),
@ -437,6 +441,18 @@ Sta::makeCheckSlewLimits()
check_slew_limits_ = new CheckSlewLimits(this); check_slew_limits_ = new CheckSlewLimits(this);
} }
void
Sta::makeCheckFanoutLimits()
{
check_fanout_limits_ = new CheckFanoutLimits(this);
}
void
Sta::makeCheckCapacitanceLimits()
{
check_capacitance_limits_ = new CheckCapacitanceLimits(this);
}
void void
Sta::makeCheckMinPulseWidths() Sta::makeCheckMinPulseWidths()
{ {
@ -483,6 +499,8 @@ Sta::~Sta()
{ {
// Delete "top down" to minimize chance of referencing deleted memory. // Delete "top down" to minimize chance of referencing deleted memory.
delete check_slew_limits_; delete check_slew_limits_;
delete check_fanout_limits_;
delete check_capacitance_limits_;
delete check_min_pulse_widths_; delete check_min_pulse_widths_;
delete check_min_periods_; delete check_min_periods_;
delete check_max_skews_; delete check_max_skews_;
@ -4813,7 +4831,7 @@ void
Sta::checkSlewLimitPreamble() Sta::checkSlewLimitPreamble()
{ {
if (sdc_->haveClkSlewLimits()) if (sdc_->haveClkSlewLimits())
// Arrivals are needed to know what pin clock domains. // Arrivals are needed to know pin clock domains.
updateTiming(false); updateTiming(false);
else else
findDelays(); findDelays();
@ -4840,7 +4858,7 @@ Sta::pinSlewLimitViolations(const Corner *corner,
void void
Sta::reportSlewLimitShortHeader() Sta::reportSlewLimitShortHeader()
{ {
report_path_->reportSlewLimitShortHeader(); report_path_->reportLimitShortHeader("Slew");
} }
void void
@ -4854,7 +4872,7 @@ Sta::reportSlewLimitShort(Pin *pin,
float limit, slack; float limit, slack;
check_slew_limits_->checkSlews(pin, corner, min_max, check_slew_limits_->checkSlews(pin, corner, min_max,
corner1, rf, slew, limit, slack); corner1, rf, slew, limit, slack);
report_path_->reportSlewLimitShort(pin, rf, slew, limit, slack); report_path_->reportLimitShort("slew", pin, delayAsFloat(slew), limit, slack);
} }
void void
@ -4868,7 +4886,7 @@ Sta::reportSlewLimitVerbose(Pin *pin,
float limit, slack; float limit, slack;
check_slew_limits_->checkSlews(pin, corner, min_max, check_slew_limits_->checkSlews(pin, corner, min_max,
corner1, rf, slew, limit, slack); corner1, rf, slew, limit, slack);
report_path_->reportSlewLimitVerbose(pin, corner1, rf, slew, report_path_->reportLimitVerbose("slew", pin, rf, delayAsFloat(slew),
limit, slack, min_max); limit, slack, min_max);
} }
@ -4891,6 +4909,148 @@ Sta::checkSlews(const Pin *pin,
////////////////////////////////////////////////////////////////' ////////////////////////////////////////////////////////////////'
void
Sta::checkFanoutLimitPreamble()
{
if (check_fanout_limits_ == nullptr)
makeCheckFanoutLimits();
}
Pin *
Sta::pinMinFanoutLimitSlack(const MinMax *min_max)
{
checkFanoutLimitPreamble();
return check_fanout_limits_->pinMinFanoutLimitSlack(min_max);
}
PinSeq *
Sta::pinFanoutLimitViolations(const MinMax *min_max)
{
checkFanoutLimitPreamble();
return check_fanout_limits_->pinFanoutLimitViolations(min_max);
}
void
Sta::reportFanoutLimitShortHeader()
{
report_path_->reportLimitShortHeader("Fanout");
}
void
Sta::reportFanoutLimitShort(Pin *pin,
const MinMax *min_max)
{
float fanout, limit, slack;
check_fanout_limits_->checkFanout(pin, min_max,
fanout, limit, slack);
report_path_->reportLimitShort("fanout", pin, fanout, limit, slack);
}
void
Sta::reportFanoutLimitVerbose(Pin *pin,
const MinMax *min_max)
{
float fanout, limit, slack;
check_fanout_limits_->checkFanout(pin, min_max,
fanout, limit, slack);
report_path_->reportLimitVerbose("fanout", pin, nullptr, fanout,
limit, slack, min_max);
}
void
Sta::checkFanouts(const Pin *pin,
const MinMax *min_max,
// Return values.
float &fanout,
float &limit,
float &slack)
{
checkFanoutLimitPreamble();
check_fanout_limits_->init(min_max);
check_fanout_limits_->checkFanout(pin, min_max,
fanout, limit, slack);
}
////////////////////////////////////////////////////////////////'
void
Sta::checkCapacitanceLimitPreamble()
{
if (check_capacitance_limits_ == nullptr)
makeCheckCapacitanceLimits();
}
Pin *
Sta::pinMinCapacitanceLimitSlack(const Corner *corner,
const MinMax *min_max)
{
checkCapacitanceLimitPreamble();
return check_capacitance_limits_->pinMinCapacitanceLimitSlack(corner, min_max);
}
PinSeq *
Sta::pinCapacitanceLimitViolations(const Corner *corner,
const MinMax *min_max)
{
checkCapacitanceLimitPreamble();
return check_capacitance_limits_->pinCapacitanceLimitViolations(corner, min_max);
}
void
Sta::reportCapacitanceLimitShortHeader()
{
report_path_->reportLimitShortHeader("Capacitance");
}
void
Sta::reportCapacitanceLimitShort(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
const Corner *corner1;
const RiseFall *rf;
float capacitance, limit, slack;
check_capacitance_limits_->checkCapacitance(pin, corner, min_max,
corner1, rf, capacitance,
limit, slack);
report_path_->reportLimitShort("capacitance", pin, capacitance, limit, slack);
}
void
Sta::reportCapacitanceLimitVerbose(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
const Corner *corner1;
const RiseFall *rf;
float capacitance, limit, slack;
check_capacitance_limits_->checkCapacitance(pin, corner, min_max,
corner1, rf, capacitance,
limit, slack);
report_path_->reportLimitVerbose("capacitance", pin, rf,
capacitance, limit, slack, min_max);
}
void
Sta::checkCapacitances(const Pin *pin,
const Corner *corner,
const MinMax *min_max,
// Return values.
const Corner *&corner1,
const RiseFall *&rf,
float &capacitance,
float &limit,
float &slack)
{
checkCapacitanceLimitPreamble();
check_capacitance_limits_->init(min_max);
check_capacitance_limits_->checkCapacitance(pin, corner, min_max,
corner1, rf, capacitance,
limit, slack);
}
////////////////////////////////////////////////////////////////'
void void
Sta::minPulseWidthPreamble() Sta::minPulseWidthPreamble()
{ {

View File

@ -386,7 +386,7 @@ proc report_slew_limits { corner min_max all_violators verbose nosplit } {
if { $all_violators } { if { $all_violators } {
set violators [pin_slew_limit_violations $corner $min_max] set violators [pin_slew_limit_violations $corner $min_max]
if { $violators != {} } { if { $violators != {} } {
puts "${min_max}_transition" puts "${min_max} slew"
puts "" puts ""
if { $verbose } { if { $verbose } {
foreach pin $violators { foreach pin $violators {
@ -404,7 +404,7 @@ proc report_slew_limits { corner min_max all_violators verbose nosplit } {
} else { } else {
set pin [pin_min_slew_limit_slack $corner $min_max] set pin [pin_min_slew_limit_slack $corner $min_max]
if { $pin != "NULL" } { if { $pin != "NULL" } {
puts "${min_max}_transition" puts "${min_max} slew"
puts "" puts ""
if { $verbose } { if { $verbose } {
report_slew_limit_verbose $pin $corner $min_max report_slew_limit_verbose $pin $corner $min_max
@ -418,6 +418,80 @@ proc report_slew_limits { corner min_max all_violators verbose nosplit } {
} }
} }
proc report_fanout_limits { min_max all_violators verbose nosplit } {
if { $all_violators } {
set violators [pin_fanout_limit_violations $min_max]
if { $violators != {} } {
puts "${min_max} fanout"
puts ""
if { $verbose } {
foreach pin $violators {
report_fanout_limit_verbose $pin $min_max
puts ""
}
} else {
report_fanout_limit_short_header
foreach pin $violators {
report_fanout_limit_short $pin $min_max
}
puts ""
}
}
} else {
set pin [pin_min_fanout_limit_slack $min_max]
if { $pin != "NULL" } {
puts "${min_max} fanout"
puts ""
if { $verbose } {
report_fanout_limit_verbose $pin $min_max
puts ""
} else {
report_fanout_limit_short_header
report_fanout_limit_short $pin $min_max
puts ""
}
}
}
}
proc report_capacitance_limits { corner min_max all_violators verbose nosplit } {
if { $all_violators } {
set violators [pin_capacitance_limit_violations $corner $min_max]
if { $violators != {} } {
puts "${min_max} capacitance"
puts ""
if { $verbose } {
foreach pin $violators {
report_capacitance_limit_verbose $pin $corner $min_max
puts ""
}
} else {
report_capacitance_limit_short_header
foreach pin $violators {
report_capacitance_limit_short $pin $corner $min_max
}
puts ""
}
}
} else {
set pin [pin_min_capacitance_limit_slack $corner $min_max]
if { $pin != "NULL" } {
puts "${min_max} capacitance"
puts ""
if { $verbose } {
report_capacitance_limit_verbose $pin $corner $min_max
puts ""
} else {
report_capacitance_limit_short_header
report_capacitance_limit_short $pin $corner $min_max
puts ""
}
}
}
}
################################################################
proc report_path_ends { path_ends } { proc report_path_ends { path_ends } {
report_path_end_header report_path_end_header
set prev_end "NULL" set prev_end "NULL"

View File

@ -319,6 +319,8 @@ define_sta_cmd_args "report_check_types" \
[-recovery] [-removal]\ [-recovery] [-removal]\
[-clock_gating_setup] [-clock_gating_hold]\ [-clock_gating_setup] [-clock_gating_hold]\
[-max_slew] [-min_slew]\ [-max_slew] [-min_slew]\
[-max_fanout] [-min_fanout]\
[-max_capacitance] [-min_capacitance]\
[-min_pulse_width] [-min_period] [-max_skew]\ [-min_pulse_width] [-min_period] [-max_skew]\
[-digits digits] [-no_line_splits]\ [-digits digits] [-no_line_splits]\
[> filename] [>> filename]} [> filename] [>> filename]}
@ -358,35 +360,47 @@ proc_redirect report_check_types {
set recovery 1 set recovery 1
set clk_gating_setup 1 set clk_gating_setup 1
set max_slew 1 set max_slew 1
set max_fanout 1
set max_capacitance 1
} else { } else {
set setup 0 set setup 0
set recovery 0 set recovery 0
set clk_gating_setup 0 set clk_gating_setup 0
set max_slew 0 set max_slew 0
set max_fanout 0
set max_capacitance 0
} }
if { $min_max == "min" || $min_max == "min_max" } { if { $min_max == "min" || $min_max == "min_max" } {
set hold 1 set hold 1
set removal 1 set removal 1
set clk_gating_hold 1 set clk_gating_hold 1
set min_slew 1 set min_slew 1
set min_fanout 1
set min_capacitance 1
} else { } else {
set hold 0 set hold 0
set min_delay 0 set min_delay 0
set removal 0 set removal 0
set clk_gating_hold 0 set clk_gating_hold 0
set min_slew 0 set min_slew 0
set min_fanout 0
set min_capacitance 0
} }
set min_pulse_width 1 set min_pulse_width 1
set min_period 1 set min_period 1
set max_skew 1 set max_skew 1
set max_fanout 1
set max_capacitance 1
} else { } else {
parse_key_args "report_check_types" args keys {} \ parse_key_args "report_check_types" args keys {} \
flags {-max_delay -min_delay -recovery -removal \ flags {-max_delay -min_delay -recovery -removal \
-clock_gating_setup -clock_gating_hold \ -clock_gating_setup -clock_gating_hold \
-max_slew -min_slew \ -max_slew -min_slew \
-max_transition -min_transition \ -max_fanout -min_fanout \
-max_capacitance -min_capacitance \
-min_pulse_width \ -min_pulse_width \
-min_period -max_skew} 1 -min_period -max_skew \
-max_transition -min_transition } 1
set setup [info exists flags(-max_delay)] set setup [info exists flags(-max_delay)]
set hold [info exists flags(-min_delay)] set hold [info exists flags(-min_delay)]
@ -404,6 +418,10 @@ proc_redirect report_check_types {
sta_warn "-min_transition deprecated. Use -min_slew." sta_warn "-min_transition deprecated. Use -min_slew."
set min_slew 1 set min_slew 1
} }
set max_fanout [info exists flags(-max_fanout)]
set min_fanout [info exists flags(-min_fanout)]
set max_capacitance [info exists flags(-max_capacitance)]
set min_capacitance [info exists flags(-min_capacitance)]
set min_pulse_width [info exists flags(-min_pulse_width)] set min_pulse_width [info exists flags(-min_pulse_width)]
set min_period [info exists flags(-min_period)] set min_period [info exists flags(-min_period)]
set max_skew [info exists flags(-max_skew)] set max_skew [info exists flags(-max_skew)]
@ -457,6 +475,18 @@ proc_redirect report_check_types {
if { $min_slew } { if { $min_slew } {
report_slew_limits $corner "min" $violators $verbose $nosplit report_slew_limits $corner "min" $violators $verbose $nosplit
} }
if { $max_fanout } {
# report_fanout_limits "max" $violators $verbose $nosplit
}
if { $min_fanout } {
# report_fanout_limits "min" $violators $verbose $nosplit
}
if { $max_capacitance } {
# report_capacitance_limits $corner "max" $violators $verbose $nosplit
}
if { $min_capacitance } {
# report_capacitance_limits $corner "min" $violators $verbose $nosplit
}
if { $min_pulse_width } { if { $min_pulse_width } {
if { $violators } { if { $violators } {
set checks [min_pulse_width_violations $corner] set checks [min_pulse_width_violations $corner]

View File

@ -4613,6 +4613,8 @@ report_delay_calc_cmd(Edge *edge,
return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits); return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits);
} }
////////////////////////////////////////////////////////////////
Pin * Pin *
pin_min_slew_limit_slack(const Corner *corner, pin_min_slew_limit_slack(const Corner *corner,
const MinMax *min_max) const MinMax *min_max)
@ -4653,6 +4655,82 @@ report_slew_limit_verbose(Pin *pin,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Pin *
pin_min_fanout_limit_slack(const MinMax *min_max)
{
cmdLinkedNetwork();
return Sta::sta()->pinMinFanoutLimitSlack(min_max);
}
PinSeq *
pin_fanout_limit_violations(const MinMax *min_max)
{
cmdLinkedNetwork();
return Sta::sta()->pinFanoutLimitViolations(min_max);
}
void
report_fanout_limit_short_header()
{
Sta::sta()->reportFanoutLimitShortHeader();
}
void
report_fanout_limit_short(Pin *pin,
const MinMax *min_max)
{
Sta::sta()->reportFanoutLimitShort(pin, min_max);
}
void
report_fanout_limit_verbose(Pin *pin,
const MinMax *min_max)
{
Sta::sta()->reportFanoutLimitVerbose(pin, min_max);
}
////////////////////////////////////////////////////////////////
Pin *
pin_min_capacitance_limit_slack(const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
return Sta::sta()->pinMinCapacitanceLimitSlack(corner, min_max);
}
PinSeq *
pin_capacitance_limit_violations(const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
return Sta::sta()->pinCapacitanceLimitViolations(corner, min_max);
}
void
report_capacitance_limit_short_header()
{
Sta::sta()->reportCapacitanceLimitShortHeader();
}
void
report_capacitance_limit_short(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
Sta::sta()->reportCapacitanceLimitShort(pin, corner, min_max);
}
void
report_capacitance_limit_verbose(Pin *pin,
const Corner *corner,
const MinMax *min_max)
{
Sta::sta()->reportCapacitanceLimitVerbose(pin, corner, min_max);
}
////////////////////////////////////////////////////////////////
TmpFloatSeq * TmpFloatSeq *
design_power(const Corner *corner) design_power(const Corner *corner)
{ {