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