1 // OpenSTA, Static Timing Analyzer
2 // Copyright (c) 2021, Parallax Software, Inc.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 
17 #include "Liberty.hh"
18 
19 #include "DisallowCopyAssign.hh"
20 #include "EnumNameMap.hh"
21 #include "Report.hh"
22 #include "Debug.hh"
23 #include "Error.hh"
24 #include "StringUtil.hh"
25 #include "StringSet.hh"
26 #include "PatternMatch.hh"
27 #include "Units.hh"
28 #include "Transition.hh"
29 #include "TimingRole.hh"
30 #include "FuncExpr.hh"
31 #include "TableModel.hh"
32 #include "TimingArc.hh"
33 #include "InternalPower.hh"
34 #include "LeakagePower.hh"
35 #include "Sequential.hh"
36 #include "Wireload.hh"
37 #include "EquivCells.hh"
38 #include "Network.hh"
39 #include "PortDirection.hh"
40 
41 namespace sta {
42 
43 typedef Set<TimingModel*> TimingModelSet;
44 typedef Set<FuncExpr*> FuncExprSet;
45 typedef Set<LatchEnable*> LatchEnableSet;
46 
47 bool LibertyLibrary::found_rise_fall_caps_ = false;
48 
49 void
initLiberty()50 initLiberty()
51 {
52   TimingArcSet::init();
53 }
54 
55 void
deleteLiberty()56 deleteLiberty()
57 {
58   TimingArcSet::destroy();
59 }
60 
LibertyLibrary(const char * name,const char * filename)61 LibertyLibrary::LibertyLibrary(const char *name,
62 			       const char *filename) :
63   ConcreteLibrary(name, filename, true),
64   units_(new Units()),
65   delay_model_type_(DelayModelType::cmos_linear), // default
66   nominal_process_(0.0),
67   nominal_voltage_(0.0),
68   nominal_temperature_(0.0),
69   scale_factors_(nullptr),
70   default_input_pin_cap_(0.0),
71   default_output_pin_cap_(0.0),
72   default_bidirect_pin_cap_(0.0),
73   default_fanout_load_(0.0),
74   default_fanout_load_exists_(false),
75   default_max_cap_(0.0),
76   default_max_cap_exists_(false),
77   default_max_fanout_(0.0),
78   default_max_fanout_exists_(false),
79   default_max_slew_(0.0),
80   default_max_slew_exists_(false),
81   slew_derate_from_library_(1.0),
82   default_wire_load_(nullptr),
83   default_wire_load_mode_(WireloadMode::unknown),
84   default_wire_load_selection_(nullptr),
85   default_operating_conditions_(nullptr),
86   ocv_arc_depth_(0.0),
87   default_ocv_derate_(nullptr),
88   buffers_(nullptr)
89 {
90   // Scalar templates are builtin.
91   for (int i = 0; i != int(TableTemplateType::count); i++) {
92     TableTemplateType type = static_cast<TableTemplateType>(i);
93     TableTemplate *scalar_template = new TableTemplate("scalar", nullptr,
94 						       nullptr, nullptr);
95     addTableTemplate(scalar_template, type);
96   }
97 
98   for (auto tr_index : RiseFall::rangeIndex()) {
99     wire_slew_degradation_tbls_[tr_index] = nullptr;
100     input_threshold_[tr_index] = input_threshold_default_;
101     output_threshold_[tr_index] = output_threshold_default_;
102     slew_lower_threshold_[tr_index] = slew_lower_threshold_default_;
103     slew_upper_threshold_[tr_index] = slew_upper_threshold_default_;
104   }
105 }
106 
~LibertyLibrary()107 LibertyLibrary::~LibertyLibrary()
108 {
109   bus_dcls_.deleteContents();
110   for (int i = 0; i < int(TableTemplateType::count); i++)
111     template_maps_[i].deleteContents();
112   scale_factors_map_.deleteContents();
113   delete scale_factors_;
114 
115   for (auto tr_index : RiseFall::rangeIndex()) {
116     TableModel *model = wire_slew_degradation_tbls_[tr_index];
117     delete model;
118   }
119   operating_conditions_.deleteContents();
120   wireloads_.deleteContents();
121   wire_load_selections_.deleteContents();
122   delete units_;
123   ocv_derate_map_.deleteContents();
124 
125   for (auto name_volt : supply_voltage_map_) {
126     const char *supply_name = name_volt.first;
127     stringDelete(supply_name);
128   }
129   delete buffers_;
130 }
131 
132 LibertyCell *
findLibertyCell(const char * name) const133 LibertyLibrary::findLibertyCell(const char *name) const
134 {
135   return static_cast<LibertyCell*>(findCell(name));
136 }
137 
138 void
findLibertyCellsMatching(PatternMatch * pattern,LibertyCellSeq * cells)139 LibertyLibrary::findLibertyCellsMatching(PatternMatch *pattern,
140 					 LibertyCellSeq *cells)
141 {
142   LibertyCellIterator cell_iter(this);
143   while (cell_iter.hasNext()) {
144     LibertyCell *cell = cell_iter.next();
145     if (pattern->match(cell->name()))
146       cells->push_back(cell);
147   }
148 }
149 
150 LibertyCellSeq *
buffers()151 LibertyLibrary::buffers()
152 {
153   if (buffers_ == nullptr) {
154     buffers_ = new LibertyCellSeq;
155     LibertyCellIterator cell_iter(this);
156     while (cell_iter.hasNext()) {
157       LibertyCell *cell = cell_iter.next();
158       if (!cell->dontUse()
159 	  && cell->isBuffer())
160 	buffers_->push_back(cell);
161     }
162   }
163   return buffers_;
164 }
165 
166 void
setDelayModelType(DelayModelType type)167 LibertyLibrary::setDelayModelType(DelayModelType type)
168 {
169   delay_model_type_ = type;
170 }
171 
172 void
addBusDcl(BusDcl * bus_dcl)173 LibertyLibrary::addBusDcl(BusDcl *bus_dcl)
174 {
175   bus_dcls_[bus_dcl->name()] = bus_dcl;
176 }
177 
178 BusDcl *
findBusDcl(const char * name) const179 LibertyLibrary::findBusDcl(const char *name) const
180 {
181   return bus_dcls_.findKey(name);
182 }
183 
184 void
addTableTemplate(TableTemplate * tbl_template,TableTemplateType type)185 LibertyLibrary::addTableTemplate(TableTemplate *tbl_template,
186 				 TableTemplateType type)
187 {
188   template_maps_[int(type)][tbl_template->name()] = tbl_template;
189 }
190 
191 TableTemplate *
findTableTemplate(const char * name,TableTemplateType type)192 LibertyLibrary::findTableTemplate(const char *name,
193 				  TableTemplateType type)
194 {
195   return template_maps_[int(type)][name];
196 }
197 
198 void
setNominalProcess(float process)199 LibertyLibrary::setNominalProcess(float process)
200 {
201   nominal_process_ = process;
202 }
203 
204 void
setNominalVoltage(float voltage)205 LibertyLibrary::setNominalVoltage(float voltage)
206 {
207   nominal_voltage_ = voltage;
208 }
209 
210 void
setNominalTemperature(float temperature)211 LibertyLibrary::setNominalTemperature(float temperature)
212 {
213   nominal_temperature_ = temperature;
214 }
215 
216 void
setScaleFactors(ScaleFactors * scales)217 LibertyLibrary::setScaleFactors(ScaleFactors *scales)
218 {
219   scale_factors_ = scales;
220 }
221 
222 void
addScaleFactors(ScaleFactors * scales)223 LibertyLibrary::addScaleFactors(ScaleFactors *scales)
224 {
225   scale_factors_map_[scales->name()] = scales;
226 }
227 
228 ScaleFactors *
findScaleFactors(const char * name)229 LibertyLibrary::findScaleFactors(const char *name)
230 {
231   return scale_factors_map_[name];
232 }
233 
234 float
scaleFactor(ScaleFactorType type,const Pvt * pvt) const235 LibertyLibrary::scaleFactor(ScaleFactorType type,
236 			    const Pvt *pvt) const
237 {
238   return scaleFactor(type, 0, nullptr, pvt);
239 }
240 
241 float
scaleFactor(ScaleFactorType type,const LibertyCell * cell,const Pvt * pvt) const242 LibertyLibrary::scaleFactor(ScaleFactorType type,
243 			    const LibertyCell *cell,
244 			    const Pvt *pvt) const
245 {
246   return scaleFactor(type, 0, cell, pvt);
247 }
248 
249 float
scaleFactor(ScaleFactorType type,int tr_index,const LibertyCell * cell,const Pvt * pvt) const250 LibertyLibrary::scaleFactor(ScaleFactorType type,
251 			    int tr_index,
252 			    const LibertyCell *cell,
253 			    const Pvt *pvt) const
254 {
255   if (pvt == nullptr)
256     pvt = default_operating_conditions_;
257   // If there is no operating condition, nominal pvt values are used.
258   // All scale factors are unity for nominal pvt.
259   if (pvt) {
260     ScaleFactors *scale_factors = nullptr;
261     // Cell level scale factors have precidence over library scale factors.
262     if (cell)
263       scale_factors = cell->scaleFactors();
264     if (scale_factors == nullptr)
265       scale_factors = scale_factors_;
266     if (scale_factors) {
267       float process_scale = 1.0F + (pvt->process() - nominal_process_)
268 	* scale_factors->scale(type, ScaleFactorPvt::process, tr_index);
269       float temp_scale = 1.0F + (pvt->temperature() - nominal_temperature_)
270 	* scale_factors->scale(type, ScaleFactorPvt::temp, tr_index);
271       float volt_scale = 1.0F + (pvt->voltage() - nominal_voltage_)
272 	* scale_factors->scale(type, ScaleFactorPvt::volt, tr_index);
273       float scale = process_scale * temp_scale * volt_scale;
274       return scale;
275     }
276   }
277   return 1.0F;
278 }
279 
280 void
setWireSlewDegradationTable(TableModel * model,RiseFall * rf)281 LibertyLibrary::setWireSlewDegradationTable(TableModel *model,
282 			 		    RiseFall *rf)
283 {
284   int tr_index = rf->index();
285   if (wire_slew_degradation_tbls_[tr_index])
286     delete wire_slew_degradation_tbls_[tr_index];
287   wire_slew_degradation_tbls_[tr_index] = model;
288 }
289 
290 TableModel *
wireSlewDegradationTable(const RiseFall * rf) const291 LibertyLibrary::wireSlewDegradationTable(const RiseFall *rf) const
292 {
293   return wire_slew_degradation_tbls_[rf->index()];
294 }
295 
296 float
degradeWireSlew(const LibertyCell * cell,const RiseFall * rf,const Pvt * pvt,float in_slew,float wire_delay) const297 LibertyLibrary::degradeWireSlew(const LibertyCell *cell,
298 				const RiseFall *rf,
299 				const Pvt *pvt,
300 				float in_slew,
301 				float wire_delay) const
302 {
303   const TableModel *model = wireSlewDegradationTable(rf);
304   if (model)
305     return degradeWireSlew(cell, pvt, model, in_slew, wire_delay);
306   else
307     return in_slew;
308 }
309 
310 float
degradeWireSlew(const LibertyCell * cell,const Pvt * pvt,const TableModel * model,float in_slew,float wire_delay) const311 LibertyLibrary::degradeWireSlew(const LibertyCell *cell,
312 				const Pvt *pvt,
313 				const TableModel *model,
314 				float in_slew,
315 				float wire_delay) const
316 {
317   switch (model->order()) {
318   case 0:
319     return model->findValue(this, cell, pvt, 0.0, 0.0, 0.0);
320   case 1: {
321     TableAxis *axis1 = model->axis1();
322     TableAxisVariable var1 = axis1->variable();
323     if (var1 == TableAxisVariable::output_pin_transition)
324       return model->findValue(this, cell, pvt, in_slew, 0.0, 0.0);
325     else if (var1 == TableAxisVariable::connect_delay)
326       return model->findValue(this, cell, pvt, wire_delay, 0.0, 0.0);
327     else {
328       criticalError(231, "unsupported slew degradation table axes");
329       return 0.0;
330     }
331   }
332   case 2: {
333     TableAxis *axis1 = model->axis1();
334     TableAxis *axis2 = model->axis2();
335     TableAxisVariable var1 = axis1->variable();
336     TableAxisVariable var2 = axis2->variable();
337     if (var1 == TableAxisVariable::output_pin_transition
338 	&& var2 == TableAxisVariable::connect_delay)
339       return model->findValue(this, cell, pvt, in_slew, wire_delay, 0.0);
340     else if (var1 == TableAxisVariable::connect_delay
341 	     && var2 == TableAxisVariable::output_pin_transition)
342       return model->findValue(this, cell, pvt, wire_delay, in_slew, 0.0);
343     else {
344       criticalError(232, "unsupported slew degradation table axes");
345       return 0.0;
346     }
347   }
348   default:
349     criticalError(233, "unsupported slew degradation table order");
350     return 0.0;
351   }
352 }
353 
354 // Check for supported axis variables.
355 // Return true if axes are supported.
356 bool
checkSlewDegradationAxes(Table * table)357 LibertyLibrary::checkSlewDegradationAxes(Table *table)
358 {
359   switch (table->order()) {
360   case 0:
361     return true;
362   case 1: {
363     TableAxis *axis1 = table->axis1();
364     TableAxisVariable var1 = axis1->variable();
365     return var1 == TableAxisVariable::output_pin_transition
366       || var1 == TableAxisVariable::connect_delay;
367   }
368   case 2: {
369     TableAxis *axis1 = table->axis1();
370     TableAxis *axis2 = table->axis2();
371     TableAxisVariable var1 = axis1->variable();
372     TableAxisVariable var2 = axis2->variable();
373     return (var1 == TableAxisVariable::output_pin_transition
374 	    && var2 == TableAxisVariable::connect_delay)
375       || (var1 == TableAxisVariable::connect_delay
376 	  && var2 == TableAxisVariable::output_pin_transition);
377   }
378   default:
379     criticalError(234, "unsupported slew degradation table axes");
380     return 0.0;
381   }
382 }
383 
384 void
defaultMaxFanout(float & fanout,bool & exists) const385 LibertyLibrary::defaultMaxFanout(float &fanout,
386 				 bool &exists) const
387 {
388   fanout = default_max_fanout_;
389   exists = default_max_fanout_exists_;
390 }
391 
392 void
setDefaultMaxFanout(float fanout)393 LibertyLibrary::setDefaultMaxFanout(float fanout)
394 {
395   default_max_fanout_ = fanout;
396   default_max_fanout_exists_ = true;
397 }
398 
399 void
defaultMaxSlew(float & slew,bool & exists) const400 LibertyLibrary::defaultMaxSlew(float &slew,
401 			       bool &exists) const
402 {
403   slew = default_max_slew_;
404   exists = default_max_slew_exists_;
405 }
406 
407 void
setDefaultMaxSlew(float slew)408 LibertyLibrary::setDefaultMaxSlew(float slew)
409 {
410   default_max_slew_ = slew;
411   default_max_slew_exists_ = true;
412 }
413 
414 void
defaultMaxCapacitance(float & cap,bool & exists) const415 LibertyLibrary::defaultMaxCapacitance(float &cap,
416 				      bool &exists) const
417 {
418   cap = default_max_cap_;
419   exists = default_max_cap_exists_;
420 }
421 
422 void
setDefaultMaxCapacitance(float cap)423 LibertyLibrary::setDefaultMaxCapacitance(float cap)
424 {
425   default_max_cap_ = cap;
426   default_max_cap_exists_ = true;
427 }
428 
429 void
defaultFanoutLoad(float & fanout,bool & exists) const430 LibertyLibrary::defaultFanoutLoad(// Return values.
431 				  float &fanout,
432 				  bool &exists) const
433 {
434   fanout = default_fanout_load_;
435   exists = default_fanout_load_exists_;
436 }
437 
438 void
setDefaultFanoutLoad(float load)439 LibertyLibrary::setDefaultFanoutLoad(float load)
440 {
441   default_fanout_load_ = load;
442   default_fanout_load_exists_ = true;
443 }
444 
445 void
setDefaultBidirectPinCap(float cap)446 LibertyLibrary::setDefaultBidirectPinCap(float cap)
447 {
448   default_bidirect_pin_cap_ = cap;
449 }
450 
451 void
setDefaultInputPinCap(float cap)452 LibertyLibrary::setDefaultInputPinCap(float cap)
453 {
454   default_input_pin_cap_ = cap;
455 }
456 
457 void
setDefaultOutputPinCap(float cap)458 LibertyLibrary::setDefaultOutputPinCap(float cap)
459 {
460   default_output_pin_cap_ = cap;
461 }
462 
463 void
defaultIntrinsic(const RiseFall * rf,float & intrinsic,bool & exists) const464 LibertyLibrary::defaultIntrinsic(const RiseFall *rf,
465 				 // Return values.
466 				 float &intrinsic,
467 				 bool &exists) const
468 {
469   default_intrinsic_.value(rf, intrinsic, exists);
470 }
471 
472 void
setDefaultIntrinsic(const RiseFall * rf,float value)473 LibertyLibrary::setDefaultIntrinsic(const RiseFall *rf,
474 				    float value)
475 {
476   default_intrinsic_.setValue(rf, value);
477 }
478 
479 void
defaultPinResistance(const RiseFall * rf,const PortDirection * dir,float & res,bool & exists) const480 LibertyLibrary::defaultPinResistance(const RiseFall *rf,
481 				     const PortDirection *dir,
482 				     // Return values.
483 				     float &res,
484 				     bool &exists) const
485 {
486   if (dir->isAnyTristate())
487     defaultBidirectPinRes(rf, res, exists);
488   else
489     defaultOutputPinRes(rf, res, exists);
490 }
491 
492 void
defaultBidirectPinRes(const RiseFall * rf,float & res,bool & exists) const493 LibertyLibrary::defaultBidirectPinRes(const RiseFall *rf,
494 				      // Return values.
495 				      float &res,
496 				      bool &exists) const
497 {
498   return default_inout_pin_res_.value(rf, res, exists);
499 }
500 
501 void
setDefaultBidirectPinRes(const RiseFall * rf,float value)502 LibertyLibrary::setDefaultBidirectPinRes(const RiseFall *rf,
503 					 float value)
504 {
505   default_inout_pin_res_.setValue(rf, value);
506 }
507 
508 void
defaultOutputPinRes(const RiseFall * rf,float & res,bool & exists) const509 LibertyLibrary::defaultOutputPinRes(const RiseFall *rf,
510 				    // Return values.
511 				    float &res,
512 				    bool &exists) const
513 {
514   default_output_pin_res_.value(rf, res, exists);
515 }
516 
517 void
setDefaultOutputPinRes(const RiseFall * rf,float value)518 LibertyLibrary::setDefaultOutputPinRes(const RiseFall *rf,
519 				       float value)
520 {
521   default_output_pin_res_.setValue(rf, value);
522 }
523 
524 void
addWireload(Wireload * wireload)525 LibertyLibrary::addWireload(Wireload *wireload)
526 {
527   wireloads_[wireload->name()] = wireload;
528 }
529 
530 Wireload *
findWireload(const char * name) const531 LibertyLibrary::findWireload(const char *name) const
532 {
533   return wireloads_.findKey(name);
534 }
535 
536 void
setDefaultWireload(Wireload * wireload)537 LibertyLibrary::setDefaultWireload(Wireload *wireload)
538 {
539   default_wire_load_ = wireload;
540 }
541 
542 Wireload *
defaultWireload() const543 LibertyLibrary::defaultWireload() const
544 {
545   return default_wire_load_;
546 }
547 
548 void
addWireloadSelection(WireloadSelection * selection)549 LibertyLibrary::addWireloadSelection(WireloadSelection *selection)
550 {
551   wire_load_selections_[selection->name()] = selection;
552 }
553 
554 WireloadSelection *
findWireloadSelection(const char * name) const555 LibertyLibrary::findWireloadSelection(const char *name) const
556 {
557   return wire_load_selections_.findKey(name);
558 }
559 
560 WireloadSelection *
defaultWireloadSelection() const561 LibertyLibrary::defaultWireloadSelection() const
562 {
563   return default_wire_load_selection_;
564 }
565 
566 void
setDefaultWireloadSelection(WireloadSelection * selection)567 LibertyLibrary::setDefaultWireloadSelection(WireloadSelection *selection)
568 {
569   default_wire_load_selection_ = selection;
570 }
571 
572 WireloadMode
defaultWireloadMode() const573 LibertyLibrary::defaultWireloadMode() const
574 {
575   return default_wire_load_mode_;
576 }
577 
578 void
setDefaultWireloadMode(WireloadMode mode)579 LibertyLibrary::setDefaultWireloadMode(WireloadMode mode)
580 {
581   default_wire_load_mode_ = mode;
582 }
583 
584 void
addOperatingConditions(OperatingConditions * op_cond)585 LibertyLibrary::addOperatingConditions(OperatingConditions *op_cond)
586 {
587   operating_conditions_[op_cond->name()] = op_cond;
588 }
589 
590 OperatingConditions *
findOperatingConditions(const char * name)591 LibertyLibrary::findOperatingConditions(const char *name)
592 {
593   return operating_conditions_.findKey(name);
594 }
595 
596 OperatingConditions *
defaultOperatingConditions() const597 LibertyLibrary::defaultOperatingConditions() const
598 {
599   return default_operating_conditions_;
600 }
601 
602 void
setDefaultOperatingConditions(OperatingConditions * op_cond)603 LibertyLibrary::setDefaultOperatingConditions(OperatingConditions *op_cond)
604 {
605   default_operating_conditions_ = op_cond;
606 }
607 
608 float
inputThreshold(const RiseFall * rf) const609 LibertyLibrary::inputThreshold(const RiseFall *rf) const
610 {
611   return input_threshold_[rf->index()];
612 }
613 
614 void
setInputThreshold(const RiseFall * rf,float th)615 LibertyLibrary::setInputThreshold(const RiseFall *rf,
616 				  float th)
617 {
618   input_threshold_[rf->index()] = th;
619 }
620 
621 float
outputThreshold(const RiseFall * rf) const622 LibertyLibrary::outputThreshold(const RiseFall *rf) const
623 {
624   return output_threshold_[rf->index()];
625 }
626 
627 void
setOutputThreshold(const RiseFall * rf,float th)628 LibertyLibrary::setOutputThreshold(const RiseFall *rf,
629 				   float th)
630 {
631   output_threshold_[rf->index()] = th;
632 }
633 
634 float
slewLowerThreshold(const RiseFall * rf) const635 LibertyLibrary::slewLowerThreshold(const RiseFall *rf) const
636 {
637   return slew_lower_threshold_[rf->index()];
638 }
639 
640 void
setSlewLowerThreshold(const RiseFall * rf,float th)641 LibertyLibrary::setSlewLowerThreshold(const RiseFall *rf,
642 				      float th)
643 {
644   slew_lower_threshold_[rf->index()] = th;
645 }
646 
647 float
slewUpperThreshold(const RiseFall * rf) const648 LibertyLibrary::slewUpperThreshold(const RiseFall *rf) const
649 {
650   return slew_upper_threshold_[rf->index()];
651 }
652 
653 void
setSlewUpperThreshold(const RiseFall * rf,float th)654 LibertyLibrary::setSlewUpperThreshold(const RiseFall *rf,
655 				      float th)
656 {
657   slew_upper_threshold_[rf->index()] = th;
658 }
659 
660 float
slewDerateFromLibrary() const661 LibertyLibrary::slewDerateFromLibrary() const
662 {
663   return slew_derate_from_library_;
664 }
665 
666 void
setSlewDerateFromLibrary(float derate)667 LibertyLibrary::setSlewDerateFromLibrary(float derate)
668 {
669   slew_derate_from_library_ = derate;
670 }
671 
672 LibertyCell *
makeScaledCell(const char * name,const char * filename)673 LibertyLibrary::makeScaledCell(const char *name,
674 			       const char *filename)
675 {
676   LibertyCell *cell = new LibertyCell(this, name, filename);
677   return cell;
678 }
679 
680 ////////////////////////////////////////////////////////////////
681 
682 void
makeCornerMap(LibertyLibrary * lib,int ap_index,Network * network,Report * report)683 LibertyLibrary::makeCornerMap(LibertyLibrary *lib,
684 			      int ap_index,
685 			      Network *network,
686 			      Report *report)
687 {
688   LibertyCellIterator cell_iter(lib);
689   while (cell_iter.hasNext()) {
690     LibertyCell *cell = cell_iter.next();
691     const char *name = cell->name();
692     LibertyCell *link_cell = network->findLibertyCell(name);
693     if (link_cell)
694       makeCornerMap(link_cell, cell, ap_index, report);
695   }
696 }
697 
698 // Map a cell linked in the network to the corresponding liberty cell
699 // to use for delay calculation at a corner.
700 void
makeCornerMap(LibertyCell * link_cell,LibertyCell * corner_cell,int ap_index,Report * report)701 LibertyLibrary::makeCornerMap(LibertyCell *link_cell,
702 			      LibertyCell *corner_cell,
703 			      int ap_index,
704 			      Report *report)
705 {
706   link_cell->setCornerCell(corner_cell, ap_index);
707   makeCornerMap(link_cell, corner_cell, true, ap_index, report);
708   // Check for brain damage in the other direction.
709   makeCornerMap(corner_cell, link_cell, false, ap_index, report);
710 }
711 
712 void
makeCornerMap(LibertyCell * cell1,LibertyCell * cell2,bool link,int ap_index,Report * report)713 LibertyLibrary::makeCornerMap(LibertyCell *cell1,
714 			      LibertyCell *cell2,
715 			      bool link,
716 			      int ap_index,
717 			      Report *report)
718 {
719   LibertyCellPortBitIterator port_iter1(cell1);
720   while (port_iter1.hasNext()) {
721     LibertyPort *port1 = port_iter1.next();
722     const char *port_name = port1->name();
723     LibertyPort *port2 = cell2->findLibertyPort(port_name);
724     if (port2) {
725       if (link)
726 	port1->setCornerPort(port2, ap_index);
727     }
728     else
729       report->warn(2, "cell %s/%s port %s not found in cell %s/%s.",
730 		   cell1->library()->name(),
731 		   cell1->name(),
732 		   port_name,
733 		   cell2->library()->name(),
734 		   cell2->name());
735   }
736 
737   for (auto arc_set1 : cell1->timing_arc_sets_) {
738     auto arc_set2 = cell2->findTimingArcSet(arc_set1);
739     if (arc_set2) {
740       if (link) {
741 	TimingArcSetArcIterator arc_iter1(arc_set1);
742 	TimingArcSetArcIterator arc_iter2(arc_set2);
743 	while (arc_iter1.hasNext() && arc_iter2.hasNext()) {
744 	  TimingArc *arc1 = arc_iter1.next();
745 	  TimingArc *arc2 = arc_iter2.next();
746 	  if (TimingArc::equiv(arc1, arc2))
747 	    arc1->setCornerArc(arc2, ap_index);
748 	}
749       }
750     }
751     else
752       report->warn(3, "cell %s/%s %s -> %s timing group %s not found in cell %s/%s.",
753 		   cell1->library()->name(),
754 		   cell1->name(),
755 		   arc_set1->from()->name(),
756 		   arc_set1->to()->name(),
757 		   arc_set1->role()->asString(),
758 		   cell2->library()->name(),
759 		   cell2->name());
760   }
761 }
762 
763 ////////////////////////////////////////////////////////////////
764 
765 float
ocvArcDepth() const766 LibertyLibrary::ocvArcDepth() const
767 {
768   return ocv_arc_depth_;
769 }
770 
771 void
setOcvArcDepth(float depth)772 LibertyLibrary::setOcvArcDepth(float depth)
773 {
774   ocv_arc_depth_ = depth;
775 }
776 
777 OcvDerate *
defaultOcvDerate() const778 LibertyLibrary::defaultOcvDerate() const
779 {
780   return default_ocv_derate_;
781 }
782 
783 void
setDefaultOcvDerate(OcvDerate * derate)784 LibertyLibrary::setDefaultOcvDerate(OcvDerate *derate)
785 {
786   default_ocv_derate_ = derate;
787 }
788 
789 OcvDerate *
findOcvDerate(const char * derate_name)790 LibertyLibrary::findOcvDerate(const char *derate_name)
791 {
792   return ocv_derate_map_.findKey(derate_name);
793 }
794 
795 void
addOcvDerate(OcvDerate * derate)796 LibertyLibrary::addOcvDerate(OcvDerate *derate)
797 {
798   ocv_derate_map_[derate->name()] = derate;
799 }
800 
801 void
addSupplyVoltage(const char * supply_name,float voltage)802 LibertyLibrary::addSupplyVoltage(const char *supply_name,
803 				 float voltage)
804 {
805   supply_voltage_map_[stringCopy(supply_name)] = voltage;
806 }
807 
808 void
supplyVoltage(const char * supply_name,float & voltage,bool & exists) const809 LibertyLibrary::supplyVoltage(const char *supply_name,
810 			      // Return value.
811 			      float &voltage,
812 			      bool &exists) const
813 {
814   supply_voltage_map_.findKey(supply_name, voltage, exists);
815 }
816 
817 bool
supplyExists(const char * supply_name) const818 LibertyLibrary::supplyExists(const char *supply_name) const
819 {
820   return supply_voltage_map_.hasKey(supply_name);
821 }
822 
823 ////////////////////////////////////////////////////////////////
824 
LibertyCellIterator(const LibertyLibrary * library)825 LibertyCellIterator::LibertyCellIterator(const LibertyLibrary *
826 						       library):
827   iter_(library->cell_map_)
828 {
829 }
830 
831 bool
hasNext()832 LibertyCellIterator::hasNext()
833 {
834   return iter_.hasNext();
835 }
836 
837 LibertyCell *
next()838 LibertyCellIterator::next()
839 {
840   return static_cast<LibertyCell*>(iter_.next());
841 }
842 
843 ////////////////////////////////////////////////////////////////
844 
LibertyCell(LibertyLibrary * library,const char * name,const char * filename)845 LibertyCell::LibertyCell(LibertyLibrary *library,
846 			 const char *name,
847 			 const char *filename) :
848   ConcreteCell(library, name, true, filename),
849   liberty_library_(library),
850   area_(0.0),
851   dont_use_(false),
852   is_macro_(false),
853   is_memory_(false),
854   is_pad_(false),
855   is_level_shifter_(false),
856   has_internal_ports_(false),
857   interface_timing_(false),
858   clock_gate_type_(ClockGateType::none),
859   has_infered_reg_timing_arcs_(false),
860   scale_factors_(nullptr),
861   test_cell_(nullptr),
862   ocv_arc_depth_(0.0),
863   ocv_derate_(nullptr),
864   is_disabled_constraint_(false),
865   leakage_power_(0.0),
866   leakage_power_exists_(false)
867 {
868   liberty_cell_ = this;
869 }
870 
~LibertyCell()871 LibertyCell::~LibertyCell()
872 {
873   mode_defs_.deleteContents();
874   latch_d_to_q_map_.deleteContents();
875 
876   deleteTimingArcAttrs();
877   timing_arc_sets_.deleteContents();
878   port_timing_arc_set_map_.deleteContents();
879   timing_arc_set_from_map_.deleteContents();
880   timing_arc_set_to_map_.deleteContents();
881 
882   deleteInternalPowerAttrs();
883   internal_powers_.deleteContents();
884   leakage_powers_.deleteContents();
885 
886   sequentials_.deleteContents();
887   bus_dcls_.deleteContents();
888   scaled_cells_.deleteContents();
889 
890   delete test_cell_;
891   ocv_derate_map_.deleteContents();
892 
893   pg_port_map_.deleteContents();
894 }
895 
896 void
deleteTimingArcAttrs()897 LibertyCell::deleteTimingArcAttrs()
898 {
899   for (auto attrs : timing_arc_attrs_) {
900     attrs->deleteContents();
901     delete attrs;
902   }
903 }
904 
905 LibertyPort *
findLibertyPort(const char * name) const906 LibertyCell::findLibertyPort(const char *name) const
907 {
908   return static_cast<LibertyPort*>(findPort(name));
909 }
910 
911 void
findLibertyPortsMatching(PatternMatch * pattern,LibertyPortSeq * ports) const912 LibertyCell::findLibertyPortsMatching(PatternMatch *pattern,
913 				      LibertyPortSeq *ports) const
914 {
915   LibertyCellPortIterator port_iter(this);
916   while (port_iter.hasNext()) {
917     LibertyPort *port = port_iter.next();
918     if (pattern->match(port->name()))
919       ports->push_back(port);
920   }
921 }
922 
923 void
addPort(ConcretePort * port)924 LibertyCell::addPort(ConcretePort *port)
925 {
926   ConcreteCell::addPort(port);
927   if (port->direction()->isInternal())
928     has_internal_ports_ = true;
929 }
930 
931 
932 void
setHasInternalPorts(bool has_internal)933 LibertyCell::setHasInternalPorts(bool has_internal)
934 {
935   has_internal_ports_ = has_internal;
936 }
937 
938 void
addPgPort(LibertyPgPort * pg_port)939 LibertyCell::addPgPort(LibertyPgPort *pg_port)
940 {
941   pg_port_map_[pg_port->name()] = pg_port;
942 }
943 
944 LibertyPgPort *
findPgPort(const char * name) const945 LibertyCell::findPgPort(const char *name) const
946 {
947   return pg_port_map_.findKey(name);
948 }
949 
950 ModeDef *
makeModeDef(const char * name)951 LibertyCell::makeModeDef(const char *name)
952 {
953   ModeDef *mode = new ModeDef(name);
954   mode_defs_[mode->name()] = mode;
955   return mode;
956 }
957 
958 ModeDef *
findModeDef(const char * name)959 LibertyCell::findModeDef(const char *name)
960 {
961   return mode_defs_.findKey(name);
962 }
963 
964 void
setScaleFactors(ScaleFactors * scale_factors)965 LibertyCell::setScaleFactors(ScaleFactors *scale_factors)
966 {
967   scale_factors_ = scale_factors;
968 }
969 
970 void
addBusDcl(BusDcl * bus_dcl)971 LibertyCell::addBusDcl(BusDcl *bus_dcl)
972 {
973   bus_dcls_[bus_dcl->name()] = bus_dcl;
974 }
975 
976 BusDcl *
findBusDcl(const char * name) const977 LibertyCell::findBusDcl(const char *name) const
978 {
979   return bus_dcls_.findKey(name);
980 }
981 
982 void
setArea(float area)983 LibertyCell::setArea(float area)
984 {
985   area_ = area;
986 }
987 
988 void
setDontUse(bool dont_use)989 LibertyCell::setDontUse(bool dont_use)
990 {
991   dont_use_ = dont_use;
992 }
993 
994 void
setIsMacro(bool is_macro)995 LibertyCell::setIsMacro(bool is_macro)
996 {
997   is_macro_ = is_macro;
998 }
999 
1000 void
setIsMemory(bool is_memory)1001 LibertyCell::setIsMemory(bool is_memory)
1002 {
1003   is_memory_ = is_memory;
1004 }
1005 
1006 void
setIsPad(bool is_pad)1007 LibertyCell::LibertyCell::setIsPad(bool is_pad)
1008 {
1009   is_pad_ = is_pad;
1010 }
1011 
1012 void
setIsLevelShifter(bool is_level_shifter)1013 LibertyCell::LibertyCell::setIsLevelShifter(bool is_level_shifter)
1014 {
1015   is_level_shifter_ = is_level_shifter;
1016 }
1017 
1018 void
setInterfaceTiming(bool value)1019 LibertyCell::setInterfaceTiming(bool value)
1020 {
1021   interface_timing_ = value;
1022 }
1023 
1024 bool
isClockGateLatchPosedge() const1025 LibertyCell::isClockGateLatchPosedge() const
1026 {
1027   return clock_gate_type_ == ClockGateType::latch_posedge;
1028 }
1029 
1030 bool
isClockGateLatchNegedge() const1031 LibertyCell::isClockGateLatchNegedge() const
1032 {
1033   return clock_gate_type_ == ClockGateType::latch_posedge;
1034 }
1035 
1036 bool
isClockGateOther() const1037 LibertyCell::isClockGateOther() const
1038 {
1039   return clock_gate_type_ == ClockGateType::other;
1040 }
1041 
1042 bool
isClockGate() const1043 LibertyCell::isClockGate() const
1044 {
1045   return clock_gate_type_ != ClockGateType::none;
1046 }
1047 
1048 void
setClockGateType(ClockGateType type)1049 LibertyCell::setClockGateType(ClockGateType type)
1050 {
1051   clock_gate_type_ = type;
1052 }
1053 
1054 bool
isBuffer() const1055 LibertyCell::isBuffer() const
1056 {
1057   LibertyPort *input;
1058   LibertyPort *output;
1059   bufferPorts(input, output);
1060   return input && output
1061     && hasBufferFunc(input, output)
1062     && !is_level_shifter_;
1063 }
1064 
1065 bool
hasBufferFunc(const LibertyPort * input,const LibertyPort * output) const1066 LibertyCell::hasBufferFunc(const LibertyPort *input,
1067 			   const LibertyPort *output) const
1068 {
1069   FuncExpr *func = output->function();
1070   return func
1071     && func->op() == FuncExpr::op_port
1072     && func->port() == input;
1073 }
1074 
1075 bool
isInverter() const1076 LibertyCell::isInverter() const
1077 {
1078   LibertyPort *input;
1079   LibertyPort *output;
1080   bufferPorts(input, output);
1081   return input && output
1082     && hasInverterFunc(input, output);
1083 }
1084 
1085 bool
hasInverterFunc(const LibertyPort * input,const LibertyPort * output) const1086 LibertyCell::hasInverterFunc(const LibertyPort *input,
1087 			     const LibertyPort *output) const
1088 {
1089   FuncExpr *func = output->function();
1090   return func
1091     && func->op() == FuncExpr::op_not
1092     && func->left()->op() == FuncExpr::op_port
1093     && func->left()->port() == input;
1094 }
1095 
1096 void
bufferPorts(LibertyPort * & input,LibertyPort * & output) const1097 LibertyCell::bufferPorts(// Return values.
1098 			 LibertyPort *&input,
1099 			 LibertyPort *&output) const
1100 {
1101   input = nullptr;
1102   output = nullptr;
1103   for (ConcretePort *cport : ports_) {
1104     LibertyPort *port = static_cast<LibertyPort*>(cport);
1105     PortDirection *dir = port->direction();
1106     if (dir->isInput()) {
1107       if (input) {
1108 	// More than one input.
1109 	input = nullptr;
1110 	output = nullptr;
1111 	break;
1112       }
1113       input = port;
1114     }
1115     else if (dir->isOutput()) {
1116       if (output) {
1117 	// More than one output.
1118 	input = nullptr;
1119 	output = nullptr;
1120 	break;
1121       }
1122       output = port;
1123     }
1124     else if (!dir->isPowerGround()) {
1125 	input = nullptr;
1126 	output = nullptr;
1127 	break;
1128     }
1129   }
1130 }
1131 
1132 unsigned
addTimingArcSet(TimingArcSet * arc_set)1133 LibertyCell::addTimingArcSet(TimingArcSet *arc_set)
1134 {
1135   int set_index = timing_arc_sets_.size();
1136   if (set_index > timing_arc_set_index_max)
1137     criticalError(235, "timing arc set max index exceeded");
1138   timing_arc_sets_.push_back(arc_set);
1139 
1140   LibertyPort *from = arc_set->from();
1141   TimingRole *role = arc_set->role();
1142   if (role == TimingRole::regClkToQ()
1143       || role == TimingRole::latchEnToQ())
1144     from->setIsRegClk(true);
1145   if (role->isTimingCheck())
1146     from->setIsCheckClk(true);
1147   return set_index;
1148 }
1149 
1150 void
addTimingArcAttrs(TimingArcAttrs * attrs)1151 LibertyCell::addTimingArcAttrs(TimingArcAttrs *attrs)
1152 {
1153   timing_arc_attrs_.push_back(attrs);
1154 }
1155 
1156 void
addInternalPower(InternalPower * power)1157 LibertyCell::addInternalPower(InternalPower *power)
1158 {
1159   internal_powers_.push_back(power);
1160   port_internal_powers_[power->port()].push_back(power);
1161 }
1162 
1163 InternalPowerSeq *
internalPowers()1164 LibertyCell::internalPowers()
1165 {
1166   return &internal_powers_;
1167 }
1168 
1169 InternalPowerSeq *
internalPowers(const LibertyPort * port)1170 LibertyCell::internalPowers(const LibertyPort *port)
1171 {
1172   return &port_internal_powers_[port];
1173 }
1174 
1175 void
addInternalPowerAttrs(InternalPowerAttrs * attrs)1176 LibertyCell::addInternalPowerAttrs(InternalPowerAttrs *attrs)
1177 {
1178   internal_power_attrs_.push_back(attrs);
1179 }
1180 
1181 void
deleteInternalPowerAttrs()1182 LibertyCell::deleteInternalPowerAttrs()
1183 {
1184   for (auto attrs : internal_power_attrs_) {
1185     attrs->deleteContents();
1186     delete attrs;
1187   }
1188 }
1189 
1190 void
addLeakagePower(LeakagePower * power)1191 LibertyCell::addLeakagePower(LeakagePower *power)
1192 {
1193   leakage_powers_.push_back(power);
1194 }
1195 
1196 void
setLeakagePower(float leakage)1197 LibertyCell::setLeakagePower(float leakage)
1198 {
1199   leakage_power_ = leakage;
1200   leakage_power_exists_ = true;
1201 }
1202 
1203 void
leakagePower(float & leakage,bool & exists) const1204 LibertyCell::leakagePower(// Return values.
1205 			  float &leakage,
1206 			  bool &exists) const
1207 {
1208   leakage = leakage_power_;
1209   exists = leakage_power_exists_;
1210 }
1211 
1212 void
finish(bool infer_latches,Report * report,Debug * debug)1213 LibertyCell::finish(bool infer_latches,
1214 		    Report *report,
1215 		    Debug *debug)
1216 {
1217   translatePresetClrCheckRoles();
1218   makeTimingArcMap(report);
1219   makeTimingArcPortMaps();
1220   findDefaultCondArcs();
1221   makeLatchEnables(report, debug);
1222   if (infer_latches
1223       && !interface_timing_)
1224     inferLatchRoles(debug);
1225 }
1226 
1227 void
findDefaultCondArcs()1228 LibertyCell::findDefaultCondArcs()
1229 {
1230   for (auto port_pair_set : port_timing_arc_set_map_) {
1231     TimingArcSetSeq *sets = port_pair_set.second;
1232     bool has_cond_arcs = false;
1233     for (auto set : *sets) {
1234       if (set->cond()) {
1235 	has_cond_arcs = true;
1236 	break;
1237       }
1238     }
1239     if (has_cond_arcs) {
1240       for (auto set : *sets) {
1241 	if (!set->cond())
1242 	  set->setIsCondDefault(true);
1243       }
1244     }
1245   }
1246 }
1247 
1248 // Timing checks for set/clear pins use setup/hold times.  This
1249 // changes their roles to recovery/removal by finding the set/clear
1250 // pins and then translating the timing check roles.
1251 void
translatePresetClrCheckRoles()1252 LibertyCell::translatePresetClrCheckRoles()
1253 {
1254   LibertyPortSet pre_clr_ports;
1255   for (auto arc_set : timing_arc_sets_) {
1256     if (arc_set->role() == TimingRole::regSetClr())
1257       pre_clr_ports.insert(arc_set->from());
1258   }
1259 
1260   if (!pre_clr_ports.empty()) {
1261     for (auto arc_set : timing_arc_sets_) {
1262       if (pre_clr_ports.findKey(arc_set->to())) {
1263 	if (arc_set->role() == TimingRole::setup())
1264 	  arc_set->setRole(TimingRole::recovery());
1265 	else if (arc_set->role() == TimingRole::hold())
1266 	  arc_set->setRole(TimingRole::removal());
1267       }
1268     }
1269   }
1270 }
1271 
1272 void
makeTimingArcMap(Report *)1273 LibertyCell::makeTimingArcMap(Report *)
1274 {
1275   // Filter duplicate timing arcs, keeping the later definition.
1276   for (auto arc_set : timing_arc_sets_)
1277     // The last definition will be left in the set.
1278     timing_arc_set_map_.insert(arc_set);
1279 
1280   // Prune the arc sets not in the map.
1281   int j = 0;
1282   for (size_t i = 0; i < timing_arc_sets_.size(); i++) {
1283     TimingArcSet *arc_set = timing_arc_sets_[i];
1284     TimingArcSet *match = timing_arc_set_map_.findKey(arc_set);
1285     if (match != arc_set) {
1286       // Unfortunately these errors are common in some brain damaged
1287       // libraries.
1288       // report->warn("cell %s/%s has duplicate %s -> %s %s timing groups.",
1289       // 		   library_->name(),
1290       // 		   name_,
1291       // 		   match->from()->name(),
1292       // 		   match->to()->name(),
1293       // 		   match->role()->asString());
1294       delete arc_set;
1295     }
1296     else
1297       // Shift arc sets down to fill holes left by removed duplicates.
1298       timing_arc_sets_[j++] = arc_set;
1299   }
1300   timing_arc_sets_.resize(j);
1301 
1302   if (timing_arc_set_map_.size() != timing_arc_sets_.size())
1303     criticalError(205, "timing arc count mismatch");
1304 }
1305 
1306 void
makeTimingArcPortMaps()1307 LibertyCell::makeTimingArcPortMaps()
1308 {
1309   for (auto arc_set : timing_arc_sets_) {
1310     LibertyPort *from = arc_set->from();
1311     LibertyPort *to = arc_set->to();
1312     LibertyPortPair port_pair(from, to);
1313     TimingArcSetSeq *sets = port_timing_arc_set_map_.findKey(port_pair);
1314     if (sets == nullptr) {
1315       // First arc set for from/to ports.
1316       sets = new TimingArcSetSeq;
1317       port_timing_arc_set_map_[port_pair] = sets;
1318     }
1319     sets->push_back(arc_set);
1320 
1321     sets = timing_arc_set_from_map_.findKey(from);
1322     if (sets == nullptr) {
1323       sets = new TimingArcSetSeq;
1324       timing_arc_set_from_map_[from] = sets;
1325     }
1326     sets->push_back(arc_set);
1327 
1328     sets = timing_arc_set_to_map_.findKey(to);
1329     if (sets == nullptr) {
1330       sets = new TimingArcSetSeq;
1331       timing_arc_set_to_map_[to] = sets;
1332     }
1333     sets->push_back(arc_set);
1334   }
1335 }
1336 
1337 TimingArcSetSeq *
timingArcSets(const LibertyPort * from,const LibertyPort * to) const1338 LibertyCell::timingArcSets(const LibertyPort *from,
1339 			   const LibertyPort *to) const
1340 {
1341   if (from && to) {
1342     LibertyPortPair port_pair(from, to);
1343     return port_timing_arc_set_map_.findKey(port_pair);
1344   }
1345   else if (from)
1346     return timing_arc_set_from_map_.findKey(from);
1347   else if (to)
1348     return timing_arc_set_to_map_.findKey(to);
1349   else
1350     return nullptr;
1351 }
1352 
1353 TimingArcSet *
findTimingArcSet(TimingArcSet * key) const1354 LibertyCell::findTimingArcSet(TimingArcSet *key) const
1355 {
1356   return timing_arc_set_map_.findKey(key);
1357 }
1358 
1359 TimingArcSet *
findTimingArcSet(unsigned arc_set_index) const1360 LibertyCell::findTimingArcSet(unsigned arc_set_index) const
1361 {
1362   return timing_arc_sets_[arc_set_index];
1363 }
1364 
1365 size_t
timingArcSetCount() const1366 LibertyCell::timingArcSetCount() const
1367 {
1368   return timing_arc_sets_.size();
1369 }
1370 
1371 bool
hasTimingArcs(LibertyPort * port) const1372 LibertyCell::hasTimingArcs(LibertyPort *port) const
1373 {
1374   return timing_arc_set_from_map_.findKey(port)
1375     || timing_arc_set_to_map_.findKey(port);
1376 }
1377 
1378 void
makeSequential(int size,bool is_register,FuncExpr * clk,FuncExpr * data,FuncExpr * clear,FuncExpr * preset,LogicValue clr_preset_out,LogicValue clr_preset_out_inv,LibertyPort * output,LibertyPort * output_inv)1379 LibertyCell::makeSequential(int size,
1380 			    bool is_register,
1381 			    FuncExpr *clk,
1382 			    FuncExpr *data,
1383 			    FuncExpr *clear,
1384 			    FuncExpr *preset,
1385 			    LogicValue clr_preset_out,
1386 			    LogicValue clr_preset_out_inv,
1387 			    LibertyPort *output,
1388 			    LibertyPort *output_inv)
1389 {
1390   for (int bit = 0; bit < size; bit++) {
1391     FuncExpr *clk_bit = nullptr;
1392     if (clk)
1393       clk_bit = clk->bitSubExpr(bit);
1394     FuncExpr *data_bit = nullptr;
1395     if (data)
1396       data_bit = data->bitSubExpr(bit);
1397     FuncExpr *clear_bit = nullptr;
1398     if (clear)
1399       clear_bit = clear->bitSubExpr(bit);
1400     FuncExpr *preset_bit = nullptr;
1401     if (preset)
1402       preset_bit = preset->bitSubExpr(bit);
1403     LibertyPort *out_bit = output;
1404     if (output && output->hasMembers())
1405       out_bit = output->findLibertyMember(bit);
1406     LibertyPort *out_inv_bit = output_inv;
1407     if (output_inv && output_inv->hasMembers())
1408       out_inv_bit = output_inv->findLibertyMember(bit);
1409     Sequential *seq = new Sequential(is_register, clk_bit, data_bit,
1410 				     clear_bit,preset_bit,
1411 				     clr_preset_out, clr_preset_out_inv,
1412 				     out_bit, out_inv_bit);
1413     sequentials_.push_back(seq);
1414     port_to_seq_map_[seq->output()] = seq;
1415     port_to_seq_map_[seq->outputInv()] = seq;
1416   }
1417 }
1418 
1419 Sequential *
outputPortSequential(LibertyPort * port)1420 LibertyCell::outputPortSequential(LibertyPort *port)
1421 {
1422   return port_to_seq_map_.findKey(port);
1423 }
1424 
1425 bool
hasSequentials() const1426 LibertyCell::hasSequentials() const
1427 {
1428   return !sequentials_.empty();
1429 }
1430 
1431 void
addScaledCell(OperatingConditions * op_cond,LibertyCell * scaled_cell)1432 LibertyCell::addScaledCell(OperatingConditions *op_cond,
1433 			   LibertyCell *scaled_cell)
1434 {
1435   scaled_cells_[op_cond] = scaled_cell;
1436 
1437   LibertyCellPortBitIterator port_iter1(this);
1438   LibertyCellPortBitIterator port_iter2(scaled_cell);
1439   while (port_iter1.hasNext() && port_iter2.hasNext()) {
1440     LibertyPort *port = port_iter1.next();
1441     LibertyPort *scaled_port = port_iter2.next();
1442     port->addScaledPort(op_cond, scaled_port);
1443   }
1444 
1445   LibertyCellTimingArcSetIterator set_iter1(this);
1446   LibertyCellTimingArcSetIterator set_iter2(scaled_cell);
1447   while (set_iter1.hasNext() && set_iter2.hasNext()) {
1448     TimingArcSet *arc_set1 = set_iter1.next();
1449     TimingArcSet *arc_set2 = set_iter2.next();
1450     TimingArcSetArcIterator arc_iter1(arc_set1);
1451     TimingArcSetArcIterator arc_iter2(arc_set2);
1452     while (arc_iter1.hasNext() && arc_iter2.hasNext()) {
1453       TimingArc *arc = arc_iter1.next();
1454       TimingArc *scaled_arc = arc_iter2.next();
1455       if (TimingArc::equiv(arc, scaled_arc)) {
1456 	TimingModel *model = scaled_arc->model();
1457 	model->setIsScaled(true);
1458 	arc->addScaledModel(op_cond, model);
1459       }
1460     }
1461   }
1462 }
1463 
1464 void
setLibertyLibrary(LibertyLibrary * library)1465 LibertyCell::setLibertyLibrary(LibertyLibrary *library)
1466 {
1467   liberty_library_ = library;
1468   library_ = library;
1469 }
1470 
1471 void
setHasInferedRegTimingArcs(bool infered)1472 LibertyCell::setHasInferedRegTimingArcs(bool infered)
1473 {
1474   has_infered_reg_timing_arcs_ = infered;
1475 }
1476 
1477 void
setTestCell(TestCell * test)1478 LibertyCell::setTestCell(TestCell *test)
1479 {
1480   test_cell_ = test;
1481 }
1482 
1483 void
setIsDisabledConstraint(bool is_disabled)1484 LibertyCell::setIsDisabledConstraint(bool is_disabled)
1485 {
1486   is_disabled_constraint_ = is_disabled;
1487 }
1488 
1489 LibertyCell *
cornerCell(int ap_index)1490 LibertyCell::cornerCell(int ap_index)
1491 {
1492   if (ap_index < static_cast<int>(corner_cells_.size()))
1493     return corner_cells_[ap_index];
1494   else
1495     return nullptr;
1496 }
1497 
1498 void
setCornerCell(LibertyCell * corner_cell,int ap_index)1499 LibertyCell::setCornerCell(LibertyCell *corner_cell,
1500 			   int ap_index)
1501 {
1502   if (ap_index >= static_cast<int>(corner_cells_.size()))
1503     corner_cells_.resize(ap_index + 1);
1504   corner_cells_[ap_index] = corner_cell;
1505 }
1506 
1507 ////////////////////////////////////////////////////////////////
1508 
1509 float
ocvArcDepth() const1510 LibertyCell::ocvArcDepth() const
1511 {
1512   return ocv_arc_depth_;
1513 }
1514 
1515 void
setOcvArcDepth(float depth)1516 LibertyCell::setOcvArcDepth(float depth)
1517 {
1518   ocv_arc_depth_ = depth;
1519 }
1520 
1521 OcvDerate *
ocvDerate() const1522 LibertyCell::ocvDerate() const
1523 {
1524   if (ocv_derate_)
1525     return ocv_derate_;
1526   else
1527     return liberty_library_->defaultOcvDerate();
1528 }
1529 
1530 void
setOcvDerate(OcvDerate * derate)1531 LibertyCell::setOcvDerate(OcvDerate *derate)
1532 {
1533   ocv_derate_ = derate;
1534 }
1535 
1536 OcvDerate *
findOcvDerate(const char * derate_name)1537 LibertyCell::findOcvDerate(const char *derate_name)
1538 {
1539   return ocv_derate_map_.findKey(derate_name);
1540 }
1541 
1542 void
addOcvDerate(OcvDerate * derate)1543 LibertyCell::addOcvDerate(OcvDerate *derate)
1544 {
1545   ocv_derate_map_[derate->name()] = derate;
1546 }
1547 
1548 ////////////////////////////////////////////////////////////////
1549 
LibertyCellTimingArcSetIterator(const LibertyCell * cell)1550 LibertyCellTimingArcSetIterator::LibertyCellTimingArcSetIterator(const LibertyCell *cell) :
1551   TimingArcSetSeq::ConstIterator(&cell->timing_arc_sets_)
1552 {
1553 }
1554 
LibertyCellTimingArcSetIterator(const LibertyCell * cell,const LibertyPort * from,const LibertyPort * to)1555 LibertyCellTimingArcSetIterator::LibertyCellTimingArcSetIterator(const LibertyCell *cell,
1556 								 const LibertyPort *from,
1557 								 const LibertyPort *to):
1558   TimingArcSetSeq::ConstIterator(cell->timingArcSets(from, to))
1559 {
1560 }
1561 
1562 ////////////////////////////////////////////////////////////////
1563 
1564 // Latch enable port/function for a latch D->Q timing arc set.
1565 class LatchEnable
1566 {
1567 public:
1568   LatchEnable(LibertyPort *data,
1569 	      LibertyPort *enable,
1570 	      RiseFall *enable_rf,
1571 	      FuncExpr *enable_func,
1572 	      LibertyPort *output,
1573 	      TimingArcSet *d_to_q,
1574 	      TimingArcSet *en_to_q,
1575 	      TimingArcSet *setup_check);
data() const1576   LibertyPort *data() const { return data_; }
output() const1577   LibertyPort *output() const { return output_; }
enable() const1578   LibertyPort *enable() const { return enable_; }
enableFunc() const1579   FuncExpr *enableFunc() const { return enable_func_; }
enableTransition() const1580   RiseFall *enableTransition() const { return enable_rf_; }
dToQ() const1581   TimingArcSet *dToQ() const { return d_to_q_; }
enToQ() const1582   TimingArcSet *enToQ() const { return en_to_q_; }
setupCheck() const1583   TimingArcSet *setupCheck() const { return setup_check_; }
1584 
1585 private:
1586   DISALLOW_COPY_AND_ASSIGN(LatchEnable);
1587 
1588   LibertyPort *data_;
1589   LibertyPort *enable_;
1590   RiseFall *enable_rf_;
1591   FuncExpr *enable_func_;
1592   LibertyPort *output_;
1593   TimingArcSet *d_to_q_;
1594   TimingArcSet *en_to_q_;
1595   TimingArcSet *setup_check_;
1596 };
1597 
LatchEnable(LibertyPort * data,LibertyPort * enable,RiseFall * enable_rf,FuncExpr * enable_func,LibertyPort * output,TimingArcSet * d_to_q,TimingArcSet * en_to_q,TimingArcSet * setup_check)1598 LatchEnable::LatchEnable(LibertyPort *data,
1599 			 LibertyPort *enable,
1600 			 RiseFall *enable_rf,
1601 			 FuncExpr *enable_func,
1602 			 LibertyPort *output,
1603 			 TimingArcSet *d_to_q,
1604 			 TimingArcSet *en_to_q,
1605 			 TimingArcSet *setup_check) :
1606   data_(data),
1607   enable_(enable),
1608   enable_rf_(enable_rf),
1609   enable_func_(enable_func),
1610   output_(output),
1611   d_to_q_(d_to_q),
1612   en_to_q_(en_to_q),
1613   setup_check_(setup_check)
1614 {
1615 }
1616 
1617 // Latch enable port/function for a latch D->Q timing arc set.
1618 // This augments cell timing data by linking enables to D->Q arcs.
1619 // Use timing arcs rather than sequentials (because they are optional).
1620 void
makeLatchEnables(Report * report,Debug * debug)1621 LibertyCell::makeLatchEnables(Report *report,
1622 			      Debug *debug)
1623 {
1624   if (hasSequentials()
1625       || hasInferedRegTimingArcs()) {
1626     for (auto en_to_q : timing_arc_sets_) {
1627       if (en_to_q->role() == TimingRole::latchEnToQ()) {
1628 	LibertyPort *en = en_to_q->from();
1629 	LibertyPort *q = en_to_q->to();
1630 	LibertyCellTimingArcSetIterator to_iter(this, nullptr, q);
1631 	while (to_iter.hasNext()) {
1632 	  TimingArcSet *d_to_q = to_iter.next();
1633 	  if (d_to_q->role() == TimingRole::latchDtoQ()) {
1634 	    LibertyPort *d = d_to_q->from();
1635 	    LibertyCellTimingArcSetIterator check_iter(this, en, d);
1636 	    while (check_iter.hasNext()) {
1637 	      TimingArcSet *setup_check = check_iter.next();
1638 	      if (setup_check->role() == TimingRole::setup()) {
1639 		LatchEnable *latch_enable = makeLatchEnable(d, en, q, d_to_q,
1640 							    en_to_q,
1641 							    setup_check,
1642 							    debug);
1643 		TimingArcSetArcIterator check_arc_iter(setup_check);
1644 		if (check_arc_iter.hasNext()) {
1645 		  TimingArc *check_arc = check_arc_iter.next();
1646 		  RiseFall *en_rf = latch_enable->enableTransition();
1647 		  RiseFall *check_rf = check_arc->fromTrans()->asRiseFall();
1648 		  if (check_rf == en_rf) {
1649 		    report->warn(4, "cell %s/%s %s -> %s latch enable %s_edge timing arc is inconsistent with %s -> %s setup_%s check.",
1650 				 library_->name(),
1651 				 name_,
1652 				 en->name(),
1653 				 q->name(),
1654 				 en_rf == RiseFall::rise()?"rising":"falling",
1655 				 en->name(),
1656 				 d->name(),
1657 				 check_rf==RiseFall::rise()?"rising":"falling");
1658 		  }
1659 		  FuncExpr *en_func = latch_enable->enableFunc();
1660 		  if (en_func) {
1661 		    TimingSense en_sense = en_func->portTimingSense(en);
1662 		    if (en_sense == TimingSense::positive_unate
1663 			&& en_rf != RiseFall::rise())
1664 		      report->warn(5, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.",
1665 				   library_->name(),
1666 				   name_,
1667 				   en->name(),
1668 				   q->name(),
1669 				   en_rf == RiseFall::rise()?"rising":"falling");
1670 		    else if (en_sense == TimingSense::negative_unate
1671 			     && en_rf != RiseFall::fall())
1672 		      report->warn(6, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.",
1673 				   library_->name(),
1674 				   name_,
1675 				   en->name(),
1676 				   q->name(),
1677 				   en_rf == RiseFall::rise()?"rising":"falling");
1678 		  }
1679 		  break;
1680 		}
1681 	      }
1682 	    }
1683 	  }
1684 	}
1685       }
1686     }
1687   }
1688 }
1689 
1690 FuncExpr *
findLatchEnableFunc(LibertyPort * data,LibertyPort * enable) const1691 LibertyCell::findLatchEnableFunc(LibertyPort *data,
1692 				 LibertyPort *enable) const
1693 {
1694   for (auto seq : sequentials_) {
1695     if (seq->isLatch()
1696 	&& seq->data()
1697 	&& seq->data()->hasPort(data)
1698 	&& seq->clock()
1699 	&& seq->clock()->hasPort(enable))
1700       return seq->clock();
1701   }
1702   return nullptr;
1703 }
1704 
1705 LatchEnable *
makeLatchEnable(LibertyPort * d,LibertyPort * en,LibertyPort * q,TimingArcSet * d_to_q,TimingArcSet * en_to_q,TimingArcSet * setup_check,Debug * debug)1706 LibertyCell::makeLatchEnable(LibertyPort *d,
1707 			     LibertyPort *en,
1708 			     LibertyPort *q,
1709 			     TimingArcSet *d_to_q,
1710 			     TimingArcSet *en_to_q,
1711 			     TimingArcSet *setup_check,
1712 			     Debug *debug)
1713 {
1714   RiseFall *en_rf = en_to_q->isRisingFallingEdge();
1715   FuncExpr *en_func = findLatchEnableFunc(d, en);
1716   LatchEnable *latch_enable = new LatchEnable(d, en, en_rf, en_func, q,
1717 					      d_to_q, en_to_q, setup_check);
1718   // Multiple enables for D->Q pairs are not supported.
1719   if (latch_d_to_q_map_[d_to_q])
1720     delete latch_d_to_q_map_[d_to_q];
1721   latch_d_to_q_map_[d_to_q] = latch_enable;
1722   latch_check_map_[setup_check] = latch_enable;
1723   latch_data_ports_.insert(d);
1724   debugPrint(debug, "liberty", 2, "latch d=%s en=%s q=%s",
1725              d->name(), en->name(), q->name());
1726   return latch_enable;
1727 }
1728 
1729 void
inferLatchRoles(Debug * debug)1730 LibertyCell::inferLatchRoles(Debug *debug)
1731 {
1732   if (hasInferedRegTimingArcs()) {
1733     // Hunt down potential latch D/EN/Q triples.
1734     LatchEnableSet latch_enables;
1735     LibertyCellTimingArcSetIterator set_iter(this);
1736     while (set_iter.hasNext()) {
1737       TimingArcSet *en_to_q = set_iter.next();
1738       // Locate potential d->q arcs from reg clk->q arcs.
1739       if (en_to_q->role() == TimingRole::regClkToQ()) {
1740 	LibertyPort *en = en_to_q->from();
1741 	LibertyPort *q = en_to_q->to();
1742 	LibertyCellTimingArcSetIterator to_iter(this, nullptr, q);
1743 	while (to_iter.hasNext()) {
1744 	  TimingArcSet *d_to_q = to_iter.next();
1745 	  // Look for combinational d->q arcs.
1746 	  TimingRole *d_to_q_role = d_to_q->role();
1747 	  if ((d_to_q_role == TimingRole::combinational()
1748 	       && ((d_to_q->arcCount() == 2
1749 		    && (d_to_q->sense() == TimingSense::positive_unate
1750 			|| d_to_q->sense() == TimingSense::negative_unate))
1751 		   || (d_to_q->arcCount() == 4)))
1752 	      // Previously identified as D->Q arc.
1753 	      || d_to_q_role == TimingRole::latchDtoQ()) {
1754 	    LibertyPort *d = d_to_q->from();
1755 	    // Check for setup check from en -> d.
1756 	    LibertyCellTimingArcSetIterator check_iter(this, en, d);
1757 	    while (check_iter.hasNext()) {
1758 	      TimingArcSet *setup_check = check_iter.next();
1759 	      if (setup_check->role() == TimingRole::setup()) {
1760 		makeLatchEnable(d, en, q, d_to_q, en_to_q, setup_check, debug);
1761 		d_to_q->setRole(TimingRole::latchDtoQ());
1762 		en_to_q->setRole(TimingRole::latchEnToQ());
1763 	      }
1764 	    }
1765 	  }
1766 	}
1767       }
1768     }
1769   }
1770 }
1771 
1772 bool
isLatchData(LibertyPort * port)1773 LibertyCell::isLatchData(LibertyPort *port)
1774 {
1775   return latch_data_ports_.hasKey(port);
1776 }
1777 
1778 void
latchEnable(TimingArcSet * d_to_q_set,LibertyPort * & enable_port,FuncExpr * & enable_func,RiseFall * & enable_rf) const1779 LibertyCell::latchEnable(TimingArcSet *d_to_q_set,
1780 			 // Return values.
1781 			 LibertyPort *&enable_port,
1782 			 FuncExpr *&enable_func,
1783 			 RiseFall *&enable_rf) const
1784 {
1785   enable_port = nullptr;
1786   LatchEnable *latch_enable = latch_d_to_q_map_.findKey(d_to_q_set);
1787   if (latch_enable) {
1788     enable_port = latch_enable->enable();
1789     enable_func = latch_enable->enableFunc();
1790     enable_rf = latch_enable->enableTransition();
1791   }
1792 }
1793 
1794 RiseFall *
latchCheckEnableTrans(TimingArcSet * check_set)1795 LibertyCell::latchCheckEnableTrans(TimingArcSet *check_set)
1796 {
1797   LatchEnable *latch_enable = latch_check_map_.findKey(check_set);
1798   if (latch_enable)
1799     return latch_enable->enableTransition();
1800   else
1801     return nullptr;
1802 }
1803 
1804 ////////////////////////////////////////////////////////////////
1805 
LibertyCellPortIterator(const LibertyCell * cell)1806 LibertyCellPortIterator::LibertyCellPortIterator(const LibertyCell *cell) :
1807   iter_(cell->ports_)
1808 {
1809 }
1810 
1811 bool
hasNext()1812 LibertyCellPortIterator::hasNext()
1813 {
1814   return iter_.hasNext();
1815 }
1816 
1817 LibertyPort *
next()1818 LibertyCellPortIterator::next()
1819 {
1820   return static_cast<LibertyPort*>(iter_.next());
1821 }
1822 
1823 ////////////////////////////////////////////////////////////////
1824 
LibertyCellPortBitIterator(const LibertyCell * cell)1825 LibertyCellPortBitIterator::LibertyCellPortBitIterator(const LibertyCell *cell):
1826   iter_(cell->portBitIterator())
1827 {
1828 }
1829 
~LibertyCellPortBitIterator()1830 LibertyCellPortBitIterator::~LibertyCellPortBitIterator()
1831 {
1832   delete iter_;
1833 }
1834 
1835 bool
hasNext()1836 LibertyCellPortBitIterator::hasNext()
1837 {
1838   return iter_->hasNext();
1839 }
1840 
1841 LibertyPort *
next()1842 LibertyCellPortBitIterator::next()
1843 {
1844   return static_cast<LibertyPort*>(iter_->next());
1845 }
1846 
1847 ////////////////////////////////////////////////////////////////
1848 
LibertyPort(LibertyCell * cell,const char * name,bool is_bus,int from_index,int to_index,bool is_bundle,ConcretePortSeq * members)1849 LibertyPort::LibertyPort(LibertyCell *cell,
1850 			 const char *name,
1851 			 bool is_bus,
1852 			 int from_index,
1853 			 int to_index,
1854 			 bool is_bundle,
1855 			 ConcretePortSeq *members) :
1856   ConcretePort(cell, name, is_bus, from_index, to_index, is_bundle, members),
1857   liberty_cell_(cell),
1858   function_(nullptr),
1859   tristate_enable_(nullptr),
1860   scaled_ports_(nullptr),
1861   fanout_load_(0.0),
1862   fanout_load_exists_(false),
1863   min_period_(0.0),
1864   pulse_clk_trigger_(nullptr),
1865   pulse_clk_sense_(nullptr),
1866   related_ground_pin_(nullptr),
1867   related_power_pin_(nullptr),
1868   min_pulse_width_exists_(false),
1869   min_period_exists_(false),
1870   is_clk_(false),
1871   is_reg_clk_(false),
1872   is_check_clk_(false),
1873   is_clk_gate_clk_pin_(false),
1874   is_clk_gate_enable_pin_(false),
1875   is_clk_gate_out_pin_(false),
1876   is_pll_feedback_pin_(false),
1877   is_disabled_constraint_(false)
1878 {
1879   liberty_port_ = this;
1880   min_pulse_width_[RiseFall::riseIndex()] = 0.0;
1881   min_pulse_width_[RiseFall::fallIndex()] = 0.0;
1882 }
1883 
~LibertyPort()1884 LibertyPort::~LibertyPort()
1885 {
1886   if (function_)
1887     function_->deleteSubexprs();
1888   if (tristate_enable_)
1889     tristate_enable_->deleteSubexprs();
1890   delete scaled_ports_;
1891   stringDelete(related_ground_pin_);
1892   stringDelete(related_power_pin_);
1893 }
1894 
1895 void
setDirection(PortDirection * dir)1896 LibertyPort::setDirection(PortDirection *dir)
1897 {
1898   ConcretePort::setDirection(dir);
1899   if (dir->isInternal())
1900     liberty_cell_->setHasInternalPorts(true);
1901 }
1902 
1903 LibertyPort *
findLibertyMember(int index) const1904 LibertyPort::findLibertyMember(int index) const
1905 {
1906   return static_cast<LibertyPort*>(findMember(index));
1907 }
1908 
1909 LibertyPort *
findLibertyBusBit(int index) const1910 LibertyPort::findLibertyBusBit(int index) const
1911 {
1912   return static_cast<LibertyPort*>(findBusBit(index));
1913 }
1914 
1915 void
setCapacitance(float cap)1916 LibertyPort::setCapacitance(float cap)
1917 {
1918   setCapacitance(RiseFall::rise(), MinMax::min(), cap);
1919   setCapacitance(RiseFall::fall(), MinMax::min(), cap);
1920   setCapacitance(RiseFall::rise(), MinMax::max(), cap);
1921   setCapacitance(RiseFall::fall(), MinMax::max(), cap);
1922 }
1923 
1924 void
setCapacitance(const RiseFall * rf,const MinMax * min_max,float cap)1925 LibertyPort::setCapacitance(const RiseFall *rf,
1926 			    const MinMax *min_max,
1927 			    float cap)
1928 {
1929   capacitance_.setValue(rf, min_max, cap);
1930   if (hasMembers()) {
1931     LibertyPortMemberIterator member_iter(this);
1932     while (member_iter.hasNext()) {
1933       LibertyPort *port_bit = member_iter.next();
1934       port_bit->setCapacitance(rf, min_max, cap);
1935     }
1936   }
1937 }
1938 
1939 float
capacitance() const1940 LibertyPort::capacitance() const
1941 {
1942   float cap;
1943   bool exists;
1944   capacitance_.maxValue(cap, exists);
1945   if (exists)
1946     return cap;
1947   else
1948     return 0.0;
1949 }
1950 
1951 float
capacitance(const MinMax * min_max) const1952 LibertyPort::capacitance(const MinMax *min_max) const
1953 {
1954   return capacitance_.value(min_max);
1955 }
1956 
1957 float
capacitance(const RiseFall * rf,const MinMax * min_max) const1958 LibertyPort::capacitance(const RiseFall *rf,
1959 			 const MinMax *min_max) const
1960 {
1961   float cap;
1962   bool exists;
1963   capacitance_.value(rf, min_max, cap, exists);
1964   if (exists)
1965     return cap;
1966   else
1967     return 0.0;
1968 }
1969 
1970 void
capacitance(const RiseFall * rf,const MinMax * min_max,float & cap,bool & exists) const1971 LibertyPort::capacitance(const RiseFall *rf,
1972 			 const MinMax *min_max,
1973 			 // Return values.
1974 			 float &cap,
1975 			 bool &exists) const
1976 {
1977   capacitance_.value(rf, min_max, cap, exists);
1978 }
1979 
1980 float
capacitance(const RiseFall * rf,const MinMax * min_max,const OperatingConditions * op_cond,const Pvt * pvt) const1981 LibertyPort::capacitance(const RiseFall *rf,
1982 			 const MinMax *min_max,
1983 			 const OperatingConditions *op_cond,
1984 			 const Pvt *pvt) const
1985 {
1986   if (scaled_ports_) {
1987     LibertyPort *scaled_port = (*scaled_ports_)[op_cond];
1988     // Scaled capacitance is not derated because scale factors are wrt
1989     // nominal pvt.
1990     if (scaled_port)
1991       return scaled_port->capacitance(rf, min_max);
1992   }
1993   LibertyLibrary *lib = liberty_cell_->libertyLibrary();
1994   float cap = capacitance(rf, min_max);
1995   return cap * lib->scaleFactor(ScaleFactorType::pin_cap, liberty_cell_, pvt);
1996 }
1997 
1998 bool
capacitanceIsOneValue() const1999 LibertyPort::capacitanceIsOneValue() const
2000 {
2001   return capacitance_.isOneValue();
2002 }
2003 
2004 ////////////////////////////////////////////////////////////////
2005 
2006 float
driveResistance() const2007 LibertyPort::driveResistance() const
2008 {
2009   return driveResistance(nullptr, MinMax::max());
2010 }
2011 
2012 // Min/max "drive" for all cell timing arcs.
2013 float
driveResistance(const RiseFall * rf,const MinMax * min_max) const2014 LibertyPort::driveResistance(const RiseFall *rf,
2015 			     const MinMax *min_max) const
2016 {
2017   float max_drive = min_max->initValue();
2018   bool found_drive = false;
2019   LibertyCellTimingArcSetIterator set_iter(liberty_cell_, nullptr, this);
2020   while (set_iter.hasNext()) {
2021     TimingArcSet *set = set_iter.next();
2022     if (!set->role()->isTimingCheck()) {
2023       TimingArcSetArcIterator arc_iter(set);
2024       while (arc_iter.hasNext()) {
2025 	TimingArc *arc = arc_iter.next();
2026 	if (rf == nullptr
2027 	    || arc->toTrans()->asRiseFall() == rf) {
2028           float drive = arc->driveResistance();
2029           if (drive > 0.0) {
2030             if (min_max->compare(drive, max_drive))
2031               max_drive = drive;
2032 	    found_drive = true;
2033 	  }
2034 	}
2035       }
2036     }
2037   }
2038   if (found_drive)
2039     return max_drive;
2040   else
2041     return 0.0;
2042 }
2043 
2044 ArcDelay
intrinsicDelay(const StaState * sta) const2045 LibertyPort::intrinsicDelay(const StaState *sta) const
2046 {
2047   return intrinsicDelay(nullptr, MinMax::max(), sta);
2048 }
2049 
2050 ArcDelay
intrinsicDelay(const RiseFall * rf,const MinMax * min_max,const StaState * sta) const2051 LibertyPort::intrinsicDelay(const RiseFall *rf,
2052 			    const MinMax *min_max,
2053                             const StaState *sta) const
2054 {
2055   ArcDelay max_delay = min_max->initValue();
2056   bool found_delay = false;
2057   LibertyCellTimingArcSetIterator set_iter(liberty_cell_, nullptr, this);
2058   while (set_iter.hasNext()) {
2059     TimingArcSet *set = set_iter.next();
2060     if (!set->role()->isTimingCheck()) {
2061       TimingArcSetArcIterator arc_iter(set);
2062       while (arc_iter.hasNext()) {
2063 	TimingArc *arc = arc_iter.next();
2064 	if (rf == nullptr
2065 	    || arc->toTrans()->asRiseFall() == rf) {
2066           ArcDelay delay = arc->intrinsicDelay();
2067           if (delayGreater(delay, 0.0, sta)) {
2068 	    if (delayGreater(delay, max_delay, min_max, sta))
2069 	      max_delay = delay;
2070 	    found_delay = true;
2071 	  }
2072         }
2073       }
2074     }
2075   }
2076   if (found_delay)
2077     return max_delay;
2078   else
2079     return 0.0;
2080 }
2081 
2082 ////////////////////////////////////////////////////////////////
2083 
2084 void
setFunction(FuncExpr * func)2085 LibertyPort::setFunction(FuncExpr *func)
2086 {
2087   function_ = func;
2088   if (is_bus_ || is_bundle_) {
2089     LibertyPortMemberIterator member_iter(this);
2090     int bit_offset = 0;
2091     while (member_iter.hasNext()) {
2092       LibertyPort *port_bit = member_iter.next();
2093       FuncExpr *sub_expr = (func) ? func->bitSubExpr(bit_offset) : nullptr;
2094       port_bit->setFunction(sub_expr);
2095       bit_offset++;
2096     }
2097   }
2098 }
2099 
2100 void
setTristateEnable(FuncExpr * enable)2101 LibertyPort::setTristateEnable(FuncExpr *enable)
2102 {
2103   tristate_enable_ = enable;
2104   if (hasMembers()) {
2105     LibertyPortMemberIterator member_iter(this);
2106     while (member_iter.hasNext()) {
2107       LibertyPort *port_bit = member_iter.next();
2108       FuncExpr *sub_expr =
2109 	(enable) ? enable->bitSubExpr(port_bit->busBitIndex()) : nullptr;
2110       port_bit->setTristateEnable(sub_expr);
2111     }
2112   }
2113 }
2114 
2115 void
slewLimit(const MinMax * min_max,float & limit,bool & exists) const2116 LibertyPort::slewLimit(const MinMax *min_max,
2117 		       // Return values.
2118 		       float &limit,
2119 		       bool &exists) const
2120 {
2121   slew_limit_.value(min_max, limit, exists);
2122 }
2123 
2124 void
setSlewLimit(float slew,const MinMax * min_max)2125 LibertyPort::setSlewLimit(float slew,
2126 			  const MinMax *min_max)
2127 {
2128   slew_limit_.setValue(min_max, slew);
2129 }
2130 
2131 void
capacitanceLimit(const MinMax * min_max,float & limit,bool & exists) const2132 LibertyPort::capacitanceLimit(const MinMax *min_max,
2133 			      // Return values.
2134 			      float &limit,
2135 			      bool &exists) const
2136 {
2137   return cap_limit_.value(min_max, limit, exists);
2138 }
2139 
2140 void
setCapacitanceLimit(float cap,const MinMax * min_max)2141 LibertyPort::setCapacitanceLimit(float cap,
2142 				 const MinMax *min_max)
2143 {
2144   cap_limit_.setValue(min_max, cap);
2145 }
2146 
2147 void
fanoutLoad(float & fanout_load,bool & exists) const2148 LibertyPort::fanoutLoad(// Return values.
2149 			float &fanout_load,
2150 			bool &exists) const
2151 {
2152   fanout_load = fanout_load_;
2153   exists = fanout_load_exists_;
2154 }
2155 
2156 void
setFanoutLoad(float fanout_load)2157 LibertyPort::setFanoutLoad(float fanout_load)
2158 {
2159   fanout_load_ = fanout_load;
2160   fanout_load_exists_ = true;
2161 }
2162 
2163 void
fanoutLimit(const MinMax * min_max,float & limit,bool & exists) const2164 LibertyPort::fanoutLimit(const MinMax *min_max,
2165 			 // Return values.
2166 			 float &limit,
2167 			 bool &exists) const
2168 {
2169   return fanout_limit_.value(min_max, limit, exists);
2170 }
2171 
2172 void
setFanoutLimit(float fanout,const MinMax * min_max)2173 LibertyPort::setFanoutLimit(float fanout,
2174 			    const MinMax *min_max)
2175 {
2176   fanout_limit_.setValue(min_max, fanout);
2177 }
2178 
2179 void
minPeriod(const OperatingConditions * op_cond,const Pvt * pvt,float & min_period,bool & exists) const2180 LibertyPort::minPeriod(const OperatingConditions *op_cond,
2181 		       const Pvt *pvt,
2182 		       float &min_period,
2183 		       bool &exists) const
2184 {
2185   if (scaled_ports_) {
2186     LibertyPort *scaled_port = (*scaled_ports_)[op_cond];
2187     if (scaled_port) {
2188       scaled_port->minPeriod(min_period, exists);
2189       return;
2190     }
2191   }
2192   LibertyLibrary *lib = liberty_cell_->libertyLibrary();
2193   min_period = min_period_ * lib->scaleFactor(ScaleFactorType::min_period,
2194 					      liberty_cell_, pvt);
2195   exists = min_period_exists_;
2196 }
2197 
2198 void
minPeriod(float & min_period,bool & exists) const2199 LibertyPort::minPeriod(float &min_period,
2200 		       bool &exists) const
2201 {
2202   min_period = min_period_;
2203   exists = min_period_exists_;
2204 }
2205 
2206 void
setMinPeriod(float min_period)2207 LibertyPort::setMinPeriod(float min_period)
2208 {
2209   min_period_ = min_period;
2210   min_period_exists_ = true;
2211 }
2212 
2213 void
minPulseWidth(const RiseFall * hi_low,const OperatingConditions * op_cond,const Pvt * pvt,float & min_width,bool & exists) const2214 LibertyPort::minPulseWidth(const RiseFall *hi_low,
2215 			   const OperatingConditions *op_cond,
2216 			   const Pvt *pvt,
2217 			   float &min_width,
2218 			   bool &exists) const
2219 {
2220   if (scaled_ports_) {
2221     LibertyPort *scaled_port = (*scaled_ports_)[op_cond];
2222     if (scaled_port) {
2223       scaled_port->minPulseWidth(hi_low, min_width, exists);
2224       return;
2225     }
2226   }
2227   int hi_low_index = hi_low->index();
2228   LibertyLibrary *lib = liberty_cell_->libertyLibrary();
2229   min_width = min_pulse_width_[hi_low_index]
2230     * lib->scaleFactor(ScaleFactorType::min_pulse_width, hi_low_index,
2231 		       liberty_cell_, pvt);
2232   exists = min_pulse_width_exists_ & (1 << hi_low_index);
2233 }
2234 
2235 void
minPulseWidth(const RiseFall * hi_low,float & min_width,bool & exists) const2236 LibertyPort::minPulseWidth(const RiseFall *hi_low,
2237 			   float &min_width,
2238 			   bool &exists) const
2239 {
2240   int hi_low_index = hi_low->index();
2241   min_width = min_pulse_width_[hi_low_index];
2242   exists = min_pulse_width_exists_ & (1 << hi_low_index);
2243 }
2244 
2245 void
setMinPulseWidth(RiseFall * hi_low,float min_width)2246 LibertyPort::setMinPulseWidth(RiseFall *hi_low,
2247 			      float min_width)
2248 {
2249   int hi_low_index = hi_low->index();
2250   min_pulse_width_[hi_low_index] = min_width;
2251   min_pulse_width_exists_ |= (1 << hi_low_index);
2252 }
2253 
2254 bool
equiv(const LibertyPort * port1,const LibertyPort * port2)2255 LibertyPort::equiv(const LibertyPort *port1,
2256 		   const LibertyPort *port2)
2257 {
2258   return (port1 == nullptr && port2 == nullptr)
2259     || (port1 != nullptr && port2 != nullptr
2260 	&& stringEq(port1->name(), port2->name())
2261 	&& port1->direction() == port2->direction());
2262 }
2263 
2264 bool
less(const LibertyPort * port1,const LibertyPort * port2)2265 LibertyPort::less(const LibertyPort *port1,
2266 		  const LibertyPort *port2)
2267 {
2268   const char *name1 = port1->name();
2269   const char *name2 = port2->name();
2270   if (stringEq(name1, name2)) {
2271     PortDirection *dir1 = port1->direction();
2272     PortDirection *dir2 = port2->direction();
2273     if (dir1 == dir2) {
2274     }
2275     else
2276       return dir1->index() < dir2->index();
2277   }
2278   return stringLess(name1, name2);
2279 }
2280 
2281 void
addScaledPort(OperatingConditions * op_cond,LibertyPort * scaled_port)2282 LibertyPort::addScaledPort(OperatingConditions *op_cond,
2283 			   LibertyPort *scaled_port)
2284 {
2285   if (scaled_ports_ == nullptr)
2286     scaled_ports_ = new ScaledPortMap;
2287   (*scaled_ports_)[op_cond] = scaled_port;
2288 }
2289 
2290 bool
isClock() const2291 LibertyPort::isClock() const
2292 {
2293   return is_clk_;
2294 }
2295 
2296 void
setIsClock(bool is_clk)2297 LibertyPort::setIsClock(bool is_clk)
2298 {
2299   is_clk_ = is_clk;
2300 }
2301 
2302 void
setIsRegClk(bool is_clk)2303 LibertyPort::setIsRegClk(bool is_clk)
2304 {
2305   is_reg_clk_ = is_clk;
2306 }
2307 
2308 void
setIsCheckClk(bool is_clk)2309 LibertyPort::setIsCheckClk(bool is_clk)
2310 {
2311   is_check_clk_ = is_clk;
2312 }
2313 
2314 void
setIsClockGateClockPin(bool is_clk_gate_clk)2315 LibertyPort::setIsClockGateClockPin(bool is_clk_gate_clk)
2316 {
2317   is_clk_gate_clk_pin_ = is_clk_gate_clk;
2318 }
2319 
2320 void
setIsClockGateEnablePin(bool is_clk_gate_enable)2321 LibertyPort::setIsClockGateEnablePin(bool is_clk_gate_enable)
2322 {
2323   is_clk_gate_enable_pin_ = is_clk_gate_enable;
2324 }
2325 
2326 void
setIsClockGateOutPin(bool is_clk_gate_out)2327 LibertyPort::setIsClockGateOutPin(bool is_clk_gate_out)
2328 {
2329   is_clk_gate_out_pin_ = is_clk_gate_out;
2330 }
2331 
2332 void
setIsPllFeedbackPin(bool is_pll_feedback_pin)2333 LibertyPort::setIsPllFeedbackPin(bool is_pll_feedback_pin)
2334 {
2335   is_pll_feedback_pin_ = is_pll_feedback_pin;
2336 }
2337 
2338 void
setPulseClk(RiseFall * trigger,RiseFall * sense)2339 LibertyPort::setPulseClk(RiseFall *trigger,
2340 			 RiseFall *sense)
2341 {
2342   pulse_clk_trigger_ = trigger;
2343   pulse_clk_sense_ = sense;
2344 }
2345 
2346 void
setIsDisabledConstraint(bool is_disabled)2347 LibertyPort::setIsDisabledConstraint(bool is_disabled)
2348 {
2349   is_disabled_constraint_ = is_disabled;
2350 }
2351 
2352 LibertyPort *
cornerPort(int ap_index)2353 LibertyPort::cornerPort(int ap_index)
2354 {
2355   if (ap_index < static_cast<int>(corner_ports_.size())) {
2356     LibertyPort *corner_port = corner_ports_[ap_index];
2357     if (corner_port)
2358       return corner_port;
2359   }
2360   return this;
2361 }
2362 
2363 const LibertyPort *
cornerPort(int ap_index) const2364 LibertyPort::cornerPort(int ap_index) const
2365 {
2366   if (ap_index < static_cast<int>(corner_ports_.size())) {
2367     LibertyPort *corner_port = corner_ports_[ap_index];
2368     if (corner_port)
2369       return corner_port;
2370   }
2371   return this;
2372 }
2373 
2374 void
setCornerPort(LibertyPort * corner_port,int ap_index)2375 LibertyPort::setCornerPort(LibertyPort *corner_port,
2376 			   int ap_index)
2377 {
2378   if (ap_index >= static_cast<int>(corner_ports_.size()))
2379     corner_ports_.resize(ap_index + 1);
2380   corner_ports_[ap_index] = corner_port;
2381 }
2382 
2383 void
setRelatedGroundPin(const char * related_ground_pin)2384 LibertyPort::setRelatedGroundPin(const char *related_ground_pin)
2385 {
2386   related_ground_pin_ = stringCopy(related_ground_pin);
2387 }
2388 
2389 void
setRelatedPowerPin(const char * related_power_pin)2390 LibertyPort::setRelatedPowerPin(const char *related_power_pin)
2391 {
2392   related_power_pin_ = stringCopy(related_power_pin);
2393 }
2394 
2395 ////////////////////////////////////////////////////////////////
2396 
2397 void
sortLibertyPortSet(LibertyPortSet * set,LibertyPortSeq & ports)2398 sortLibertyPortSet(LibertyPortSet *set,
2399 		   LibertyPortSeq &ports)
2400 {
2401   LibertyPortSet::Iterator port_iter(set);
2402   while (port_iter.hasNext())
2403     ports.push_back(port_iter.next());
2404   sort(ports, LibertyPortNameLess());
2405 }
2406 
2407 bool
operator ()(const LibertyPort * port1,const LibertyPort * port2) const2408 LibertyPortNameLess::operator()(const LibertyPort *port1,
2409 				const LibertyPort *port2) const
2410 {
2411   return stringLess(port1->name(), port2->name());
2412 }
2413 
2414 bool
operator ()(const LibertyPortPair * pair1,const LibertyPortPair * pair2) const2415 LibertyPortPairLess::operator()(const LibertyPortPair *pair1,
2416 				const LibertyPortPair *pair2) const
2417 {
2418   return pair1->first < pair2->first
2419     || (pair1->first == pair2->first
2420 	&& pair1->second < pair2->second);
2421 }
2422 
2423 bool
operator ()(const LibertyPortPair & pair1,const LibertyPortPair & pair2) const2424 LibertyPortPairLess::operator()(const LibertyPortPair &pair1,
2425 				const LibertyPortPair &pair2) const
2426 {
2427   return pair1.first < pair2.first
2428     || (pair1.first == pair2.first
2429 	&& pair1.second < pair2.second);
2430 }
2431 
2432 ////////////////////////////////////////////////////////////////
2433 
LibertyPortMemberIterator(const LibertyPort * port)2434 LibertyPortMemberIterator::LibertyPortMemberIterator(const LibertyPort *port) :
2435   iter_(port->memberIterator())
2436 {
2437 }
2438 
~LibertyPortMemberIterator()2439 LibertyPortMemberIterator::~LibertyPortMemberIterator()
2440 {
2441   delete iter_;
2442 }
2443 
2444 bool
hasNext()2445 LibertyPortMemberIterator::hasNext()
2446 {
2447   return iter_->hasNext();
2448 }
2449 
2450 LibertyPort *
next()2451 LibertyPortMemberIterator::next()
2452 {
2453   return static_cast<LibertyPort*>(iter_->next());
2454 }
2455 
2456 ////////////////////////////////////////////////////////////////
2457 
BusDcl(const char * name,int from,int to)2458 BusDcl::BusDcl(const char *name,
2459 	       int from,
2460 	       int to) :
2461   name_(stringCopy(name)),
2462   from_(from),
2463   to_(to)
2464 {
2465 }
2466 
~BusDcl()2467 BusDcl::~BusDcl()
2468 {
2469   stringDelete(name_);
2470 }
2471 
2472 ////////////////////////////////////////////////////////////////
2473 
ModeDef(const char * name)2474 ModeDef::ModeDef(const char *name) :
2475   name_(stringCopy(name))
2476 {
2477 }
2478 
~ModeDef()2479 ModeDef::~ModeDef()
2480 {
2481   values_.deleteContents();
2482   stringDelete(name_);
2483 }
2484 
2485 ModeValueDef *
defineValue(const char * value,FuncExpr * cond,const char * sdf_cond)2486 ModeDef::defineValue(const char *value,
2487 		     FuncExpr *cond,
2488 		     const char *sdf_cond)
2489 {
2490   ModeValueDef *val_def = new ModeValueDef(value, cond, sdf_cond);
2491   values_[val_def->value()] = val_def;
2492   return val_def;
2493 }
2494 
2495 ModeValueDef *
findValueDef(const char * value)2496 ModeDef::findValueDef(const char *value)
2497 {
2498   return values_[value];
2499 }
2500 
2501 ////////////////////////////////////////////////////////////////
2502 
ModeValueDef(const char * value,FuncExpr * cond,const char * sdf_cond)2503 ModeValueDef::ModeValueDef(const char *value,
2504 			   FuncExpr *cond,
2505 			   const char *sdf_cond) :
2506   value_(stringCopy(value)),
2507   cond_(cond),
2508   sdf_cond_(stringCopy(sdf_cond))
2509 {
2510 }
2511 
~ModeValueDef()2512 ModeValueDef::~ModeValueDef()
2513 {
2514   stringDelete(value_);
2515   if (cond_)
2516     cond_->deleteSubexprs();
2517   if (sdf_cond_)
2518     stringDelete(sdf_cond_);
2519 }
2520 
2521 void
setSdfCond(const char * sdf_cond)2522 ModeValueDef::setSdfCond(const char *sdf_cond)
2523 {
2524   sdf_cond_ = stringCopy(sdf_cond);
2525 }
2526 
2527 ////////////////////////////////////////////////////////////////
2528 
TableTemplate(const char * name)2529 TableTemplate::TableTemplate(const char *name) :
2530   name_(stringCopy(name)),
2531   axis1_(nullptr),
2532   axis2_(nullptr),
2533   axis3_(nullptr)
2534 {
2535 }
2536 
TableTemplate(const char * name,TableAxis * axis1,TableAxis * axis2,TableAxis * axis3)2537 TableTemplate::TableTemplate(const char *name,
2538 			     TableAxis *axis1,
2539 			     TableAxis *axis2,
2540 			     TableAxis *axis3) :
2541   name_(stringCopy(name)),
2542   axis1_(axis1),
2543   axis2_(axis2),
2544   axis3_(axis3)
2545 {
2546 }
2547 
~TableTemplate()2548 TableTemplate::~TableTemplate()
2549 {
2550   stringDelete(name_);
2551   delete axis1_;
2552   delete axis2_;
2553   delete axis3_;
2554 }
2555 
2556 void
setName(const char * name)2557 TableTemplate::setName(const char *name)
2558 {
2559   stringDelete(name_);
2560   name_ = stringCopy(name);
2561 }
2562 
2563 void
setAxis1(TableAxis * axis)2564 TableTemplate::setAxis1(TableAxis *axis)
2565 {
2566   axis1_ = axis;
2567 }
2568 
2569 void
setAxis2(TableAxis * axis)2570 TableTemplate::setAxis2(TableAxis *axis)
2571 {
2572   axis2_ = axis;
2573 }
2574 
2575 void
setAxis3(TableAxis * axis)2576 TableTemplate::setAxis3(TableAxis *axis)
2577 {
2578   axis3_ = axis;
2579 }
2580 
2581 ////////////////////////////////////////////////////////////////
2582 
Pvt(float process,float voltage,float temperature)2583 Pvt::Pvt(float process,
2584 	 float voltage,
2585 	 float temperature) :
2586   process_(process),
2587   voltage_(voltage),
2588   temperature_(temperature)
2589 {
2590 }
2591 
2592 void
setProcess(float process)2593 Pvt::setProcess(float process)
2594 {
2595   process_ = process;
2596 }
2597 
2598 void
setVoltage(float voltage)2599 Pvt::setVoltage(float voltage)
2600 {
2601   voltage_ = voltage;
2602 }
2603 
2604 void
setTemperature(float temp)2605 Pvt::setTemperature(float temp)
2606 {
2607   temperature_ = temp;
2608 }
2609 
OperatingConditions(const char * name)2610 OperatingConditions::OperatingConditions(const char *name) :
2611   Pvt(0.0, 0.0, 0.0),
2612   name_(stringCopy(name)),
2613   // Default wireload tree.
2614   wire_load_tree_(WireloadTree::balanced)
2615 {
2616 }
2617 
OperatingConditions(const char * name,float process,float voltage,float temperature,WireloadTree wire_load_tree)2618 OperatingConditions::OperatingConditions(const char *name,
2619 					 float process,
2620 					 float voltage,
2621 					 float temperature,
2622 					 WireloadTree wire_load_tree) :
2623   Pvt(process, voltage, temperature),
2624   name_(stringCopy(name)),
2625   wire_load_tree_(wire_load_tree)
2626 {
2627 }
2628 
~OperatingConditions()2629 OperatingConditions::~OperatingConditions()
2630 {
2631   stringDelete(name_);
2632 }
2633 
2634 void
setWireloadTree(WireloadTree tree)2635 OperatingConditions::setWireloadTree(WireloadTree tree)
2636 {
2637   wire_load_tree_ = tree;
2638 }
2639 
2640 ////////////////////////////////////////////////////////////////
2641 
2642 static EnumNameMap<ScaleFactorType> scale_factor_type_map =
2643   {{ScaleFactorType::pin_cap, "pin_cap"},
2644    {ScaleFactorType::wire_cap, "wire_res"},
2645    {ScaleFactorType::min_period, "min_period"},
2646    {ScaleFactorType::cell, "cell"},
2647    {ScaleFactorType::hold, "hold"},
2648    {ScaleFactorType::setup, "setup"},
2649    {ScaleFactorType::recovery, "recovery"},
2650    {ScaleFactorType::removal, "removal"},
2651    {ScaleFactorType::nochange, "nochange"},
2652    {ScaleFactorType::skew, "skew"},
2653    {ScaleFactorType::leakage_power, "leakage_power"},
2654    {ScaleFactorType::internal_power, "internal_power"},
2655    {ScaleFactorType::transition, "transition"},
2656    {ScaleFactorType::min_pulse_width, "min_pulse_width"},
2657    {ScaleFactorType::unknown, "unknown"}
2658   };
2659 
2660 const char *
scaleFactorTypeName(ScaleFactorType type)2661 scaleFactorTypeName(ScaleFactorType type)
2662 {
2663   return scale_factor_type_map.find(type);
2664 }
2665 
2666 ScaleFactorType
findScaleFactorType(const char * name)2667 findScaleFactorType(const char *name)
2668 {
2669   return scale_factor_type_map.find(name, ScaleFactorType::unknown);
2670 }
2671 
2672 bool
scaleFactorTypeRiseFallSuffix(ScaleFactorType type)2673 scaleFactorTypeRiseFallSuffix(ScaleFactorType type)
2674 {
2675   return type == ScaleFactorType::cell
2676     || type == ScaleFactorType::hold
2677     || type == ScaleFactorType::setup
2678     || type == ScaleFactorType::recovery
2679     || type == ScaleFactorType::removal
2680     || type == ScaleFactorType::nochange
2681     || type == ScaleFactorType::skew;
2682 }
2683 
2684 bool
scaleFactorTypeRiseFallPrefix(ScaleFactorType type)2685 scaleFactorTypeRiseFallPrefix(ScaleFactorType type)
2686 {
2687   return type == ScaleFactorType::transition;
2688 }
2689 
2690 bool
scaleFactorTypeLowHighSuffix(ScaleFactorType type)2691 scaleFactorTypeLowHighSuffix(ScaleFactorType type)
2692 {
2693   return type == ScaleFactorType::min_pulse_width;
2694 }
2695 
2696 ////////////////////////////////////////////////////////////////
2697 
2698 EnumNameMap<ScaleFactorPvt> scale_factor_pvt_names =
2699   {{ScaleFactorPvt::process, "process"},
2700    {ScaleFactorPvt::volt, "volt"},
2701    {ScaleFactorPvt::temp, "temp"}
2702   };
2703 
2704 ScaleFactorPvt
findScaleFactorPvt(const char * name)2705 findScaleFactorPvt(const char *name)
2706 {
2707   return scale_factor_pvt_names.find(name, ScaleFactorPvt::unknown);
2708 }
2709 
2710 const char *
scaleFactorPvtName(ScaleFactorPvt pvt)2711 scaleFactorPvtName(ScaleFactorPvt pvt)
2712 {
2713   return scale_factor_pvt_names.find(pvt);
2714 }
2715 
2716 ////////////////////////////////////////////////////////////////
2717 
ScaleFactors(const char * name)2718 ScaleFactors::ScaleFactors(const char *name) :
2719   name_(stringCopy(name))
2720 {
2721   for (int type = 0; type < scale_factor_type_count; type++) {
2722     for (int pvt = 0; pvt < int(ScaleFactorPvt::count); pvt++) {
2723       for (auto tr_index : RiseFall::rangeIndex()) {
2724 	scales_[type][pvt][tr_index] = 0.0;
2725       }
2726     }
2727   }
2728 }
2729 
~ScaleFactors()2730 ScaleFactors::~ScaleFactors()
2731 {
2732   stringDelete(name_);
2733 }
2734 
2735 void
setScale(ScaleFactorType type,ScaleFactorPvt pvt,RiseFall * rf,float scale)2736 ScaleFactors::setScale(ScaleFactorType type,
2737 		       ScaleFactorPvt pvt,
2738 		       RiseFall *rf,
2739 		       float scale)
2740 {
2741   scales_[int(type)][int(pvt)][rf->index()] = scale;
2742 }
2743 
2744 void
setScale(ScaleFactorType type,ScaleFactorPvt pvt,float scale)2745 ScaleFactors::setScale(ScaleFactorType type,
2746 		       ScaleFactorPvt pvt,
2747 		       float scale)
2748 {
2749   scales_[int(type)][int(pvt)][0] = scale;
2750 }
2751 
2752 float
scale(ScaleFactorType type,ScaleFactorPvt pvt,RiseFall * rf)2753 ScaleFactors::scale(ScaleFactorType type,
2754 		    ScaleFactorPvt pvt,
2755 		    RiseFall *rf)
2756 {
2757   return scales_[int(type)][int(pvt)][rf->index()];
2758 }
2759 
2760 float
scale(ScaleFactorType type,ScaleFactorPvt pvt,int tr_index)2761 ScaleFactors::scale(ScaleFactorType type,
2762 		    ScaleFactorPvt pvt,
2763 		    int tr_index)
2764 {
2765   return scales_[int(type)][int(pvt)][tr_index];
2766 }
2767 
2768 float
scale(ScaleFactorType type,ScaleFactorPvt pvt)2769 ScaleFactors::scale(ScaleFactorType type,
2770 		    ScaleFactorPvt pvt)
2771 {
2772   return scales_[int(type)][int(pvt)][0];
2773 }
2774 
2775 void
print()2776 ScaleFactors::print()
2777 {
2778   printf("%10s", " ");
2779   for (int pvt_index = 0; pvt_index < int(ScaleFactorPvt::count); pvt_index++) {
2780     ScaleFactorPvt pvt = (ScaleFactorPvt) pvt_index;
2781     printf("%10s", scaleFactorPvtName(pvt));
2782   }
2783   printf("\n");
2784   for (int type_index = 0; type_index < scale_factor_type_count; type_index++) {
2785     ScaleFactorType type = (ScaleFactorType) type_index;
2786     printf("%10s ", scaleFactorTypeName(type));
2787     for (int pvt_index = 0; pvt_index < int(ScaleFactorPvt::count); pvt_index++) {
2788       if (scaleFactorTypeRiseFallSuffix(type)
2789 	  || scaleFactorTypeRiseFallPrefix(type)
2790 	  || scaleFactorTypeLowHighSuffix(type)) {
2791 	printf(" %.3f,%.3f",
2792 	       scales_[type_index][pvt_index][RiseFall::riseIndex()],
2793 	       scales_[type_index][pvt_index][RiseFall::fallIndex()]);
2794       }
2795       else {
2796 	printf(" %.3f",
2797 	       scales_[type_index][pvt_index][0]);
2798       }
2799     }
2800     printf("\n");
2801   }
2802 }
2803 
TestCell(LibertyPort * data_in,LibertyPort * scan_in,LibertyPort * scan_enable,LibertyPort * scan_out,LibertyPort * scan_out_inv)2804 TestCell::TestCell(LibertyPort *data_in,
2805 		   LibertyPort *scan_in,
2806 		   LibertyPort *scan_enable,
2807 		   LibertyPort *scan_out,
2808 		   LibertyPort *scan_out_inv) :
2809   data_in_(data_in),
2810   scan_in_(scan_in),
2811   scan_enable_(scan_enable),
2812   scan_out_(scan_out),
2813   scan_out_inv_(scan_out_inv)
2814 {
2815 }
2816 
TestCell()2817 TestCell::TestCell() :
2818   data_in_(nullptr),
2819   scan_in_(nullptr),
2820   scan_enable_(nullptr),
2821   scan_out_(nullptr),
2822   scan_out_inv_(nullptr)
2823 {
2824 }
2825 
2826 void
setDataIn(LibertyPort * port)2827 TestCell::setDataIn(LibertyPort *port)
2828 {
2829   data_in_ = port;
2830 }
2831 
2832 void
setScanIn(LibertyPort * port)2833 TestCell::setScanIn(LibertyPort *port)
2834 {
2835   scan_in_ = port;
2836 }
2837 
2838 void
setScanEnable(LibertyPort * port)2839 TestCell::setScanEnable(LibertyPort *port)
2840 {
2841   scan_enable_ = port;
2842 }
2843 
2844 void
setScanOut(LibertyPort * port)2845 TestCell::setScanOut(LibertyPort *port)
2846 {
2847   scan_out_ = port;
2848 }
2849 
2850 void
setScanOutInv(LibertyPort * port)2851 TestCell::setScanOutInv(LibertyPort *port)
2852 {
2853   scan_out_inv_ = port;
2854 }
2855 
2856 ////////////////////////////////////////////////////////////////
2857 
OcvDerate(const char * name)2858 OcvDerate::OcvDerate(const char *name) :
2859   name_(name)
2860 {
2861   for (auto el_index : EarlyLate::rangeIndex()) {
2862     for (auto tr_index : RiseFall::rangeIndex()) {
2863       derate_[tr_index][el_index][int(PathType::clk)] = nullptr;
2864       derate_[tr_index][el_index][int(PathType::data)] = nullptr;
2865     }
2866   }
2867 }
2868 
~OcvDerate()2869 OcvDerate::~OcvDerate()
2870 {
2871   stringDelete(name_);
2872   // Derating table models can be shared in multiple places in derate_;
2873   // Collect them in a set to avoid duplicate deletes.
2874   Set<Table*> models;
2875   for (auto el_index : EarlyLate::rangeIndex()) {
2876     for (auto tr_index : RiseFall::rangeIndex()) {
2877       Table *derate;
2878       derate = derate_[tr_index][el_index][int(PathType::clk)];
2879       if (derate)
2880 	models.insert(derate);
2881       derate = derate_[tr_index][el_index][int(PathType::data)];
2882       if (derate)
2883 	models.insert(derate);
2884     }
2885   }
2886   Set<Table*>::Iterator model_iter(models);
2887   while (model_iter.hasNext()) {
2888     Table *model = model_iter.next();
2889     delete model;
2890   }
2891 }
2892 
2893 Table *
derateTable(const RiseFall * rf,const EarlyLate * early_late,PathType path_type)2894 OcvDerate::derateTable(const RiseFall *rf,
2895 		       const EarlyLate *early_late,
2896 		       PathType path_type)
2897 {
2898   return derate_[rf->index()][early_late->index()][int(path_type)];
2899 }
2900 
2901 void
setDerateTable(const RiseFall * rf,const EarlyLate * early_late,const PathType path_type,Table * derate)2902 OcvDerate::setDerateTable(const RiseFall *rf,
2903 			  const EarlyLate *early_late,
2904 			  const PathType path_type,
2905 			  Table *derate)
2906 {
2907   derate_[rf->index()][early_late->index()][int(path_type)] = derate;
2908 }
2909 
2910 ////////////////////////////////////////////////////////////////
2911 
LibertyPgPort(const char * name,LibertyCell * cell)2912 LibertyPgPort::LibertyPgPort(const char *name,
2913 			     LibertyCell *cell) :
2914   name_(stringCopy(name)),
2915   pg_type_(unknown),
2916   voltage_name_(nullptr),
2917   cell_(cell)
2918 {
2919 }
2920 
~LibertyPgPort()2921 LibertyPgPort::~LibertyPgPort()
2922 {
2923   stringDelete(name_);
2924   stringDelete(voltage_name_);
2925 }
2926 
2927 void
setPgType(PgType type)2928 LibertyPgPort::setPgType(PgType type)
2929 {
2930   pg_type_ = type;
2931 }
2932 
2933 void
setVoltageName(const char * voltage_name)2934 LibertyPgPort::setVoltageName(const char *voltage_name)
2935 {
2936   voltage_name_ = stringCopy(voltage_name);
2937 }
2938 
2939 bool
equiv(const LibertyPgPort * port1,const LibertyPgPort * port2)2940 LibertyPgPort::equiv(const LibertyPgPort *port1,
2941                      const LibertyPgPort *port2)
2942 {
2943   return stringEq(port1->name_, port2->name_)
2944     && port1->pg_type_ == port2->pg_type_;
2945 }
2946 
2947 ////////////////////////////////////////////////////////////////
2948 
LibertyCellPgPortIterator(const LibertyCell * cell)2949 LibertyCellPgPortIterator::LibertyCellPgPortIterator(const LibertyCell *cell) :
2950   iter_(const_cast<LibertyCell*>(cell)->pg_port_map_)
2951 {
2952 }
2953 
2954 bool
hasNext()2955 LibertyCellPgPortIterator::hasNext()
2956 {
2957   return iter_.hasNext();
2958 }
2959 
2960 LibertyPgPort *
next()2961 LibertyCellPgPortIterator::next()
2962 {
2963   const char *name;
2964   LibertyPgPort *port;
2965   iter_.next(name, port);
2966   return port;
2967 }
2968 
2969 } // namespace
2970