From 12ca61388641c10e8d6eac9875377e034a1ea99e Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 18 Apr 2019 18:01:10 -0700 Subject: [PATCH] 2.0.14 --- CMakeLists.txt | 6 ++-- dcalc/ArnoldiDelayCalc.cc | 11 +++--- dcalc/DmpDelayCalc.cc | 41 ++++++++++++---------- dcalc/LumpedCapDelayCalc.cc | 33 ++++++++++-------- liberty/LibertyReader.cc | 14 ++++++-- liberty/LibertyReaderPvt.hh | 1 + parasitics/ConcreteParasitics.cc | 20 ++++++----- parasitics/ConcreteParasitics.hh | 2 +- parasitics/NullParasitics.cc | 6 ++++ parasitics/NullParasitics.hh | 1 + parasitics/Parasitics.hh | 1 + search/Power.cc | 18 ++++++---- tcl/Sdc.tcl | 49 ++++++++++++++------------ tcl/StaTcl.i | 60 +++++++++++++------------------- 14 files changed, 145 insertions(+), 118 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 305c84fa..acd81b72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ cmake_minimum_required (VERSION 3.9) -project(STA VERSION 2.0.13) +project(STA VERSION 2.0.14) set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_CXX_STANDARD 11) @@ -33,12 +33,12 @@ if(NOT CMAKE_BUILD_TYPE) endif() # Compiler specific options. -if (CMAKE_CXX_COMPILER_ID MATCHES AppleClang|Clang|GNU) +if (CMAKE_CXX_COMPILER_ID MATCHES AppleClang|Clang) set(STA_COMPILE_OPTIONS -Wall -Wcast-qual -Wunused-parameter -Wredundant-decls -Wno-deprecated-register) endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(STA_COMPILE_OPTIONS -Wall -Wcast-qual -Wunused-parameter -Wredundant-decls -Wno-deprecated-register) + set(STA_COMPILE_OPTIONS -Wall -Wcast-qual -Wunused-parameter -Wredundant-decls) endif() message(STATUS "System name: ${CMAKE_SYSTEM_NAME}") diff --git a/dcalc/ArnoldiDelayCalc.cc b/dcalc/ArnoldiDelayCalc.cc index 5241841c..a8ab1868 100644 --- a/dcalc/ArnoldiDelayCalc.cc +++ b/dcalc/ArnoldiDelayCalc.cc @@ -288,11 +288,12 @@ ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin, } if (parasitic_network) { - Parasitic *parasitic = reduce_->reduceToArnoldi(parasitic_network, - drvr_pin, - parasitic_ap->couplingCapFactor(), - drvr_tr, op_cond, corner, - cnst_min_max, parasitic_ap); + Parasitic *parasitic = + reduce_->reduceToArnoldi(parasitic_network, + drvr_pin, + parasitic_ap->couplingCapFactor(), + drvr_tr, op_cond, corner, + cnst_min_max, parasitic_ap); if (delete_parasitic_network) { Net *net = network_->net(drvr_pin); parasitics_->deleteParasiticNetwork(net, parasitic_ap); diff --git a/dcalc/DmpDelayCalc.cc b/dcalc/DmpDelayCalc.cc index c5dfa5c9..dcb85183 100644 --- a/dcalc/DmpDelayCalc.cc +++ b/dcalc/DmpDelayCalc.cc @@ -202,28 +202,31 @@ DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin, { // set_load has precidence over parasitics. if (!sdc_->drvrPinHasWireCap(drvr_pin)) { + Parasitic *parasitic = nullptr; const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); - // Prefer PiPoleResidue. - Parasitic *parasitic = parasitics_->findPiPoleResidue(drvr_pin, tr, - parasitic_ap); - if (parasitic) - return parasitic; + if (parasitics_->haveParasitics()) { + // Prefer PiPoleResidue. + parasitic = parasitics_->findPiPoleResidue(drvr_pin, tr, + parasitic_ap); + if (parasitic) + return parasitic; - parasitic = parasitics_->findPiElmore(drvr_pin, tr, parasitic_ap); - if (parasitic) - return parasitic; + parasitic = parasitics_->findPiElmore(drvr_pin, tr, parasitic_ap); + if (parasitic) + return parasitic; - Parasitic *parasitic_network = - parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); - if (parasitic_network) { - parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, - dcalc_ap->operatingConditions(), - dcalc_ap->corner(), - dcalc_ap->constraintMinMax(), - parasitic_ap); - parasitic = parasitics_->findPiPoleResidue(drvr_pin, tr, parasitic_ap); - reduced_parasitic_drvrs_.push_back(drvr_pin); - return parasitic; + Parasitic *parasitic_network = + parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); + if (parasitic_network) { + parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, + dcalc_ap->operatingConditions(), + dcalc_ap->corner(), + dcalc_ap->constraintMinMax(), + parasitic_ap); + parasitic = parasitics_->findPiPoleResidue(drvr_pin, tr, parasitic_ap); + reduced_parasitic_drvrs_.push_back(drvr_pin); + return parasitic; + } } const MinMax *cnst_min_max = dcalc_ap->constraintMinMax(); diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index 79832e48..b72976ac 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -53,23 +53,26 @@ LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin, { // set_load has precidence over parasitics. if (!sdc_->drvrPinHasWireCap(drvr_pin)) { + Parasitic *parasitic = nullptr; const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); - // Prefer PiElmore. - Parasitic *parasitic = parasitics_->findPiElmore(drvr_pin, tr,parasitic_ap); - if (parasitic) - return parasitic; - - Parasitic *parasitic_network = - parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); - if (parasitic_network) { - parasitics_->reduceToPiElmore(parasitic_network, drvr_pin, - dcalc_ap->operatingConditions(), - dcalc_ap->corner(), - dcalc_ap->constraintMinMax(), - parasitic_ap); + if (parasitics_->haveParasitics()) { + // Prefer PiElmore. parasitic = parasitics_->findPiElmore(drvr_pin, tr,parasitic_ap); - reduced_parasitic_drvrs_.push_back(drvr_pin); - return parasitic; + if (parasitic) + return parasitic; + + Parasitic *parasitic_network = + parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); + if (parasitic_network) { + parasitics_->reduceToPiElmore(parasitic_network, drvr_pin, + dcalc_ap->operatingConditions(), + dcalc_ap->corner(), + dcalc_ap->constraintMinMax(), + parasitic_ap); + parasitic = parasitics_->findPiElmore(drvr_pin, tr,parasitic_ap); + reduced_parasitic_drvrs_.push_back(drvr_pin); + return parasitic; + } } const MinMax *cnst_min_max = dcalc_ap->constraintMinMax(); diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index c11796c2..67550600 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -541,7 +541,8 @@ LibertyReader::beginLibrary(LibertyGroup *group) time_scale_ = 1E-9F; // 1ohm default res_scale_ = 1.0F; - cap_scale_ = 1.0F; + // pF default + cap_scale_ = 1E-12F; // 1v default volt_scale_ = 1; // Default is 1mA. @@ -549,7 +550,7 @@ LibertyReader::beginLibrary(LibertyGroup *group) // Default is 1; power_scale_ = 1; // Default is fJ. - energy_scale_ = 1e-15; + setEnergyScale(); library_->units()->timeUnit()->setScale(time_scale_); library_->units()->capacitanceUnit()->setScale(cap_scale_); @@ -566,6 +567,13 @@ LibertyReader::beginLibrary(LibertyGroup *group) libError(group, "library does not have a name.\n"); } +// Energy scale is derived. +void +LibertyReader::setEnergyScale() +{ + energy_scale_ = volt_scale_ * volt_scale_ * cap_scale_; +} + void LibertyReader::endLibrary(LibertyGroup *group) { @@ -666,6 +674,7 @@ LibertyReader::visitVoltageUnit(LibertyAttr *attr) { if (library_) parseUnits(attr, "V", volt_scale_, library_->units()->voltageUnit()); + setEnergyScale(); } void @@ -771,6 +780,7 @@ LibertyReader::visitCapacitiveLoadUnit(LibertyAttr *attr) else libWarn(attr, "capacitive_load_unit missing values suffix.\n"); library_->units()->capacitanceUnit()->setScale(cap_scale_); + setEnergyScale(); } } diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 9a42a1a0..bc4cc673 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -425,6 +425,7 @@ public: virtual void visitAttr9(LibertyAttr *) {} protected: + void setEnergyScale(); void defineVisitors(); virtual void begin(LibertyGroup *group); virtual void end(LibertyGroup *group); diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc index 8b08b8b8..d0074196 100644 --- a/parasitics/ConcreteParasitics.cc +++ b/parasitics/ConcreteParasitics.cc @@ -864,7 +864,7 @@ bool ConcreteParasitics::haveParasitics() { return !drvr_parasitic_map_.empty() - || parasitic_network_map_.empty(); + || !parasitic_network_map_.empty(); } void @@ -887,9 +887,11 @@ ConcreteParasitics::deleteParasitics() int ap_tr_count = ap_count * TransRiseFall::index_count; for (auto drvr_parasitics : drvr_parasitic_map_) { ConcreteParasitic **parasitics = drvr_parasitics.second; - for (int i = 0; i < ap_tr_count; i++) - delete parasitics[i]; - delete [] parasitics; + if (parasitics) { + for (int i = 0; i < ap_tr_count; i++) + delete parasitics[i]; + delete [] parasitics; + } } drvr_parasitic_map_.clear(); @@ -1035,7 +1037,7 @@ ConcreteParasitics::findPiElmore(const Pin *drvr_pin, const TransRiseFall *tr, const ParasiticAnalysisPt *ap) const { - if (ap) { + if (!drvr_parasitic_map_.empty()) { int ap_tr_index = parasiticAnalysisPtIndex(ap, tr); UniqueLock lock(lock_); ConcreteParasitic **parasitics = drvr_parasitic_map_.findKey(drvr_pin); @@ -1153,7 +1155,7 @@ ConcreteParasitics::findPiPoleResidue(const Pin *drvr_pin, const TransRiseFall *tr, const ParasiticAnalysisPt *ap) const { - if (ap) { + if (!drvr_parasitic_map_.empty()) { int ap_tr_index = parasiticAnalysisPtIndex(ap, tr); UniqueLock lock(lock_); ConcreteParasitic **parasitics = drvr_parasitic_map_.findKey(drvr_pin); @@ -1269,7 +1271,7 @@ Parasitic * ConcreteParasitics::findParasiticNetwork(const Net *net, const ParasiticAnalysisPt *ap) const { - if (ap) { + if (!parasitic_network_map_.empty()) { UniqueLock lock(lock_); if (!parasitic_network_map_.empty()) { ConcreteParasiticNetwork **parasitics=parasitic_network_map_.findKey(net); @@ -1284,7 +1286,7 @@ Parasitic * ConcreteParasitics::findParasiticNetwork(const Pin *pin, const ParasiticAnalysisPt *ap) const { - if (ap) { + if (!parasitic_network_map_.empty()) { UniqueLock lock(lock_); if (!parasitic_network_map_.empty()) { // Only call findParasiticNet if parasitics exist. @@ -1322,7 +1324,7 @@ void ConcreteParasitics::deleteParasiticNetwork(const Net *net, const ParasiticAnalysisPt *ap) { - if (ap) { + if (!parasitic_network_map_.empty()) { UniqueLock lock(lock_); ConcreteParasiticNetwork **parasitics = parasitic_network_map_.findKey(net); if (parasitics) { diff --git a/parasitics/ConcreteParasitics.hh b/parasitics/ConcreteParasitics.hh index ebbf1654..5c4d24c6 100644 --- a/parasitics/ConcreteParasitics.hh +++ b/parasitics/ConcreteParasitics.hh @@ -42,7 +42,7 @@ class ConcreteParasitics : public Parasitics, public EstimateParasitics public: ConcreteParasitics(StaState *sta); virtual ~ConcreteParasitics(); - bool haveParasitics(); + virtual bool haveParasitics(); virtual void clear(); virtual void save(); diff --git a/parasitics/NullParasitics.cc b/parasitics/NullParasitics.cc index 963bb9f5..ddc7226b 100644 --- a/parasitics/NullParasitics.cc +++ b/parasitics/NullParasitics.cc @@ -24,6 +24,12 @@ NullParasitics::NullParasitics(StaState *sta) : { } +bool +NullParasitics::haveParasitics() +{ + return false; +} + void NullParasitics::clear() { diff --git a/parasitics/NullParasitics.hh b/parasitics/NullParasitics.hh index 6897f715..c8fae1b2 100644 --- a/parasitics/NullParasitics.hh +++ b/parasitics/NullParasitics.hh @@ -27,6 +27,7 @@ class NullParasitics : public Parasitics { public: NullParasitics(StaState *sta); + virtual bool haveParasitics(); virtual void clear(); virtual void save(); virtual void deleteParasitics(); diff --git a/parasitics/Parasitics.hh b/parasitics/Parasitics.hh index dcb205f2..2bfbaa42 100644 --- a/parasitics/Parasitics.hh +++ b/parasitics/Parasitics.hh @@ -46,6 +46,7 @@ class Parasitics : public StaState { public: virtual ~Parasitics() {} + virtual bool haveParasitics() = 0; // Clear all state. virtual void clear() = 0; diff --git a/search/Power.cc b/search/Power.cc index cb4e0333..28bf8504 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -139,10 +139,9 @@ Power::power(const Instance *inst, float activity1; bool is_clk; activity(to_pin, activity1, is_clk); - if (to_port->direction()->isAnyOutput()) { + if (to_port->direction()->isAnyOutput()) findSwitchingPower(cell, to_port, activity1, load_cap, dcalc_ap, result); - } findInternalPower(inst, cell, to_port, activity1, load_cap, dcalc_ap, result); } @@ -185,8 +184,9 @@ Power::findInternalPower(const Instance *inst, while (tr_iter.hasNext()) { TransRiseFall *to_tr = tr_iter.next(); // Should use unateness to find from_tr. + TransRiseFall *from_tr = to_tr; float slew = delayAsFloat(sta_->vertexSlew(from_vertex, - to_tr, dcalc_ap)); + from_tr, dcalc_ap)); float energy; if (from_port) energy = pwr->power(to_tr, pvt, slew, load_cap); @@ -199,7 +199,7 @@ Power::findInternalPower(const Instance *inst, to_tr->shortName(), to_port->name(), pwr->when() ? pwr->when()->asString() : "", - related_pg_pin ? related_pg_pin : ""); + related_pg_pin ? related_pg_pin : "(no pg_pin)"); debugPrint4(debug_, "power", 2, " slew = %s activity = %.2f/ns energy = %.5g pwr = %.5g\n", units_->timeUnit()->asString(slew), activity * 1e-9, @@ -269,7 +269,7 @@ Power::findLeakagePower(const Instance *, cell->leakagePower(leak, exists); if (exists) { // Prefer cell_leakage_power until propagated activities exist. - debugPrint2(debug_, "power", 2, "leakage %s cell %.3e\n", + debugPrint2(debug_, "power", 2, "leakage cell %s %.3e\n", cell->name(), leak); leakage = leak; @@ -292,7 +292,13 @@ Power::findSwitchingPower(LibertyCell *cell, PowerResult &result) { float volt = voltage(cell, to_port, dcalc_ap); - float switching = load_cap * volt * volt * activity / 2.0; + float switching = .5 * load_cap * volt * volt * activity; + debugPrint5(debug_, "power", 2, "switching %s/%s activity = %.2e volt = %.2f %.3e\n", + cell->name(), + to_port->name(), + activity, + volt, + switching); result.setSwitching(switching); } diff --git a/tcl/Sdc.tcl b/tcl/Sdc.tcl index 2279f801..662516a1 100644 --- a/tcl/Sdc.tcl +++ b/tcl/Sdc.tcl @@ -193,57 +193,60 @@ define_cmd_args "set_units" \ {[-capacitance cap_unit] [-resistance res_unit] [-time time_unit]\ [-voltage voltage_unit] [-current current_unit] [-power power_unit]} +# Note that this does NOT actually set the units. +# It merely checks that the library units are the same as the +# units in the set_units command. proc set_units { args } { parse_key_args "set_cmd_units" args \ - keys {-capacitance -resistance -time -voltage -current -power \ - -digits -suffix} flags {} + keys {-capacitance -resistance -time -voltage -current -power} flags {} if { [llength $args] != 0 } { cmd_usage_error "set_units" } - set_unit_values "capacitance" -capacitance "f" keys - set_unit_values "time" -time "s" keys - set_unit_values "voltage" -voltage "v" keys - set_unit_values "current" -current "A" keys - set_unit_values "resistance" -resistance "ohm" keys + check_unit "capacitance" -capacitance "f" keys + check_unit "time" -time "s" keys + check_unit "voltage" -voltage "v" keys + check_unit "current" -current "A" keys + check_unit "resistance" -resistance "ohm" keys } -proc set_unit_values { unit key unit_name key_var } { +proc check_unit { unit key unit_name key_var } { upvar 1 $key_var keys if { [info exists keys($key)] } { set value $keys($key) if { [string equal -nocase $value $unit_name] } { - set_cmd_unit_scale $unit 1.0 + check_unit_scale $unit 1.0 } else { set prefix [string index $value 0] set suffix [string range $value 1 end] if { [string equal -nocase $suffix $unit_name] } { if { [string equal $prefix "M"] } { - set_cmd_unit_scale $unit 1E+6 + check_unit_scale $unit 1E+6 } elseif { [string equal $prefix "k"] } { - set_cmd_unit_scale $unit 1E+3 + check_unit_scale $unit 1E+3 } elseif { [string equal $prefix "m"] } { - set_cmd_unit_scale $unit 1E-3 + check_unit_scale $unit 1E-3 } elseif { [string equal $prefix "u"] } { - set_cmd_unit_scale $unit 1E-6 + check_unit_scale $unit 1E-6 } elseif { [string equal $prefix "n"] } { - set_cmd_unit_scale $unit 1E-9 + check_unit_scale $unit 1E-9 } elseif { [string equal $prefix "p"] } { - set_cmd_unit_scale $unit 1E-12 + check_unit_scale $unit 1E-12 } elseif { [string equal $prefix "f"] } { - set_cmd_unit_scale $unit 1E-15 + check_unit_scale $unit 1E-15 } else { sta_error "unknown $unit prefix '$prefix'." } } else { - sta_error "unknown $unit unit '$suffix'." + sta_error "unknown unit $unit '$suffix'." } } - if [info exists keys(-digits)] { - set_cmd_unit_digits $unit $keys(-digits) - } - if [info exists keys(-suffix)] { - set_cmd_unit_suffix $unit $keys(-suffix) - } + } +} + +proc check_unit_scale { unit scale } { + set unit_scale [unit_scale $unit] + if { ![fuzzy_equal $scale $unit_scale] } { + sta_warn "$unit scale [format %.0e $scale] does not match library scale [format %.0e $unit_scale]." } } diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 3a1d099f..eec7996f 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -42,6 +42,7 @@ #include "StringUtil.hh" #include "PatternMatch.hh" #include "MinMax.hh" +#include "Fuzzy.hh" #include "PortDirection.hh" #include "FuncExpr.hh" #include "Units.hh" @@ -3840,43 +3841,43 @@ pin_is_genclk_src(const Pin *pin) // format_unit functions print with fixed digits and suffix. // Pass value arg as string to support NaNs. const char * -format_time(const char *value_str, +format_time(const char *value, int digits) { - float value = strtof(value_str, nullptr); - return Sta::sta()->units()->timeUnit()->asString(value, digits); + float value1 = strtof(value, nullptr); + return Sta::sta()->units()->timeUnit()->asString(value1, digits); } const char * -format_capacitance(const char *value_str, +format_capacitance(const char *value, int digits) { - float value = strtof(value_str, nullptr); - return Sta::sta()->units()->capacitanceUnit()->asString(value, digits); + float value1 = strtof(value, nullptr); + return Sta::sta()->units()->capacitanceUnit()->asString(value1, digits); } const char * -format_resistance(const char *value_str, +format_resistance(const char *value, int digits) { - float value = strtof(value_str, nullptr); - return Sta::sta()->units()->resistanceUnit()->asString(value, digits); + float value1 = strtof(value, nullptr); + return Sta::sta()->units()->resistanceUnit()->asString(value1, digits); } const char * -format_voltage(const char *value_str, +format_voltage(const char *value, int digits) { - float value = strtof(value_str, nullptr); - return Sta::sta()->units()->voltageUnit()->asString(value, digits); + float value1 = strtof(value, nullptr); + return Sta::sta()->units()->voltageUnit()->asString(value1, digits); } const char * -format_power(const char *value_str, +format_power(const char *value, int digits) { - float value = strtof(value_str, nullptr); - return Sta::sta()->units()->powerUnit()->asString(value, digits); + float value1 = strtof(value, nullptr); + return Sta::sta()->units()->powerUnit()->asString(value1, digits); } // Unit converstion from sta unit to user interface and visa versa. @@ -4723,32 +4724,21 @@ liberty_supply_exists(const char *supply_name) return lib && lib->supplyExists(supply_name); } -void -set_cmd_unit_scale(const char *unit_name, - float scale) +float +unit_scale(const char *unit_name) { Unit *unit = Sta::sta()->units()->find(unit_name); if (unit) - unit->setScale(scale); + return unit->scale(); + else + return 1.0F; } -void -set_cmd_unit_digits(const char *unit_name, - int digits) +bool +fuzzy_equal(float value1, + float value2) { - Unit *unit = Sta::sta()->units()->find(unit_name); - if (unit) - unit->setDigits(digits); -} - -void -set_cmd_unit_suffix(const char *unit_name, - const char *suffix) -{ - Unit *unit = Sta::sta()->units()->find(unit_name); - if (unit) { - unit->setSuffix(suffix); - } + return fuzzyEqual(value1, value2); } char