factor variables out of sdc

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-04-09 16:35:15 -07:00
parent 5bb4d58d69
commit 6ebd162d42
28 changed files with 489 additions and 452 deletions

View File

@ -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

View File

@ -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<rcmodel*> unsaved_parasitics_;
bool pocv_enabled_;
};
ArcDelayCalc *
@ -391,6 +393,7 @@ ArnoldiDelayCalc::gateDelay(const Pin *drvr_pin,
ConcreteParasitic *cparasitic =
reinterpret_cast<ConcreteParasitic*>(const_cast<Parasitic*>(parasitic));
rcmodel_ = dynamic_cast<rcmodel*>(cparasitic);
pocv_enabled_ = variables_->pocvEnabled();
GateTableModel *table_model = arc->gateTableModel(dcalc_ap);
if (table_model && rcmodel_) {
const Pvt *pvt = pinPvt(drvr_pin, dcalc_ap);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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),

View File

@ -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,

View File

@ -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.

View File

@ -122,8 +122,6 @@ public:
class ExceptionPath;
typedef Set<ExceptionState*, ExceptionStateLess> ExceptionStateSet;
enum class CrprMode { same_pin, same_transition };
// Constraint applies to clock or data paths.
enum class PathClkOrData { clk, data };

View File

@ -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,

View File

@ -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();

View File

@ -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

98
include/sta/Variables.hh Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
//
// 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

View File

@ -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;
}

View File

@ -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)
{

131
sdc/Variables.cc Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
//
// 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

View File

@ -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

View File

@ -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);
}

View File

@ -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()));
}

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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