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

#include <string>

#include "StringSeq.hh"
#include "LibertyClass.hh"
#include "NetworkClass.hh"
#include "SdcClass.hh"
#include "GraphClass.hh"
#include "ParasiticsClass.hh"
#include "StaState.hh"
#include "VertexVisitor.hh"
#include "SearchClass.hh"
#include "PowerClass.hh"
#include "ArcDelayCalc.hh"
#include "CircuitSim.hh"
#include "Variables.hh"

struct Tcl_Interp;

namespace sta {

// Don't include headers to minimize dependencies.
class MinMax;
class MinMaxAll;
class RiseFallBoth;
class RiseFall;
class VerilogReader;
class ReportPath;
class CheckTiming;
class DcalcAnalysisPt;
class CheckSlewLimits;
class CheckFanoutLimits;
class CheckCapacitanceLimits;
class CheckMinPulseWidths;
class CheckMinPeriods;
class CheckMaxSkews;
class PatternMatch;
class CheckPeriods;
class LibertyReader;
class SearchPred;
class Corner;
class ClkSkews;
class ReportField;
class EquivCells;

typedef InstanceSeq::Iterator SlowDrvrIterator;
typedef Vector<const char*> CheckError;
typedef Vector<CheckError*> CheckErrorSeq;
typedef Vector<Corner*> CornerSeq;

enum class CmdNamespace { sta, sdc };

// Initialize sta functions that are not part of the Sta class.
void initSta();

// Call before exit to make leak detection simpler for purify and valgrind.
void
deleteAllMemory();

// The Lord, God, King, Master of the Timing Universe.
// This class is a FACADE used to present an API to the collection of
// objects that hold the collective state of the static timing analyzer.
// It should only hold pointers to objects so that only the referenced
// class declarations and not their definitions are needed by this header.
//
// The report object is not owned by the sta object.
class Sta : public StaState
{
public:
  Sta();
  // The Sta is a FACTORY for the components.
  // makeComponents calls the make{Component} virtual functions.
  // Ideally this would be called by the Sta constructor, but a
  // virtual function called in a base class constructor does not
  // call the derived class function.
  virtual void makeComponents();
  // Call copyState for each component to notify it that some
  // pointers to some components have changed.
  // This must be called after changing any of the StaState components.
  virtual void updateComponentsState();
  virtual ~Sta();

  // Singleton accessor used by tcl command interpreter.
  static Sta *sta();
  static void setSta(Sta *sta);

  // Default number of threads to use.
  virtual int defaultThreadCount() const;
  void setThreadCount(int thread_count);

  virtual LibertyLibrary *readLiberty(const char *filename,
				      Corner *corner,
				      const MinMaxAll *min_max,
				      bool infer_latches);
  bool setMinLibrary(const char *min_filename,
		     const char *max_filename);
  bool readVerilog(const char *filename);
  // Network readers call this to notify the Sta to delete any previously
  // linked network.
  void readNetlistBefore();
  // Return true if successful.
  bool linkDesign(const char *top_cell_name,
                  bool make_black_boxes);

  // SDC Swig API.
  Instance *currentInstance() const;
  void setCurrentInstance(Instance *inst);
  virtual void setAnalysisType(AnalysisType analysis_type);
  void setOperatingConditions(OperatingConditions *op_cond,
			      const MinMaxAll *min_max);
  void setTimingDerate(TimingDerateType type,
		       PathClkOrData clk_data,
		       const RiseFallBoth *rf,
		       const EarlyLate *early_late,
		       float derate);
  // Delay type is always net for net derating.
  void setTimingDerate(const Net *net,
		       PathClkOrData clk_data,
		       const RiseFallBoth *rf,
		       const EarlyLate *early_late,
		       float derate);
  void setTimingDerate(const Instance *inst,
		       TimingDerateCellType type,
		       PathClkOrData clk_data,
		       const RiseFallBoth *rf,
		       const EarlyLate *early_late,
		       float derate);
  void setTimingDerate(const LibertyCell *cell,
		       TimingDerateCellType type,
		       PathClkOrData clk_data,
		       const RiseFallBoth *rf,
		       const EarlyLate *early_late,
		       float derate);
  void unsetTimingDerate();
  void setInputSlew(const Port *port,
		    const RiseFallBoth *rf,
		    const MinMaxAll *min_max,
		    float slew);
  // Set port external pin load (set_load -pin port).
  void setPortExtPinCap(const Port *port,
			const RiseFallBoth *rf,
                        const Corner *corner,
			const MinMaxAll *min_max,
			float cap);
  void portExtCaps(const Port *port,
                   const Corner *corner,
                   const MinMax *min_max,
                   float &pin_cap,
                   float &wire_cap,
                   int &fanout);
  // Set port external wire load (set_load -wire port).
  void setPortExtWireCap(const Port *port,
			 bool subtract_pin_cap,
			 const RiseFallBoth *rf,
                         const Corner *corner,
			 const MinMaxAll *min_max,
			 float cap);
  // Set net wire capacitance (set_load -wire net).
  void setNetWireCap(const Net *net,
		     bool subtract_pin_load,
		     const Corner *corner,
		     const MinMaxAll *min_max,
		     float cap);
  // Remove all "set_load net" annotations.
  void removeNetLoadCaps() const;
  // Set port external fanout (used by wireload models).
  void setPortExtFanout(const Port *port,
			int fanout,
                        const Corner *corner,
			const MinMaxAll *min_max);
  // Liberty port capacitance.
  float capacitance(const LibertyPort *port,
                    Corner *corner,
                    const MinMax *min_max);
  // pin_cap  = net pin capacitances + port external pin capacitance,
  // wire_cap = annotated net capacitance + port external wire capacitance.
  void connectedCap(const Pin *drvr_pin,
		    const RiseFall *rf,
		    const Corner *corner,
		    const MinMax *min_max,
		    float &pin_cap,
		    float &wire_cap) const;
  void connectedCap(const Net *net,
		    Corner *corner,
		    const MinMax *min_max,
		    float &pin_cap,
		    float &wire_cap) const;
  void setResistance(const Net *net,
		     const MinMaxAll *min_max,
		     float res);
  void setDriveCell(const LibertyLibrary *library,
		    const LibertyCell *cell,
		    const Port *port,
		    const LibertyPort *from_port,
		    float *from_slews,
		    const LibertyPort *to_port,
		    const RiseFallBoth *rf,
		    const MinMaxAll *min_max);
  void setDriveResistance(const Port *port,
			  const RiseFallBoth *rf,
			  const MinMaxAll *min_max,
			  float res);
  void setLatchBorrowLimit(const Pin *pin,
			   float limit);
  void setLatchBorrowLimit(const Instance *inst,
			   float limit);
  void setLatchBorrowLimit(const Clock *clk,
			   float limit);
  void setMinPulseWidth(const RiseFallBoth *rf,
			float min_width);
  void setMinPulseWidth(const Pin *pin,
			const RiseFallBoth *rf,
			float min_width);
  void setMinPulseWidth(const Instance *inst,
			const RiseFallBoth *rf,
			float min_width);
  void setMinPulseWidth(const Clock *clk,
			const RiseFallBoth *rf,
			float min_width);
  void setWireload(Wireload *wireload,
		   const MinMaxAll *min_max);
  void setWireloadMode(WireloadMode mode);
  void setWireloadSelection(WireloadSelection *selection,
			    const MinMaxAll *min_max);
  void setSlewLimit(Clock *clk,
		    const RiseFallBoth *rf,
		    const PathClkOrData clk_data,
		    const MinMax *min_max,
		    float slew);
  void setSlewLimit(Port *port,
		    const MinMax *min_max,
		    float slew);
  void setSlewLimit(Cell *cell,
		    const MinMax *min_max,
		    float slew);
  void setCapacitanceLimit(Cell *cell,
			   const MinMax *min_max,
			   float cap);
  void setCapacitanceLimit(Port *port,
			   const MinMax *min_max,
			   float cap);
  void setCapacitanceLimit(Pin *pin,
			   const MinMax *min_max,
			   float cap);
  void setFanoutLimit(Cell *cell,
		      const MinMax *min_max,
		      float fanout);
  void setFanoutLimit(Port *port,
		      const MinMax *min_max,
		      float fanout);
  void setMaxArea(float area);

