From 32adfad72ecdd2fd74ebf5543dc7c6900c4c9637 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 8 Jun 2020 20:11:15 -0700 Subject: [PATCH] liberty default_fanout_load, fanout_load for report -max_fanout --- include/sta/Liberty.hh | 11 +++++- include/sta/Sta.hh | 12 +++--- liberty/Liberty.cc | 31 +++++++++++++++- liberty/LibertyReader.cc | 16 ++++++++ liberty/LibertyReaderPvt.hh | 1 + search/CheckCapacitanceLimits.cc | 44 +++++++++++++++------- search/CheckFanoutLimits.cc | 64 +++++++++++++++++++++++--------- search/CheckFanoutLimits.hh | 2 +- search/CheckSlewLimits.cc | 18 +++------ search/Sta.cc | 12 +++--- 10 files changed, 151 insertions(+), 60 deletions(-) diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 205cb4ec..4f39606e 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -202,7 +202,9 @@ public: void defaultMaxFanout(float &fanout, bool &exists) const; void setDefaultMaxFanout(float fanout); - float defaultFanoutLoad() const { return default_fanout_load_; } + void defaultFanoutLoad(// Return values. + float &fanout, + bool &exists) const; void setDefaultFanoutLoad(float load); // Logic thresholds. @@ -307,6 +309,7 @@ protected: RiseFallValues default_inout_pin_res_; RiseFallValues default_output_pin_res_; float default_fanout_load_; + bool default_fanout_load_exists_; float default_max_cap_; bool default_max_cap_exists_; float default_max_fanout_; @@ -623,6 +626,10 @@ public: LibertyLibrary *libertyLibrary() const { return liberty_cell_->libertyLibrary(); } LibertyPort *findLibertyMember(int index) const; LibertyPort *findLibertyBusBit(int index) const; + void fanoutLoad(// Return values. + float &fanout_load, + bool &exists) const; + void setFanoutLoad(float fanout_load); float capacitance(const RiseFall *rf, const MinMax *min_max) const; void capacitance(const RiseFall *rf, @@ -748,6 +755,8 @@ protected: RiseFallMinMax capacitance_; MinMaxFloatValues slew_limit_; // inputs and outputs MinMaxFloatValues cap_limit_; // outputs + float fanout_load_; // inputs + bool fanout_load_exists_; MinMaxFloatValues fanout_limit_; // outputs float min_period_; float min_pulse_width_[RiseFall::index_count]; diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index a9f6aa5a..cef2e98c 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -647,12 +647,12 @@ public: 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 checkFanout(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. diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 99958888..4c328b77 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -71,6 +71,7 @@ LibertyLibrary::LibertyLibrary(const char *name, default_output_pin_cap_(0.0), default_bidirect_pin_cap_(0.0), default_fanout_load_(0.0), + default_fanout_load_exists_(false), default_max_cap_(0.0), default_max_cap_exists_(false), default_max_fanout_(0.0), @@ -425,10 +426,20 @@ LibertyLibrary::setDefaultMaxCapacitance(float cap) default_max_cap_exists_ = true; } +void +LibertyLibrary::defaultFanoutLoad(// Return values. + float &fanout, + bool &exists) const +{ + fanout = default_fanout_load_; + exists = default_fanout_load_exists_; +} + void LibertyLibrary::setDefaultFanoutLoad(float load) { default_fanout_load_ = load; + default_fanout_load_exists_ = true; } void @@ -1811,8 +1822,8 @@ LibertyPort::LibertyPort(LibertyCell *cell, function_(nullptr), tristate_enable_(nullptr), scaled_ports_(nullptr), - // capacitance_ intentionally not initialized so - // liberty reader can apply default capacitance. + fanout_load_(0.0), + fanout_load_exists_(false), min_period_(0.0), pulse_clk_trigger_(nullptr), pulse_clk_sense_(nullptr), @@ -2040,6 +2051,22 @@ LibertyPort::setCapacitanceLimit(float cap, cap_limit_.setValue(min_max, cap); } +void +LibertyPort::fanoutLoad(// Return values. + float &fanout_load, + bool &exists) const +{ + fanout_load = fanout_load_; + exists = fanout_load_exists_; +} + +void +LibertyPort::setFanoutLoad(float fanout_load) +{ + fanout_load_ = fanout_load; + fanout_load_exists_ = true; +} + void LibertyPort::fanoutLimit(const MinMax *min_max, // Return values. diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 914a7b34..b83235e8 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -307,6 +307,7 @@ LibertyReader::defineVisitors() &LibertyReader::visitRiseCapRange); defineAttrVisitor("fall_capacitance_range", &LibertyReader::visitFallCapRange); + defineAttrVisitor("fanout_load", &LibertyReader::visitFanoutLoad); defineAttrVisitor("max_fanout", &LibertyReader::visitMaxFanout); defineAttrVisitor("min_fanout", &LibertyReader::visitMinFanout); defineAttrVisitor("max_transition", &LibertyReader::visitMaxTransition); @@ -2967,6 +2968,21 @@ LibertyReader::defaultCap(LibertyPort *port) return cap; } +void +LibertyReader::visitFanoutLoad(LibertyAttr *attr) +{ + if (ports_) { + float fanout; + bool exists; + getAttrFloat(attr, fanout, exists); + if (exists) { + visitPorts([&] (LibertyPort *port) { + port->setFanoutLoad(fanout); + }); + } + } +} + void LibertyReader::visitMaxFanout(LibertyAttr *attr) { diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index a29862d4..edeb0f24 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -206,6 +206,7 @@ public: virtual void visitFallCap(LibertyAttr *attr); virtual void visitRiseCapRange(LibertyAttr *attr); virtual void visitFallCapRange(LibertyAttr *attr); + virtual void visitFanoutLoad(LibertyAttr *attr); virtual void visitMaxFanout(LibertyAttr *attr); virtual void visitMinFanout(LibertyAttr *attr); virtual void visitFanout(LibertyAttr *attr, diff --git a/search/CheckCapacitanceLimits.cc b/search/CheckCapacitanceLimits.cc index fffda964..1eb6d74d 100644 --- a/search/CheckCapacitanceLimits.cc +++ b/search/CheckCapacitanceLimits.cc @@ -145,6 +145,7 @@ CheckCapacitanceLimits::checkCapacitance1(const Pin *pin, } } +// return the tightest limit. void CheckCapacitanceLimits::findLimit(const Pin *pin, const MinMax *min_max, @@ -152,28 +153,45 @@ CheckCapacitanceLimits::findLimit(const Pin *pin, float &limit, bool &exists) const { - exists = false; + // Default to top ("design") limit. + limit = top_limit_; + exists = top_limit_exists_; + const Network *network = sta_->network(); Sdc *sdc = sta_->sdc(); + float limit1; + bool exists1; 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_; + sdc->capacitanceLimit(port, min_max, limit1, exists1); + if (exists1 + && (!exists + || min_max->compare(limit, limit1))) { + limit = limit1; + exists = true; } } 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); + limit1, exists1); + if (exists1 + && (!exists + || min_max->compare(limit, limit1))) { + limit = limit1; + exists = true; + } + LibertyPort *port = network->libertyPort(pin); + if (port) { + port->capacitanceLimit(min_max, limit1, exists1); + if (!exists1 + && port->direction()->isAnyOutput()) + port->libertyLibrary()->defaultMaxCapacitance(limit1, exists1); + if (exists1 + && (!exists + || min_max->compare(limit, limit1))) { + limit = limit1; + exists = true; } } } diff --git a/search/CheckFanoutLimits.cc b/search/CheckFanoutLimits.cc index 00550cd9..0620b5a9 100644 --- a/search/CheckFanoutLimits.cc +++ b/search/CheckFanoutLimits.cc @@ -105,6 +105,7 @@ CheckFanoutLimits::checkFanout(const Pin *pin, fanout, slack, limit); } +// return the tightest limit. void CheckFanoutLimits::findLimit(const Pin *pin, const MinMax *min_max, @@ -112,29 +113,46 @@ CheckFanoutLimits::findLimit(const Pin *pin, float &limit, bool &exists) const { - exists = false; + // Default to top ("design") limit. + limit = top_limit_; + exists = top_limit_exists_; + const Network *network = sta_->network(); Sdc *sdc = sta_->sdc(); + float limit1; + bool exists1; 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_; + sdc->fanoutLimit(port, min_max, limit1, exists1); + if (exists1 + && (!exists + || min_max->compare(limit, limit1))) { + limit = limit1; + exists = true; } } 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 - && min_max == MinMax::max() - && port->direction()->isAnyOutput()) - port->libertyLibrary()->defaultMaxFanout(limit, exists); + limit1, exists1); + if (exists1 + && (!exists + || min_max->compare(limit, limit1))) { + limit = limit1; + exists = true; + } + LibertyPort *port = network->libertyPort(pin); + if (port) { + port->fanoutLimit(min_max, limit1, exists1); + if (!exists1 + && min_max == MinMax::max() + && port->direction()->isAnyOutput()) + port->libertyLibrary()->defaultMaxFanout(limit1, exists1); + if (exists1 + && (!exists + || min_max->compare(limit, limit1))) { + limit = limit1; + exists = true; } } } @@ -149,7 +167,7 @@ CheckFanoutLimits::checkFanout(const Pin *pin, float &slack, float &limit) const { - float fanout1 = this->fanout(pin); + float fanout1 = fanoutLoad(pin); float slack1 = (min_max == MinMax::max()) ? limit1 - fanout1 : fanout1 - limit1; @@ -161,7 +179,7 @@ CheckFanoutLimits::checkFanout(const Pin *pin, } float -CheckFanoutLimits::fanout(const Pin *pin) const +CheckFanoutLimits::fanoutLoad(const Pin *pin) const { float fanout = 0; const Network *network = sta_->network(); @@ -170,8 +188,18 @@ CheckFanoutLimits::fanout(const Pin *pin) const NetPinIterator *pin_iter = network->pinIterator(net); while (pin_iter->hasNext()) { Pin *pin = pin_iter->next(); - if (network->isLoad(pin)) - fanout++; + if (network->isLoad(pin)) { + LibertyPort *port = network->libertyPort(pin); + float fanout_load; + bool exists; + port->fanoutLoad(fanout_load, exists); + if (!exists) { + LibertyLibrary *lib = port->libertyLibrary(); + lib->defaultFanoutLoad(fanout_load, exists); + } + if (exists) + fanout += fanout_load; + } } delete pin_iter; } diff --git a/search/CheckFanoutLimits.hh b/search/CheckFanoutLimits.hh index f8de4139..380e6c43 100644 --- a/search/CheckFanoutLimits.hh +++ b/search/CheckFanoutLimits.hh @@ -60,7 +60,7 @@ protected: // Return values. Pin *&min_slack_pin, float &min_slack); - float fanout(const Pin *pin) const; + float fanoutLoad(const Pin *pin) const; float top_limit_; bool top_limit_exists_; diff --git a/search/CheckSlewLimits.cc b/search/CheckSlewLimits.cc index 2975bc53..db939c25 100644 --- a/search/CheckSlewLimits.cc +++ b/search/CheckSlewLimits.cc @@ -170,6 +170,7 @@ CheckSlewLimits::checkSlews1(Vertex *vertex, } } +// return the tightest limit. void CheckSlewLimits::findLimit(const Pin *pin, const Vertex *vertex, @@ -202,7 +203,6 @@ CheckSlewLimits::findLimit(const Pin *pin, if (exists1 && (!exists || min_max->compare(limit, limit1))) { - // Use the tightest clock limit. limit = limit1; exists = true; } @@ -210,7 +210,6 @@ CheckSlewLimits::findLimit(const Pin *pin, if (network->isTopLevelPort(pin)) { Port *port = network->port(pin); sdc->slewLimit(port, min_max, limit1, exists1); - // Use the tightest limit. if (exists1 && (!exists || min_max->compare(limit, limit1))) { @@ -222,23 +221,16 @@ CheckSlewLimits::findLimit(const Pin *pin, LibertyPort *port = network->libertyPort(pin); if (port) { port->slewLimit(min_max, limit1, exists1); - // Use the tightest limit. + if (!exists1 + && port->direction()->isAnyOutput() + && min_max == MinMax::max()) + port->libertyLibrary()->defaultMaxSlew(limit1, exists1); if (exists1 && (!exists || min_max->compare(limit, limit1))) { limit = limit1; exists = true; } - if (port->direction()->isAnyOutput() - && min_max == MinMax::max()) { - port->libertyLibrary()->defaultMaxSlew(limit1, exists1); - if (exists1 - && (!exists - || min_max->compare(limit, limit1))) { - limit = limit1; - exists = true; - } - } } } } diff --git a/search/Sta.cc b/search/Sta.cc index ef93de5d..c7b807c3 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -4954,12 +4954,12 @@ Sta::reportFanoutLimitVerbose(Pin *pin, } void -Sta::checkFanouts(const Pin *pin, - const MinMax *min_max, - // Return values. - float &fanout, - float &limit, - float &slack) +Sta::checkFanout(const Pin *pin, + const MinMax *min_max, + // Return values. + float &fanout, + float &limit, + float &slack) { checkFanoutLimitPreamble(); check_fanout_limits_->init(min_max);