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 ¯o,
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