  void makeClock(const char *name,
		 PinSet *pins,
		 bool add_to_pins,
		 float period,
		 FloatSeq *waveform,
		 char *comment);
  // edges size must be 3.
  void makeGeneratedClock(const char *name,
			  PinSet *pins,
			  bool add_to_pins,
			  Pin *src_pin,
			  Clock *master_clk,
			  int divide_by,
			  int multiply_by,
			  float duty_cycle,
			  bool invert,
			  bool combinational,
			  IntSeq *edges,
			  FloatSeq *edge_shifts,
			  char *comment);
  void removeClock(Clock *clk);
  // Update period/waveform for generated clocks from source pin clock.
  void updateGeneratedClks();
  // True if pin is defined as a clock source (pin may be hierarchical).
  bool isClockSrc(const Pin *pin) const;
  // Propagated (non-ideal) clocks.
  void setPropagatedClock(Clock *clk);
  void removePropagatedClock(Clock *clk);
  void setPropagatedClock(Pin *pin);
  void removePropagatedClock(Pin *pin);
  void setClockSlew(Clock *clock,
		    const RiseFallBoth *rf,
		    const MinMaxAll *min_max,
		    float slew);
  void removeClockSlew(Clock *clk);
  // Clock latency.
  // Latency can be on a clk, pin, or clk/pin combination.
  void setClockLatency(Clock *clk,
		       Pin *pin,
		       const RiseFallBoth *rf,
		       const MinMaxAll *min_max,
		       float delay);
  void removeClockLatency(const Clock *clk,
			  const Pin *pin);
  // Clock insertion delay (source latency).
  void setClockInsertion(const Clock *clk,
			 const Pin *pin,
			 const RiseFallBoth *rf,
			 const MinMaxAll *min_max,
			 const EarlyLateAll *early_late,
			 float delay);
  void removeClockInsertion(const Clock *clk,
			    const Pin *pin);
  // Clock uncertainty.
  virtual void setClockUncertainty(Clock *clk,
				   const SetupHoldAll *setup_hold,
				   float uncertainty);
  virtual void removeClockUncertainty(Clock *clk,
				      const SetupHoldAll *setup_hold);
  virtual void setClockUncertainty(Pin *pin,
				   const SetupHoldAll *setup_hold,
				   float uncertainty);
  virtual void removeClockUncertainty(Pin *pin,
				      const SetupHoldAll *setup_hold);
  // Inter-clock uncertainty.
  virtual void setClockUncertainty(Clock *from_clk,
				   const RiseFallBoth *from_rf,
				   Clock *to_clk,
				   const RiseFallBoth *to_rf,
				   const SetupHoldAll *setup_hold,
				   float uncertainty);
  virtual void removeClockUncertainty(Clock *from_clk,
				      const RiseFallBoth *from_rf,
				      Clock *to_clk,
				      const RiseFallBoth *to_rf,
				      const SetupHoldAll *setup_hold);
  ClockGroups *makeClockGroups(const char *name,
			       bool logically_exclusive,
			       bool physically_exclusive,
			       bool asynchronous,
			       bool allow_paths,
			       const char *comment);
  // nullptr name removes all.
  void removeClockGroupsLogicallyExclusive(const char *name);
  void removeClockGroupsPhysicallyExclusive(const char *name);
  void removeClockGroupsAsynchronous(const char *name);
  void makeClockGroup(ClockGroups *clk_groups,
		      ClockSet *clks);
  void setClockSense(PinSet *pins,
		     ClockSet *clks,
		     ClockSense sense);
  void setClockGatingCheck(const RiseFallBoth *rf,
			   const SetupHold *setup_hold,
			   float margin);
  void setClockGatingCheck(Clock *clk,
			   const RiseFallBoth *rf,
			   const SetupHold *setup_hold,
			   float margin);
  void setClockGatingCheck(Instance *inst,
			   const RiseFallBoth *rf,
			   const SetupHold *setup_hold,
			   float margin,
			   LogicValue active_value);
  void setClockGatingCheck(Pin *pin,
			   const RiseFallBoth *rf,
			   const SetupHold *setup_hold,
			   float margin,
			   LogicValue active_value);
  void setDataCheck(Pin *from,
		    const RiseFallBoth *from_rf,
		    Pin *to,
		    const RiseFallBoth *to_rf,
		    Clock *clk,
		    const SetupHoldAll *setup_hold,
		    float margin);
  void removeDataCheck(Pin *from,
		       const RiseFallBoth *from_rf,
		       Pin *to,
		       const RiseFallBoth *to_rf,
		       Clock *clk,
		       const SetupHoldAll *setup_hold);
  // set_disable_timing cell [-from] [-to]
  // Disable all edges thru cell if from/to are null.
  // Bus and bundle ports are NOT supported.
  void disable(LibertyCell *cell,
	       LibertyPort *from,
	       LibertyPort *to);
  void removeDisable(LibertyCell *cell,
		     LibertyPort *from,
		     LibertyPort *to);
  // set_disable_timing liberty port.
  // Bus and bundle ports are NOT supported.
  void disable(LibertyPort *port);
  void removeDisable(LibertyPort *port);
  // set_disable_timing port (top level instance port).
  // Bus and bundle ports are NOT supported.
  void disable(Port *port);
  void removeDisable(Port *port);
  // set_disable_timing instance [-from] [-to].
  // Disable all edges thru instance if from/to are null.
  // Bus and bundle ports are NOT supported.
  // Hierarchical instances are NOT supported.
  void disable(Instance *inst,
	       LibertyPort *from,
	       LibertyPort *to);
  void removeDisable(Instance *inst,
		     LibertyPort *from,
		     LibertyPort *to);
  // set_disable_timing pin
  void disable(Pin *pin);
  void removeDisable(Pin *pin);
  // set_disable_timing [get_timing_arc -of_objects instance]]
  void disable(Edge *edge);
  void removeDisable(Edge *edge);
  // set_disable_timing [get_timing_arc -of_objects lib_cell]]
  void disable(TimingArcSet *arc_set);
  void removeDisable(TimingArcSet *arc_set);
  // Edge is disabled by constant.
  bool isDisabledConstant(Edge *edge);
  // Return a set of constant pins that disabled edge.
  // Caller owns the returned set.
  PinSet disabledConstantPins(Edge *edge);
  // Edge timing sense with propagated constants.
  TimingSense simTimingSense(Edge *edge);
  // Edge is disabled by set_disable_timing constraint.
  bool isDisabledConstraint(Edge *edge);
  // Edge is disabled to break combinational loops.
  bool isDisabledLoop(Edge *edge) const;
  // Edge is disabled internal bidirect output path.
  bool isDisabledBidirectInstPath(Edge *edge) const;
  // Edge is disabled bidirect net path.
  bool isDisabledBidirectNetPath(Edge *edge) const;
  bool isDisabledPresetClr(Edge *edge) const;
  // Return a vector of graph edges that are disabled, sorted by
  // from/to vertex names.  Caller owns the returned vector.
  EdgeSeq disabledEdges();
  EdgeSeq disabledEdgesSorted();
  void disableClockGatingCheck(Instance *inst);
  void disableClockGatingCheck(Pin *pin);
  void removeDisableClockGatingCheck(Instance *inst);
  void removeDisableClockGatingCheck(Pin *pin);
  void setLogicValue(Pin *pin,
		     LogicValue value);
  void setCaseAnalysis(Pin *pin,
		       LogicValue value);
  void removeCaseAnalysis(Pin *pin);
  void setInputDelay(const Pin *pin,
		     const RiseFallBoth *rf,
		     const Clock *clk,
		     const RiseFall *clk_rf,
		     const Pin *ref_pin,
		     bool source_latency_included,
		     bool network_latency_included,
		     const MinMaxAll *min_max,
		     bool add,
		     float delay);
  void removeInputDelay(const Pin *pin,
			const RiseFallBoth *rf, 
			const Clock *clk,
			const RiseFall *clk_rf, 
			const MinMaxAll *min_max);
  void setOutputDelay(const Pin *pin,
		      const RiseFallBoth *rf,
		      const Clock *clk,
		      const RiseFall *clk_rf,
		      const Pin *ref_pin,
		      bool source_latency_included,
		      bool network_latency_included,
		      const MinMaxAll *min_max,
		      bool add,
		      float delay);
  void removeOutputDelay(const Pin *pin,
			 const RiseFallBoth *rf, 
			 const Clock *clk,
			 const RiseFall *clk_rf, 
			 const MinMaxAll *min_max);
  void makeFalsePath(ExceptionFrom *from,
		     ExceptionThruSeq *thrus,
		     ExceptionTo *to,
		     const MinMaxAll *min_max,
		     const char *comment);
  void makeMulticyclePath(ExceptionFrom *from,
			  ExceptionThruSeq *thrus,
			  ExceptionTo *to,
			  const MinMaxAll *min_max,
			  bool use_end_clk,
			  int path_multiplier,
			  const char *comment);
  void makePathDelay(ExceptionFrom *from,
		     ExceptionThruSeq *thrus,
		     ExceptionTo *to,
		     const MinMax *min_max,
		     bool ignore_clk_latency,
		     float delay,
		     const char *comment);
  void makeGroupPath(const char *name,
		     bool is_default,
		     ExceptionFrom *from,
		     ExceptionThruSeq *thrus,
		     ExceptionTo *to,
		     const char *comment);
  bool isGroupPathName(const char *group_name);
  void resetPath(ExceptionFrom *from,
		 ExceptionThruSeq *thrus,
		 ExceptionTo *to,
		 const MinMaxAll *min_max);
  // Make an exception -from specification.
  ExceptionFrom *makeExceptionFrom(PinSet *from_pins,
				   ClockSet *from_clks,
				   InstanceSet *from_insts,
				   const RiseFallBoth *from_rf);
  void checkExceptionFromPins(ExceptionFrom *from,
			      const char *file,
			      int line) const;
  bool exceptionFromInvalid(const Pin *pin) const;
  void deleteExceptionFrom(ExceptionFrom *from);
  // Make an exception -through specification.
  ExceptionThru *makeExceptionThru(PinSet *pins,
				   NetSet *nets,
				   InstanceSet *insts,
				   const RiseFallBoth *rf);
  void deleteExceptionThru(ExceptionThru *thru);
  // Make an exception -to specification.
  ExceptionTo *makeExceptionTo(PinSet *to_pins,
			       ClockSet *to_clks,
			       InstanceSet *to_insts,
			       const RiseFallBoth *rf,
			       const RiseFallBoth *end_rf);
  void checkExceptionToPins(ExceptionTo *to,
			    const char *file, int) const;
  void deleteExceptionTo(ExceptionTo *to);
  InstanceSet findRegisterInstances(ClockSet *clks,
                                    const RiseFallBoth *clk_rf,
                                    bool edge_triggered,
                                    bool latches);
  PinSet findRegisterDataPins(ClockSet *clks,
                              const RiseFallBoth *clk_rf,
                              bool registers,
                              bool latches);
  PinSet findRegisterClkPins(ClockSet *clks,
                             const RiseFallBoth *clk_rf,
                             bool registers,
                             bool latches);
  PinSet findRegisterAsyncPins(ClockSet *clks,
                               const RiseFallBoth *clk_rf,
                               bool registers,
                               bool latches);
  PinSet findRegisterOutputPins(ClockSet *clks,
                                const RiseFallBoth *clk_rf,
                                bool registers,
                                bool latches);
  PinSet findFaninPins(PinSeq *to,
                       bool flat,
                       bool startpoints_only,
                       int inst_levels,
                       int pin_levels,
                       bool thru_disabled,
                       bool thru_constants);
  InstanceSet
  findFaninInstances(PinSeq *to,
		     bool flat,
		     bool startpoints_only,
		     int inst_levels,
		     int pin_levels,
		     bool thru_disabled,
		     bool thru_constants);
  PinSet
  findFanoutPins(PinSeq *from,
		 bool flat,
		 bool endpoints_only,
		 int inst_levels,
		 int pin_levels,
		 bool thru_disabled,
		 bool thru_constants);
  InstanceSet
  findFanoutInstances(PinSeq *from,
		      bool flat,
		      bool endpoints_only,
		      int inst_levels,
		      int pin_levels,
		      bool thru_disabled,
		      bool thru_constants);

