1 %module sta
2 
3 %{
4 
5 // OpenSTA, Static Timing Analyzer
6 // Copyright (c) 2021, Parallax Software, Inc.
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 
21 ////////////////////////////////////////////////////////////////
22 //
23 // Most of the TCL SWIG interface code is in this file.  This and any
24 // optional interface code is %included into a final interface file
25 // used by the application.
26 //
27 // Define TCL methods for each network object.  This works despite the
28 // fact that the underlying implementation does not have class methods
29 // corresponding to the TCL methods defined here.
30 //
31 // Note the function name changes from sta naming convention
32 // (lower/capitalize) to TCL naming convention (lower/underscore).
33 //
34 ////////////////////////////////////////////////////////////////
35 
36 #include <limits>
37 
38 #include "Machine.hh"
39 #include "StaConfig.hh"  // STA_VERSION
40 #include "Stats.hh"
41 #include "Report.hh"
42 #include "Error.hh"
43 #include "StringUtil.hh"
44 #include "PatternMatch.hh"
45 #include "MinMax.hh"
46 #include "Fuzzy.hh"
47 #include "FuncExpr.hh"
48 #include "Units.hh"
49 #include "Transition.hh"
50 #include "TimingRole.hh"
51 #include "TimingArc.hh"
52 #include "Liberty.hh"
53 #include "EquivCells.hh"
54 #include "Wireload.hh"
55 #include "PortDirection.hh"
56 #include "Network.hh"
57 #include "Clock.hh"
58 #include "PortDelay.hh"
59 #include "ExceptionPath.hh"
60 #include "Sdc.hh"
61 #include "Graph.hh"
62 #include "Parasitics.hh"
63 #include "DelayCalc.hh"
64 #include "DcalcAnalysisPt.hh"
65 #include "Corner.hh"
66 #include "PathVertex.hh"
67 #include "PathRef.hh"
68 #include "PathExpanded.hh"
69 #include "PathEnd.hh"
70 #include "PathGroup.hh"
71 #include "PathAnalysisPt.hh"
72 #include "Property.hh"
73 #include "WritePathSpice.hh"
74 #include "Search.hh"
75 #include "Sta.hh"
76 #include "search/Tag.hh"
77 #include "search/CheckTiming.hh"
78 #include "search/CheckMinPulseWidths.hh"
79 #include "search/Levelize.hh"
80 #include "search/ReportPath.hh"
81 #include "search/Power.hh"
82 
83 namespace sta {
84 
85 ////////////////////////////////////////////////////////////////
86 //
87 // C++ helper functions used by the interface functions.
88 // These are not visible in the TCL API.
89 //
90 ////////////////////////////////////////////////////////////////
91 
92 typedef Vector<Library*> LibrarySeq;
93 typedef CellSeq TmpCellSeq;
94 typedef LibertyCellSeq TmpLibertyCellSeq;
95 typedef PortSeq TmpPortSeq;
96 typedef LibertyPortSeq TmpLibertyPortSeq;
97 typedef PinSet TmpPinSet;
98 typedef PinSeq TmpPinSeq;
99 typedef InstanceSeq TmpInstanceSeq;
100 typedef InstanceSet TmpInstanceSet;
101 typedef MinPulseWidthCheckSeq::Iterator MinPulseWidthCheckSeqIterator;
102 typedef FloatSeq TmpFloatSeq;
103 typedef string TmpString;
104 typedef Set<const char*, CharPtrLess> StringSet;
105 typedef MinMaxAll MinMaxAllNull;
106 typedef ClockSet TmpClockSet;
107 typedef StringSeq TmpStringSeq;
108 
109 using std::vector;
110 
111 // Get the network for commands.
112 Network *
cmdNetwork()113 cmdNetwork()
114 {
115   return Sta::sta()->cmdNetwork();
116 }
117 
118 // Make sure the network has been read and linked.
119 // Throwing an error means the caller doesn't have to check the result.
120 Network *
cmdLinkedNetwork()121 cmdLinkedNetwork()
122 {
123   Network *network = cmdNetwork();
124   if (network->isLinked())
125     return network;
126   else {
127     Report *report = Sta::sta()->report();
128     report->error(201, "no network has been linked.");
129     return nullptr;
130   }
131 }
132 
133 // Make sure an editable network has been read and linked.
134 NetworkEdit *
cmdEditNetwork()135 cmdEditNetwork()
136 {
137   Network *network = cmdLinkedNetwork();
138   if (network->isEditable())
139     return dynamic_cast<NetworkEdit*>(network);
140   else {
141     Report *report = Sta::sta()->report();
142     report->error(202, "network does not support edits.");
143     return nullptr;
144   }
145 }
146 
147 // Get the graph for commands.
148 // Throw to cmd level on failure.
149 Graph *
cmdGraph()150 cmdGraph()
151 {
152   cmdLinkedNetwork();
153   return Sta::sta()->ensureGraph();
154 }
155 
156 template <class TYPE>
157 Vector<TYPE> *
tclListSeq(Tcl_Obj * const source,swig_type_info * swig_type,Tcl_Interp * interp)158 tclListSeq(Tcl_Obj *const source,
159 	   swig_type_info *swig_type,
160 	   Tcl_Interp *interp)
161 {
162   int argc;
163   Tcl_Obj **argv;
164 
165   if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
166       && argc > 0) {
167     Vector<TYPE> *seq = new Vector<TYPE>;
168     for (int i = 0; i < argc; i++) {
169       void *obj;
170       // Ignore returned TCL_ERROR because can't get swig_type_info.
171       SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
172       seq->push_back(reinterpret_cast<TYPE>(obj));
173     }
174     return seq;
175   }
176   else
177     return nullptr;
178 }
179 
180 LibertyLibrarySeq *
tclListSeqLibertyLibrary(Tcl_Obj * const source,Tcl_Interp * interp)181 tclListSeqLibertyLibrary(Tcl_Obj *const source,
182 			 Tcl_Interp *interp)
183 {
184   return tclListSeq<LibertyLibrary*>(source, SWIGTYPE_p_LibertyLibrary, interp);
185 }
186 
187 vector<LibertyCell*> *
tclListSeqLibertyCell(Tcl_Obj * const source,Tcl_Interp * interp)188 tclListSeqLibertyCell(Tcl_Obj *const source,
189 		      Tcl_Interp *interp)
190 {
191   return tclListSeq<LibertyCell*>(source, SWIGTYPE_p_LibertyCell, interp);
192 }
193 
194 template <class TYPE>
195 Set<TYPE> *
tclListSet(Tcl_Obj * const source,swig_type_info * swig_type,Tcl_Interp * interp)196 tclListSet(Tcl_Obj *const source,
197 	   swig_type_info *swig_type,
198 	   Tcl_Interp *interp)
199 {
200   int argc;
201   Tcl_Obj **argv;
202 
203   if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
204       && argc > 0) {
205     Set<TYPE> *set = new Set<TYPE>;
206     for (int i = 0; i < argc; i++) {
207       void *obj;
208       // Ignore returned TCL_ERROR because can't get swig_type_info.
209       SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
210       set->insert(reinterpret_cast<TYPE>(obj));
211     }
212     return set;
213   }
214   else
215     return nullptr;
216 }
217 
218 PinSet *
tclListSetPin(Tcl_Obj * const source,Tcl_Interp * interp)219 tclListSetPin(Tcl_Obj *const source,
220               Tcl_Interp *interp)
221 {
222   return tclListSet<Pin*>(source, SWIGTYPE_p_Pin, interp);
223 }
224 
225 StringSet *
tclListSetConstChar(Tcl_Obj * const source,Tcl_Interp * interp)226 tclListSetConstChar(Tcl_Obj *const source,
227 		    Tcl_Interp *interp)
228 {
229   int argc;
230   Tcl_Obj **argv;
231 
232   if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
233     StringSet *set = new StringSet;
234     for (int i = 0; i < argc; i++) {
235       int length;
236       const char *str = Tcl_GetStringFromObj(argv[i], &length);
237       set->insert(str);
238     }
239     return set;
240   }
241   else
242     return nullptr;
243 }
244 
245 StringSeq *
tclListSeqConstChar(Tcl_Obj * const source,Tcl_Interp * interp)246 tclListSeqConstChar(Tcl_Obj *const source,
247 		    Tcl_Interp *interp)
248 {
249   int argc;
250   Tcl_Obj **argv;
251 
252   if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
253     StringSeq *seq = new StringSeq;
254     for (int i = 0; i < argc; i++) {
255       int length;
256       const char *str = Tcl_GetStringFromObj(argv[i], &length);
257       seq->push_back(str);
258     }
259     return seq;
260   }
261   else
262     return nullptr;
263 }
264 
265 ////////////////////////////////////////////////////////////////
266 
267 TmpPinSet *
findStartpoints()268 findStartpoints()
269 {
270   PinSet *pins = new PinSet;
271   VertexPinCollector visitor(pins);
272   Sta::sta()->visitStartpoints(&visitor);
273   return pins;
274 }
275 
276 TmpPinSet *
findEndpoints()277 findEndpoints()
278 {
279   PinSet *pins = new PinSet;
280   VertexPinCollector visitor(pins);
281   Sta::sta()->visitEndpoints(&visitor);
282   return pins;
283 }
284 
285 void
pushPowerResultFloats(PowerResult & power,TmpFloatSeq * floats)286 pushPowerResultFloats(PowerResult &power,
287 		      TmpFloatSeq *floats)
288 {
289   floats->push_back(power.internal());
290   floats->push_back(power.switching());
291   floats->push_back(power.leakage());
292   floats->push_back(power.total());
293 }
294 
295 ////////////////////////////////////////////////////////////////
296 
297 void
tclArgError(Tcl_Interp * interp,const char * msg,const char * arg)298 tclArgError(Tcl_Interp *interp,
299             const char *msg,
300             const char *arg)
301 {
302   // Swig does not add try/catch around arg parsing so this cannot use Report::error.
303   string error_msg = "Error: ";
304   error_msg += msg;
305   char *error = stringPrint(error_msg.c_str(), arg);
306   Tcl_SetResult(interp, error, TCL_VOLATILE);
307   stringDelete(error);
308 }
309 
310 void
objectListNext(const char * list,const char * type,bool & type_match,const char * & next)311 objectListNext(const char *list,
312 	       const char *type,
313 	       // Return values.
314 	       bool &type_match,
315 	       const char *&next)
316 {
317   // Default return values (failure).
318   type_match = false;
319   next = nullptr;
320   // _hexaddress_p_type
321   const char *s = list;
322   char ch = *s++;
323   if (ch == '_') {
324     while (*s && isxdigit(*s))
325       s++;
326     if ((s - list - 1) == sizeof(void*) * 2
327 	&& *s && *s++ == '_'
328 	&& *s && *s++ == 'p'
329 	&& *s && *s++ == '_') {
330       const char *t = type;
331       while (*s && *s != ' ') {
332 	if (*s != *t)
333 	  return;
334 	s++;
335 	t++;
336       }
337       type_match = true;
338       if (*s)
339 	next = s + 1;
340       else
341 	next = nullptr;
342     }
343   }
344 }
345 
346 } // namespace
347 
348 using namespace sta;
349 
350 %}
351 
352 ////////////////////////////////////////////////////////////////
353 //
354 // SWIG type definitions.
355 //
356 ////////////////////////////////////////////////////////////////
357 
358 // String that is deleted after crossing over to tcland.
359 %typemap(out) TmpString* {
360   string *str = $1;
361   if (str) {
362     // String is volatile because it is deleted.
363     Tcl_SetResult(interp, const_cast<char*>(str->c_str()), TCL_VOLATILE);
364     delete str;
365   }
366   else
367     Tcl_SetResult(interp, nullptr, TCL_STATIC);
368 }
369 
370 %typemap(in) StringSeq* {
371   $1 = tclListSeqConstChar($input, interp);
372 }
373 
374 %typemap(out) StringSeq* {
375   StringSeq *strs = $1;
376   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
377   StringSeq::Iterator str_iter(strs);
378   while (str_iter.hasNext()) {
379     const char *str = str_iter.next();
380     Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str));
381     Tcl_ListObjAppendElement(interp, list, obj);
382   }
383   Tcl_SetObjResult(interp, list);
384 }
385 
386 %typemap(out) TmpStringSeq* {
387   StringSeq *strs = $1;
388   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
389   StringSeq::Iterator str_iter(strs);
390   while (str_iter.hasNext()) {
391     const char *str = str_iter.next();
392     Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str));
393     Tcl_ListObjAppendElement(interp, list, obj);
394   }
395   Tcl_SetObjResult(interp, list);
396   delete strs;
397 }
398 
399 %typemap(out) Library* {
400   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
401   Tcl_SetObjResult(interp, obj);
402 }
403 
404 %typemap(out) LibraryIterator* {
405   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
406   Tcl_SetObjResult(interp, obj);
407 }
408 
409 %typemap(out) LibertyLibraryIterator* {
410   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
411   Tcl_SetObjResult(interp, obj);
412 }
413 
414 %typemap(out) Cell* {
415   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
416   Tcl_SetObjResult(interp, obj);
417 }
418 
419 %typemap(out) CellSeq* {
420   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
421   CellSeq *cells = $1;
422   CellSeq::Iterator cell_iter(cells);
423   while (cell_iter.hasNext()) {
424     Cell *cell = cell_iter.next();
425     Tcl_Obj *obj = SWIG_NewInstanceObj(cell, SWIGTYPE_p_Cell, false);
426     Tcl_ListObjAppendElement(interp, list, obj);
427   }
428   Tcl_SetObjResult(interp, list);
429 }
430 
431 %typemap(out) TmpCellSeq* {
432   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
433   CellSeq *cells = $1;
434   CellSeq::Iterator cell_iter(cells);
435   while (cell_iter.hasNext()) {
436     Cell *cell = cell_iter.next();
437     Tcl_Obj *obj = SWIG_NewInstanceObj(cell, SWIGTYPE_p_Cell, false);
438     Tcl_ListObjAppendElement(interp, list, obj);
439   }
440   Tcl_SetObjResult(interp, list);
441   delete cells;
442 }
443 
444 %typemap(in) vector<LibertyCell*> * {
445   $1 = tclListSeqLibertyCell($input, interp);
446 }
447 
448 %typemap(out) LibertyCellSeq* {
449   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
450   LibertyCellSeq *cells = $1;
451   LibertyCellSeq::Iterator cell_iter(cells);
452   while (cell_iter.hasNext()) {
453     LibertyCell *cell = cell_iter.next();
454     Tcl_Obj *obj = SWIG_NewInstanceObj(cell, SWIGTYPE_p_LibertyCell,
455 				      false);
456     Tcl_ListObjAppendElement(interp, list, obj);
457   }
458   Tcl_SetObjResult(interp, list);
459 }
460 
461 %typemap(out) TmpLibertyCellSeq* {
462   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
463   LibertyCellSeq *cells = $1;
464   LibertyCellSeq::Iterator cell_iter(cells);
465   while (cell_iter.hasNext()) {
466     LibertyCell *cell = cell_iter.next();
467     Tcl_Obj *obj = SWIG_NewInstanceObj(cell, SWIGTYPE_p_LibertyCell,
468 				      false);
469     Tcl_ListObjAppendElement(interp, list, obj);
470   }
471   Tcl_SetObjResult(interp, list);
472   delete cells;
473 }
474 
475 %typemap(out) CellPortIterator* {
476   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
477   Tcl_SetObjResult(interp, obj);
478 }
479 
480 %typemap(out) LibertyCellPortIterator* {
481   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
482   Tcl_SetObjResult(interp, obj);
483 }
484 
485 %typemap(out) Port* {
486   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
487   Tcl_SetObjResult(interp, obj);
488 }
489 
490 %typemap(in) PortSet* {
491   $1 = tclListSet<Port*>($input, SWIGTYPE_p_Port, interp);
492 }
493 
494 %typemap(in) PortSeq* {
495   $1 = tclListSeq<Port*>($input, SWIGTYPE_p_Port, interp);
496 }
497 
498 %typemap(out) TmpPortSeq* {
499   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
500   TmpPortSeq *ports = $1;
501   TmpPortSeq::Iterator port_iter(ports);
502   while (port_iter.hasNext()) {
503     Port *port = port_iter.next();
504     Tcl_Obj *obj = SWIG_NewInstanceObj(port, SWIGTYPE_p_Port, false);
505     Tcl_ListObjAppendElement(interp, list, obj);
506   }
507   delete ports;
508   Tcl_SetObjResult(interp, list);
509 }
510 
511 %typemap(out) TmpLibertyPortSeq* {
512   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
513   TmpLibertyPortSeq *ports = $1;
514   TmpLibertyPortSeq::Iterator port_iter(ports);
515   while (port_iter.hasNext()) {
516     LibertyPort *port = port_iter.next();
517     Tcl_Obj *obj = SWIG_NewInstanceObj(port, SWIGTYPE_p_LibertyPort,
518 				      false);
519     Tcl_ListObjAppendElement(interp, list, obj);
520   }
521   delete ports;
522   Tcl_SetObjResult(interp, list);
523 }
524 
525 %typemap(out) TmpPinSet* {
526   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
527   PinSet *pins = $1;
528   PinSet::Iterator pin_iter(pins);
529   while (pin_iter.hasNext()) {
530     Pin *pin = pin_iter.next();
531     Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false);
532     Tcl_ListObjAppendElement(interp, list, obj);
533   }
534   delete pins;
535   Tcl_SetObjResult(interp, list);
536 }
537 
538 %typemap(out) TmpPinSeq* {
539   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
540   PinSeq *pins = $1;
541   PinSeq::Iterator pin_iter(pins);
542   while (pin_iter.hasNext()) {
543     Pin *pin = pin_iter.next();
544     Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false);
545     Tcl_ListObjAppendElement(interp, list, obj);
546   }
547   delete pins;
548   Tcl_SetObjResult(interp, list);
549 }
550 
551 %typemap(out) PortMemberIterator* {
552   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
553   Tcl_SetObjResult(interp, obj);
554 }
555 
556 %typemap(out) LibertyCell* {
557   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
558   Tcl_SetObjResult(interp, obj);
559 }
560 
561 %typemap(out) LibertyPort* {
562   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
563   Tcl_SetObjResult(interp, obj);
564 }
565 
566 %typemap(out) LibertyPortMemberIterator* {
567   Tcl_Obj *obj = SWIG_NewInstanceObj($1,
568 				    SWIGTYPE_p_LibertyPortMemberIterator,
569 				    false);
570   Tcl_SetObjResult(interp, obj);
571 }
572 
573 %typemap(out) TimingArc* {
574   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
575   Tcl_SetObjResult(interp, obj);
576 }
577 
578 %typemap(out) Wireload* {
579   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
580   Tcl_SetObjResult(interp, obj);
581 }
582 
583 %typemap(out) WireloadSelection* {
584   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
585   Tcl_SetObjResult(interp, obj);
586 }
587 
588 %typemap(in) Transition* {
589   int length;
590   const char *arg = Tcl_GetStringFromObj($input, &length);
591   Transition *tr = Transition::find(arg);
592   if (tr == nullptr) {
593     Tcl_SetResult(interp,const_cast<char*>("Error: transition not found."),
594 		  TCL_STATIC);
595     return TCL_ERROR;
596   }
597   else
598     $1 = tr;
599 }
600 
601 %typemap(out) Transition* {
602   Transition *tr = $1;
603   const char *str = "";
604   if (tr)
605     str = tr->asString();
606   Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
607 }
608 
609 %typemap(in) RiseFall* {
610   int length;
611   const char *arg = Tcl_GetStringFromObj($input, &length);
612   RiseFall *tr = RiseFall::find(arg);
613   if (tr == nullptr) {
614     Tcl_SetResult(interp,const_cast<char*>("Error: unknown transition name."),
615 		  TCL_STATIC);
616     return TCL_ERROR;
617   }
618   $1 = tr;
619 }
620 
621 %typemap(out) RiseFall* {
622   const RiseFall *tr = $1;
623   const char *str = "";
624   if (tr)
625     str = tr->asString();
626   Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
627 }
628 
629 %typemap(in) RiseFallBoth* {
630   int length;
631   const char *arg = Tcl_GetStringFromObj($input, &length);
632   RiseFallBoth *tr = RiseFallBoth::find(arg);
633   if (tr == nullptr) {
634     Tcl_SetResult(interp,const_cast<char*>("Error: unknown transition name."),
635 		  TCL_STATIC);
636     return TCL_ERROR;
637   }
638   $1 = tr;
639 }
640 
641 %typemap(out) RiseFallBoth* {
642   RiseFallBoth *tr = $1;
643   const char *str = "";
644   if (tr)
645     str = tr->asString();
646   Tcl_SetResult(interp, const_cast<char*>(str), TCL_STATIC);
647 }
648 
649 %typemap(in) TimingRole* {
650   int length;
651   const char *arg = Tcl_GetStringFromObj($input, &length);
652   TimingRole *role = TimingRole::find(arg);
653   if (role)
654     $1 = TimingRole::find(arg);
655   else {
656     Tcl_SetResult(interp,const_cast<char*>("Error: unknown timing role."),
657 		  TCL_STATIC);
658     return TCL_ERROR;
659   }
660 }
661 
662 %typemap(out) TimingRole* {
663   Tcl_SetResult(interp, const_cast<char*>($1->asString()), TCL_STATIC);
664 }
665 
666 %typemap(in) LogicValue {
667   int length;
668   const char *arg = Tcl_GetStringFromObj($input, &length);
669   if (stringEq(arg, "0") || stringEq(arg, "zero"))
670     $1 = LogicValue::zero;
671   else if (stringEq(arg, "1") || stringEq(arg, "one"))
672     $1 = LogicValue::one;
673   else if (stringEq(arg, "X"))
674     $1 = LogicValue::unknown;
675   else if (stringEq(arg, "rise") || stringEq(arg, "rising"))
676     $1 = LogicValue::rise;
677   else if (stringEq(arg, "fall") || stringEq(arg, "falling"))
678     $1 = LogicValue::fall;
679   else {
680     Tcl_SetResult(interp,const_cast<char*>("Error: unknown logic value."),
681 		  TCL_STATIC);
682     return TCL_ERROR;
683   }
684 }
685 
686 %typemap(in) AnalysisType {
687   int length;
688   const char *arg = Tcl_GetStringFromObj($input, &length);
689   if (stringEqual(arg, "single"))
690     $1 = AnalysisType::single;
691   else if (stringEqual(arg, "bc_wc"))
692     $1 = AnalysisType::bc_wc;
693   else if (stringEq(arg, "on_chip_variation"))
694     $1 = AnalysisType::ocv;
695   else {
696     Tcl_SetResult(interp,const_cast<char*>("Error: unknown analysis type."),
697 		  TCL_STATIC);
698 
699     return TCL_ERROR;
700   }
701 }
702 
703 %typemap(out) Instance* {
704   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
705   Tcl_SetObjResult(interp, obj);
706 }
707 
708 %typemap(in) InstanceSeq* {
709   $1 = tclListSeq<Instance*>($input, SWIGTYPE_p_Instance, interp);
710 }
711 
712 %typemap(out) TmpInstanceSeq* {
713   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
714   TmpInstanceSeq *insts = $1;
715   TmpInstanceSeq::Iterator inst_iter(insts);
716   while (inst_iter.hasNext()) {
717     Instance *inst = inst_iter.next();
718     Tcl_Obj *obj = SWIG_NewInstanceObj(inst, SWIGTYPE_p_Instance,false);
719     Tcl_ListObjAppendElement(interp, list, obj);
720   }
721   delete insts;
722   Tcl_SetObjResult(interp, list);
723 }
724 
725 %typemap(out) InstanceChildIterator* {
726   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
727   Tcl_SetObjResult(interp, obj);
728 }
729 
730 %typemap(out) LeafInstanceIterator* {
731   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
732   Tcl_SetObjResult(interp, obj);
733 }
734 
735 %typemap(out) InstancePinIterator* {
736   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
737   Tcl_SetObjResult(interp, obj);
738 }
739 
740 %typemap(out) InstanceNetIterator* {
741   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
742   Tcl_SetObjResult(interp, obj);
743 }
744 
745 %typemap(out) Pin* {
746   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
747   Tcl_SetObjResult(interp, obj);
748 }
749 
750 %typemap(out) PinSeq* {
751   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
752   PinSeq *pins = $1;
753   PinSeq::Iterator pin_iter(pins);
754   while (pin_iter.hasNext()) {
755     Pin *pin = pin_iter.next();
756     Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false);
757     Tcl_ListObjAppendElement(interp, list, obj);
758   }
759   delete pins;
760   Tcl_SetObjResult(interp, list);
761 }
762 
763 %typemap(out) Net* {
764   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
765   Tcl_SetObjResult(interp, obj);
766 }
767 
768 %typemap(out) NetSeq* {
769   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
770   NetSeq *nets = $1;
771   NetSeq::Iterator net_iter(nets);
772   while (net_iter.hasNext()) {
773     Net *net = net_iter.next();
774     Tcl_Obj *obj = SWIG_NewInstanceObj(net, SWIGTYPE_p_Net, false);
775     Tcl_ListObjAppendElement(interp, list, obj);
776   }
777   delete nets;
778   Tcl_SetObjResult(interp, list);
779 }
780 
781 %typemap(out) NetPinIterator* {
782   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
783   Tcl_SetObjResult(interp, obj);
784 }
785 
786 %typemap(out) NetTermIterator* {
787   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
788   Tcl_SetObjResult(interp, obj);
789 }
790 
791 %typemap(out) NetConnectedPinIterator* {
792   Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
793   Tcl_SetObjResult(interp, obj);
794 }
795 
796 %typemap(out) PinConnectedPinIterator* {
797   Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
798   Tcl_SetObjResult(interp, obj);
799 }
800 
801 %typemap(out) Clock* {
802   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
803   Tcl_SetObjResult(interp, obj);
804 }
805 
806 %typemap(out) ClockSeq* {
807   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
808   ClockSeq *clks = $1;
809   ClockSeq::Iterator clk_iter(clks);
810   while (clk_iter.hasNext()) {
811     Clock *clk = clk_iter.next();
812     Tcl_Obj *obj = SWIG_NewInstanceObj(clk, SWIGTYPE_p_Clock, false);
813     Tcl_ListObjAppendElement(interp, list, obj);
814   }
815   delete clks;
816   Tcl_SetObjResult(interp, list);
817 }
818 
819 %typemap(out) ClockIterator* {
820   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
821   Tcl_SetObjResult(interp, obj);
822 }
823 
824 %typemap(out) ClockEdge* {
825   Tcl_Obj *obj = SWIG_NewInstanceObj($1,$1_descriptor, false);
826   Tcl_SetObjResult(interp, obj);
827 }
828 
829 %typemap(in) FloatSeq* {
830   int argc;
831   Tcl_Obj **argv;
832   FloatSeq *floats = nullptr;
833 
834   if (Tcl_ListObjGetElements(interp, $input, &argc, &argv) == TCL_OK) {
835     if (argc)
836       floats = new FloatSeq;
837     for (int i = 0; i < argc; i++) {
838       char *arg = Tcl_GetString(argv[i]);
839       double value;
840       if (Tcl_GetDouble(interp, arg, &value) == TCL_OK)
841 	floats->push_back(static_cast<float>(value));
842       else {
843 	delete floats;
844 	tclArgError(interp, "%s is not a floating point number.", arg);
845 	return TCL_ERROR;
846       }
847     }
848   }
849   $1 = floats;
850 }
851 
852 %typemap(out) FloatSeq* {
853   FloatSeq *floats = $1;
854   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
855   if (floats) {
856     for (unsigned i = 0; i < floats->size(); i++) {
857       Tcl_Obj *obj = Tcl_NewDoubleObj((*floats)[i]);
858       Tcl_ListObjAppendElement(interp, list, obj);
859     }
860   }
861   Tcl_SetObjResult(interp, list);
862 }
863 
864 %typemap(out) TmpFloatSeq* {
865   FloatSeq *floats = $1;
866   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
867   if (floats) {
868     for (unsigned i = 0; i < floats->size(); i++) {
869       Tcl_Obj *obj = Tcl_NewDoubleObj((*floats)[i]);
870       Tcl_ListObjAppendElement(interp, list, obj);
871     }
872     delete floats;
873   }
874   Tcl_SetObjResult(interp, list);
875 }
876 
877 %typemap(in) IntSeq* {
878   int argc;
879   Tcl_Obj **argv;
880   IntSeq *ints = nullptr;
881 
882   if (Tcl_ListObjGetElements(interp, $input, &argc, &argv) == TCL_OK) {
883     if (argc)
884       ints = new IntSeq;
885     for (int i = 0; i < argc; i++) {
886       char *arg = Tcl_GetString(argv[i]);
887       int value;
888       if (Tcl_GetInt(interp, arg, &value) == TCL_OK)
889 	ints->push_back(value);
890       else {
891 	delete ints;
892 	tclArgError(interp, "%s is not an integer.", arg);
893 	return TCL_ERROR;
894       }
895     }
896   }
897   $1 = ints;
898 }
899 
900 %typemap(in) MinMax* {
901   int length;
902   char *arg = Tcl_GetStringFromObj($input, &length);
903   MinMax *min_max = MinMax::find(arg);
904   if (min_max)
905     $1 = min_max;
906   else {
907     tclArgError(interp, "%s not min or max.", arg);
908     return TCL_ERROR;
909   }
910 }
911 
912 %typemap(out) MinMax* {
913   Tcl_SetResult(interp, const_cast<char*>($1->asString()), TCL_STATIC);
914 }
915 
916 %typemap(out) MinMax* {
917   Tcl_SetResult(interp, const_cast<char*>($1->asString()), TCL_STATIC);
918 }
919 
920 %typemap(in) MinMaxAll* {
921   int length;
922   char *arg = Tcl_GetStringFromObj($input, &length);
923   MinMaxAll *min_max = MinMaxAll::find(arg);
924   if (min_max)
925     $1 = min_max;
926   else {
927     tclArgError(interp, "%s not min, max or min_max.", arg);
928     return TCL_ERROR;
929   }
930 }
931 
932 %typemap(in) MinMaxAllNull* {
933   int length;
934   char *arg = Tcl_GetStringFromObj($input, &length);
935   if (stringEqual(arg, "NULL"))
936     $1 = nullptr;
937   else {
938     MinMaxAll *min_max = MinMaxAll::find(arg);
939     if (min_max)
940       $1 = min_max;
941     else {
942       tclArgError(interp, "%s not min, max or min_max.", arg);
943       return TCL_ERROR;
944     }
945   }
946 }
947 
948 %typemap(out) MinMaxAll* {
949   Tcl_SetResult(interp, const_cast<char*>($1->asString()), TCL_STATIC);
950 }
951 
952 // SetupHold is typedef'd to MinMax.
953 %typemap(in) SetupHold* {
954   int length;
955   char *arg = Tcl_GetStringFromObj($input, &length);
956   if (stringEqual(arg, "hold")
957       || stringEqual(arg, "min"))
958     $1 = MinMax::min();
959   else if (stringEqual(arg, "setup")
960 	   || stringEqual(arg, "max"))
961     $1 = MinMax::max();
962   else {
963     tclArgError(interp, "%s not setup, hold, min or max.", arg);
964     return TCL_ERROR;
965   }
966 }
967 
968 // SetupHoldAll is typedef'd to MinMaxAll.
969 %typemap(in) SetupHoldAll* {
970   int length;
971   char *arg = Tcl_GetStringFromObj($input, &length);
972   if (stringEqual(arg, "hold")
973       || stringEqual(arg, "min"))
974     $1 = SetupHoldAll::min();
975   else if (stringEqual(arg, "setup")
976 	   || stringEqual(arg, "max"))
977     $1 = SetupHoldAll::max();
978   else if (stringEqual(arg, "setup_hold")
979 	   || stringEqual(arg, "min_max"))
980     $1 = SetupHoldAll::all();
981   else {
982     tclArgError(interp, "%s not setup, hold, setup_hold, min, max or min_max.", arg);
983     return TCL_ERROR;
984   }
985 }
986 
987 // EarlyLate is typedef'd to MinMax.
988 %typemap(in) EarlyLate* {
989   int length;
990   char *arg = Tcl_GetStringFromObj($input, &length);
991   EarlyLate *early_late = EarlyLate::find(arg);
992   if (early_late)
993     $1 = early_late;
994   else {
995     tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
996     return TCL_ERROR;
997   }
998 }
999 
1000 // EarlyLateAll is typedef'd to MinMaxAll.
1001 %typemap(in) EarlyLateAll* {
1002   int length;
1003   char *arg = Tcl_GetStringFromObj($input, &length);
1004   EarlyLateAll *early_late = EarlyLateAll::find(arg);
1005   if (early_late)
1006     $1 = early_late;
1007   else {
1008     tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
1009     return TCL_ERROR;
1010   }
1011 }
1012 
1013 %typemap(in) TimingDerateType {
1014   int length;
1015   char *arg = Tcl_GetStringFromObj($input, &length);
1016   if (stringEq(arg, "net_delay"))
1017     $1 = TimingDerateType::net_delay;
1018   else if (stringEq(arg, "cell_delay"))
1019     $1 = TimingDerateType::cell_delay;
1020   else if (stringEq(arg, "cell_check"))
1021     $1 = TimingDerateType::cell_check;
1022   else {
1023     tclArgError(interp, "%s not clk or data.", arg);
1024     return TCL_ERROR;
1025   }
1026 }
1027 
1028 %typemap(in) PathClkOrData {
1029   int length;
1030   char *arg = Tcl_GetStringFromObj($input, &length);
1031   if (stringEq(arg, "clk"))
1032     $1 = PathClkOrData::clk;
1033   else if (stringEq(arg, "data"))
1034     $1 = PathClkOrData::data;
1035   else {
1036     tclArgError(interp, "%s not clk or data.", arg);
1037     return TCL_ERROR;
1038   }
1039 }
1040 
1041 %typemap(in) ReportSortBy {
1042   int length;
1043   char *arg = Tcl_GetStringFromObj($input, &length);
1044   if (stringEq(arg, "group"))
1045     $1 = sort_by_group;
1046   else if (stringEq(arg, "slack"))
1047     $1 = sort_by_slack;
1048   else {
1049     tclArgError(interp, "%s not group or slack.", arg);
1050     return TCL_ERROR;
1051   }
1052 }
1053 
1054 %typemap(in) ReportPathFormat {
1055   int length;
1056   char *arg = Tcl_GetStringFromObj($input, &length);
1057   if (stringEq(arg, "full"))
1058     $1 = ReportPathFormat::full;
1059   else if (stringEq(arg, "full_clock"))
1060     $1 = ReportPathFormat::full_clock;
1061   else if (stringEq(arg, "full_clock_expanded"))
1062     $1 = ReportPathFormat::full_clock_expanded;
1063   else if (stringEq(arg, "short"))
1064     $1 = ReportPathFormat::shorter;
1065   else if (stringEq(arg, "end"))
1066     $1 = ReportPathFormat::endpoint;
1067   else if (stringEq(arg, "summary"))
1068     $1 = ReportPathFormat::summary;
1069   else if (stringEq(arg, "slack_only"))
1070     $1 = ReportPathFormat::slack_only;
1071   else if (stringEq(arg, "json"))
1072     $1 = ReportPathFormat::json;
1073   else {
1074     tclArgError(interp, "unknown path type %s.", arg);
1075     return TCL_ERROR;
1076   }
1077 }
1078 
1079 %typemap(in) PinSeq* {
1080   $1 = tclListSeq<Pin*>($input, SWIGTYPE_p_Pin, interp);
1081 }
1082 
1083 %typemap(in) PinSet* {
1084   $1 = tclListSetPin($input, interp);
1085 }
1086 
1087 %typemap(out) PinSet* {
1088   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1089   const PinSet *pins = $1;
1090   if (pins) {
1091     PinSet::ConstIterator pin_iter(pins);
1092     while (pin_iter.hasNext()) {
1093       Pin *pin = pin_iter.next();
1094       Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false);
1095       Tcl_ListObjAppendElement(interp, list, obj);
1096     }
1097   }
1098   Tcl_SetObjResult(interp, list);
1099 }
1100 
1101 %typemap(out) PinSet& {
1102   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1103   const PinSet *pins = $1;
1104   if (pins) {
1105     PinSet::ConstIterator pin_iter(pins);
1106     while (pin_iter.hasNext()) {
1107       Pin *pin = pin_iter.next();
1108       Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false);
1109       Tcl_ListObjAppendElement(interp, list, obj);
1110     }
1111   }
1112   Tcl_SetObjResult(interp, list);
1113 }
1114 
1115 %typemap(in) ClockSet* {
1116   $1 = tclListSet<Clock*>($input, SWIGTYPE_p_Clock, interp);
1117 }
1118 
1119 %typemap(out) ClockSet* {
1120   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1121   const ClockSet *clks = $1;
1122   if (clks) {
1123     ClockSet::ConstIterator clk_iter(clks);
1124     while (clk_iter.hasNext()) {
1125       Clock *clk = clk_iter.next();
1126       Tcl_Obj *obj = SWIG_NewInstanceObj(clk, SWIGTYPE_p_Clock, false);
1127       Tcl_ListObjAppendElement(interp, list, obj);
1128     }
1129   }
1130   Tcl_SetObjResult(interp, list);
1131 }
1132 
1133 %typemap(out) TmpClockSet* {
1134   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1135   const ClockSet *clks = $1;
1136   if (clks) {
1137     ClockSet::ConstIterator clk_iter(clks);
1138     while (clk_iter.hasNext()) {
1139       Clock *clk = clk_iter.next();
1140       Tcl_Obj *obj = SWIG_NewInstanceObj(clk, SWIGTYPE_p_Clock, false);
1141       Tcl_ListObjAppendElement(interp, list, obj);
1142     }
1143     delete clks;
1144   }
1145   Tcl_SetObjResult(interp, list);
1146 }
1147 
1148 %typemap(in) InstanceSet* {
1149   $1 = tclListSet<Instance*>($input, SWIGTYPE_p_Instance, interp);
1150 }
1151 
1152 %typemap(out) TmpInstanceSet* {
1153   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1154   InstanceSet *insts = $1;
1155   InstanceSet::Iterator inst_iter(insts);
1156   while (inst_iter.hasNext()) {
1157     Instance *inst = inst_iter.next();
1158     Tcl_Obj *obj = SWIG_NewInstanceObj(inst, SWIGTYPE_p_Instance,false);
1159     Tcl_ListObjAppendElement(interp, list, obj);
1160   }
1161   delete insts;
1162   Tcl_SetObjResult(interp, list);
1163 }
1164 
1165 %typemap(in) NetSet* {
1166   $1 = tclListSet<Net*>($input, SWIGTYPE_p_Net, interp);
1167 }
1168 
1169 %typemap(in) ExceptionThruSeq* {
1170   $1 = tclListSeq<ExceptionThru*>($input, SWIGTYPE_p_ExceptionThru, interp);
1171 }
1172 
1173 %typemap(out) Vertex* {
1174   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1175   Tcl_SetObjResult(interp, obj);
1176 }
1177 
1178 %typemap(out) Vertex** {
1179   int i = 0;
1180   Tcl_ResetResult(interp);
1181   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1182   while ($1[i]) {
1183     Tcl_Obj *obj = SWIG_NewInstanceObj($1[i], SWIGTYPE_p_Vertex,false);
1184     Tcl_ListObjAppendElement(interp, list, obj);
1185     i++;
1186   }
1187   Tcl_SetObjResult(interp, list);
1188 }
1189 
1190 %typemap(in) EdgeSeq* {
1191   $1 = tclListSeq<Edge*>($input, SWIGTYPE_p_Edge, interp);
1192 }
1193 
1194 %typemap(out) Edge* {
1195   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1196   Tcl_SetObjResult(interp, obj);
1197 }
1198 
1199 %typemap(out) EdgeSeq* {
1200   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1201   EdgeSeq *edges = $1;
1202   EdgeSeq::Iterator edge_iter(edges);
1203   while (edge_iter.hasNext()) {
1204     Edge *edge = edge_iter.next();
1205     Tcl_Obj *obj = SWIG_NewInstanceObj(edge, SWIGTYPE_p_Edge, false);
1206     Tcl_ListObjAppendElement(interp, list, obj);
1207   }
1208   delete edges;
1209   Tcl_SetObjResult(interp, list);
1210 }
1211 
1212 %typemap(out) VertexIterator* {
1213   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1214   Tcl_SetObjResult(interp, obj);
1215 }
1216 
1217 %typemap(out) VertexInEdgeIterator* {
1218   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1219   Tcl_SetObjResult(interp, obj);
1220 }
1221 
1222 %typemap(out) VertexOutEdgeIterator* {
1223   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1224   Tcl_SetObjResult(interp, obj);
1225 }
1226 
1227 %typemap(out) TimingArcSetArcIterator* {
1228   Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
1229   Tcl_SetObjResult(interp, obj);
1230 }
1231 
1232 %typemap(out) LibertyCellTimingArcSetIterator* {
1233   Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
1234   Tcl_SetObjResult(interp, obj);
1235 }
1236 
1237 %typemap(out) CheckErrorSeq & {
1238   Tcl_Obj *error_list = Tcl_NewListObj(0, nullptr);
1239   CheckErrorSeq *check_errors = $1;
1240   CheckErrorSeq::Iterator check_iter(check_errors);
1241   while (check_iter.hasNext()) {
1242     CheckError *error = check_iter.next();
1243     Tcl_Obj *string_list = Tcl_NewListObj(0, nullptr);
1244     CheckError::Iterator string_iter(error);
1245     while (string_iter.hasNext()) {
1246       const char *str = string_iter.next();
1247       size_t str_len = strlen(str);
1248       Tcl_Obj *obj = Tcl_NewStringObj(const_cast<char*>(str),
1249 				      static_cast<int>(str_len));
1250       Tcl_ListObjAppendElement(interp, string_list, obj);
1251     }
1252     Tcl_ListObjAppendElement(interp, error_list, string_list);
1253   }
1254   Tcl_SetObjResult(interp, error_list);
1255 }
1256 
1257 %typemap(out) PathEnd* {
1258   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1259   Tcl_SetObjResult(interp, obj);
1260 }
1261 
1262 %typemap(out) PathEndSeq* {
1263   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1264   const PathEndSeq *path_ends = $1;
1265   PathEndSeq::ConstIterator end_iter(path_ends);
1266   while (end_iter.hasNext()) {
1267     PathEnd *path_end = end_iter.next();
1268     Tcl_Obj *obj = SWIG_NewInstanceObj(path_end, SWIGTYPE_p_PathEnd, false);
1269     Tcl_ListObjAppendElement(interp, list, obj);
1270   }
1271   // Delete the PathEndSeq, not the ends.
1272   delete path_ends;
1273   Tcl_SetObjResult(interp, list);
1274 }
1275 
1276 %typemap(out) MinPulseWidthCheckSeqIterator* {
1277   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1278   Tcl_SetObjResult(interp, obj);
1279 }
1280 
1281 %typemap(out) PathRefSeq* {
1282   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1283   Tcl_SetObjResult(interp, obj);
1284 
1285   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1286   PathRefSeq *paths = $1;
1287   PathRefSeq::Iterator path_iter(paths);
1288   while (path_iter.hasNext()) {
1289     PathRef *path = &path_iter.next();
1290     PathRef *copy = new PathRef(path);
1291     Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false);
1292     Tcl_ListObjAppendElement(interp, list, obj);
1293   }
1294   Tcl_SetObjResult(interp, list);
1295 }
1296 
1297 %typemap(out) MinPulseWidthCheck* {
1298   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1299   Tcl_SetObjResult(interp, obj);
1300 }
1301 
1302 %typemap(out) MinPulseWidthCheckSeq & {
1303   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1304   Tcl_SetObjResult(interp, obj);
1305 }
1306 
1307 %typemap(out) MinPulseWidthCheckSeqIterator & {
1308   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1309   Tcl_SetObjResult(interp, obj);
1310 }
1311 
1312 %typemap(out) VertexPathIterator* {
1313   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1314   Tcl_SetObjResult(interp, obj);
1315 }
1316 
1317 %typemap(out) SlowDrvrIterator* {
1318   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1319   Tcl_SetObjResult(interp, obj);
1320 }
1321 
1322 %typemap(out) ExceptionFrom* {
1323   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1324   Tcl_SetObjResult(interp, obj);
1325 }
1326 
1327 %typemap(out) ExceptionTo* {
1328   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1329   Tcl_SetObjResult(interp, obj);
1330 }
1331 
1332 %typemap(out) ExceptionThru* {
1333   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1334   Tcl_SetObjResult(interp, obj);
1335 }
1336 
1337 %typemap(out) OperatingConditions* {
1338   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1339   Tcl_SetObjResult(interp, obj);
1340 }
1341 
1342 %typemap(in) ReducedParasiticType {
1343   int length;
1344   char *arg = Tcl_GetStringFromObj($input, &length);
1345   if (stringEq(arg, "pi_elmore"))
1346     $1 = ReducedParasiticType::pi_elmore;
1347   else if (stringEq(arg, "pi_pole_residue2"))
1348     $1 = ReducedParasiticType::pi_pole_residue2;
1349   else if (stringEq(arg, "none"))
1350     $1 = ReducedParasiticType::none;
1351   else {
1352     tclArgError(interp, "%s pi_elmore, pi_pole_residue2, or none.", arg);
1353     return TCL_ERROR;
1354   }
1355 }
1356 
1357 %typemap(out) Arrival {
1358   Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
1359 }
1360 
1361 %typemap(out) Required {
1362   Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
1363 }
1364 
1365 %typemap(out) Slack {
1366   Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
1367 }
1368 
1369 %typemap(out) ArcDelay {
1370   Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
1371 }
1372 
1373 %typemap(out) Slew {
1374   Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
1375 }
1376 
1377 %typemap(in) PathGroupNameSet* {
1378   $1 = tclListSetConstChar($input, interp);
1379 }
1380 
1381 %typemap(in) StringSet* {
1382   $1 = tclListSetConstChar($input, interp);
1383 }
1384 
1385 %typemap(out) Corner* {
1386   Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
1387   Tcl_SetObjResult(interp, obj);
1388 }
1389 
1390 %typemap(out) Corners* {
1391   Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1392   Corners *corners = $1;
1393   for (Corner *corner : *corners) {
1394     Tcl_Obj *obj = SWIG_NewInstanceObj(corner, SWIGTYPE_p_Corner, false);
1395     Tcl_ListObjAppendElement(interp, list, obj);
1396   }
1397   Tcl_SetObjResult(interp, list);
1398 }
1399 
1400 %typemap(out) PropertyValue {
1401   PropertyValue value = $1;
1402   switch (value.type()) {
1403   case PropertyValue::Type::type_none:
1404     Tcl_SetResult(interp, const_cast<char*>(""), TCL_STATIC);
1405     break;
1406   case PropertyValue::Type::type_string:
1407     Tcl_SetResult(interp, const_cast<char*>(value.stringValue()), TCL_VOLATILE);
1408     break;
1409   case PropertyValue::Type::type_float: {
1410     char *float_string = stringPrint("%.6e", value.floatValue());
1411     Tcl_SetResult(interp, float_string, TCL_VOLATILE);
1412     stringDelete(float_string);
1413   }
1414     break;
1415   case PropertyValue::Type::type_bool: {
1416     const char *bool_string = value.boolValue() ? "1" : "0";
1417     Tcl_SetResult(interp, const_cast<char*>(bool_string), TCL_STATIC);
1418   }
1419     break;
1420   case PropertyValue::Type::type_library: {
1421     Tcl_Obj *obj = SWIG_NewInstanceObj(value.library(),
1422 				       SWIGTYPE_p_Library, false);
1423     Tcl_SetObjResult(interp, obj);
1424   }
1425     break;
1426   case PropertyValue::Type::type_cell: {
1427     Tcl_Obj *obj = SWIG_NewInstanceObj(value.cell(),
1428 				       SWIGTYPE_p_Cell, false);
1429     Tcl_SetObjResult(interp, obj);
1430   }
1431     break;
1432   case PropertyValue::Type::type_port: {
1433     Tcl_Obj *obj = SWIG_NewInstanceObj(value.port(),
1434 				       SWIGTYPE_p_Port, false);
1435     Tcl_SetObjResult(interp, obj);
1436   }
1437     break;
1438   case PropertyValue::Type::type_liberty_library: {
1439     Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyLibrary(),
1440 				       SWIGTYPE_p_LibertyLibrary, false);
1441     Tcl_SetObjResult(interp, obj);
1442   }
1443     break;
1444   case PropertyValue::Type::type_liberty_cell: {
1445     Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyCell(),
1446 				       SWIGTYPE_p_LibertyCell, false);
1447     Tcl_SetObjResult(interp, obj);
1448   }
1449     break;
1450   case PropertyValue::Type::type_liberty_port: {
1451     Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyPort(),
1452 				       SWIGTYPE_p_LibertyPort, false);
1453     Tcl_SetObjResult(interp, obj);
1454   }
1455     break;
1456   case PropertyValue::Type::type_instance: {
1457     Tcl_Obj *obj = SWIG_NewInstanceObj(value.instance(),
1458 				       SWIGTYPE_p_Instance, false);
1459     Tcl_SetObjResult(interp, obj);
1460   }
1461     break;
1462   case PropertyValue::Type::type_pin: {
1463     Tcl_Obj *obj = SWIG_NewInstanceObj(value.pin(), SWIGTYPE_p_Pin, false);
1464     Tcl_SetObjResult(interp, obj);
1465   }
1466     break;
1467   case PropertyValue::Type::type_pins: {
1468     Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1469     PinSeq *pins = value.pins();
1470     PinSeq::Iterator pin_iter(pins);
1471     while (pin_iter.hasNext()) {
1472       Pin *pin = pin_iter.next();
1473       Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false);
1474       Tcl_ListObjAppendElement(interp, list, obj);
1475     }
1476     Tcl_SetObjResult(interp, list);
1477   }
1478     break;
1479   case PropertyValue::Type::type_net: {
1480     Tcl_Obj *obj = SWIG_NewInstanceObj(value.net(),
1481 				       SWIGTYPE_p_Net, false);
1482     Tcl_SetObjResult(interp, obj);
1483   }
1484     break;
1485   case PropertyValue::Type::type_clk: {
1486     Tcl_Obj *obj = SWIG_NewInstanceObj(value.clock(),
1487 				       SWIGTYPE_p_Clock, false);
1488     Tcl_SetObjResult(interp, obj);
1489   }
1490     break;
1491   case PropertyValue::Type::type_clks: {
1492     Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1493     ClockSeq *clks = value.clocks();
1494     ClockSeq::Iterator clk_iter(clks);
1495     while (clk_iter.hasNext()) {
1496       Clock *clk = clk_iter.next();
1497       Tcl_Obj *obj = SWIG_NewInstanceObj(clk, SWIGTYPE_p_Clock, false);
1498       Tcl_ListObjAppendElement(interp, list, obj);
1499     }
1500     Tcl_SetObjResult(interp, list);
1501   }
1502     break;
1503   case PropertyValue::Type::type_path_refs: {
1504     Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1505     PathRefSeq *paths = value.pathRefs();
1506     PathRefSeq::Iterator path_iter(paths);
1507     while (path_iter.hasNext()) {
1508       PathRef &path = path_iter.next();
1509       PathRef *copy = new PathRef(path);
1510       Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false);
1511       Tcl_ListObjAppendElement(interp, list, obj);
1512     }
1513     Tcl_SetObjResult(interp, list);
1514   }
1515     break;
1516   case PropertyValue::Type::type_pwr_activity: {
1517     PwrActivity activity = value.pwrActivity();
1518     Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
1519     Tcl_Obj *obj;
1520     const char *str;
1521 
1522     str = stringPrintTmp("%.5e", activity.activity());
1523     obj = Tcl_NewStringObj(str, strlen(str));
1524     Tcl_ListObjAppendElement(interp, list, obj);
1525 
1526     str = stringPrintTmp("%.3f", activity.duty());
1527     obj = Tcl_NewStringObj(str, strlen(str));
1528     Tcl_ListObjAppendElement(interp, list, obj);
1529 
1530     str = activity.originName();
1531     obj = Tcl_NewStringObj(str, strlen(str));
1532     Tcl_ListObjAppendElement(interp, list, obj);
1533 
1534     Tcl_SetObjResult(interp, list);
1535   }
1536     break;
1537   }
1538 }
1539 
1540 ////////////////////////////////////////////////////////////////
1541 //
1542 // Empty class definitions to make swig happy.
1543 // Private constructor/destructor so swig doesn't emit them.
1544 //
1545 ////////////////////////////////////////////////////////////////
1546 
1547 class Library
1548 {
1549 private:
1550   Library();
1551   ~Library();
1552 };
1553 
1554 class LibraryIterator
1555 {
1556 private:
1557   LibraryIterator();
1558   ~LibraryIterator();
1559 };
1560 
1561 class Cell
1562 {
1563 private:
1564   Cell();
1565   ~Cell();
1566 };
1567 
1568 class CellPortIterator
1569 {
1570 private:
1571   CellPortIterator();
1572   ~CellPortIterator();
1573 };
1574 
1575 class LibertyCellPortIterator
1576 {
1577 private:
1578   LibertyCellPortIterator();
1579   ~LibertyCellPortIterator();
1580 };
1581 
1582 class Port
1583 {
1584 private:
1585   Port();
1586   ~Port();
1587 };
1588 
1589 class PortMemberIterator
1590 {
1591 private:
1592   PortMemberIterator();
1593   ~PortMemberIterator();
1594 };
1595 
1596 class LibertyLibrary
1597 {
1598 private:
1599   LibertyLibrary();
1600   ~LibertyLibrary();
1601 };
1602 
1603 class LibertyLibraryIterator
1604 {
1605 private:
1606   LibertyLibraryIterator();
1607   ~LibertyLibraryIterator();
1608 };
1609 
1610 class LibertyCell
1611 {
1612 private:
1613   LibertyCell();
1614   ~LibertyCell();
1615 };
1616 
1617 class LibertyPort
1618 {
1619 private:
1620   LibertyPort();
1621   ~LibertyPort();
1622 };
1623 
1624 class LibertyPortMemberIterator
1625 {
1626 private:
1627   LibertyPortMemberIterator();
1628   ~LibertyPortMemberIterator();
1629 };
1630 
1631 class TimingArcSet
1632 {
1633 private:
1634   TimingArcSet();
1635   ~TimingArcSet();
1636 };
1637 
1638 class LibertyCellTimingArcSetIterator
1639 {
1640 private:
1641   LibertyCellTimingArcSetIterator();
1642   ~LibertyCellTimingArcSetIterator();
1643 };
1644 
1645 class TimingArcSetArcIterator
1646 {
1647 private:
1648   TimingArcSetArcIterator();
1649   ~TimingArcSetArcIterator();
1650 };
1651 
1652 class TimingArc
1653 {
1654 private:
1655   TimingArc();
1656   ~TimingArc();
1657 };
1658 
1659 class Wireload
1660 {
1661 private:
1662   Wireload();
1663   ~Wireload();
1664 };
1665 
1666 class WireloadSelection
1667 {
1668 private:
1669   WireloadSelection();
1670   ~WireloadSelection();
1671 };
1672 
1673 class Transition
1674 {
1675 private:
1676   Transition();
1677   ~Transition();
1678 };
1679 
1680 class Instance
1681 {
1682 private:
1683   Instance();
1684   ~Instance();
1685 };
1686 
1687 class Pin
1688 {
1689 private:
1690   Pin();
1691   ~Pin();
1692 };
1693 
1694 class Term
1695 {
1696 private:
1697   Term();
1698   ~Term();
1699 };
1700 
1701 class InstanceChildIterator
1702 {
1703 private:
1704   InstanceChildIterator();
1705   ~InstanceChildIterator();
1706 };
1707 
1708 class InstancePinIterator
1709 {
1710 private:
1711   InstancePinIterator();
1712   ~InstancePinIterator();
1713 };
1714 
1715 class InstanceNetIterator
1716 {
1717 private:
1718   InstanceNetIterator();
1719   ~InstanceNetIterator();
1720 };
1721 
1722 class LeafInstanceIterator
1723 {
1724 private:
1725   LeafInstanceIterator();
1726   ~LeafInstanceIterator();
1727 };
1728 
1729 class Net
1730 {
1731 private:
1732   Net();
1733   ~Net();
1734 };
1735 
1736 class NetPinIterator
1737 {
1738 private:
1739   NetPinIterator();
1740   ~NetPinIterator();
1741 };
1742 
1743 class NetTermIterator
1744 {
1745 private:
1746   NetTermIterator();
1747   ~NetTermIterator();
1748 };
1749 
1750 class NetConnectedPinIterator
1751 {
1752 private:
1753   NetConnectedPinIterator();
1754   ~NetConnectedPinIterator();
1755 };
1756 
1757 class PinConnectedPinIterator
1758 {
1759 private:
1760   PinConnectedPinIterator();
1761   ~PinConnectedPinIterator();
1762 };
1763 
1764 class Clock
1765 {
1766 private:
1767   Clock();
1768   ~Clock();
1769 };
1770 
1771 class ClockIterator
1772 {
1773 private:
1774   ClockIterator();
1775   ~ClockIterator();
1776 };
1777 
1778 class ClockEdge
1779 {
1780 private:
1781   ClockEdge();
1782   ~ClockEdge();
1783 };
1784 
1785 class Vertex
1786 {
1787 private:
1788   Vertex();
1789   ~Vertex();
1790 };
1791 
1792 class Edge
1793 {
1794 private:
1795   Edge();
1796   ~Edge();
1797 };
1798 
1799 class VertexIterator
1800 {
1801 private:
1802   VertexIterator();
1803   ~VertexIterator();
1804 };
1805 
1806 class VertexInEdgeIterator
1807 {
1808 private:
1809   VertexInEdgeIterator();
1810   ~VertexInEdgeIterator();
1811 };
1812 
1813 class VertexOutEdgeIterator
1814 {
1815 private:
1816   VertexOutEdgeIterator();
1817   ~VertexOutEdgeIterator();
1818 };
1819 
1820 class PathRef
1821 {
1822 private:
1823   PathRef();
1824   ~PathRef();
1825 };
1826 
1827 class PathEnd
1828 {
1829 private:
1830   PathEnd();
1831   ~PathEnd();
1832 };
1833 
1834 class MinPulseWidthCheck
1835 {
1836 private:
1837   MinPulseWidthCheck();
1838   ~MinPulseWidthCheck();
1839 };
1840 
1841 class MinPulseWidthCheckSeq
1842 {
1843 private:
1844   MinPulseWidthCheckSeq();
1845   ~MinPulseWidthCheckSeq();
1846 };
1847 
1848 class MinPulseWidthCheckSeqIterator
1849 {
1850 private:
1851   MinPulseWidthCheckSeqIterator();
1852   ~MinPulseWidthCheckSeqIterator();
1853 };
1854 
1855 class VertexPathIterator
1856 {
1857 private:
1858   VertexPathIterator();
1859   ~VertexPathIterator();
1860 };
1861 
1862 class SlowDrvrIterator
1863 {
1864 private:
1865   SlowDrvrIterator();
1866   ~SlowDrvrIterator();
1867 };
1868 
1869 class ExceptionFrom
1870 {
1871 private:
1872   ExceptionFrom();
1873   ~ExceptionFrom();
1874 };
1875 
1876 class ExceptionThru
1877 {
1878 private:
1879   ExceptionThru();
1880   ~ExceptionThru();
1881 };
1882 
1883 class ExceptionTo
1884 {
1885 private:
1886   ExceptionTo();
1887   ~ExceptionTo();
1888 };
1889 
1890 class OperatingConditions
1891 {
1892 private:
1893   OperatingConditions();
1894   ~OperatingConditions();
1895 };
1896 
1897 class Corner
1898 {
1899 private:
1900   Corner();
1901   ~Corner();
1902 };
1903 
1904 ////////////////////////////////////////////////////////////////
1905 //
1906 // C++ functions visible as TCL functions.
1907 //
1908 ////////////////////////////////////////////////////////////////
1909 
1910 %inline %{
1911 
1912 float float_inf = INF;
1913 int group_count_max = PathGroup::group_count_max;
1914 
1915 const char *
version()1916 version()
1917 {
1918   return STA_VERSION;
1919 }
1920 
1921 const char *
git_sha1()1922 git_sha1()
1923 {
1924   return STA_GIT_SHA1;
1925 }
1926 
1927 void
report_error(int id,const char * msg)1928 report_error(int id,
1929              const char *msg)
1930 {
1931   Report *report = Sta::sta()->report();
1932   report->error(id, "%s", msg);
1933 }
1934 
1935 void
report_file_error(int id,const char * filename,int line,const char * msg)1936 report_file_error(int id,
1937                   const char *filename,
1938                   int line,
1939                   const char *msg)
1940 {
1941   Report *report = Sta::sta()->report();
1942   report->error(id, filename, line, "%s", msg);
1943 }
1944 
1945 void
report_warn(int id,const char * msg)1946 report_warn(int id,
1947             const char *msg)
1948 {
1949   Report *report = Sta::sta()->report();
1950   report->warn(id, "%s", msg);
1951 }
1952 
1953 void
report_file_warn(int id,const char * filename,int line,const char * msg)1954 report_file_warn(int id,
1955                  const char *filename,
1956                  int line,
1957                  const char *msg)
1958 {
1959   Report *report = Sta::sta()->report();
1960   report->fileWarn(id, filename, line, "%s", msg);
1961 }
1962 
1963 void
report_line(const char * msg)1964 report_line(const char *msg)
1965 {
1966   Report *report = Sta::sta()->report();
1967   report->reportLineString(msg);
1968 }
1969 
1970 void
fflush()1971 fflush()
1972 {
1973   fflush(stdout);
1974   fflush(stderr);
1975 }
1976 
1977 void
redirect_file_begin(const char * filename)1978 redirect_file_begin(const char *filename)
1979 {
1980   Sta::sta()->report()->redirectFileBegin(filename);
1981 }
1982 
1983 void
redirect_file_append_begin(const char * filename)1984 redirect_file_append_begin(const char *filename)
1985 {
1986   Sta::sta()->report()->redirectFileAppendBegin(filename);
1987 }
1988 
1989 void
redirect_file_end()1990 redirect_file_end()
1991 {
1992   Sta::sta()->report()->redirectFileEnd();
1993 }
1994 
1995 void
redirect_string_begin()1996 redirect_string_begin()
1997 {
1998   Sta::sta()->report()->redirectStringBegin();
1999 }
2000 
2001 const char *
redirect_string_end()2002 redirect_string_end()
2003 {
2004   return Sta::sta()->report()->redirectStringEnd();
2005 }
2006 
2007 void
log_begin_cmd(const char * filename)2008 log_begin_cmd(const char *filename)
2009 {
2010   Sta::sta()->report()->logBegin(filename);
2011 }
2012 
2013 void
log_end()2014 log_end()
2015 {
2016   Sta::sta()->report()->logEnd();
2017 }
2018 
2019 void
set_debug(const char * what,int level)2020 set_debug(const char *what,
2021 	  int level)
2022 {
2023   Sta::sta()->setDebugLevel(what, level);
2024 }
2025 
2026 bool
is_object(const char * obj)2027 is_object(const char *obj)
2028 {
2029   // _hexaddress_p_type
2030   const char *s = obj;
2031   char ch = *s++;
2032   if (ch != '_')
2033     return false;
2034   while (*s && isxdigit(*s))
2035     s++;
2036   if ((s - obj - 1) == sizeof(void*) * 2
2037       && *s && *s++ == '_'
2038       && *s && *s++ == 'p'
2039       && *s && *s++ == '_') {
2040     while (*s && *s != ' ')
2041       s++;
2042     return *s == '\0';
2043   }
2044   else
2045     return false;
2046 }
2047 
2048 // Assumes is_object is true.
2049 const char *
object_type(const char * obj)2050 object_type(const char *obj)
2051 {
2052   return &obj[1 + sizeof(void*) * 2 + 3];
2053 }
2054 
2055 bool
is_object_list(const char * list,const char * type)2056 is_object_list(const char *list,
2057 	       const char *type)
2058 {
2059   const char *s = list;
2060   while (s) {
2061     bool type_match;
2062     const char *next;
2063     objectListNext(s, type, type_match, next);
2064     if (type_match)
2065       s = next;
2066     else
2067       return false;
2068   }
2069   return true;
2070 }
2071 
2072 void
set_rise_fall_short_names(const char * rise_short_name,const char * fall_short_name)2073 set_rise_fall_short_names(const char *rise_short_name,
2074 			  const char *fall_short_name)
2075 {
2076   RiseFall::rise()->setShortName(rise_short_name);
2077   RiseFall::fall()->setShortName(fall_short_name);
2078 
2079   RiseFallBoth::rise()->setShortName(rise_short_name);
2080   RiseFallBoth::fall()->setShortName(fall_short_name);
2081 
2082   Transition::rise()->setName(rise_short_name);
2083   Transition::fall()->setName(fall_short_name);
2084 }
2085 
2086 const char *
rise_short_name()2087 rise_short_name()
2088 {
2089   return RiseFall::rise()->shortName();
2090 }
2091 
2092 const char *
fall_short_name()2093 fall_short_name()
2094 {
2095   return RiseFall::fall()->shortName();
2096 }
2097 
2098 bool
pin_is_constrained(Pin * pin)2099 pin_is_constrained(Pin *pin)
2100 {
2101   return Sta::sta()->sdc()->isConstrained(pin);
2102 }
2103 
2104 bool
instance_is_constrained(Instance * inst)2105 instance_is_constrained(Instance *inst)
2106 {
2107   return Sta::sta()->sdc()->isConstrained(inst);
2108 }
2109 
2110 bool
net_is_constrained(Net * net)2111 net_is_constrained(Net *net)
2112 {
2113   return Sta::sta()->sdc()->isConstrained(net);
2114 }
2115 
2116 bool
clk_thru_tristate_enabled()2117 clk_thru_tristate_enabled()
2118 {
2119   return Sta::sta()->clkThruTristateEnabled();
2120 }
2121 
2122 void
set_clk_thru_tristate_enabled(bool enabled)2123 set_clk_thru_tristate_enabled(bool enabled)
2124 {
2125   Sta::sta()->setClkThruTristateEnabled(enabled);
2126 }
2127 
2128 bool
network_is_linked()2129 network_is_linked()
2130 {
2131   return Sta::sta()->cmdNetwork()->isLinked();
2132 }
2133 
2134 void
set_path_divider(char divider)2135 set_path_divider(char divider)
2136 {
2137   cmdNetwork()->setPathDivider(divider);
2138 }
2139 
2140 void
set_current_instance(Instance * inst)2141 set_current_instance(Instance *inst)
2142 {
2143   Sta::sta()->setCurrentInstance(inst);
2144 }
2145 
2146 bool
read_liberty_cmd(char * filename,Corner * corner,const MinMaxAll * min_max,bool infer_latches)2147 read_liberty_cmd(char *filename,
2148 		 Corner *corner,
2149 		 const MinMaxAll *min_max,
2150 		 bool infer_latches)
2151 {
2152   LibertyLibrary *lib = Sta::sta()->readLiberty(filename, corner, min_max,
2153 						infer_latches);
2154   return (lib != nullptr);
2155 }
2156 
2157 bool
set_min_library_cmd(char * min_filename,char * max_filename)2158 set_min_library_cmd(char *min_filename,
2159 		    char *max_filename)
2160 {
2161   return Sta::sta()->setMinLibrary(min_filename, max_filename);
2162 }
2163 
2164 Library *
find_library(const char * name)2165 find_library(const char *name)
2166 {
2167   return cmdNetwork()->findLibrary(name);
2168 }
2169 
2170 LibraryIterator *
library_iterator()2171 library_iterator()
2172 {
2173   return cmdNetwork()->libraryIterator();
2174 }
2175 
2176 LibertyLibrary *
find_liberty(const char * name)2177 find_liberty(const char *name)
2178 {
2179   return cmdNetwork()->findLiberty(name);
2180 }
2181 
2182 LibertyLibraryIterator *
liberty_library_iterator()2183 liberty_library_iterator()
2184 {
2185   return cmdNetwork()->libertyLibraryIterator();
2186 }
2187 
2188 LibertyCell *
find_liberty_cell(const char * name)2189 find_liberty_cell(const char *name)
2190 {
2191   return cmdNetwork()->findLibertyCell(name);
2192 }
2193 
2194 TmpCellSeq *
find_cells_matching(const char * pattern,bool regexp,bool nocase)2195 find_cells_matching(const char *pattern,
2196 		    bool regexp,
2197 		    bool nocase)
2198 {
2199   Network *network = cmdNetwork();
2200   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
2201   TmpCellSeq *cells = new TmpCellSeq;
2202   LibraryIterator *lib_iter = network->libraryIterator();
2203   while (lib_iter->hasNext()) {
2204     Library *lib = lib_iter->next();
2205     network->findCellsMatching(lib, &matcher, cells);
2206   }
2207   delete lib_iter;
2208   return cells;
2209 }
2210 
2211 LibertyCellSeq *
find_library_buffers(LibertyLibrary * library)2212 find_library_buffers(LibertyLibrary *library)
2213 {
2214   return library->buffers();
2215 }
2216 
2217 void
make_equiv_cells(LibertyLibrary * lib)2218 make_equiv_cells(LibertyLibrary *lib)
2219 {
2220   LibertyLibrarySeq libs;
2221   libs.push_back(lib);
2222   Sta::sta()->makeEquivCells(&libs, nullptr);
2223 }
2224 
2225 LibertyCellSeq *
find_equiv_cells(LibertyCell * cell)2226 find_equiv_cells(LibertyCell *cell)
2227 {
2228   return Sta::sta()->equivCells(cell);
2229 }
2230 
2231 bool
equiv_cells(LibertyCell * cell1,LibertyCell * cell2)2232 equiv_cells(LibertyCell *cell1,
2233 	    LibertyCell *cell2)
2234 {
2235   return sta::equivCells(cell1, cell2);
2236 }
2237 
2238 bool
equiv_cell_ports(LibertyCell * cell1,LibertyCell * cell2)2239 equiv_cell_ports(LibertyCell *cell1,
2240 		 LibertyCell *cell2)
2241 {
2242   return equivCellPorts(cell1, cell2);
2243 }
2244 
2245 bool
equiv_cell_timing_arcs(LibertyCell * cell1,LibertyCell * cell2)2246 equiv_cell_timing_arcs(LibertyCell *cell1,
2247 		       LibertyCell *cell2)
2248 {
2249   return equivCellTimingArcSets(cell1, cell2);
2250 }
2251 
2252 void
set_cmd_namespace_cmd(const char * namespc)2253 set_cmd_namespace_cmd(const char *namespc)
2254 {
2255   if (stringEq(namespc, "sdc"))
2256     Sta::sta()->setCmdNamespace(CmdNamespace::sdc);
2257   else if (stringEq(namespc, "sta"))
2258     Sta::sta()->setCmdNamespace(CmdNamespace::sta);
2259   else
2260     criticalError(269, "unknown namespace");
2261 }
2262 
2263 bool
link_design_cmd(const char * top_cell_name)2264 link_design_cmd(const char *top_cell_name)
2265 {
2266   return Sta::sta()->linkDesign(top_cell_name);
2267 }
2268 
2269 bool
link_make_black_boxes()2270 link_make_black_boxes()
2271 {
2272   return Sta::sta()->linkMakeBlackBoxes();
2273 }
2274 
2275 void
set_link_make_black_boxes(bool make)2276 set_link_make_black_boxes(bool make)
2277 {
2278   Sta::sta()->setLinkMakeBlackBoxes(make);
2279 }
2280 
2281 Instance *
top_instance()2282 top_instance()
2283 {
2284   return cmdLinkedNetwork()->topInstance();
2285 }
2286 
2287 const char *
liberty_port_direction(const LibertyPort * port)2288 liberty_port_direction(const LibertyPort *port)
2289 {
2290   return port->direction()->name();
2291 }
2292 
2293 const char *
port_direction(const Port * port)2294 port_direction(const Port *port)
2295 {
2296   return cmdLinkedNetwork()->direction(port)->name();
2297 }
2298 
2299 const char *
pin_direction(const Pin * pin)2300 pin_direction(const Pin *pin)
2301 {
2302   return cmdLinkedNetwork()->direction(pin)->name();
2303 }
2304 
2305 TmpPortSeq *
find_ports_matching(const char * pattern,bool regexp,bool nocase)2306 find_ports_matching(const char *pattern,
2307 		    bool regexp,
2308 		    bool nocase)
2309 {
2310   Network *network = cmdLinkedNetwork();
2311   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
2312   Cell *top_cell = network->cell(network->topInstance());
2313   PortSeq ports1;
2314   network->findPortsMatching(top_cell, &matcher, &ports1);
2315   // Expand bus/bundle ports.
2316   TmpPortSeq *ports = new TmpPortSeq;
2317   PortSeq::Iterator port_iter(ports1);
2318   while (port_iter.hasNext()) {
2319     Port *port = port_iter.next();
2320     if (network->isBus(port)
2321 	|| network->isBundle(port)) {
2322       PortMemberIterator *member_iter = network->memberIterator(port);
2323       while (member_iter->hasNext()) {
2324 	Port *member = member_iter->next();
2325 	ports->push_back(member);
2326       }
2327       delete member_iter;
2328     }
2329     else
2330       ports->push_back(port);
2331   }
2332   return ports;
2333 }
2334 
2335 TmpPinSeq *
find_port_pins_matching(const char * pattern,bool regexp,bool nocase)2336 find_port_pins_matching(const char *pattern,
2337 			bool regexp,
2338 			bool nocase)
2339 {
2340   Network *network = cmdLinkedNetwork();
2341   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
2342   PortSeq ports;
2343   Instance *top_inst = network->topInstance();
2344   Cell *top_cell = network->cell(top_inst);
2345   network->findPortsMatching(top_cell, &matcher, &ports);
2346   TmpPinSeq *pins = new TmpPinSeq;
2347   PortSeq::Iterator port_iter(ports);
2348   while (port_iter.hasNext()) {
2349     Port *port = port_iter.next();
2350     if (network->isBus(port)
2351 	|| network->isBundle(port)) {
2352       PortMemberIterator *member_iter = network->memberIterator(port);
2353       while (member_iter->hasNext()) {
2354 	Port *member = member_iter->next();
2355 	Pin *pin = network->findPin(top_inst, member);
2356 	if (pin)
2357 	  pins->push_back(pin);
2358       }
2359       delete member_iter;
2360     }
2361     else {
2362       Pin *pin = network->findPin(top_inst, port);
2363       if (pin)
2364 	pins->push_back(pin);
2365     }
2366   }
2367   return pins;
2368 }
2369 
2370 Pin *
find_pin(const char * path_name)2371 find_pin(const char *path_name)
2372 {
2373   return cmdLinkedNetwork()->findPin(path_name);
2374 }
2375 
2376 TmpPinSeq *
find_pins_matching(const char * pattern,bool regexp,bool nocase)2377 find_pins_matching(const char *pattern,
2378 		   bool regexp,
2379 		   bool nocase)
2380 {
2381   Sta *sta = Sta::sta();
2382   Network *network = cmdLinkedNetwork();
2383   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
2384   Instance *current_instance = sta->currentInstance();
2385   TmpPinSeq *pins = new TmpPinSeq;
2386   network->findPinsMatching(current_instance, &matcher, pins);
2387   return pins;
2388 }
2389 
2390 TmpPinSeq *
find_pins_hier_matching(const char * pattern,bool regexp,bool nocase)2391 find_pins_hier_matching(const char *pattern,
2392 			bool regexp,
2393 			bool nocase)
2394 {
2395   Sta *sta = Sta::sta();
2396   Network *network = cmdLinkedNetwork();
2397   Instance *current_instance = sta->currentInstance();
2398   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
2399   TmpPinSeq *pins = new TmpPinSeq;
2400   network->findPinsHierMatching(current_instance, &matcher, pins);
2401   return pins;
2402 }
2403 
2404 Instance *
find_instance(char * path_name)2405 find_instance(char *path_name)
2406 {
2407   return cmdLinkedNetwork()->findInstance(path_name);
2408 }
2409 
2410 TmpInstanceSeq *
network_leaf_instances()2411 network_leaf_instances()
2412 {
2413   InstanceSeq *insts = new InstanceSeq;
2414   LeafInstanceIterator *iter = cmdLinkedNetwork()->leafInstanceIterator();
2415   while (iter->hasNext()) {
2416     Instance *inst = iter->next();
2417     insts->push_back(inst);
2418   }
2419   delete iter;
2420   return insts;
2421 }
2422 
2423 TmpInstanceSeq *
find_instances_matching(const char * pattern,bool regexp,bool nocase)2424 find_instances_matching(const char *pattern,
2425 			bool regexp,
2426 			bool nocase)
2427 {
2428   Sta *sta = Sta::sta();
2429   Instance *current_instance = sta->currentInstance();
2430   PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp());
2431   TmpInstanceSeq *insts = new InstanceSeq;
2432   cmdLinkedNetwork()->findInstancesMatching(current_instance, &matcher, insts);
2433   return insts;
2434 }
2435 
2436 TmpInstanceSeq *
find_instances_hier_matching(const char * pattern,bool regexp,bool nocase)2437 find_instances_hier_matching(const char *pattern,
2438 			     bool regexp,
2439 			     bool nocase)
2440 {
2441   Sta *sta = Sta::sta();
2442   Network *network = cmdLinkedNetwork();
2443   Instance *current_instance = sta->currentInstance();
2444   PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp());
2445   TmpInstanceSeq *insts = new InstanceSeq;
2446   network->findInstancesHierMatching(current_instance, &matcher, insts);
2447   return insts;
2448 }
2449 
2450 TmpInstanceSet *
find_register_instances(ClockSet * clks,const RiseFallBoth * clk_tr,bool edge_triggered,bool latches)2451 find_register_instances(ClockSet *clks,
2452 			const RiseFallBoth *clk_tr,
2453 			bool edge_triggered,
2454 			bool latches)
2455 {
2456   cmdLinkedNetwork();
2457   InstanceSet *insts = Sta::sta()->findRegisterInstances(clks, clk_tr,
2458 							 edge_triggered,
2459 							 latches);
2460   delete clks;
2461   return insts;
2462 }
2463 
2464 TmpPinSet *
find_register_data_pins(ClockSet * clks,const RiseFallBoth * clk_tr,bool edge_triggered,bool latches)2465 find_register_data_pins(ClockSet *clks,
2466 			const RiseFallBoth *clk_tr,
2467 			bool edge_triggered,
2468 			bool latches)
2469 {
2470   cmdLinkedNetwork();
2471   PinSet *pins = Sta::sta()->findRegisterDataPins(clks, clk_tr,
2472 						  edge_triggered, latches);
2473   delete clks;
2474   return pins;
2475 }
2476 
2477 TmpPinSet *
find_register_clk_pins(ClockSet * clks,const RiseFallBoth * clk_tr,bool edge_triggered,bool latches)2478 find_register_clk_pins(ClockSet *clks,
2479 		       const RiseFallBoth *clk_tr,
2480 		       bool edge_triggered,
2481 		       bool latches)
2482 {
2483   cmdLinkedNetwork();
2484   PinSet *pins = Sta::sta()->findRegisterClkPins(clks, clk_tr,
2485 						 edge_triggered, latches);
2486   delete clks;
2487   return pins;
2488 }
2489 
2490 TmpPinSet *
find_register_async_pins(ClockSet * clks,const RiseFallBoth * clk_tr,bool edge_triggered,bool latches)2491 find_register_async_pins(ClockSet *clks,
2492 			 const RiseFallBoth *clk_tr,
2493 			 bool edge_triggered,
2494 			 bool latches)
2495 {
2496   cmdLinkedNetwork();
2497   PinSet *pins = Sta::sta()->findRegisterAsyncPins(clks, clk_tr,
2498 						   edge_triggered, latches);
2499   delete clks;
2500   return pins;
2501 }
2502 
2503 TmpPinSet *
find_register_output_pins(ClockSet * clks,const RiseFallBoth * clk_tr,bool edge_triggered,bool latches)2504 find_register_output_pins(ClockSet *clks,
2505 			  const RiseFallBoth *clk_tr,
2506 			  bool edge_triggered,
2507 			  bool latches)
2508 {
2509   cmdLinkedNetwork();
2510   PinSet *pins = Sta::sta()->findRegisterOutputPins(clks, clk_tr,
2511 						    edge_triggered, latches);
2512   delete clks;
2513   return pins;
2514 }
2515 
2516 Net *
find_net(char * path_name)2517 find_net(char *path_name)
2518 {
2519   return cmdLinkedNetwork()->findNet(path_name);
2520 }
2521 
2522 NetSeq *
find_nets_matching(const char * pattern,bool regexp,bool nocase)2523 find_nets_matching(const char *pattern,
2524 		   bool regexp,
2525 		   bool nocase)
2526 {
2527   Network *network = cmdLinkedNetwork();
2528   Instance *current_instance = Sta::sta()->currentInstance();
2529   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
2530   NetSeq *nets = new NetSeq;
2531   network->findNetsMatching(current_instance, &matcher, nets);
2532   return nets;
2533 }
2534 
2535 NetSeq *
find_nets_hier_matching(const char * pattern,bool regexp,bool nocase)2536 find_nets_hier_matching(const char *pattern,
2537 			bool regexp,
2538 			bool nocase)
2539 {
2540   Network *network = cmdLinkedNetwork();
2541   Instance *current_instance = Sta::sta()->currentInstance();
2542   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
2543   NetSeq *nets = new NetSeq;
2544   network->findNetsHierMatching(current_instance, &matcher, nets);
2545   return nets;
2546 }
2547 
2548 TmpPortSeq *
filter_ports(const char * property,const char * op,const char * pattern,PortSeq * ports)2549 filter_ports(const char *property,
2550 	     const char *op,
2551 	     const char *pattern,
2552 	     PortSeq *ports)
2553 {
2554   Sta *sta = Sta::sta();
2555   TmpPortSeq *filtered_ports = new TmpPortSeq;
2556   PortSeq::Iterator port_iter(ports);
2557   bool exact_match = stringEq(op, "==");
2558   while (port_iter.hasNext()) {
2559     Port *port = port_iter.next();
2560     PropertyValue value(getProperty(port, property, sta));
2561     const char *prop = value.stringValue();
2562     if (prop &&
2563 	((exact_match && stringEq(prop, pattern))
2564 	 || (!exact_match && patternMatch(pattern, prop))))
2565       filtered_ports->push_back(port);
2566   }
2567   delete ports;
2568   return filtered_ports;
2569 }
2570 
2571 TmpInstanceSeq *
filter_insts(const char * property,const char * op,const char * pattern,InstanceSeq * insts)2572 filter_insts(const char *property,
2573 	     const char *op,
2574 	     const char *pattern,
2575 	     InstanceSeq *insts)
2576 {
2577   Sta *sta = Sta::sta();
2578   cmdLinkedNetwork();
2579   TmpInstanceSeq *filtered_insts = new TmpInstanceSeq;
2580   TmpInstanceSeq::Iterator inst_iter(insts);
2581   bool exact_match = stringEq(op, "==");
2582   while (inst_iter.hasNext()) {
2583     Instance *inst = inst_iter.next();
2584     PropertyValue value(getProperty(inst, property, sta));
2585     const char *prop = value.stringValue();
2586     if (prop &&
2587 	((exact_match && stringEq(prop, pattern))
2588 	 || (!exact_match && patternMatch(pattern, prop))))
2589       filtered_insts->push_back(inst);
2590   }
2591   delete insts;
2592   return filtered_insts;
2593 }
2594 
2595 PinSeq *
filter_pins(const char * property,const char * op,const char * pattern,PinSeq * pins)2596 filter_pins(const char *property,
2597 	    const char *op,
2598 	    const char *pattern,
2599 	    PinSeq *pins)
2600 {
2601   Sta *sta = Sta::sta();
2602   PinSeq *filtered_pins = new PinSeq;
2603   PinSeq::Iterator pin_iter(pins);
2604   bool exact_match = stringEq(op, "==");
2605   while (pin_iter.hasNext()) {
2606     Pin *pin = pin_iter.next();
2607     PropertyValue value(getProperty(pin, property, sta));
2608     const char *prop = value.stringValue();
2609     if (prop &&
2610 	((exact_match && stringEq(prop, pattern))
2611 	 || (!exact_match && patternMatch(pattern, prop))))
2612       filtered_pins->push_back(pin);
2613   }
2614   delete pins;
2615   return filtered_pins;
2616 }
2617 
2618 PropertyValue
pin_property(const Pin * pin,const char * property)2619 pin_property(const Pin *pin,
2620 	     const char *property)
2621 {
2622   cmdLinkedNetwork();
2623   return getProperty(pin, property, Sta::sta());
2624 }
2625 
2626 PropertyValue
instance_property(const Instance * inst,const char * property)2627 instance_property(const Instance *inst,
2628 		  const char *property)
2629 {
2630   cmdLinkedNetwork();
2631   return getProperty(inst, property, Sta::sta());
2632 }
2633 
2634 PropertyValue
net_property(const Net * net,const char * property)2635 net_property(const Net *net,
2636 	     const char *property)
2637 {
2638   cmdLinkedNetwork();
2639   return getProperty(net, property, Sta::sta());
2640 }
2641 
2642 PropertyValue
port_property(const Port * port,const char * property)2643 port_property(const Port *port,
2644 	      const char *property)
2645 {
2646   return getProperty(port, property, Sta::sta());
2647 }
2648 
2649 
2650 PropertyValue
liberty_cell_property(const LibertyCell * cell,const char * property)2651 liberty_cell_property(const LibertyCell *cell,
2652 		      const char *property)
2653 {
2654   return getProperty(cell, property, Sta::sta());
2655 }
2656 
2657 PropertyValue
cell_property(const Cell * cell,const char * property)2658 cell_property(const Cell *cell,
2659 	      const char *property)
2660 {
2661   return getProperty(cell, property, Sta::sta());
2662 }
2663 
2664 PropertyValue
liberty_port_property(const LibertyPort * port,const char * property)2665 liberty_port_property(const LibertyPort *port,
2666 		      const char *property)
2667 {
2668   return getProperty(port, property, Sta::sta());
2669 }
2670 
2671 PropertyValue
library_property(const Library * lib,const char * property)2672 library_property(const Library *lib,
2673 		 const char *property)
2674 {
2675   return getProperty(lib, property, Sta::sta());
2676 }
2677 
2678 PropertyValue
liberty_library_property(const LibertyLibrary * lib,const char * property)2679 liberty_library_property(const LibertyLibrary *lib,
2680 			 const char *property)
2681 {
2682   return getProperty(lib, property, Sta::sta());
2683 }
2684 
2685 PropertyValue
edge_property(Edge * edge,const char * property)2686 edge_property(Edge *edge,
2687 	      const char *property)
2688 {
2689   cmdGraph();
2690   return getProperty(edge, property, Sta::sta());
2691 }
2692 
2693 PropertyValue
clock_property(Clock * clk,const char * property)2694 clock_property(Clock *clk,
2695 	       const char *property)
2696 {
2697   cmdLinkedNetwork();
2698   return getProperty(clk, property, Sta::sta());
2699 }
2700 
2701 PropertyValue
path_end_property(PathEnd * end,const char * property)2702 path_end_property(PathEnd *end,
2703 		  const char *property)
2704 {
2705   cmdLinkedNetwork();
2706   return getProperty(end, property, Sta::sta());
2707 }
2708 
2709 PropertyValue
path_ref_property(PathRef * path,const char * property)2710 path_ref_property(PathRef *path,
2711 		  const char *property)
2712 {
2713   cmdLinkedNetwork();
2714   return getProperty(path, property, Sta::sta());
2715 }
2716 
2717 PropertyValue
timing_arc_set_property(TimingArcSet * arc_set,const char * property)2718 timing_arc_set_property(TimingArcSet *arc_set,
2719 			const char *property)
2720 {
2721   cmdLinkedNetwork();
2722   return getProperty(arc_set, property, Sta::sta());
2723 }
2724 
2725 LeafInstanceIterator *
leaf_instance_iterator()2726 leaf_instance_iterator()
2727 {
2728   return cmdLinkedNetwork()->leafInstanceIterator();
2729 }
2730 
2731 ////////////////////////////////////////////////////////////////
2732 
2733 void
define_corners_cmd(StringSet * corner_names)2734 define_corners_cmd(StringSet *corner_names)
2735 {
2736   Sta *sta = Sta::sta();
2737   sta->makeCorners(corner_names);
2738   delete corner_names;
2739 }
2740 
2741 Corner *
cmd_corner()2742 cmd_corner()
2743 {
2744   return Sta::sta()->cmdCorner();
2745 }
2746 
2747 void
set_cmd_corner(Corner * corner)2748 set_cmd_corner(Corner *corner)
2749 {
2750   Sta::sta()->setCmdCorner(corner);
2751 }
2752 
2753 Corner *
find_corner(const char * corner_name)2754 find_corner(const char *corner_name)
2755 {
2756   return Sta::sta()->findCorner(corner_name);
2757 }
2758 
2759 Corners *
corners()2760 corners()
2761 {
2762   return Sta::sta()->corners();
2763 }
2764 
2765 bool
multi_corner()2766 multi_corner()
2767 {
2768   return Sta::sta()->multiCorner();
2769 }
2770 
2771 ////////////////////////////////////////////////////////////////
2772 
2773 void
set_analysis_type_cmd(const char * analysis_type)2774 set_analysis_type_cmd(const char *analysis_type)
2775 {
2776   AnalysisType type;
2777   if (stringEq(analysis_type, "single"))
2778     type = AnalysisType::single;
2779   else if (stringEq(analysis_type, "bc_wc"))
2780     type = AnalysisType::bc_wc;
2781   else if (stringEq(analysis_type, "on_chip_variation"))
2782     type = AnalysisType::ocv;
2783   else {
2784     criticalError(270, "unknown analysis type");
2785     type = AnalysisType::single;
2786   }
2787   Sta::sta()->setAnalysisType(type);
2788 }
2789 
2790 OperatingConditions *
operating_conditions(const MinMax * min_max)2791 operating_conditions(const MinMax *min_max)
2792 {
2793   return Sta::sta()->operatingConditions(min_max);
2794 }
2795 
2796 void
set_operating_conditions_cmd(OperatingConditions * op_cond,const MinMaxAll * min_max)2797 set_operating_conditions_cmd(OperatingConditions *op_cond,
2798 			     const MinMaxAll *min_max)
2799 {
2800   Sta::sta()->setOperatingConditions(op_cond, min_max);
2801 }
2802 
2803 EdgeSeq *
filter_timing_arcs(const char * property,const char * op,const char * pattern,EdgeSeq * edges)2804 filter_timing_arcs(const char *property,
2805 		   const char *op,
2806 		   const char *pattern,
2807 		   EdgeSeq *edges)
2808 {
2809   Sta *sta = Sta::sta();
2810   EdgeSeq *filtered_edges = new EdgeSeq;
2811   EdgeSeq::Iterator edge_iter(edges);
2812   bool exact_match = stringEq(op, "==");
2813   while (edge_iter.hasNext()) {
2814     Edge *edge = edge_iter.next();
2815     PropertyValue value(getProperty(edge, property, sta));
2816     const char *prop = value.stringValue();
2817     if (prop &&
2818 	((exact_match && stringEq(prop, pattern))
2819 	 || (!exact_match && patternMatch(pattern, prop))))
2820       filtered_edges->push_back(edge);
2821   }
2822   delete edges;
2823   return filtered_edges;
2824 }
2825 
2826 const char *
operating_condition_analysis_type()2827 operating_condition_analysis_type()
2828 {
2829   switch (Sta::sta()->sdc()->analysisType()){
2830   case AnalysisType::single:
2831     return "single";
2832   case AnalysisType::bc_wc:
2833     return "bc_wc";
2834   case AnalysisType::ocv:
2835     return "on_chip_variation";
2836   }
2837   // Prevent warnings from lame compilers.
2838   return "?";
2839 }
2840 
2841 void
set_instance_pvt(Instance * inst,const MinMaxAll * min_max,float process,float voltage,float temperature)2842 set_instance_pvt(Instance *inst,
2843 		 const MinMaxAll *min_max,
2844 		 float process,
2845 		 float voltage,
2846 		 float temperature)
2847 {
2848   cmdLinkedNetwork();
2849   Pvt *pvt = new Pvt(process, voltage, temperature);
2850   Sta::sta()->setPvt(inst, min_max, pvt);
2851 }
2852 
2853 float
port_ext_pin_cap(Port * port,const MinMax * min_max)2854 port_ext_pin_cap(Port *port,
2855 		 const MinMax *min_max)
2856 {
2857   cmdLinkedNetwork();
2858   float pin_cap, wire_cap;
2859   int fanout;
2860   Sta::sta()->portExtCaps(port, min_max, pin_cap, wire_cap, fanout);
2861   return pin_cap;
2862 }
2863 
2864 void
set_port_pin_cap(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float cap)2865 set_port_pin_cap(Port *port,
2866 		 const RiseFallBoth *rf,
2867 		 const MinMaxAll *min_max,
2868 		 float cap)
2869 {
2870   Sta::sta()->setPortExtPinCap(port, rf, min_max, cap);
2871 }
2872 
2873 float
port_ext_wire_cap(Port * port,const MinMax * min_max)2874 port_ext_wire_cap(Port *port,
2875                   const MinMax *min_max)
2876 {
2877   cmdLinkedNetwork();
2878   float pin_cap, wire_cap;
2879   int fanout;
2880   Sta::sta()->portExtCaps(port, min_max, pin_cap, wire_cap, fanout);
2881   return wire_cap;
2882 }
2883 
2884 void
set_port_wire_cap(Port * port,bool subtract_pin_cap,const RiseFallBoth * rf,const MinMaxAll * min_max,float cap)2885 set_port_wire_cap(Port *port,
2886 		  bool subtract_pin_cap,
2887 		  const RiseFallBoth *rf,
2888 		  const MinMaxAll *min_max,
2889 		  float cap)
2890 {
2891   Sta::sta()->setPortExtWireCap(port, subtract_pin_cap, rf, min_max, cap);
2892 }
2893 
2894 void
set_port_ext_fanout_cmd(Port * port,int fanout,const MinMaxAll * min_max)2895 set_port_ext_fanout_cmd(Port *port,
2896 			int fanout,
2897 			const MinMaxAll *min_max)
2898 {
2899   Sta::sta()->setPortExtFanout(port, fanout, min_max);
2900 }
2901 
2902 float
port_ext_fanout(Port * port,const MinMax * min_max)2903 port_ext_fanout(Port *port,
2904                 const MinMax *min_max)
2905 {
2906   cmdLinkedNetwork();
2907   float pin_cap, wire_cap;
2908   int fanout;
2909   Sta::sta()->portExtCaps(port, min_max, pin_cap, wire_cap, fanout);
2910   return fanout;
2911 }
2912 
2913 void
set_net_wire_cap(Net * net,bool subtract_pin_cap,Corner * corner,const MinMaxAll * min_max,float cap)2914 set_net_wire_cap(Net *net,
2915 		 bool subtract_pin_cap,
2916 		 Corner *corner,
2917 		 const MinMaxAll *min_max,
2918 		 float cap)
2919 {
2920   Sta::sta()->setNetWireCap(net, subtract_pin_cap, corner, min_max, cap);
2921 }
2922 
2923 void
set_wire_load_mode_cmd(const char * mode_name)2924 set_wire_load_mode_cmd(const char *mode_name)
2925 {
2926   WireloadMode mode = stringWireloadMode(mode_name);
2927   if (mode == WireloadMode::unknown)
2928     criticalError(271, "unknown wire load mode");
2929   else
2930     Sta::sta()->setWireloadMode(mode);
2931 }
2932 
2933 void
set_net_resistance(Net * net,const MinMaxAll * min_max,float res)2934 set_net_resistance(Net *net,
2935 		   const MinMaxAll *min_max,
2936 		   float res)
2937 {
2938   Sta::sta()->setResistance(net, min_max, res);
2939 }
2940 
2941 void
set_wire_load_cmd(Wireload * wireload,const MinMaxAll * min_max)2942 set_wire_load_cmd(Wireload *wireload,
2943 		  const MinMaxAll *min_max)
2944 {
2945   Sta::sta()->setWireload(wireload, min_max);
2946 }
2947 
2948 void
set_wire_load_selection_group_cmd(WireloadSelection * selection,const MinMaxAll * min_max)2949 set_wire_load_selection_group_cmd(WireloadSelection *selection,
2950 				  const MinMaxAll *min_max)
2951 {
2952   Sta::sta()->setWireloadSelection(selection, min_max);
2953 }
2954 
2955 void
make_clock(const char * name,PinSet * pins,bool add_to_pins,float period,FloatSeq * waveform,char * comment)2956 make_clock(const char *name,
2957 	   PinSet *pins,
2958 	   bool add_to_pins,
2959 	   float period,
2960 	   FloatSeq *waveform,
2961 	   char *comment)
2962 {
2963   cmdLinkedNetwork();
2964   Sta::sta()->makeClock(name, pins, add_to_pins, period, waveform, comment);
2965 }
2966 
2967 void
make_generated_clock(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)2968 make_generated_clock(const char *name,
2969 		     PinSet *pins,
2970 		     bool add_to_pins,
2971 		     Pin *src_pin,
2972 		     Clock *master_clk,
2973 		     Pin *pll_out,
2974 		     Pin *pll_fdbk,
2975 		     int divide_by,
2976 		     int multiply_by,
2977 		     float duty_cycle,
2978 		     bool invert,
2979 		     bool combinational,
2980 		     IntSeq *edges,
2981 		     FloatSeq *edge_shifts,
2982 		     char *comment)
2983 {
2984   cmdLinkedNetwork();
2985   Sta::sta()->makeGeneratedClock(name, pins, add_to_pins,
2986 				 src_pin, master_clk, pll_out, pll_fdbk,
2987 				 divide_by, multiply_by, duty_cycle, invert,
2988 				 combinational, edges, edge_shifts,
2989 				 comment);
2990 }
2991 
2992 void
remove_clock_cmd(Clock * clk)2993 remove_clock_cmd(Clock *clk)
2994 {
2995   cmdLinkedNetwork();
2996   Sta::sta()->removeClock(clk);
2997 }
2998 
2999 void
set_propagated_clock_cmd(Clock * clk)3000 set_propagated_clock_cmd(Clock *clk)
3001 {
3002   cmdLinkedNetwork();
3003   Sta::sta()->setPropagatedClock(clk);
3004 }
3005 
3006 void
set_propagated_clock_pin_cmd(Pin * pin)3007 set_propagated_clock_pin_cmd(Pin *pin)
3008 {
3009   cmdLinkedNetwork();
3010   Sta::sta()->setPropagatedClock(pin);
3011 }
3012 
3013 void
unset_propagated_clock_cmd(Clock * clk)3014 unset_propagated_clock_cmd(Clock *clk)
3015 {
3016   cmdLinkedNetwork();
3017   Sta::sta()->removePropagatedClock(clk);
3018 }
3019 
3020 void
unset_propagated_clock_pin_cmd(Pin * pin)3021 unset_propagated_clock_pin_cmd(Pin *pin)
3022 {
3023   cmdLinkedNetwork();
3024   Sta::sta()->removePropagatedClock(pin);
3025 }
3026 
3027 void
set_clock_slew_cmd(Clock * clk,const RiseFallBoth * rf,const MinMaxAll * min_max,float slew)3028 set_clock_slew_cmd(Clock *clk,
3029 		   const RiseFallBoth *rf,
3030 		   const MinMaxAll *min_max,
3031 		   float slew)
3032 {
3033   cmdLinkedNetwork();
3034   Sta::sta()->setClockSlew(clk, rf, min_max, slew);
3035 }
3036 
3037 void
unset_clock_slew_cmd(Clock * clk)3038 unset_clock_slew_cmd(Clock *clk)
3039 {
3040   cmdLinkedNetwork();
3041   Sta::sta()->removeClockSlew(clk);
3042 }
3043 
3044 void
set_clock_latency_cmd(Clock * clk,Pin * pin,const RiseFallBoth * rf,MinMaxAll * min_max,float delay)3045 set_clock_latency_cmd(Clock *clk,
3046 		      Pin *pin,
3047 		      const RiseFallBoth *rf,
3048 		      MinMaxAll *min_max, float delay)
3049 {
3050   cmdLinkedNetwork();
3051   Sta::sta()->setClockLatency(clk, pin, rf, min_max, delay);
3052 }
3053 
3054 void
set_clock_insertion_cmd(Clock * clk,Pin * pin,const RiseFallBoth * rf,const MinMaxAll * min_max,const EarlyLateAll * early_late,float delay)3055 set_clock_insertion_cmd(Clock *clk,
3056 			Pin *pin,
3057 			const RiseFallBoth *rf,
3058 			const MinMaxAll *min_max,
3059 			const EarlyLateAll *early_late,
3060 			float delay)
3061 {
3062   cmdLinkedNetwork();
3063   Sta::sta()->setClockInsertion(clk, pin, rf, min_max, early_late, delay);
3064 }
3065 
3066 void
unset_clock_latency_cmd(Clock * clk,Pin * pin)3067 unset_clock_latency_cmd(Clock *clk,
3068 			Pin *pin)
3069 {
3070   cmdLinkedNetwork();
3071   Sta::sta()->removeClockLatency(clk, pin);
3072 }
3073 
3074 void
unset_clock_insertion_cmd(Clock * clk,Pin * pin)3075 unset_clock_insertion_cmd(Clock *clk,
3076 			  Pin *pin)
3077 {
3078   cmdLinkedNetwork();
3079   Sta::sta()->removeClockInsertion(clk, pin);
3080 }
3081 
3082 void
set_clock_uncertainty_clk(Clock * clk,const SetupHoldAll * setup_hold,float uncertainty)3083 set_clock_uncertainty_clk(Clock *clk,
3084 			  const SetupHoldAll *setup_hold,
3085 			  float uncertainty)
3086 {
3087   cmdLinkedNetwork();
3088   Sta::sta()->setClockUncertainty(clk, setup_hold, uncertainty);
3089 }
3090 
3091 void
unset_clock_uncertainty_clk(Clock * clk,const SetupHoldAll * setup_hold)3092 unset_clock_uncertainty_clk(Clock *clk,
3093 			    const SetupHoldAll *setup_hold)
3094 {
3095   cmdLinkedNetwork();
3096   Sta::sta()->removeClockUncertainty(clk, setup_hold);
3097 }
3098 
3099 void
set_clock_uncertainty_pin(Pin * pin,const MinMaxAll * min_max,float uncertainty)3100 set_clock_uncertainty_pin(Pin *pin,
3101 			  const MinMaxAll *min_max,
3102 			  float uncertainty)
3103 {
3104   cmdLinkedNetwork();
3105   Sta::sta()->setClockUncertainty(pin, min_max, uncertainty);
3106 }
3107 
3108 void
unset_clock_uncertainty_pin(Pin * pin,const MinMaxAll * min_max)3109 unset_clock_uncertainty_pin(Pin *pin,
3110 			    const MinMaxAll *min_max)
3111 {
3112   cmdLinkedNetwork();
3113   Sta::sta()->removeClockUncertainty(pin, min_max);
3114 }
3115 
3116 void
set_inter_clock_uncertainty(Clock * from_clk,const RiseFallBoth * from_tr,Clock * to_clk,const RiseFallBoth * to_tr,const MinMaxAll * min_max,float uncertainty)3117 set_inter_clock_uncertainty(Clock *from_clk,
3118 			    const RiseFallBoth *from_tr,
3119 			    Clock *to_clk,
3120 			    const RiseFallBoth *to_tr,
3121 			    const MinMaxAll *min_max,
3122 			    float uncertainty)
3123 {
3124   cmdLinkedNetwork();
3125   Sta::sta()->setClockUncertainty(from_clk, from_tr, to_clk, to_tr, min_max,
3126 				  uncertainty);
3127 }
3128 
3129 void
unset_inter_clock_uncertainty(Clock * from_clk,const RiseFallBoth * from_tr,Clock * to_clk,const RiseFallBoth * to_tr,const MinMaxAll * min_max)3130 unset_inter_clock_uncertainty(Clock *from_clk,
3131 			      const RiseFallBoth *from_tr,
3132 			      Clock *to_clk,
3133 			      const RiseFallBoth *to_tr,
3134 			      const MinMaxAll *min_max)
3135 {
3136   cmdLinkedNetwork();
3137   Sta::sta()->removeClockUncertainty(from_clk, from_tr, to_clk, to_tr, min_max);
3138 }
3139 
3140 void
set_clock_gating_check_cmd(const RiseFallBoth * rf,const SetupHold * setup_hold,float margin)3141 set_clock_gating_check_cmd(const RiseFallBoth *rf,
3142 			   const SetupHold *setup_hold,
3143 			   float margin)
3144 {
3145   Sta::sta()->setClockGatingCheck(rf, setup_hold, margin);
3146 }
3147 
3148 void
set_clock_gating_check_clk_cmd(Clock * clk,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin)3149 set_clock_gating_check_clk_cmd(Clock *clk,
3150 			       const RiseFallBoth *rf,
3151 			       const SetupHold *setup_hold,
3152 			       float margin)
3153 {
3154   Sta::sta()->setClockGatingCheck(clk, rf, setup_hold, margin);
3155 }
3156 
3157 void
set_clock_gating_check_pin_cmd(Pin * pin,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin,LogicValue active_value)3158 set_clock_gating_check_pin_cmd(Pin *pin,
3159 			       const RiseFallBoth *rf,
3160 			       const SetupHold *setup_hold,
3161 			       float margin,
3162 			       LogicValue active_value)
3163 {
3164   Sta::sta()->setClockGatingCheck(pin, rf, setup_hold, margin, active_value);
3165 }
3166 
3167 void
set_clock_gating_check_instance_cmd(Instance * inst,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin,LogicValue active_value)3168 set_clock_gating_check_instance_cmd(Instance *inst,
3169 				    const RiseFallBoth *rf,
3170 				    const SetupHold *setup_hold,
3171 				    float margin,
3172 				    LogicValue active_value)
3173 {
3174   Sta::sta()->setClockGatingCheck(inst, rf, setup_hold, margin, active_value);
3175 }
3176 
3177 void
set_data_check_cmd(Pin * from,const RiseFallBoth * from_rf,Pin * to,const RiseFallBoth * to_rf,Clock * clk,const SetupHoldAll * setup_hold,float margin)3178 set_data_check_cmd(Pin *from,
3179 		   const RiseFallBoth *from_rf,
3180 		   Pin *to,
3181 		   const RiseFallBoth *to_rf,
3182 		   Clock *clk,
3183 		   const SetupHoldAll *setup_hold,
3184 		   float margin)
3185 {
3186   Sta::sta()->setDataCheck(from, from_rf, to, to_rf, clk, setup_hold, margin);
3187 }
3188 
3189 void
unset_data_check_cmd(Pin * from,const RiseFallBoth * from_tr,Pin * to,const RiseFallBoth * to_tr,Clock * clk,const SetupHoldAll * setup_hold)3190 unset_data_check_cmd(Pin *from,
3191 		     const RiseFallBoth *from_tr,
3192 		     Pin *to,
3193 		     const RiseFallBoth *to_tr,
3194 		     Clock *clk,
3195 		     const SetupHoldAll *setup_hold)
3196 {
3197   Sta::sta()->removeDataCheck(from, from_tr, to, to_tr, clk, setup_hold);
3198 }
3199 
3200 void
set_input_delay_cmd(Pin * pin,RiseFallBoth * rf,Clock * clk,RiseFall * clk_rf,Pin * ref_pin,bool source_latency_included,bool network_latency_included,MinMaxAll * min_max,bool add,float delay)3201 set_input_delay_cmd(Pin *pin,
3202 		    RiseFallBoth *rf,
3203 		    Clock *clk,
3204 		    RiseFall *clk_rf,
3205 		    Pin *ref_pin,
3206 		    bool source_latency_included,
3207 		    bool network_latency_included,
3208 		    MinMaxAll *min_max,
3209 		    bool add,
3210 		    float delay)
3211 {
3212   cmdLinkedNetwork();
3213   Sta::sta()->setInputDelay(pin, rf, clk, clk_rf, ref_pin,
3214 			    source_latency_included, network_latency_included,
3215 			    min_max, add, delay);
3216 }
3217 
3218 void
unset_input_delay_cmd(Pin * pin,RiseFallBoth * rf,Clock * clk,RiseFall * clk_rf,MinMaxAll * min_max)3219 unset_input_delay_cmd(Pin *pin,
3220 		      RiseFallBoth *rf,
3221 		      Clock *clk,
3222 		      RiseFall *clk_rf,
3223 		      MinMaxAll *min_max)
3224 {
3225   cmdLinkedNetwork();
3226   Sta::sta()->removeInputDelay(pin, rf, clk, clk_rf, min_max);
3227 }
3228 
3229 void
set_output_delay_cmd(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)3230 set_output_delay_cmd(Pin *pin,
3231 		     const RiseFallBoth *rf,
3232 		     Clock *clk,
3233 		     const RiseFall *clk_rf,
3234 		     Pin *ref_pin,
3235 		     bool source_latency_included,
3236 		     bool network_latency_included,
3237 		     const MinMaxAll *min_max,
3238 		     bool add,
3239 		     float delay)
3240 {
3241   cmdLinkedNetwork();
3242   Sta::sta()->setOutputDelay(pin, rf, clk, clk_rf, ref_pin,
3243 			     source_latency_included, network_latency_included,
3244 			     min_max, add, delay);
3245 }
3246 
3247 void
unset_output_delay_cmd(Pin * pin,RiseFallBoth * rf,Clock * clk,RiseFall * clk_rf,MinMaxAll * min_max)3248 unset_output_delay_cmd(Pin *pin,
3249 		       RiseFallBoth *rf,
3250 		       Clock *clk,
3251 		       RiseFall *clk_rf,
3252 		       MinMaxAll *min_max)
3253 {
3254   cmdLinkedNetwork();
3255   Sta::sta()->removeOutputDelay(pin, rf, clk, clk_rf, min_max);
3256 }
3257 
3258 void
disable_cell(LibertyCell * cell,LibertyPort * from,LibertyPort * to)3259 disable_cell(LibertyCell *cell,
3260 	     LibertyPort *from,
3261 	     LibertyPort *to)
3262 {
3263   cmdLinkedNetwork();
3264   Sta::sta()->disable(cell, from, to);
3265 }
3266 
3267 void
unset_disable_cell(LibertyCell * cell,LibertyPort * from,LibertyPort * to)3268 unset_disable_cell(LibertyCell *cell,
3269 		   LibertyPort *from,
3270 		   LibertyPort *to)
3271 {
3272   cmdLinkedNetwork();
3273   Sta::sta()->removeDisable(cell, from, to);
3274 }
3275 
3276 void
disable_lib_port(LibertyPort * port)3277 disable_lib_port(LibertyPort *port)
3278 {
3279   cmdLinkedNetwork();
3280   Sta::sta()->disable(port);
3281 }
3282 
3283 void
unset_disable_lib_port(LibertyPort * port)3284 unset_disable_lib_port(LibertyPort *port)
3285 {
3286   cmdLinkedNetwork();
3287   Sta::sta()->removeDisable(port);
3288 }
3289 
3290 void
disable_port(Port * port)3291 disable_port(Port *port)
3292 {
3293   cmdLinkedNetwork();
3294   Sta::sta()->disable(port);
3295 }
3296 
3297 void
unset_disable_port(Port * port)3298 unset_disable_port(Port *port)
3299 {
3300   cmdLinkedNetwork();
3301   Sta::sta()->removeDisable(port);
3302 }
3303 
3304 void
disable_instance(Instance * instance,LibertyPort * from,LibertyPort * to)3305 disable_instance(Instance *instance,
3306 		 LibertyPort *from,
3307 		 LibertyPort *to)
3308 {
3309   cmdLinkedNetwork();
3310   Sta::sta()->disable(instance, from, to);
3311 }
3312 
3313 void
unset_disable_instance(Instance * instance,LibertyPort * from,LibertyPort * to)3314 unset_disable_instance(Instance *instance,
3315 		       LibertyPort *from,
3316 		       LibertyPort *to)
3317 {
3318   cmdLinkedNetwork();
3319   Sta::sta()->removeDisable(instance, from, to);
3320 }
3321 
3322 void
disable_pin(Pin * pin)3323 disable_pin(Pin *pin)
3324 {
3325   cmdLinkedNetwork();
3326   Sta::sta()->disable(pin);
3327 }
3328 
3329 void
unset_disable_pin(Pin * pin)3330 unset_disable_pin(Pin *pin)
3331 {
3332   cmdLinkedNetwork();
3333   Sta::sta()->removeDisable(pin);
3334 }
3335 
3336 void
disable_edge(Edge * edge)3337 disable_edge(Edge *edge)
3338 {
3339   cmdLinkedNetwork();
3340   Sta::sta()->disable(edge);
3341 }
3342 
3343 void
unset_disable_edge(Edge * edge)3344 unset_disable_edge(Edge *edge)
3345 {
3346   cmdLinkedNetwork();
3347   Sta::sta()->removeDisable(edge);
3348 }
3349 
3350 void
disable_timing_arc_set(TimingArcSet * arc_set)3351 disable_timing_arc_set(TimingArcSet *arc_set)
3352 {
3353   cmdLinkedNetwork();
3354   Sta::sta()->disable(arc_set);
3355 }
3356 
3357 void
unset_disable_timing_arc_set(TimingArcSet * arc_set)3358 unset_disable_timing_arc_set(TimingArcSet *arc_set)
3359 {
3360   cmdLinkedNetwork();
3361   Sta::sta()->removeDisable(arc_set);
3362 }
3363 
3364 void
disable_clock_gating_check_inst(Instance * inst)3365 disable_clock_gating_check_inst(Instance *inst)
3366 {
3367   cmdLinkedNetwork();
3368   Sta::sta()->disableClockGatingCheck(inst);
3369 }
3370 
3371 void
disable_clock_gating_check_pin(Pin * pin)3372 disable_clock_gating_check_pin(Pin *pin)
3373 {
3374   cmdLinkedNetwork();
3375   Sta::sta()->disableClockGatingCheck(pin);
3376 }
3377 
3378 void
unset_disable_clock_gating_check_inst(Instance * inst)3379 unset_disable_clock_gating_check_inst(Instance *inst)
3380 {
3381   cmdLinkedNetwork();
3382   Sta::sta()->removeDisableClockGatingCheck(inst);
3383 }
3384 
3385 void
unset_disable_clock_gating_check_pin(Pin * pin)3386 unset_disable_clock_gating_check_pin(Pin *pin)
3387 {
3388   cmdLinkedNetwork();
3389   Sta::sta()->removeDisableClockGatingCheck(pin);
3390 }
3391 
3392 void
make_false_path(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max,const char * comment)3393 make_false_path(ExceptionFrom *from,
3394 		ExceptionThruSeq *thrus,
3395 		ExceptionTo *to,
3396 		const MinMaxAll *min_max,
3397 		const char *comment)
3398 {
3399   cmdLinkedNetwork();
3400   Sta::sta()->makeFalsePath(from, thrus, to, min_max, comment);
3401 }
3402 
3403 void
make_multicycle_path(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max,bool use_end_clk,int path_multiplier,const char * comment)3404 make_multicycle_path(ExceptionFrom *from,
3405 		     ExceptionThruSeq *thrus,
3406 		     ExceptionTo *to,
3407 		     const MinMaxAll *min_max,
3408 		     bool use_end_clk,
3409 		     int path_multiplier,
3410 		     const char *comment)
3411 {
3412   cmdLinkedNetwork();
3413   Sta::sta()->makeMulticyclePath(from, thrus, to, min_max, use_end_clk,
3414 				 path_multiplier, comment);
3415 }
3416 
3417 void
make_path_delay(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMax * min_max,bool ignore_clk_latency,float delay,const char * comment)3418 make_path_delay(ExceptionFrom *from,
3419 		ExceptionThruSeq *thrus,
3420 		ExceptionTo *to,
3421 		const MinMax *min_max,
3422 		bool ignore_clk_latency,
3423 		float delay,
3424 		const char *comment)
3425 {
3426   cmdLinkedNetwork();
3427   Sta::sta()->makePathDelay(from, thrus, to, min_max,
3428 			    ignore_clk_latency, delay, comment);
3429 }
3430 
3431 void
reset_path_cmd(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max)3432 reset_path_cmd(ExceptionFrom *
3433 	       from, ExceptionThruSeq *thrus,
3434 	       ExceptionTo *to,
3435 	       const MinMaxAll *min_max)
3436 {
3437   cmdLinkedNetwork();
3438   Sta::sta()->resetPath(from, thrus, to, min_max);
3439   // from/to and thru are owned and deleted by the caller.
3440   // ExceptionThruSeq thrus arg is made by TclListSeqExceptionThru
3441   // in the swig converter so it is deleted here.
3442   delete thrus;
3443 }
3444 
3445 void
make_group_path(const char * name,bool is_default,ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const char * comment)3446 make_group_path(const char *name,
3447 		bool is_default,
3448 		ExceptionFrom *from,
3449 		ExceptionThruSeq *thrus,
3450 		ExceptionTo *to,
3451 		const char *comment)
3452 {
3453   cmdLinkedNetwork();
3454   if (name[0] == '\0')
3455     name = nullptr;
3456   Sta::sta()->makeGroupPath(name, is_default, from, thrus, to, comment);
3457 }
3458 
3459 bool
is_path_group_name(const char * name)3460 is_path_group_name(const char *name)
3461 {
3462   cmdLinkedNetwork();
3463   return Sta::sta()->isGroupPathName(name);
3464 }
3465 
3466 ExceptionFrom *
make_exception_from(PinSet * from_pins,ClockSet * from_clks,InstanceSet * from_insts,const RiseFallBoth * from_tr)3467 make_exception_from(PinSet *from_pins,
3468 		    ClockSet *from_clks,
3469 		    InstanceSet *from_insts,
3470 		    const RiseFallBoth *from_tr)
3471 {
3472   cmdLinkedNetwork();
3473   return Sta::sta()->makeExceptionFrom(from_pins, from_clks, from_insts,
3474 				       from_tr);
3475 }
3476 
3477 void
delete_exception_from(ExceptionFrom * from)3478 delete_exception_from(ExceptionFrom *from)
3479 {
3480   Sta::sta()->deleteExceptionFrom(from);
3481 }
3482 
3483 void
check_exception_from_pins(ExceptionFrom * from,const char * file,int line)3484 check_exception_from_pins(ExceptionFrom *from,
3485 			  const char *file,
3486 			  int line)
3487 {
3488   Sta::sta()->checkExceptionFromPins(from, file, line);
3489 }
3490 
3491 ExceptionThru *
make_exception_thru(PinSet * pins,NetSet * nets,InstanceSet * insts,const RiseFallBoth * rf)3492 make_exception_thru(PinSet *pins,
3493 		    NetSet *nets,
3494 		    InstanceSet *insts,
3495 		    const RiseFallBoth *rf)
3496 {
3497   cmdLinkedNetwork();
3498   return Sta::sta()->makeExceptionThru(pins, nets, insts, rf);
3499 }
3500 
3501 void
delete_exception_thru(ExceptionThru * thru)3502 delete_exception_thru(ExceptionThru *thru)
3503 {
3504   Sta::sta()->deleteExceptionThru(thru);
3505 }
3506 
3507 ExceptionTo *
make_exception_to(PinSet * to_pins,ClockSet * to_clks,InstanceSet * to_insts,const RiseFallBoth * rf,RiseFallBoth * end_rf)3508 make_exception_to(PinSet *to_pins,
3509 		  ClockSet *to_clks,
3510 		  InstanceSet *to_insts,
3511 		  const RiseFallBoth *rf,
3512  		  RiseFallBoth *end_rf)
3513 {
3514   cmdLinkedNetwork();
3515   return Sta::sta()->makeExceptionTo(to_pins, to_clks, to_insts, rf, end_rf);
3516 }
3517 
3518 void
delete_exception_to(ExceptionTo * to)3519 delete_exception_to(ExceptionTo *to)
3520 {
3521   Sta::sta()->deleteExceptionTo(to);
3522 }
3523 
3524 void
check_exception_to_pins(ExceptionTo * to,const char * file,int line)3525 check_exception_to_pins(ExceptionTo *to,
3526 			const char *file,
3527 			int line)
3528 {
3529   Sta::sta()->checkExceptionToPins(to, file, line);
3530 }
3531 
3532 void
set_input_slew_cmd(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float slew)3533 set_input_slew_cmd(Port *port,
3534 		   const RiseFallBoth *rf,
3535 		   const MinMaxAll *min_max,
3536 		   float slew)
3537 {
3538   cmdLinkedNetwork();
3539   Sta::sta()->setInputSlew(port, rf, min_max, slew);
3540 }
3541 
3542 void
set_drive_cell_cmd(LibertyLibrary * library,LibertyCell * cell,Port * port,LibertyPort * from_port,float from_slew_rise,float from_slew_fall,LibertyPort * to_port,const RiseFallBoth * rf,const MinMaxAll * min_max)3543 set_drive_cell_cmd(LibertyLibrary *library,
3544 		   LibertyCell *cell,
3545 		   Port *port,
3546 		   LibertyPort *from_port,
3547 		   float from_slew_rise,
3548 		   float from_slew_fall,
3549 		   LibertyPort *to_port,
3550 		   const RiseFallBoth *rf,
3551 		   const MinMaxAll *min_max)
3552 {
3553   float from_slews[RiseFall::index_count];
3554   from_slews[RiseFall::riseIndex()] = from_slew_rise;
3555   from_slews[RiseFall::fallIndex()] = from_slew_fall;
3556   Sta::sta()->setDriveCell(library, cell, port, from_port, from_slews,
3557 			   to_port, rf, min_max);
3558 }
3559 
3560 void
set_drive_resistance_cmd(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float res)3561 set_drive_resistance_cmd(Port *port,
3562 			 const RiseFallBoth *rf,
3563 			 const MinMaxAll *min_max,
3564 			 float res)
3565 {
3566   cmdLinkedNetwork();
3567   Sta::sta()->setDriveResistance(port, rf, min_max, res);
3568 }
3569 
3570 void
set_slew_limit_clk(Clock * clk,const RiseFallBoth * rf,PathClkOrData clk_data,const MinMax * min_max,float slew)3571 set_slew_limit_clk(Clock *clk,
3572 		   const RiseFallBoth *rf,
3573 		   PathClkOrData clk_data,
3574 		   const MinMax *min_max,
3575 		   float slew)
3576 {
3577   cmdLinkedNetwork();
3578   Sta::sta()->setSlewLimit(clk, rf, clk_data, min_max, slew);
3579 }
3580 
3581 void
set_slew_limit_port(Port * port,const MinMax * min_max,float slew)3582 set_slew_limit_port(Port *port,
3583 		    const MinMax *min_max,
3584 		    float slew)
3585 {
3586   cmdLinkedNetwork();
3587   Sta::sta()->setSlewLimit(port, min_max, slew);
3588 }
3589 
3590 void
set_slew_limit_cell(Cell * cell,const MinMax * min_max,float slew)3591 set_slew_limit_cell(Cell *cell,
3592 		    const MinMax *min_max,
3593 		    float slew)
3594 {
3595   cmdLinkedNetwork();
3596   Sta::sta()->setSlewLimit(cell, min_max, slew);
3597 }
3598 
3599 void
set_port_capacitance_limit(Port * port,const MinMax * min_max,float cap)3600 set_port_capacitance_limit(Port *port,
3601 			   const MinMax *min_max,
3602 			   float cap)
3603 {
3604   Sta::sta()->setCapacitanceLimit(port, min_max, cap);
3605 }
3606 
3607 void
set_pin_capacitance_limit(Pin * pin,const MinMax * min_max,float cap)3608 set_pin_capacitance_limit(Pin *pin,
3609 			  const MinMax *min_max,
3610 			  float cap)
3611 {
3612   Sta::sta()->setCapacitanceLimit(pin, min_max, cap);
3613 }
3614 
3615 void
set_cell_capacitance_limit(Cell * cell,const MinMax * min_max,float cap)3616 set_cell_capacitance_limit(Cell *cell,
3617 			   const MinMax *min_max,
3618 			   float cap)
3619 {
3620   Sta::sta()->setCapacitanceLimit(cell, min_max, cap);
3621 }
3622 
3623 void
set_latch_borrow_limit_pin(Pin * pin,float limit)3624 set_latch_borrow_limit_pin(Pin *pin,
3625 			   float limit)
3626 {
3627   Sta::sta()->setLatchBorrowLimit(pin, limit);
3628 }
3629 
3630 void
set_latch_borrow_limit_inst(Instance * inst,float limit)3631 set_latch_borrow_limit_inst(Instance *inst,
3632 			    float limit)
3633 {
3634   Sta::sta()->setLatchBorrowLimit(inst, limit);
3635 }
3636 
3637 void
set_latch_borrow_limit_clk(Clock * clk,float limit)3638 set_latch_borrow_limit_clk(Clock *clk, float limit)
3639 {
3640   Sta::sta()->setLatchBorrowLimit(clk, limit);
3641 }
3642 
3643 void
set_min_pulse_width_global(const RiseFallBoth * rf,float min_width)3644 set_min_pulse_width_global(const RiseFallBoth *rf,
3645 			   float min_width)
3646 {
3647   Sta::sta()->setMinPulseWidth(rf, min_width);
3648 }
3649 
3650 void
set_min_pulse_width_pin(Pin * pin,const RiseFallBoth * rf,float min_width)3651 set_min_pulse_width_pin(Pin *pin,
3652 			const RiseFallBoth *rf,
3653 			float min_width)
3654 {
3655   Sta::sta()->setMinPulseWidth(pin, rf, min_width);
3656 }
3657 
3658 void
set_min_pulse_width_clk(Clock * clk,const RiseFallBoth * rf,float min_width)3659 set_min_pulse_width_clk(Clock *clk,
3660 			const RiseFallBoth *rf,
3661 			float min_width)
3662 {
3663   Sta::sta()->setMinPulseWidth(clk, rf, min_width);
3664 }
3665 
3666 void
set_min_pulse_width_inst(Instance * inst,const RiseFallBoth * rf,float min_width)3667 set_min_pulse_width_inst(Instance *inst,
3668 			 const RiseFallBoth *rf,
3669 			 float min_width)
3670 {
3671   Sta::sta()->setMinPulseWidth(inst, rf, min_width);
3672 }
3673 
3674 void
set_max_area_cmd(float area)3675 set_max_area_cmd(float area)
3676 {
3677   Sta::sta()->setMaxArea(area);
3678 }
3679 
3680 void
set_port_fanout_limit(Port * port,const MinMax * min_max,float fanout)3681 set_port_fanout_limit(Port *port,
3682 		      const MinMax *min_max,
3683 		      float fanout)
3684 {
3685   Sta::sta()->setFanoutLimit(port, min_max, fanout);
3686 }
3687 
3688 void
set_cell_fanout_limit(Cell * cell,const MinMax * min_max,float fanout)3689 set_cell_fanout_limit(Cell *cell,
3690 		      const MinMax *min_max,
3691 		      float fanout)
3692 {
3693   Sta::sta()->setFanoutLimit(cell, min_max, fanout);
3694 }
3695 
3696 void
set_logic_value_cmd(Pin * pin,LogicValue value)3697 set_logic_value_cmd(Pin *pin,
3698 		    LogicValue value)
3699 {
3700   Sta::sta()->setLogicValue(pin, value);
3701 }
3702 
3703 void
set_case_analysis_cmd(Pin * pin,LogicValue value)3704 set_case_analysis_cmd(Pin *pin,
3705 		      LogicValue value)
3706 {
3707   Sta::sta()->setCaseAnalysis(pin, value);
3708 }
3709 
3710 void
unset_case_analysis_cmd(Pin * pin)3711 unset_case_analysis_cmd(Pin *pin)
3712 {
3713   Sta::sta()->removeCaseAnalysis(pin);
3714 }
3715 
3716 void
set_timing_derate_cmd(TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)3717 set_timing_derate_cmd(TimingDerateType type,
3718 		      PathClkOrData clk_data,
3719 		      const RiseFallBoth *rf,
3720 		      const EarlyLate *early_late,
3721 		      float derate)
3722 {
3723   Sta::sta()->setTimingDerate(type, clk_data, rf, early_late, derate);
3724 }
3725 
3726 void
set_timing_derate_net_cmd(const Net * net,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)3727 set_timing_derate_net_cmd(const Net *net,
3728 			  PathClkOrData clk_data,
3729 			  const RiseFallBoth *rf,
3730 			  const EarlyLate *early_late,
3731 			  float derate)
3732 {
3733   Sta::sta()->setTimingDerate(net, clk_data, rf, early_late, derate);
3734 }
3735 
3736 void
set_timing_derate_inst_cmd(const Instance * inst,TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)3737 set_timing_derate_inst_cmd(const Instance *inst,
3738 			   TimingDerateType type,
3739 			   PathClkOrData clk_data,
3740 			   const RiseFallBoth *rf,
3741 			   const EarlyLate *early_late,
3742 			   float derate)
3743 {
3744   Sta::sta()->setTimingDerate(inst, type, clk_data, rf, early_late, derate);
3745 }
3746 
3747 void
set_timing_derate_cell_cmd(const LibertyCell * cell,TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)3748 set_timing_derate_cell_cmd(const LibertyCell *cell,
3749 			   TimingDerateType type,
3750 			   PathClkOrData clk_data,
3751 			   const RiseFallBoth *rf,
3752 			   const EarlyLate *early_late,
3753 			   float derate)
3754 {
3755   Sta::sta()->setTimingDerate(cell, type, clk_data, rf, early_late, derate);
3756 }
3757 
3758 void
unset_timing_derate_cmd()3759 unset_timing_derate_cmd()
3760 {
3761   Sta::sta()->unsetTimingDerate();
3762 }
3763 
3764 ClockIterator *
clock_iterator()3765 clock_iterator()
3766 {
3767   return new ClockIterator(Sta::sta()->sdc());
3768 }
3769 
3770 Clock *
find_clock(const char * name)3771 find_clock(const char *name)
3772 {
3773   cmdLinkedNetwork();
3774   return Sta::sta()->sdc()->findClock(name);
3775 }
3776 
3777 bool
is_clock_src(const Pin * pin)3778 is_clock_src(const Pin *pin)
3779 {
3780   return Sta::sta()->isClockSrc(pin);
3781 }
3782 
3783 Clock *
default_arrival_clock()3784 default_arrival_clock()
3785 {
3786   return Sta::sta()->sdc()->defaultArrivalClock();
3787 }
3788 
3789 ClockSeq *
find_clocks_matching(const char * pattern,bool regexp,bool nocase)3790 find_clocks_matching(const char *pattern,
3791 		     bool regexp,
3792 		     bool nocase)
3793 {
3794   cmdLinkedNetwork();
3795   ClockSeq *clks = new ClockSeq;
3796   Sta *sta = Sta::sta();
3797   Sdc *sdc = sta->sdc();
3798   PatternMatch matcher(pattern, regexp, nocase, sta->tclInterp());
3799   sdc->findClocksMatching(&matcher, clks);
3800   return clks;
3801 }
3802 
3803 void
update_generated_clks()3804 update_generated_clks()
3805 {
3806   cmdLinkedNetwork();
3807   Sta::sta()->updateGeneratedClks();
3808 }
3809 
3810 bool
is_clock(Pin * pin)3811 is_clock(Pin *pin)
3812 {
3813   Sta *sta = Sta::sta();
3814   return sta->isClock(pin);
3815 }
3816 
3817 bool
is_ideal_clock(Pin * pin)3818 is_ideal_clock(Pin *pin)
3819 {
3820   Sta *sta = Sta::sta();
3821   return sta->isIdealClock(pin);
3822 }
3823 
3824 bool
is_clock_search(const Pin * pin)3825 is_clock_search(const Pin *pin)
3826 {
3827   Sta *sta = Sta::sta();
3828   Graph *graph = sta->graph();
3829   Search *search = sta->search();
3830   Vertex *vertex, *bidirect_drvr_vertex;
3831   graph->pinVertices(pin, vertex, bidirect_drvr_vertex);
3832   return search->isClock(vertex);
3833 }
3834 
3835 bool
is_genclk_src(const Pin * pin)3836 is_genclk_src(const Pin *pin)
3837 {
3838   Sta *sta = Sta::sta();
3839   Graph *graph = sta->graph();
3840   Search *search = sta->search();
3841   Vertex *vertex, *bidirect_drvr_vertex;
3842   graph->pinVertices(pin, vertex, bidirect_drvr_vertex);
3843   return search->isGenClkSrc(vertex);
3844 }
3845 
3846 // format_unit functions print with fixed digits and suffix.
3847 // Pass value arg as string to support NaNs.
3848 const char *
format_time(const char * value,int digits)3849 format_time(const char *value,
3850 	    int digits)
3851 {
3852   float value1 = strtof(value, nullptr);
3853   return Sta::sta()->units()->timeUnit()->asString(value1, digits);
3854 }
3855 
3856 const char *
format_capacitance(const char * value,int digits)3857 format_capacitance(const char *value,
3858 		   int digits)
3859 {
3860   float value1 = strtof(value, nullptr);
3861   return Sta::sta()->units()->capacitanceUnit()->asString(value1, digits);
3862 }
3863 
3864 const char *
format_resistance(const char * value,int digits)3865 format_resistance(const char *value,
3866 		  int digits)
3867 {
3868   float value1 = strtof(value, nullptr);
3869   return Sta::sta()->units()->resistanceUnit()->asString(value1, digits);
3870 }
3871 
3872 const char *
format_voltage(const char * value,int digits)3873 format_voltage(const char *value,
3874 	       int digits)
3875 {
3876   float value1 = strtof(value, nullptr);
3877   return Sta::sta()->units()->voltageUnit()->asString(value1, digits);
3878 }
3879 
3880 const char *
format_power(const char * value,int digits)3881 format_power(const char *value,
3882 	     int digits)
3883 {
3884   float value1 = strtof(value, nullptr);
3885   return Sta::sta()->units()->powerUnit()->asString(value1, digits);
3886 }
3887 
3888 const char *
format_distance(const char * value,int digits)3889 format_distance(const char *value,
3890 		int digits)
3891 {
3892   float value1 = strtof(value, nullptr);
3893   Unit *dist_unit = Sta::sta()->units()->distanceUnit();
3894   return dist_unit->asString(value1, digits);
3895 }
3896 
3897 const char *
format_area(const char * value,int digits)3898 format_area(const char *value,
3899 	    int digits)
3900 {
3901   float value1 = strtof(value, nullptr);
3902   Unit *dist_unit = Sta::sta()->units()->distanceUnit();
3903   return dist_unit->asString(value1 / dist_unit->scale(), digits);
3904 }
3905 
3906 ////////////////////////////////////////////////////////////////
3907 
3908 // Unit converstion from sta unit to user interface and visa versa.
3909 double
time_ui_sta(double value)3910 time_ui_sta(double value)
3911 {
3912   return value * Sta::sta()->units()->timeUnit()->scale();
3913 }
3914 
3915 double
time_sta_ui(double value)3916 time_sta_ui(double value)
3917 {
3918   return value / Sta::sta()->units()->timeUnit()->scale();
3919 }
3920 
3921 double
capacitance_ui_sta(double value)3922 capacitance_ui_sta(double value)
3923 {
3924   return value * Sta::sta()->units()->capacitanceUnit()->scale();
3925 }
3926 
3927 double
capacitance_sta_ui(double value)3928 capacitance_sta_ui(double value)
3929 {
3930   return value / Sta::sta()->units()->capacitanceUnit()->scale();
3931 }
3932 
3933 double
resistance_ui_sta(double value)3934 resistance_ui_sta(double value)
3935 {
3936   return value * Sta::sta()->units()->resistanceUnit()->scale();
3937 }
3938 
3939 double
resistance_sta_ui(double value)3940 resistance_sta_ui(double value)
3941 {
3942   return value / Sta::sta()->units()->resistanceUnit()->scale();
3943 }
3944 
3945 double
voltage_ui_sta(double value)3946 voltage_ui_sta(double value)
3947 {
3948   return value * Sta::sta()->units()->voltageUnit()->scale();
3949 }
3950 
3951 double
voltage_sta_ui(double value)3952 voltage_sta_ui(double value)
3953 {
3954   return value / Sta::sta()->units()->voltageUnit()->scale();
3955 }
3956 
3957 double
current_ui_sta(double value)3958 current_ui_sta(double value)
3959 {
3960   return value * Sta::sta()->units()->currentUnit()->scale();
3961 }
3962 
3963 double
current_sta_ui(double value)3964 current_sta_ui(double value)
3965 {
3966   return value / Sta::sta()->units()->currentUnit()->scale();
3967 }
3968 
3969 double
power_ui_sta(double value)3970 power_ui_sta(double value)
3971 {
3972   return value * Sta::sta()->units()->powerUnit()->scale();
3973 }
3974 
3975 double
power_sta_ui(double value)3976 power_sta_ui(double value)
3977 {
3978   return value / Sta::sta()->units()->powerUnit()->scale();
3979 }
3980 
3981 double
distance_ui_sta(double value)3982 distance_ui_sta(double value)
3983 {
3984   return value * Sta::sta()->units()->distanceUnit()->scale();
3985 }
3986 
3987 double
distance_sta_ui(double value)3988 distance_sta_ui(double value)
3989 {
3990   return value / Sta::sta()->units()->distanceUnit()->scale();
3991 }
3992 
3993 double
area_ui_sta(double value)3994 area_ui_sta(double value)
3995 {
3996   double scale = Sta::sta()->units()->distanceUnit()->scale();
3997   return value * scale * scale;
3998 }
3999 
4000 double
area_sta_ui(double value)4001 area_sta_ui(double value)
4002 {
4003   double scale = Sta::sta()->units()->distanceUnit()->scale();
4004   return value / (scale * scale);
4005 }
4006 
4007 ////////////////////////////////////////////////////////////////
4008 
4009 void
set_cmd_unit_scale(const char * unit_name,float scale)4010 set_cmd_unit_scale(const char *unit_name,
4011 		   float scale)
4012 {
4013   Unit *unit = Sta::sta()->units()->find(unit_name);
4014   if (unit)
4015     unit->setScale(scale);
4016 }
4017 
4018 void
set_cmd_unit_digits(const char * unit_name,int digits)4019 set_cmd_unit_digits(const char *unit_name,
4020 		    int digits)
4021 {
4022   Unit *unit = Sta::sta()->units()->find(unit_name);
4023   if (unit)
4024     unit->setDigits(digits);
4025 }
4026 
4027 void
set_cmd_unit_suffix(const char * unit_name,const char * suffix)4028 set_cmd_unit_suffix(const char *unit_name,
4029 		    const char *suffix)
4030 {
4031   Unit *unit = Sta::sta()->units()->find(unit_name);
4032   if (unit) {
4033     unit->setSuffix(suffix);
4034   }
4035 }
4036 
4037 const char *
unit_scale_abreviation(const char * unit_name)4038 unit_scale_abreviation(const char *unit_name)
4039 {
4040   Unit *unit = Sta::sta()->units()->find(unit_name);
4041   if (unit)
4042     return unit->scaleAbreviation();
4043   else
4044     return "";
4045 }
4046 
4047 const char *
unit_suffix(const char * unit_name)4048 unit_suffix(const char *unit_name)
4049 {
4050   Unit *unit = Sta::sta()->units()->find(unit_name);
4051   if (unit)
4052     return unit->suffix();
4053   else
4054     return "";
4055 }
4056 
4057 ////////////////////////////////////////////////////////////////
4058 
4059 VertexIterator *
vertex_iterator()4060 vertex_iterator()
4061 {
4062   return new VertexIterator(cmdGraph());
4063 }
4064 
4065 void
set_arc_delay(Edge * edge,TimingArc * arc,const Corner * corner,const MinMaxAll * min_max,float delay)4066 set_arc_delay(Edge *edge,
4067 	      TimingArc *arc,
4068 	      const Corner *corner,
4069 	      const MinMaxAll *min_max,
4070 	      float delay)
4071 {
4072   cmdGraph();
4073   Sta::sta()->setArcDelay(edge, arc, corner, min_max, delay);
4074 }
4075 
4076 void
set_annotated_slew(Vertex * vertex,const Corner * corner,const MinMaxAll * min_max,const RiseFallBoth * rf,float slew)4077 set_annotated_slew(Vertex *vertex,
4078 		   const Corner *corner,
4079 		   const MinMaxAll *min_max,
4080 		   const RiseFallBoth *rf,
4081 		   float slew)
4082 {
4083   cmdGraph();
4084   Sta::sta()->setAnnotatedSlew(vertex, corner, min_max, rf, slew);
4085 }
4086 
4087 // Remove all delay and slew annotations.
4088 void
remove_delay_slew_annotations()4089 remove_delay_slew_annotations()
4090 {
4091   cmdGraph();
4092   Sta::sta()->removeDelaySlewAnnotations();
4093 }
4094 
4095 CheckErrorSeq &
check_timing_cmd(bool no_input_delay,bool no_output_delay,bool reg_multiple_clks,bool reg_no_clks,bool unconstrained_endpoints,bool loops,bool generated_clks)4096 check_timing_cmd(bool no_input_delay,
4097 		 bool no_output_delay,
4098 		 bool reg_multiple_clks,
4099 		 bool reg_no_clks,
4100 		 bool unconstrained_endpoints,
4101 		 bool loops,
4102 		 bool generated_clks)
4103 {
4104   cmdLinkedNetwork();
4105   return Sta::sta()->checkTiming(no_input_delay, no_output_delay,
4106 				 reg_multiple_clks, reg_no_clks,
4107 				 unconstrained_endpoints,
4108 				 loops, generated_clks);
4109 }
4110 
4111 bool
crpr_enabled()4112 crpr_enabled()
4113 {
4114   return Sta::sta()->crprEnabled();
4115 }
4116 
4117 void
set_crpr_enabled(bool enabled)4118 set_crpr_enabled(bool enabled)
4119 {
4120   return Sta::sta()->setCrprEnabled(enabled);
4121 }
4122 
4123 const char *
crpr_mode()4124 crpr_mode()
4125 {
4126   switch (Sta::sta()->crprMode()) {
4127   case CrprMode::same_transition:
4128     return "same_transition";
4129   case CrprMode::same_pin:
4130     return "same_pin";
4131   default:
4132     return "";
4133   }
4134 }
4135 
4136 void
set_crpr_mode(const char * mode)4137 set_crpr_mode(const char *mode)
4138 {
4139   if (stringEq(mode, "same_pin"))
4140     Sta::sta()->setCrprMode(CrprMode::same_pin);
4141   else if (stringEq(mode, "same_transition"))
4142     Sta::sta()->setCrprMode(CrprMode::same_transition);
4143   else
4144     criticalError(272, "unknown common clk pessimism mode.");
4145 }
4146 
4147 bool
pocv_enabled()4148 pocv_enabled()
4149 {
4150   return Sta::sta()->pocvEnabled();
4151 }
4152 
4153 void
set_pocv_enabled(bool enabled)4154 set_pocv_enabled(bool enabled)
4155 {
4156 #if !SSTA
4157   if (enabled)
4158     Sta::sta()->report()->error(204, "POCV support requires compilation with SSTA=1.");
4159 #endif
4160   return Sta::sta()->setPocvEnabled(enabled);
4161 }
4162 
4163 float
pocv_sigma_factor()4164 pocv_sigma_factor()
4165 {
4166   return Sta::sta()->sigmaFactor();
4167 }
4168 
4169 void
set_pocv_sigma_factor(float factor)4170 set_pocv_sigma_factor(float factor)
4171 {
4172   Sta::sta()->setSigmaFactor(factor);
4173 }
4174 
4175 bool
propagate_gated_clock_enable()4176 propagate_gated_clock_enable()
4177 {
4178   return Sta::sta()->propagateGatedClockEnable();
4179 }
4180 
4181 void
set_propagate_gated_clock_enable(bool enable)4182 set_propagate_gated_clock_enable(bool enable)
4183 {
4184   Sta::sta()->setPropagateGatedClockEnable(enable);
4185 }
4186 
4187 bool
preset_clr_arcs_enabled()4188 preset_clr_arcs_enabled()
4189 {
4190   return Sta::sta()->presetClrArcsEnabled();
4191 }
4192 
4193 void
set_preset_clr_arcs_enabled(bool enable)4194 set_preset_clr_arcs_enabled(bool enable)
4195 {
4196   Sta::sta()->setPresetClrArcsEnabled(enable);
4197 }
4198 
4199 bool
cond_default_arcs_enabled()4200 cond_default_arcs_enabled()
4201 {
4202   return Sta::sta()->condDefaultArcsEnabled();
4203 }
4204 
4205 void
set_cond_default_arcs_enabled(bool enabled)4206 set_cond_default_arcs_enabled(bool enabled)
4207 {
4208   Sta::sta()->setCondDefaultArcsEnabled(enabled);
4209 }
4210 
4211 bool
bidirect_inst_paths_enabled()4212 bidirect_inst_paths_enabled()
4213 {
4214   return Sta::sta()->bidirectInstPathsEnabled();
4215 }
4216 
4217 void
set_bidirect_inst_paths_enabled(bool enabled)4218 set_bidirect_inst_paths_enabled(bool enabled)
4219 {
4220   Sta::sta()->setBidirectInstPathsEnabled(enabled);
4221 }
4222 
4223 bool
bidirect_net_paths_enabled()4224 bidirect_net_paths_enabled()
4225 {
4226   return Sta::sta()->bidirectNetPathsEnabled();
4227 }
4228 
4229 void
set_bidirect_net_paths_enabled(bool enabled)4230 set_bidirect_net_paths_enabled(bool enabled)
4231 {
4232   Sta::sta()->setBidirectNetPathsEnabled(enabled);
4233 }
4234 
4235 bool
recovery_removal_checks_enabled()4236 recovery_removal_checks_enabled()
4237 {
4238   return Sta::sta()->recoveryRemovalChecksEnabled();
4239 }
4240 
4241 void
set_recovery_removal_checks_enabled(bool enabled)4242 set_recovery_removal_checks_enabled(bool enabled)
4243 {
4244   Sta::sta()->setRecoveryRemovalChecksEnabled(enabled);
4245 }
4246 
4247 bool
gated_clk_checks_enabled()4248 gated_clk_checks_enabled()
4249 {
4250   return Sta::sta()->gatedClkChecksEnabled();
4251 }
4252 
4253 void
set_gated_clk_checks_enabled(bool enabled)4254 set_gated_clk_checks_enabled(bool enabled)
4255 {
4256   Sta::sta()->setGatedClkChecksEnabled(enabled);
4257 }
4258 
4259 bool
dynamic_loop_breaking()4260 dynamic_loop_breaking()
4261 {
4262   return Sta::sta()->dynamicLoopBreaking();
4263 }
4264 
4265 void
set_dynamic_loop_breaking(bool enable)4266 set_dynamic_loop_breaking(bool enable)
4267 {
4268   Sta::sta()->setDynamicLoopBreaking(enable);
4269 }
4270 
4271 bool
use_default_arrival_clock()4272 use_default_arrival_clock()
4273 {
4274   return Sta::sta()->useDefaultArrivalClock();
4275 }
4276 
4277 void
set_use_default_arrival_clock(bool enable)4278 set_use_default_arrival_clock(bool enable)
4279 {
4280   return Sta::sta()->setUseDefaultArrivalClock(enable);
4281 }
4282 
4283 bool
propagate_all_clocks()4284 propagate_all_clocks()
4285 {
4286   return Sta::sta()->propagateAllClocks();
4287 }
4288 
4289 void
set_propagate_all_clocks(bool prop)4290 set_propagate_all_clocks(bool prop)
4291 {
4292   Sta::sta()->setPropagateAllClocks(prop);
4293 }
4294 
4295 ////////////////////////////////////////////////////////////////
4296 
4297 PathEndSeq *
find_path_ends(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,bool unconstrained,Corner * corner,const MinMaxAll * delay_min_max,int group_count,int endpoint_count,bool unique_pins,float slack_min,float slack_max,bool sort_by_slack,PathGroupNameSet * groups,bool setup,bool hold,bool recovery,bool removal,bool clk_gating_setup,bool clk_gating_hold)4298 find_path_ends(ExceptionFrom *from,
4299 	       ExceptionThruSeq *thrus,
4300 	       ExceptionTo *to,
4301 	       bool unconstrained,
4302 	       Corner *corner,
4303 	       const MinMaxAll *delay_min_max,
4304 	       int group_count,
4305 	       int endpoint_count,
4306 	       bool unique_pins,
4307 	       float slack_min,
4308 	       float slack_max,
4309 	       bool sort_by_slack,
4310 	       PathGroupNameSet *groups,
4311 	       bool setup,
4312 	       bool hold,
4313 	       bool recovery,
4314 	       bool removal,
4315 	       bool clk_gating_setup,
4316 	       bool clk_gating_hold)
4317 {
4318   cmdLinkedNetwork();
4319   Sta *sta = Sta::sta();
4320   PathEndSeq *ends = sta->findPathEnds(from, thrus, to, unconstrained,
4321 				       corner, delay_min_max,
4322 				       group_count, endpoint_count, unique_pins,
4323 				       slack_min, slack_max,
4324 				       sort_by_slack,
4325 				       groups->size() ? groups : nullptr,
4326 				       setup, hold,
4327 				       recovery, removal,
4328 				       clk_gating_setup, clk_gating_hold);
4329   delete groups;
4330   return ends;
4331 }
4332 
4333 void
report_path_end_header()4334 report_path_end_header()
4335 {
4336   Sta::sta()->reportPathEndHeader();
4337 }
4338 
4339 void
report_path_end_footer()4340 report_path_end_footer()
4341 {
4342   Sta::sta()->reportPathEndFooter();
4343 }
4344 
4345 void
report_path_end(PathEnd * end)4346 report_path_end(PathEnd *end)
4347 {
4348   Sta::sta()->reportPathEnd(end);
4349 }
4350 
4351 void
report_path_end2(PathEnd * end,PathEnd * prev_end)4352 report_path_end2(PathEnd *end,
4353 		 PathEnd *prev_end)
4354 {
4355   Sta::sta()->reportPathEnd(end, prev_end);
4356 }
4357 
4358 void
set_report_path_format(ReportPathFormat format)4359 set_report_path_format(ReportPathFormat format)
4360 {
4361   Sta::sta()->setReportPathFormat(format);
4362 }
4363 
4364 void
set_report_path_field_order(StringSeq * field_names)4365 set_report_path_field_order(StringSeq *field_names)
4366 {
4367   Sta::sta()->setReportPathFieldOrder(field_names);
4368   delete field_names;
4369 }
4370 
4371 void
set_report_path_fields(bool report_input_pin,bool report_net,bool report_cap,bool report_slew)4372 set_report_path_fields(bool report_input_pin,
4373 		       bool report_net,
4374 		       bool report_cap,
4375 		       bool report_slew)
4376 {
4377   Sta::sta()->setReportPathFields(report_input_pin,
4378 				  report_net,
4379 				  report_cap,
4380 				  report_slew);
4381 }
4382 
4383 void
set_report_path_field_properties(const char * field_name,const char * title,int width,bool left_justify)4384 set_report_path_field_properties(const char *field_name,
4385 				 const char *title,
4386 				 int width,
4387 				 bool left_justify)
4388 {
4389   Sta *sta = Sta::sta();
4390   ReportField *field = sta->findReportPathField(field_name);
4391   if (field)
4392     field->setProperties(title, width, left_justify);
4393   else
4394     sta->report()->error(607, "unknown report path field %s", field_name);
4395 }
4396 
4397 void
set_report_path_field_width(const char * field_name,int width)4398 set_report_path_field_width(const char *field_name,
4399 			    int width)
4400 {
4401   Sta *sta = Sta::sta();
4402   ReportField *field = sta->findReportPathField(field_name);
4403   if (field)
4404     field->setWidth(width);
4405   else
4406     sta->report()->error(608, "unknown report path field %s", field_name);
4407 }
4408 
4409 void
set_report_path_digits(int digits)4410 set_report_path_digits(int digits)
4411 {
4412   Sta::sta()->setReportPathDigits(digits);
4413 }
4414 
4415 void
set_report_path_no_split(bool no_split)4416 set_report_path_no_split(bool no_split)
4417 {
4418   Sta::sta()->setReportPathNoSplit(no_split);
4419 }
4420 
4421 void
set_report_path_sigmas(bool report_sigmas)4422 set_report_path_sigmas(bool report_sigmas)
4423 {
4424   Sta::sta()->setReportPathSigmas(report_sigmas);
4425 }
4426 
4427 void
delete_path_ref(PathRef * path)4428 delete_path_ref(PathRef *path)
4429 {
4430   delete path;
4431 }
4432 
4433 void
remove_constraints()4434 remove_constraints()
4435 {
4436   Sta::sta()->removeConstraints();
4437 }
4438 
4439 void
report_path_cmd(PathRef * path)4440 report_path_cmd(PathRef *path)
4441 {
4442   Sta::sta()->reportPath(path);
4443 }
4444 
4445 void
report_clk_skew(ClockSet * clks,const Corner * corner,const SetupHold * setup_hold,int digits)4446 report_clk_skew(ClockSet *clks,
4447 		const Corner *corner,
4448 		const SetupHold *setup_hold,
4449 		int digits)
4450 {
4451   cmdLinkedNetwork();
4452   Sta::sta()->reportClkSkew(clks, corner, setup_hold, digits);
4453   delete clks;
4454 }
4455 
4456 float
worst_clk_skew_cmd(const SetupHold * setup_hold)4457 worst_clk_skew_cmd(const SetupHold *setup_hold)
4458 {
4459   cmdLinkedNetwork();
4460   return Sta::sta()->findWorstClkSkew(setup_hold);
4461 }
4462 
4463 TmpPinSet *
startpoints()4464 startpoints()
4465 {
4466   return findStartpoints();
4467 }
4468 
4469 TmpPinSet *
endpoints()4470 endpoints()
4471 {
4472   return findEndpoints();
4473 }
4474 
4475 TmpPinSet *
group_path_pins(const char * group_path_name)4476 group_path_pins(const char *group_path_name)
4477 {
4478   Sta *sta = Sta::sta();
4479   Sdc *sdc = sta->sdc();
4480   if (sdc->isGroupPathName(group_path_name))
4481     return sta->findGroupPathPins(group_path_name);
4482   else
4483     return nullptr;
4484 }
4485 
4486 ////////////////////////////////////////////////////////////////
4487 
4488 MinPulseWidthCheckSeq &
min_pulse_width_violations(const Corner * corner)4489 min_pulse_width_violations(const Corner *corner)
4490 {
4491   cmdLinkedNetwork();
4492   return Sta::sta()->minPulseWidthViolations(corner);
4493 }
4494 
4495 MinPulseWidthCheckSeq &
min_pulse_width_check_pins(PinSeq * pins,const Corner * corner)4496 min_pulse_width_check_pins(PinSeq *pins,
4497 			   const Corner *corner)
4498 {
4499   cmdLinkedNetwork();
4500   Sta *sta = Sta::sta();
4501   MinPulseWidthCheckSeq &checks = sta->minPulseWidthChecks(pins, corner);
4502   delete pins;
4503   return checks;
4504 }
4505 
4506 MinPulseWidthCheckSeq &
min_pulse_width_checks(const Corner * corner)4507 min_pulse_width_checks(const Corner *corner)
4508 {
4509   cmdLinkedNetwork();
4510   return Sta::sta()->minPulseWidthChecks(corner);
4511 }
4512 
4513 MinPulseWidthCheck *
min_pulse_width_check_slack(const Corner * corner)4514 min_pulse_width_check_slack(const Corner *corner)
4515 {
4516   cmdLinkedNetwork();
4517   return Sta::sta()->minPulseWidthSlack(corner);
4518 }
4519 
4520 void
report_mpw_checks(MinPulseWidthCheckSeq * checks,bool verbose)4521 report_mpw_checks(MinPulseWidthCheckSeq *checks,
4522 		  bool verbose)
4523 {
4524   Sta::sta()->reportMpwChecks(checks, verbose);
4525 }
4526 
4527 void
report_mpw_check(MinPulseWidthCheck * check,bool verbose)4528 report_mpw_check(MinPulseWidthCheck *check,
4529 		 bool verbose)
4530 {
4531   Sta::sta()->reportMpwCheck(check, verbose);
4532 }
4533 
4534 ////////////////////////////////////////////////////////////////
4535 
4536 MinPeriodCheckSeq &
min_period_violations()4537 min_period_violations()
4538 {
4539   cmdLinkedNetwork();
4540   return Sta::sta()->minPeriodViolations();
4541 }
4542 
4543 MinPeriodCheck *
min_period_check_slack()4544 min_period_check_slack()
4545 {
4546   cmdLinkedNetwork();
4547   return Sta::sta()->minPeriodSlack();
4548 }
4549 
4550 void
report_min_period_checks(MinPeriodCheckSeq * checks,bool verbose)4551 report_min_period_checks(MinPeriodCheckSeq *checks,
4552 			 bool verbose)
4553 {
4554   Sta::sta()->reportChecks(checks, verbose);
4555 }
4556 
4557 void
report_min_period_check(MinPeriodCheck * check,bool verbose)4558 report_min_period_check(MinPeriodCheck *check,
4559 			bool verbose)
4560 {
4561   Sta::sta()->reportCheck(check, verbose);
4562 }
4563 
4564 ////////////////////////////////////////////////////////////////
4565 
4566 MaxSkewCheckSeq &
max_skew_violations()4567 max_skew_violations()
4568 {
4569   cmdLinkedNetwork();
4570   return Sta::sta()->maxSkewViolations();
4571 }
4572 
4573 MaxSkewCheck *
max_skew_check_slack()4574 max_skew_check_slack()
4575 {
4576   cmdLinkedNetwork();
4577   return Sta::sta()->maxSkewSlack();
4578 }
4579 
4580 void
report_max_skew_checks(MaxSkewCheckSeq * checks,bool verbose)4581 report_max_skew_checks(MaxSkewCheckSeq *checks,
4582 		       bool verbose)
4583 {
4584   Sta::sta()->reportChecks(checks, verbose);
4585 }
4586 
4587 void
report_max_skew_check(MaxSkewCheck * check,bool verbose)4588 report_max_skew_check(MaxSkewCheck *check,
4589 		      bool verbose)
4590 {
4591   Sta::sta()->reportCheck(check, verbose);
4592 }
4593 
4594 ////////////////////////////////////////////////////////////////
4595 
4596 void
find_timing_cmd(bool full)4597 find_timing_cmd(bool full)
4598 {
4599   cmdLinkedNetwork();
4600   Sta::sta()->updateTiming(full);
4601 }
4602 
4603 void
find_requireds()4604 find_requireds()
4605 {
4606   cmdLinkedNetwork();
4607   Sta::sta()->findRequireds();
4608 }
4609 
4610 void
find_delays()4611 find_delays()
4612 {
4613   cmdLinkedNetwork();
4614   Sta::sta()->findDelays();
4615 }
4616 
4617 Slack
total_negative_slack_cmd(const MinMax * min_max)4618 total_negative_slack_cmd(const MinMax *min_max)
4619 {
4620   cmdLinkedNetwork();
4621   Sta *sta = Sta::sta();
4622   return sta->totalNegativeSlack(min_max);
4623 }
4624 
4625 Slack
total_negative_slack_corner_cmd(const Corner * corner,const MinMax * min_max)4626 total_negative_slack_corner_cmd(const Corner *corner,
4627 				const MinMax *min_max)
4628 {
4629   cmdLinkedNetwork();
4630   Sta *sta = Sta::sta();
4631   return sta->totalNegativeSlack(corner, min_max);
4632 }
4633 
4634 Slack
worst_slack_cmd(const MinMax * min_max)4635 worst_slack_cmd(const MinMax *min_max)
4636 {
4637   cmdLinkedNetwork();
4638   Sta *sta = Sta::sta();
4639   Slack worst_slack;
4640   Vertex *worst_vertex;
4641   sta->worstSlack(min_max, worst_slack, worst_vertex);
4642   return worst_slack;
4643 }
4644 
4645 Vertex *
worst_slack_vertex(const MinMax * min_max)4646 worst_slack_vertex(const MinMax *min_max)
4647 {
4648   cmdLinkedNetwork();
4649   Sta *sta = Sta::sta();
4650   Slack worst_slack;
4651   Vertex *worst_vertex;
4652   sta->worstSlack(min_max, worst_slack, worst_vertex);
4653   return worst_vertex;;
4654 }
4655 
4656 Slack
worst_slack_corner(const Corner * corner,const MinMax * min_max)4657 worst_slack_corner(const Corner *corner,
4658 		   const MinMax *min_max)
4659 {
4660   cmdLinkedNetwork();
4661   Sta *sta = Sta::sta();
4662   Slack worst_slack;
4663   Vertex *worst_vertex;
4664   sta->worstSlack(corner, min_max, worst_slack, worst_vertex);
4665   return worst_slack;
4666 }
4667 
4668 PathRef *
vertex_worst_arrival_path(Vertex * vertex,const MinMax * min_max)4669 vertex_worst_arrival_path(Vertex *vertex,
4670 			  const MinMax *min_max)
4671 {
4672   Sta *sta = Sta::sta();
4673   PathRef path = sta->vertexWorstArrivalPath(vertex, min_max);
4674   if (!path.isNull())
4675     return new PathRef(path);
4676   else
4677     return nullptr;
4678 }
4679 
4680 PathRef *
vertex_worst_arrival_path_rf(Vertex * vertex,const RiseFall * rf,MinMax * min_max)4681 vertex_worst_arrival_path_rf(Vertex *vertex,
4682 			     const RiseFall *rf,
4683 			     MinMax *min_max)
4684 {
4685   Sta *sta = Sta::sta();
4686   PathRef path = sta->vertexWorstArrivalPath(vertex, rf, min_max);
4687   if (!path.isNull())
4688     return new PathRef(path);
4689   else
4690     return nullptr;
4691 }
4692 
4693 PathRef *
vertex_worst_slack_path(Vertex * vertex,const MinMax * min_max)4694 vertex_worst_slack_path(Vertex *vertex,
4695 			const MinMax *min_max)
4696 {
4697   Sta *sta = Sta::sta();
4698   PathRef path = sta->vertexWorstSlackPath(vertex, min_max);
4699   if (!path.isNull())
4700     return new PathRef(path);
4701   else
4702     return nullptr;
4703 }
4704 
4705 TmpString *
report_delay_calc_cmd(Edge * edge,TimingArc * arc,const Corner * corner,const MinMax * min_max,int digits)4706 report_delay_calc_cmd(Edge *edge,
4707 		      TimingArc *arc,
4708 		      const Corner *corner,
4709 		      const MinMax *min_max,
4710 		      int digits)
4711 {
4712   cmdLinkedNetwork();
4713   return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits);
4714 }
4715 
4716 ////////////////////////////////////////////////////////////////
4717 
4718 PinSeq *
check_slew_limits(Net * net,bool violators,const Corner * corner,const MinMax * min_max)4719 check_slew_limits(Net *net,
4720                   bool violators,
4721                   const Corner *corner,
4722                   const MinMax *min_max)
4723 {
4724   cmdLinkedNetwork();
4725   return Sta::sta()->checkSlewLimits(net, violators, corner, min_max);
4726 }
4727 
4728 size_t
max_slew_violation_count()4729 max_slew_violation_count()
4730 {
4731   cmdLinkedNetwork();
4732   return Sta::sta()->checkSlewLimits(nullptr, true, nullptr, MinMax::max())->size();
4733 }
4734 
4735 void
report_slew_limit_short_header()4736 report_slew_limit_short_header()
4737 {
4738   Sta::sta()->reportSlewLimitShortHeader();
4739 }
4740 
4741 void
report_slew_limit_short(Pin * pin,const Corner * corner,const MinMax * min_max)4742 report_slew_limit_short(Pin *pin,
4743 			const Corner *corner,
4744 			const MinMax *min_max)
4745 {
4746   Sta::sta()->reportSlewLimitShort(pin, corner, min_max);
4747 }
4748 
4749 void
report_slew_limit_verbose(Pin * pin,const Corner * corner,const MinMax * min_max)4750 report_slew_limit_verbose(Pin *pin,
4751 			  const Corner *corner,
4752 			  const MinMax *min_max)
4753 {
4754   Sta::sta()->reportSlewLimitVerbose(pin, corner, min_max);
4755 }
4756 
4757 ////////////////////////////////////////////////////////////////
4758 
4759 PinSeq *
check_fanout_limits(Net * net,bool violators,const MinMax * min_max)4760 check_fanout_limits(Net *net,
4761                     bool violators,
4762                     const MinMax *min_max)
4763 {
4764   cmdLinkedNetwork();
4765   return Sta::sta()->checkFanoutLimits(net, violators, min_max);
4766 }
4767 
4768 size_t
max_fanout_violation_count()4769 max_fanout_violation_count()
4770 {
4771   cmdLinkedNetwork();
4772   return Sta::sta()->checkFanoutLimits(nullptr, true, MinMax::max())->size();
4773 }
4774 
4775 void
report_fanout_limit_short_header()4776 report_fanout_limit_short_header()
4777 {
4778   Sta::sta()->reportFanoutLimitShortHeader();
4779 }
4780 
4781 void
report_fanout_limit_short(Pin * pin,const MinMax * min_max)4782 report_fanout_limit_short(Pin *pin,
4783 			  const MinMax *min_max)
4784 {
4785   Sta::sta()->reportFanoutLimitShort(pin, min_max);
4786 }
4787 
4788 void
report_fanout_limit_verbose(Pin * pin,const MinMax * min_max)4789 report_fanout_limit_verbose(Pin *pin,
4790 			    const MinMax *min_max)
4791 {
4792   Sta::sta()->reportFanoutLimitVerbose(pin, min_max);
4793 }
4794 
4795 ////////////////////////////////////////////////////////////////
4796 
4797 PinSeq *
check_capacitance_limits(Net * net,bool violators,const Corner * corner,const MinMax * min_max)4798 check_capacitance_limits(Net *net,
4799                          bool violators,
4800                          const Corner *corner,
4801                          const MinMax *min_max)
4802 {
4803   cmdLinkedNetwork();
4804   return Sta::sta()->checkCapacitanceLimits(net, violators, corner, min_max);
4805 }
4806 
4807 size_t
max_capacitance_violation_count()4808 max_capacitance_violation_count()
4809 {
4810   cmdLinkedNetwork();
4811   return Sta::sta()->checkCapacitanceLimits(nullptr, true,nullptr,MinMax::max())->size();
4812 }
4813 
4814 void
report_capacitance_limit_short_header()4815 report_capacitance_limit_short_header()
4816 {
4817   Sta::sta()->reportCapacitanceLimitShortHeader();
4818 }
4819 
4820 void
report_capacitance_limit_short(Pin * pin,const Corner * corner,const MinMax * min_max)4821 report_capacitance_limit_short(Pin *pin,
4822 			       const Corner *corner,
4823 			       const MinMax *min_max)
4824 {
4825   Sta::sta()->reportCapacitanceLimitShort(pin, corner, min_max);
4826 }
4827 
4828 void
report_capacitance_limit_verbose(Pin * pin,const Corner * corner,const MinMax * min_max)4829 report_capacitance_limit_verbose(Pin *pin,
4830 				 const Corner *corner,
4831 				 const MinMax *min_max)
4832 {
4833   Sta::sta()->reportCapacitanceLimitVerbose(pin, corner, min_max);
4834 }
4835 
4836 ////////////////////////////////////////////////////////////////
4837 
4838 TmpFloatSeq *
design_power(const Corner * corner)4839 design_power(const Corner *corner)
4840 {
4841   cmdLinkedNetwork();
4842   PowerResult total, sequential, combinational, macro, pad;
4843   Sta::sta()->power(corner, total, sequential, combinational, macro, pad);
4844   FloatSeq *floats = new FloatSeq;
4845   pushPowerResultFloats(total, floats);
4846   pushPowerResultFloats(sequential, floats);
4847   pushPowerResultFloats(combinational, floats);
4848   pushPowerResultFloats(macro, floats);
4849   pushPowerResultFloats(pad, floats);
4850   return floats;
4851 }
4852 
4853 TmpFloatSeq *
instance_power(Instance * inst,const Corner * corner)4854 instance_power(Instance *inst,
4855 	       const Corner *corner)
4856 {
4857   cmdLinkedNetwork();
4858   PowerResult power;
4859   Sta::sta()->power(inst, corner, power);
4860   FloatSeq *floats = new FloatSeq;
4861   floats->push_back(power.internal());
4862   floats->push_back(power.switching());
4863   floats->push_back(power.leakage());
4864   floats->push_back(power.total());
4865   return floats;
4866 }
4867 
4868 void
set_power_global_activity(float activity,float duty)4869 set_power_global_activity(float activity,
4870 			  float duty)
4871 {
4872   Sta::sta()->power()->setGlobalActivity(activity, duty);
4873 }
4874 
4875 void
set_power_input_activity(float activity,float duty)4876 set_power_input_activity(float activity,
4877 			 float duty)
4878 {
4879   return Sta::sta()->power()->setInputActivity(activity, duty);
4880 }
4881 
4882 void
set_power_input_port_activity(const Port * input_port,float activity,float duty)4883 set_power_input_port_activity(const Port *input_port,
4884 			      float activity,
4885 			      float duty)
4886 {
4887   return Sta::sta()->power()->setInputPortActivity(input_port, activity, duty);
4888 }
4889 
4890 void
set_power_pin_activity(const Pin * pin,float activity,float duty)4891 set_power_pin_activity(const Pin *pin,
4892 		       float activity,
4893 		       float duty)
4894 {
4895   return Sta::sta()->power()->setUserActivity(pin, activity, duty,
4896 					      PwrActivityOrigin::user);
4897 }
4898 
4899 ////////////////////////////////////////////////////////////////
4900 
4901 EdgeSeq *
disabled_edges_sorted()4902 disabled_edges_sorted()
4903 {
4904   cmdLinkedNetwork();
4905   return Sta::sta()->disabledEdgesSorted();
4906 }
4907 
4908 void
write_sdc_cmd(const char * filename,bool leaf,bool compatible,bool no_timestamp,int digits)4909 write_sdc_cmd(const char *filename,
4910 	      bool leaf,
4911 	      bool compatible,
4912 	      bool no_timestamp,
4913 	      int digits)
4914 {
4915   cmdLinkedNetwork();
4916   Sta::sta()->writeSdc(filename, leaf, compatible, no_timestamp, digits);
4917 }
4918 
4919 void
write_path_spice_cmd(PathRef * path,const char * spice_filename,const char * subckt_filename,const char * lib_subckt_filename,const char * model_filename,const char * power_name,const char * gnd_name)4920 write_path_spice_cmd(PathRef *path,
4921 		     const char *spice_filename,
4922 		     const char *subckt_filename,
4923 		     const char *lib_subckt_filename,
4924 		     const char *model_filename,
4925 		     const char *power_name,
4926 		     const char *gnd_name)
4927 {
4928   Sta *sta = Sta::sta();
4929   writePathSpice(path, spice_filename, subckt_filename,
4930 		 lib_subckt_filename, model_filename,
4931 		 power_name, gnd_name, sta);
4932 }
4933 
4934 bool
liberty_supply_exists(const char * supply_name)4935 liberty_supply_exists(const char *supply_name)
4936 {
4937   auto network = Sta::sta()->network();
4938   auto lib = network->defaultLibertyLibrary();
4939   return lib && lib->supplyExists(supply_name);
4940 }
4941 
4942 float
unit_scale(const char * unit_name)4943 unit_scale(const char *unit_name)
4944 {
4945   Unit *unit = Sta::sta()->units()->find(unit_name);
4946   if (unit)
4947     return unit->scale();
4948   else
4949     return 1.0F;
4950 }
4951 
4952 bool
fuzzy_equal(float value1,float value2)4953 fuzzy_equal(float value1,
4954 	    float value2)
4955 {
4956   return fuzzyEqual(value1, value2);
4957 }
4958 
4959 char
pin_sim_logic_value(const Pin * pin)4960 pin_sim_logic_value(const Pin *pin)
4961 {
4962   return logicValueString(Sta::sta()->simLogicValue(pin));
4963 }
4964 
4965 char
pin_case_logic_value(const Pin * pin)4966 pin_case_logic_value(const Pin *pin)
4967 {
4968   Sta *sta = Sta::sta();
4969   Sdc *sdc = sta->sdc();
4970   LogicValue value = LogicValue::unknown;
4971   bool exists;
4972   sdc->caseLogicValue(pin, value, exists);
4973   return logicValueString(value);
4974 }
4975 
4976 char
pin_logic_value(const Pin * pin)4977 pin_logic_value(const Pin *pin)
4978 {
4979   Sta *sta = Sta::sta();
4980   Sdc *sdc = sta->sdc();
4981   LogicValue value = LogicValue::unknown;
4982   bool exists;
4983   sdc->logicValue(pin, value, exists);
4984   return logicValueString(value);
4985 }
4986 
4987 SlowDrvrIterator *
slow_driver_iterator()4988 slow_driver_iterator()
4989 {
4990   return Sta::sta()->slowDrvrIterator();
4991 }
4992 
4993 bool
timing_arc_disabled(Edge * edge,TimingArc * arc)4994 timing_arc_disabled(Edge *edge,
4995 		    TimingArc *arc)
4996 {
4997   Graph *graph = Sta::sta()->graph();
4998   return !searchThru(edge, arc, graph);
4999 }
5000 
5001 ClockGroups *
make_clock_groups(const char * name,bool logically_exclusive,bool physically_exclusive,bool asynchronous,bool allow_paths,const char * comment)5002 make_clock_groups(const char *name,
5003 		  bool logically_exclusive,
5004 		  bool physically_exclusive,
5005 		  bool asynchronous,
5006 		  bool allow_paths,
5007 		  const char *comment)
5008 {
5009   return Sta::sta()->makeClockGroups(name, logically_exclusive,
5010 				     physically_exclusive, asynchronous,
5011 				     allow_paths, comment);
5012 }
5013 
5014 void
clock_groups_make_group(ClockGroups * clk_groups,ClockSet * clks)5015 clock_groups_make_group(ClockGroups *clk_groups,
5016 			ClockSet *clks)
5017 {
5018   Sta::sta()->makeClockGroup(clk_groups, clks);
5019 }
5020 
5021 void
unset_clock_groups_logically_exclusive(const char * name)5022 unset_clock_groups_logically_exclusive(const char *name)
5023 {
5024   Sta::sta()->removeClockGroupsLogicallyExclusive(name);
5025 }
5026 
5027 void
unset_clock_groups_physically_exclusive(const char * name)5028 unset_clock_groups_physically_exclusive(const char *name)
5029 {
5030   Sta::sta()->removeClockGroupsPhysicallyExclusive(name);
5031 }
5032 
5033 void
unset_clock_groups_asynchronous(const char * name)5034 unset_clock_groups_asynchronous(const char *name)
5035 {
5036   Sta::sta()->removeClockGroupsAsynchronous(name);
5037 }
5038 
5039 // Debugging function.
5040 bool
same_clk_group(Clock * clk1,Clock * clk2)5041 same_clk_group(Clock *clk1,
5042 	       Clock *clk2)
5043 {
5044   Sta *sta = Sta::sta();
5045   Sdc *sdc = sta->sdc();
5046   return sdc->sameClockGroupExplicit(clk1, clk2);
5047 }
5048 
5049 void
set_clock_sense_cmd(PinSet * pins,ClockSet * clks,bool positive,bool negative,bool stop_propagation)5050 set_clock_sense_cmd(PinSet *pins,
5051 		    ClockSet *clks,
5052 		    bool positive,
5053 		    bool negative,
5054 		    bool stop_propagation)
5055 {
5056   ClockSense sense;
5057   if (positive)
5058     sense = ClockSense::positive;
5059   else if (negative)
5060     sense = ClockSense::negative;
5061   else if (stop_propagation)
5062     sense = ClockSense::stop;
5063   else
5064     criticalError(273, "unknown clock sense");
5065   Sta::sta()->setClockSense(pins, clks, sense);
5066 }
5067 
5068 bool
timing_role_is_check(TimingRole * role)5069 timing_role_is_check(TimingRole *role)
5070 {
5071   return role->isTimingCheck();
5072 }
5073 
5074 ////////////////////////////////////////////////////////////////
5075 
5076 TmpPinSet *
find_fanin_pins(PinSeq * to,bool flat,bool startpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)5077 find_fanin_pins(PinSeq *to,
5078 		bool flat,
5079 		bool startpoints_only,
5080 		int inst_levels,
5081 		int pin_levels,
5082 		bool thru_disabled,
5083 		bool thru_constants)
5084 {
5085   cmdLinkedNetwork();
5086   Sta *sta = Sta::sta();
5087   PinSet *fanin = sta->findFaninPins(to, flat, startpoints_only,
5088 				     inst_levels, pin_levels,
5089 				     thru_disabled, thru_constants);
5090   delete to;
5091   return fanin;
5092 }
5093 
5094 TmpInstanceSet *
find_fanin_insts(PinSeq * to,bool flat,bool startpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)5095 find_fanin_insts(PinSeq *to,
5096 		 bool flat,
5097 		 bool startpoints_only,
5098 		 int inst_levels,
5099 		 int pin_levels,
5100 		 bool thru_disabled,
5101 		 bool thru_constants)
5102 {
5103   cmdLinkedNetwork();
5104   Sta *sta = Sta::sta();
5105   InstanceSet *fanin = sta->findFaninInstances(to, flat, startpoints_only,
5106 					       inst_levels, pin_levels,
5107 					       thru_disabled, thru_constants);
5108   delete to;
5109   return fanin;
5110 }
5111 
5112 TmpPinSet *
find_fanout_pins(PinSeq * from,bool flat,bool endpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)5113 find_fanout_pins(PinSeq *from,
5114 		 bool flat,
5115 		 bool endpoints_only,
5116 		 int inst_levels,
5117 		 int pin_levels,
5118 		 bool thru_disabled,
5119 		 bool thru_constants)
5120 {
5121   cmdLinkedNetwork();
5122   Sta *sta = Sta::sta();
5123   PinSet *fanout = sta->findFanoutPins(from, flat, endpoints_only,
5124 				       inst_levels, pin_levels,
5125 				       thru_disabled, thru_constants);
5126   delete from;
5127   return fanout;
5128 }
5129 
5130 TmpInstanceSet *
find_fanout_insts(PinSeq * from,bool flat,bool endpoints_only,int inst_levels,int pin_levels,bool thru_disabled,bool thru_constants)5131 find_fanout_insts(PinSeq *from,
5132 		  bool flat,
5133 		  bool endpoints_only,
5134 		  int inst_levels,
5135 		  int pin_levels,
5136 		  bool thru_disabled,
5137 		  bool thru_constants)
5138 {
5139   cmdLinkedNetwork();
5140   Sta *sta = Sta::sta();
5141   InstanceSet *fanout = sta->findFanoutInstances(from, flat, endpoints_only,
5142 						 inst_levels, pin_levels,
5143 						 thru_disabled, thru_constants);
5144   delete from;
5145   return fanout;
5146 }
5147 
5148 TmpPinSet *
net_load_pins(Net * net)5149 net_load_pins(Net *net)
5150 {
5151   Network *network = cmdLinkedNetwork();
5152   PinSet *pins = new PinSet;
5153   NetConnectedPinIterator *pin_iter = network->connectedPinIterator(net);
5154   while (pin_iter->hasNext()) {
5155     Pin *pin = pin_iter->next();
5156     if (network->isLoad(pin))
5157       pins->insert(pin);
5158   }
5159   delete pin_iter;
5160   return pins;
5161 }
5162 
5163 TmpPinSet *
net_driver_pins(Net * net)5164 net_driver_pins(Net *net)
5165 {
5166   Network *network = cmdLinkedNetwork();
5167   PinSet *pins = new PinSet;
5168   NetConnectedPinIterator *pin_iter = network->connectedPinIterator(net);
5169   while (pin_iter->hasNext()) {
5170     Pin *pin = pin_iter->next();
5171     if (network->isDriver(pin))
5172       pins->insert(pin);
5173   }
5174   delete pin_iter;
5175   return pins;
5176 }
5177 
5178 ////////////////////////////////////////////////////////////////
5179 
5180 void
report_loops()5181 report_loops()
5182 {
5183   Sta *sta = Sta::sta();
5184   Network *network = cmdLinkedNetwork();
5185   Graph *graph = cmdGraph();
5186   Report *report = sta->report();
5187   GraphLoopSeq *loops = sta->graphLoops();
5188   GraphLoopSeq::Iterator loop_iter(loops);
5189   while (loop_iter.hasNext()) {
5190     GraphLoop *loop = loop_iter.next();
5191     loop->report(report, network, graph);
5192     report->reportLineString("");
5193   }
5194 }
5195 
5196 // Includes top instance.
5197 int
network_instance_count()5198 network_instance_count()
5199 {
5200   Network *network = cmdNetwork();
5201   return network->instanceCount();
5202 }
5203 
5204 int
network_pin_count()5205 network_pin_count()
5206 {
5207   Network *network = cmdNetwork();
5208   return network->pinCount();
5209 }
5210 
5211 int
network_net_count()5212 network_net_count()
5213 {
5214   Network *network = cmdNetwork();
5215   return network->netCount();
5216 }
5217 
5218 int
network_leaf_instance_count()5219 network_leaf_instance_count()
5220 {
5221   Network *network = cmdNetwork();
5222   return network->leafInstanceCount();
5223 }
5224 
5225 int
network_leaf_pin_count()5226 network_leaf_pin_count()
5227 {
5228   Network *network = cmdNetwork();
5229   return network->leafPinCount();
5230 }
5231 
5232 int
graph_vertex_count()5233 graph_vertex_count()
5234 {
5235   return cmdGraph()->vertexCount();
5236 }
5237 
5238 int
graph_edge_count()5239 graph_edge_count()
5240 {
5241   return cmdGraph()->edgeCount();
5242 }
5243 
5244 int
graph_arc_count()5245 graph_arc_count()
5246 {
5247   return cmdGraph()->arcCount();
5248 }
5249 
5250 int
tag_group_count()5251 tag_group_count()
5252 {
5253   return Sta::sta()->tagGroupCount();
5254 }
5255 
5256 void
report_tag_groups()5257 report_tag_groups()
5258 {
5259   Sta::sta()->search()->reportTagGroups();
5260 }
5261 
5262 void
report_tag_arrivals_cmd(Vertex * vertex)5263 report_tag_arrivals_cmd(Vertex *vertex)
5264 {
5265   Sta::sta()->search()->reportArrivals(vertex);
5266 }
5267 
5268 void
report_arrival_count_histogram()5269 report_arrival_count_histogram()
5270 {
5271   Sta::sta()->search()->reportArrivalCountHistogram();
5272 }
5273 
5274 int
tag_count()5275 tag_count()
5276 {
5277   return Sta::sta()->tagCount();
5278 }
5279 
5280 void
report_tags()5281 report_tags()
5282 {
5283   Sta::sta()->search()->reportTags();
5284 }
5285 
5286 void
report_clk_infos()5287 report_clk_infos()
5288 {
5289   Sta::sta()->search()->reportClkInfos();
5290 }
5291 
5292 int
clk_info_count()5293 clk_info_count()
5294 {
5295   return Sta::sta()->clkInfoCount();
5296 }
5297 
5298 int
arrival_count()5299 arrival_count()
5300 {
5301   return Sta::sta()->arrivalCount();
5302 }
5303 
5304 void
delete_all_memory()5305 delete_all_memory()
5306 {
5307   deleteAllMemory();
5308 }
5309 
5310 Tcl_Interp *
tcl_interp()5311 tcl_interp()
5312 {
5313   return Sta::sta()->tclInterp();
5314 }
5315 
5316 // Initialize sta after delete_all_memory.
5317 void
init_sta()5318 init_sta()
5319 {
5320   initSta();
5321 }
5322 
5323 void
clear_sta()5324 clear_sta()
5325 {
5326   Sta::sta()->clear();
5327 }
5328 
5329 void
make_sta(Tcl_Interp * interp)5330 make_sta(Tcl_Interp *interp)
5331 {
5332   Sta *sta = new Sta;
5333   Sta::setSta(sta);
5334   sta->makeComponents();
5335   sta->setTclInterp(interp);
5336 }
5337 
5338 void
clear_network()5339 clear_network()
5340 {
5341   Sta *sta = Sta::sta();
5342   sta->network()->clear();
5343 }
5344 
5345 // Elapsed run time (in seconds).
5346 double
elapsed_run_time()5347 elapsed_run_time()
5348 {
5349   return elapsedRunTime();
5350 }
5351 
5352 // User run time (in seconds).
5353 double
user_run_time()5354 user_run_time()
5355 {
5356   return userRunTime();
5357 }
5358 
5359 // User run time (in seconds).
5360 unsigned long
cputime()5361 cputime()
5362 {
5363   return static_cast<unsigned long>(userRunTime() + .5);
5364 }
5365 
5366 // Peak memory usage in bytes.
5367 unsigned long
memory_usage()5368 memory_usage()
5369 {
5370   return memoryUsage();
5371 }
5372 
5373 int
processor_count()5374 processor_count()
5375 {
5376   return processorCount();
5377 }
5378 
5379 int
thread_count()5380 thread_count()
5381 {
5382   return Sta::sta()->threadCount();
5383 }
5384 
5385 void
set_thread_count(int count)5386 set_thread_count(int count)
5387 {
5388   Sta::sta()->setThreadCount(count);
5389 }
5390 
5391 void
arrivals_invalid()5392 arrivals_invalid()
5393 {
5394   Sta *sta = Sta::sta();
5395   sta->arrivalsInvalid();
5396 }
5397 
5398 void
delays_invalid()5399 delays_invalid()
5400 {
5401   Sta *sta = Sta::sta();
5402   sta->delaysInvalid();
5403 }
5404 
5405 const char *
pin_location(const Pin * pin)5406 pin_location(const Pin *pin)
5407 {
5408   Network *network = cmdNetwork();
5409   double x, y;
5410   bool exists;
5411   network->location(pin, x, y, exists);
5412   // return x/y as tcl list
5413   if (exists)
5414     return sta::stringPrintTmp("%f %f", x, y);
5415   else
5416     return "";
5417 }
5418 
5419 const char *
port_location(const Port * port)5420 port_location(const Port *port)
5421 {
5422   Network *network = cmdNetwork();
5423   const Pin *pin = network->findPin(network->topInstance(), port);
5424   return pin_location(pin);
5425 }
5426 
5427 int
endpoint_count()5428 endpoint_count()
5429 {
5430   return Sta::sta()->endpointCount();
5431 }
5432 
5433 %} // inline
5434 
5435 ////////////////////////////////////////////////////////////////
5436 //
5437 // Object Methods
5438 //
5439 ////////////////////////////////////////////////////////////////
5440 
5441 %extend Library {
name()5442 const char *name()
5443 {
5444   return cmdNetwork()->name(self);
5445 }
5446 
5447 Cell *
find_cell(const char * name)5448 find_cell(const char *name)
5449 {
5450   return cmdNetwork()->findCell(self, name);
5451 }
5452 
5453 TmpCellSeq *
find_cells_matching(const char * pattern,bool regexp,bool nocase)5454 find_cells_matching(const char *pattern,
5455 		    bool regexp,
5456 		    bool nocase)
5457 {
5458   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
5459   TmpCellSeq *cells = new TmpCellSeq;
5460   cmdNetwork()->findCellsMatching(self, &matcher, cells);
5461   return cells;
5462 }
5463 
5464 } // Library methods
5465 
5466 %extend LibertyLibrary {
name()5467 const char *name() { return self->name(); }
5468 
5469 LibertyCell *
find_liberty_cell(const char * name)5470 find_liberty_cell(const char *name)
5471 {
5472   return self->findLibertyCell(name);
5473 }
5474 
5475 TmpLibertyCellSeq *
find_liberty_cells_matching(const char * pattern,bool regexp,bool nocase)5476 find_liberty_cells_matching(const char *pattern,
5477 			    bool regexp,
5478 			    bool nocase)
5479 {
5480   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
5481   // TmpLibertyCellSeq deletes temporary CellSeq after conversion to tcl list.
5482   TmpLibertyCellSeq *cells = new TmpLibertyCellSeq;
5483   self->findLibertyCellsMatching(&matcher, cells);
5484   return cells;
5485 }
5486 
5487 Wireload *
find_wireload(const char * model_name)5488 find_wireload(const char *model_name)
5489 {
5490   return self->findWireload(model_name);
5491 }
5492 
5493 WireloadSelection *
find_wireload_selection(const char * selection_name)5494 find_wireload_selection(const char *selection_name)
5495 {
5496   return self->findWireloadSelection(selection_name);
5497 }
5498 
5499 OperatingConditions *
find_operating_conditions(const char * op_cond_name)5500 find_operating_conditions(const char *op_cond_name)
5501 {
5502   return self->findOperatingConditions(op_cond_name);
5503 }
5504 
5505 OperatingConditions *
default_operating_conditions()5506 default_operating_conditions()
5507 {
5508   return self->defaultOperatingConditions();
5509 }
5510 
5511 } // LibertyLibrary methods
5512 
5513 %extend LibraryIterator {
has_next()5514 bool has_next() { return self->hasNext(); }
next()5515 Library *next() { return self->next(); }
finish()5516 void finish() { delete self; }
5517 } // LibraryIterator methods
5518 
5519 %extend LibertyLibraryIterator {
has_next()5520 bool has_next() { return self->hasNext(); }
next()5521 LibertyLibrary *next() { return self->next(); }
finish()5522 void finish() { delete self; }
5523 } // LibertyLibraryIterator methods
5524 
5525 %extend Cell {
library()5526 Library *library() { return cmdNetwork()->library(self); }
liberty_cell()5527 LibertyCell *liberty_cell() { return cmdNetwork()->libertyCell(self); }
is_leaf()5528 bool is_leaf() { return cmdNetwork()->isLeaf(self); }
5529 CellPortIterator *
port_iterator()5530 port_iterator() { return cmdNetwork()->portIterator(self); }
5531 
5532 Port *
find_port(const char * name)5533 find_port(const char *name)
5534 {
5535   return cmdNetwork()->findPort(self, name);
5536 }
5537 
5538 TmpPortSeq *
find_ports_matching(const char * pattern,bool regexp,bool nocase)5539 find_ports_matching(const char *pattern,
5540 		    bool regexp,
5541 		    bool nocase)
5542 {
5543   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
5544   TmpPortSeq *ports = new TmpPortSeq;
5545   cmdNetwork()->findPortsMatching(self, &matcher, ports);
5546   return ports;
5547 }
5548 
5549 } // Cell methods
5550 
5551 %extend LibertyCell {
name()5552 const char *name() { return self->name(); }
is_leaf()5553 bool is_leaf() { return self->isLeaf(); }
is_buffer()5554 bool is_buffer() { return self->isBuffer(); }
is_inverter()5555 bool is_inverter() { return self->isInverter(); }
liberty_library()5556 LibertyLibrary *liberty_library() { return self->libertyLibrary(); }
cell()5557 Cell *cell() { return reinterpret_cast<Cell*>(self); }
5558 LibertyPort *
find_liberty_port(const char * name)5559 find_liberty_port(const char *name)
5560 {
5561   return self->findLibertyPort(name);
5562 }
5563 
5564 TmpLibertyPortSeq *
find_liberty_ports_matching(const char * pattern,bool regexp,bool nocase)5565 find_liberty_ports_matching(const char *pattern,
5566 			    bool regexp,
5567 			    bool nocase)
5568 {
5569   PatternMatch matcher(pattern, regexp, nocase, Sta::sta()->tclInterp());
5570   TmpLibertyPortSeq *ports = new TmpLibertyPortSeq;
5571   self->findLibertyPortsMatching(&matcher, ports);
5572   return ports;
5573 }
5574 
5575 LibertyCellPortIterator *
liberty_port_iterator()5576 liberty_port_iterator() { return new LibertyCellPortIterator(self); }
5577 
5578 LibertyCellTimingArcSetIterator *
timing_arc_set_iterator()5579 timing_arc_set_iterator() { return new LibertyCellTimingArcSetIterator(self); }
5580 
5581 } // LibertyCell methods
5582 
5583 %extend CellPortIterator {
has_next()5584 bool has_next() { return self->hasNext(); }
next()5585 Port *next() { return self->next(); }
finish()5586 void finish() { delete self; }
5587 } // CellPortIterator methods
5588 
5589 %extend LibertyCellPortIterator {
has_next()5590 bool has_next() { return self->hasNext(); }
next()5591 LibertyPort *next() { return self->next(); }
finish()5592 void finish() { delete self; }
5593 } // LibertyCellPortIterator methods
5594 
5595 %extend Port {
bus_name()5596 const char *bus_name() { return cmdNetwork()->busName(self); }
cell()5597 Cell *cell() { return cmdNetwork()->cell(self); }
liberty_port()5598 LibertyPort *liberty_port() { return cmdNetwork()->libertyPort(self); }
is_bus()5599 bool is_bus() { return cmdNetwork()->isBus(self); }
5600 PortMemberIterator *
member_iterator()5601 member_iterator() { return cmdNetwork()->memberIterator(self); }
5602 
5603 } // Port methods
5604 
5605 %extend LibertyPort {
bus_name()5606 const char *bus_name() { return self->busName(); }
cell()5607 Cell *cell() { return self->cell(); }
is_bus()5608 bool is_bus() { return self->isBus(); }
5609 LibertyPortMemberIterator *
member_iterator()5610 member_iterator() { return new LibertyPortMemberIterator(self); }
5611 
5612 const char *
function()5613 function()
5614 {
5615   FuncExpr *func = self->function();
5616   if (func)
5617     return func->asString();
5618   else
5619     return nullptr;
5620 }
5621 
5622 const char *
tristate_enable()5623 tristate_enable()
5624 {
5625   FuncExpr *enable = self->tristateEnable();
5626   if (enable)
5627     return enable->asString();
5628   else
5629     return nullptr;
5630 }
5631 
5632 float
capacitance(Corner * corner,const MinMax * min_max)5633 capacitance(Corner *corner,
5634 	    const MinMax *min_max)
5635 {
5636   Sta *sta = Sta::sta();
5637   return sta->capacitance(self, corner, min_max);
5638 }
5639 
5640 } // LibertyPort methods
5641 
5642 %extend OperatingConditions {
process()5643 float process() { return self->process(); }
voltage()5644 float voltage() { return self->voltage(); }
temperature()5645 float temperature() { return self->temperature(); }
5646 }
5647 
5648 %extend PortMemberIterator {
has_next()5649 bool has_next() { return self->hasNext(); }
next()5650 Port *next() { return self->next(); }
finish()5651 void finish() { delete self; }
5652 } // PortMemberIterator methods
5653 
5654 %extend LibertyPortMemberIterator {
has_next()5655 bool has_next() { return self->hasNext(); }
next()5656 LibertyPort *next() { return self->next(); }
finish()5657 void finish() { delete self; }
5658 } // LibertyPortMemberIterator methods
5659 
5660 %extend TimingArcSet {
from()5661 LibertyPort *from() { return self->from(); }
to()5662 LibertyPort *to() { return self->to(); }
role()5663 TimingRole *role() { return self->role(); }
sdf_cond()5664 const char *sdf_cond() { return self->sdfCond(); }
5665 
5666 const char *
full_name()5667 full_name()
5668 {
5669   const char *from = self->from()->name();
5670   const char *to = self->to()->name();
5671   const char *cell_name = self->libertyCell()->name();
5672   return stringPrintTmp("%s %s -> %s",
5673 			cell_name,
5674 			from,
5675 			to);
5676 }
5677 
5678 } // TimingArcSet methods
5679 
5680 %extend LibertyCellTimingArcSetIterator {
has_next()5681 bool has_next() { return self->hasNext(); }
next()5682 TimingArcSet *next() { return self->next(); }
finish()5683 void finish() { delete self; }
5684 }
5685 
5686 %extend TimingArc {
from()5687 LibertyPort *from() { return self->from(); }
to()5688 LibertyPort *to() { return self->to(); }
from_trans()5689 Transition *from_trans() { return self->fromTrans(); }
from_trans_name()5690 const char *from_trans_name() { return self->fromTrans()->asRiseFall()->name(); }
to_trans()5691 Transition *to_trans() { return self->toTrans(); }
to_trans_name()5692 const char *to_trans_name() { return self->toTrans()->asRiseFall()->name(); }
role()5693 TimingRole *role() { return self->role(); }
5694 } // TimingArc methods
5695 
5696 %extend TimingArcSetArcIterator {
has_next()5697 bool has_next() { return self->hasNext(); }
next()5698 TimingArc *next() { return self->next(); }
finish()5699 void finish() { delete self; }
5700 }
5701 
5702 %extend Instance {
parent()5703 Instance *parent() { return cmdLinkedNetwork()->parent(self); }
cell()5704 Cell *cell() { return cmdLinkedNetwork()->cell(self); }
liberty_cell()5705 LibertyCell *liberty_cell() { return cmdLinkedNetwork()->libertyCell(self); }
is_leaf()5706 bool is_leaf() { return cmdLinkedNetwork()->isLeaf(self); }
5707 InstanceChildIterator *
child_iterator()5708 child_iterator() { return cmdLinkedNetwork()->childIterator(self); }
5709 InstancePinIterator *
pin_iterator()5710 pin_iterator() { return cmdLinkedNetwork()->pinIterator(self); }
5711 InstanceNetIterator *
net_iterator()5712 net_iterator() { return cmdLinkedNetwork()->netIterator(self); }
5713 Pin *
find_pin(const char * name)5714 find_pin(const char *name)
5715 {
5716   return cmdLinkedNetwork()->findPin(self, name);
5717 }
5718 } // Instance methods
5719 
5720 %extend InstanceChildIterator {
has_next()5721 bool has_next() { return self->hasNext(); }
next()5722 Instance *next() { return self->next(); }
finish()5723 void finish() { delete self; }
5724 } // InstanceChildIterator methods
5725 
5726 %extend LeafInstanceIterator {
has_next()5727 bool has_next() { return self->hasNext(); }
next()5728 Instance *next() { return self->next(); }
finish()5729 void finish() { delete self; }
5730 } // LeafInstanceIterator methods
5731 
5732 %extend InstancePinIterator {
has_next()5733 bool has_next() { return self->hasNext(); }
next()5734 Pin *next() { return self->next(); }
finish()5735 void finish() { delete self; }
5736 } // InstancePinIterator methods
5737 
5738 %extend InstanceNetIterator {
has_next()5739 bool has_next() { return self->hasNext(); }
next()5740 Net *next() { return self->next(); }
finish()5741 void finish() { delete self; }
5742 } // InstanceNetIterator methods
5743 
5744 %extend Pin {
port_name()5745 const char *port_name() { return cmdLinkedNetwork()->portName(self); }
instance()5746 Instance *instance() { return cmdLinkedNetwork()->instance(self); }
net()5747 Net *net() { return cmdLinkedNetwork()->net(self); }
port()5748 Port *port() { return cmdLinkedNetwork()->port(self); }
term()5749 Term *term() { return cmdLinkedNetwork()->term(self); }
liberty_port()5750 LibertyPort *liberty_port() { return cmdLinkedNetwork()->libertyPort(self); }
is_driver()5751 bool is_driver() { return cmdLinkedNetwork()->isDriver(self); }
is_load()5752 bool is_load() { return cmdLinkedNetwork()->isLoad(self); }
is_leaf()5753 bool is_leaf() { return cmdLinkedNetwork()->isLeaf(self); }
is_hierarchical()5754 bool is_hierarchical() { return cmdLinkedNetwork()->isHierarchical(self); }
is_top_level_port()5755 bool is_top_level_port() { return cmdLinkedNetwork()->isTopLevelPort(self); }
connected_pin_iterator()5756 PinConnectedPinIterator *connected_pin_iterator()
5757 { return cmdLinkedNetwork()->connectedPinIterator(self); }
5758 
5759 Vertex **
vertices()5760 vertices()
5761 {
5762   Vertex *vertex, *vertex_bidirect_drvr;
5763   static Vertex *vertices[3];
5764 
5765   cmdGraph()->pinVertices(self, vertex, vertex_bidirect_drvr);
5766   vertices[0] = vertex;
5767   vertices[1] = vertex_bidirect_drvr;
5768   vertices[2] = nullptr;
5769   return vertices;
5770 }
5771 
5772 float
capacitance(const RiseFall * rf,const Corner * corner,const MinMax * min_max)5773 capacitance(const RiseFall *rf,
5774 	    const Corner *corner,
5775 	    const MinMax *min_max)
5776 {
5777   cmdLinkedNetwork();
5778   float pin_cap, wire_cap;
5779   Sta::sta()->connectedCap(self, rf, corner, min_max, pin_cap, wire_cap);
5780   return pin_cap + wire_cap;
5781 }
5782 
5783 float
pin_capacitance(const RiseFall * rf,const Corner * corner,const MinMax * min_max)5784 pin_capacitance(const RiseFall *rf,
5785 		const Corner *corner,
5786 		const MinMax *min_max)
5787 {
5788   cmdLinkedNetwork();
5789   float pin_cap, wire_cap;
5790   Sta::sta()->connectedCap(self, rf, corner, min_max, pin_cap, wire_cap);
5791   return pin_cap;
5792 }
5793 
5794 float
wire_capacitance(const RiseFall * rf,const Corner * corner,const MinMax * min_max)5795 wire_capacitance(const RiseFall *rf,
5796 		 const Corner *corner,
5797 		 const MinMax *min_max)
5798 {
5799   cmdLinkedNetwork();
5800   float pin_cap, wire_cap;
5801   Sta::sta()->connectedCap(self, rf, corner, min_max, pin_cap, wire_cap);
5802   return wire_cap;
5803 }
5804 
5805 } // Pin methods
5806 
5807 %extend PinConnectedPinIterator {
has_next()5808 bool has_next() { return self->hasNext(); }
next()5809 Pin *next() { return self->next(); }
finish()5810 void finish() { delete self; }
5811 } // PinConnectedPinIterator methods
5812 
5813 %extend Term {
net()5814 Net *net() { return cmdLinkedNetwork()->net(self); }
pin()5815 Pin *pin() { return cmdLinkedNetwork()->pin(self); }
5816 } // Term methods
5817 
5818 %extend Net {
instance()5819 Instance *instance() { return cmdLinkedNetwork()->instance(self); }
highest_connected_net()5820 Net *highest_connected_net()
5821 { return cmdLinkedNetwork()->highestConnectedNet(self); }
pin_iterator()5822 NetPinIterator *pin_iterator() { return cmdLinkedNetwork()->pinIterator(self);}
term_iterator()5823 NetTermIterator *term_iterator() {return cmdLinkedNetwork()->termIterator(self);}
connected_pin_iterator()5824 NetConnectedPinIterator *connected_pin_iterator()
5825 { return cmdLinkedNetwork()->connectedPinIterator(self); }
is_power()5826 bool is_power() { return cmdLinkedNetwork()->isPower(self);}
is_ground()5827 bool is_ground() { return cmdLinkedNetwork()->isGround(self);}
5828 
5829 float
capacitance(Corner * corner,const MinMax * min_max)5830 capacitance(Corner *corner,
5831 	    const MinMax *min_max)
5832 {
5833   cmdLinkedNetwork();
5834   float pin_cap, wire_cap;
5835   Sta::sta()->connectedCap(self, corner, min_max, pin_cap, wire_cap);
5836   return pin_cap + wire_cap;
5837 }
5838 
5839 float
pin_capacitance(Corner * corner,const MinMax * min_max)5840 pin_capacitance(Corner *corner,
5841 		const MinMax *min_max)
5842 {
5843   cmdLinkedNetwork();
5844   float pin_cap, wire_cap;
5845   Sta::sta()->connectedCap(self, corner, min_max, pin_cap, wire_cap);
5846   return pin_cap;
5847 }
5848 
5849 float
wire_capacitance(Corner * corner,const MinMax * min_max)5850 wire_capacitance(Corner *corner,
5851 		 const MinMax *min_max)
5852 {
5853   cmdLinkedNetwork();
5854   float pin_cap, wire_cap;
5855   Sta::sta()->connectedCap(self, corner, min_max, pin_cap, wire_cap);
5856   return wire_cap;
5857 }
5858 
5859 // get_ports -of_objects net
5860 TmpPortSeq *
ports()5861 ports()
5862 {
5863   Network *network = cmdLinkedNetwork();
5864   PortSeq *ports = new PortSeq;
5865   if (network->isTopInstance(network->instance(self))) {
5866     NetTermIterator *term_iter = network->termIterator(self);
5867     while (term_iter->hasNext()) {
5868       Term *term = term_iter->next();
5869       Port *port = network->port(network->pin(term));
5870       ports->push_back(port);
5871     }
5872     delete term_iter;
5873   }
5874   return ports;
5875 }
5876 
5877 } // Net methods
5878 
5879 %extend NetPinIterator {
has_next()5880 bool has_next() { return self->hasNext(); }
next()5881 Pin *next() { return self->next(); }
finish()5882 void finish() { delete self; }
5883 } // NetPinIterator methods
5884 
5885 %extend NetTermIterator {
has_next()5886 bool has_next() { return self->hasNext(); }
next()5887 Term *next() { return self->next(); }
finish()5888 void finish() { delete self; }
5889 } // NetTermIterator methods
5890 
5891 %extend NetConnectedPinIterator {
has_next()5892 bool has_next() { return self->hasNext(); }
next()5893 Pin *next() { return self->next(); }
finish()5894 void finish() { delete self; }
5895 } // NetConnectedPinIterator methods
5896 
5897 %extend Clock {
period()5898 float period() { return self->period(); }
waveform()5899 FloatSeq *waveform() { return self->waveform(); }
time(RiseFall * rf)5900 float time(RiseFall *rf) { return self->edge(rf)->time(); }
is_generated()5901 bool is_generated() { return self->isGenerated(); }
waveform_valid()5902 bool waveform_valid() { return self->waveformValid(); }
is_virtual()5903 bool is_virtual() { return self->isVirtual(); }
is_propagated()5904 bool is_propagated() { return self->isPropagated(); }
sources()5905 PinSet &sources() { return self->pins(); }
5906 
5907 float
slew(const RiseFall * rf,const MinMax * min_max)5908 slew(const RiseFall *rf,
5909      const MinMax *min_max)
5910 {
5911   return self->slew(rf, min_max);
5912 }
5913 
5914 }
5915 
5916 %extend ClockEdge {
clock()5917 Clock *clock() { return self->clock(); }
transition()5918 RiseFall *transition() { return self->transition(); }
time()5919 float time() { return self->time(); }
5920 }
5921 
5922 %extend ClockIterator {
has_next()5923 bool has_next() { return self->hasNext(); }
next()5924 Clock *next() { return self->next(); }
finish()5925 void finish() { delete self; }
5926 }
5927 
5928 %extend Vertex {
pin()5929 Pin *pin() { return self->pin(); }
is_bidirect_driver()5930 bool is_bidirect_driver() { return self->isBidirectDriver(); }
level()5931 int level() { return Sta::sta()->vertexLevel(self); }
tag_group_index()5932 int tag_group_index() { return self->tagGroupIndex(); }
5933 
5934 Slew
slew(const RiseFall * rf,const MinMax * min_max)5935 slew(const RiseFall *rf,
5936      const MinMax *min_max)
5937 {
5938   Sta *sta = Sta::sta();
5939   return sta->vertexSlew(self, rf, min_max);
5940 }
5941 
5942 Slew
slew_corner(const RiseFall * rf,const Corner * corner,const MinMax * min_max)5943 slew_corner(const RiseFall *rf,
5944             const Corner *corner,
5945             const MinMax *min_max)
5946 {
5947   Sta *sta = Sta::sta();
5948   return sta->vertexSlew(self, rf, corner, min_max);
5949 }
5950 
5951 VertexOutEdgeIterator *
out_edge_iterator()5952 out_edge_iterator()
5953 {
5954   return new VertexOutEdgeIterator(self, Sta::sta()->graph());
5955 }
5956 
5957 VertexInEdgeIterator *
in_edge_iterator()5958 in_edge_iterator()
5959 {
5960   return new VertexInEdgeIterator(self, Sta::sta()->graph());
5961 }
5962 
5963 TmpFloatSeq *
arrivals_clk(const RiseFall * rf,Clock * clk,const RiseFall * clk_rf)5964 arrivals_clk(const RiseFall *rf,
5965 	     Clock *clk,
5966 	     const RiseFall *clk_rf)
5967 {
5968   Sta *sta = Sta::sta();
5969   TmpFloatSeq *floats = new FloatSeq;
5970   const ClockEdge *clk_edge = nullptr;
5971   if (clk)
5972     clk_edge = clk->edge(clk_rf);
5973   for (auto path_ap : sta->corners()->pathAnalysisPts()) {
5974     floats->push_back(delayAsFloat(sta->vertexArrival(self, rf, clk_edge,
5975 						      path_ap)));
5976   }
5977   return floats;
5978 }
5979 
5980 TmpStringSeq *
arrivals_clk_delays(const RiseFall * rf,Clock * clk,const RiseFall * clk_rf,int digits)5981 arrivals_clk_delays(const RiseFall *rf,
5982 		    Clock *clk,
5983 		    const RiseFall *clk_rf,
5984 		    int digits)
5985 {
5986   Sta *sta = Sta::sta();
5987   StringSeq *arrivals = new StringSeq;
5988   const ClockEdge *clk_edge = nullptr;
5989   if (clk)
5990     clk_edge = clk->edge(clk_rf);
5991   for (auto path_ap : sta->corners()->pathAnalysisPts()) {
5992     arrivals->push_back(delayAsString(sta->vertexArrival(self, rf, clk_edge,
5993 							 path_ap),
5994 				      sta, digits));
5995   }
5996   return arrivals;
5997 }
5998 
5999 TmpFloatSeq *
requireds_clk(const RiseFall * rf,Clock * clk,const RiseFall * clk_rf)6000 requireds_clk(const RiseFall *rf,
6001 	      Clock *clk,
6002 	      const RiseFall *clk_rf)
6003 {
6004   Sta *sta = Sta::sta();
6005   TmpFloatSeq *floats = new FloatSeq;
6006   const ClockEdge *clk_edge = nullptr;
6007   if (clk)
6008     clk_edge = clk->edge(clk_rf);
6009   for (auto path_ap : sta->corners()->pathAnalysisPts()) {
6010     floats->push_back(delayAsFloat(sta->vertexRequired(self, rf, clk_edge,
6011 						       path_ap)));
6012   }
6013   return floats;
6014 }
6015 
6016 TmpStringSeq *
requireds_clk_delays(const RiseFall * rf,Clock * clk,const RiseFall * clk_rf,int digits)6017 requireds_clk_delays(const RiseFall *rf,
6018 		     Clock *clk,
6019 		     const RiseFall *clk_rf,
6020 		     int digits)
6021 {
6022   Sta *sta = Sta::sta();
6023   StringSeq *requireds = new StringSeq;
6024   const ClockEdge *clk_edge = nullptr;
6025   if (clk)
6026     clk_edge = clk->edge(clk_rf);
6027   for (auto path_ap : sta->corners()->pathAnalysisPts()) {
6028     requireds->push_back(delayAsString(sta->vertexRequired(self, rf, clk_edge,
6029 							   path_ap),
6030 				       sta, digits));
6031   }
6032   return requireds;
6033 }
6034 
6035 Slack
slack(MinMax * min_max)6036 slack(MinMax *min_max)
6037 {
6038   Sta *sta = Sta::sta();
6039   return sta->vertexSlack(self, min_max);
6040 }
6041 
6042 TmpFloatSeq *
slacks(RiseFall * rf)6043 slacks(RiseFall *rf)
6044 {
6045   Sta *sta = Sta::sta();
6046   TmpFloatSeq *floats = new FloatSeq;
6047   for (auto path_ap : sta->corners()->pathAnalysisPts()) {
6048     floats->push_back(delayAsFloat(sta->vertexSlack(self, rf, path_ap)));
6049   }
6050   return floats;
6051 }
6052 
6053 // Slack with respect to a clock rise/fall edge.
6054 TmpFloatSeq *
slacks_clk(const RiseFall * rf,Clock * clk,const RiseFall * clk_rf)6055 slacks_clk(const RiseFall *rf,
6056 	   Clock *clk,
6057 	   const RiseFall *clk_rf)
6058 {
6059   Sta *sta = Sta::sta();
6060   TmpFloatSeq *floats = new FloatSeq;
6061   const ClockEdge *clk_edge = nullptr;
6062   if (clk)
6063     clk_edge = clk->edge(clk_rf);
6064   for (auto path_ap : sta->corners()->pathAnalysisPts()) {
6065     floats->push_back(delayAsFloat(sta->vertexSlack(self, rf, clk_edge,
6066 						    path_ap)));
6067   }
6068   return floats;
6069 }
6070 
6071 TmpStringSeq *
slacks_clk_delays(const RiseFall * rf,Clock * clk,const RiseFall * clk_rf,int digits)6072 slacks_clk_delays(const RiseFall *rf,
6073 		  Clock *clk,
6074 		  const RiseFall *clk_rf,
6075 		  int digits)
6076 {
6077   Sta *sta = Sta::sta();
6078   StringSeq *slacks = new StringSeq;
6079   const ClockEdge *clk_edge = nullptr;
6080   if (clk)
6081     clk_edge = clk->edge(clk_rf);
6082   for (auto path_ap : sta->corners()->pathAnalysisPts()) {
6083     slacks->push_back(delayAsString(sta->vertexSlack(self, rf, clk_edge,
6084 						     path_ap),
6085 				    sta, digits));
6086   }
6087   return slacks;
6088 }
6089 
6090 VertexPathIterator *
path_iterator(const RiseFall * rf,const MinMax * min_max)6091 path_iterator(const RiseFall *rf,
6092 	      const MinMax *min_max)
6093 {
6094   return Sta::sta()->vertexPathIterator(self, rf, min_max);
6095 }
6096 
6097 bool
has_downstream_clk_pin()6098 has_downstream_clk_pin()
6099 {
6100   return self->hasDownstreamClkPin();
6101 }
6102 
6103 bool
is_clock()6104 is_clock()
6105 {
6106   Sta *sta = Sta::sta();
6107   Search *search = sta->search();
6108   return search->isClock(self);
6109 }
6110 
is_disabled_constraint()6111 bool is_disabled_constraint() { return self->isDisabledConstraint(); }
6112 
6113 } // Vertex methods
6114 
6115 %extend Edge {
from()6116 Vertex *from() { return self->from(Sta::sta()->graph()); }
to()6117 Vertex *to() { return self->to(Sta::sta()->graph()); }
from_pin()6118 Pin *from_pin() { return self->from(Sta::sta()->graph())->pin(); }
to_pin()6119 Pin *to_pin() { return self->to(Sta::sta()->graph())->pin(); }
role()6120 TimingRole *role() { return self->role(); }
sense()6121 const char *sense() { return timingSenseString(self->sense()); }
6122 TimingArcSetArcIterator *
timing_arc_iterator()6123 timing_arc_iterator() { return new TimingArcSetArcIterator(self->timingArcSet()); }
is_disabled_loop()6124 bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); }
is_disabled_constraint()6125 bool is_disabled_constraint() { return Sta::sta()->isDisabledConstraint(self);}
is_disabled_constant()6126 bool is_disabled_constant() { return Sta::sta()->isDisabledConstant(self); }
is_disabled_cond_default()6127 bool is_disabled_cond_default()
6128 { return Sta::sta()->isDisabledCondDefault(self); }
6129 TmpPinSet *
disabled_constant_pins()6130 disabled_constant_pins() { return Sta::sta()->disabledConstantPins(self); }
is_disabled_bidirect_inst_path()6131 bool is_disabled_bidirect_inst_path()
6132 { return Sta::sta()->isDisabledBidirectInstPath(self); }
is_disabled_bidirect_net_path()6133 bool is_disabled_bidirect_net_path()
6134 { return Sta::sta()->isDisabledBidirectNetPath(self); }
is_disabled_preset_clear()6135 bool is_disabled_preset_clear()
6136 { return Sta::sta()->isDisabledPresetClr(self); }
6137 const char *
sim_timing_sense()6138 sim_timing_sense(){return timingSenseString(Sta::sta()->simTimingSense(self));}
6139 
6140 TmpFloatSeq *
arc_delays(TimingArc * arc)6141 arc_delays(TimingArc *arc)
6142 {
6143   Sta *sta = Sta::sta();
6144   TmpFloatSeq *floats = new FloatSeq;
6145   for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts())
6146     floats->push_back(delayAsFloat(sta->arcDelay(self, arc, dcalc_ap)));
6147   return floats;
6148 }
6149 
6150 TmpStringSeq *
arc_delay_strings(TimingArc * arc,int digits)6151 arc_delay_strings(TimingArc *arc,
6152 		  int digits)
6153 {
6154   Sta *sta = Sta::sta();
6155   StringSeq *delays = new StringSeq;
6156   for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts())
6157     delays->push_back(delayAsString(sta->arcDelay(self, arc, dcalc_ap),
6158 				    sta, digits));
6159   return delays;
6160 }
6161 
6162 bool
delay_annotated(TimingArc * arc,const Corner * corner,const MinMax * min_max)6163 delay_annotated(TimingArc *arc,
6164 		const Corner *corner,
6165 		const MinMax *min_max)
6166 {
6167   DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
6168   return Sta::sta()->arcDelayAnnotated(self, arc, dcalc_ap);
6169 }
6170 
6171 float
arc_delay(TimingArc * arc,const Corner * corner,const MinMax * min_max)6172 arc_delay(TimingArc *arc,
6173 	  const Corner *corner,
6174 	  const MinMax *min_max)
6175 {
6176   DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
6177   return delayAsFloat(Sta::sta()->arcDelay(self, arc, dcalc_ap));
6178 }
6179 
6180 const char *
cond()6181 cond()
6182 {
6183   FuncExpr *cond = self->timingArcSet()->cond();
6184   if (cond)
6185     return cond->asString();
6186   else
6187     return nullptr;
6188 }
6189 
6190 const char *
mode_name()6191 mode_name()
6192 {
6193   return self->timingArcSet()->modeName();
6194 }
6195 
6196 const char *
mode_value()6197 mode_value()
6198 {
6199   return self->timingArcSet()->modeValue();
6200 }
6201 
6202 const char *
latch_d_to_q_en()6203 latch_d_to_q_en()
6204 {
6205   if (self->role() == TimingRole::latchDtoQ()) {
6206     Sta *sta = Sta::sta();
6207     const Network *network = sta->cmdNetwork();
6208     const Graph *graph = sta->graph();
6209     Pin *from_pin = self->from(graph)->pin();
6210     Instance *inst = network->instance(from_pin);
6211     LibertyCell *lib_cell = network->libertyCell(inst);
6212     TimingArcSet *d_q_set = self->timingArcSet();
6213     LibertyPort *enable_port;
6214     FuncExpr *enable_func;
6215     RiseFall *enable_rf;
6216     lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_rf);
6217     const char *en_name = enable_port->name();
6218     return stringPrintTmp("%s %s", en_name, enable_rf->asString());
6219 
6220   }
6221   return "";
6222 }
6223 
6224 } // Edge methods
6225 
6226 %extend VertexIterator {
has_next()6227 bool has_next() { return self->hasNext(); }
next()6228 Vertex *next() { return self->next(); }
finish()6229 void finish() { delete self; }
6230 }
6231 
6232 %extend VertexInEdgeIterator {
has_next()6233 bool has_next() { return self->hasNext(); }
next()6234 Edge *next() { return self->next(); }
finish()6235 void finish() { delete self; }
6236 }
6237 
6238 %extend VertexOutEdgeIterator {
has_next()6239 bool has_next() { return self->hasNext(); }
next()6240 Edge *next() { return self->next(); }
finish()6241 void finish() { delete self; }
6242 }
6243 
6244 %extend PathEnd {
is_unconstrained()6245 bool is_unconstrained() { return self->isUnconstrained(); }
is_check()6246 bool is_check() { return self->isCheck(); }
is_latch_check()6247 bool is_latch_check() { return self->isLatchCheck(); }
is_data_check()6248 bool is_data_check() { return self->isDataCheck(); }
is_output_delay()6249 bool is_output_delay() { return self->isOutputDelay(); }
is_path_delay()6250 bool is_path_delay() { return self->isPathDelay(); }
is_gated_clock()6251 bool is_gated_clock() { return self->isGatedClock(); }
vertex()6252 Vertex *vertex() { return self->vertex(Sta::sta()); }
path()6253 PathRef *path() { return &self->pathRef(); }
end_transition()6254 RiseFall *end_transition()
6255 { return const_cast<RiseFall*>(self->path()->transition(Sta::sta())); }
slack()6256 Slack slack() { return self->slack(Sta::sta()); }
margin()6257 ArcDelay margin() { return self->margin(Sta::sta()); }
data_required_time()6258 Required data_required_time() { return self->requiredTimeOffset(Sta::sta()); }
data_arrival_time()6259 Arrival data_arrival_time() { return self->dataArrivalTimeOffset(Sta::sta()); }
check_role()6260 TimingRole *check_role() { return self->checkRole(Sta::sta()); }
min_max()6261 MinMax *min_max() { return const_cast<MinMax*>(self->minMax(Sta::sta())); }
source_clk_offset()6262 float source_clk_offset() { return self->sourceClkOffset(Sta::sta()); }
source_clk_latency()6263 Arrival source_clk_latency() { return self->sourceClkLatency(Sta::sta()); }
source_clk_insertion_delay()6264 Arrival source_clk_insertion_delay()
6265 { return self->sourceClkInsertionDelay(Sta::sta()); }
target_clk()6266 Clock *target_clk() { return self->targetClk(Sta::sta()); }
target_clk_edge()6267 ClockEdge *target_clk_edge() { return self->targetClkEdge(Sta::sta()); }
target_clk_path()6268 Path *target_clk_path() { return self->targetClkPath(); }
target_clk_time()6269 float target_clk_time() { return self->targetClkTime(Sta::sta()); }
target_clk_offset()6270 float target_clk_offset() { return self->targetClkOffset(Sta::sta()); }
target_clk_mcp_adjustment()6271 float target_clk_mcp_adjustment()
6272 { return self->targetClkMcpAdjustment(Sta::sta()); }
target_clk_delay()6273 Arrival target_clk_delay() { return self->targetClkDelay(Sta::sta()); }
target_clk_insertion_delay()6274 Arrival target_clk_insertion_delay()
6275 { return self->targetClkInsertionDelay(Sta::sta()); }
target_clk_uncertainty()6276 float target_clk_uncertainty()
6277 { return self->targetNonInterClkUncertainty(Sta::sta()); }
inter_clk_uncertainty()6278 float inter_clk_uncertainty()
6279 { return self->interClkUncertainty(Sta::sta()); }
target_clk_arrival()6280 Arrival target_clk_arrival() { return self->targetClkArrival(Sta::sta()); }
path_delay_margin_is_external()6281 bool path_delay_margin_is_external()
6282 { return self->pathDelayMarginIsExternal();}
common_clk_pessimism()6283 Crpr common_clk_pessimism() { return self->commonClkPessimism(Sta::sta()); }
target_clk_end_trans()6284 RiseFall *target_clk_end_trans()
6285 { return const_cast<RiseFall*>(self->targetClkEndTrans(Sta::sta())); }
6286 
6287 }
6288 
6289 %extend MinPulseWidthCheckSeqIterator {
has_next()6290 bool has_next() { return self->hasNext(); }
next()6291 MinPulseWidthCheck *next() { return self->next(); }
finish()6292 void finish() { delete self; }
6293 } // MinPulseWidthCheckSeqIterator methods
6294 
6295 %extend PathRef {
6296 float
arrival()6297 arrival()
6298 {
6299   Sta *sta = Sta::sta();
6300   return delayAsFloat(self->arrival(sta));
6301 }
6302 
6303 float
required()6304 required()
6305 {
6306   Sta *sta = Sta::sta();
6307   return delayAsFloat(self->required(sta));
6308 }
6309 
6310 float
slack()6311 slack()
6312 {
6313   Sta *sta = Sta::sta();
6314   return delayAsFloat(self->slack(sta));
6315 }
6316 
6317 Pin *
pin()6318 pin()
6319 {
6320   Sta *sta = Sta::sta();
6321   return self->pin(sta);
6322 }
6323 
6324 const char *
tag()6325 tag()
6326 {
6327   Sta *sta = Sta::sta();
6328   return self->tag(sta)->asString(sta);
6329 }
6330 
6331 // mea_opt3
6332 TmpPinSeq *
pins()6333 pins()
6334 {
6335   Sta *sta = Sta::sta();
6336   PinSeq *pins = new PinSeq;
6337   PathRef path1(self);
6338   while (!path1.isNull()) {
6339     pins->push_back(path1.vertex(sta)->pin());
6340     PathRef prev_path;
6341     path1.prevPath(sta, prev_path);
6342     path1.init(prev_path);
6343   }
6344   return pins;
6345 }
6346 
6347 }
6348 
6349 %extend VertexPathIterator {
has_next()6350 bool has_next() { return self->hasNext(); }
6351 PathRef *
next()6352 next()
6353 {
6354   Path *path = self->next();
6355   return new PathRef(path);
6356 }
6357 
finish()6358 void finish() { delete self; }
6359 }
6360 
6361 %extend SlowDrvrIterator {
has_next()6362 bool has_next() { return self->hasNext(); }
next()6363 Instance *next() { return self->next(); }
6364 void
finish()6365 finish()
6366 {
6367   delete self->container();
6368   delete self;
6369 }
6370 
6371 }
6372 
6373 %extend Corner {
name()6374 const char *name() { return self->name(); }
6375 }
6376 
6377 // Local Variables:
6378 // mode:c++
6379 // End:
6380