1 // OpenSTA, Static Timing Analyzer
2 // Copyright (c) 2021, Parallax Software, Inc.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 
17 #include "Sta.hh"
18 
19 #include "Machine.hh"
20 #include "DispatchQueue.hh"
21 #include "ReportTcl.hh"
22 #include "Debug.hh"
23 #include "Stats.hh"
24 #include "Fuzzy.hh"
25 #include "Units.hh"
26 #include "TimingArc.hh"
27 #include "FuncExpr.hh"
28 #include "EquivCells.hh"
29 #include "Liberty.hh"
30 #include "liberty/LibertyReader.hh"
31 #include "SdcNetwork.hh"
32 #include "MakeConcreteNetwork.hh"
33 #include "PortDirection.hh"
34 #include "VerilogReader.hh"
35 #include "Graph.hh"
36 #include "GraphCmp.hh"
37 #include "Sdc.hh"
38 #include "WriteSdc.hh"
39 #include "ExceptionPath.hh"
40 #include "MakeConcreteParasitics.hh"
41 #include "Parasitics.hh"
42 #include "parasitics/SpefReader.hh"
43 #include "DelayCalc.hh"
44 #include "ArcDelayCalc.hh"
45 #include "dcalc/GraphDelayCalc1.hh"
46 #include "sdf/SdfWriter.hh"
47 #include "Levelize.hh"
48 #include "Sim.hh"
49 #include "ClkInfo.hh"
50 #include "TagGroup.hh"
51 #include "PathAnalysisPt.hh"
52 #include "Corner.hh"
53 #include "Search.hh"
54 #include "Latches.hh"
55 #include "PathGroup.hh"
56 #include "CheckTiming.hh"
57 #include "CheckSlewLimits.hh"
58 #include "CheckFanoutLimits.hh"
59 #include "CheckCapacitanceLimits.hh"
60 #include "CheckMinPulseWidths.hh"
61 #include "CheckMinPeriods.hh"
62 #include "CheckMaxSkews.hh"
63 #include "ClkSkew.hh"
64 #include "FindRegister.hh"
65 #include "ReportPath.hh"
66 #include "VisitPathGroupVertices.hh"
67 #include "Genclks.hh"
68 #include "ClkNetwork.hh"
69 #include "Power.hh"
70 
71 namespace sta {
72 
73 using std::min;
74 
75 static const ClockEdge *clk_edge_wildcard = reinterpret_cast<ClockEdge*>(1);
76 
77 static bool
78 libertyPortCapsEqual(LibertyPort *port1,
79 		     LibertyPort *port2);
80 static bool
81 hasDisabledArcs(Edge *edge,
82 		Graph *graph);
83 static InstanceSet *
84 pinInstances(PinSet *pins,
85 	     const Network *network);
86 
87 ////////////////////////////////////////////////////////////////
88 //
89 // Observers are used to propagate updates from a component
90 // to other components.
91 //
92 ////////////////////////////////////////////////////////////////
93 
94 // When an incremental change is made the delay calculation
95 // changes downstream.  This invalidates the required times
96 // for all vertices upstream of the changes.
97 class StaDelayCalcObserver : public DelayCalcObserver
98 {
99 public:
100   explicit StaDelayCalcObserver(Search *search);
101   virtual void delayChangedFrom(Vertex *vertex);
102   virtual void delayChangedTo(Vertex *vertex);
103   virtual void checkDelayChangedTo(Vertex *vertex);
104 
105 private:
106   DISALLOW_COPY_AND_ASSIGN(StaDelayCalcObserver);
107 
108   Search *search_;
109 };
110 
StaDelayCalcObserver(Search * search)111 StaDelayCalcObserver::StaDelayCalcObserver(Search *search) :
112   DelayCalcObserver(),
113   search_(search)
114 {
115 }
116 
117 void
delayChangedFrom(Vertex * vertex)118 StaDelayCalcObserver::delayChangedFrom(Vertex *vertex)
119 {
120   search_->requiredInvalid(vertex);
121 }
122 
123 void
delayChangedTo(Vertex * vertex)124 StaDelayCalcObserver::delayChangedTo(Vertex *vertex)
125 {
126   search_->arrivalInvalid(vertex);
127 }
128 
129 void
checkDelayChangedTo(Vertex * vertex)130 StaDelayCalcObserver::checkDelayChangedTo(Vertex *vertex)
131 {
132   search_->requiredInvalid(vertex);
133 }
134 
135 ////////////////////////////////////////////////////////////////
136 
137 class StaSimObserver : public SimObserver
138 {
139 public:
140   StaSimObserver(GraphDelayCalc *graph_delay_calc,
141 		 Levelize *levelize,
142 		 Search *search);
143   virtual void valueChangeAfter(Vertex *vertex);
144   virtual void faninEdgesChangeAfter(Vertex *vertex);
145   virtual void fanoutEdgesChangeAfter(Vertex *vertex);
146 
147 private:
148   DISALLOW_COPY_AND_ASSIGN(StaSimObserver);
149 
150   GraphDelayCalc *graph_delay_calc_;
151   Levelize *levelize_;
152   Search *search_;
153 };
154 
StaSimObserver(GraphDelayCalc * graph_delay_calc,Levelize * levelize,Search * search)155 StaSimObserver::StaSimObserver(GraphDelayCalc *graph_delay_calc,
156 			       Levelize *levelize,
157 			       Search *search) :
158   SimObserver(),
159   graph_delay_calc_(graph_delay_calc),
160   levelize_(levelize),
161   search_(search)
162 {
163 }
164 
165 // When pins with constant values are incrementally connected to a net
166 // the downstream delays and arrivals will not be updated (removed)
167 // because the search predicate does not search through constants.
168 // This observer makes sure the delays and arrivals are invalidated.
169 void
valueChangeAfter(Vertex * vertex)170 StaSimObserver::valueChangeAfter(Vertex *vertex)
171 {
172   graph_delay_calc_->delayInvalid(vertex);
173   search_->arrivalInvalid(vertex);
174   search_->requiredInvalid(vertex);
175   search_->endpointInvalid(vertex);
176   levelize_->invalidFrom(vertex);
177 }
178 
179 void
faninEdgesChangeAfter(Vertex * vertex)180 StaSimObserver::faninEdgesChangeAfter(Vertex *vertex)
181 {
182   graph_delay_calc_->delayInvalid(vertex);
183   search_->arrivalInvalid(vertex);
184   search_->endpointInvalid(vertex);
185 }
186 
187 void
fanoutEdgesChangeAfter(Vertex * vertex)188 StaSimObserver::fanoutEdgesChangeAfter(Vertex *vertex)
189 {
190   search_->requiredInvalid(vertex);
191   search_->endpointInvalid(vertex);
192 }
193 
194 ////////////////////////////////////////////////////////////////
195 
196 class StaLevelizeObserver : public LevelizeObserver
197 {
198 public:
199   StaLevelizeObserver(Search *search);
200   virtual void levelChangedBefore(Vertex *vertex);
201 
202 private:
203   DISALLOW_COPY_AND_ASSIGN(StaLevelizeObserver);
204 
205   Search *search_;
206 };
207 
StaLevelizeObserver(Search * search)208 StaLevelizeObserver::StaLevelizeObserver(Search *search) :
209   search_(search)
210 {
211 }
212 
213 void
levelChangedBefore(Vertex * vertex)214 StaLevelizeObserver::levelChangedBefore(Vertex *vertex)
215 {
216   search_->levelChangedBefore(vertex);
217 }
218 
219 ////////////////////////////////////////////////////////////////
220 
221 void
initSta()222 initSta()
223 {
224   initElapsedTime();
225   TimingRole::init();
226   PortDirection::init();
227   initTmpStrings();
228   initLiberty();
229   initDelayConstants();
230   registerDelayCalcs();
231   initPathSenseThru();
232 }
233 
234 void
deleteAllMemory()235 deleteAllMemory()
236 {
237   // Verilog modules refer to the network in the sta so it has
238   // to deleted before the sta.
239   deleteVerilogReader();
240   Sta *sta = Sta::sta();
241   if (sta) {
242     delete sta;
243     Sta::setSta(nullptr);
244   }
245   deleteDelayCalcs();
246   deleteTmpStrings();
247   TimingRole::destroy();
248   PortDirection::destroy();
249   deleteLiberty();
250 }
251 
252 ////////////////////////////////////////////////////////////////
253 
254 // Singleton used by TCL commands.
255 Sta *Sta::sta_;
256 
Sta()257 Sta::Sta() :
258   StaState(),
259   current_instance_(nullptr),
260   check_timing_(nullptr),
261   check_slew_limits_(nullptr),
262   check_fanout_limits_(nullptr),
263   check_capacitance_limits_(nullptr),
264   check_min_pulse_widths_(nullptr),
265   check_min_periods_(nullptr),
266   check_max_skews_(nullptr),
267   clk_skews_(nullptr),
268   report_path_(nullptr),
269   power_(nullptr),
270   link_make_black_boxes_(true),
271   update_genclks_(false),
272   equiv_cells_(nullptr),
273   graph_sdc_annotated_(false),
274   // Default to same parasitics for each corner min/max.
275   parasitics_per_corner_(false),
276   parasitics_per_min_max_(false)
277 {
278 }
279 
280 void
makeComponents()281 Sta::makeComponents()
282 {
283   makeReport();
284   makeDebug();
285   makeUnits();
286   makeNetwork();
287   makeSdc();
288   makeLevelize();
289   makeParasitics();
290   makeCorners();
291   makeArcDelayCalc();
292   makeGraphDelayCalc();
293   makeSim();
294   makeSearch();
295   makeLatches();
296   makeClkNetwork();
297   makeSdcNetwork();
298   makeReportPath();
299   makePower();
300   setCmdNamespace(CmdNamespace::sdc);
301   updateComponentsState();
302 
303   makeObservers();
304   // This must follow updateComponentsState.
305   makeParasiticAnalysisPts();
306   setThreadCount(defaultThreadCount());
307 }
308 
309 void
makeObservers()310 Sta::makeObservers()
311 {
312   graph_delay_calc_->setObserver(new StaDelayCalcObserver(search_));
313   sim_->setObserver(new StaSimObserver(graph_delay_calc_, levelize_, search_));
314   levelize_->setObserver(new StaLevelizeObserver(search_));
315 }
316 
317 int
defaultThreadCount() const318 Sta::defaultThreadCount() const
319 {
320   return 1;
321 }
322 
323 void
setThreadCount(int thread_count)324 Sta::setThreadCount(int thread_count)
325 {
326   thread_count_ = thread_count;
327   if (dispatch_queue_)
328     dispatch_queue_->setThreadCount(thread_count);
329   else if (thread_count > 1)
330     dispatch_queue_ = new DispatchQueue(thread_count);
331   updateComponentsState();
332 }
333 
334 void
updateComponentsState()335 Sta::updateComponentsState()
336 {
337   // These components do not use StaState:
338   //  units_
339   network_->copyState(this);
340   cmd_network_->copyState(this);
341   sdc_network_->copyState(this);
342   if (graph_)
343     graph_->copyState(this);
344   sdc_->copyState(this);
345   corners_->copyState(this);
346   levelize_->copyState(this);
347   parasitics_->copyState(this);
348   if (arc_delay_calc_)
349     arc_delay_calc_->copyState(this);
350   sim_->copyState(this);
351   search_->copyState(this);
352   latches_->copyState(this);
353   graph_delay_calc_->copyState(this);
354   report_path_->copyState(this);
355   if (check_timing_)
356     check_timing_->copyState(this);
357   clk_network_->copyState(this);
358   if (power_)
359     power_->copyState(this);
360 }
361 
362 void
makeReport()363 Sta::makeReport()
364 {
365   report_ = new ReportTcl();
366 }
367 
368 void
makeDebug()369 Sta::makeDebug()
370 {
371   debug_ = new Debug(report_);
372 }
373 
374 void
makeUnits()375 Sta::makeUnits()
376 {
377   units_ = new Units();
378 }
379 
380 void
makeNetwork()381 Sta::makeNetwork()
382 {
383   network_ = makeConcreteNetwork();
384 }
385 
386 void
makeSdc()387 Sta::makeSdc()
388 {
389   sdc_ = new Sdc(this);
390 }
391 
392 void
makeLevelize()393 Sta::makeLevelize()
394 {
395   levelize_ = new Levelize(this);
396 }
397 
398 void
makeParasitics()399 Sta::makeParasitics()
400 {
401   parasitics_ = makeConcreteParasitics(this);
402 }
403 
404 void
makeArcDelayCalc()405 Sta::makeArcDelayCalc()
406 {
407   arc_delay_calc_ = makeDelayCalc("dmp_ceff_elmore", this);
408 }
409 
410 void
makeGraphDelayCalc()411 Sta::makeGraphDelayCalc()
412 {
413   graph_delay_calc_ = new GraphDelayCalc1(this);
414 }
415 
416 void
makeSim()417 Sta::makeSim()
418 {
419   sim_ = new Sim(this);
420 }
421 
422 void
makeSearch()423 Sta::makeSearch()
424 {
425   search_ = new Search(this);
426 }
427 
428 void
makeLatches()429 Sta::makeLatches()
430 {
431   latches_ = new Latches(this);
432 }
433 
434 void
makeSdcNetwork()435 Sta::makeSdcNetwork()
436 {
437   sdc_network_ = sta::makeSdcNetwork(network_);
438 }
439 
440 void
makeCheckTiming()441 Sta::makeCheckTiming()
442 {
443   check_timing_ = new CheckTiming(this);
444 }
445 
446 void
makeCheckSlewLimits()447 Sta::makeCheckSlewLimits()
448 {
449   check_slew_limits_ = new CheckSlewLimits(this);
450 }
451 
452 void
makeCheckFanoutLimits()453 Sta::makeCheckFanoutLimits()
454 {
455   check_fanout_limits_ = new CheckFanoutLimits(this);
456 }
457 
458 void
makeCheckCapacitanceLimits()459 Sta::makeCheckCapacitanceLimits()
460 {
461   check_capacitance_limits_ = new CheckCapacitanceLimits(this);
462 }
463 
464 void
makeCheckMinPulseWidths()465 Sta::makeCheckMinPulseWidths()
466 {
467   check_min_pulse_widths_ = new CheckMinPulseWidths(this);
468 }
469 
470 void
makeCheckMinPeriods()471 Sta::makeCheckMinPeriods()
472 {
473   check_min_periods_ = new CheckMinPeriods(this);
474 }
475 
476 void
makeCheckMaxSkews()477 Sta::makeCheckMaxSkews()
478 {
479   check_max_skews_ = new CheckMaxSkews(this);
480 }
481 
482 void
makeReportPath()483 Sta::makeReportPath()
484 {
485   report_path_ = new ReportPath(this);
486 }
487 
488 void
makeClkNetwork()489 Sta::makeClkNetwork()
490 {
491   clk_network_ = new ClkNetwork(this);
492 }
493 
494 void
makePower()495 Sta::makePower()
496 {
497   power_ = new Power(this);
498 }
499 
500 void
setSta(Sta * sta)501 Sta::setSta(Sta *sta)
502 {
503   sta_ = sta;
504 }
505 
506 Sta *
sta()507 Sta::sta()
508 {
509   return sta_;
510 }
511 
~Sta()512 Sta::~Sta()
513 {
514   // Delete "top down" to minimize chance of referencing deleted memory.
515   delete check_slew_limits_;
516   delete check_fanout_limits_;
517   delete check_capacitance_limits_;
518   delete check_min_pulse_widths_;
519   delete check_min_periods_;
520   delete check_max_skews_;
521   delete clk_skews_;
522   delete check_timing_;
523   delete report_path_;
524   // Constraints reference search filter, so delete search first.
525   delete search_;
526   delete latches_;
527   delete parasitics_;
528   if (arc_delay_calc_)
529     delete arc_delay_calc_;
530   delete graph_delay_calc_;
531   delete sim_;
532   delete levelize_;
533   delete sdc_;
534   delete corners_;
535   delete graph_;
536   delete sdc_network_;
537   delete network_;
538   delete debug_;
539   delete units_;
540   delete report_;
541   delete clk_network_;
542   delete power_;
543   delete equiv_cells_;
544   delete dispatch_queue_;
545 }
546 
547 void
clear()548 Sta::clear()
549 {
550   clkPinsInvalid();
551   // Constraints reference search filter, so clear search first.
552   search_->clear();
553   sdc_->clear();
554   graph_sdc_annotated_ = false;
555   // corners are NOT cleared because they are used to index liberty files.
556   levelize_->clear();
557   if (parasitics_)
558     parasitics_->clear();
559   graph_delay_calc_->clear();
560   sim_->clear();
561   if (check_min_pulse_widths_)
562     check_min_pulse_widths_->clear();
563   if (check_min_periods_)
564     check_min_periods_->clear();
565   delete graph_;
566   graph_ = nullptr;
567   current_instance_ = nullptr;
568   // Notify components that graph is toast.
569   updateComponentsState();
570 }
571 
572 void
networkChanged()573 Sta::networkChanged()
574 {
575   // Everything else from clear().
576   search_->clear();
577   levelize_->clear();
578   if (parasitics_)
579     parasitics_->clear();
580   graph_delay_calc_->clear();
581   sim_->clear();
582   if (check_min_pulse_widths_)
583     check_min_pulse_widths_->clear();
584   if (check_min_periods_)
585     check_min_periods_->clear();
586   delete graph_;
587   graph_ = nullptr;
588   graph_sdc_annotated_ = false;
589   current_instance_ = nullptr;
590   updateComponentsState();
591 }
592 
593 void
setTclInterp(Tcl_Interp * interp)594 Sta::setTclInterp(Tcl_Interp *interp)
595 {
596   tcl_interp_ = interp;
597   report_->setTclInterp(interp);
598 }
599 
600 Tcl_Interp *
tclInterp()601 Sta::tclInterp()
602 {
603   return tcl_interp_;
604 }
605 
606 CmdNamespace
cmdNamespace()607 Sta::cmdNamespace()
608 {
609   return cmd_namespace_;
610 }
611 
612 void
setCmdNamespace(CmdNamespace namespc)613 Sta::setCmdNamespace(CmdNamespace namespc)
614 {
615   cmd_namespace_ = namespc;
616   switch (cmd_namespace_) {
617   case CmdNamespace::sta:
618     cmd_network_ = network_;
619     break;
620   case CmdNamespace::sdc:
621     cmd_network_ = sdc_network_;
622     break;
623   }
624   updateComponentsState();
625 }
626 
627 Instance *
currentInstance() const628 Sta::currentInstance() const
629 {
630   if (current_instance_ == nullptr)
631     return network_->topInstance();
632   else
633     return current_instance_;
634 }
635 
636 void
setCurrentInstance(Instance * inst)637 Sta::setCurrentInstance(Instance *inst)
638 {
639   current_instance_ = inst;
640 }
641 
642 ////////////////////////////////////////////////////////////////
643 
644 LibertyLibrary *
readLiberty(const char * filename,Corner * corner,const MinMaxAll * min_max,bool infer_latches)645 Sta::readLiberty(const char *filename,
646 		 Corner *corner,
647 		 const MinMaxAll *min_max,
648 		 bool infer_latches)
649 {
650   Stats stats(debug_, report_);
651   LibertyLibrary *library = readLibertyFile(filename, corner, min_max,
652 					    infer_latches, network_);
653   if (library
654       // The default library is the first library read.
655       // This corresponds to a link_path of '*'.
656       && network_->defaultLibertyLibrary() == nullptr) {
657     network_->setDefaultLibertyLibrary(library);
658     // Set units from default (first) library.
659     *units_ = *library->units();
660   }
661   stats.report("Read liberty");
662   return library;
663 }
664 
665 LibertyLibrary *
readLibertyFile(const char * filename,Corner * corner,const MinMaxAll * min_max,bool infer_latches,Network * network)666 Sta::readLibertyFile(const char *filename,
667 		     Corner *corner,
668 		     const MinMaxAll *min_max,
669 		     bool infer_latches,
670 		     Network *network)
671 {
672   LibertyLibrary *liberty = sta::readLibertyFile(filename, infer_latches,
673 						 network);
674   if (liberty) {
675     // Don't map liberty cells if they are redefined by reading another
676     // library with the same cell names.
677     if (min_max == MinMaxAll::all()) {
678       readLibertyAfter(liberty, corner, MinMax::min());
679       readLibertyAfter(liberty, corner, MinMax::max());
680     }
681     else
682       readLibertyAfter(liberty, corner, min_max->asMinMax());
683     network_->readLibertyAfter(liberty);
684   }
685   return liberty;
686 }
687 
688 LibertyLibrary *
readLibertyFile(const char * filename,bool infer_latches,Network * network)689 Sta::readLibertyFile(const char *filename,
690 		     bool infer_latches,
691 		     Network *network)
692 {
693   return sta::readLibertyFile(filename, infer_latches, network);
694 }
695 
696 void
readLibertyAfter(LibertyLibrary * liberty,Corner * corner,const MinMax * min_max)697 Sta::readLibertyAfter(LibertyLibrary *liberty,
698 		      Corner *corner,
699 		      const MinMax *min_max)
700 {
701   corner->addLiberty(liberty, min_max);
702   LibertyLibrary::makeCornerMap(liberty, corner->libertyIndex(min_max),
703 				network_, report_);
704 }
705 
706 bool
setMinLibrary(const char * min_filename,const char * max_filename)707 Sta::setMinLibrary(const char *min_filename,
708 		   const char *max_filename)
709 {
710   LibertyLibrary *max_lib = network_->findLibertyFilename(max_filename);
711   if (max_lib) {
712     LibertyLibrary *min_lib = readLibertyFile(min_filename, cmd_corner_,
713 					      MinMaxAll::min(), false,
714 					      network_);
715     return min_lib != nullptr;
716   }
717   else
718     return false;
719 }
720 
721 void
readNetlistBefore()722 Sta::readNetlistBefore()
723 {
724   clear();
725   NetworkReader *network_reader = networkReader();
726   if (network_reader)
727     network_reader->readNetlistBefore();
728 }
729 
730 bool
linkDesign(const char * top_cell_name)731 Sta::linkDesign(const char *top_cell_name)
732 {
733   clear();
734   Stats stats(debug_, report_);
735   bool status = network_->linkNetwork(top_cell_name,
736 				      link_make_black_boxes_,
737 				      report_);
738   stats.report("Link");
739   return status;
740 }
741 
742 bool
linkMakeBlackBoxes() const743 Sta::linkMakeBlackBoxes() const
744 {
745   return link_make_black_boxes_;
746 }
747 
748 void
setLinkMakeBlackBoxes(bool make)749 Sta::setLinkMakeBlackBoxes(bool make)
750 {
751   link_make_black_boxes_ = make;
752 }
753 
754 ////////////////////////////////////////////////////////////////
755 
756 void
setDebugLevel(const char * what,int level)757 Sta::setDebugLevel(const char *what,
758 		   int level)
759 {
760   debug_->setLevel(what, level);
761 }
762 
763 ////////////////////////////////////////////////////////////////
764 
765 void
setAnalysisType(AnalysisType analysis_type)766 Sta::setAnalysisType(AnalysisType analysis_type)
767 {
768   if (analysis_type != sdc_->analysisType()) {
769     sdc_->setAnalysisType(analysis_type);
770     graph_delay_calc_->delaysInvalid();
771     search_->arrivalsInvalid();
772     search_->deletePathGroups();
773     corners_->analysisTypeChanged();
774     if (graph_)
775       graph_->setDelayCount(corners_->dcalcAnalysisPtCount());
776   }
777 }
778 
779 OperatingConditions *
operatingConditions(const MinMax * min_max) const780 Sta::operatingConditions(const MinMax *min_max) const
781 {
782   return sdc_->operatingConditions(min_max);
783 }
784 
785 void
setOperatingConditions(OperatingConditions * op_cond,const MinMaxAll * min_max)786 Sta::setOperatingConditions(OperatingConditions *op_cond,
787 			    const MinMaxAll *min_max)
788 {
789   sdc_->setOperatingConditions(op_cond, min_max);
790   corners_->operatingConditionsChanged();
791   graph_delay_calc_->delaysInvalid();
792   search_->arrivalsInvalid();
793 }
794 
795 Pvt *
pvt(Instance * inst,const MinMax * min_max)796 Sta::pvt(Instance *inst,
797 	 const MinMax *min_max)
798 {
799   return sdc_->pvt(inst, min_max);
800 }
801 
802 void
setPvt(Instance * inst,const MinMaxAll * min_max,float process,float voltage,float temperature)803 Sta::setPvt(Instance *inst,
804 	    const MinMaxAll *min_max,
805 	    float process,
806 	    float voltage,
807 	    float temperature)
808 {
809   Pvt *pvt = new Pvt(process, voltage, temperature);
810   setPvt(inst, min_max, pvt);
811 }
812 
813 void
setPvt(Instance * inst,const MinMaxAll * min_max,Pvt * pvt)814 Sta::setPvt(Instance *inst,
815 	    const MinMaxAll *min_max,
816 	    Pvt *pvt)
817 {
818   sdc_->setPvt(inst, min_max, pvt);
819   delaysInvalidFrom(inst);
820 }
821 
822 void
setTimingDerate(TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)823 Sta::setTimingDerate(TimingDerateType type,
824 		     PathClkOrData clk_data,
825 		     const RiseFallBoth *rf,
826 		     const EarlyLate *early_late,
827 		     float derate)
828 {
829   sdc_->setTimingDerate(type, clk_data, rf, early_late, derate);
830   // Delay calculation results are still valid.
831   // The search derates delays while finding arrival times.
832   search_->arrivalsInvalid();
833 }
834 
835 void
setTimingDerate(const Net * net,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)836 Sta::setTimingDerate(const Net *net,
837 		     PathClkOrData clk_data,
838 		     const RiseFallBoth *rf,
839 		     const EarlyLate *early_late,
840 		     float derate)
841 {
842   sdc_->setTimingDerate(net, clk_data, rf, early_late, derate);
843   // Delay calculation results are still valid.
844   // The search derates delays while finding arrival times.
845   search_->arrivalsInvalid();
846 }
847 
848 void
setTimingDerate(const Instance * inst,TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)849 Sta::setTimingDerate(const Instance *inst,
850 		     TimingDerateType type,
851 		     PathClkOrData clk_data,
852 		     const RiseFallBoth *rf,
853 		     const EarlyLate *early_late,
854 		     float derate)
855 {
856   sdc_->setTimingDerate(inst, type, clk_data, rf, early_late, derate);
857   // Delay calculation results are still valid.
858   // The search derates delays while finding arrival times.
859   search_->arrivalsInvalid();
860 }
861 
862 void
setTimingDerate(const LibertyCell * cell,TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)863 Sta::setTimingDerate(const LibertyCell *cell,
864 		     TimingDerateType type,
865 		     PathClkOrData clk_data,
866 		     const RiseFallBoth *rf,
867 		     const EarlyLate *early_late,
868 		     float derate)
869 {
870   sdc_->setTimingDerate(cell, type, clk_data, rf, early_late, derate);
871   // Delay calculation results are still valid.
872   // The search derates delays while finding arrival times.
873   search_->arrivalsInvalid();
874 }
875 
876 void
unsetTimingDerate()877 Sta::unsetTimingDerate()
878 {
879   sdc_->unsetTimingDerate();
880   // Delay calculation results are still valid.
881   // The search derates delays while finding arrival times.
882   search_->arrivalsInvalid();
883 }
884 
885 void
setInputSlew(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float slew)886 Sta::setInputSlew(Port *port,
887 		  const RiseFallBoth *rf,
888 		  const MinMaxAll *min_max,
889 		  float slew)
890 {
891   sdc_->setInputSlew(port, rf, min_max, slew);
892   delaysInvalidFrom(port);
893 }
894 
895 void
setDriveCell(LibertyLibrary * library,LibertyCell * cell,Port * port,LibertyPort * from_port,float * from_slews,LibertyPort * to_port,const RiseFallBoth * rf,const MinMaxAll * min_max)896 Sta::setDriveCell(LibertyLibrary *library,
897 		  LibertyCell *cell,
898 		  Port *port,
899 		  LibertyPort *from_port,
900 		  float *from_slews,
901 		  LibertyPort *to_port,
902 		  const RiseFallBoth *rf,
903 		  const MinMaxAll *min_max)
904 {
905   sdc_->setDriveCell(library, cell, port, from_port, from_slews, to_port,
906 		     rf, min_max);
907   delaysInvalidFrom(port);
908 }
909 
910 void
setDriveResistance(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float res)911 Sta::setDriveResistance(Port *port,
912 			const RiseFallBoth *rf,
913 			const MinMaxAll *min_max,
914 			float res)
915 {
916   sdc_->setDriveResistance(port, rf, min_max, res);
917   delaysInvalidFrom(port);
918 }
919 
920 void
setLatchBorrowLimit(Pin * pin,float limit)921 Sta::setLatchBorrowLimit(Pin *pin,
922 			 float limit)
923 {
924   sdc_->setLatchBorrowLimit(pin, limit);
925   search_->requiredInvalid(pin);
926 }
927 
928 void
setLatchBorrowLimit(Instance * inst,float limit)929 Sta::setLatchBorrowLimit(Instance *inst,
930 			 float limit)
931 {
932   sdc_->setLatchBorrowLimit(inst, limit);
933   search_->requiredInvalid(inst);
934 }
935 
936 void
setLatchBorrowLimit(Clock * clk,float limit)937 Sta::setLatchBorrowLimit(Clock *clk,
938 			 float limit)
939 {
940   sdc_->setLatchBorrowLimit(clk, limit);
941   search_->arrivalsInvalid();
942 }
943 
944 void
setMinPulseWidth(const RiseFallBoth * rf,float min_width)945 Sta::setMinPulseWidth(const RiseFallBoth *rf,
946 		      float min_width)
947 {
948   sdc_->setMinPulseWidth(rf, min_width);
949 }
950 
951 void
setMinPulseWidth(const Pin * pin,const RiseFallBoth * rf,float min_width)952 Sta::setMinPulseWidth(const Pin *pin,
953 		      const RiseFallBoth *rf,
954 		      float min_width)
955 {
956   sdc_->setMinPulseWidth(pin, rf, min_width);
957 }
958 
959 void
setMinPulseWidth(const Instance * inst,const RiseFallBoth * rf,float min_width)960 Sta::setMinPulseWidth(const Instance *inst,
961 		      const RiseFallBoth *rf,
962 		      float min_width)
963 {
964   sdc_->setMinPulseWidth(inst, rf, min_width);
965 }
966 
967 void
setMinPulseWidth(const Clock * clk,const RiseFallBoth * rf,float min_width)968 Sta::setMinPulseWidth(const Clock *clk,
969 		      const RiseFallBoth *rf,
970 		      float min_width)
971 {
972   sdc_->setMinPulseWidth(clk, rf, min_width);
973 }
974 
975 void
setWireloadMode(WireloadMode mode)976 Sta::setWireloadMode(WireloadMode mode)
977 {
978   sdc_->setWireloadMode(mode);
979   graph_delay_calc_->delaysInvalid();
980   search_->arrivalsInvalid();
981 }
982 
983 void
setWireload(Wireload * wireload,const MinMaxAll * min_max)984 Sta::setWireload(Wireload *wireload,
985 		 const MinMaxAll *min_max)
986 {
987   sdc_->setWireload(wireload, min_max);
988   graph_delay_calc_->delaysInvalid();
989   search_->arrivalsInvalid();
990 }
991 
992 void
setWireloadSelection(WireloadSelection * selection,const MinMaxAll * min_max)993 Sta::setWireloadSelection(WireloadSelection *selection,
994 			  const MinMaxAll *min_max)
995 {
996   sdc_->setWireloadSelection(selection, min_max);
997   graph_delay_calc_->delaysInvalid();
998   search_->arrivalsInvalid();
999 }
1000 
1001 void
setSlewLimit(Clock * clk,const RiseFallBoth * rf,const PathClkOrData clk_data,const MinMax * min_max,float slew)1002 Sta::setSlewLimit(Clock *clk,
1003 		  const RiseFallBoth *rf,
1004 		  const PathClkOrData clk_data,
1005 		  const MinMax *min_max,
1006 		  float slew)
1007 {
1008   sdc_->setSlewLimit(clk, rf, clk_data, min_max, slew);
1009 }
1010 
1011 void
setSlewLimit(Port * port,const MinMax * min_max,float slew)1012 Sta::setSlewLimit(Port *port,
1013 		  const MinMax *min_max,
1014 		  float slew)
1015 {
1016   sdc_->setSlewLimit(port, min_max, slew);
1017 }
1018 
1019 void
setSlewLimit(Cell * cell,const MinMax * min_max,float slew)1020 Sta::setSlewLimit(Cell *cell,
1021 		  const MinMax *min_max,
1022 		  float slew)
1023 {
1024   sdc_->setSlewLimit(cell, min_max, slew);
1025 }
1026 
1027 void
setCapacitanceLimit(Cell * cell,const MinMax * min_max,float cap)1028 Sta::setCapacitanceLimit(Cell *cell,
1029 			 const MinMax *min_max,
1030 			 float cap)
1031 {
1032   sdc_->setCapacitanceLimit(cell, min_max, cap);
1033 }
1034 
1035 void
setCapacitanceLimit(Port * port,const MinMax * min_max,float cap)1036 Sta::setCapacitanceLimit(Port *port,
1037 			 const MinMax *min_max,
1038 			 float cap)
1039 {
1040   sdc_->setCapacitanceLimit(port, min_max, cap);
1041 }
1042 
1043 void
setCapacitanceLimit(Pin * pin,const MinMax * min_max,float cap)1044 Sta::setCapacitanceLimit(Pin *pin,
1045 			 const MinMax *min_max,
1046 			 float cap)
1047 {
1048   sdc_->setCapacitanceLimit(pin, min_max, cap);
1049 }
1050 
1051 void
setFanoutLimit(Cell * cell,const MinMax * min_max,float fanout)1052 Sta::setFanoutLimit(Cell *cell,
1053 		    const MinMax *min_max,
1054 		    float fanout)
1055 {
1056   sdc_->setFanoutLimit(cell, min_max, fanout);
1057 }
1058 
1059 void
setFanoutLimit(Port * port,const MinMax * min_max,float fanout)1060 Sta::setFanoutLimit(Port *port,
1061 		    const MinMax *min_max,
1062 		    float fanout)
1063 {
1064   sdc_->setFanoutLimit(port, min_max, fanout);
1065 }
1066 
1067 void
setMaxArea(float area)1068 Sta::setMaxArea(float area)
1069 {
1070   sdc_->setMaxArea(area);
1071 }
1072 
1073 void
makeClock(const char * name,PinSet * pins,bool add_to_pins,float period,FloatSeq * waveform,char * comment)1074 Sta::makeClock(const char *name,
1075 	       PinSet *pins,
1076 	       bool add_to_pins,
1077 	       float period,
1078 	       FloatSeq *waveform,
1079 	       char *comment)
1080 {
1081   sdc_->makeClock(name, pins, add_to_pins, period, waveform, comment);
1082   update_genclks_ = true;
1083   search_->arrivalsInvalid();
1084 }
1085 
1086 void
makeGeneratedClock(const char * name,PinSet * pins,bool add_to_pins,Pin * src_pin,Clock * master_clk,Pin * pll_out,Pin * pll_fdbk,int divide_by,int multiply_by,float duty_cycle,bool invert,bool combinational,IntSeq * edges,FloatSeq * edge_shifts,char * comment)1087 Sta::makeGeneratedClock(const char *name,
1088 			PinSet *pins,
1089 			bool add_to_pins,
1090 			Pin *src_pin,
1091 			Clock *master_clk,
1092 			Pin *pll_out,
1093 			Pin *pll_fdbk,
1094 			int divide_by,
1095 			int multiply_by,
1096 			float duty_cycle,
1097 			bool invert,
1098 			bool combinational,
1099 			IntSeq *edges,
1100 			FloatSeq *edge_shifts,
1101 			char *comment)
1102 {
1103   sdc_->makeGeneratedClock(name, pins, add_to_pins,
1104 			   src_pin, master_clk,
1105 			   pll_out, pll_fdbk,
1106 			   divide_by, multiply_by, duty_cycle,
1107 			   invert, combinational,
1108 			   edges, edge_shifts, comment);
1109   update_genclks_ = true;
1110   search_->arrivalsInvalid();
1111 }
1112 
1113 void
removeClock(Clock * clk)1114 Sta::removeClock(Clock *clk)
1115 {
1116   sdc_->removeClock(clk);
1117   search_->arrivalsInvalid();
1118 }
1119 
1120 bool
isClockSrc(const Pin * pin) const1121 Sta::isClockSrc(const Pin *pin) const
1122 {
1123   return sdc_->isClock(pin);
1124 }
1125 
1126 void
setPropagatedClock(Clock * clk)1127 Sta::setPropagatedClock(Clock *clk)
1128 {
1129   sdc_->setPropagatedClock(clk);
1130   graph_delay_calc_->delaysInvalid();
1131   search_->arrivalsInvalid();
1132   clkPinsInvalid();
1133 }
1134 
1135 void
removePropagatedClock(Clock * clk)1136 Sta::removePropagatedClock(Clock *clk)
1137 {
1138   sdc_->removePropagatedClock(clk);
1139   graph_delay_calc_->delaysInvalid();
1140   search_->arrivalsInvalid();
1141   clkPinsInvalid();
1142 }
1143 
1144 void
setPropagatedClock(Pin * pin)1145 Sta::setPropagatedClock(Pin *pin)
1146 {
1147   sdc_->setPropagatedClock(pin);
1148   graph_delay_calc_->delaysInvalid();
1149   search_->arrivalsInvalid();
1150   clkPinsInvalid();
1151 }
1152 
1153 void
removePropagatedClock(Pin * pin)1154 Sta::removePropagatedClock(Pin *pin)
1155 {
1156   sdc_->removePropagatedClock(pin);
1157   graph_delay_calc_->delaysInvalid();
1158   search_->arrivalsInvalid();
1159   clkPinsInvalid();
1160 }
1161 
1162 void
setClockSlew(Clock * clk,const RiseFallBoth * rf,const MinMaxAll * min_max,float slew)1163 Sta::setClockSlew(Clock *clk,
1164 		  const RiseFallBoth *rf,
1165 		  const MinMaxAll *min_max,
1166 		  float slew)
1167 {
1168   sdc_->setClockSlew(clk, rf, min_max, slew);
1169   clockSlewChanged(clk);
1170 }
1171 
1172 void
removeClockSlew(Clock * clk)1173 Sta::removeClockSlew(Clock *clk)
1174 {
1175   sdc_->removeClockSlew(clk);
1176   clockSlewChanged(clk);
1177 }
1178 
1179 void
clockSlewChanged(Clock * clk)1180 Sta::clockSlewChanged(Clock *clk)
1181 {
1182   for (Pin *pin : clk->pins())
1183     graph_delay_calc_->delayInvalid(pin);
1184   search_->arrivalsInvalid();
1185 }
1186 
1187 void
setClockLatency(Clock * clk,Pin * pin,const RiseFallBoth * rf,const MinMaxAll * min_max,float delay)1188 Sta::setClockLatency(Clock *clk,
1189 		     Pin *pin,
1190 		     const RiseFallBoth *rf,
1191 		     const MinMaxAll *min_max,
1192 		     float delay)
1193 {
1194   sdcChangedGraph();
1195   sdc_->setClockLatency(clk, pin, rf, min_max, delay);
1196   search_->arrivalsInvalid();
1197 }
1198 
1199 void
sdcChangedGraph()1200 Sta::sdcChangedGraph()
1201 {
1202   if (graph_sdc_annotated_)
1203     sdc_->removeGraphAnnotations();
1204   graph_sdc_annotated_ = false;
1205 }
1206 
1207 void
ensureGraphSdcAnnotated()1208 Sta::ensureGraphSdcAnnotated()
1209 {
1210   if (!graph_sdc_annotated_) {
1211     sdc_->annotateGraph();
1212     graph_sdc_annotated_ = true;
1213   }
1214 }
1215 
1216 void
removeClockLatency(const Clock * clk,const Pin * pin)1217 Sta::removeClockLatency(const Clock *clk,
1218 			const Pin *pin)
1219 {
1220   sdcChangedGraph();
1221   sdc_->removeClockLatency(clk, pin);
1222   search_->arrivalsInvalid();
1223 }
1224 
1225 void
setClockInsertion(const Clock * clk,const Pin * pin,const RiseFallBoth * rf,const MinMaxAll * min_max,const EarlyLateAll * early_late,float delay)1226 Sta::setClockInsertion(const Clock *clk,
1227 		       const Pin *pin,
1228 		       const RiseFallBoth *rf,
1229 		       const MinMaxAll *min_max,
1230 		       const EarlyLateAll *early_late,
1231 		       float delay)
1232 {
1233   sdc_->setClockInsertion(clk, pin, rf, min_max, early_late, delay);
1234   search_->arrivalsInvalid();
1235 }
1236 
1237 void
removeClockInsertion(const Clock * clk,const Pin * pin)1238 Sta::removeClockInsertion(const Clock *clk,
1239 			  const Pin *pin)
1240 {
1241   sdc_->removeClockInsertion(clk, pin);
1242   search_->arrivalsInvalid();
1243 }
1244 
1245 void
setClockUncertainty(Clock * clk,const SetupHoldAll * setup_hold,float uncertainty)1246 Sta::setClockUncertainty(Clock *clk,
1247 			 const SetupHoldAll *setup_hold,
1248 			 float uncertainty)
1249 {
1250   clk->setUncertainty(setup_hold, uncertainty);
1251   search_->arrivalsInvalid();
1252 }
1253 
1254 void
removeClockUncertainty(Clock * clk,const SetupHoldAll * setup_hold)1255 Sta::removeClockUncertainty(Clock *clk,
1256 			    const SetupHoldAll *setup_hold)
1257 {
1258   clk->removeUncertainty(setup_hold);
1259   search_->arrivalsInvalid();
1260 }
1261 
1262 void
setClockUncertainty(Pin * pin,const SetupHoldAll * setup_hold,float uncertainty)1263 Sta::setClockUncertainty(Pin *pin,
1264 			 const SetupHoldAll *setup_hold,
1265 			 float uncertainty)
1266 {
1267   sdc_->setClockUncertainty(pin, setup_hold, uncertainty);
1268   search_->arrivalsInvalid();
1269 }
1270 
1271 void
removeClockUncertainty(Pin * pin,const SetupHoldAll * setup_hold)1272 Sta::removeClockUncertainty(Pin *pin,
1273 			    const SetupHoldAll *setup_hold)
1274 {
1275   sdc_->removeClockUncertainty(pin, setup_hold);
1276   search_->arrivalsInvalid();
1277 }
1278 
1279 void
setClockUncertainty(Clock * from_clk,const RiseFallBoth * from_rf,Clock * to_clk,const RiseFallBoth * to_rf,const SetupHoldAll * setup_hold,float uncertainty)1280 Sta::setClockUncertainty(Clock *from_clk,
1281 			 const RiseFallBoth *from_rf,
1282 			 Clock *to_clk,
1283 			 const RiseFallBoth *to_rf,
1284 			 const SetupHoldAll *setup_hold,
1285 			 float uncertainty)
1286 {
1287   sdc_->setClockUncertainty(from_clk, from_rf, to_clk, to_rf,
1288 			    setup_hold, uncertainty);
1289   search_->arrivalsInvalid();
1290 }
1291 
1292 void
removeClockUncertainty(Clock * from_clk,const RiseFallBoth * from_rf,Clock * to_clk,const RiseFallBoth * to_rf,const SetupHoldAll * setup_hold)1293 Sta::removeClockUncertainty(Clock *from_clk,
1294 			    const RiseFallBoth *from_rf,
1295 			    Clock *to_clk,
1296 			    const RiseFallBoth *to_rf,
1297 			    const SetupHoldAll *setup_hold)
1298 {
1299   sdc_->removeClockUncertainty(from_clk, from_rf, to_clk, to_rf, setup_hold);
1300   search_->arrivalsInvalid();
1301 }
1302 
1303 ClockGroups *
makeClockGroups(const char * name,bool logically_exclusive,bool physically_exclusive,bool asynchronous,bool allow_paths,const char * comment)1304 Sta::makeClockGroups(const char *name,
1305 		     bool logically_exclusive,
1306 		     bool physically_exclusive,
1307 		     bool asynchronous,
1308 		     bool allow_paths,
1309 		     const char *comment)
1310 {
1311   ClockGroups *groups = sdc_->makeClockGroups(name,
1312 					      logically_exclusive,
1313 					      physically_exclusive,
1314 					      asynchronous,
1315 					      allow_paths,
1316 					      comment);
1317   search_->requiredsInvalid();
1318   return groups;
1319 }
1320 
1321 void
removeClockGroupsLogicallyExclusive(const char * name)1322 Sta::removeClockGroupsLogicallyExclusive(const char *name)
1323 {
1324   sdc_->removeClockGroupsLogicallyExclusive(name);
1325   search_->requiredsInvalid();
1326 }
1327 
1328 void
removeClockGroupsPhysicallyExclusive(const char * name)1329 Sta::removeClockGroupsPhysicallyExclusive(const char *name)
1330 {
1331   sdc_->removeClockGroupsPhysicallyExclusive(name);
1332   search_->requiredsInvalid();
1333 }
1334 
1335 void
removeClockGroupsAsynchronous(const char * name)1336 Sta::removeClockGroupsAsynchronous(const char *name)
1337 {
1338   sdc_->removeClockGroupsAsynchronous(name);
1339   search_->requiredsInvalid();
1340 }
1341 
1342 void
makeClockGroup(ClockGroups * clk_groups,ClockSet * clks)1343 Sta::makeClockGroup(ClockGroups *clk_groups,
1344 		    ClockSet *clks)
1345 {
1346   sdc_->makeClockGroup(clk_groups, clks);
1347 }
1348 
1349 void
setClockSense(PinSet * pins,ClockSet * clks,ClockSense sense)1350 Sta::setClockSense(PinSet *pins,
1351 		   ClockSet *clks,
1352 		   ClockSense sense)
1353 {
1354   sdc_->setClockSense(pins, clks, sense);
1355   search_->arrivalsInvalid();
1356 }
1357 
1358 ////////////////////////////////////////////////////////////////
1359 
1360 void
setClockGatingCheck(const RiseFallBoth * rf,const SetupHold * setup_hold,float margin)1361 Sta::setClockGatingCheck(const RiseFallBoth *rf,
1362 			 const SetupHold *setup_hold,
1363 			 float margin)
1364 {
1365   sdc_->setClockGatingCheck(rf, setup_hold, margin);
1366   search_->arrivalsInvalid();
1367 }
1368 
1369 void
setClockGatingCheck(Clock * clk,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin)1370 Sta::setClockGatingCheck(Clock *clk,
1371 			 const RiseFallBoth *rf,
1372 			 const SetupHold *setup_hold,
1373 			 float margin)
1374 {
1375   sdc_->setClockGatingCheck(clk, rf, setup_hold, margin);
1376   search_->arrivalsInvalid();
1377 }
1378 
1379 void
setClockGatingCheck(Instance * inst,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin,LogicValue active_value)1380 Sta::setClockGatingCheck(Instance *inst,
1381 			 const RiseFallBoth *rf,
1382 			 const SetupHold *setup_hold,
1383 			 float margin,
1384 			 LogicValue active_value)
1385 {
1386   sdc_->setClockGatingCheck(inst, rf, setup_hold, margin,active_value);
1387   search_->arrivalsInvalid();
1388 }
1389 
1390 void
setClockGatingCheck(Pin * pin,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin,LogicValue active_value)1391 Sta::setClockGatingCheck(Pin *pin,
1392 			 const RiseFallBoth *rf,
1393 			 const SetupHold *setup_hold,
1394 			 float margin,
1395 			 LogicValue active_value)
1396 {
1397   sdc_->setClockGatingCheck(pin, rf, setup_hold, margin,active_value);
1398   search_->arrivalsInvalid();
1399 }
1400 
1401 void
setDataCheck(Pin * from,const RiseFallBoth * from_rf,Pin * to,const RiseFallBoth * to_rf,Clock * clk,const SetupHoldAll * setup_hold,float margin)1402 Sta::setDataCheck(Pin *from,
1403 		  const RiseFallBoth *from_rf,
1404 		  Pin *to,
1405 		  const RiseFallBoth *to_rf,
1406 		  Clock *clk,
1407 		  const SetupHoldAll *setup_hold,
1408 		  float margin)
1409 {
1410   sdcChangedGraph();
1411   sdc_->setDataCheck(from, from_rf, to, to_rf, clk, setup_hold,margin);
1412   search_->requiredInvalid(to);
1413 }
1414 
1415 void
removeDataCheck(Pin * from,const RiseFallBoth * from_rf,Pin * to,const RiseFallBoth * to_rf,Clock * clk,const SetupHoldAll * setup_hold)1416 Sta::removeDataCheck(Pin *from,
1417 		     const RiseFallBoth *from_rf,
1418 		     Pin *to,
1419 		     const RiseFallBoth *to_rf,
1420 		     Clock *clk,
1421 		     const SetupHoldAll *setup_hold)
1422 {
1423   sdc_->removeDataCheck(from, from_rf, to, to_rf, clk, setup_hold);
1424   search_->requiredInvalid(to);
1425 }
1426 
1427 ////////////////////////////////////////////////////////////////
1428 
1429 void
disable(Pin * pin)1430 Sta::disable(Pin *pin)
1431 {
1432   sdcChangedGraph();
1433   sdc_->disable(pin);
1434   // Levelization respects disabled edges.
1435   levelize_->invalid();
1436   graph_delay_calc_->delayInvalid(pin);
1437   search_->arrivalsInvalid();
1438 }
1439 
1440 void
removeDisable(Pin * pin)1441 Sta::removeDisable(Pin *pin)
1442 {
1443   sdcChangedGraph();
1444   sdc_->removeDisable(pin);
1445   disableAfter();
1446   // Levelization respects disabled edges.
1447   levelize_->invalid();
1448   graph_delay_calc_->delayInvalid(pin);
1449   search_->arrivalsInvalid();
1450 }
1451 
1452 void
disable(Instance * inst,LibertyPort * from,LibertyPort * to)1453 Sta::disable(Instance *inst,
1454 	     LibertyPort *from,
1455 	     LibertyPort *to)
1456 {
1457   sdcChangedGraph();
1458   sdc_->disable(inst, from, to);
1459 
1460   if (from) {
1461     Pin *from_pin = network_->findPin(inst, from);
1462     graph_delay_calc_->delayInvalid(from_pin);
1463   }
1464   if (to) {
1465     Pin *to_pin = network_->findPin(inst, to);
1466     graph_delay_calc_->delayInvalid(to_pin);
1467   }
1468   if (from == nullptr && to == nullptr) {
1469     InstancePinIterator *pin_iter = network_->pinIterator(inst);
1470     while (pin_iter->hasNext()) {
1471       Pin *pin = pin_iter->next();
1472       graph_delay_calc_->delayInvalid(pin);
1473     }
1474     delete pin_iter;
1475   }
1476   // Levelization respects disabled edges.
1477   levelize_->invalid();
1478   search_->arrivalsInvalid();
1479 }
1480 
1481 void
removeDisable(Instance * inst,LibertyPort * from,LibertyPort * to)1482 Sta::removeDisable(Instance *inst,
1483 		   LibertyPort *from,
1484 		   LibertyPort *to)
1485 {
1486   sdcChangedGraph();
1487   sdc_->removeDisable(inst, from, to);
1488 
1489   if (from) {
1490     Pin *from_pin = network_->findPin(inst, from);
1491     graph_delay_calc_->delayInvalid(from_pin);
1492   }
1493   if (to) {
1494     Pin *to_pin = network_->findPin(inst, to);
1495     graph_delay_calc_->delayInvalid(to_pin);
1496   }
1497   if (from == nullptr && to == nullptr) {
1498     InstancePinIterator *pin_iter = network_->pinIterator(inst);
1499     while (pin_iter->hasNext()) {
1500       Pin *pin = pin_iter->next();
1501       graph_delay_calc_->delayInvalid(pin);
1502     }
1503     delete pin_iter;
1504   }
1505   // Levelization respects disabled edges.
1506   levelize_->invalid();
1507   search_->arrivalsInvalid();
1508 }
1509 
1510 void
disable(LibertyCell * cell,LibertyPort * from,LibertyPort * to)1511 Sta::disable(LibertyCell *cell,
1512 	     LibertyPort *from,
1513 	     LibertyPort *to)
1514 {
1515   sdc_->disable(cell, from, to);
1516   disableAfter();
1517 }
1518 
1519 void
removeDisable(LibertyCell * cell,LibertyPort * from,LibertyPort * to)1520 Sta::removeDisable(LibertyCell *cell,
1521 		   LibertyPort *from,
1522 		   LibertyPort *to)
1523 {
1524   sdc_->removeDisable(cell, from, to);
1525   disableAfter();
1526 }
1527 
1528 void
disable(LibertyPort * port)1529 Sta::disable(LibertyPort *port)
1530 {
1531   sdcChangedGraph();
1532   sdc_->disable(port);
1533   disableAfter();
1534 }
1535 
1536 void
removeDisable(LibertyPort * port)1537 Sta::removeDisable(LibertyPort *port)
1538 {
1539   sdcChangedGraph();
1540   sdc_->removeDisable(port);
1541   disableAfter();
1542 }
1543 
1544 void
disable(Port * port)1545 Sta::disable(Port *port)
1546 {
1547   sdc_->disable(port);
1548   disableAfter();
1549 }
1550 
1551 void
removeDisable(Port * port)1552 Sta::removeDisable(Port *port)
1553 {
1554   sdc_->removeDisable(port);
1555   disableAfter();
1556 }
1557 
1558 void
disable(Edge * edge)1559 Sta::disable(Edge *edge)
1560 {
1561   sdc_->disable(edge);
1562   disableAfter();
1563 }
1564 
1565 void
removeDisable(Edge * edge)1566 Sta::removeDisable(Edge *edge)
1567 {
1568   sdc_->removeDisable(edge);
1569   disableAfter();
1570 }
1571 
1572 void
disable(TimingArcSet * arc_set)1573 Sta::disable(TimingArcSet *arc_set)
1574 {
1575   sdc_->disable(arc_set);
1576   disableAfter();
1577 }
1578 
1579 void
removeDisable(TimingArcSet * arc_set)1580 Sta::removeDisable(TimingArcSet *arc_set)
1581 {
1582   sdc_->removeDisable(arc_set);
1583   disableAfter();
1584 }
1585 
1586 void
disableAfter()1587 Sta::disableAfter()
1588 {
1589   // Levelization respects disabled edges.
1590   levelize_->invalid();
1591   graph_delay_calc_->delaysInvalid();
1592   search_->arrivalsInvalid();
1593 }
1594 
1595 ////////////////////////////////////////////////////////////////
1596 
1597 EdgeSeq *
disabledEdges()1598 Sta::disabledEdges()
1599 {
1600   ensureLevelized();
1601   EdgeSeq *disabled_edges = new EdgeSeq;
1602   VertexIterator vertex_iter(graph_);
1603   while (vertex_iter.hasNext()) {
1604     Vertex *vertex = vertex_iter.next();
1605     VertexOutEdgeIterator edge_iter(vertex, graph_);
1606     while (edge_iter.hasNext()) {
1607       Edge *edge = edge_iter.next();
1608       if (isDisabledConstant(edge)
1609 	  || isDisabledCondDefault(edge)
1610 	  || isDisabledConstraint(edge)
1611 	  || edge->isDisabledLoop()
1612 	  || isDisabledPresetClr(edge))
1613 	disabled_edges->push_back(edge);
1614     }
1615   }
1616   return disabled_edges;
1617 }
1618 
1619 
1620 EdgeSeq *
disabledEdgesSorted()1621 Sta::disabledEdgesSorted()
1622 {
1623   EdgeSeq *disabled_edges = disabledEdges();
1624   sortEdges(disabled_edges, network_, graph_);
1625   return disabled_edges;
1626 }
1627 
1628 bool
isDisabledConstraint(Edge * edge)1629 Sta::isDisabledConstraint(Edge *edge)
1630 {
1631   Pin *from_pin = edge->from(graph_)->pin();
1632   Pin *to_pin = edge->to(graph_)->pin();
1633   const Instance *inst = network_->instance(from_pin);
1634   TimingArcSet *arc_set = edge->timingArcSet();
1635   return sdc_->isDisabled(from_pin)
1636     || sdc_->isDisabled(to_pin)
1637     || sdc_->isDisabled(inst, from_pin, to_pin, edge->role())
1638     || sdc_->isDisabled(edge)
1639     || sdc_->isDisabled(arc_set);
1640 }
1641 
1642 bool
isDisabledConstant(Edge * edge)1643 Sta::isDisabledConstant(Edge *edge)
1644 {
1645   sim_->ensureConstantsPropagated();
1646   const TimingRole *role = edge->role();
1647   Vertex *from_vertex = edge->from(graph_);
1648   Pin *from_pin = from_vertex->pin();
1649   Vertex *to_vertex = edge->to(graph_);
1650   Pin *to_pin = to_vertex->pin();
1651   const Instance *inst = network_->instance(from_pin);
1652   return sim_->logicZeroOne(from_vertex)
1653     || sim_->logicZeroOne(to_vertex)
1654     || (!role->isWire()
1655 	&& (isCondDisabled(edge, inst, from_pin, to_pin, network_, sim_)
1656 	    || isModeDisabled(edge, inst, network_, sim_)
1657 	    || isTestDisabled(inst, from_pin, to_pin, network_, sim_)
1658 	    || hasDisabledArcs(edge, graph_)));
1659 }
1660 
1661 static bool
hasDisabledArcs(Edge * edge,Graph * graph)1662 hasDisabledArcs(Edge *edge,
1663 		Graph *graph)
1664 {
1665   TimingArcSet *arc_set = edge->timingArcSet();
1666   TimingArcSetArcIterator arc_iter(arc_set);
1667   while (arc_iter.hasNext()) {
1668     TimingArc *arc = arc_iter.next();
1669     if (!searchThru(edge, arc, graph))
1670       return true;
1671   }
1672   return false;
1673 }
1674 
1675 bool
isDisabledLoop(Edge * edge) const1676 Sta::isDisabledLoop(Edge *edge) const
1677 {
1678   return levelize_->isDisabledLoop(edge);
1679 }
1680 
1681 bool
isDisabledCondDefault(Edge * edge)1682 Sta::isDisabledCondDefault(Edge *edge)
1683 {
1684   return sdc_->isDisabledCondDefault(edge);
1685 }
1686 
1687 PinSet *
disabledConstantPins(Edge * edge)1688 Sta::disabledConstantPins(Edge *edge)
1689 {
1690   sim_->ensureConstantsPropagated();
1691   PinSet *pins = new PinSet;
1692   Vertex *from_vertex = edge->from(graph_);
1693   Pin *from_pin = from_vertex->pin();
1694   Vertex *to_vertex = edge->to(graph_);
1695   Pin *to_pin = to_vertex->pin();
1696   if (sim_->logicZeroOne(from_vertex))
1697     pins->insert(from_pin);
1698   if (edge->role()->isWire()) {
1699     if (sim_->logicZeroOne(to_vertex))
1700       pins->insert(to_pin);
1701   }
1702   else {
1703     Instance *inst = network_->instance(to_pin);
1704     bool is_disabled;
1705     FuncExpr *disable_cond;
1706     isCondDisabled(edge, inst, from_pin, to_pin, network_, sim_,
1707 		   is_disabled, disable_cond);
1708     if (is_disabled)
1709       exprConstantPins(disable_cond, inst, pins);
1710     isModeDisabled(edge, inst, network_, sim_,
1711 		   is_disabled, disable_cond);
1712     if (is_disabled)
1713       exprConstantPins(disable_cond, inst, pins);
1714     Pin *scan_enable;
1715     isTestDisabled(inst, from_pin, to_pin, network_, sim_,
1716 		   is_disabled, scan_enable);
1717     if (is_disabled)
1718       pins->insert(scan_enable);
1719     if (hasDisabledArcs(edge, graph_)) {
1720       LibertyPort *to_port = network_->libertyPort(to_pin);
1721       if (to_port) {
1722 	FuncExpr *func = to_port->function();
1723 	if (func
1724 	    && sim_->functionSense(inst, from_pin, to_pin) != edge->sense())
1725 	  exprConstantPins(func, inst, pins);
1726       }
1727     }
1728   }
1729   return pins;
1730 }
1731 
1732 TimingSense
simTimingSense(Edge * edge)1733 Sta::simTimingSense(Edge *edge)
1734 {
1735   Pin *from_pin = edge->from(graph_)->pin();
1736   Pin *to_pin = edge->to(graph_)->pin();
1737   Instance *inst = network_->instance(from_pin);
1738   return sim_->functionSense(inst, from_pin, to_pin);
1739 }
1740 
1741 void
exprConstantPins(FuncExpr * expr,Instance * inst,PinSet * pins)1742 Sta::exprConstantPins(FuncExpr *expr, Instance *inst, PinSet *pins)
1743 {
1744   FuncExprPortIterator port_iter(expr);
1745   while (port_iter.hasNext()) {
1746     LibertyPort *port = port_iter.next();
1747     Pin *pin = network_->findPin(inst, port);
1748     if (pin) {
1749       LogicValue value = sim_->logicValue(pin);
1750       if (value != LogicValue::unknown)
1751 	pins->insert(pin);
1752     }
1753   }
1754 }
1755 
1756 bool
isDisabledBidirectInstPath(Edge * edge) const1757 Sta::isDisabledBidirectInstPath(Edge *edge) const
1758 {
1759   return !sdc_->bidirectInstPathsEnabled()
1760     && edge->isBidirectInstPath();
1761 }
1762 
1763 bool
isDisabledBidirectNetPath(Edge * edge) const1764 Sta::isDisabledBidirectNetPath(Edge *edge) const
1765 {
1766   return !sdc_->bidirectNetPathsEnabled()
1767     && edge->isBidirectNetPath();
1768 }
1769 
1770 bool
isDisabledPresetClr(Edge * edge) const1771 Sta::isDisabledPresetClr(Edge *edge) const
1772 {
1773   return !sdc_->presetClrArcsEnabled()
1774     && edge->role() == TimingRole::regSetClr();
1775 }
1776 
1777 void
disableClockGatingCheck(Instance * inst)1778 Sta::disableClockGatingCheck(Instance *inst)
1779 {
1780   sdc_->disableClockGatingCheck(inst);
1781   search_->endpointsInvalid();
1782 }
1783 
1784 void
disableClockGatingCheck(Pin * pin)1785 Sta::disableClockGatingCheck(Pin *pin)
1786 {
1787   sdc_->disableClockGatingCheck(pin);
1788   search_->endpointsInvalid();
1789 }
1790 
1791 void
removeDisableClockGatingCheck(Instance * inst)1792 Sta::removeDisableClockGatingCheck(Instance *inst)
1793 {
1794   sdc_->removeDisableClockGatingCheck(inst);
1795   search_->endpointsInvalid();
1796 }
1797 
1798 void
removeDisableClockGatingCheck(Pin * pin)1799 Sta::removeDisableClockGatingCheck(Pin *pin)
1800 {
1801   sdc_->removeDisableClockGatingCheck(pin);
1802   search_->endpointsInvalid();
1803 }
1804 
1805 void
setLogicValue(Pin * pin,LogicValue value)1806 Sta::setLogicValue(Pin *pin,
1807 		   LogicValue value)
1808 {
1809   sdc_->setLogicValue(pin, value);
1810   // Levelization respects constant disabled edges.
1811   levelize_->invalid();
1812   sim_->constantsInvalid();
1813   // Constants disable edges which isolate downstream vertices of the
1814   // graph from the delay calculator's BFS search.  This means that
1815   // simply invaldating the delays downstream from the constant pin
1816   // fails.  This could be more incremental if the graph delay
1817   // calculator searched thru disabled edges but ignored their
1818   // results.
1819   graph_delay_calc_->delaysInvalid();
1820   search_->arrivalsInvalid();
1821 }
1822 
1823 void
setCaseAnalysis(Pin * pin,LogicValue value)1824 Sta::setCaseAnalysis(Pin *pin,
1825 		     LogicValue value)
1826 {
1827   sdc_->setCaseAnalysis(pin, value);
1828   // Levelization respects constant disabled edges.
1829   levelize_->invalid();
1830   sim_->constantsInvalid();
1831   // Constants disable edges which isolate downstream vertices of the
1832   // graph from the delay calculator's BFS search.  This means that
1833   // simply invaldating the delays downstream from the constant pin
1834   // fails.  This could be handled incrementally by invalidating delays
1835   // on the output of gates one level downstream.
1836   graph_delay_calc_->delaysInvalid();
1837   search_->arrivalsInvalid();
1838 }
1839 
1840 void
removeCaseAnalysis(Pin * pin)1841 Sta::removeCaseAnalysis(Pin *pin)
1842 {
1843   sdc_->removeCaseAnalysis(pin);
1844   // Levelization respects constant disabled edges.
1845   levelize_->invalid();
1846   sim_->constantsInvalid();
1847   // Constants disable edges which isolate downstream vertices of the
1848   // graph from the delay calculator's BFS search.  This means that
1849   // simply invaldating the delays downstream from the constant pin
1850   // fails.  This could be handled incrementally by invalidating delays
1851   // on the output of gates one level downstream.
1852   graph_delay_calc_->delaysInvalid();
1853   search_->arrivalsInvalid();
1854 }
1855 
1856 void
setInputDelay(Pin * pin,const RiseFallBoth * rf,Clock * clk,const RiseFall * clk_rf,Pin * ref_pin,bool source_latency_included,bool network_latency_included,const MinMaxAll * min_max,bool add,float delay)1857 Sta::setInputDelay(Pin *pin,
1858 		   const RiseFallBoth *rf,
1859 		   Clock *clk,
1860 		   const RiseFall *clk_rf,
1861 		   Pin *ref_pin,
1862 		   bool source_latency_included,
1863 		   bool network_latency_included,
1864 		   const MinMaxAll *min_max,
1865 		   bool add,
1866 		   float delay)
1867 {
1868   sdc_->setInputDelay(pin, rf, clk, clk_rf, ref_pin,
1869 		      source_latency_included, network_latency_included,
1870 		      min_max, add, delay);
1871 
1872   search_->arrivalInvalid(pin);
1873 }
1874 
1875 void
removeInputDelay(Pin * pin,RiseFallBoth * rf,Clock * clk,RiseFall * clk_rf,MinMaxAll * min_max)1876 Sta::removeInputDelay(Pin *pin,
1877 		      RiseFallBoth *rf,
1878 		      Clock *clk,
1879 		      RiseFall *clk_rf,
1880 		      MinMaxAll *min_max)
1881 {
1882   sdc_->removeInputDelay(pin, rf, clk, clk_rf, min_max);
1883   search_->arrivalInvalid(pin);
1884 }
1885 
1886 void
setOutputDelay(Pin * pin,const RiseFallBoth * rf,Clock * clk,const RiseFall * clk_rf,Pin * ref_pin,bool source_latency_included,bool network_latency_included,const MinMaxAll * min_max,bool add,float delay)1887 Sta::setOutputDelay(Pin *pin,
1888 		    const RiseFallBoth *rf,
1889 		    Clock *clk,
1890 		    const RiseFall *clk_rf,
1891 		    Pin *ref_pin,
1892 		    bool source_latency_included,
1893 		    bool network_latency_included,
1894 		    const MinMaxAll *min_max,
1895 		    bool add,
1896 		    float delay)
1897 {
1898   sdc_->setOutputDelay(pin, rf, clk, clk_rf, ref_pin,
1899 		       source_latency_included,network_latency_included,
1900 		       min_max, add, delay);
1901   sdcChangedGraph();
1902   search_->requiredInvalid(pin);
1903 }
1904 
1905 void
removeOutputDelay(Pin * pin,RiseFallBoth * rf,Clock * clk,RiseFall * clk_rf,MinMaxAll * min_max)1906 Sta::removeOutputDelay(Pin *pin,
1907 		       RiseFallBoth *rf,
1908 		       Clock *clk,
1909 		       RiseFall *clk_rf,
1910 		       MinMaxAll *min_max)
1911 {
1912   sdc_->removeOutputDelay(pin, rf, clk, clk_rf, min_max);
1913   sdcChangedGraph();
1914   search_->arrivalInvalid(pin);
1915 }
1916 
1917 void
makeFalsePath(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max,const char * comment)1918 Sta::makeFalsePath(ExceptionFrom *from,
1919 		   ExceptionThruSeq *thrus,
1920 		   ExceptionTo *to,
1921 		   const MinMaxAll *min_max,
1922 		   const char *comment)
1923 {
1924   sdc_->makeFalsePath(from, thrus, to, min_max, comment);
1925   search_->arrivalsInvalid();
1926 }
1927 
1928 void
makeMulticyclePath(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max,bool use_end_clk,int path_multiplier,const char * comment)1929 Sta::makeMulticyclePath(ExceptionFrom *from,
1930 			ExceptionThruSeq *thrus,
1931 			ExceptionTo *to,
1932 			const MinMaxAll *min_max,
1933 			bool use_end_clk,
1934 			int path_multiplier,
1935 			const char *comment)
1936 {
1937   sdc_->makeMulticyclePath(from, thrus, to, min_max,
1938 			   use_end_clk, path_multiplier,
1939 			   comment);
1940   search_->arrivalsInvalid();
1941 }
1942 
1943 void
makePathDelay(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMax * min_max,bool ignore_clk_latency,float delay,const char * comment)1944 Sta::makePathDelay(ExceptionFrom *from,
1945 		   ExceptionThruSeq *thrus,
1946 		   ExceptionTo *to,
1947 		   const MinMax *min_max,
1948 		   bool ignore_clk_latency,
1949 		   float delay,
1950 		   const char *comment)
1951 {
1952   sdc_->makePathDelay(from, thrus, to, min_max,
1953 		      ignore_clk_latency, delay,
1954 		      comment);
1955   search_->endpointsInvalid();
1956   search_->arrivalsInvalid();
1957 }
1958 
1959 void
resetPath(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max)1960 Sta::resetPath(ExceptionFrom *from,
1961 	       ExceptionThruSeq *thrus,
1962 	       ExceptionTo *to,
1963 	       const MinMaxAll *min_max)
1964 {
1965   sdc_->resetPath(from, thrus, to, min_max);
1966   search_->arrivalsInvalid();
1967 }
1968 
1969 void
makeGroupPath(const char * name,bool is_default,ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const char * comment)1970 Sta::makeGroupPath(const char *name,
1971 		   bool is_default,
1972 		   ExceptionFrom *from,
1973 		   ExceptionThruSeq *thrus,
1974 		   ExceptionTo *to,
1975 		   const char *comment)
1976 {
1977   sdc_->makeGroupPath(name, is_default, from, thrus, to, comment);
1978   search_->arrivalsInvalid();
1979 }
1980 
1981 bool
isGroupPathName(const char * group_name)1982 Sta::isGroupPathName(const char *group_name)
1983 {
1984   return PathGroups::isGroupPathName(group_name)
1985     || sdc_->findClock(group_name)
1986     || sdc_->isGroupPathName(group_name);
1987 }
1988 
1989 ExceptionFrom *
makeExceptionFrom(PinSet * from_pins,ClockSet * from_clks,InstanceSet * from_insts,const RiseFallBoth * from_rf)1990 Sta::makeExceptionFrom(PinSet *from_pins,
1991 		       ClockSet *from_clks,
1992 		       InstanceSet *from_insts,
1993 		       const RiseFallBoth *from_rf)
1994 {
1995   return sdc_->makeExceptionFrom(from_pins, from_clks, from_insts,
1996 				 from_rf);
1997 }
1998 
1999 void
checkExceptionFromPins(ExceptionFrom * from,const char * file,int line) const2000 Sta::checkExceptionFromPins(ExceptionFrom *from,
2001 			    const char *file,
2002 			    int line) const
2003 {
2004   if (from) {
2005     PinSet::ConstIterator pin_iter(from->pins());
2006     while (pin_iter.hasNext()) {
2007       const Pin *pin = pin_iter.next();
2008       if (exceptionFromInvalid(pin)) {
2009 	if (line)
2010 	  report_->fileWarn(160, file, line, "'%s' is not a valid startpoint.",
2011 			    cmd_network_->pathName(pin));
2012 	else
2013 	  report_->warn(16, "'%s' is not a valid startoint.",
2014 			cmd_network_->pathName(pin));
2015       }
2016     }
2017   }
2018 }
2019 
2020 bool
exceptionFromInvalid(const Pin * pin) const2021 Sta::exceptionFromInvalid(const Pin *pin) const
2022 {
2023   Net *net = network_->net(pin);
2024   // Floating pins are invalid.
2025   return (net == nullptr
2026 	  && !network_->isTopLevelPort(pin))
2027     || (net
2028 	// Pins connected to power/ground are invalid.
2029 	&& (network_->isPower(net)
2030 	    || network_->isGround(net)))
2031     || !((network_->isTopLevelPort(pin)
2032 	  && network_->direction(pin)->isAnyInput())
2033 	 || network_->isRegClkPin(pin)
2034 	 || network_->isLatchData(pin));
2035 }
2036 
2037 void
deleteExceptionFrom(ExceptionFrom * from)2038 Sta::deleteExceptionFrom(ExceptionFrom *from)
2039 {
2040   delete from;
2041 }
2042 
2043 ExceptionThru *
makeExceptionThru(PinSet * pins,NetSet * nets,InstanceSet * insts,const RiseFallBoth * rf)2044 Sta::makeExceptionThru(PinSet *pins,
2045 		       NetSet *nets,
2046 		       InstanceSet *insts,
2047 		       const RiseFallBoth *rf)
2048 {
2049   return sdc_->makeExceptionThru(pins, nets, insts, rf);
2050 }
2051 
2052 void
deleteExceptionThru(ExceptionThru * thru)2053 Sta::deleteExceptionThru(ExceptionThru *thru)
2054 {
2055   delete thru;
2056 }
2057 
2058 ExceptionTo *
makeExceptionTo(PinSet * to_pins,ClockSet * to_clks,InstanceSet * to_insts,const RiseFallBoth * rf,RiseFallBoth * end_rf)2059 Sta::makeExceptionTo(PinSet *to_pins,
2060 		     ClockSet *to_clks,
2061 		     InstanceSet *to_insts,
2062 		     const RiseFallBoth *rf,
2063  		     RiseFallBoth *end_rf)
2064 {
2065   return sdc_->makeExceptionTo(to_pins, to_clks, to_insts, rf, end_rf);
2066 }
2067 
2068 void
deleteExceptionTo(ExceptionTo * to)2069 Sta::deleteExceptionTo(ExceptionTo *to)
2070 {
2071   delete to;
2072 }
2073 
2074 void
checkExceptionToPins(ExceptionTo * to,const char * file,int line) const2075 Sta::checkExceptionToPins(ExceptionTo *to,
2076 			  const char *file,
2077 			  int line) const
2078 {
2079   if (to) {
2080     PinSet::Iterator pin_iter(to->pins());
2081     while (pin_iter.hasNext()) {
2082       const Pin *pin = pin_iter.next();
2083       if (sdc_->exceptionToInvalid(pin)) {
2084 	if (line)
2085 	  report_->fileWarn(161, file, line, "'%s' is not a valid endpoint.",
2086 			    cmd_network_->pathName(pin));
2087 	else
2088 	  report_->warn(17, "'%s' is not a valid endpoint.",
2089 			cmd_network_->pathName(pin));
2090       }
2091     }
2092   }
2093 }
2094 
2095 void
removeConstraints()2096 Sta::removeConstraints()
2097 {
2098   levelize_->invalid();
2099   graph_delay_calc_->clear();
2100   search_->clear();
2101   sim_->constantsInvalid();
2102   if (graph_)
2103     sdc_->removeGraphAnnotations();
2104   sdc_->clear();
2105   clk_network_->clear();
2106 }
2107 
2108 void
constraintsChanged()2109 Sta::constraintsChanged()
2110 {
2111   levelize_->invalid();
2112   graph_delay_calc_->delaysInvalid();
2113   search_->arrivalsInvalid();
2114   sim_->constantsInvalid();
2115 }
2116 
2117 void
writeSdc(const char * filename,bool leaf,bool native,bool no_timestamp,int digits)2118 Sta::writeSdc(const char *filename,
2119 	      bool leaf,
2120 	      bool native,
2121 	      bool no_timestamp,
2122 	      int digits)
2123 {
2124   sta::writeSdc(network_->topInstance(), filename, "write_sdc",
2125 		leaf, native, no_timestamp, digits, sdc_);
2126 }
2127 
2128 ////////////////////////////////////////////////////////////////
2129 
2130 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)2131 Sta::checkTiming(bool no_input_delay,
2132 		 bool no_output_delay,
2133 		 bool reg_multiple_clks,
2134 		 bool reg_no_clks,
2135 		 bool unconstrained_endpoints,
2136 		 bool loops,
2137 		 bool generated_clks)
2138 {
2139   searchPreamble();
2140   if (unconstrained_endpoints)
2141     // Only need non-clock arrivals for unconstrained_endpoints.
2142     search_->findAllArrivals();
2143   else
2144     search_->findClkArrivals();
2145   if (check_timing_ == nullptr)
2146     makeCheckTiming();
2147   return check_timing_->check(no_input_delay, no_output_delay,
2148 			      reg_multiple_clks, reg_no_clks,
2149 			      unconstrained_endpoints,
2150 			      loops, generated_clks);
2151 }
2152 
2153 bool
crprEnabled() const2154 Sta::crprEnabled() const
2155 {
2156   return sdc_->crprEnabled();
2157 }
2158 
2159 void
setCrprEnabled(bool enabled)2160 Sta::setCrprEnabled(bool enabled)
2161 {
2162   // Pessimism is only relevant for on_chip_variation analysis.
2163   if (sdc_->analysisType() == AnalysisType::ocv
2164       && enabled != sdc_->crprEnabled())
2165     search_->arrivalsInvalid();
2166   sdc_->setCrprEnabled(enabled);
2167 }
2168 
2169 CrprMode
crprMode() const2170 Sta::crprMode() const
2171 {
2172   return sdc_->crprMode();
2173 }
2174 
2175 void
setCrprMode(CrprMode mode)2176 Sta::setCrprMode(CrprMode mode)
2177 {
2178   // Pessimism is only relevant for on_chip_variation analysis.
2179   if (sdc_->analysisType() == AnalysisType::ocv
2180       && sdc_->crprEnabled()
2181       && sdc_->crprMode() != mode)
2182     search_->arrivalsInvalid();
2183   sdc_->setCrprMode(mode);
2184 }
2185 
2186 bool
pocvEnabled() const2187 Sta::pocvEnabled() const
2188 {
2189   return pocv_enabled_;
2190 }
2191 
2192 void
setPocvEnabled(bool enabled)2193 Sta::setPocvEnabled(bool enabled)
2194 {
2195   if (enabled != pocv_enabled_) {
2196     graph_delay_calc_->delaysInvalid();
2197     search_->arrivalsInvalid();
2198   }
2199   pocv_enabled_ = enabled;
2200   updateComponentsState();
2201 }
2202 
2203 void
setSigmaFactor(float factor)2204 Sta::setSigmaFactor(float factor)
2205 {
2206   if (!fuzzyEqual(factor, sigma_factor_)) {
2207     sigma_factor_ = factor;
2208     search_->arrivalsInvalid();
2209     updateComponentsState();
2210   }
2211 }
2212 
2213 bool
propagateGatedClockEnable() const2214 Sta::propagateGatedClockEnable() const
2215 {
2216   return sdc_->propagateGatedClockEnable();
2217 }
2218 
2219 void
setPropagateGatedClockEnable(bool enable)2220 Sta::setPropagateGatedClockEnable(bool enable)
2221 {
2222   if (sdc_->propagateGatedClockEnable() != enable)
2223     search_->arrivalsInvalid();
2224   sdc_->setPropagateGatedClockEnable(enable);
2225 }
2226 
2227 bool
presetClrArcsEnabled() const2228 Sta::presetClrArcsEnabled() const
2229 {
2230   return sdc_->presetClrArcsEnabled();
2231 }
2232 
2233 void
setPresetClrArcsEnabled(bool enable)2234 Sta::setPresetClrArcsEnabled(bool enable)
2235 {
2236   if (sdc_->presetClrArcsEnabled() != enable) {
2237     levelize_->invalid();
2238     graph_delay_calc_->delaysInvalid();
2239     search_->arrivalsInvalid();
2240   }
2241   sdc_->setPresetClrArcsEnabled(enable);
2242 }
2243 
2244 bool
condDefaultArcsEnabled() const2245 Sta::condDefaultArcsEnabled() const
2246 {
2247   return sdc_->condDefaultArcsEnabled();
2248 }
2249 
2250 void
setCondDefaultArcsEnabled(bool enabled)2251 Sta::setCondDefaultArcsEnabled(bool enabled)
2252 {
2253   if (sdc_->condDefaultArcsEnabled() != enabled) {
2254     graph_delay_calc_->delaysInvalid();
2255     search_->arrivalsInvalid();
2256     sdc_->setCondDefaultArcsEnabled(enabled);
2257   }
2258 }
2259 
2260 bool
bidirectInstPathsEnabled() const2261 Sta::bidirectInstPathsEnabled() const
2262 {
2263   return sdc_->bidirectInstPathsEnabled();
2264 }
2265 
2266 void
setBidirectInstPathsEnabled(bool enabled)2267 Sta::setBidirectInstPathsEnabled(bool enabled)
2268 {
2269   if (sdc_->bidirectInstPathsEnabled() != enabled) {
2270     levelize_->invalid();
2271     graph_delay_calc_->delaysInvalid();
2272     search_->arrivalsInvalid();
2273     sdc_->setBidirectInstPathsEnabled(enabled);
2274   }
2275 }
2276 
2277 bool
bidirectNetPathsEnabled() const2278 Sta::bidirectNetPathsEnabled() const
2279 {
2280   return sdc_->bidirectNetPathsEnabled();
2281 }
2282 
2283 void
setBidirectNetPathsEnabled(bool enabled)2284 Sta::setBidirectNetPathsEnabled(bool enabled)
2285 {
2286   if (sdc_->bidirectNetPathsEnabled() != enabled) {
2287     graph_delay_calc_->delaysInvalid();
2288     search_->arrivalsInvalid();
2289     sdc_->setBidirectNetPathsEnabled(enabled);
2290   }
2291 }
2292 
2293 bool
recoveryRemovalChecksEnabled() const2294 Sta::recoveryRemovalChecksEnabled() const
2295 {
2296   return sdc_->recoveryRemovalChecksEnabled();
2297 }
2298 
2299 void
setRecoveryRemovalChecksEnabled(bool enabled)2300 Sta::setRecoveryRemovalChecksEnabled(bool enabled)
2301 {
2302   if (sdc_->recoveryRemovalChecksEnabled() != enabled) {
2303     search_->arrivalsInvalid();
2304     sdc_->setRecoveryRemovalChecksEnabled(enabled);
2305   }
2306 }
2307 
2308 bool
gatedClkChecksEnabled() const2309 Sta::gatedClkChecksEnabled() const
2310 {
2311   return sdc_->gatedClkChecksEnabled();
2312 }
2313 
2314 void
setGatedClkChecksEnabled(bool enabled)2315 Sta::setGatedClkChecksEnabled(bool enabled)
2316 {
2317   if (sdc_->gatedClkChecksEnabled() != enabled) {
2318     search_->arrivalsInvalid();
2319     sdc_->setGatedClkChecksEnabled(enabled);
2320   }
2321 }
2322 
2323 bool
dynamicLoopBreaking() const2324 Sta::dynamicLoopBreaking() const
2325 {
2326   return sdc_->dynamicLoopBreaking();
2327 }
2328 
2329 void
setDynamicLoopBreaking(bool enable)2330 Sta::setDynamicLoopBreaking(bool enable)
2331 {
2332   if (sdc_->dynamicLoopBreaking() != enable) {
2333     sdc_->setDynamicLoopBreaking(enable);
2334     search_->arrivalsInvalid();
2335   }
2336 }
2337 
2338 bool
useDefaultArrivalClock() const2339 Sta::useDefaultArrivalClock() const
2340 {
2341   return sdc_->useDefaultArrivalClock();
2342 }
2343 
2344 void
setUseDefaultArrivalClock(bool enable)2345 Sta::setUseDefaultArrivalClock(bool enable)
2346 {
2347   if (sdc_->useDefaultArrivalClock() != enable) {
2348     sdc_->setUseDefaultArrivalClock(enable);
2349     search_->arrivalsInvalid();
2350   }
2351 }
2352 
2353 bool
propagateAllClocks() const2354 Sta::propagateAllClocks() const
2355 {
2356   return sdc_->propagateAllClocks();
2357 }
2358 
2359 void
setPropagateAllClocks(bool prop)2360 Sta::setPropagateAllClocks(bool prop)
2361 {
2362   sdc_->setPropagateAllClocks(prop);
2363 }
2364 
2365 bool
clkThruTristateEnabled() const2366 Sta::clkThruTristateEnabled() const
2367 {
2368   return sdc_->clkThruTristateEnabled();
2369 }
2370 
2371 void
setClkThruTristateEnabled(bool enable)2372 Sta::setClkThruTristateEnabled(bool enable)
2373 {
2374   if (enable != sdc_->clkThruTristateEnabled()) {
2375     search_->arrivalsInvalid();
2376     sdc_->setClkThruTristateEnabled(enable);
2377   }
2378 }
2379 
2380 ////////////////////////////////////////////////////////////////
2381 
2382 Corner *
findCorner(const char * corner_name)2383 Sta::findCorner(const char *corner_name)
2384 {
2385   return corners_->findCorner(corner_name);
2386 }
2387 
2388 bool
multiCorner()2389 Sta::multiCorner()
2390 {
2391   return corners_->multiCorner();
2392 }
2393 
2394 // Init one corner named "default".
2395 void
makeCorners()2396 Sta::makeCorners()
2397 {
2398   corners_ = new Corners(this);
2399   StringSet corner_names;
2400   corner_names.insert("default");
2401   corners_->makeCorners(&corner_names);
2402   cmd_corner_ = corners_->findCorner(0);
2403 }
2404 
2405 void
makeCorners(StringSet * corner_names)2406 Sta::makeCorners(StringSet *corner_names)
2407 {
2408   parasitics_->deleteParasitics();
2409   corners_->makeCorners(corner_names);
2410   makeParasiticAnalysisPts();
2411   cmd_corner_ = corners_->findCorner(0);
2412 }
2413 
2414 Corner *
cmdCorner() const2415 Sta::cmdCorner() const
2416 {
2417   return cmd_corner_;
2418 }
2419 
2420 void
setCmdCorner(Corner * corner)2421 Sta::setCmdCorner(Corner *corner)
2422 {
2423   cmd_corner_ = corner;
2424 }
2425 
2426 ////////////////////////////////////////////////////////////////
2427 
2428 // from/thrus/to are owned and deleted by Search.
2429 // Returned sequence is owned by the caller.
2430 // PathEnds are owned by Search PathGroups and deleted on next call.
2431 PathEndSeq *
findPathEnds(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,bool unconstrained,const Corner * corner,const MinMaxAll * min_max,int group_count,int endpoint_count,bool unique_pins,float slack_min,float slack_max,bool sort_by_slack,PathGroupNameSet * group_names,bool setup,bool hold,bool recovery,bool removal,bool clk_gating_setup,bool clk_gating_hold)2432 Sta::findPathEnds(ExceptionFrom *from,
2433 		  ExceptionThruSeq *thrus,
2434 		  ExceptionTo *to,
2435 		  bool unconstrained,
2436 		  const Corner *corner,
2437 		  const MinMaxAll *min_max,
2438 		  int group_count,
2439 		  int endpoint_count,
2440 		  bool unique_pins,
2441 		  float slack_min,
2442 		  float slack_max,
2443 		  bool sort_by_slack,
2444 		  PathGroupNameSet *group_names,
2445 		  bool setup,
2446 		  bool hold,
2447 		  bool recovery,
2448 		  bool removal,
2449 		  bool clk_gating_setup,
2450 		  bool clk_gating_hold)
2451 {
2452   searchPreamble();
2453   return search_->findPathEnds(from, thrus, to, unconstrained,
2454 			       corner, min_max, group_count, endpoint_count,
2455 			       unique_pins, slack_min, slack_max,
2456 			       sort_by_slack, group_names,
2457 			       setup, hold,
2458 			       recovery, removal,
2459 			       clk_gating_setup, clk_gating_hold);
2460 }
2461 
2462 ////////////////////////////////////////////////////////////////
2463 
2464 // Overall flow:
2465 //  make graph
2466 //  propagate constants
2467 //  levelize
2468 //  delay calculation
2469 //  update generated clocks
2470 //  find arrivals
2471 
2472 void
searchPreamble()2473 Sta::searchPreamble()
2474 {
2475   findDelays();
2476   updateGeneratedClks();
2477   sdc_->searchPreamble();
2478   search_->deleteFilteredArrivals();
2479 }
2480 
2481 void
setReportPathFormat(ReportPathFormat format)2482 Sta::setReportPathFormat(ReportPathFormat format)
2483 {
2484   report_path_->setPathFormat(format);
2485 }
2486 
2487 void
setReportPathFieldOrder(StringSeq * field_names)2488 Sta::setReportPathFieldOrder(StringSeq *field_names)
2489 {
2490   report_path_->setReportFieldOrder(field_names);
2491 }
2492 
2493 void
setReportPathFields(bool report_input_pin,bool report_net,bool report_cap,bool report_slew)2494 Sta::setReportPathFields(bool report_input_pin,
2495 			 bool report_net,
2496 			 bool report_cap,
2497 			 bool report_slew)
2498 {
2499   report_path_->setReportFields(report_input_pin, report_net, report_cap,
2500 				report_slew);
2501 }
2502 
2503 ReportField *
findReportPathField(const char * name)2504 Sta::findReportPathField(const char *name)
2505 {
2506   return report_path_->findField(name);
2507 }
2508 
2509 void
setReportPathDigits(int digits)2510 Sta::setReportPathDigits(int digits)
2511 {
2512   report_path_->setDigits(digits);
2513 }
2514 
2515 void
setReportPathNoSplit(bool no_split)2516 Sta::setReportPathNoSplit(bool no_split)
2517 {
2518   report_path_->setNoSplit(no_split);
2519 }
2520 
2521 void
setReportPathSigmas(bool report_sigmas)2522 Sta::setReportPathSigmas(bool report_sigmas)
2523 {
2524   report_path_->setReportSigmas(report_sigmas);
2525 }
2526 
2527 void
reportPathEnds(PathEndSeq * ends)2528 Sta::reportPathEnds(PathEndSeq *ends)
2529 {
2530   report_path_->reportPathEnds(ends);
2531 }
2532 
2533 void
reportPathEndHeader()2534 Sta::reportPathEndHeader()
2535 {
2536   report_path_->reportPathEndHeader();
2537 }
2538 
2539 void
reportPathEndFooter()2540 Sta::reportPathEndFooter()
2541 {
2542   report_path_->reportPathEndFooter();
2543 }
2544 
2545 void
reportPathEnd(PathEnd * end)2546 Sta::reportPathEnd(PathEnd *end)
2547 {
2548   report_path_->reportPathEnd(end);
2549 }
2550 
2551 void
reportPathEnd(PathEnd * end,PathEnd * prev_end)2552 Sta::reportPathEnd(PathEnd *end,
2553 		   PathEnd *prev_end)
2554 {
2555   report_path_->reportPathEnd(end, prev_end);
2556 }
2557 
2558 void
reportPath(Path * path)2559 Sta::reportPath(Path *path)
2560 {
2561   report_path_->reportPath(path);
2562 }
2563 
2564 void
updateTiming(bool full)2565 Sta::updateTiming(bool full)
2566 {
2567   searchPreamble();
2568   if (full)
2569     search_->arrivalsInvalid();
2570   search_->findAllArrivals();
2571 }
2572 
2573 void
reportClkSkew(ClockSet * clks,const Corner * corner,const SetupHold * setup_hold,int digits)2574 Sta::reportClkSkew(ClockSet *clks,
2575 		   const Corner *corner,
2576 		   const SetupHold *setup_hold,
2577 		   int digits)
2578 {
2579   ensureClkArrivals();
2580   if (clk_skews_ == nullptr)
2581     clk_skews_ = new ClkSkews(this);
2582   clk_skews_->reportClkSkew(clks, corner, setup_hold, digits);
2583 }
2584 
2585 float
findWorstClkSkew(const SetupHold * setup_hold)2586 Sta::findWorstClkSkew(const SetupHold *setup_hold)
2587 {
2588   ensureClkArrivals();
2589   if (clk_skews_ == nullptr)
2590     clk_skews_ = new ClkSkews(this);
2591   return clk_skews_->findWorstClkSkew(cmd_corner_, setup_hold);
2592 }
2593 
2594 ////////////////////////////////////////////////////////////////
2595 
2596 void
delaysInvalid()2597 Sta::delaysInvalid()
2598 {
2599   graph_delay_calc_->delaysInvalid();
2600   search_->arrivalsInvalid();
2601 }
2602 
2603 void
arrivalsInvalid()2604 Sta::arrivalsInvalid()
2605 {
2606   search_->arrivalsInvalid();
2607 }
2608 
2609 void
ensureClkArrivals()2610 Sta::ensureClkArrivals()
2611 {
2612   searchPreamble();
2613   search_->findClkArrivals();
2614 }
2615 
2616 ////////////////////////////////////////////////////////////////
2617 
2618 void
visitStartpoints(VertexVisitor * visitor)2619 Sta::visitStartpoints(VertexVisitor *visitor)
2620 {
2621   ensureGraph();
2622   search_->visitStartpoints(visitor);
2623 }
2624 
2625 void
visitEndpoints(VertexVisitor * visitor)2626 Sta::visitEndpoints(VertexVisitor *visitor)
2627 {
2628   ensureGraph();
2629   search_->visitEndpoints(visitor);
2630 }
2631 
2632 class EndpointCounter : public VertexVisitor
2633 {
2634 public:
EndpointCounter()2635   EndpointCounter() : count_(0) {}
visit(Vertex *)2636   virtual void visit(Vertex *) { count_++; }
count() const2637   int count() const { return count_; }
copy()2638   virtual EndpointCounter *copy() { return new EndpointCounter; }
2639 protected:
2640   int count_;
2641 };
2642 
2643 int
endpointCount()2644 Sta::endpointCount()
2645 {
2646   ensureGraph();
2647   EndpointCounter counter;
2648   search_->visitEndpoints(&counter);
2649   return counter.count();
2650 }
2651 
2652 PinSet *
findGroupPathPins(const char * group_path_name)2653 Sta::findGroupPathPins(const char *group_path_name)
2654 {
2655   if (!(search_->havePathGroups()
2656         && search_->arrivalsValid())) {
2657     PathEndSeq *path_ends = findPathEnds(// from, thrus, to, unconstrained
2658 					 nullptr, nullptr, nullptr, false,
2659 					 // corner, min_max,
2660 					 nullptr, MinMaxAll::max(),
2661 					 // group_count, endpoint_count, unique_pins
2662 					 1, 1, false,
2663 					 -INF, INF, // slack_min, slack_max,
2664 					 false, // sort_by_slack
2665 					 nullptr, // group_names
2666 					 // setup, hold, recovery, removal,
2667 					 true, true, true, true,
2668 					 // clk_gating_setup, clk_gating_hold
2669 					 true, true);
2670     // No use for the path end sequence.
2671     delete path_ends;
2672   }
2673 
2674   PathGroup *path_group = search_->findPathGroup(group_path_name,
2675 						 MinMax::max());
2676   PinSet *pins = new PinSet;
2677   VertexPinCollector visitor(pins);
2678   visitPathGroupVertices(path_group, &visitor, this);
2679   return pins;
2680 }
2681 
2682 ////////////////////////////////////////////////////////////////
2683 
2684 void
findRequireds()2685 Sta::findRequireds()
2686 {
2687   searchPreamble();
2688   search_->findAllArrivals();
2689   search_->findRequireds();
2690 }
2691 
2692 ////////////////////////////////////////////////////////////////
2693 
2694 VertexPathIterator *
vertexPathIterator(Vertex * vertex,const RiseFall * rf,const PathAnalysisPt * path_ap)2695 Sta::vertexPathIterator(Vertex *vertex,
2696 			const RiseFall *rf,
2697 			const PathAnalysisPt *path_ap)
2698 {
2699   return new VertexPathIterator(vertex, rf, path_ap, this);
2700 }
2701 
2702 VertexPathIterator *
vertexPathIterator(Vertex * vertex,const RiseFall * rf,const MinMax * min_max)2703 Sta::vertexPathIterator(Vertex *vertex,
2704 			const RiseFall *rf,
2705 			const MinMax *min_max)
2706 {
2707   return new VertexPathIterator(vertex, rf, min_max, this);
2708 }
2709 
2710 PathRef
vertexWorstArrivalPath(Vertex * vertex,const MinMax * min_max)2711 Sta::vertexWorstArrivalPath(Vertex *vertex,
2712 			    const MinMax *min_max)
2713 {
2714   return vertexWorstArrivalPath(vertex, nullptr, min_max);
2715 }
2716 
2717 PathRef
vertexWorstArrivalPath(Vertex * vertex,const RiseFall * rf,const MinMax * min_max)2718 Sta::vertexWorstArrivalPath(Vertex *vertex,
2719 			    const RiseFall *rf,
2720 			    const MinMax *min_max)
2721 {
2722   PathRef worst_path;
2723   Arrival worst_arrival = min_max->initValue();
2724   VertexPathIterator path_iter(vertex, rf, min_max, this);
2725   while (path_iter.hasNext()) {
2726     PathVertex *path = path_iter.next();
2727     Arrival arrival = path->arrival(this);
2728     if (!path->tag(this)->isGenClkSrcPath()
2729 	&& delayGreater(arrival, worst_arrival, min_max, this)) {
2730       worst_arrival = arrival;
2731       worst_path.init(path);
2732     }
2733   }
2734   return worst_path;
2735 }
2736 
2737 PathRef
vertexWorstRequiredPath(Vertex * vertex,const MinMax * min_max)2738 Sta::vertexWorstRequiredPath(Vertex *vertex,
2739                              const MinMax *min_max)
2740 {
2741   return vertexWorstRequiredPath(vertex, nullptr, min_max);
2742 }
2743 
2744 PathRef
vertexWorstRequiredPath(Vertex * vertex,const RiseFall * rf,const MinMax * min_max)2745 Sta::vertexWorstRequiredPath(Vertex *vertex,
2746                              const RiseFall *rf,
2747                              const MinMax *min_max)
2748 {
2749   PathRef worst_path;
2750   const MinMax *req_min_max = min_max->opposite();
2751   Arrival worst_req = req_min_max->initValue();
2752   VertexPathIterator path_iter(vertex, rf, min_max, this);
2753   while (path_iter.hasNext()) {
2754     PathVertex *path = path_iter.next();
2755     const Required path_req = path->required(this);
2756     if (!path->tag(this)->isGenClkSrcPath()
2757 	&& delayGreater(path_req, worst_req, req_min_max, this)) {
2758       worst_req = path_req;
2759       worst_path.init(path);
2760     }
2761   }
2762   return worst_path;
2763 }
2764 
2765 PathRef
vertexWorstSlackPath(Vertex * vertex,const RiseFall * rf,const MinMax * min_max)2766 Sta::vertexWorstSlackPath(Vertex *vertex,
2767 			  const RiseFall *rf,
2768 			  const MinMax *min_max)
2769 {
2770   PathRef worst_path;
2771   Slack min_slack = MinMax::min()->initValue();
2772   VertexPathIterator path_iter(vertex, rf, min_max, this);
2773   while (path_iter.hasNext()) {
2774     PathVertex *path = path_iter.next();
2775     Slack slack = path->slack(this);
2776     if (!path->tag(this)->isGenClkSrcPath()
2777 	&& delayLess(slack, min_slack, this)) {
2778       min_slack = slack;
2779       worst_path.init(path);
2780     }
2781   }
2782   return worst_path;
2783 }
2784 
2785 PathRef
vertexWorstSlackPath(Vertex * vertex,const MinMax * min_max)2786 Sta::vertexWorstSlackPath(Vertex *vertex,
2787 			  const MinMax *min_max)
2788 
2789 {
2790   return vertexWorstSlackPath(vertex, nullptr, min_max);
2791 }
2792 
2793 Arrival
vertexArrival(Vertex * vertex,const RiseFall * rf,const PathAnalysisPt * path_ap)2794 Sta::vertexArrival(Vertex *vertex,
2795 		   const RiseFall *rf,
2796 		   const PathAnalysisPt *path_ap)
2797 {
2798   return vertexArrival(vertex, rf, clk_edge_wildcard, path_ap);
2799 }
2800 
2801 Arrival
vertexArrival(Vertex * vertex,const RiseFall * rf,const ClockEdge * clk_edge,const PathAnalysisPt * path_ap)2802 Sta::vertexArrival(Vertex *vertex,
2803 		   const RiseFall *rf,
2804 		   const ClockEdge *clk_edge,
2805 		   const PathAnalysisPt *path_ap)
2806 {
2807   searchPreamble();
2808   search_->findArrivals(vertex->level());
2809   const MinMax *min_max = path_ap->pathMinMax();
2810   Arrival arrival = min_max->initValue();
2811   VertexPathIterator path_iter(vertex, rf, path_ap, this);
2812   while (path_iter.hasNext()) {
2813     Path *path = path_iter.next();
2814     const Arrival &path_arrival = path->arrival(this);
2815     ClkInfo *clk_info = path->clkInfo(search_);
2816     if ((clk_edge == clk_edge_wildcard
2817 	 || clk_info->clkEdge() == clk_edge)
2818 	&& !clk_info->isGenClkSrcPath()
2819 	&& delayGreater(path->arrival(this), arrival, min_max, this))
2820       arrival = path_arrival;
2821   }
2822   return arrival;
2823 }
2824 
2825 Required
vertexRequired(Vertex * vertex,const MinMax * min_max)2826 Sta::vertexRequired(Vertex *vertex,
2827 		    const MinMax *min_max)
2828 {
2829   return vertexRequired(vertex, nullptr, clk_edge_wildcard, nullptr, min_max);
2830 }
2831 
2832 Required
vertexRequired(Vertex * vertex,const RiseFall * rf,const MinMax * min_max)2833 Sta::vertexRequired(Vertex *vertex,
2834 		    const RiseFall *rf,
2835 		    const MinMax *min_max)
2836 {
2837   return vertexRequired(vertex, rf, clk_edge_wildcard, nullptr, min_max);
2838 }
2839 
2840 Required
vertexRequired(Vertex * vertex,const RiseFall * rf,const PathAnalysisPt * path_ap)2841 Sta::vertexRequired(Vertex *vertex,
2842 		    const RiseFall *rf,
2843 		    const PathAnalysisPt *path_ap)
2844 {
2845   return vertexRequired(vertex, rf, clk_edge_wildcard, path_ap, nullptr);
2846 }
2847 
2848 Required
vertexRequired(Vertex * vertex,const RiseFall * rf,const ClockEdge * clk_edge,const PathAnalysisPt * path_ap)2849 Sta::vertexRequired(Vertex *vertex,
2850 		    const RiseFall *rf,
2851 		    const ClockEdge *clk_edge,
2852 		    const PathAnalysisPt *path_ap)
2853 {
2854   return vertexRequired(vertex, rf, clk_edge, path_ap, nullptr);
2855 }
2856 
2857 Required
vertexRequired(Vertex * vertex,const RiseFall * rf,const ClockEdge * clk_edge,const PathAnalysisPt * path_ap,const MinMax * min_max)2858 Sta::vertexRequired(Vertex *vertex,
2859 		    const RiseFall *rf,
2860 		    const ClockEdge *clk_edge,
2861 		    const PathAnalysisPt *path_ap,
2862 		    const MinMax *min_max)
2863 {
2864   findRequired(vertex);
2865   const MinMax *req_min_max = min_max
2866     ? min_max->opposite()
2867     : path_ap->pathMinMax()->opposite();
2868   Required required = req_min_max->initValue();
2869   VertexPathIterator path_iter(vertex, rf, path_ap, min_max, this);
2870   while (path_iter.hasNext()) {
2871     const Path *path = path_iter.next();
2872     const Required path_required = path->required(this);
2873     if ((clk_edge == clk_edge_wildcard
2874 	 || path->clkEdge(search_) == clk_edge)
2875 	&& delayGreater(path_required, required, req_min_max, this))
2876       required = path_required;
2877   }
2878   return required;
2879 }
2880 
2881 Slack
netSlack(const Net * net,const MinMax * min_max)2882 Sta::netSlack(const Net *net,
2883 	      const MinMax *min_max)
2884 {
2885   ensureGraph();
2886   Slack slack = MinMax::min()->initValue();
2887   NetPinIterator *pin_iter = network_->pinIterator(net);
2888   while (pin_iter->hasNext()) {
2889     Pin *pin = pin_iter->next();
2890     if (network_->isLoad(pin)) {
2891       Vertex *vertex = graph_->pinLoadVertex(pin);
2892       Slack pin_slack = vertexSlack(vertex, min_max);
2893       if (delayLess(pin_slack, slack, this))
2894 	slack = pin_slack;
2895     }
2896   }
2897   return slack;
2898 }
2899 
2900 Slack
pinSlack(const Pin * pin,const MinMax * min_max)2901 Sta::pinSlack(const Pin *pin,
2902 	      const MinMax *min_max)
2903 {
2904   ensureGraph();
2905   Vertex *vertex, *bidirect_drvr_vertex;
2906   graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
2907   Slack slack = MinMax::min()->initValue();
2908   if (vertex)
2909     slack = vertexSlack(vertex, min_max);
2910   if (bidirect_drvr_vertex) {
2911     Slack slack1 = vertexSlack(bidirect_drvr_vertex, min_max);
2912     if (delayLess(slack1, slack, this))
2913       slack = slack1;
2914   }
2915   return slack;
2916 }
2917 
2918 Slack
pinSlack(const Pin * pin,const RiseFall * rf,const MinMax * min_max)2919 Sta::pinSlack(const Pin *pin,
2920 	      const RiseFall *rf,
2921 	      const MinMax *min_max)
2922 {
2923   ensureGraph();
2924   Vertex *vertex, *bidirect_drvr_vertex;
2925   graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
2926   Slack slack = MinMax::min()->initValue();
2927   if (vertex)
2928     slack = vertexSlack(vertex, rf, min_max);
2929   if (bidirect_drvr_vertex) {
2930     Slack slack1 = vertexSlack(bidirect_drvr_vertex, rf, min_max);
2931     if (delayLess(slack1, slack, this))
2932       slack = slack1;
2933   }
2934   return slack;
2935 }
2936 
2937 Slack
vertexSlack(Vertex * vertex,const MinMax * min_max)2938 Sta::vertexSlack(Vertex *vertex,
2939 		 const MinMax *min_max)
2940 {
2941   findRequired(vertex);
2942   MinMax *min = MinMax::min();
2943   Slack slack = min->initValue();
2944   VertexPathIterator path_iter(vertex, this);
2945   while (path_iter.hasNext()) {
2946     Path *path = path_iter.next();
2947     if (path->minMax(this) == min_max) {
2948       Slack path_slack = path->slack(this);
2949       if (delayLess(path_slack, slack, this))
2950 	slack = path_slack;
2951     }
2952   }
2953   return slack;
2954 }
2955 
2956 Slack
vertexSlack(Vertex * vertex,const RiseFall * rf,const MinMax * min_max)2957 Sta::vertexSlack(Vertex *vertex,
2958 		 const RiseFall *rf,
2959 		 const MinMax *min_max)
2960 {
2961   findRequired(vertex);
2962   Slack slack = MinMax::min()->initValue();
2963   VertexPathIterator path_iter(vertex, rf, min_max, this);
2964   while (path_iter.hasNext()) {
2965     Path *path = path_iter.next();
2966     Slack path_slack = path->slack(this);
2967     if (delayLess(path_slack, slack, this))
2968       slack = path_slack;
2969   }
2970   return slack;
2971 }
2972 
2973 Slack
vertexSlack(Vertex * vertex,const RiseFall * rf,const PathAnalysisPt * path_ap)2974 Sta::vertexSlack(Vertex *vertex,
2975 		 const RiseFall *rf,
2976 		 const PathAnalysisPt *path_ap)
2977 {
2978   findRequired(vertex);
2979   return vertexSlack1(vertex, rf, clk_edge_wildcard, path_ap);
2980 }
2981 
2982 Slack
vertexSlack(Vertex * vertex,const RiseFall * rf,const ClockEdge * clk_edge,const PathAnalysisPt * path_ap)2983 Sta::vertexSlack(Vertex *vertex,
2984 		 const RiseFall *rf,
2985 		 const ClockEdge *clk_edge,
2986 		 const PathAnalysisPt *path_ap)
2987 {
2988   findRequired(vertex);
2989   return vertexSlack1(vertex, rf, clk_edge, path_ap);
2990 }
2991 
2992 Slack
vertexSlack1(Vertex * vertex,const RiseFall * rf,const ClockEdge * clk_edge,const PathAnalysisPt * path_ap)2993 Sta::vertexSlack1(Vertex *vertex,
2994 		  const RiseFall *rf,
2995 		  const ClockEdge *clk_edge,
2996 		  const PathAnalysisPt *path_ap)
2997 {
2998   MinMax *min = MinMax::min();
2999   Slack slack = min->initValue();
3000   VertexPathIterator path_iter(vertex, rf, path_ap, this);
3001   while (path_iter.hasNext()) {
3002     Path *path = path_iter.next();
3003     Slack path_slack = path->slack(this);
3004     if ((clk_edge == clk_edge_wildcard
3005 	 || path->clkEdge(search_) == clk_edge)
3006 	&& delayLess(path_slack, slack, this))
3007       slack = path_slack;
3008   }
3009   return slack;
3010 }
3011 
3012 void
vertexSlacks(Vertex * vertex,Slack (& slacks)[RiseFall::index_count][MinMax::index_count])3013 Sta::vertexSlacks(Vertex *vertex,
3014 		  Slack (&slacks)[RiseFall::index_count][MinMax::index_count])
3015 {
3016   findRequired(vertex);
3017   for(int rf_index : RiseFall::rangeIndex()) {
3018     for(MinMax *min_max : MinMax::range()) {
3019       slacks[rf_index][min_max->index()] = MinMax::min()->initValue();
3020     }
3021   }
3022   VertexPathIterator path_iter(vertex, this);
3023   while (path_iter.hasNext()) {
3024     Path *path = path_iter.next();
3025     Slack path_slack = path->slack(this);
3026     int rf_index = path->rfIndex(this);
3027     int mm_index = path->minMax(this)->index();
3028     if (delayLess(path_slack, slacks[rf_index][mm_index], this))
3029       slacks[rf_index][mm_index] = path_slack;
3030   }
3031 }
3032 
3033 void
findRequired(Vertex * vertex)3034 Sta::findRequired(Vertex *vertex)
3035 {
3036   searchPreamble();
3037   search_->findAllArrivals();
3038   search_->findRequireds(vertex->level());
3039   if (sdc_->crprEnabled()
3040       && search_->crprPathPruningEnabled()
3041       && !search_->crprApproxMissingRequireds()
3042       // Clocks invariably have requireds that are pruned but isn't
3043       // worth finding arrivals and requireds all over again for
3044       // the entire fanout of the clock.
3045       && !search_->isClock(vertex)
3046       && vertex->requiredsPruned()) {
3047     // Invalidate arrivals and requireds and disable
3048     // path pruning on fanout vertices with DFS.
3049     int fanout = 0;
3050     disableFanoutCrprPruning(vertex, fanout);
3051     debugPrint(debug_, "search", 1, "resurrect pruned required %s fanout %d",
3052                vertex->name(sdc_network_),
3053                fanout);
3054     // Find fanout arrivals and requireds with pruning disabled.
3055     search_->findArrivals();
3056     search_->findRequireds(vertex->level());
3057   }
3058 }
3059 
3060 void
disableFanoutCrprPruning(Vertex * vertex,int & fanout)3061 Sta::disableFanoutCrprPruning(Vertex *vertex,
3062 			      int &fanout)
3063 {
3064   if (!vertex->crprPathPruningDisabled()) {
3065     search_->arrivalInvalid(vertex);
3066     search_->requiredInvalid(vertex);
3067     vertex->setCrprPathPruningDisabled(true);
3068     fanout++;
3069     SearchPred *pred = search_->searchAdj();
3070     VertexOutEdgeIterator edge_iter(vertex, graph_);
3071     while (edge_iter.hasNext()) {
3072       Edge *edge = edge_iter.next();
3073       Vertex *to_vertex = edge->to(graph_);
3074       if (pred->searchThru(edge)
3075 	  && pred->searchTo(to_vertex))
3076 	disableFanoutCrprPruning(to_vertex, fanout);
3077     }
3078   }
3079 }
3080 
3081 Slack
totalNegativeSlack(const MinMax * min_max)3082 Sta::totalNegativeSlack(const MinMax *min_max)
3083 {
3084   searchPreamble();
3085   return search_->totalNegativeSlack(min_max);
3086 }
3087 
3088 Slack
totalNegativeSlack(const Corner * corner,const MinMax * min_max)3089 Sta::totalNegativeSlack(const Corner *corner,
3090 			const MinMax *min_max)
3091 {
3092   searchPreamble();
3093   return search_->totalNegativeSlack(corner, min_max);
3094 }
3095 
3096 void
worstSlack(const MinMax * min_max,Slack & worst_slack,Vertex * & worst_vertex)3097 Sta::worstSlack(const MinMax *min_max,
3098 		// Return values.
3099 		Slack &worst_slack,
3100 		Vertex *&worst_vertex)
3101 {
3102   searchPreamble();
3103   return search_->worstSlack(min_max, worst_slack, worst_vertex);
3104 }
3105 
3106 void
worstSlack(const Corner * corner,const MinMax * min_max,Slack & worst_slack,Vertex * & worst_vertex)3107 Sta::worstSlack(const Corner *corner,
3108 		const MinMax *min_max,
3109 		// Return values.
3110 		Slack &worst_slack,
3111 		Vertex *&worst_vertex)
3112 {
3113   searchPreamble();
3114   return search_->worstSlack(corner, min_max, worst_slack, worst_vertex);
3115 }
3116 
3117 ////////////////////////////////////////////////////////////////
3118 
3119 string *
reportDelayCalc(Edge * edge,TimingArc * arc,const Corner * corner,const MinMax * min_max,int digits)3120 Sta::reportDelayCalc(Edge *edge,
3121 		     TimingArc *arc,
3122 		     const Corner *corner,
3123 		     const MinMax *min_max,
3124 		     int digits)
3125 {
3126   findDelays();
3127   return graph_delay_calc_->reportDelayCalc(edge, arc, corner, min_max, digits);
3128 }
3129 
3130 void
setArcDelayCalc(const char * delay_calc_name)3131 Sta::setArcDelayCalc(const char *delay_calc_name)
3132 {
3133   delete arc_delay_calc_;
3134   arc_delay_calc_ = makeDelayCalc(delay_calc_name, sta_);
3135   // Update pointers to arc_delay_calc.
3136   updateComponentsState();
3137   graph_delay_calc_->delaysInvalid();
3138   search_->arrivalsInvalid();
3139 }
3140 
3141 void
findDelays(Vertex * to_vertex)3142 Sta::findDelays(Vertex *to_vertex)
3143 {
3144   delayCalcPreamble();
3145   graph_delay_calc_->findDelays(to_vertex->level());
3146 }
3147 
3148 void
findDelays()3149 Sta::findDelays()
3150 {
3151   delayCalcPreamble();
3152   graph_delay_calc_->findDelays(levelize_->maxLevel());
3153 }
3154 
3155 void
findDelays(Level level)3156 Sta::findDelays(Level level)
3157 {
3158   delayCalcPreamble();
3159   graph_delay_calc_->findDelays(level);
3160 }
3161 
3162 void
delayCalcPreamble()3163 Sta::delayCalcPreamble()
3164 {
3165   ensureClkNetwork();
3166 }
3167 
3168 void
setIncrementalDelayTolerance(float tol)3169 Sta::setIncrementalDelayTolerance(float tol)
3170 {
3171   graph_delay_calc_->setIncrementalDelayTolerance(tol);
3172 }
3173 
3174 ArcDelay
arcDelay(Edge * edge,TimingArc * arc,const DcalcAnalysisPt * dcalc_ap)3175 Sta::arcDelay(Edge *edge,
3176 	      TimingArc *arc,
3177 	      const DcalcAnalysisPt *dcalc_ap)
3178 {
3179   findDelays(edge->to(graph_));
3180   return graph_->arcDelay(edge, arc, dcalc_ap->index());
3181 }
3182 
3183 bool
arcDelayAnnotated(Edge * edge,TimingArc * arc,DcalcAnalysisPt * dcalc_ap)3184 Sta::arcDelayAnnotated(Edge *edge,
3185 		       TimingArc *arc,
3186 		       DcalcAnalysisPt *dcalc_ap)
3187 {
3188   return graph_->arcDelayAnnotated(edge, arc, dcalc_ap->index());
3189 }
3190 
3191 void
setArcDelayAnnotated(Edge * edge,TimingArc * arc,DcalcAnalysisPt * dcalc_ap,bool annotated)3192 Sta::setArcDelayAnnotated(Edge *edge,
3193 			  TimingArc *arc,
3194 			  DcalcAnalysisPt *dcalc_ap,
3195 			  bool annotated)
3196 {
3197   graph_->setArcDelayAnnotated(edge, arc, dcalc_ap->index(), annotated);
3198   Vertex *to = edge->to(graph_);
3199   search_->arrivalInvalid(to);
3200   search_->requiredInvalid(edge->from(graph_));
3201   if (!annotated)
3202     graph_delay_calc_->delayInvalid(to);
3203 }
3204 
3205 Slew
vertexSlew(Vertex * vertex,const RiseFall * rf,const Corner * corner,const MinMax * min_max)3206 Sta::vertexSlew(Vertex *vertex,
3207 		const RiseFall *rf,
3208                 const Corner *corner,
3209                 const MinMax *min_max)
3210 {
3211   findDelays(vertex);
3212   const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
3213   return graph_->slew(vertex, rf, dcalc_ap->index());
3214 }
3215 
3216 Slew
vertexSlew(Vertex * vertex,const RiseFall * rf,const DcalcAnalysisPt * dcalc_ap)3217 Sta::vertexSlew(Vertex *vertex,
3218 		const RiseFall *rf,
3219 		const DcalcAnalysisPt *dcalc_ap)
3220 {
3221   findDelays(vertex);
3222   return graph_->slew(vertex, rf, dcalc_ap->index());
3223 }
3224 
3225 Slew
vertexSlew(Vertex * vertex,const RiseFall * rf,const MinMax * min_max)3226 Sta::vertexSlew(Vertex *vertex,
3227 		const RiseFall *rf,
3228 		const MinMax *min_max)
3229 {
3230   findDelays(vertex);
3231   Slew mm_slew = min_max->initValue();
3232   for (DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
3233     Slew slew = graph_->slew(vertex, rf, dcalc_ap->index());
3234     if (delayGreater(slew, mm_slew, min_max, this))
3235       mm_slew = slew;
3236   }
3237   return mm_slew;
3238 }
3239 
3240 ////////////////////////////////////////////////////////////////
3241 
3242 Graph *
ensureGraph()3243 Sta::ensureGraph()
3244 {
3245   if (graph_ == nullptr && network_) {
3246     makeGraph();
3247     // Update pointers to graph.
3248     updateComponentsState();
3249   }
3250   return graph_;
3251 }
3252 
3253 void
makeGraph()3254 Sta::makeGraph()
3255 {
3256   graph_ = new Graph(this, 2, true, corners_->dcalcAnalysisPtCount());
3257   graph_->makeGraph();
3258 }
3259 
3260 void
ensureLevelized()3261 Sta::ensureLevelized()
3262 {
3263   ensureGraph();
3264   ensureGraphSdcAnnotated();
3265   // Need constant propagation before levelization to know edges that
3266   // are disabled by constants.
3267   sim_->ensureConstantsPropagated();
3268   levelize_->ensureLevelized();
3269 }
3270 
3271 void
updateGeneratedClks()3272 Sta::updateGeneratedClks()
3273 {
3274   if (update_genclks_) {
3275     ensureLevelized();
3276     bool gen_clk_changed = true;
3277     while (gen_clk_changed) {
3278       gen_clk_changed = false;
3279       for (Clock *clk : sdc_->clks()) {
3280 	if (clk->isGenerated() && !clk->waveformValid()) {
3281 	  search_->genclks()->ensureMaster(clk);
3282 	  Clock *master_clk = clk->masterClk();
3283 	  if (master_clk && master_clk->waveformValid()) {
3284 	    clk->generate(master_clk);
3285 	    gen_clk_changed = true;
3286 	  }
3287 	}
3288       }
3289     }
3290   }
3291   update_genclks_ = false;
3292 }
3293 
3294 Level
vertexLevel(Vertex * vertex)3295 Sta::vertexLevel(Vertex *vertex)
3296 {
3297   ensureLevelized();
3298   return vertex->level();
3299 }
3300 
3301 GraphLoopSeq *
graphLoops()3302 Sta::graphLoops()
3303 {
3304   ensureLevelized();
3305   return levelize_->loops();
3306 }
3307 
3308 PathAnalysisPt *
pathAnalysisPt(Path * path)3309 Sta::pathAnalysisPt(Path *path)
3310 {
3311   return path->pathAnalysisPt(this);
3312 }
3313 
3314 DcalcAnalysisPt *
pathDcalcAnalysisPt(Path * path)3315 Sta::pathDcalcAnalysisPt(Path *path)
3316 {
3317   return pathAnalysisPt(path)->dcalcAnalysisPt();
3318 }
3319 
3320 Vertex *
maxArrivalCountVertex() const3321 Sta::maxArrivalCountVertex() const
3322 {
3323   Vertex *max_vertex = nullptr;
3324   int max_count = 0;
3325   VertexIterator vertex_iter(graph_);
3326   while (vertex_iter.hasNext()) {
3327     Vertex *vertex = vertex_iter.next();
3328     int count = vertexArrivalCount(vertex);
3329     if (count > max_count) {
3330       max_count = count;
3331       max_vertex = vertex;
3332     }
3333   }
3334   return max_vertex;
3335 }
3336 
3337 int
vertexArrivalCount(Vertex * vertex) const3338 Sta::vertexArrivalCount(Vertex  *vertex) const
3339 {
3340   TagGroup *tag_group = search_->tagGroup(vertex);
3341   if (tag_group)
3342     return tag_group->arrivalCount();
3343   else
3344     return 0;
3345 }
3346 
3347 int
arrivalCount() const3348 Sta::arrivalCount() const
3349 {
3350   int count = 0;
3351   VertexIterator vertex_iter(graph_);
3352   while (vertex_iter.hasNext()) {
3353     Vertex *vertex = vertex_iter.next();
3354     count += vertexArrivalCount(vertex);
3355   }
3356   return count;
3357 }
3358 
3359 TagIndex
tagCount() const3360 Sta::tagCount() const
3361 {
3362   return search_->tagCount();
3363 }
3364 
3365 TagGroupIndex
tagGroupCount() const3366 Sta::tagGroupCount() const
3367 {
3368   return search_->tagGroupCount();
3369 }
3370 
3371 int
clkInfoCount() const3372 Sta::clkInfoCount() const
3373 {
3374   return search_->clkInfoCount();
3375 }
3376 
3377 void
setArcDelay(Edge * edge,TimingArc * arc,const Corner * corner,const MinMaxAll * min_max,ArcDelay delay)3378 Sta::setArcDelay(Edge *edge,
3379 		 TimingArc *arc,
3380 		 const Corner *corner,
3381 		 const MinMaxAll *min_max,
3382 		 ArcDelay delay)
3383 {
3384   for (MinMax *mm : min_max->range()) {
3385     const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(mm);
3386     DcalcAPIndex ap_index = dcalc_ap->index();
3387     graph_->setArcDelay(edge, arc, ap_index, delay);
3388     // Don't let delay calculation clobber the value.
3389     graph_->setArcDelayAnnotated(edge, arc, ap_index, true);
3390   }
3391   if (edge->role()->isTimingCheck())
3392     search_->requiredInvalid(edge->to(graph_));
3393   else {
3394     search_->arrivalInvalid(edge->to(graph_));
3395     search_->requiredInvalid(edge->from(graph_));
3396   }
3397 }
3398 
3399 void
setAnnotatedSlew(Vertex * vertex,const Corner * corner,const MinMaxAll * min_max,const RiseFallBoth * rf,float slew)3400 Sta::setAnnotatedSlew(Vertex *vertex,
3401 		      const Corner *corner,
3402 		      const MinMaxAll *min_max,
3403 		      const RiseFallBoth *rf,
3404 		      float slew)
3405 {
3406   for (MinMax *mm : min_max->range()) {
3407     const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(mm);
3408     DcalcAPIndex ap_index = dcalc_ap->index();
3409     for (RiseFall *rf1 : rf->range()) {
3410       graph_->setSlew(vertex, rf1, ap_index, slew);
3411       // Don't let delay calculation clobber the value.
3412       vertex->setSlewAnnotated(true, rf1, ap_index);
3413     }
3414   }
3415   graph_delay_calc_->delayInvalid(vertex);
3416 }
3417 
3418 void
writeSdf(const char * filename,Corner * corner,char sdf_divider,int digits,bool gzip,bool no_timestamp,bool no_version)3419 Sta::writeSdf(const char *filename,
3420 	      Corner *corner,
3421 	      char sdf_divider,
3422 	      int digits,
3423 	      bool gzip,
3424 	      bool no_timestamp,
3425 	      bool no_version)
3426 {
3427   findDelays();
3428   sta::writeSdf(filename, corner, sdf_divider, digits, gzip, no_timestamp,
3429 		no_version, this);
3430 }
3431 
3432 void
removeDelaySlewAnnotations()3433 Sta::removeDelaySlewAnnotations()
3434 {
3435   graph_->removeDelaySlewAnnotations();
3436   graph_delay_calc_->delaysInvalid();
3437 }
3438 
3439 LogicValue
simLogicValue(const Pin * pin)3440 Sta::simLogicValue(const Pin *pin)
3441 {
3442   ensureGraph();
3443   sim_->ensureConstantsPropagated();
3444   return sim_->logicValue(pin);
3445 }
3446 
3447 void
findLogicConstants()3448 Sta::findLogicConstants()
3449 {
3450   ensureGraph();
3451   sim_->findLogicConstants();
3452 }
3453 
3454 void
clearLogicConstants()3455 Sta::clearLogicConstants()
3456 {
3457   sim_->clear();
3458 }
3459 
3460 void
setPortExtPinCap(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float cap)3461 Sta::setPortExtPinCap(Port *port,
3462 		      const RiseFallBoth *rf,
3463 		      const MinMaxAll *min_max,
3464 		      float cap)
3465 {
3466   for (RiseFall *rf1 : rf->range()) {
3467     for (MinMax *mm : min_max->range()) {
3468       sdc_->setPortExtPinCap(port, rf1, mm, cap);
3469     }
3470   }
3471   delaysInvalidFromFanin(port);
3472 }
3473 
3474 void
portExtCaps(Port * port,const MinMax * min_max,float & pin_cap,float & wire_cap,int & fanout)3475 Sta::portExtCaps(Port *port,
3476                  const MinMax *min_max,
3477                  float &pin_cap,
3478                  float &wire_cap,
3479                  int &fanout)
3480 {
3481   bool pin_exists = false;
3482   bool wire_exists = false;
3483   bool fanout_exists = false;
3484   pin_cap = min_max->initValue();
3485   wire_cap = min_max->initValue();
3486   fanout = min_max->initValue();
3487   for (RiseFall *rf : RiseFall::range()) {
3488     float pin_cap1, wire_cap1;
3489     int fanout1;
3490     bool pin_exists1, wire_exists1, fanout_exists1;
3491     sdc_->portExtCap(port, rf, min_max,
3492                      pin_cap1, pin_exists1,
3493                      wire_cap1, wire_exists1,
3494                      fanout1, fanout_exists1);
3495     if (pin_exists1) {
3496       pin_cap = min_max->minMax(pin_cap, pin_cap1);
3497       pin_exists = true;
3498     }
3499     if (wire_exists1) {
3500       wire_cap = min_max->minMax(wire_cap, wire_cap1);
3501       wire_exists = true;
3502     }
3503     if (fanout_exists1) {
3504       fanout = min_max->minMax(fanout, fanout1);
3505       fanout_exists = true;
3506     }
3507   }
3508   if (!pin_exists)
3509     pin_cap = 0.0;
3510   if (!wire_exists)
3511     wire_cap = 0.0;
3512   if (!fanout_exists)
3513     fanout = 0;
3514 }
3515 
3516 void
setPortExtWireCap(Port * port,bool subtract_pin_cap,const RiseFallBoth * rf,const MinMaxAll * min_max,float cap)3517 Sta::setPortExtWireCap(Port *port,
3518 		       bool subtract_pin_cap,
3519 		       const RiseFallBoth *rf,
3520 		       const MinMaxAll *min_max,
3521 		       float cap)
3522 {
3523   Corner *corner = cmd_corner_;
3524   for (RiseFall *rf1 : rf->range()) {
3525     for (MinMax *mm : min_max->range()) {
3526       sdc_->setPortExtWireCap(port, subtract_pin_cap, rf1, corner, mm, cap);
3527     }
3528   }
3529   delaysInvalidFromFanin(port);
3530 }
3531 
3532 void
removeNetLoadCaps() const3533 Sta::removeNetLoadCaps() const
3534 {
3535   sdc_->removeNetLoadCaps();
3536   graph_delay_calc_->delaysInvalid();
3537 }
3538 
3539 void
setPortExtFanout(Port * port,int fanout,const MinMaxAll * min_max)3540 Sta::setPortExtFanout(Port *port,
3541 		      int fanout,
3542 		      const MinMaxAll *min_max)
3543 {
3544   for (MinMax *mm : min_max->range())
3545     sdc_->setPortExtFanout(port, mm, fanout);
3546   delaysInvalidFromFanin(port);
3547 }
3548 
3549 void
setNetWireCap(Net * net,bool subtract_pin_cap,const Corner * corner,const MinMaxAll * min_max,float cap)3550 Sta::setNetWireCap(Net *net,
3551 		   bool subtract_pin_cap,
3552 		   const Corner *corner,
3553 		   const MinMaxAll *min_max,
3554 		   float cap)
3555 {
3556   if (corner == nullptr) {
3557     for (Corner *corner : *corners_) {
3558       for (MinMax *mm : min_max->range())
3559         sdc_->setNetWireCap(net, subtract_pin_cap, corner, mm, cap);
3560     }
3561   }
3562   else {
3563     for (MinMax *mm : min_max->range())
3564       sdc_->setNetWireCap(net, subtract_pin_cap, corner, mm, cap);
3565   }
3566   delaysInvalidFromFanin(net);
3567 }
3568 
3569 void
connectedCap(Pin * drvr_pin,const RiseFall * rf,const Corner * corner,const MinMax * min_max,float & pin_cap,float & wire_cap) const3570 Sta::connectedCap(Pin *drvr_pin,
3571 		  const RiseFall *rf,
3572 		  const Corner *corner,
3573 		  const MinMax *min_max,
3574 		  float &pin_cap,
3575 		  float &wire_cap) const
3576 {
3577   pin_cap = 0.0;
3578   wire_cap = 0.0;
3579   bool cap_exists = false;
3580   const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
3581   Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap);
3582   float ap_pin_cap = 0.0;
3583   float ap_wire_cap = 0.0;
3584   graph_delay_calc_->loadCap(drvr_pin, parasitic, rf, dcalc_ap,
3585 			     ap_pin_cap, ap_wire_cap);
3586   arc_delay_calc_->finishDrvrPin();
3587   if (!cap_exists
3588       || min_max->compare(ap_pin_cap, pin_cap)) {
3589     pin_cap = ap_pin_cap;
3590     wire_cap = ap_wire_cap;
3591     cap_exists = true;
3592   }
3593 }
3594 
3595 void
connectedCap(Net * net,Corner * corner,const MinMax * min_max,float & pin_cap,float & wire_cap) const3596 Sta::connectedCap(Net *net,
3597 		  Corner *corner,
3598 		  const MinMax *min_max,
3599 		  float &pin_cap,
3600 		  float &wire_cap) const
3601 {
3602   Pin *drvr_pin = findNetParasiticDrvrPin(net);
3603   if (drvr_pin) {
3604     pin_cap = min_max->initValue();
3605     wire_cap = min_max->initValue();
3606     for (const Corner *corner : makeCornerSeq(corner)) {
3607       for (RiseFall *rf : RiseFall::range()) {
3608         float pin_cap1, wire_cap1;
3609         connectedCap(drvr_pin, rf, corner, min_max, pin_cap1, wire_cap1);
3610         pin_cap = min_max->minMax(pin_cap, pin_cap1);
3611         wire_cap = min_max->minMax(wire_cap, wire_cap1);
3612       }
3613     }
3614   }
3615   else {
3616     pin_cap = 0.0;
3617     wire_cap = 0.0;
3618   }
3619 }
3620 
3621 CornerSeq
makeCornerSeq(Corner * corner) const3622 Sta::makeCornerSeq(Corner *corner) const
3623 {
3624   CornerSeq corners;
3625   if (corner)
3626     corners.push_back(corner);
3627   else
3628     corners = corners_->corners();
3629   return corners;
3630 }
3631 
3632 float
capacitance(const LibertyPort * port,Corner * corner,const MinMax * min_max)3633 Sta::capacitance(const LibertyPort *port,
3634                  Corner *corner,
3635                  const MinMax *min_max)
3636 {
3637   OperatingConditions *op_cond = operatingConditions(min_max);
3638   float cap = min_max->initValue();
3639   for (const Corner *corner : makeCornerSeq(corner)) {
3640     int lib_ap = corner->libertyIndex(min_max);
3641     const LibertyPort *corner_port = port->cornerPort(lib_ap);
3642     for (RiseFall *rf : RiseFall::range())
3643       cap = min_max->minMax(cap, corner_port->capacitance(rf, min_max, op_cond, op_cond));
3644   }
3645   return cap;
3646 }
3647 
3648 // Look for a driver to find a parasitic if the net has one.
3649 // Settle for a load pin if there are no drivers.
3650 Pin *
findNetParasiticDrvrPin(Net * net) const3651 Sta::findNetParasiticDrvrPin(Net *net) const
3652 {
3653   Pin *load_pin = nullptr;
3654   NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
3655   while (pin_iter->hasNext()) {
3656     Pin *pin = pin_iter->next();
3657     if (network_->isDriver(pin)) {
3658       delete pin_iter;
3659       return pin;
3660     }
3661     if (network_->isLoad(pin))
3662       load_pin = pin;
3663   }
3664   delete pin_iter;
3665   return load_pin;
3666 }
3667 
3668 void
setResistance(Net * net,const MinMaxAll * min_max,float res)3669 Sta::setResistance(Net *net,
3670 		   const MinMaxAll *min_max,
3671 		   float res)
3672 {
3673   sdc_->setResistance(net, min_max, res);
3674 }
3675 
3676 ////////////////////////////////////////////////////////////////
3677 
3678 bool
readSpef(const char * filename,Instance * instance,const Corner * corner,const MinMaxAll * min_max,bool increment,bool pin_cap_included,bool keep_coupling_caps,float coupling_cap_factor,ReducedParasiticType reduce_to,bool delete_after_reduce,bool quiet)3679 Sta::readSpef(const char *filename,
3680 	      Instance *instance,
3681               const Corner *corner,
3682 	      const MinMaxAll *min_max,
3683 	      bool increment,
3684 	      bool pin_cap_included,
3685 	      bool keep_coupling_caps,
3686 	      float coupling_cap_factor,
3687 	      ReducedParasiticType reduce_to,
3688 	      bool delete_after_reduce,
3689 	      bool quiet)
3690 {
3691   setParasiticAnalysisPts(corner != nullptr,
3692                           min_max != MinMaxAll::all());
3693   if (corner == nullptr)
3694     corner = cmd_corner_;
3695   const MinMax *cnst_min_max = (min_max == MinMaxAll::all())
3696     ? MinMax::max()
3697     : min_max->asMinMax();
3698   ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(cnst_min_max);
3699   const OperatingConditions *op_cond =
3700     sdc_->operatingConditions(cnst_min_max);
3701   bool success = readSpefFile(filename, instance, ap, increment,
3702 			      pin_cap_included,
3703 			      keep_coupling_caps, coupling_cap_factor,
3704 			      reduce_to, delete_after_reduce,
3705 			      op_cond, corner, cnst_min_max, quiet,
3706 			      report_, network_, parasitics_);
3707   graph_delay_calc_->delaysInvalid();
3708   search_->arrivalsInvalid();
3709   return success;
3710 }
3711 
3712 void
setParasiticAnalysisPts(bool per_corner,bool per_min_max)3713 Sta::setParasiticAnalysisPts(bool per_corner,
3714                              bool per_min_max)
3715 {
3716   if (per_corner != parasitics_per_corner_
3717       || per_min_max != parasitics_per_min_max_) {
3718     deleteParasitics();
3719     parasitics_per_corner_ = per_corner;
3720     parasitics_per_min_max_ = per_min_max;
3721     makeParasiticAnalysisPts();
3722   }
3723 }
3724 
3725 void
makeParasiticAnalysisPts()3726 Sta::makeParasiticAnalysisPts()
3727 {
3728   corners_->makeParasiticAnalysisPts(parasitics_per_corner_,
3729                                      parasitics_per_min_max_);
3730 }
3731 
3732 void
findPiElmore(Pin * drvr_pin,const RiseFall * rf,const MinMax * min_max,float & c2,float & rpi,float & c1,bool & exists) const3733 Sta::findPiElmore(Pin *drvr_pin,
3734 		  const RiseFall *rf,
3735 		  const MinMax *min_max,
3736 		  float &c2,
3737 		  float &rpi,
3738 		  float &c1,
3739 		  bool &exists) const
3740 {
3741   Corner *corner = cmd_corner_;
3742   const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
3743   Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, rf, ap);
3744   if (pi_elmore) {
3745     parasitics_->piModel(pi_elmore, c2, rpi, c1);
3746     exists = true;
3747   }
3748   else
3749     exists = false;
3750 }
3751 
3752 void
makePiElmore(Pin * drvr_pin,const RiseFall * rf,const MinMaxAll * min_max,float c2,float rpi,float c1)3753 Sta::makePiElmore(Pin *drvr_pin,
3754 		  const RiseFall *rf,
3755 		  const MinMaxAll *min_max,
3756 		  float c2,
3757 		  float rpi,
3758 		  float c1)
3759 {
3760   Corner *corner = cmd_corner_;
3761   for (MinMax *mm : min_max->range()) {
3762     ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(mm);
3763     parasitics_->makePiElmore(drvr_pin, rf, ap, c2, rpi, c1);
3764   }
3765   delaysInvalidFrom(drvr_pin);
3766 }
3767 
3768 void
findElmore(Pin * drvr_pin,Pin * load_pin,const RiseFall * rf,const MinMax * min_max,float & elmore,bool & exists) const3769 Sta::findElmore(Pin *drvr_pin,
3770 		Pin *load_pin,
3771 		const RiseFall *rf,
3772 		const MinMax *min_max,
3773 		float &elmore,
3774 		bool &exists) const
3775 {
3776   Corner *corner = cmd_corner_;
3777   const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
3778   Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, rf, ap);
3779   if (pi_elmore) {
3780     exists = false;
3781     parasitics_->findElmore(pi_elmore, load_pin, elmore, exists);
3782   }
3783   else
3784     exists = false;
3785 }
3786 
3787 void
setElmore(Pin * drvr_pin,Pin * load_pin,const RiseFall * rf,const MinMaxAll * min_max,float elmore)3788 Sta::setElmore(Pin *drvr_pin,
3789 	       Pin *load_pin,
3790 	       const RiseFall *rf,
3791 	       const MinMaxAll *min_max,
3792 	       float elmore)
3793 {
3794   Corner *corner = cmd_corner_;
3795   for (MinMax *mm : min_max->range()) {
3796     const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(mm);
3797     Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, rf, ap);
3798     if (pi_elmore)
3799       parasitics_->setElmore(pi_elmore, load_pin, elmore);
3800   }
3801   delaysInvalidFrom(drvr_pin);
3802 }
3803 
3804 void
deleteParasitics()3805 Sta::deleteParasitics()
3806 {
3807   parasitics_->deleteParasitics();
3808   graph_delay_calc_->delaysInvalid();
3809   search_->arrivalsInvalid();
3810 }
3811 
3812 Parasitic *
makeParasiticNetwork(const Net * net,bool includes_pin_caps,const ParasiticAnalysisPt * ap)3813 Sta::makeParasiticNetwork(const Net *net,
3814                           bool includes_pin_caps,
3815                           const ParasiticAnalysisPt *ap)
3816 {
3817   Parasitic *parasitic = parasitics_->makeParasiticNetwork(net, includes_pin_caps, ap);
3818   delaysInvalidFromFanin(const_cast<Net*>(net));
3819   return parasitic;
3820 }
3821 
3822 ////////////////////////////////////////////////////////////////
3823 //
3824 // Network edit commands.
3825 //
3826 // This implementation calls Sta before/after methods to
3827 // update the Sta components.
3828 // A different implementation may let the network edits
3829 // call the before/after methods implicitly so these functions
3830 // should not (Verific).
3831 //
3832 ////////////////////////////////////////////////////////////////
3833 
3834 NetworkEdit *
networkCmdEdit()3835 Sta::networkCmdEdit()
3836 {
3837   return dynamic_cast<NetworkEdit*>(cmd_network_);
3838 }
3839 
3840 Instance *
makeInstance(const char * name,LibertyCell * cell,Instance * parent)3841 Sta::makeInstance(const char *name,
3842 		  LibertyCell *cell,
3843 		  Instance *parent)
3844 {
3845   NetworkEdit *network = networkCmdEdit();
3846   Instance *inst = network->makeInstance(cell, name, parent);
3847   network->makePins(inst);
3848   makeInstanceAfter(inst);
3849   return inst;
3850 }
3851 
3852 void
deleteInstance(Instance * inst)3853 Sta::deleteInstance(Instance *inst)
3854 {
3855   NetworkEdit *network = networkCmdEdit();
3856   deleteInstanceBefore(inst);
3857   network->deleteInstance(inst);
3858 }
3859 
3860 void
replaceCell(Instance * inst,LibertyCell * to_lib_cell)3861 Sta::replaceCell(Instance *inst,
3862 		 LibertyCell *to_lib_cell)
3863 {
3864   Cell *to_cell = network_->cell(to_lib_cell);
3865   replaceCell(inst, to_cell, to_lib_cell);
3866 }
3867 
3868 void
replaceCell(Instance * inst,Cell * to_cell)3869 Sta::replaceCell(Instance *inst,
3870 		 Cell *to_cell)
3871 {
3872   LibertyCell *to_lib_cell = network_->libertyCell(to_cell);
3873   replaceCell(inst, to_cell, to_lib_cell);
3874 }
3875 
3876 void
replaceCell(Instance * inst,Cell * to_cell,LibertyCell * to_lib_cell)3877 Sta::replaceCell(Instance *inst,
3878 		 Cell *to_cell,
3879 		 LibertyCell *to_lib_cell)
3880 {
3881   NetworkEdit *network = networkCmdEdit();
3882   LibertyCell *from_lib_cell = network->libertyCell(inst);
3883   if (sta::equivCells(from_lib_cell, to_lib_cell)) {
3884     replaceEquivCellBefore(inst, to_lib_cell);
3885     network->replaceCell(inst, to_cell);
3886     replaceEquivCellAfter(inst);
3887   }
3888   else {
3889     replaceCellBefore(inst, to_lib_cell);
3890     network->replaceCell(inst, to_cell);
3891     replaceCellAfter(inst);
3892   }
3893 }
3894 
3895 Net *
makeNet(const char * name,Instance * parent)3896 Sta::makeNet(const char *name,
3897 	     Instance *parent)
3898 {
3899   NetworkEdit *network = networkCmdEdit();
3900   Net *net = network->makeNet(name, parent);
3901   // Sta notification unnecessary.
3902   return net;
3903 }
3904 
3905 void
deleteNet(Net * net)3906 Sta::deleteNet(Net *net)
3907 {
3908   NetworkEdit *network = networkCmdEdit();
3909   deleteNetBefore(net);
3910   network->deleteNet(net);
3911 }
3912 
3913 void
connectPin(Instance * inst,Port * port,Net * net)3914 Sta::connectPin(Instance *inst,
3915 		Port *port,
3916 		Net *net)
3917 {
3918   NetworkEdit *network = networkCmdEdit();
3919   Pin *pin = network->connect(inst, port, net);
3920   connectPinAfter(pin);
3921 }
3922 
3923 void
connectPin(Instance * inst,LibertyPort * port,Net * net)3924 Sta::connectPin(Instance *inst,
3925 		LibertyPort *port,
3926 		Net *net)
3927 {
3928   NetworkEdit *network = networkCmdEdit();
3929   Pin *pin = network->connect(inst, port, net);
3930   connectPinAfter(pin);
3931 }
3932 
3933 void
disconnectPin(Pin * pin)3934 Sta::disconnectPin(Pin *pin)
3935 {
3936   NetworkEdit *network = networkCmdEdit();
3937   disconnectPinBefore(pin);
3938   network->disconnectPin(pin);
3939 }
3940 
3941 ////////////////////////////////////////////////////////////////
3942 //
3943 // Network edit before/after methods.
3944 //
3945 ////////////////////////////////////////////////////////////////
3946 
3947 void
makeInstanceAfter(Instance * inst)3948 Sta::makeInstanceAfter(Instance *inst)
3949 {
3950   // There is no user "connect_pin" called for internal pins,
3951   // so call it implicitly.
3952   LibertyCell *lib_cell = network_->libertyCell(inst);
3953   if (lib_cell
3954       && lib_cell->hasInternalPorts()) {
3955     LibertyCellPortBitIterator port_iter(lib_cell);
3956     while (port_iter.hasNext()) {
3957       LibertyPort *lib_port = port_iter.next();
3958       if (lib_port->direction()->isInternal()) {
3959 	Pin *pin = network_->findPin(inst, lib_port);
3960 	if (pin)
3961 	  connectPinAfter(pin);
3962       }
3963     }
3964   }
3965 }
3966 
3967 // Not used by Sta (connectPinAfter).
3968 void
makePinAfter(Pin * pin)3969 Sta::makePinAfter(Pin *pin)
3970 {
3971   if (!network_->isHierarchical(pin) && graph_) {
3972     Vertex *vertex, *bidir_drvr_vertex;
3973     graph_->makePinVertices(pin, vertex, bidir_drvr_vertex);
3974     graph_->makePinInstanceEdges(pin);
3975     search_->arrivalInvalid(vertex);
3976     search_->requiredInvalid(vertex);
3977     if (bidir_drvr_vertex) {
3978       search_->arrivalInvalid(bidir_drvr_vertex);
3979       search_->requiredInvalid(bidir_drvr_vertex);
3980     }
3981     if (network_->net(pin))
3982       connectPinAfter(pin);
3983   }
3984   sim_->makePinAfter(pin);
3985 }
3986 
3987 void
replaceEquivCellBefore(Instance * inst,LibertyCell * to_cell)3988 Sta::replaceEquivCellBefore(Instance *inst,
3989 			    LibertyCell *to_cell)
3990 {
3991   if (graph_) {
3992     InstancePinIterator *pin_iter = network_->pinIterator(inst);
3993     while (pin_iter->hasNext()) {
3994       Pin *pin = pin_iter->next();
3995       LibertyPort *port = network_->libertyPort(pin);
3996       if (port->direction()->isAnyInput()) {
3997 	Vertex *vertex = graph_->pinLoadVertex(pin);
3998 	replaceCellPinInvalidate(port, vertex, to_cell);
3999 
4000 	// Replace the timing arc sets in the graph edges.
4001 	VertexOutEdgeIterator edge_iter(vertex, graph_);
4002 	while (edge_iter.hasNext()) {
4003 	  Edge *edge = edge_iter.next();
4004 	  Vertex *to_vertex = edge->to(graph_);
4005 	  if (network_->instance(to_vertex->pin()) == inst) {
4006 	    TimingArcSet *from_set = edge->timingArcSet();
4007 	    // Find corresponding timing arc set.
4008 	    TimingArcSet *to_set = to_cell->findTimingArcSet(from_set);
4009 	    if (to_set)
4010 	      edge->setTimingArcSet(to_set);
4011 	    else
4012 	      report_->critical(264, "corresponding timing arc set not found in equiv cells");
4013 	  }
4014 	}
4015       }
4016       else {
4017 	// Force delay calculation on output pins.
4018 	Vertex *vertex = graph_->pinDrvrVertex(pin);
4019 	graph_delay_calc_->delayInvalid(vertex);
4020       }
4021     }
4022     delete pin_iter;
4023   }
4024 }
4025 
4026 void
replaceEquivCellAfter(Instance * inst)4027 Sta::replaceEquivCellAfter(Instance *inst)
4028 {
4029   if (graph_) {
4030     InstancePinIterator *pin_iter = network_->pinIterator(inst);
4031     while (pin_iter->hasNext()) {
4032       Pin *pin = pin_iter->next();
4033       if (network_->direction(pin)->isAnyInput())
4034 	parasitics_->loadPinCapacitanceChanged(pin);
4035     }
4036     delete pin_iter;
4037   }
4038 }
4039 
4040 void
replaceCellPinInvalidate(LibertyPort * from_port,Vertex * vertex,LibertyCell * to_cell)4041 Sta::replaceCellPinInvalidate(LibertyPort *from_port,
4042 			      Vertex *vertex,
4043 			      LibertyCell *to_cell)
4044 {
4045   LibertyPort *to_port = to_cell->findLibertyPort(from_port->name());
4046   if (!libertyPortCapsEqual(to_port, from_port)
4047       // If this is an ideal clock pin, do not invalidate
4048       // arrivals and delay calc on the clock pin driver.
4049       && !(to_port->isClock()
4050 	   && idealClockMode()))
4051     // Input port capacitance changed, so invalidate delay
4052     // calculation from input driver.
4053     delaysInvalidFromFanin(vertex);
4054   else
4055     delaysInvalidFrom(vertex);
4056 }
4057 
4058 bool
idealClockMode()4059 Sta::idealClockMode()
4060 {
4061   for (Clock *clk : sdc_->clks()) {
4062     if (clk->isPropagated())
4063       return false;
4064   }
4065   return true;
4066 }
4067 
4068 static bool
libertyPortCapsEqual(LibertyPort * port1,LibertyPort * port2)4069 libertyPortCapsEqual(LibertyPort *port1,
4070 		     LibertyPort *port2)
4071 {
4072   return port1->capacitance(RiseFall::rise(), MinMax::min())
4073     == port2->capacitance(RiseFall::rise(), MinMax::min())
4074     && port1->capacitance(RiseFall::rise(), MinMax::max())
4075     == port2->capacitance(RiseFall::rise(), MinMax::max())
4076     && port1->capacitance(RiseFall::fall(), MinMax::min())
4077     == port2->capacitance(RiseFall::fall(), MinMax::min())
4078     && port1->capacitance(RiseFall::fall(), MinMax::max())
4079     == port2->capacitance(RiseFall::fall(), MinMax::max());
4080 }
4081 
4082 void
replaceCellBefore(Instance * inst,LibertyCell * to_cell)4083 Sta::replaceCellBefore(Instance *inst,
4084 		       LibertyCell *to_cell)
4085 {
4086   if (graph_) {
4087     // Delete all graph edges between instance pins.
4088     InstancePinIterator *pin_iter = network_->pinIterator(inst);
4089     while (pin_iter->hasNext()) {
4090       Pin *pin = pin_iter->next();
4091       LibertyPort *port = network_->libertyPort(pin);
4092       if (port->direction()->isAnyInput()) {
4093 	Vertex *vertex = graph_->pinLoadVertex(pin);
4094 	replaceCellPinInvalidate(port, vertex, to_cell);
4095 
4096 	VertexOutEdgeIterator edge_iter(vertex, graph_);
4097 	while (edge_iter.hasNext()) {
4098 	  Edge *edge = edge_iter.next();
4099 	  Vertex *to_vertex = edge->to(graph_);
4100 	  if (network_->instance(to_vertex->pin()) == inst)
4101 	    deleteEdge(edge);
4102 	}
4103       }
4104     }
4105     delete pin_iter;
4106   }
4107 }
4108 
4109 void
replaceCellAfter(Instance * inst)4110 Sta::replaceCellAfter(Instance *inst)
4111 {
4112   if (graph_) {
4113     graph_->makeInstanceEdges(inst);
4114     InstancePinIterator *pin_iter = network_->pinIterator(inst);
4115     while (pin_iter->hasNext()) {
4116       Pin *pin = pin_iter->next();
4117       sim_->pinSetFuncAfter(pin);
4118       if (network_->direction(pin)->isAnyInput())
4119 	parasitics_->loadPinCapacitanceChanged(pin);
4120     }
4121     delete pin_iter;
4122   }
4123 }
4124 
4125 void
connectPinAfter(Pin * pin)4126 Sta::connectPinAfter(Pin *pin)
4127 {
4128   if (graph_) {
4129     if (network_->isHierarchical(pin)) {
4130       graph_->makeWireEdgesThruPin(pin);
4131       EdgesThruHierPinIterator edge_iter(pin, network_, graph_);
4132       while (edge_iter.hasNext()) {
4133 	Edge *edge = edge_iter.next();
4134 	if (edge->role()->isWire()) {
4135 	  connectDrvrPinAfter(edge->from(graph_));
4136 	  connectLoadPinAfter(edge->to(graph_));
4137 	}
4138       }
4139     }
4140     else {
4141       Vertex *vertex, *bidir_drvr_vertex;
4142       if (network_->vertexId(pin) == vertex_id_null) {
4143 	graph_->makePinVertices(pin, vertex, bidir_drvr_vertex);
4144 	graph_->makePinInstanceEdges(pin);
4145       }
4146       else
4147 	graph_->pinVertices(pin, vertex, bidir_drvr_vertex);
4148       search_->arrivalInvalid(vertex);
4149       search_->requiredInvalid(vertex);
4150       if (bidir_drvr_vertex) {
4151 	search_->arrivalInvalid(bidir_drvr_vertex);
4152 	search_->requiredInvalid(bidir_drvr_vertex);
4153       }
4154 
4155       // Make interconnect edges from/to pin.
4156       if (network_->isDriver(pin)) {
4157 	graph_->makeWireEdgesFromPin(pin);
4158 	connectDrvrPinAfter(bidir_drvr_vertex ? bidir_drvr_vertex : vertex);
4159       }
4160       // Note that a bidirect is both a driver and a load so this
4161       // is NOT an else clause for the above "if".
4162       if (network_->isLoad(pin)) {
4163 	graph_->makeWireEdgesToPin(pin);
4164 	connectLoadPinAfter(vertex);
4165       }
4166     }
4167   }
4168   sdc_->connectPinAfter(pin);
4169   sim_->connectPinAfter(pin);
4170 }
4171 
4172 void
connectDrvrPinAfter(Vertex * vertex)4173 Sta::connectDrvrPinAfter(Vertex *vertex)
4174 {
4175   // Invalidate arrival at fanout vertices.
4176   VertexOutEdgeIterator edge_iter(vertex, graph_);
4177   while (edge_iter.hasNext()) {
4178     Edge *edge = edge_iter.next();
4179     Vertex *to_vertex = edge->to(graph_);
4180     search_->arrivalInvalid(to_vertex);
4181     search_->endpointInvalid(to_vertex);
4182     sdc_->clkHpinDisablesChanged(to_vertex->pin());
4183   }
4184   Pin *pin = vertex->pin();
4185   sdc_->clkHpinDisablesChanged(pin);
4186   graph_delay_calc_->delayInvalid(vertex);
4187   search_->requiredInvalid(vertex);
4188   search_->endpointInvalid(vertex);
4189   levelize_->invalidFrom(vertex);
4190   clk_network_->connectPinAfter(pin);
4191 }
4192 
4193 void
connectLoadPinAfter(Vertex * vertex)4194 Sta::connectLoadPinAfter(Vertex *vertex)
4195 {
4196   // Invalidate delays and required at fanin vertices.
4197   VertexInEdgeIterator edge_iter(vertex, graph_);
4198   while (edge_iter.hasNext()) {
4199     Edge *edge = edge_iter.next();
4200     Vertex *from_vertex = edge->from(graph_);
4201     graph_delay_calc_->delayInvalid(from_vertex);
4202     search_->requiredInvalid(from_vertex);
4203     sdc_->clkHpinDisablesChanged(from_vertex->pin());
4204   }
4205   Pin *pin = vertex->pin();
4206   sdc_->clkHpinDisablesChanged(pin);
4207   graph_delay_calc_->delayInvalid(vertex);
4208   levelize_->invalidFrom(vertex);
4209   search_->arrivalInvalid(vertex);
4210   search_->endpointInvalid(vertex);
4211   clk_network_->connectPinAfter(pin);
4212 }
4213 
4214 void
disconnectPinBefore(Pin * pin)4215 Sta::disconnectPinBefore(Pin *pin)
4216 {
4217   parasitics_->disconnectPinBefore(pin);
4218   sdc_->disconnectPinBefore(pin);
4219   sim_->disconnectPinBefore(pin);
4220   if (graph_) {
4221     if (network_->isDriver(pin)) {
4222       Vertex *vertex = graph_->pinDrvrVertex(pin);
4223       // Delete wire edges from pin.
4224       if (vertex) {
4225 	VertexOutEdgeIterator edge_iter(vertex, graph_);
4226 	while (edge_iter.hasNext()) {
4227 	  Edge *edge = edge_iter.next();
4228 	  if (edge->role()->isWire())
4229 	    deleteEdge(edge);
4230 	}
4231 	clk_network_->disconnectPinBefore(pin);
4232       }
4233     }
4234     if (network_->isLoad(pin)) {
4235       // Delete wire edges to pin.
4236       Vertex *vertex = graph_->pinLoadVertex(pin);
4237       if (vertex) {
4238 	VertexInEdgeIterator edge_iter(vertex, graph_);
4239 	while (edge_iter.hasNext()) {
4240 	  Edge *edge = edge_iter.next();
4241 	  if (edge->role()->isWire())
4242 	    deleteEdge(edge);
4243 	}
4244 	clk_network_->disconnectPinBefore(pin);
4245       }
4246     }
4247     if (network_->isHierarchical(pin)) {
4248       // Delete wire edges thru pin.
4249       EdgesThruHierPinIterator edge_iter(pin, network_, graph_);
4250       while (edge_iter.hasNext()) {
4251 	Edge *edge = edge_iter.next();
4252 	if (edge->role()->isWire()) {
4253 	  deleteEdge(edge);
4254 	  clk_network_->disconnectPinBefore(edge->from(graph_)->pin());
4255 	}
4256       }
4257     }
4258   }
4259 }
4260 
4261 void
deleteEdge(Edge * edge)4262 Sta::deleteEdge(Edge *edge)
4263 {
4264   Vertex *from = edge->from(graph_);
4265   Vertex *to = edge->to(graph_);
4266   search_->arrivalInvalid(to);
4267   search_->requiredInvalid(from);
4268   graph_delay_calc_->delayInvalid(to);
4269   levelize_->relevelizeFrom(to);
4270   levelize_->deleteEdgeBefore(edge);
4271   sdc_->clkHpinDisablesChanged(edge->from(graph_)->pin());
4272   graph_->deleteEdge(edge);
4273 }
4274 
4275 void
deleteNetBefore(Net * net)4276 Sta::deleteNetBefore(Net *net)
4277 {
4278   if (graph_) {
4279     NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
4280     while (pin_iter->hasNext()) {
4281       Pin *pin = pin_iter->next();
4282       if (!network_->isHierarchical(pin)) {
4283 	disconnectPinBefore(pin);
4284 	// Delete wire edges on net pins.
4285 	Vertex *vertex = graph_->pinDrvrVertex(pin);
4286 	if (vertex) {
4287 	  VertexOutEdgeIterator edge_iter(vertex, graph_);
4288 	  while (edge_iter.hasNext()) {
4289 	    Edge *edge = edge_iter.next();
4290 	    if (edge->role()->isWire())
4291 	      deleteEdge(edge);
4292 	  }
4293 	}
4294       }
4295     }
4296     delete pin_iter;
4297   }
4298   sdc_->deleteNetBefore(net);
4299 }
4300 
4301 void
deleteInstanceBefore(Instance * inst)4302 Sta::deleteInstanceBefore(Instance *inst)
4303 {
4304   if (network_->isLeaf(inst)) {
4305     deleteInstancePinsBefore(inst);
4306     deleteLeafInstanceBefore(inst);
4307   }
4308   else {
4309     // Delete hierarchical instance children.
4310     InstanceChildIterator *child_iter = network_->childIterator(inst);
4311     while (child_iter->hasNext()) {
4312       Instance *child = child_iter->next();
4313       deleteInstanceBefore(child);
4314     }
4315     delete child_iter;
4316   }
4317 }
4318 
4319 void
deleteLeafInstanceBefore(Instance * inst)4320 Sta::deleteLeafInstanceBefore(Instance *inst)
4321 {
4322   sim_->deleteInstanceBefore(inst);
4323 }
4324 
4325 void
deleteInstancePinsBefore(Instance * inst)4326 Sta::deleteInstancePinsBefore(Instance *inst)
4327 {
4328   InstancePinIterator *pin_iter = network_->pinIterator(inst);
4329   while (pin_iter->hasNext()) {
4330     Pin *pin = pin_iter->next();
4331     deletePinBefore(pin);
4332   }
4333   delete pin_iter;
4334 }
4335 
4336 void
deletePinBefore(Pin * pin)4337 Sta::deletePinBefore(Pin *pin)
4338 {
4339   if (graph_) {
4340     if (network_->isLoad(pin)) {
4341       Vertex *vertex = graph_->pinLoadVertex(pin);
4342       if (vertex) {
4343         levelize_->deleteVertexBefore(vertex);
4344         graph_delay_calc_->deleteVertexBefore(vertex);
4345         search_->deleteVertexBefore(vertex);
4346 
4347         VertexInEdgeIterator in_edge_iter(vertex, graph_);
4348         while (in_edge_iter.hasNext()) {
4349           Edge *edge = in_edge_iter.next();
4350           if (edge->role()->isWire()) {
4351             Vertex *from = edge->from(graph_);
4352             // Only notify from vertex (to vertex will be deleted).
4353             search_->requiredInvalid(from);
4354           }
4355           levelize_->deleteEdgeBefore(edge);
4356         }
4357         graph_->deleteVertex(vertex);
4358       }
4359     }
4360     if (network_->isDriver(pin)) {
4361       Vertex *vertex = graph_->pinDrvrVertex(pin);
4362       if (vertex) {
4363         levelize_->deleteVertexBefore(vertex);
4364         graph_delay_calc_->deleteVertexBefore(vertex);
4365         search_->deleteVertexBefore(vertex);
4366 
4367         VertexOutEdgeIterator edge_iter(vertex, graph_);
4368         while (edge_iter.hasNext()) {
4369           Edge *edge = edge_iter.next();
4370           if (edge->role()->isWire()) {
4371             // Only notify to vertex (from will be deleted).
4372             Vertex *to = edge->to(graph_);
4373             // to->prev_paths point to vertex, so delete them.
4374             search_->arrivalInvalidDelete(to);
4375             graph_delay_calc_->delayInvalid(to);
4376             levelize_->relevelizeFrom(to);
4377           }
4378           levelize_->deleteEdgeBefore(edge);
4379         }
4380         graph_->deleteVertex(vertex);
4381       }
4382     }
4383     if (network_->direction(pin) == PortDirection::internal()) {
4384       // Internal pins are not loads or drivers.
4385       Vertex *vertex = graph_->pinLoadVertex(pin);
4386       if (vertex) {
4387         levelize_->deleteVertexBefore(vertex);
4388         graph_delay_calc_->deleteVertexBefore(vertex);
4389         search_->deleteVertexBefore(vertex);
4390         graph_->deleteVertex(vertex);
4391       }
4392     }
4393   }
4394   sim_->deletePinBefore(pin);
4395   clk_network_->deletePinBefore(pin);
4396 }
4397 
4398 void
delaysInvalidFrom(Port * port)4399 Sta::delaysInvalidFrom(Port *port)
4400 {
4401   if (graph_) {
4402     Instance *top_inst = network_->topInstance();
4403     Pin *pin = network_->findPin(top_inst, port);
4404     delaysInvalidFrom(pin);
4405   }
4406 }
4407 
4408 void
delaysInvalidFrom(Instance * inst)4409 Sta::delaysInvalidFrom(Instance *inst)
4410 {
4411   if (graph_) {
4412     InstancePinIterator *pin_iter = network_->pinIterator(inst);
4413     while (pin_iter->hasNext()) {
4414       Pin *pin = pin_iter->next();
4415       delaysInvalidFrom(pin);
4416     }
4417     delete pin_iter;
4418   }
4419 }
4420 
4421 void
delaysInvalidFrom(Pin * pin)4422 Sta::delaysInvalidFrom(Pin *pin)
4423 {
4424   if (graph_) {
4425     Vertex *vertex, *bidirect_drvr_vertex;
4426     graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
4427     delaysInvalidFrom(vertex);
4428     if (bidirect_drvr_vertex)
4429       delaysInvalidFrom(bidirect_drvr_vertex);
4430   }
4431 }
4432 
4433 void
delaysInvalidFrom(Vertex * vertex)4434 Sta::delaysInvalidFrom(Vertex *vertex)
4435 {
4436   search_->arrivalInvalid(vertex);
4437   search_->requiredInvalid(vertex);
4438   graph_delay_calc_->delayInvalid(vertex);
4439 }
4440 
4441 void
delaysInvalidFromFanin(Port * port)4442 Sta::delaysInvalidFromFanin(Port *port)
4443 {
4444   if (graph_) {
4445     Instance *top_inst = network_->topInstance();
4446     Pin *pin = network_->findPin(top_inst, port);
4447     Vertex *vertex, *bidirect_drvr_vertex;
4448     graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
4449     delaysInvalidFromFanin(vertex);
4450     if (bidirect_drvr_vertex)
4451       delaysInvalidFromFanin(bidirect_drvr_vertex);
4452   }
4453 }
4454 
4455 void
delaysInvalidFromFanin(Pin * pin)4456 Sta::delaysInvalidFromFanin(Pin *pin)
4457 {
4458   if (graph_) {
4459     Vertex *vertex, *bidirect_drvr_vertex;
4460     graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
4461     if (vertex)
4462       delaysInvalidFromFanin(vertex);
4463     if (bidirect_drvr_vertex)
4464       delaysInvalidFromFanin(bidirect_drvr_vertex);
4465   }
4466 }
4467 
4468 void
delaysInvalidFromFanin(Net * net)4469 Sta::delaysInvalidFromFanin(Net *net)
4470 {
4471   if (graph_) {
4472     NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
4473     while (pin_iter->hasNext()) {
4474       Pin *pin = pin_iter->next();
4475       if (!network_->isHierarchical(pin)) {
4476 	Vertex *vertex, *bidirect_drvr_vertex;
4477 	graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
4478 	if (vertex)
4479 	  delaysInvalidFrom(vertex);
4480 	if (bidirect_drvr_vertex)
4481 	  delaysInvalidFrom(bidirect_drvr_vertex);
4482       }
4483     }
4484     delete pin_iter;
4485   }
4486 }
4487 
4488 void
delaysInvalidFromFanin(Vertex * vertex)4489 Sta::delaysInvalidFromFanin(Vertex *vertex)
4490 {
4491   VertexInEdgeIterator edge_iter(vertex, graph_);
4492   while (edge_iter.hasNext()) {
4493     Edge *edge = edge_iter.next();
4494     Vertex *from_vertex = edge->from(graph_);
4495     delaysInvalidFrom(from_vertex);
4496     search_->requiredInvalid(from_vertex);
4497   }
4498 }
4499 
4500 ////////////////////////////////////////////////////////////////
4501 
4502 void
clocks(const Pin * pin,ClockSet & clks)4503 Sta::clocks(const Pin *pin,
4504 	    // Return value.
4505 	    ClockSet &clks)
4506 {
4507   ensureClkArrivals();
4508   search_->clocks(pin, clks);
4509 }
4510 
4511 ////////////////////////////////////////////////////////////////
4512 
4513 InstanceSet *
findRegisterInstances(ClockSet * clks,const RiseFallBoth * clk_rf,bool edge_triggered,bool latches)4514 Sta::findRegisterInstances(ClockSet *clks,
4515 			   const RiseFallBoth *clk_rf,
4516 			   bool edge_triggered,
4517 			   bool latches)
4518 {
4519   findRegisterPreamble();
4520   return findRegInstances(clks, clk_rf, edge_triggered, latches, this);
4521 }
4522 
4523 PinSet *
findRegisterDataPins(ClockSet * clks,const RiseFallBoth * clk_rf,bool edge_triggered,bool latches)4524 Sta::findRegisterDataPins(ClockSet *clks,
4525 			  const RiseFallBoth *clk_rf,
4526 			  bool edge_triggered,
4527 			  bool latches)
4528 {
4529   findRegisterPreamble();
4530   return findRegDataPins(clks, clk_rf, edge_triggered, latches, this);
4531 }
4532 
4533 PinSet *
findRegisterClkPins(ClockSet * clks,const RiseFallBoth * clk_rf,bool edge_triggered,bool latches)4534 Sta::findRegisterClkPins(ClockSet *clks,
4535 			 const RiseFallBoth *clk_rf,
4536 			 bool edge_triggered,
4537 			 bool latches)
4538 {
4539   findRegisterPreamble();
4540   return findRegClkPins(clks, clk_rf, edge_triggered, latches, this);
4541 }
4542 
4543 PinSet *
findRegisterAsyncPins(ClockSet * clks,const RiseFallBoth * clk_rf,bool edge_triggered,bool latches)4544 Sta::findRegisterAsyncPins(ClockSet *clks,
4545 			   const RiseFallBoth *clk_rf,
4546 			   bool edge_triggered,
4547 			   bool latches)
4548 {
4549   findRegisterPreamble();
4550   return findRegAsyncPins(clks, clk_rf, edge_triggered, latches, this);
4551 }
4552 
4553 PinSet *
findRegisterOutputPins(ClockSet * clks,const RiseFallBoth * clk_rf,bool edge_triggered,bool latches)4554 Sta::findRegisterOutputPins(ClockSet *clks,
4555 			    const RiseFallBoth *clk_rf,
4556 			    bool edge_triggered,
4557 			    bool latches)
4558 {
4559   findRegisterPreamble();
4560   return findRegOutputPins(clks, clk_rf, edge_triggered, latches, this);
4561 }
4562 
4563 void
findRegisterPreamble()4564 Sta::findRegisterPreamble()
4565 {
4566   ensureGraph();
4567   ensureGraphSdcAnnotated();
4568   sim_->ensureConstantsPropagated();
4569 }
4570 
4571 ////////////////////////////////////////////////////////////////
4572 
4573 class FanInOutSrchPred : public SearchPred
4574 {
4575 public:
4576   FanInOutSrchPred(bool thru_disabled,
4577 		   bool thru_constants,
4578 		   const StaState *sta);
4579   virtual bool searchFrom(const Vertex *from_vertex);
4580   virtual bool searchThru(Edge *edge);
4581   virtual bool searchTo(const Vertex *to_vertex);
4582 
4583 protected:
4584   bool crossesHierarchy(Edge *edge);
4585   virtual bool searchThruRole(Edge *edge);
4586 
4587   bool thru_disabled_;
4588   bool thru_constants_;
4589   const StaState *sta_;
4590 };
4591 
FanInOutSrchPred(bool thru_disabled,bool thru_constants,const StaState * sta)4592 FanInOutSrchPred::FanInOutSrchPred(bool thru_disabled,
4593 				   bool thru_constants,
4594 				   const StaState *sta) :
4595   SearchPred(),
4596   thru_disabled_(thru_disabled),
4597   thru_constants_(thru_constants),
4598   sta_(sta)
4599 {
4600 }
4601 
4602 bool
searchFrom(const Vertex * from_vertex)4603 FanInOutSrchPred::searchFrom(const Vertex *from_vertex)
4604 {
4605   return (thru_disabled_
4606 	  || !from_vertex->isDisabledConstraint())
4607     && (thru_constants_
4608 	|| !from_vertex->isConstant());
4609 }
4610 
4611 bool
searchThru(Edge * edge)4612 FanInOutSrchPred::searchThru(Edge *edge)
4613 {
4614   const Sdc *sdc = sta_->sdc();
4615   return searchThruRole(edge)
4616     && (thru_disabled_
4617 	|| !(edge->isDisabledConstraint()
4618 	     || edge->isDisabledCond()
4619 	     || sdc->isDisabledCondDefault(edge)))
4620     && (thru_constants_
4621 	|| edge->simTimingSense() != TimingSense::none);
4622 }
4623 
4624 bool
searchThruRole(Edge * edge)4625 FanInOutSrchPred::searchThruRole(Edge *edge)
4626 {
4627   TimingRole *role = edge->role();
4628   return role == TimingRole::wire()
4629     || role == TimingRole::combinational()
4630     || role == TimingRole::tristateEnable()
4631     || role == TimingRole::tristateDisable();
4632 }
4633 
4634 bool
crossesHierarchy(Edge * edge)4635 FanInOutSrchPred::crossesHierarchy(Edge *edge)
4636 {
4637   Network *network = sta_->network();
4638   Graph *graph = sta_->graph();
4639   Vertex *from = edge->from(graph);
4640   Vertex *to = edge->to(graph);
4641   Instance *from_inst = network->instance(from->pin());
4642   Instance *to_inst = network->instance(to->pin());
4643   return network->parent(from_inst) != network->parent(to_inst);
4644 }
4645 
4646 bool
searchTo(const Vertex * to_vertex)4647 FanInOutSrchPred::searchTo(const Vertex *to_vertex)
4648 {
4649   return (thru_disabled_
4650 	  || !to_vertex->isDisabledConstraint())
4651     && (thru_constants_
4652 	|| !to_vertex->isConstant());
4653 }
4654 
4655 class FaninSrchPred : public FanInOutSrchPred
4656 {
4657 public:
4658   FaninSrchPred(bool thru_disabled,
4659 		bool thru_constants,
4660 		const StaState *sta);
4661 
4662 protected:
4663   virtual bool searchThruRole(Edge *edge);
4664 };
4665 
FaninSrchPred(bool thru_disabled,bool thru_constants,const StaState * sta)4666 FaninSrchPred::FaninSrchPred(bool thru_disabled,
4667 			     bool thru_constants,
4668 			     const StaState *sta) :
4669   FanInOutSrchPred(thru_disabled, thru_constants, sta)
4670 {
4671 }
4672 
4673 bool
searchThruRole(Edge * edge)4674 FaninSrchPred::searchThruRole(Edge *edge)
4675 {
4676   TimingRole *role = edge->role();
4677   return role == TimingRole::wire()
4678     || role == TimingRole::combinational()
4679     || role == TimingRole::tristateEnable()
4680     || role == TimingRole::tristateDisable()
4681     || role == TimingRole::regClkToQ()
4682     || role == TimingRole::latchEnToQ();
4683 }
4684 
4685 PinSet *
findFaninPins(PinSeq * to,bool flat,bool startpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)4686 Sta::findFaninPins(PinSeq *to,
4687 		   bool flat,
4688 		   bool startpoints_only,
4689 		   int inst_levels,
4690 		   int pin_levels,
4691 		   bool thru_disabled,
4692 		   bool thru_constants)
4693 {
4694   ensureGraph();
4695   ensureLevelized();
4696   PinSet *fanin = new PinSet;
4697   FaninSrchPred pred(thru_disabled, thru_constants, this);
4698   PinSeq::Iterator to_iter(to);
4699   while (to_iter.hasNext()) {
4700     Pin *pin = to_iter.next();
4701     if (network_->isHierarchical(pin)) {
4702       EdgesThruHierPinIterator edge_iter(pin, network_, graph_);
4703       while (edge_iter.hasNext()) {
4704 	Edge *edge = edge_iter.next();
4705 	findFaninPins(edge->from(graph_), flat, startpoints_only,
4706 		      inst_levels, pin_levels, fanin, pred);
4707       }
4708     }
4709     else {
4710       Vertex *vertex = graph_->pinLoadVertex(pin);
4711       findFaninPins(vertex, flat, startpoints_only,
4712 		    inst_levels, pin_levels, fanin, pred);
4713     }
4714   }
4715   return fanin;
4716 }
4717 
4718 void
findFaninPins(Vertex * vertex,bool flat,bool startpoints_only,int inst_levels,int pin_levels,PinSet * fanin,SearchPred & pred)4719 Sta::findFaninPins(Vertex *vertex,
4720 		   bool flat,
4721 		   bool startpoints_only,
4722 		   int inst_levels,
4723 		   int pin_levels,
4724 		   PinSet *fanin,
4725 		   SearchPred &pred)
4726 {
4727   VertexSet visited;
4728   findFaninPins(vertex, flat, inst_levels,
4729 		pin_levels, visited, &pred, 0, 0);
4730   VertexSet::Iterator visited_iter(visited);
4731   while (visited_iter.hasNext()) {
4732     Vertex *visited_vertex = visited_iter.next();
4733     Pin *visited_pin = visited_vertex->pin();
4734     if (!startpoints_only
4735 	|| network_->isRegClkPin(visited_pin)
4736 	|| !hasFanin(visited_vertex, &pred, graph_))
4737       fanin->insert(visited_pin);
4738   }
4739 }
4740 
4741 void
findFaninPins(Vertex * to,bool flat,int inst_levels,int pin_levels,VertexSet & visited,SearchPred * pred,int inst_level,int pin_level)4742 Sta::findFaninPins(Vertex *to,
4743 		   bool flat,
4744 		   int inst_levels,
4745 		   int pin_levels,
4746 		   VertexSet &visited,
4747 		   SearchPred *pred,
4748 		   int inst_level,
4749 		   int pin_level)
4750 {
4751   debugPrint(debug_, "fanin", 1, "%s",
4752              to->name(sdc_network_));
4753   if (!visited.hasKey(to)) {
4754     visited.insert(to);
4755     Pin *to_pin = to->pin();
4756     bool is_reg_clk_pin = network_->isRegClkPin(to_pin);
4757     if (!is_reg_clk_pin
4758 	&& (inst_levels <= 0
4759 	    || inst_level < inst_levels)
4760 	&& (pin_levels <= 0
4761 	    || pin_level < pin_levels)
4762 	&& pred->searchTo(to)) {
4763       VertexInEdgeIterator edge_iter(to, graph_);
4764       while (edge_iter.hasNext()) {
4765 	Edge *edge = edge_iter.next();
4766 	Vertex *from_vertex = edge->from(graph_);
4767 	if (pred->searchThru(edge)
4768 	    && (flat
4769 		|| !crossesHierarchy(edge))
4770 	    && pred->searchFrom(from_vertex)) {
4771 	  findFaninPins(from_vertex, flat, inst_levels,
4772 			pin_levels, visited, pred,
4773 			edge->role()->isWire() ? inst_level : inst_level+1,
4774 			pin_level+1);
4775 	}
4776       }
4777     }
4778   }
4779 }
4780 
4781 InstanceSet *
findFaninInstances(PinSeq * to,bool flat,bool startpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)4782 Sta::findFaninInstances(PinSeq *to,
4783 			bool flat,
4784 			bool startpoints_only,
4785 			int inst_levels,
4786 			int pin_levels,
4787 			bool thru_disabled,
4788 			bool thru_constants)
4789 {
4790   PinSet *pins = findFaninPins(to, flat, startpoints_only, inst_levels,
4791 			       pin_levels, thru_disabled, thru_constants);
4792   return pinInstances(pins, network_);
4793 }
4794 
4795 PinSet *
findFanoutPins(PinSeq * from,bool flat,bool endpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)4796 Sta::findFanoutPins(PinSeq *from,
4797 		    bool flat,
4798 		    bool endpoints_only,
4799 		    int inst_levels,
4800 		    int pin_levels,
4801 		    bool thru_disabled,
4802 		    bool thru_constants)
4803 {
4804   ensureGraph();
4805   ensureLevelized();
4806   PinSet *fanout = new PinSet;
4807   FanInOutSrchPred pred(thru_disabled, thru_constants, this);
4808   PinSeq::Iterator from_iter(from);
4809   while (from_iter.hasNext()) {
4810     Pin *pin = from_iter.next();
4811     if (network_->isHierarchical(pin)) {
4812       EdgesThruHierPinIterator edge_iter(pin, network_, graph_);
4813       while (edge_iter.hasNext()) {
4814 	Edge *edge = edge_iter.next();
4815 	findFanoutPins(edge->to(graph_), flat, endpoints_only,
4816 		       inst_levels, pin_levels, fanout, pred);
4817       }
4818     }
4819     else {
4820       Vertex *vertex = graph_->pinDrvrVertex(pin);
4821       findFanoutPins(vertex, flat, endpoints_only,
4822 		     inst_levels, pin_levels, fanout, pred);
4823     }
4824   }
4825   return fanout;
4826 }
4827 
4828 void
findFanoutPins(Vertex * vertex,bool flat,bool endpoints_only,int inst_levels,int pin_levels,PinSet * fanout,SearchPred & pred)4829 Sta::findFanoutPins(Vertex *vertex,
4830 		    bool flat,
4831 		    bool endpoints_only,
4832 		    int inst_levels,
4833 		    int pin_levels,
4834 		    PinSet *fanout,
4835 		    SearchPred &pred)
4836 {
4837   VertexSet visited;
4838   findFanoutPins(vertex, flat, inst_levels,
4839 		 pin_levels, visited, &pred, 0, 0);
4840   VertexSet::Iterator visited_iter(visited);
4841   while (visited_iter.hasNext()) {
4842     Vertex *visited_vertex = visited_iter.next();
4843     Pin *visited_pin = visited_vertex->pin();
4844     if (!endpoints_only
4845 	|| search_->isEndpoint(visited_vertex, &pred))
4846       fanout->insert(visited_pin);
4847   }
4848 }
4849 
4850 // DFS to support level limits.
4851 void
findFanoutPins(Vertex * from,bool flat,int inst_levels,int pin_levels,VertexSet & visited,SearchPred * pred,int inst_level,int pin_level)4852 Sta::findFanoutPins(Vertex *from,
4853 		    bool flat,
4854 		    int inst_levels,
4855 		    int pin_levels,
4856 		    VertexSet &visited,
4857 		    SearchPred *pred,
4858 		    int inst_level,
4859 		    int pin_level)
4860 {
4861   debugPrint(debug_, "fanout", 1, "%s",
4862              from->name(sdc_network_));
4863   if (!visited.hasKey(from)) {
4864     visited.insert(from);
4865     if (!search_->isEndpoint(from, pred)
4866 	&& (inst_levels <= 0
4867 	    || inst_level < inst_levels)
4868 	&& (pin_levels <= 0
4869 	    || pin_level < pin_levels)
4870 	&& pred->searchFrom(from)) {
4871       VertexOutEdgeIterator edge_iter(from, graph_);
4872       while (edge_iter.hasNext()) {
4873 	Edge *edge = edge_iter.next();
4874 	Vertex *to_vertex = edge->to(graph_);
4875 	if (pred->searchThru(edge)
4876 	    && (flat
4877 		|| !crossesHierarchy(edge))
4878 	    && pred->searchTo(to_vertex)) {
4879 	  findFanoutPins(to_vertex, flat, inst_levels,
4880 			 pin_levels, visited, pred,
4881 			 edge->role()->isWire() ? inst_level : inst_level+1,
4882 			 pin_level+1);
4883 	}
4884       }
4885     }
4886   }
4887 }
4888 
4889 InstanceSet *
findFanoutInstances(PinSeq * from,bool flat,bool endpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)4890 Sta::findFanoutInstances(PinSeq *from,
4891 			 bool flat,
4892 			 bool endpoints_only,
4893 			 int inst_levels,
4894 			 int pin_levels,
4895 			 bool thru_disabled,
4896 			 bool thru_constants)
4897 {
4898   PinSet *pins = findFanoutPins(from, flat, endpoints_only, inst_levels,
4899 				pin_levels, thru_disabled, thru_constants);
4900   return pinInstances(pins, network_);
4901 }
4902 
4903 static InstanceSet *
pinInstances(PinSet * pins,const Network * network)4904 pinInstances(PinSet *pins,
4905 	     const Network *network)
4906 {
4907   InstanceSet *insts = new InstanceSet;
4908   PinSet::Iterator pin_iter(pins);
4909   while (pin_iter.hasNext()) {
4910     Pin *pin = pin_iter.next();
4911     insts->insert(network->instance(pin));
4912   }
4913   delete pins;
4914   return insts;
4915 }
4916 
4917 bool
crossesHierarchy(Edge * edge) const4918 Sta::crossesHierarchy(Edge *edge) const
4919 {
4920   Vertex *from = edge->from(graph_);
4921   Vertex *to = edge->to(graph_);
4922   const Pin *from_pin = from->pin();
4923   Instance *from_inst = network_->instance(from_pin);
4924   Instance *to_inst = network_->instance(to->pin());
4925   Instance *from_parent, *to_parent;
4926   // Treat input/output port pins as "inside".
4927   if (network_->isTopInstance(from_inst))
4928     from_parent = from_inst;
4929   else
4930     from_parent = network_->parent(from_inst);
4931   if (network_->isTopInstance(to_inst))
4932     to_parent = to_inst;
4933   else
4934     to_parent = network_->parent(to_inst);
4935   return from_parent != to_parent;
4936 }
4937 
4938 ////////////////////////////////////////////////////////////////
4939 
4940 class InstanceMaxSlewGreater
4941 {
4942 public:
4943   explicit InstanceMaxSlewGreater(const StaState *sta);
4944   bool operator()(const Instance *inst1,
4945 		  const Instance *inst2) const;
4946 
4947 protected:
4948   Slew instMaxSlew(const Instance *inst) const;
4949   const StaState *sta_;
4950 };
4951 
InstanceMaxSlewGreater(const StaState * sta)4952 InstanceMaxSlewGreater::InstanceMaxSlewGreater(const StaState *sta) :
4953   sta_(sta)
4954 {
4955 }
4956 
4957 bool
operator ()(const Instance * inst1,const Instance * inst2) const4958 InstanceMaxSlewGreater::operator()(const Instance *inst1,
4959 				   const Instance *inst2) const
4960 {
4961   return delayGreater(instMaxSlew(inst1), instMaxSlew(inst2), sta_);
4962 }
4963 
4964 Slew
instMaxSlew(const Instance * inst) const4965 InstanceMaxSlewGreater::instMaxSlew(const Instance *inst) const
4966 {
4967   Network *network = sta_->network();
4968   Graph *graph = sta_->graph();
4969   Slew max_slew = 0.0;
4970   InstancePinIterator *pin_iter = network->pinIterator(inst);
4971   while (pin_iter->hasNext()) {
4972     Pin *pin = pin_iter->next();
4973     if (network->isDriver(pin)) {
4974       Vertex *vertex = graph->pinDrvrVertex(pin);
4975       for (RiseFall *rf : RiseFall::range()) {
4976 	for (DcalcAnalysisPt *dcalc_ap : sta_->corners()->dcalcAnalysisPts()) {
4977 	  Slew slew = graph->slew(vertex, rf, dcalc_ap->index());
4978 	  if (delayGreater(slew, max_slew, sta_))
4979 	    max_slew = slew;
4980 	}
4981       }
4982     }
4983   }
4984   delete pin_iter;
4985   return max_slew;
4986 }
4987 
4988 SlowDrvrIterator *
slowDrvrIterator()4989 Sta::slowDrvrIterator()
4990 {
4991   InstanceSeq *insts = new InstanceSeq;
4992   LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
4993   while (leaf_iter->hasNext()) {
4994     Instance *leaf = leaf_iter->next();
4995     insts->push_back(leaf);
4996   }
4997   delete leaf_iter;
4998 
4999   sort(insts, InstanceMaxSlewGreater(this));
5000   return new SlowDrvrIterator(insts);
5001 }
5002 
5003 ////////////////////////////////////////////////////////////////
5004 
5005 void
checkSlewLimitPreamble()5006 Sta::checkSlewLimitPreamble()
5007 {
5008   if (sdc_->haveClkSlewLimits())
5009     // Arrivals are needed to know pin clock domains.
5010     updateTiming(false);
5011   else
5012     findDelays();
5013   if (check_slew_limits_ == nullptr)
5014     makeCheckSlewLimits();
5015   ensureClkNetwork();
5016 }
5017 
5018 PinSeq *
checkSlewLimits(Net * net,bool violators,const Corner * corner,const MinMax * min_max)5019 Sta::checkSlewLimits(Net *net,
5020                      bool violators,
5021                      const Corner *corner,
5022                      const MinMax *min_max)
5023 {
5024   checkSlewLimitPreamble();
5025   return check_slew_limits_->checkSlewLimits(net, violators, corner, min_max);
5026 }
5027 
5028 void
reportSlewLimitShortHeader()5029 Sta::reportSlewLimitShortHeader()
5030 {
5031   report_path_->reportLimitShortHeader(report_path_->fieldSlew());
5032 }
5033 
5034 void
reportSlewLimitShort(Pin * pin,const Corner * corner,const MinMax * min_max)5035 Sta::reportSlewLimitShort(Pin *pin,
5036 			  const Corner *corner,
5037 			  const MinMax *min_max)
5038 {
5039   const Corner *corner1;
5040   const RiseFall *rf1;
5041   Slew slew1;
5042   float limit1, slack1;
5043   check_slew_limits_->checkSlew(pin, corner, min_max, true,
5044 				corner1, rf1, slew1, limit1, slack1);
5045   report_path_->reportLimitShort(report_path_->fieldSlew(), pin,
5046 				 delayAsFloat(slew1), limit1, slack1);
5047 }
5048 
5049 void
reportSlewLimitVerbose(Pin * pin,const Corner * corner,const MinMax * min_max)5050 Sta::reportSlewLimitVerbose(Pin *pin,
5051 			    const Corner *corner,
5052 			    const MinMax *min_max)
5053 {
5054   const Corner *corner1;
5055   const RiseFall *rf1;
5056   Slew slew1;
5057   float limit1, slack1;
5058   check_slew_limits_->checkSlew(pin, corner, min_max, true,
5059 				corner1, rf1, slew1, limit1, slack1);
5060   report_path_->reportLimitVerbose(report_path_->fieldSlew(), pin, rf1,
5061 				   delayAsFloat(slew1),
5062 				   limit1, slack1, corner1, min_max);
5063 }
5064 
5065 void
checkSlew(const Pin * pin,const Corner * corner,const MinMax * min_max,bool check_clks,const Corner * & corner1,const RiseFall * & rf,Slew & slew,float & limit,float & slack)5066 Sta::checkSlew(const Pin *pin,
5067 	       const Corner *corner,
5068 	       const MinMax *min_max,
5069 	       bool check_clks,
5070 	       // Return values.
5071 	       const Corner *&corner1,
5072 	       const RiseFall *&rf,
5073 	       Slew &slew,
5074 	       float &limit,
5075 	       float &slack)
5076 {
5077   check_slew_limits_->checkSlew(pin, corner, min_max, check_clks,
5078 				corner1, rf, slew, limit, slack);
5079 }
5080 
5081 ////////////////////////////////////////////////////////////////'
5082 
5083 void
checkFanoutLimitPreamble()5084 Sta::checkFanoutLimitPreamble()
5085 {
5086   if (check_fanout_limits_ == nullptr)
5087     makeCheckFanoutLimits();
5088   ensureClkNetwork();
5089 }
5090 
5091 PinSeq *
checkFanoutLimits(Net * net,bool violators,const MinMax * min_max)5092 Sta::checkFanoutLimits(Net *net,
5093                        bool violators,
5094                        const MinMax *min_max)
5095 {
5096   checkFanoutLimitPreamble();
5097   return check_fanout_limits_->checkFanoutLimits(net, violators, min_max);
5098 }
5099 
5100 void
reportFanoutLimitShortHeader()5101 Sta::reportFanoutLimitShortHeader()
5102 {
5103   report_path_->reportLimitShortHeader(report_path_->fieldFanout());
5104 }
5105 
5106 void
reportFanoutLimitShort(Pin * pin,const MinMax * min_max)5107 Sta::reportFanoutLimitShort(Pin *pin,
5108 			    const MinMax *min_max)
5109 {
5110   float fanout, limit, slack;
5111   check_fanout_limits_->checkFanout(pin, min_max,
5112 				    fanout, limit, slack);
5113   report_path_->reportLimitShort(report_path_->fieldFanout(),
5114 				 pin, fanout, limit, slack);
5115 }
5116 
5117 void
reportFanoutLimitVerbose(Pin * pin,const MinMax * min_max)5118 Sta::reportFanoutLimitVerbose(Pin *pin,
5119 			      const MinMax *min_max)
5120 {
5121   float fanout, limit, slack;
5122   check_fanout_limits_->checkFanout(pin, min_max,
5123 				    fanout, limit, slack);
5124   report_path_->reportLimitVerbose(report_path_->fieldFanout(),
5125 				   pin, nullptr, fanout,
5126 				   limit, slack, nullptr, min_max);
5127 }
5128 
5129 void
checkFanout(const Pin * pin,const MinMax * min_max,float & fanout,float & limit,float & slack)5130 Sta::checkFanout(const Pin *pin,
5131 		 const MinMax *min_max,
5132 		 // Return values.
5133 		 float &fanout,
5134 		 float &limit,
5135 		 float &slack)
5136 {
5137   check_fanout_limits_->checkFanout(pin, min_max,
5138 				    fanout, limit, slack);
5139 }
5140 
5141 ////////////////////////////////////////////////////////////////'
5142 
5143 void
checkCapacitanceLimitPreamble()5144 Sta::checkCapacitanceLimitPreamble()
5145 {
5146   if (check_capacitance_limits_ == nullptr)
5147     makeCheckCapacitanceLimits();
5148   ensureClkNetwork();
5149 }
5150 
5151 PinSeq *
checkCapacitanceLimits(Net * net,bool violators,const Corner * corner,const MinMax * min_max)5152 Sta::checkCapacitanceLimits(Net *net,
5153                             bool violators,
5154                             const Corner *corner,
5155                             const MinMax *min_max)
5156 {
5157   checkCapacitanceLimitPreamble();
5158   return check_capacitance_limits_->checkCapacitanceLimits(net, violators,
5159                                                            corner, min_max);
5160 }
5161 
5162 void
reportCapacitanceLimitShortHeader()5163 Sta::reportCapacitanceLimitShortHeader()
5164 {
5165   report_path_->reportLimitShortHeader(report_path_->fieldCapacitance());
5166 }
5167 
5168 void
reportCapacitanceLimitShort(Pin * pin,const Corner * corner,const MinMax * min_max)5169 Sta::reportCapacitanceLimitShort(Pin *pin,
5170 				 const Corner *corner,
5171 				 const MinMax *min_max)
5172 {
5173   const Corner *corner1;
5174   const RiseFall *rf;
5175   float capacitance, limit, slack;
5176   check_capacitance_limits_->checkCapacitance(pin, corner, min_max,
5177 					      corner1, rf, capacitance,
5178 					      limit, slack);
5179   report_path_->reportLimitShort(report_path_->fieldCapacitance(),
5180 				 pin, capacitance, limit, slack);
5181 }
5182 
5183 void
reportCapacitanceLimitVerbose(Pin * pin,const Corner * corner,const MinMax * min_max)5184 Sta::reportCapacitanceLimitVerbose(Pin *pin,
5185 				   const Corner *corner,
5186 				   const MinMax *min_max)
5187 {
5188   const Corner *corner1;
5189   const RiseFall *rf1;
5190   float capacitance1, limit1, slack1;
5191   check_capacitance_limits_->checkCapacitance(pin, corner, min_max,
5192 					      corner1, rf1, capacitance1,
5193 					      limit1, slack1);
5194   report_path_->reportLimitVerbose(report_path_->fieldCapacitance(),
5195 				   pin, rf1, capacitance1,
5196 				   limit1, slack1, corner1, min_max);
5197 }
5198 
5199 void
checkCapacitance(const Pin * pin,const Corner * corner,const MinMax * min_max,const Corner * & corner1,const RiseFall * & rf,float & capacitance,float & limit,float & slack)5200 Sta::checkCapacitance(const Pin *pin,
5201 		      const Corner *corner,
5202 		      const MinMax *min_max,
5203 		      // Return values.
5204 		      const Corner *&corner1,
5205 		      const RiseFall *&rf,
5206 		      float &capacitance,
5207 		      float &limit,
5208 		      float &slack)
5209 {
5210   check_capacitance_limits_->checkCapacitance(pin, corner, min_max,
5211 					      corner1, rf, capacitance,
5212 					      limit, slack);
5213 }
5214 
5215 ////////////////////////////////////////////////////////////////
5216 
5217 void
minPulseWidthPreamble()5218 Sta::minPulseWidthPreamble()
5219 {
5220   ensureClkArrivals();
5221   if (check_min_pulse_widths_ == nullptr)
5222     makeCheckMinPulseWidths();
5223 }
5224 
5225 MinPulseWidthCheckSeq &
minPulseWidthChecks(PinSeq * pins,const Corner * corner)5226 Sta::minPulseWidthChecks(PinSeq *pins,
5227 			 const Corner *corner)
5228 {
5229   minPulseWidthPreamble();
5230   return check_min_pulse_widths_->check(pins, corner);
5231 }
5232 
5233 MinPulseWidthCheckSeq &
minPulseWidthChecks(const Corner * corner)5234 Sta::minPulseWidthChecks(const Corner *corner)
5235 {
5236   minPulseWidthPreamble();
5237   return check_min_pulse_widths_->check(corner);
5238 }
5239 
5240 MinPulseWidthCheckSeq &
minPulseWidthViolations(const Corner * corner)5241 Sta::minPulseWidthViolations(const Corner *corner)
5242 {
5243   minPulseWidthPreamble();
5244   return check_min_pulse_widths_->violations(corner);
5245 }
5246 
5247 MinPulseWidthCheck *
minPulseWidthSlack(const Corner * corner)5248 Sta::minPulseWidthSlack(const Corner *corner)
5249 {
5250   minPulseWidthPreamble();
5251   return check_min_pulse_widths_->minSlackCheck(corner);
5252 }
5253 
5254 void
reportMpwChecks(MinPulseWidthCheckSeq * checks,bool verbose)5255 Sta::reportMpwChecks(MinPulseWidthCheckSeq *checks,
5256 		     bool verbose)
5257 {
5258   report_path_->reportMpwChecks(checks, verbose);
5259 }
5260 
5261 void
reportMpwCheck(MinPulseWidthCheck * check,bool verbose)5262 Sta::reportMpwCheck(MinPulseWidthCheck *check,
5263 		    bool verbose)
5264 {
5265   report_path_->reportMpwCheck(check, verbose);
5266 }
5267 
5268 ////////////////////////////////////////////////////////////////
5269 
5270 MinPeriodCheckSeq &
minPeriodViolations()5271 Sta::minPeriodViolations()
5272 {
5273   minPeriodPreamble();
5274   return check_min_periods_->violations();
5275 }
5276 
5277 MinPeriodCheck *
minPeriodSlack()5278 Sta::minPeriodSlack()
5279 {
5280   minPeriodPreamble();
5281   return check_min_periods_->minSlackCheck();
5282 }
5283 
5284 void
minPeriodPreamble()5285 Sta::minPeriodPreamble()
5286 {
5287   // Need clk arrivals to know what clks arrive at the clk tree endpoints.
5288   ensureClkArrivals();
5289   if (check_min_periods_ == nullptr)
5290     makeCheckMinPeriods();
5291 }
5292 
5293 void
reportChecks(MinPeriodCheckSeq * checks,bool verbose)5294 Sta::reportChecks(MinPeriodCheckSeq *checks,
5295 		  bool verbose)
5296 {
5297   report_path_->reportChecks(checks, verbose);
5298 }
5299 
5300 void
reportCheck(MinPeriodCheck * check,bool verbose)5301 Sta::reportCheck(MinPeriodCheck *check,
5302 		 bool verbose)
5303 {
5304   report_path_->reportCheck(check, verbose);
5305 }
5306 
5307 ////////////////////////////////////////////////////////////////
5308 
5309 MaxSkewCheckSeq &
maxSkewViolations()5310 Sta::maxSkewViolations()
5311 {
5312   maxSkewPreamble();
5313   return check_max_skews_->violations();
5314 }
5315 
5316 MaxSkewCheck *
maxSkewSlack()5317 Sta::maxSkewSlack()
5318 {
5319   maxSkewPreamble();
5320   return check_max_skews_->minSlackCheck();
5321 }
5322 
5323 void
maxSkewPreamble()5324 Sta::maxSkewPreamble()
5325 {
5326   ensureClkArrivals();
5327   if (check_max_skews_ == nullptr)
5328     makeCheckMaxSkews();
5329 }
5330 
5331 void
reportChecks(MaxSkewCheckSeq * checks,bool verbose)5332 Sta::reportChecks(MaxSkewCheckSeq *checks,
5333 		  bool verbose)
5334 {
5335   report_path_->reportChecks(checks, verbose);
5336 }
5337 
5338 void
reportCheck(MaxSkewCheck * check,bool verbose)5339 Sta::reportCheck(MaxSkewCheck *check,
5340 		 bool verbose)
5341 {
5342   report_path_->reportCheck(check, verbose);
5343 }
5344 
5345 ////////////////////////////////////////////////////////////////
5346 
5347 void
makeEquivCells(LibertyLibrarySeq * equiv_libs,LibertyLibrarySeq * map_libs)5348 Sta::makeEquivCells(LibertyLibrarySeq *equiv_libs,
5349 		    LibertyLibrarySeq *map_libs)
5350 {
5351   delete equiv_cells_;
5352   equiv_cells_ = new EquivCells(equiv_libs, map_libs);
5353 }
5354 
5355 LibertyCellSeq *
equivCells(LibertyCell * cell)5356 Sta::equivCells(LibertyCell *cell)
5357 {
5358   if (equiv_cells_)
5359     return equiv_cells_->equivs(cell);
5360   else
5361     return nullptr;
5362 }
5363 
5364 ////////////////////////////////////////////////////////////////
5365 void
powerPreamble()5366 Sta::powerPreamble()
5367 {
5368   // Use arrivals to find clocking info.
5369   searchPreamble();
5370   search_->findAllArrivals();
5371 }
5372 
5373 void
power(const Corner * corner,PowerResult & total,PowerResult & sequential,PowerResult & combinational,PowerResult & macro,PowerResult & pad)5374 Sta::power(const Corner *corner,
5375 	   // Return values.
5376 	   PowerResult &total,
5377 	   PowerResult &sequential,
5378 	   PowerResult &combinational,
5379 	   PowerResult &macro,
5380 	   PowerResult &pad)
5381 {
5382   powerPreamble();
5383   power_->power(corner, total, sequential, combinational, macro, pad);
5384 }
5385 
5386 void
power(const Instance * inst,const Corner * corner,PowerResult & result)5387 Sta::power(const Instance *inst,
5388 	   const Corner *corner,
5389 	   // Return values.
5390 	   PowerResult &result)
5391 {
5392   powerPreamble();
5393   power_->power(inst, corner, result);
5394 }
5395 
5396 ////////////////////////////////////////////////////////////////
5397 
5398 void
ensureClkNetwork()5399 Sta::ensureClkNetwork()
5400 {
5401   ensureLevelized();
5402   clk_network_->ensureClkNetwork();
5403 }
5404 
5405 bool
isClock(const Pin * pin) const5406 Sta::isClock(const Pin *pin) const
5407 {
5408   return clk_network_->isClock(pin);
5409 }
5410 
5411 bool
isClock(const Net * net) const5412 Sta::isClock(const Net *net) const
5413 {
5414   return clk_network_->isClock(net);
5415 }
5416 
5417 bool
isIdealClock(const Pin * pin) const5418 Sta::isIdealClock(const Pin *pin) const
5419 {
5420   return clk_network_->isIdealClock(pin);
5421 }
5422 
5423 const PinSet *
pins(const Clock * clk)5424 Sta::pins(const Clock *clk)
5425 {
5426   return clk_network_->pins(clk);
5427 }
5428 
5429 void
clkPinsInvalid()5430 Sta::clkPinsInvalid()
5431 {
5432   clk_network_->clkPinsInvalid();
5433 }
5434 
5435 } // namespace
5436