  // The set of clocks that arrive at vertex in the clock network.
  ClockSet clocks(const Pin *pin);
  // Clock domains for a pin.
  ClockSet clockDomains(const Pin *pin);

  void checkSlewLimitPreamble();
  // Return pins with the min/max slew limit slack.
  // net=null check all nets
  // corner=nullptr checks all corners.
  PinSeq checkSlewLimits(Net *net,
                         bool violators,
                         const Corner *corner,
                         const MinMax *min_max);
  void reportSlewLimitShortHeader();
  void reportSlewLimitShort(Pin *pin,
			    const Corner *corner,
			    const MinMax *min_max);
  void reportSlewLimitVerbose(Pin *pin,
			      const Corner *corner,
			      const MinMax *min_max);
  // requires checkSlewLimitPreamble()
  void checkSlew(const Pin *pin,
		 const Corner *corner,
		 const MinMax *min_max,
		 bool check_clks,
		 // Return values.
		 const Corner *&corner1,
		 const RiseFall *&tr,
		 Slew &slew,
		 float &limit,
		 float &slack);
  void maxSlewCheck(// Return values.
                    const Pin *&pin,
                    Slew &slew,
                    float &slack,
                    float &limit);
  void findSlewLimit(const LibertyPort *port,
                     const Corner *corner,
                     const MinMax *min_max,
                     // Return values.
                     float &limit,
                     bool &exists);

