From 6ebd162d42387b21dfdd727a4af475f9bf00be5b Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 9 Apr 2025 16:35:15 -0700 Subject: [PATCH] factor variables out of sdc Signed-off-by: James Cherry --- CMakeLists.txt | 1 + dcalc/ArnoldiDelayCalc.cc | 3 + dcalc/DelayCalcBase.cc | 4 +- dcalc/DmpCeff.cc | 11 +- dcalc/GraphDelayCalc.cc | 18 ++- dcalc/LumpedCapDelayCalc.cc | 4 +- graph/DelayNormal1.cc | 5 +- include/sta/GraphDelayCalc.hh | 2 +- include/sta/Sdc.hh | 65 +--------- include/sta/SdcClass.hh | 2 - include/sta/Search.hh | 4 +- include/sta/Sta.hh | 122 ++++++++++--------- include/sta/StaState.hh | 12 +- include/sta/Variables.hh | 98 +++++++++++++++ power/Power.cc | 2 +- sdc/Sdc.cc | 222 ++-------------------------------- sdc/Variables.cc | 131 ++++++++++++++++++++ sdc/WriteSdc.cc | 5 +- search/Crpr.cc | 7 +- search/Genclks.cc | 16 +-- search/Levelize.cc | 8 +- search/PathGroup.cc | 3 +- search/ReportPath.cc | 5 +- search/Search.cc | 34 +++--- search/SearchPred.cc | 11 +- search/Sta.cc | 119 +++++++++--------- search/StaState.cc | 22 +++- search/VisitPathEnds.cc | 5 +- 28 files changed, 489 insertions(+), 452 deletions(-) create mode 100644 include/sta/Variables.hh create mode 100644 sdc/Variables.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a06e180..8f28b74e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,7 @@ set(STA_SOURCE sdc/Sdc.cc sdc/SdcGraph.cc sdc/SdcCmdComment.cc + sdc/Variables.cc sdc/WriteSdc.cc sdf/ReportAnnotation.cc diff --git a/dcalc/ArnoldiDelayCalc.cc b/dcalc/ArnoldiDelayCalc.cc index 4fcf5b4c..826ce867 100644 --- a/dcalc/ArnoldiDelayCalc.cc +++ b/dcalc/ArnoldiDelayCalc.cc @@ -48,6 +48,7 @@ #include "ArcDelayCalc.hh" #include "LumpedCapDelayCalc.hh" #include "GraphDelayCalc.hh" +#include "Variables.hh" #include "Arnoldi.hh" #include "ArnoldiReduce.hh" @@ -234,6 +235,7 @@ private: ArnoldiReduce *reduce_; delay_work *delay_work_; vector unsaved_parasitics_; + bool pocv_enabled_; }; ArcDelayCalc * @@ -391,6 +393,7 @@ ArnoldiDelayCalc::gateDelay(const Pin *drvr_pin, ConcreteParasitic *cparasitic = reinterpret_cast(const_cast(parasitic)); rcmodel_ = dynamic_cast(cparasitic); + pocv_enabled_ = variables_->pocvEnabled(); GateTableModel *table_model = arc->gateTableModel(dcalc_ap); if (table_model && rcmodel_) { const Pvt *pvt = pinPvt(drvr_pin, dcalc_ap); diff --git a/dcalc/DelayCalcBase.cc b/dcalc/DelayCalcBase.cc index b4484664..0f4b5c6b 100644 --- a/dcalc/DelayCalcBase.cc +++ b/dcalc/DelayCalcBase.cc @@ -35,6 +35,7 @@ #include "Corner.hh" #include "DcalcAnalysisPt.hh" #include "GraphDelayCalc.hh" +#include "Variables.hh" namespace sta { @@ -167,7 +168,8 @@ DelayCalcBase::checkDelay(const Pin *check_pin, float from_slew1 = delayAsFloat(from_slew); float to_slew1 = delayAsFloat(to_slew); return model->checkDelay(pinPvt(check_pin, dcalc_ap), from_slew1, to_slew1, - related_out_cap, pocv_enabled_); + related_out_cap, + variables_->pocvEnabled()); } else return delay_zero; diff --git a/dcalc/DmpCeff.cc b/dcalc/DmpCeff.cc index a47348d7..d278b7a4 100644 --- a/dcalc/DmpCeff.cc +++ b/dcalc/DmpCeff.cc @@ -47,6 +47,7 @@ #include "DcalcAnalysisPt.hh" #include "ArcDelayCalc.hh" #include "FindRoot.hh" +#include "Variables.hh" namespace sta { @@ -371,7 +372,8 @@ DmpAlg::gateCapDelaySlew(double ceff, { ArcDelay model_delay; Slew model_slew; - gate_model_->gateDelay(pvt_, in_slew_, ceff, pocv_enabled_, + gate_model_->gateDelay(pvt_, in_slew_, ceff, + variables_->pocvEnabled(), model_delay, model_slew); delay = delayAsFloat(model_delay); slew = delayAsFloat(model_slew); @@ -1562,7 +1564,7 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library, double rd = 0.0; if (gate_model) { rd = gateModelRd(drvr_cell, gate_model, rf, in_slew, c2, c1, - pvt, pocv_enabled_); + pvt, variables_->pocvEnabled()); // Zero Rd means the table is constant and thus independent of load cap. if (rd < 1e-2 // Rpi is small compared to Rd, which makes the load capacitive. @@ -1630,9 +1632,10 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, const Unit *time_unit = units->timeUnit(); float in_slew1 = delayAsFloat(in_slew); result += model->reportGateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, c_eff, - pocv_enabled_, digits); + variables_->pocvEnabled(), digits); result += "Driver waveform slew = "; - result += time_unit->asString(dcalc_result.drvrSlew(), digits); + float drvr_slew = delayAsFloat(dcalc_result.drvrSlew()); + result += time_unit->asString(drvr_slew, digits); result += '\n'; } return result; diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index da42e090..bd334f3a 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -45,6 +45,7 @@ #include "DcalcAnalysisPt.hh" #include "NetCaps.hh" #include "ClkNetwork.hh" +#include "Variables.hh" namespace sta { @@ -365,7 +366,7 @@ GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex, else { // Top level bidirect driver uses load slew unless // bidirect instance paths are disabled. - if (sdc_->bidirectDrvrSlewFromLoad(drvr_pin)) { + if (bidirectDrvrSlewFromLoad(drvr_pin)) { Vertex *load_vertex = graph_->pinLoadVertex(drvr_pin); slew = graph_->slew(load_vertex, rf, ap_index); } @@ -393,6 +394,17 @@ GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex, arc_delay_calc->finishDrvrPin(); } +// Delay calculation propagates slews from a bidirect driver +// to the bidirect port and back through the bidirect driver when +// sta_bidirect_inst_paths_enabled_ is true. +bool +GraphDelayCalc::bidirectDrvrSlewFromLoad(const Pin *pin) const +{ + return variables_->bidirectInstPathsEnabled() + && network_->direction(pin)->isBidirect() + && network_->isTopLevelPort(pin); +} + void GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex, const Pin *drvr_pin, @@ -405,7 +417,7 @@ GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex, Slew slew(default_slew); // Top level bidirect driver uses load slew unless // bidirect instance paths are disabled. - if (sdc_->bidirectDrvrSlewFromLoad(drvr_pin)) { + if (bidirectDrvrSlewFromLoad(drvr_pin)) { Vertex *load_vertex = graph_->pinLoadVertex(drvr_pin); slew = graph_->slew(load_vertex, rf, ap_index); } @@ -1185,7 +1197,7 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, if (load_changed && observer_) observer_->delayChangedTo(load_vertex); // Enqueue bidirect driver from load vertex. - if (sdc_->bidirectDrvrSlewFromLoad(load_pin)) + if (bidirectDrvrSlewFromLoad(load_pin)) iter_->enqueue(graph_->pinDrvrVertex(load_pin)); changed |= load_changed; } diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index 66bf9e7f..7bd01419 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -37,6 +37,7 @@ #include "Parasitics.hh" #include "DcalcAnalysisPt.hh" #include "GraphDelayCalc.hh" +#include "Variables.hh" namespace sta { @@ -144,7 +145,8 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin, // NaNs cause seg faults during table lookup. if (isnan(load_cap) || isnan(delayAsFloat(in_slew))) report_->error(1350, "gate delay input variable is NaN"); - model->gateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, load_cap, pocv_enabled_, + model->gateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, load_cap, + variables_->pocvEnabled(), gate_delay, drvr_slew); return makeResult(drvr_library, rf, gate_delay, drvr_slew, load_pin_index_map); } diff --git a/graph/DelayNormal1.cc b/graph/DelayNormal1.cc index 37aa3d13..d50db11f 100644 --- a/graph/DelayNormal1.cc +++ b/graph/DelayNormal1.cc @@ -32,6 +32,7 @@ #include "Fuzzy.hh" #include "Units.hh" #include "StaState.hh" +#include "Variables.hh" // SSTA compilation. #if (SSTA == 1) @@ -237,7 +238,7 @@ delayAsFloat(const Delay &delay, const EarlyLate *early_late, const StaState *sta) { - if (sta->pocvEnabled()) { + if (sta->variables()->pocvEnabled()) { if (early_late == EarlyLate::early()) return delay.mean() - delay.sigma() * sta->sigmaFactor(); else if (early_late == EarlyLate::late()) @@ -268,7 +269,7 @@ delayAsString(const Delay &delay, int digits) { const Unit *unit = sta->units()->timeUnit(); - if (sta->pocvEnabled()) { + if (sta->variables()->pocvEnabled()) { float sigma = delay.sigma(); return stringPrintTmp("%s[%s]", unit->asString(delay.mean(), digits), diff --git a/include/sta/GraphDelayCalc.hh b/include/sta/GraphDelayCalc.hh index 96857d6c..2d17a061 100644 --- a/include/sta/GraphDelayCalc.hh +++ b/include/sta/GraphDelayCalc.hh @@ -132,6 +132,7 @@ public: const RiseFall *from_rf, const TimingRole *role, const DcalcAnalysisPt *dcalc_ap); + bool bidirectDrvrSlewFromLoad(const Pin *pin) const; protected: void seedInvalidDelays(); @@ -246,7 +247,6 @@ protected: Slew checkEdgeClkSlew(const Vertex *from_vertex, const RiseFall *from_rf, const DcalcAnalysisPt *dcalc_ap); - bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const; float loadCap(const Pin *drvr_pin, const RiseFall *rf, const DcalcAnalysisPt *dcalc_ap, diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index 80c4e823..7b6297b9 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -733,6 +733,7 @@ public: // combinational loops when dynamic loop breaking is enabled. void makeLoopExceptions(); void makeLoopExceptions(GraphLoop *loop); + void deleteLoopExceptions(); void makeMulticyclePath(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, @@ -793,54 +794,6 @@ public: const WireloadSelection *wireloadSelection(const MinMax *min_max); void setWireloadSelection(WireloadSelection *selection, const MinMaxAll *min_max); - // Common reconvergent clock pessimism. - // TCL variable sta_crpr_enabled. - bool crprEnabled() const; - void setCrprEnabled(bool enabled); - // TCL variable sta_crpr_mode. - CrprMode crprMode() const; - void setCrprMode(CrprMode mode); - // True when analysis type is on chip variation and crpr is enabled. - bool crprActive() const; - // TCL variable sta_propagate_gated_clock_enable. - // Propagate gated clock enable arrivals. - bool propagateGatedClockEnable() const; - void setPropagateGatedClockEnable(bool enable); - // TCL variable sta_preset_clear_arcs_enabled. - // Enable search through preset/clear arcs. - bool presetClrArcsEnabled() const; - void setPresetClrArcsEnabled(bool enable); - // TCL variable sta_cond_default_arcs_enabled. - // Enable/disable default arcs when conditional arcs exist. - bool condDefaultArcsEnabled() const; - void setCondDefaultArcsEnabled(bool enabled); - bool isDisabledCondDefault(Edge *edge) const; - // TCL variable sta_internal_bidirect_instance_paths_enabled. - // Enable/disable timing from bidirect pins back into the instance. - bool bidirectInstPathsEnabled() const; - void setBidirectInstPathsEnabled(bool enabled); - // TCL variable sta_bidirect_net_paths_enabled. - // Enable/disable timing from bidirect driver pins to their own loads. - bool bidirectNetPathsEnabled() const; - void setBidirectNetPathsEnabled(bool enabled); - // TCL variable sta_recovery_removal_checks_enabled. - bool recoveryRemovalChecksEnabled() const; - void setRecoveryRemovalChecksEnabled(bool enabled); - // TCL variable sta_gated_clock_checks_enabled. - bool gatedClkChecksEnabled() const; - void setGatedClkChecksEnabled(bool enabled); - // TCL variable sta_dynamic_loop_breaking. - bool dynamicLoopBreaking() const; - void setDynamicLoopBreaking(bool enable); - // TCL variable sta_propagate_all_clocks. - bool propagateAllClocks() const; - void setPropagateAllClocks(bool prop); - // TCL var sta_clock_through_tristate_enabled. - bool clkThruTristateEnabled() const; - void setClkThruTristateEnabled(bool enable); - // TCL variable sta_input_port_default_clock. - bool useDefaultArrivalClock(); - void setUseDefaultArrivalClock(bool enable); // STA interface. InputDelaySet *refPinInputDelays(const Pin *ref_pin) const; @@ -1071,7 +1024,6 @@ public: const Pin *drvr, const Pin *load); void ensureClkHpinDisables(); - bool bidirectDrvrSlewFromLoad(const Pin *pin) const; protected: void portMembers(const Port *port, @@ -1214,7 +1166,6 @@ protected: const Pin *loop_prev_pin); void makeLoopExceptionThru(const Pin *pin, ExceptionThruSeq *thrus); - void deleteLoopExceptions(); void deleteConstraints(); InputDelay *findInputDelay(const Pin *pin, const ClockEdge *clk_edge); @@ -1317,7 +1268,6 @@ protected: int clk_index_; // Default clock used for unclocked input arrivals. Clock *default_arrival_clk_; - bool use_default_arrival_clock_; ClockNameMap clock_name_map_; ClockPinMap clock_pin_map_; // Clocks on hierarchical pins are indexed by the load pins. @@ -1430,19 +1380,6 @@ protected: Wireload *wireload_[MinMax::index_count]; WireloadMode wireload_mode_; WireloadSelection *wireload_selection_[MinMax::index_count]; - bool crpr_enabled_; - CrprMode crpr_mode_; - bool pocv_enabled_; - bool propagate_gated_clock_enable_; - bool preset_clr_arcs_enabled_; - bool cond_default_arcs_enabled_; - bool bidirect_net_paths_enabled_; - bool bidirect_inst_paths_enabled_; - bool recovery_removal_checks_enabled_; - bool gated_clk_checks_enabled_; - bool clk_thru_tristate_enabled_; - bool dynamic_loop_breaking_; - bool propagate_all_clks_; // Annotations on graph objects that are stored in constraints // rather on the graph itself. diff --git a/include/sta/SdcClass.hh b/include/sta/SdcClass.hh index f6d7c3f7..a6a5a49a 100644 --- a/include/sta/SdcClass.hh +++ b/include/sta/SdcClass.hh @@ -122,8 +122,6 @@ public: class ExceptionPath; typedef Set ExceptionStateSet; -enum class CrprMode { same_pin, same_transition }; - // Constraint applies to clock or data paths. enum class PathClkOrData { clk, data }; diff --git a/include/sta/Search.hh b/include/sta/Search.hh index 8129ae4f..1628b70a 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -861,11 +861,11 @@ protected: class DynLoopSrchPred { public: - explicit DynLoopSrchPred(TagGroupBldr *tag_bldr); + DynLoopSrchPred(TagGroupBldr *tag_bldr); protected: bool loopEnabled(Edge *edge, - const Sdc *sdc, + bool dynamic_loop_breaking_enabled, const Graph *graph, Search *search); bool hasPendingLoopPaths(Edge *edge, diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 61b0b66e..abd9b0b7 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -38,6 +38,7 @@ #include "PowerClass.hh" #include "ArcDelayCalc.hh" #include "CircuitSim.hh" +#include "Variables.hh" struct Tcl_Interp; @@ -436,8 +437,6 @@ public: void removeDisable(TimingArcSet *arc_set); // Edge is disabled by constant. bool isDisabledConstant(Edge *edge); - // Edge is default cond disabled by timing_disable_cond_default_arcs var. - bool isDisabledCondDefault(Edge *edge); // Return a set of constant pins that disabled edge. // Caller owns the returned set. PinSet disabledConstantPins(Edge *edge); @@ -793,61 +792,7 @@ public: bool no_version); // Remove all delay and slew annotations. void removeDelaySlewAnnotations(); - // TCL variable sta_crpr_enabled. - // Common Reconvergent Clock Removal (CRPR). - // Timing check source/target common clock path overlap for search - // with analysis mode on_chip_variation. - bool crprEnabled() const; - void setCrprEnabled(bool enabled); - // TCL variable sta_crpr_mode. - CrprMode crprMode() const; - void setCrprMode(CrprMode mode); - // TCL variable sta_pocv_enabled. - // Parametric on chip variation (statisical sta). - bool pocvEnabled() const; - void setPocvEnabled(bool enabled); - // Number of std deviations from mean to use for normal distributions. - void setSigmaFactor(float factor); - // TCL variable sta_propagate_gated_clock_enable. - // Propagate gated clock enable arrivals. - bool propagateGatedClockEnable() const; - void setPropagateGatedClockEnable(bool enable); - // TCL variable sta_preset_clear_arcs_enabled. - // Enable search through preset/clear arcs. - bool presetClrArcsEnabled() const; - void setPresetClrArcsEnabled(bool enable); - // TCL variable sta_cond_default_arcs_enabled. - // Enable/disable default arcs when conditional arcs exist. - bool condDefaultArcsEnabled() const; - void setCondDefaultArcsEnabled(bool enabled); - // TCL variable sta_internal_bidirect_instance_paths_enabled. - // Enable/disable timing from bidirect pins back into the instance. - bool bidirectInstPathsEnabled() const; - void setBidirectInstPathsEnabled(bool enabled); - // TCL variable sta_bidirect_net_paths_enabled. - // Enable/disable timing from bidirect driver pins to their own loads. - bool bidirectNetPathsEnabled() const; - void setBidirectNetPathsEnabled(bool enabled); - // TCL variable sta_recovery_removal_checks_enabled. - bool recoveryRemovalChecksEnabled() const; - void setRecoveryRemovalChecksEnabled(bool enabled); - // TCL variable sta_gated_clock_checks_enabled. - bool gatedClkChecksEnabled() const; - void setGatedClkChecksEnabled(bool enabled); - // TCL variable sta_dynamic_loop_breaking. - bool dynamicLoopBreaking() const; - void setDynamicLoopBreaking(bool enable); - // TCL variable sta_propagate_all_clocks. - // Clocks defined after sta_propagate_all_clocks is true - // are propagated (existing clocks are not effected). - bool propagateAllClocks() const; - void setPropagateAllClocks(bool prop); - // TCL var sta_clock_through_tristate_enabled. - bool clkThruTristateEnabled() const; - void setClkThruTristateEnabled(bool enable); - // TCL variable sta_input_port_default_clock. - bool useDefaultArrivalClock() const; - void setUseDefaultArrivalClock(bool enable); + virtual CheckErrorSeq &checkTiming(bool no_input_delay, bool no_output_delay, bool reg_multiple_clks, @@ -1178,7 +1123,9 @@ public: bool includes_pin_caps, const ParasiticAnalysisPt *ap); + //////////////////////////////////////////////////////////////// // TCL network edit function support. + virtual Instance *makeInstance(const char *name, LibertyCell *cell, Instance *parent); @@ -1322,10 +1269,71 @@ public: const char *gnd_name, CircuitSim ckt_sim); + //////////////////////////////////////////////////////////////// + // TCL Variables + + // TCL variable sta_crpr_enabled. + // Common Reconvergent Clock Removal (CRPR). + // Timing check source/target common clock path overlap for search + // with analysis mode on_chip_variation. + bool crprEnabled() const; + void setCrprEnabled(bool enabled); + // TCL variable sta_crpr_mode. + CrprMode crprMode() const; + void setCrprMode(CrprMode mode); + // TCL variable sta_pocv_enabled. + // Parametric on chip variation (statisical sta). + bool pocvEnabled() const; + void setPocvEnabled(bool enabled); + // Number of std deviations from mean to use for normal distributions. + void setSigmaFactor(float factor); + // TCL variable sta_propagate_gated_clock_enable. + // Propagate gated clock enable arrivals. + bool propagateGatedClockEnable() const; + void setPropagateGatedClockEnable(bool enable); + // TCL variable sta_preset_clear_arcs_enabled. + // Enable search through preset/clear arcs. + bool presetClrArcsEnabled() const; + void setPresetClrArcsEnabled(bool enable); + // TCL variable sta_cond_default_arcs_enabled. + // Enable/disable default arcs when conditional arcs exist. + bool condDefaultArcsEnabled() const; + void setCondDefaultArcsEnabled(bool enabled); + // TCL variable sta_internal_bidirect_instance_paths_enabled. + // Enable/disable timing from bidirect pins back into the instance. + bool bidirectInstPathsEnabled() const; + void setBidirectInstPathsEnabled(bool enabled); + // TCL variable sta_bidirect_net_paths_enabled. + // Enable/disable timing from bidirect driver pins to their own loads. + bool bidirectNetPathsEnabled() const; + void setBidirectNetPathsEnabled(bool enabled); + // TCL variable sta_recovery_removal_checks_enabled. + bool recoveryRemovalChecksEnabled() const; + void setRecoveryRemovalChecksEnabled(bool enabled); + // TCL variable sta_gated_clock_checks_enabled. + bool gatedClkChecksEnabled() const; + void setGatedClkChecksEnabled(bool enabled); + // TCL variable sta_dynamic_loop_breaking. + bool dynamicLoopBreaking() const; + void setDynamicLoopBreaking(bool enable); + // TCL variable sta_propagate_all_clocks. + // Clocks defined after sta_propagate_all_clocks is true + // are propagated (existing clocks are not effected). + bool propagateAllClocks() const; + void setPropagateAllClocks(bool prop); + // TCL var sta_clock_through_tristate_enabled. + bool clkThruTristateEnabled() const; + void setClkThruTristateEnabled(bool enable); + // TCL variable sta_input_port_default_clock. + bool useDefaultArrivalClock() const; + void setUseDefaultArrivalClock(bool enable); + //////////////////////////////////////////////////////////////// + protected: // Default constructors that are called by makeComponents in the Sta // constructor. These can be redefined by a derived class to // specialize the sta components. + virtual void makeVariables(); virtual void makeReport(); virtual void makeDebug(); virtual void makeUnits(); diff --git a/include/sta/StaState.hh b/include/sta/StaState.hh index 111bced3..6b94ba71 100644 --- a/include/sta/StaState.hh +++ b/include/sta/StaState.hh @@ -35,6 +35,7 @@ class NetworkReader; class Sdc; class Corners; class Graph; +class Edge; class Levelize; class Sim; class Search; @@ -44,6 +45,7 @@ class GraphDelayCalc; class Latches; class ClkNetwork; class DispatchQueue; +class Variables; // Most STA components use functionality in other components. // This class simplifies the process of copying pointers to the @@ -54,7 +56,7 @@ class StaState public: // Make an empty state. StaState(); - explicit StaState(const StaState *sta); + StaState(const StaState *sta); // Copy the state from sta. This is virtual so that a component // can notify sub-components. virtual void copyState(const StaState *sta); @@ -102,8 +104,12 @@ public: ClkNetwork *clkNetwork() { return clk_network_; } ClkNetwork *clkNetwork() const { return clk_network_; } unsigned threadCount() const { return thread_count_; } - bool pocvEnabled() const { return pocv_enabled_; } float sigmaFactor() const { return sigma_factor_; } + bool crprActive() const; + Variables *variables() { return variables_; } + const Variables *variables() const { return variables_; } + // Edge is default cond disabled by timing_disable_cond_default_arcs var. + bool isDisabledCondDefault(Edge *edge) const; protected: Report *report_; @@ -126,8 +132,8 @@ protected: ClkNetwork *clk_network_; int thread_count_; DispatchQueue *dispatch_queue_; - bool pocv_enabled_; float sigma_factor_; + Variables *variables_; }; } // namespace diff --git a/include/sta/Variables.hh b/include/sta/Variables.hh new file mode 100644 index 00000000..696347a1 --- /dev/null +++ b/include/sta/Variables.hh @@ -0,0 +1,98 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, 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 . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#pragma once + +namespace sta { + +enum class CrprMode { same_pin, same_transition }; + +// TCL Variables +class Variables +{ +public: + Variables(); + // TCL variable sta_propagate_gated_clock_enable. + bool crprEnabled() const { return crpr_enabled_; } + void setCrprEnabled(bool enabled); + CrprMode crprMode() const { return crpr_mode_; } + void setCrprMode(CrprMode mode); + // Propagate gated clock enable arrivals. + bool propagateGatedClockEnable() const { return propagate_gated_clock_enable_; } + void setPropagateGatedClockEnable(bool enable); + // TCL variable sta_preset_clear_arcs_enabled. + // Enable search through preset/clear arcs. + bool presetClrArcsEnabled() const { return preset_clr_arcs_enabled_; } + void setPresetClrArcsEnabled(bool enable); + // TCL variable sta_cond_default_arcs_enabled. + // Enable/disable default arcs when conditional arcs exist. + bool condDefaultArcsEnabled() const { return cond_default_arcs_enabled_; } + void setCondDefaultArcsEnabled(bool enabled); + // TCL variable sta_internal_bidirect_instance_paths_enabled. + // Enable/disable timing from bidirect pins back into the instance. + bool bidirectInstPathsEnabled() const { return bidirect_inst_paths_enabled_; } + void setBidirectInstPathsEnabled(bool enabled); + // TCL variable sta_bidirect_net_paths_enabled. + // Enable/disable timing from bidirect driver pins to their own loads. + bool bidirectNetPathsEnabled() const { return bidirect_net_paths_enabled_; } + void setBidirectNetPathsEnabled(bool enabled); + // TCL variable sta_recovery_removal_checks_enabled. + bool recoveryRemovalChecksEnabled() const { return recovery_removal_checks_enabled_; } + void setRecoveryRemovalChecksEnabled(bool enabled); + // TCL variable sta_gated_clock_checks_enabled. + bool gatedClkChecksEnabled() const { return gated_clk_checks_enabled_; } + void setGatedClkChecksEnabled(bool enabled); + // TCL variable sta_dynamic_loop_breaking. + bool dynamicLoopBreaking() const { return dynamic_loop_breaking_; } + void setDynamicLoopBreaking(bool enable); + // TCL variable sta_propagate_all_clocks. + bool propagateAllClocks() const { return propagate_all_clks_; } + void setPropagateAllClocks(bool prop); + // TCL var sta_clock_through_tristate_enabled. + bool clkThruTristateEnabled() const { return clk_thru_tristate_enabled_; } + void setClkThruTristateEnabled(bool enable); + // TCL variable sta_input_port_default_clock. + bool useDefaultArrivalClock() { return use_default_arrival_clock_; } + void setUseDefaultArrivalClock(bool enable); + bool pocvEnabled() const { return pocv_enabled_; } + void setPocvEnabled(bool enabled); + +private: + bool crpr_enabled_; + CrprMode crpr_mode_; + bool propagate_gated_clock_enable_; + bool preset_clr_arcs_enabled_; + bool cond_default_arcs_enabled_; + bool bidirect_net_paths_enabled_; + bool bidirect_inst_paths_enabled_; + bool recovery_removal_checks_enabled_; + bool gated_clk_checks_enabled_; + bool clk_thru_tristate_enabled_; + bool dynamic_loop_breaking_; + bool propagate_all_clks_; + bool use_default_arrival_clock_; + bool pocv_enabled_; +}; + +} // namespace diff --git a/power/Power.cc b/power/Power.cc index a0981adb..793e5c81 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -942,7 +942,7 @@ Power::getMinRfSlew(const Pin *pin) if (delayGreater(slew, mm_slew, min_max, this)) mm_slew = slew; } - return mm_slew; + return delayAsFloat(mm_slew); } return 0.0; } diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 2e46416f..aa02e319 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -30,6 +30,7 @@ #include "Debug.hh" #include "Mutex.hh" #include "Report.hh" +#include "Variables.hh" #include "PatternMatch.hh" #include "MinMax.hh" #include "TimingRole.hh" @@ -233,19 +234,6 @@ void Sdc::initVariables() { analysis_type_ = AnalysisType::ocv; - use_default_arrival_clock_ = false; - crpr_enabled_ = true; - crpr_mode_ = CrprMode::same_pin; - propagate_gated_clock_enable_ = true; - preset_clr_arcs_enabled_ = false; - cond_default_arcs_enabled_ = true; - bidirect_net_paths_enabled_ = false; - bidirect_inst_paths_enabled_ = false; - recovery_removal_checks_enabled_ = true; - gated_clk_checks_enabled_ = true; - clk_thru_tristate_enabled_ = false; - dynamic_loop_breaking_ = false; - propagate_all_clks_ = false; wireload_mode_ = WireloadMode::unknown; max_area_ = 0.0; path_delays_without_to_ = false; @@ -1000,7 +988,7 @@ Sdc::makeClock(const char *name, else { // Fresh clock definition. clk = new Clock(name, clk_index_++, network_); - clk->setIsPropagated(propagate_all_clks_); + clk->setIsPropagated(variables_->propagateAllClocks()); clocks_.push_back(clk); // Use the copied name in the map. clock_name_map_[clk->name()] = clk; @@ -1041,7 +1029,8 @@ Sdc::makeGeneratedClock(const char *name, clk->initGeneratedClk(pins, add_to_pins, src_pin, master_clk, divide_by, multiply_by, duty_cycle, invert, combinational, - edges, edge_shifts, propagate_all_clks_, + edges, edge_shifts, + variables_->propagateAllClocks(), comment, network_); makeClkPinMappings(clk); clearCycleAcctings(); @@ -1249,6 +1238,12 @@ Sdc::sortedClocks(ClockSeq &clks) sort(clks, ClkNameLess()); } +ClockEdge * +Sdc::defaultArrivalClockEdge() const +{ + return default_arrival_clk_->edge(RiseFall::rise()); +} + //////////////////////////////////////////////////////////////// class ClkHpinDisable @@ -5481,203 +5476,6 @@ Sdc::setWireloadSelection(WireloadSelection *selection, //////////////////////////////////////////////////////////////// -bool -Sdc::crprEnabled() const -{ - return crpr_enabled_; -} - -void -Sdc::setCrprEnabled(bool enabled) -{ - crpr_enabled_ = enabled; -} - -CrprMode -Sdc::crprMode() const -{ - return crpr_mode_; -} - -void -Sdc::setCrprMode(CrprMode mode) -{ - crpr_mode_ = mode; -} - -bool -Sdc::crprActive() const -{ - return analysis_type_ == AnalysisType::ocv - && crpr_enabled_; -} - -bool -Sdc::propagateGatedClockEnable() const -{ - return propagate_gated_clock_enable_; -} - -void -Sdc::setPropagateGatedClockEnable(bool enable) -{ - propagate_gated_clock_enable_ = enable; -} - -bool -Sdc::presetClrArcsEnabled() const -{ - return preset_clr_arcs_enabled_; -} - -void -Sdc::setPresetClrArcsEnabled(bool enable) -{ - preset_clr_arcs_enabled_ = enable; -} - -bool -Sdc::condDefaultArcsEnabled() const -{ - return cond_default_arcs_enabled_; -} - -void -Sdc::setCondDefaultArcsEnabled(bool enabled) -{ - cond_default_arcs_enabled_ = enabled; -} - -bool -Sdc::isDisabledCondDefault(Edge *edge) const -{ - return !cond_default_arcs_enabled_ - && edge->timingArcSet()->isCondDefault(); -} - -bool -Sdc::bidirectInstPathsEnabled() const -{ - return bidirect_inst_paths_enabled_; -} - -void -Sdc::setBidirectInstPathsEnabled(bool enabled) -{ - bidirect_inst_paths_enabled_ = enabled; -} - -// Delay calculation propagates slews from a bidirect driver -// to the bidirect port and back through the bidirect driver when -// sta_bidirect_inst_paths_enabled_ is true. -bool -Sdc::bidirectDrvrSlewFromLoad(const Pin *pin) const -{ - return bidirect_inst_paths_enabled_ - && network_->direction(pin)->isBidirect() - && network_->isTopLevelPort(pin); -} - -bool -Sdc::bidirectNetPathsEnabled() const -{ - return bidirect_inst_paths_enabled_; -} - -void -Sdc::setBidirectNetPathsEnabled(bool enabled) -{ - bidirect_inst_paths_enabled_ = enabled; -} - -bool -Sdc::recoveryRemovalChecksEnabled() const -{ - return recovery_removal_checks_enabled_; -} - -void -Sdc::setRecoveryRemovalChecksEnabled(bool enabled) -{ - recovery_removal_checks_enabled_ = enabled; -} - -bool -Sdc::gatedClkChecksEnabled() const -{ - return gated_clk_checks_enabled_; -} - -void -Sdc::setGatedClkChecksEnabled(bool enabled) -{ - gated_clk_checks_enabled_ = enabled; -} - -bool -Sdc::dynamicLoopBreaking() const -{ - return dynamic_loop_breaking_; -} - -void -Sdc::setDynamicLoopBreaking(bool enable) -{ - if (dynamic_loop_breaking_ != enable) { - if (levelize_->levelized()) { - if (enable) - makeLoopExceptions(); - else - deleteLoopExceptions(); - } - dynamic_loop_breaking_ = enable; - } -} - -bool -Sdc::propagateAllClocks() const -{ - return propagate_all_clks_; -} - -void -Sdc::setPropagateAllClocks(bool prop) -{ - propagate_all_clks_ = prop; -} - -bool -Sdc::clkThruTristateEnabled() const -{ - return clk_thru_tristate_enabled_; -} - -void -Sdc::setClkThruTristateEnabled(bool enable) -{ - clk_thru_tristate_enabled_ = enable; -} - -ClockEdge * -Sdc::defaultArrivalClockEdge() const -{ - return default_arrival_clk_->edge(RiseFall::rise()); -} - -bool -Sdc::useDefaultArrivalClock() -{ - return use_default_arrival_clock_; -} - -void -Sdc::setUseDefaultArrivalClock(bool enable) -{ - use_default_arrival_clock_ = enable; -} - -//////////////////////////////////////////////////////////////// - void Sdc::connectPinAfter(const Pin *pin) { diff --git a/sdc/Variables.cc b/sdc/Variables.cc new file mode 100644 index 00000000..1cb10bd0 --- /dev/null +++ b/sdc/Variables.cc @@ -0,0 +1,131 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2025, 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 . +// +// The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. +// +// Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// This notice may not be removed or altered from any source distribution. + +#include "Variables.hh" + +namespace sta { + +Variables::Variables() : + crpr_enabled_(true), + crpr_mode_(CrprMode::same_pin), + propagate_gated_clock_enable_(true), + preset_clr_arcs_enabled_(false), + cond_default_arcs_enabled_(true), + bidirect_net_paths_enabled_(false), + bidirect_inst_paths_enabled_(false), + recovery_removal_checks_enabled_(true), + gated_clk_checks_enabled_(true), + clk_thru_tristate_enabled_(false), + dynamic_loop_breaking_(false), + propagate_all_clks_(false), + use_default_arrival_clock_(false), + pocv_enabled_(false) +{ +} + +void +Variables::setCrprEnabled(bool enabled) +{ + crpr_enabled_ = enabled; +} + +void +Variables::setCrprMode(CrprMode mode) +{ + crpr_mode_ = mode; +} + +void +Variables::setPropagateGatedClockEnable(bool enable) +{ + propagate_gated_clock_enable_ = enable; +} + +void +Variables::setPresetClrArcsEnabled(bool enable) +{ + preset_clr_arcs_enabled_ = enable; +} + +void +Variables::setCondDefaultArcsEnabled(bool enabled) +{ + cond_default_arcs_enabled_ = enabled; +} + +void +Variables::setBidirectInstPathsEnabled(bool enabled) +{ + bidirect_inst_paths_enabled_ = enabled; +} + +void +Variables::setBidirectNetPathsEnabled(bool enabled) +{ + bidirect_net_paths_enabled_ = enabled; +} + +void +Variables::setRecoveryRemovalChecksEnabled(bool enabled) +{ + recovery_removal_checks_enabled_ = enabled; +} + +void +Variables::setGatedClkChecksEnabled(bool enabled) +{ + gated_clk_checks_enabled_ = enabled; +} + +void +Variables::setDynamicLoopBreaking(bool enable) +{ + dynamic_loop_breaking_ = enable; +} + +void +Variables::setPropagateAllClocks(bool prop) +{ + propagate_all_clks_ = prop; +} + +void +Variables::setClkThruTristateEnabled(bool enable) +{ + clk_thru_tristate_enabled_ = enable; +} + +void +Variables::setUseDefaultArrivalClock(bool enable) +{ + use_default_arrival_clock_ = enable; +} + +void +Variables::setPocvEnabled(bool enabled) +{ + pocv_enabled_ = enabled; +} + +} // namespace diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc index 93f55ba9..c84b257e 100644 --- a/sdc/WriteSdc.cc +++ b/sdc/WriteSdc.cc @@ -55,6 +55,7 @@ #include "Fuzzy.hh" #include "StaState.hh" #include "Corner.hh" +#include "Variables.hh" #include "WriteSdcPvt.hh" namespace sta { @@ -2324,13 +2325,13 @@ WriteSdc::writeFanoutLimits(const MinMax *min_max, void WriteSdc::writeVariables() const { - if (sdc_->propagateAllClocks()) { + if (variables_->propagateAllClocks()) { if (native_) gzprintf(stream_, "set sta_propagate_all_clocks 1\n"); else gzprintf(stream_, "set timing_all_clocks_propagated true\n"); } - if (sdc_->presetClrArcsEnabled()) { + if (variables_->presetClrArcsEnabled()) { if (native_) gzprintf(stream_, "set sta_preset_clear_arcs_enabled 1\n"); else diff --git a/search/Crpr.cc b/search/Crpr.cc index ea819248..3e03bd6b 100644 --- a/search/Crpr.cc +++ b/search/Crpr.cc @@ -41,6 +41,7 @@ #include "PathEnd.hh" #include "Search.hh" #include "Genclks.hh" +#include "Variables.hh" namespace sta { @@ -109,7 +110,7 @@ CheckCrpr::checkCrpr(const Path *src_path, crpr_pin = nullptr; if (sdc_->crprActive() && src_path && tgt_clk_path) { - bool same_pin = (sdc_->crprMode() == CrprMode::same_pin); + bool same_pin = (variables_->crprMode() == CrprMode::same_pin); checkCrpr1(src_path, tgt_clk_path, same_pin, crpr, crpr_pin); } } @@ -267,7 +268,7 @@ Crpr CheckCrpr::findCrpr1(const Path *src_clk_path, const Path *tgt_clk_path) { - if (pocv_enabled_) { + if (variables_->pocvEnabled()) { // Remove variation on the common path. // Note that the crpr sigma is negative to offset the // sigma of the common clock path. @@ -332,7 +333,7 @@ CheckCrpr::outputDelayCrpr(const Path *src_path, if (sdc_->crprActive()) { const PathAnalysisPt *path_ap = src_path->pathAnalysisPt(this); const PathAnalysisPt *tgt_path_ap = path_ap->tgtClkAnalysisPt(); - bool same_pin = (sdc_->crprMode() == CrprMode::same_pin); + bool same_pin = (variables_->crprMode() == CrprMode::same_pin); outputDelayCrpr1(src_path,tgt_clk_edge,tgt_path_ap, same_pin, crpr, crpr_pin); } diff --git a/search/Genclks.cc b/search/Genclks.cc index 4b0cf0c7..7d81564a 100644 --- a/search/Genclks.cc +++ b/search/Genclks.cc @@ -42,6 +42,7 @@ #include "Levelize.hh" #include "Path.hh" #include "Search.hh" +#include "Variables.hh" namespace sta { @@ -249,7 +250,7 @@ GenClkMasterSearchPred::searchFrom(const Vertex *from_vertex) bool GenClkMasterSearchPred::searchThru(Edge *edge) { - const Sdc *sdc = sta_->sdc(); + const Variables *variables = sta_->variables(); const TimingRole *role = edge->role(); // Propagate clocks through constants. return !(edge->role()->isTimingCheck() @@ -257,14 +258,14 @@ GenClkMasterSearchPred::searchThru(Edge *edge) || edge->isDisabledConstraint() // Constants disable edge cond expression. || edge->isDisabledCond() - || sdc->isDisabledCondDefault(edge) + || sta_->isDisabledCondDefault(edge) // Register/latch preset/clr edges are disabled by default. - || (!sdc->presetClrArcsEnabled() + || (!variables->presetClrArcsEnabled() && role == TimingRole::regSetClr()) || (edge->isBidirectInstPath() - && !sdc->bidirectInstPathsEnabled()) + && !variables->bidirectInstPathsEnabled()) || (edge->isBidirectNetPath() - && !sdc->bidirectNetPathsEnabled())); + && !variables->bidirectNetPathsEnabled())); } bool @@ -481,7 +482,7 @@ GenClkInsertionSearchPred::searchThru(Edge *edge) EdgeSet *fdbk_edges = genclk_info_->fdbkEdges(); return SearchPred0::searchThru(edge) && !role->isTimingCheck() - && (sdc->clkThruTristateEnabled() + && (sta_->variables()->clkThruTristateEnabled() || !(role == TimingRole::tristateEnable() || role == TimingRole::tristateDisable())) && !(fdbk_edges && fdbk_edges->hasKey(edge)) @@ -740,13 +741,12 @@ GenClkArrivalSearchPred::GenClkArrivalSearchPred(Clock *gclk, bool GenClkArrivalSearchPred::searchThru(Edge *edge) { - const Sdc *sdc = sta_->sdc(); const TimingRole *role = edge->role(); return EvalPred::searchThru(edge) && (role == TimingRole::combinational() || role->isWire() || !combinational_) - && (sdc->clkThruTristateEnabled() + && (sta_->variables()->clkThruTristateEnabled() || !(role == TimingRole::tristateEnable() || role == TimingRole::tristateDisable())); } diff --git a/search/Levelize.cc b/search/Levelize.cc index 0cc5ac52..b2f03e78 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -36,6 +36,8 @@ #include "Graph.hh" #include "GraphCmp.hh" #include "SearchPred.hh" +#include "Variables.hh" +#include "GraphDelayCalc.hh" namespace sta { @@ -185,7 +187,7 @@ Levelize::isRoot(Vertex *vertex) return false; } // Bidirect pins are not treated as roots in this case. - return !sdc_->bidirectDrvrSlewFromLoad(vertex->pin()); + return !graph_delay_calc_->bidirectDrvrSlewFromLoad(vertex->pin()); } else return false; @@ -250,7 +252,7 @@ Levelize::visit(Vertex *vertex, latch_d_to_q_edges_.insert(edge); } // Levelize bidirect driver as if it was a fanout of the bidirect load. - if (sdc_->bidirectDrvrSlewFromLoad(from_pin) + if (graph_delay_calc_->bidirectDrvrSlewFromLoad(from_pin) && !vertex->isBidirectDriver()) { Vertex *to_vertex = graph_->pinDrvrVertex(from_pin); if (search_pred_->searchTo(to_vertex) @@ -288,7 +290,7 @@ Levelize::recordLoop(Edge *edge, EdgeSeq *loop_edges = loopEdges(path, edge); GraphLoop *loop = new GraphLoop(loop_edges); loops_->push_back(loop); - if (sdc_->dynamicLoopBreaking()) + if (variables_->dynamicLoopBreaking()) sdc_->makeLoopExceptions(loop); } // Record disabled loop edges so they can be cleared without diff --git a/search/PathGroup.cc b/search/PathGroup.cc index 857eac11..b2661fa7 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -152,7 +152,8 @@ PathGroup::enumMinSlackUnderMin(PathEnd *path_end) if (tagMatchCrpr(other->tag(sta_), tag)) { PathEnd *end_min = path_end->copy(); end_min->setPath(other); - bool slack_under = fuzzyGreater(end_min->slackNoCrpr(sta_), slack_min_); + float slack = delayAsFloat(end_min->slackNoCrpr(sta_)); + bool slack_under = fuzzyGreater(slack, slack_min_); delete end_min; if (slack_under) return true; diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 5a895a3e..9cea1857 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -59,6 +59,7 @@ #include "Latches.hh" #include "Corner.hh" #include "Genclks.hh" +#include "Variables.hh" namespace sta { @@ -1397,7 +1398,7 @@ ReportPath::reportVerbose(const MinPulseWidthCheck *check) const reportLine(clk_ideal_prop, check->closeDelay(this), close_arrival, close_el); reportLine(pin_name, delay_zero, close_arrival, close_el); - if (sdc_->crprEnabled()) { + if (variables_->crprEnabled()) { Crpr pessimism = check->checkCrpr(this); close_arrival += pessimism; reportLine("clock reconvergence pessimism", pessimism, close_arrival, close_el); @@ -2530,7 +2531,7 @@ void ReportPath::reportCommonClkPessimism(const PathEnd *end, Arrival &clk_arrival) const { - if (sdc_->crprEnabled()) { + if (variables_->crprEnabled()) { Crpr pessimism = end->checkCrpr(this); clk_arrival += pessimism; reportLine("clock reconvergence pessimism", pessimism, clk_arrival, diff --git a/search/Search.cc b/search/Search.cc index a8b14824..035ac969 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -67,6 +67,7 @@ #include "Latches.hh" #include "Crpr.hh" #include "Genclks.hh" +#include "Variables.hh" namespace sta { @@ -91,10 +92,9 @@ EvalPred::setSearchThruLatches(bool thru_latches) bool EvalPred::searchThru(Edge *edge) { - const Sdc *sdc = sta_->sdc(); const TimingRole *role = edge->role(); return SearchPred0::searchThru(edge) - && (sdc->dynamicLoopBreaking() + && (sta_->variables()->dynamicLoopBreaking() || !edge->isDisabledLoop()) && !role->isTimingCheck() && (search_thru_latches_ @@ -121,12 +121,12 @@ DynLoopSrchPred::DynLoopSrchPred(TagGroupBldr *tag_bldr) : bool DynLoopSrchPred::loopEnabled(Edge *edge, - const Sdc *sdc, + bool dynamic_loop_breaking_enabled, const Graph *graph, Search *search) { return !edge->isDisabledLoop() - || (sdc->dynamicLoopBreaking() + || (dynamic_loop_breaking_enabled && hasPendingLoopPaths(edge, graph, search)); } @@ -179,14 +179,14 @@ bool SearchThru::searchThru(Edge *edge) { const Graph *graph = sta_->graph(); - const Sdc *sdc = sta_->sdc(); Search *search = sta_->search(); return EvalPred::searchThru(edge) // Only search thru latch D->Q if it is always open. // Enqueue thru latches is handled explicitly by search. && (edge->role() != TimingRole::latchDtoQ() || sta_->latches()->latchDtoQState(edge) == LatchEnableState::open) - && loopEnabled(edge, sdc, graph, search); + && loopEnabled(edge, sta_->variables()->dynamicLoopBreaking(), + graph, search); } ClkArrivalSearchPred::ClkArrivalSearchPred(const StaState *sta) : @@ -460,9 +460,9 @@ Search::findPathEnds(ExceptionFrom *from, bool clk_gating_hold) { findFilteredArrivals(from, thrus, to, unconstrained, true); - if (!sdc_->recoveryRemovalChecksEnabled()) + if (!variables_->recoveryRemovalChecksEnabled()) recovery = removal = false; - if (!sdc_->gatedClkChecksEnabled()) + if (!variables_->gatedClkChecksEnabled()) clk_gating_setup = clk_gating_hold = false; makePathGroups(group_path_count, endpoint_path_count, unique_pins, slack_min, slack_max, @@ -1231,7 +1231,7 @@ ArrivalVisitor::constrainedRequiredsInvalid(Vertex *vertex, } } // Gated clocks. - if (is_clk && sdc_->gatedClkChecksEnabled()) { + if (is_clk && variables_->gatedClkChecksEnabled()) { PinSet enable_pins(network_); search_->gatedClk()->gatedClkEnables(vertex, enable_pins); for (const Pin *enable : enable_pins) @@ -1798,11 +1798,11 @@ Search::seedInputDelayArrival(const Pin *pin, if (input_delay) { clk_edge = input_delay->clkEdge(); if (clk_edge == nullptr - && sdc_->useDefaultArrivalClock()) + && variables_->useDefaultArrivalClock()) clk_edge = sdc_->defaultArrivalClockEdge(); ref_pin = input_delay->refPin(); } - else if (sdc_->useDefaultArrivalClock()) + else if (variables_->useDefaultArrivalClock()) clk_edge = sdc_->defaultArrivalClockEdge(); if (ref_pin) { Vertex *ref_vertex = graph_->pinLoadVertex(ref_pin); @@ -2124,7 +2124,7 @@ PathVisitor::visitFromPath(const Pin *from_pin, Arrival to_arrival; if (from_clk_info->isGenClkSrcPath()) { if (!sdc_->clkStopPropagation(clk,from_pin,from_rf,to_pin,to_rf) - && (sdc_->clkThruTristateEnabled() + && (variables_->clkThruTristateEnabled() || !(role == TimingRole::tristateEnable() || role == TimingRole::tristateDisable()))) { const Clock *gclk = from_tag->genClkSrcPathClk(this); @@ -2148,7 +2148,8 @@ PathVisitor::visitFromPath(const Pin *from_pin, path_ap->corner()->findPathAnalysisPt(min_max->opposite()); Delay arc_delay_opp = search_->deratedDelay(from_vertex, arc, edge, true, path_ap_opp); - bool arc_delay_min_max_eq = fuzzyEqual(arc_delay, arc_delay_opp); + bool arc_delay_min_max_eq = + fuzzyEqual(delayAsFloat(arc_delay), delayAsFloat(arc_delay_opp)); to_tag = search_->thruClkTag(from_path, from_vertex, from_tag, true, edge, to_rf, arc_delay_min_max_eq, min_max, path_ap); @@ -2227,7 +2228,7 @@ PathVisitor::visitFromPath(const Pin *from_pin, // Propagate arrival as non-clock at the end of the clock tree. bool to_propagates_clk = !sdc_->clkStopPropagation(clk,from_pin,from_rf,to_pin,to_rf) - && (sdc_->clkThruTristateEnabled() + && (variables_->clkThruTristateEnabled() || !(role == TimingRole::tristateEnable() || role == TimingRole::tristateDisable())); arc_delay = search_->deratedDelay(from_vertex, arc, edge, @@ -2236,7 +2237,8 @@ PathVisitor::visitFromPath(const Pin *from_pin, path_ap->corner()->findPathAnalysisPt(min_max->opposite()); Delay arc_delay_opp = search_->deratedDelay(from_vertex, arc, edge, to_propagates_clk, path_ap_opp); - bool arc_delay_min_max_eq = fuzzyEqual(arc_delay, arc_delay_opp); + bool arc_delay_min_max_eq = + fuzzyEqual(delayAsFloat(arc_delay), delayAsFloat(arc_delay_opp)); to_tag = search_->thruClkTag(from_path, from_vertex, from_tag, to_propagates_clk, edge, to_rf, arc_delay_min_max_eq, @@ -3244,7 +3246,7 @@ Search::isEndpoint(Vertex *vertex, return hasFanin(vertex, pred, graph_) && ((vertex->hasChecks() && hasEnabledChecks(vertex)) - || (sdc_->gatedClkChecksEnabled() + || (variables_->gatedClkChecksEnabled() && gated_clk_->isGatedClkEnable(vertex)) || vertex->isConstrained() || sdc_->isPathDelayInternalEndpoint(pin) diff --git a/search/SearchPred.cc b/search/SearchPred.cc index 04bb6025..9cb0401e 100644 --- a/search/SearchPred.cc +++ b/search/SearchPred.cc @@ -33,6 +33,7 @@ #include "Levelize.hh" #include "Search.hh" #include "Latches.hh" +#include "Variables.hh" namespace sta { @@ -59,19 +60,20 @@ SearchPred0::searchThru(Edge *edge) { const TimingRole *role = edge->role(); const Sdc *sdc = sta_->sdc(); + const Variables *variables = sta_->variables(); return !(edge->isDisabledConstraint() // Constants disable edge cond expression. || edge->isDisabledCond() || sdc->isDisabledCondDefault(edge) // Register/latch preset/clr edges are disabled by default. || (role == TimingRole::regSetClr() - && !sdc->presetClrArcsEnabled()) + && !variables->presetClrArcsEnabled()) // Constants on other pins disable this edge (ie, a mux select). || edge->simTimingSense() == TimingSense::none || (edge->isBidirectInstPath() - && !sdc->bidirectInstPathsEnabled()) + && !variables->bidirectInstPathsEnabled()) || (edge->isBidirectNetPath() - && !sdc->bidirectNetPathsEnabled()) + && !variables->bidirectNetPathsEnabled()) || (role == TimingRole::latchDtoQ() && sta_->latches()->latchDtoQState(edge) == LatchEnableState::closed)); @@ -152,12 +154,11 @@ ClkTreeSearchPred::ClkTreeSearchPred(const StaState *sta) : bool ClkTreeSearchPred::searchThru(Edge *edge) { - const Sdc *sdc = sta_->sdc(); // Propagate clocks through constants. const TimingRole *role = edge->role(); return (role->isWire() || role == TimingRole::combinational()) - && (sdc->clkThruTristateEnabled() + && (sta_->variables()->clkThruTristateEnabled() || !(role == TimingRole::tristateEnable() || role == TimingRole::tristateDisable())) && SearchPred1::searchThru(edge); diff --git a/search/Sta.cc b/search/Sta.cc index 75b1baf2..14ddc15e 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -44,6 +44,7 @@ #include "Graph.hh" #include "GraphCmp.hh" #include "Sdc.hh" +#include "Variables.hh" #include "WriteSdc.hh" #include "ExceptionPath.hh" #include "MakeConcreteParasitics.hh" @@ -283,6 +284,7 @@ Sta::Sta() : void Sta::makeComponents() { + makeVariables(); makeReport(); makeDebug(); makeUnits(); @@ -505,6 +507,12 @@ Sta::makePower() power_ = new Power(this); } +void +Sta::makeVariables() +{ + variables_ = new Variables(); +} + void Sta::setSta(Sta *sta) { @@ -519,6 +527,7 @@ Sta::sta() Sta::~Sta() { + delete variables_; // Verilog modules refer to the network in the sta so it has // to deleted before the network. delete verilog_reader_; @@ -1693,12 +1702,6 @@ Sta::isDisabledLoop(Edge *edge) const return levelize_->isDisabledLoop(edge); } -bool -Sta::isDisabledCondDefault(Edge *edge) -{ - return sdc_->isDisabledCondDefault(edge); -} - PinSet Sta::disabledConstantPins(Edge *edge) { @@ -1768,21 +1771,21 @@ Sta::exprConstantPins(FuncExpr *expr, bool Sta::isDisabledBidirectInstPath(Edge *edge) const { - return !sdc_->bidirectInstPathsEnabled() + return !variables_->bidirectInstPathsEnabled() && edge->isBidirectInstPath(); } bool Sta::isDisabledBidirectNetPath(Edge *edge) const { - return !sdc_->bidirectNetPathsEnabled() + return !variables_->bidirectNetPathsEnabled() && edge->isBidirectNetPath(); } bool Sta::isDisabledPresetClr(Edge *edge) const { - return !sdc_->presetClrArcsEnabled() + return !variables_->presetClrArcsEnabled() && edge->role() == TimingRole::regSetClr(); } @@ -2161,10 +2164,12 @@ Sta::checkTiming(bool no_input_delay, loops, generated_clks); } +//////////////////////////////////////////////////////////////// + bool Sta::crprEnabled() const { - return sdc_->crprEnabled(); + return variables_->crprEnabled(); } void @@ -2172,15 +2177,15 @@ Sta::setCrprEnabled(bool enabled) { // Pessimism is only relevant for on_chip_variation analysis. if (sdc_->analysisType() == AnalysisType::ocv - && enabled != sdc_->crprEnabled()) + && enabled != variables_->crprEnabled()) search_->arrivalsInvalid(); - sdc_->setCrprEnabled(enabled); + variables_->setCrprEnabled(enabled); } CrprMode Sta::crprMode() const { - return sdc_->crprMode(); + return variables_->crprMode(); } void @@ -2188,25 +2193,24 @@ Sta::setCrprMode(CrprMode mode) { // Pessimism is only relevant for on_chip_variation analysis. if (sdc_->analysisType() == AnalysisType::ocv - && sdc_->crprEnabled() - && sdc_->crprMode() != mode) + && variables_->crprEnabled() + && variables_->crprMode() != mode) search_->arrivalsInvalid(); - sdc_->setCrprMode(mode); + variables_->setCrprMode(mode); } bool Sta::pocvEnabled() const { - return pocv_enabled_; + return variables_->pocvEnabled(); } void Sta::setPocvEnabled(bool enabled) { - if (enabled != pocv_enabled_) + if (enabled != variables_->pocvEnabled()) delaysInvalid(); - pocv_enabled_ = enabled; - updateComponentsState(); + variables_->setPocvEnabled(enabled); } void @@ -2222,135 +2226,141 @@ Sta::setSigmaFactor(float factor) bool Sta::propagateGatedClockEnable() const { - return sdc_->propagateGatedClockEnable(); + return variables_->propagateGatedClockEnable(); } void Sta::setPropagateGatedClockEnable(bool enable) { - if (sdc_->propagateGatedClockEnable() != enable) + if (variables_->propagateGatedClockEnable() != enable) search_->arrivalsInvalid(); - sdc_->setPropagateGatedClockEnable(enable); + variables_->setPropagateGatedClockEnable(enable); } bool Sta::presetClrArcsEnabled() const { - return sdc_->presetClrArcsEnabled(); + return variables_->presetClrArcsEnabled(); } void Sta::setPresetClrArcsEnabled(bool enable) { - if (sdc_->presetClrArcsEnabled() != enable) { + if (variables_->presetClrArcsEnabled() != enable) { levelize_->invalid(); delaysInvalid(); } - sdc_->setPresetClrArcsEnabled(enable); + variables_->setPresetClrArcsEnabled(enable); } bool Sta::condDefaultArcsEnabled() const { - return sdc_->condDefaultArcsEnabled(); + return variables_->condDefaultArcsEnabled(); } void Sta::setCondDefaultArcsEnabled(bool enabled) { - if (sdc_->condDefaultArcsEnabled() != enabled) { + if (variables_->condDefaultArcsEnabled() != enabled) { delaysInvalid(); - sdc_->setCondDefaultArcsEnabled(enabled); + variables_->setCondDefaultArcsEnabled(enabled); } } bool Sta::bidirectInstPathsEnabled() const { - return sdc_->bidirectInstPathsEnabled(); + return variables_->bidirectInstPathsEnabled(); } void Sta::setBidirectInstPathsEnabled(bool enabled) { - if (sdc_->bidirectInstPathsEnabled() != enabled) { + if (variables_->bidirectInstPathsEnabled() != enabled) { levelize_->invalid(); delaysInvalid(); - sdc_->setBidirectInstPathsEnabled(enabled); + variables_->setBidirectInstPathsEnabled(enabled); } } bool Sta::bidirectNetPathsEnabled() const { - return sdc_->bidirectNetPathsEnabled(); + return variables_->bidirectNetPathsEnabled(); } void Sta::setBidirectNetPathsEnabled(bool enabled) { - if (sdc_->bidirectNetPathsEnabled() != enabled) { + if (variables_->bidirectNetPathsEnabled() != enabled) { delaysInvalid(); - sdc_->setBidirectNetPathsEnabled(enabled); + variables_->setBidirectNetPathsEnabled(enabled); } } bool Sta::recoveryRemovalChecksEnabled() const { - return sdc_->recoveryRemovalChecksEnabled(); + return variables_->recoveryRemovalChecksEnabled(); } void Sta::setRecoveryRemovalChecksEnabled(bool enabled) { - if (sdc_->recoveryRemovalChecksEnabled() != enabled) { + if (variables_->recoveryRemovalChecksEnabled() != enabled) { search_->arrivalsInvalid(); - sdc_->setRecoveryRemovalChecksEnabled(enabled); + variables_->setRecoveryRemovalChecksEnabled(enabled); } } bool Sta::gatedClkChecksEnabled() const { - return sdc_->gatedClkChecksEnabled(); + return variables_->gatedClkChecksEnabled(); } void Sta::setGatedClkChecksEnabled(bool enabled) { - if (sdc_->gatedClkChecksEnabled() != enabled) { + if (variables_->gatedClkChecksEnabled() != enabled) { search_->arrivalsInvalid(); - sdc_->setGatedClkChecksEnabled(enabled); + variables_->setGatedClkChecksEnabled(enabled); } } bool Sta::dynamicLoopBreaking() const { - return sdc_->dynamicLoopBreaking(); + return variables_->dynamicLoopBreaking(); } void Sta::setDynamicLoopBreaking(bool enable) { - if (sdc_->dynamicLoopBreaking() != enable) { - sdc_->setDynamicLoopBreaking(enable); + if (variables_->dynamicLoopBreaking() != enable) { + if (levelize_->levelized()) { + if (enable) + sdc_->makeLoopExceptions(); + else + sdc_->deleteLoopExceptions(); + } search_->arrivalsInvalid(); + variables_->setDynamicLoopBreaking(enable); } } bool Sta::useDefaultArrivalClock() const { - return sdc_->useDefaultArrivalClock(); + return variables_->useDefaultArrivalClock(); } void Sta::setUseDefaultArrivalClock(bool enable) { - if (sdc_->useDefaultArrivalClock() != enable) { - sdc_->setUseDefaultArrivalClock(enable); + if (variables_->useDefaultArrivalClock() != enable) { + variables_->setUseDefaultArrivalClock(enable); search_->arrivalsInvalid(); } } @@ -2358,27 +2368,27 @@ Sta::setUseDefaultArrivalClock(bool enable) bool Sta::propagateAllClocks() const { - return sdc_->propagateAllClocks(); + return variables_->propagateAllClocks(); } void Sta::setPropagateAllClocks(bool prop) { - sdc_->setPropagateAllClocks(prop); + variables_->setPropagateAllClocks(prop); } bool Sta::clkThruTristateEnabled() const { - return sdc_->clkThruTristateEnabled(); + return variables_->clkThruTristateEnabled(); } void Sta::setClkThruTristateEnabled(bool enable) { - if (enable != sdc_->clkThruTristateEnabled()) { + if (enable != variables_->clkThruTristateEnabled()) { search_->arrivalsInvalid(); - sdc_->setClkThruTristateEnabled(enable); + variables_->setClkThruTristateEnabled(enable); } } @@ -3207,7 +3217,7 @@ Sta::findRequired(Vertex *vertex) searchPreamble(); search_->findAllArrivals(); search_->findRequireds(vertex->level()); - if (sdc_->crprEnabled() + if (variables_->crprEnabled() && search_->crprPathPruningEnabled() && !search_->crprApproxMissingRequireds() // Clocks invariably have requireds that are pruned but it isn't @@ -4856,12 +4866,11 @@ FanInOutSrchPred::searchFrom(const Vertex *from_vertex) bool FanInOutSrchPred::searchThru(Edge *edge) { - const Sdc *sdc = sta_->sdc(); return searchThruRole(edge) && (thru_disabled_ || !(edge->isDisabledConstraint() || edge->isDisabledCond() - || sdc->isDisabledCondDefault(edge))) + || sta_->isDisabledCondDefault(edge))) && (thru_constants_ || edge->simTimingSense() != TimingSense::none); } diff --git a/search/StaState.cc b/search/StaState.cc index bf457a2f..5dfb1f09 100644 --- a/search/StaState.cc +++ b/search/StaState.cc @@ -29,6 +29,10 @@ #include "DispatchQueue.hh" #include "Units.hh" #include "Network.hh" +#include "Variables.hh" +#include "Sdc.hh" +#include "Graph.hh" +#include "TimingArc.hh" namespace sta { @@ -50,8 +54,8 @@ StaState::StaState() : clk_network_(nullptr), thread_count_(1), dispatch_queue_(nullptr), - pocv_enabled_(false), - sigma_factor_(1.0) + sigma_factor_(1.0), + variables_(nullptr) { } @@ -108,4 +112,18 @@ StaState::setDebug(Debug *debug) debug_ = debug; } +bool +StaState::crprActive() const +{ + return sdc_->analysisType() == AnalysisType::ocv + && variables_->crprEnabled(); +} + +bool +StaState::isDisabledCondDefault(Edge *edge) const +{ + return !variables_->condDefaultArcsEnabled() + && edge->timingArcSet()->isCondDefault(); +} + } // namespace diff --git a/search/VisitPathEnds.cc b/search/VisitPathEnds.cc index 561b5fb2..5345627f 100644 --- a/search/VisitPathEnds.cc +++ b/search/VisitPathEnds.cc @@ -39,6 +39,7 @@ #include "PathEnd.hh" #include "Search.hh" #include "GatedClk.hh" +#include "Variables.hh" namespace sta { @@ -122,7 +123,7 @@ VisitPathEnds::visitClkedPathEnds(const Pin *pin, is_constrained = true; } } - if (sdc_->gatedClkChecksEnabled()) + if (variables_->gatedClkChecksEnabled()) visitGatedClkEnd(pin, vertex, path, end_rf, path_ap, filtered, visitor, is_constrained); visitDataCheckEnd(pin, path, end_rf, path_ap, filtered, visitor, @@ -288,7 +289,7 @@ VisitPathEnds::checkEdgeEnabled(Edge *edge) const && !sdc_->isDisabledCondDefault(edge) && !((check_role == TimingRole::recovery() || check_role == TimingRole::removal()) - && !sdc_->recoveryRemovalChecksEnabled()); + && !variables_->recoveryRemovalChecksEnabled()); } void