  void checkFanoutLimitPreamble();
  // Return pins with the min/max fanout limit slack.
  // net=null check all nets
  // corner=nullptr checks all corners.
  PinSeq checkFanoutLimits(Net *net,
                           bool violators,
                           const MinMax *min_max);
  void reportFanoutLimitShortHeader();
  void reportFanoutLimitShort(Pin *pin,
			      const MinMax *min_max);
  void reportFanoutLimitVerbose(Pin *pin,
				const MinMax *min_max);
  // requires checkFanoutLimitPreamble()
  void checkFanout(const Pin *pin,
		   const MinMax *min_max,
		   // Return values.
		   float &fanout,
		   float &limit,
		   float &slack);
  void maxFanoutCheck(// Return values.
                      const Pin *&pin,
                      float &fanout,
                      float &slack,
                      float &limit);

  void checkCapacitanceLimitPreamble();
  // Return pins with the min/max slew limit slack.
  // net=null check all nets
  // corner=nullptr checks all corners.
  PinSeq checkCapacitanceLimits(Net *net,
                                bool violators,
                                const Corner *corner,
                                const MinMax *min_max);
  void reportCapacitanceLimitShortHeader();
  void reportCapacitanceLimitShort(Pin *pin,
				   const Corner *corner,
				   const MinMax *min_max);
  void reportCapacitanceLimitVerbose(Pin *pin,
				     const Corner *corner,
				     const MinMax *min_max);
  // requires checkCapacitanceLimitPreamble()
  void checkCapacitance(const Pin *pin,
			const Corner *corner,
			const MinMax *min_max,
			// Return values.
			const Corner *&corner1,
			const RiseFall *&tr,
			float &capacitance,
			float &limit,
			float &slack);
  void maxCapacitanceCheck(// Return values.
                           const Pin *&pin,
                           float &capacitance,
                           float &slack,
                           float &limit);

  // Min pulse width check with the least slack.
  // corner=nullptr checks all corners.
  MinPulseWidthCheck *minPulseWidthSlack(const Corner *corner);
  // All violating min pulse width checks.
  // corner=nullptr checks all corners.
  MinPulseWidthCheckSeq &minPulseWidthViolations(const Corner *corner);
  // Min pulse width checks for pins.
  // corner=nullptr checks all corners.
  MinPulseWidthCheckSeq &minPulseWidthChecks(PinSeq *pins,
					     const Corner *corner);
  // All min pulse width checks.
  // corner=nullptr checks all corners.
  MinPulseWidthCheckSeq &minPulseWidthChecks(const Corner *corner);
  void reportMpwChecks(MinPulseWidthCheckSeq *checks,
		       bool verbose);
  void reportMpwCheck(MinPulseWidthCheck *check,
		      bool verbose);

  // Min period check with the least slack.
  MinPeriodCheck *minPeriodSlack();
  // All violating min period checks.
  MinPeriodCheckSeq &minPeriodViolations();
  void reportChecks(MinPeriodCheckSeq *checks,
		    bool verbose);
  void reportCheck(MinPeriodCheck *check,
		   bool verbose);

  // Max skew check with the least slack.
  MaxSkewCheck *maxSkewSlack();
  // All violating min period checks.
  MaxSkewCheckSeq &maxSkewViolations();
  void reportChecks(MaxSkewCheckSeq *checks,
		    bool verbose);
  void reportCheck(MaxSkewCheck *check,
		   bool verbose);

  
  ////////////////////////////////////////////////////////////////
  // User visible but non SDC commands.

  // Instance specific process/voltage/temperature.
  // Defaults to operating condition if instance is not annotated.
  const Pvt *pvt(Instance *inst,
                 const MinMax *min_max);
  void setPvt(Instance *inst,
	      const MinMaxAll *min_max,
	      float process,
	      float voltage,
	      float temperature);
  // Pvt may be shared among multiple instances.
  void setPvt(const Instance *inst,
	      const MinMaxAll *min_max,
	      const Pvt &pvt);
  void setVoltage(const MinMax *min_max,
                  float voltage);
  void setVoltage(const Net *net,
                  const MinMax *min_max,
                  float voltage);
  // Clear all state except network.
  virtual void clear();
  // Remove all constraints.
  virtual void removeConstraints();
  // Notify the sta that the constraints have changed directly rather
  // than thru this sta API.
  virtual void constraintsChanged();
  // Namespace used by command interpreter.
  CmdNamespace cmdNamespace();
  void setCmdNamespace(CmdNamespace namespc);
  OperatingConditions *operatingConditions(const MinMax *min_max) const;
  // Set the delay on a timing arc.
  // Required/arrival times are incrementally updated.
  void setArcDelay(Edge *edge,
		   TimingArc *arc,
		   const Corner *corner,
		   const MinMaxAll *min_max,
		   ArcDelay delay);
  // Set annotated slew on a vertex for delay calculation.
  void setAnnotatedSlew(Vertex *vertex,
			const Corner *corner,
			const MinMaxAll *min_max,
			const RiseFallBoth *rf,
			float slew);
  void writeSdf(const char *filename,
		const Corner *corner,
		char divider,
                bool include_typ,
		int digits,
		bool gzip,
		bool no_timestamp,
		bool no_version);
  // Remove all delay and slew annotations.
  void removeDelaySlewAnnotations();

  virtual CheckErrorSeq &checkTiming(bool no_input_delay,
				     bool no_output_delay,
				     bool reg_multiple_clks,
				     bool reg_no_clks,
				     bool unconstrained_endpoints,
				     bool loops,
				     bool generated_clks);
  // Path from/thrus/to filter.
  // from/thrus/to are owned and deleted by Search.
  // PathEnds in the returned PathEndSeq are owned by Search PathGroups
  // and deleted on next call.
  virtual PathEndSeq findPathEnds(ExceptionFrom *from,
                                  ExceptionThruSeq *thrus,
                                  ExceptionTo *to,
                                  bool unconstrained,
                                  // Use corner nullptr to report timing
                                  // for all corners.
                                  const Corner *corner,
                                  // max for setup checks.
                                  // min for hold checks.
                                  // min_max for setup and hold checks.
                                  const MinMaxAll *min_max,
                                  // Number of path ends to report in
                                  // each group.
                                  int group_path_count,
                                  // Number of paths to report for
                                  // each endpoint.
                                  int endpoint_path_count,
                                  // endpoint_path_count paths report unique pins
                                  // without rise/fall variations.
                                  bool unique_pins,
                                  // Min/max bounds for slack of
                                  // returned path ends.
                                  float slack_min,
                                  float slack_max,
                                  // Sort path ends by slack ignoring path groups.
                                  bool sort_by_slack,
                                  // Path groups to report.
                                  // Null or empty list reports all groups.
                                  PathGroupNameSet *group_names,
                                  // Predicates to filter the type of path
                                  // ends returned.
                                  bool setup,
                                  bool hold,
                                  bool recovery,
                                  bool removal,
                                  bool clk_gating_setup,
                                  bool clk_gating_hold);
  void setReportPathFormat(ReportPathFormat format);
  void setReportPathFieldOrder(StringSeq *field_names);
  void setReportPathFields(bool report_input_pin,
                           bool report_hier_pins,
			   bool report_net,
			   bool report_cap,
			   bool report_slew,
			   bool report_fanout,
			   bool report_src_attr);
  ReportField *findReportPathField(const char *name);
  void setReportPathDigits(int digits);
  void setReportPathNoSplit(bool no_split);
  void setReportPathSigmas(bool report_sigmas);
  // Header above reportPathEnd results.
  void reportPathEndHeader();
  // Footer below reportPathEnd results.
  void reportPathEndFooter();
  // Format report_path_endpoint only:
  //   Previous path end is used to detect path group changes
  //   so headers are reported by group.
  void reportPathEnd(PathEnd *end,
		     PathEnd *prev_end,
                     bool last);
  void reportPathEnd(PathEnd *end);
  void reportPathEnds(PathEndSeq *ends);
  ReportPath *reportPath() { return report_path_; }
  void reportPath(const Path *path);

  // Report clk skews for clks.
  void reportClkSkew(ConstClockSeq &clks,
		     const Corner *corner,
		     const SetupHold *setup_hold,
                     bool include_internal_latency,
		     int digits);
  float findWorstClkSkew(const SetupHold *setup_hold,
                         bool include_internal_latency);

  void reportClkLatency(ConstClockSeq &clks,
                        const Corner *corner,
                        bool include_internal_latency,
                        int digits);
  // Find min/max/rise/fall delays for clk.
  ClkDelays findClkDelays(const Clock *clk,
                          bool include_internal_latency);

  // Update arrival times for all pins.
  // If necessary updateTiming propagates arrivals around latch
  // loops until the arrivals converge.
  // If full=false update arrivals incrementally.
  // If full=true update all arrivals from scratch.
  // NOTE WELL: There is rarely any reason to call updateTiming directly because
  // arrival/required/slack functions implicitly update timing incrementally.
  // If you are calling this function you are either very confused or there is
  // bug that should be reported.
  void updateTiming(bool full);
  // Invalidate all delay calculations. Arrivals also invalidated.
  void delaysInvalid() const;
  // Invalidate all arrival and required times.
  void arrivalsInvalid();
  PinSet startpointPins();
  PinSet endpointPins();
  VertexSet *endpoints();
  int endpointViolationCount(const MinMax *min_max);
  // Find the fanin vertices for a group path.
  // Vertices in the clock network are NOT included.
  PinSet findGroupPathPins(const char *group_path_name);
  // Find all required times after updateTiming().
  void findRequireds();
  string reportDelayCalc(Edge *edge,
                         TimingArc *arc,
                         const Corner *corner,
                         const MinMax *min_max,
                         int digits);
  void writeSdc(const char *filename,
		// Map hierarchical pins and instances to leaf pins and instances.
		bool leaf,
		// Replace non-sdc get functions with OpenSTA equivalents.
		bool native,
		int digits,
                bool gzip,
		bool no_timestamp);
  // The sum of all negative endpoints slacks.
  // Incrementally updated.
  Slack totalNegativeSlack(const MinMax *min_max);
  Slack totalNegativeSlack(const Corner *corner,
			   const MinMax *min_max);
  // Worst endpoint slack and vertex.
  // Incrementally updated.
  Slack worstSlack(const MinMax *min_max);
  void worstSlack(const MinMax *min_max,
		  // Return values.
		  Slack &worst_slack,
		  Vertex *&worst_vertex);
  void worstSlack(const Corner *corner,
		  const MinMax *min_max,
		  // Return values.
		  Slack &worst_slack,
		  Vertex *&worst_vertex);
  VertexPathIterator *vertexPathIterator(Vertex *vertex,
					 const RiseFall *rf,
					 const PathAnalysisPt *path_ap);
  VertexPathIterator *vertexPathIterator(Vertex *vertex,
					 const RiseFall *rf,
					 const MinMax *min_max);
  Path *vertexWorstArrivalPath(Vertex *vertex,
                               const RiseFall *rf,
                               const MinMax *min_max);
  Path *vertexWorstArrivalPath(Vertex *vertex,
                               const MinMax *min_max);
  Path *vertexWorstRequiredPath(Vertex *vertex,
                                const RiseFall *rf,
                                const MinMax *min_max);
  Path *vertexWorstRequiredPath(Vertex *vertex,
                                const MinMax *min_max);
  Path *vertexWorstSlackPath(Vertex *vertex,
                             const MinMax *min_max);
  Path *vertexWorstSlackPath(Vertex *vertex,
                             const RiseFall *rf,
                             const MinMax *min_max);

  // Find the min clock period for rise/rise and fall/fall paths of a clock
  // using the slack. This does NOT correctly predict min period when there
  // are paths between different clocks.
  float findClkMinPeriod(const Clock *clk,
                         bool include_port_paths);

  // The following arrival/required/slack functions incrementally
  // update timing to the level of the vertex.  They do NOT do multiple
  // passes required propagate arrivals around latch loops.
  // See Sta::updateTiming() to propagate arrivals around latch loops.
  Arrival vertexArrival(Vertex *vertex,
			const RiseFall *rf,
			const ClockEdge *clk_edge,
			const PathAnalysisPt *path_ap,
                        const MinMax *min_max);
  // Min/max across all clock tags.
  Arrival vertexArrival(Vertex *vertex,
			const RiseFall *rf,
			const PathAnalysisPt *path_ap);
  Arrival vertexArrival(Vertex *vertex,
                        const MinMax *min_max);
  Arrival pinArrival(const Pin *pin,
                     const RiseFall *rf,
                     const MinMax *min_max);
  Required vertexRequired(Vertex *vertex,
			  const MinMax *min_max);
  Required vertexRequired(Vertex *vertex,
                          const RiseFall *rf,
                          const MinMax *min_max);
  // Min/max across all clock tags.
  Required vertexRequired(Vertex *vertex,
			  const RiseFall *rf,
			  const PathAnalysisPt *path_ap);
  Required vertexRequired(Vertex *vertex,
			  const RiseFall *rf,
			  const ClockEdge *clk_edge,
			  const PathAnalysisPt *path_ap);

  Slack netSlack(const Net *net,
		 const MinMax *min_max);
  Slack pinSlack(const Pin *pin,
		 const RiseFall *rf,
		 const MinMax *min_max);
  Slack pinSlack(const Pin *pin,
		 const MinMax *min_max);
  Slack vertexSlack(Vertex *vertex,
		    const MinMax *min_max);
  Slack vertexSlack(Vertex *vertex,
		    const RiseFall *rf,
		    const MinMax *min_max);
  // Slack with respect to clk_edge.
  Slack vertexSlack(Vertex *vertex,
		    const RiseFall *rf,
		    const ClockEdge *clk_edge,
		    const PathAnalysisPt *path_ap);
  // Min slack across all clock tags.
  Slack vertexSlack(Vertex *vertex,
		    const RiseFall *rf,
		    const PathAnalysisPt *path_ap);
  void vertexSlacks(Vertex *vertex,
		    Slack (&slacks)[RiseFall::index_count][MinMax::index_count]);
  // Slew for one corner.
  Slew vertexSlew(Vertex *vertex,
		  const RiseFall *rf,
		  const Corner *corner,
                  const MinMax *min_max);
  // Slew for one delay calc analysis pt (corner min/max).
  Slew vertexSlew(Vertex *vertex,
		  const RiseFall *rf,
		  const DcalcAnalysisPt *dcalc_ap);
  // Slew across all corners.
  Slew vertexSlew(Vertex *vertex,
		  const RiseFall *rf,
		  const MinMax *min_max);
  Slew vertexSlew(Vertex *vertex,
		  const MinMax *min_max);
  ArcDelay arcDelay(Edge *edge,
		    TimingArc *arc,
		    const DcalcAnalysisPt *dcalc_ap);
  // True if the timing arc has been back-annotated.
  bool arcDelayAnnotated(Edge *edge,
			 TimingArc *arc,
			 DcalcAnalysisPt *dcalc_ap);
  // Set/unset the back-annotation flag for a timing arc.
  void setArcDelayAnnotated(Edge *edge,
			    TimingArc *arc,
			    DcalcAnalysisPt *dcalc_ap,
			    bool annotated);
  // Make sure levels are up to date and return vertex level.
  Level vertexLevel(Vertex *vertex);
  GraphLoopSeq &graphLoops();
  PathAnalysisPt *pathAnalysisPt(Path *path);
  DcalcAnalysisPt *pathDcalcAnalysisPt(Path *path);
  TagIndex tagCount() const;
  TagGroupIndex tagGroupCount() const;
  int clkInfoCount() const;
  int pathCount() const;
  int vertexPathCount(Vertex  *vertex) const;
  Vertex *maxPathCountVertex() const;

  LogicValue simLogicValue(const Pin *pin);
  // Propagate liberty constant functions and pins tied high/low through
  // combinational logic and registers.
  void findLogicConstants();
  // Clear the constants found by findLogicConstants so they do not interfere
  // with normal constant propagate for timing.
  void clearLogicConstants();

  // Instances sorted by max driver pin slew.
  InstanceSeq slowDrivers(int count);

  // Make parasitic analysis points.
  // per_corner    ap_count
  //      false           2
  //       true   corners*2
  void setParasiticAnalysisPts(bool per_corner);
  // Annotate hierarchical "instance" with parasitics.
  // The parasitic analysis point is ap_name.
  // The parasitic memory footprint is much smaller if parasitic
  // networks (dspf) are reduced and deleted after reading each net
  // with reduce_to and delete_after_reduce.
  // Return true if successful.
  bool readSpef(const char *filename,
		Instance *instance,
		const Corner *corner,
                const MinMaxAll *min_max,
		bool pin_cap_included,
		bool keep_coupling_caps,
		float coupling_cap_factor,
		bool reduce);
  void reportParasiticAnnotation(bool report_unannotated,
                                 const Corner *corner);
  // Parasitics.
  void findPiElmore(Pin *drvr_pin,
		    const RiseFall *rf,
		    const MinMax *min_max,
		    float &c2,
		    float &rpi,
		    float &c1,
		    bool &exists) const;
  void findElmore(Pin *drvr_pin,
		  Pin *load_pin,
		  const RiseFall *rf,
		  const MinMax *min_max,
		  float &elmore,
		  bool &exists) const;
  void makePiElmore(Pin *drvr_pin,
		    const RiseFall *rf,
		    const MinMaxAll *min_max,
		    float c2,
		    float rpi,
		    float c1);
  void setElmore(Pin *drvr_pin,
		 Pin *load_pin,
		 const RiseFall *rf,
		 const MinMaxAll *min_max,
		 float elmore);
  void deleteParasitics();
  Parasitic *makeParasiticNetwork(const Net *net,
                                  bool includes_pin_caps,
                                  const ParasiticAnalysisPt *ap);

  ////////////////////////////////////////////////////////////////
  // TCL network edit function support.

  virtual Instance *makeInstance(const char *name,
				 LibertyCell *cell,
				 Instance *parent);
  virtual void deleteInstance(Instance *inst);
  // replace_cell
  virtual void replaceCell(Instance *inst,
			   Cell *to_cell);
  virtual void replaceCell(Instance *inst,
			   LibertyCell *to_lib_cell);
  virtual Net *makeNet(const char *name,
		       Instance *parent);
  virtual void deleteNet(Net *net);
  // connect_net
  virtual void connectPin(Instance *inst,
			  Port *port,
			  Net *net);
  virtual void connectPin(Instance *inst,
			  LibertyPort *port,
			  Net *net);
  // disconnect_net
  virtual void disconnectPin(Pin *pin);
  virtual void makePortPin(const char *port_name,
                           PortDirection *dir);
  // Notify STA of network change.
  void networkChanged();
  void deleteLeafInstanceBefore(const Instance *inst);
  void deleteInstancePinsBefore(const Instance *inst);

  // Network edit before/after methods.
  void makeInstanceAfter(const Instance *inst);
  // Replace the instance cell with to_cell.
  // equivCells(from_cell, to_cell) must be true.
  virtual void replaceEquivCellBefore(const Instance *inst,
				      const LibertyCell *to_cell);
  virtual void replaceEquivCellAfter(const Instance *inst);
  // Replace the instance cell with to_cell.
  // equivCellPorts(from_cell, to_cell) must be true.
  virtual void replaceCellBefore(const Instance *inst,
				 const LibertyCell *to_cell);
  virtual void replaceCellAfter(const Instance *inst);
  virtual void makePortPinAfter(Pin *pin);
  virtual void connectPinAfter(const Pin *pin);
  virtual void disconnectPinBefore(const Pin *pin);
  virtual void deleteNetBefore(const Net *net);
  virtual void deleteInstanceBefore(const Instance *inst);
  virtual void deletePinBefore(const Pin *pin);

  ////////////////////////////////////////////////////////////////

  void ensureClkNetwork();
  void clkPinsInvalid();
  // The following functions assume ensureClkNetwork() has been called.
  bool isClock(const Pin *pin) const;
  bool isClock(const Net *net) const;
  bool isIdealClock(const Pin *pin) const;
  bool isPropagatedClock(const Pin *pin) const;
  const PinSet *pins(const Clock *clk);

  ////////////////////////////////////////////////////////////////

  void setTclInterp(Tcl_Interp *interp);
  Tcl_Interp *tclInterp();
  // Ensure a network has been read, and linked.
  Network *ensureLinked();
  // Ensure a network has been read, linked and liberty libraries exist.
  Network *ensureLibLinked();
  void ensureLevelized();
  // Ensure that the timing graph has been built.
  Graph *ensureGraph();
  void ensureClkArrivals();
  Corner *cmdCorner() const;
  void setCmdCorner(Corner *corner);
  Corner *findCorner(const char *corner_name);
  bool multiCorner();
  virtual void makeCorners(StringSet *corner_names);
  // Find all arc delays and vertex slews with delay calculator.
  virtual void findDelays();
  // Find arc delays and vertex slews thru to level of to_vertex.
  virtual void findDelays(Vertex *to_vertex);
  // Find arc delays and vertex slews thru to level.
  virtual void findDelays(Level level);
  // Percentage (0.0:1.0) change in delay that causes downstream
  // delays to be recomputed during incremental delay calculation.
  // Defaults to 0.0 for maximum accuracy and slowest incremental speed.
  void setIncrementalDelayTolerance(float tol);
  // Make graph and find delays.
  void searchPreamble();

  // Define the delay calculator implementation.
  void setArcDelayCalc(const char *delay_calc_name);

  void setDebugLevel(const char *what,
		     int level);

  // Delays and arrivals downsteam from inst are invalid.
  void delaysInvalidFrom(const Instance *inst);
  // Delays and arrivals downsteam from pin are invalid.
  void delaysInvalidFrom(const Pin *pin);
  void delaysInvalidFrom(Vertex *vertex);
  // Delays to driving pins of net (fanin) are invalid.
  // Arrivals downsteam from net are invalid.
  void delaysInvalidFromFanin(const Net *net);
  void delaysInvalidFromFanin(const Pin *pin);
  void delaysInvalidFromFanin(Vertex *vertex);
  void replaceCellPinInvalidate(const LibertyPort *from_port,
				Vertex *vertex,
				const LibertyCell *to_cell);

  // Power API.
  Power *power() { return power_; }
  const Power *power() const { return power_; }
  void power(const Corner *corner,
	     // Return values.
	     PowerResult &total,
	     PowerResult &sequential,
  	     PowerResult &combinational,
  	     PowerResult &clock,
	     PowerResult &macro,
	     PowerResult &pad);
  PowerResult power(const Instance *inst,
                    const Corner *corner);
  PwrActivity activity(const Pin *pin);

  void writeTimingModel(const char *lib_name,
                        const char *cell_name,
                        const char *filename,
                        const Corner *corner);

  // Find equivalent cells in equiv_libs.
  // Optionally add mappings for cells in map_libs.
  void makeEquivCells(LibertyLibrarySeq *equiv_libs,
		      LibertyLibrarySeq *map_libs);
  LibertyCellSeq *equivCells(LibertyCell *cell);

  void writePathSpice(Path *path,
                      const char *spice_filename,
                      const char *subckt_filename,
                      const char *lib_subckt_filename,
                      const char *model_filename,
                      const char *power_name,
                      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();
  virtual void makeNetwork();
  virtual void makeSdcNetwork();
  virtual void makeSdc();
  virtual void makeGraph();
  virtual void makeCorners();
  virtual void makeLevelize();
  virtual void makeParasitics();
  virtual void makeArcDelayCalc();
  virtual void makeGraphDelayCalc();
  virtual void makeSim();
  virtual void makeSearch();
  virtual void makeLatches(); 
  virtual void makeClkNetwork();
  virtual void makeCheckTiming();
  virtual void makeCheckSlewLimits();
  virtual void makeCheckFanoutLimits();
  virtual void makeCheckCapacitanceLimits();
  virtual void makeCheckMinPulseWidths();
  virtual void makeCheckMinPeriods();
  virtual void makeCheckMaxSkews();
  virtual void makeReportPath();
  virtual void makePower();
  virtual void makeObservers();
  NetworkEdit *networkCmdEdit();

  LibertyLibrary *readLibertyFile(const char *filename,
				  Corner *corner,
				  const MinMaxAll *min_max,
				  bool infer_latches);
  // Allow external Liberty reader to parse forms not used by Sta.
  virtual LibertyLibrary *readLibertyFile(const char *filename,
					  bool infer_latches);
  void delayCalcPreamble();
  void delaysInvalidFrom(const Port *port);
  void delaysInvalidFromFanin(const Port *port);
  void deleteEdge(Edge *edge);
  void netParasiticCaps(Net *net,
			const RiseFall *rf,
			const MinMax *min_max,
			float &pin_cap,
			float &wire_cap) const;
  const Pin *findNetParasiticDrvrPin(const Net *net) const;
  void exprConstantPins(FuncExpr *expr,
			const Instance *inst,
			PinSet &pins);
  Slack vertexSlack1(Vertex *vertex,
		     const RiseFall *rf,
		     const ClockEdge *clk_edge,
		     const PathAnalysisPt *path_ap);
  void findRequired(Vertex *vertex);
  Required vertexRequired(Vertex *vertex,
                          const RiseFall *rf,
                          const ClockEdge *clk_edge,
                          const PathAnalysisPt *path_ap,
                          const MinMax *min_max);
  void connectDrvrPinAfter(Vertex *vertex);
  void connectLoadPinAfter(Vertex *vertex);
  Path *latchEnablePath(Path *q_path,
			Edge *d_q_edge,
			const ClockEdge *en_clk_edge);
  void clockSlewChanged(Clock *clk);
  void minPulseWidthPreamble();
  void minPeriodPreamble();
  void maxSkewPreamble();
  bool idealClockMode();
  void disableAfter();
  void findFaninPins(Vertex *vertex,
		     bool flat,
		     bool startpoints_only,
		     int inst_levels,
		     int pin_levels,
		     PinSet &fanin,
		     SearchPred &pred);
  void findFaninPins(Vertex *to,
		     bool flat,
		     int inst_levels,
		     int pin_levels,
		     VertexSet &visited,
		     SearchPred *pred,
		     int inst_level,
		     int pin_level);
  void findFanoutPins(Vertex *vertex,
		      bool flat,
		      bool endpoints_only,
		      int inst_levels,
		      int pin_levels,
		      PinSet &fanout,
		      SearchPred &pred);
  void findFanoutPins(Vertex *from,
		      bool flat,
		      int inst_levels,
		      int pin_levels,
		      VertexSet &visited,
		      SearchPred *pred,
		      int inst_level,
		      int pin_level);
  void findRegisterPreamble();
  bool crossesHierarchy(Edge *edge) const;
  void readLibertyAfter(LibertyLibrary *liberty,
			Corner *corner,
			const MinMax *min_max);
  void powerPreamble();
  void disableFanoutCrprPruning(Vertex *vertex,
				int &fanou);
  virtual void replaceCell(Instance *inst,
                           Cell *to_cell,
                           LibertyCell *to_lib_cell);
  void sdcChangedGraph();
  void ensureGraphSdcAnnotated();
  CornerSeq makeCornerSeq(Corner *corner) const;
  void makeParasiticAnalysisPts();
  void clkSkewPreamble();
  void setCmdNamespace1(CmdNamespace namespc);
  void setThreadCount1(int thread_count);

  CmdNamespace cmd_namespace_;
  Instance *current_instance_;
  Corner *cmd_corner_;
  VerilogReader *verilog_reader_;
  CheckTiming *check_timing_;
  CheckSlewLimits *check_slew_limits_;
  CheckFanoutLimits *check_fanout_limits_;
  CheckCapacitanceLimits *check_capacitance_limits_;
  CheckMinPulseWidths *check_min_pulse_widths_;
  CheckMinPeriods *check_min_periods_;
  CheckMaxSkews *check_max_skews_;
  ClkSkews *clk_skews_;
  ReportPath *report_path_;
  Power *power_;
  Tcl_Interp *tcl_interp_;
  bool update_genclks_;
  EquivCells *equiv_cells_;
  bool graph_sdc_annotated_;
  bool parasitics_per_corner_;
  bool parasitics_per_min_max_;

  // Singleton sta used by tcl command interpreter.
  static Sta *sta_;
};

} // namespace
