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 "Sdc.hh"
18
19 #include <algorithm>
20
21 #include "DisallowCopyAssign.hh"
22 #include "Stats.hh"
23 #include "Debug.hh"
24 #include "Mutex.hh"
25 #include "Report.hh"
26 #include "PatternMatch.hh"
27 #include "MinMax.hh"
28 #include "TimingRole.hh"
29 #include "TimingArc.hh"
30 #include "Liberty.hh"
31 #include "Transition.hh"
32 #include "PortDirection.hh"
33 #include "Network.hh"
34 #include "RiseFallMinMax.hh"
35 #include "Clock.hh"
36 #include "ClockLatency.hh"
37 #include "ClockInsertion.hh"
38 #include "CycleAccting.hh"
39 #include "PortDelay.hh"
40 #include "ExceptionPath.hh"
41 #include "PortExtCap.hh"
42 #include "DisabledPorts.hh"
43 #include "InputDrive.hh"
44 #include "DataCheck.hh"
45 #include "ClockGatingCheck.hh"
46 #include "ClockGroups.hh"
47 #include "DeratingFactors.hh"
48 #include "HpinDrvrLoad.hh"
49 #include "search/Levelize.hh"
50 #include "Corner.hh"
51 #include "Graph.hh"
52
53 namespace sta {
54
55 bool
operator ()(const ClockPair & pair1,const ClockPair & pair2) const56 ClockPairLess::operator()(const ClockPair &pair1,
57 const ClockPair &pair2) const
58 {
59 int first1 = pair1.first->index();
60 int second1 = pair1.second->index();
61 if (first1 > second1)
62 std::swap(first1, second1);
63 int first2 = pair2.first->index();
64 int second2 = pair2.second->index();
65 if (first2 > second2)
66 std::swap(first2, second2);
67 return (first1 < first2)
68 || (first1 == first2
69 && second1 < second2);
70 }
71
72 ////////////////////////////////////////////////////////////////
73
74 typedef Vector<ClockPair> ClockPairSeq;
75 typedef Set<Pvt*> PvtSet;
76
77 static ExceptionThruSeq *
78 clone(ExceptionThruSeq *thrus,
79 Network *network);
80
81 ////////////////////////////////////////////////////////////////
82
Sdc(StaState * sta)83 Sdc::Sdc(StaState *sta) :
84 StaState(sta),
85 derating_factors_(nullptr),
86 net_derating_factors_(nullptr),
87 inst_derating_factors_(nullptr),
88 cell_derating_factors_(nullptr),
89 clk_index_(0),
90 clk_insertions_(nullptr),
91 clk_group_exclusions_(nullptr),
92 clk_group_same_(nullptr),
93 clk_sense_map_(network_),
94 clk_gating_check_(nullptr),
95 input_delay_index_(0),
96 port_cap_map_(nullptr),
97 net_wire_cap_map_(nullptr),
98 drvr_pin_wire_cap_map_(nullptr),
99 have_thru_hpin_exceptions_(false),
100 first_from_pin_exceptions_(nullptr),
101 first_from_clk_exceptions_(nullptr),
102 first_from_inst_exceptions_(nullptr),
103 first_thru_pin_exceptions_(nullptr),
104 first_thru_inst_exceptions_(nullptr),
105 first_thru_net_exceptions_(nullptr),
106 first_to_pin_exceptions_(nullptr),
107 first_to_clk_exceptions_(nullptr),
108 first_to_inst_exceptions_(nullptr),
109 first_thru_edge_exceptions_(nullptr),
110 path_delay_internal_startpoints_(nullptr),
111 path_delay_internal_endpoints_(nullptr)
112 {
113 initVariables();
114 sdc_ = this;
115 setWireload(nullptr, MinMaxAll::all());
116 setWireloadSelection(nullptr, MinMaxAll::all());
117 setOperatingConditions(nullptr, MinMaxAll::all());
118 makeDefaultArrivalClock();
119 initInstancePvtMaps();
120 }
121
122 void
makeDefaultArrivalClock()123 Sdc::makeDefaultArrivalClock()
124 {
125 FloatSeq *waveform = new FloatSeq;
126 waveform->push_back(0.0);
127 waveform->push_back(0.0);
128 default_arrival_clk_ = new Clock("input port clock", clk_index_++);
129 default_arrival_clk_->initClk(0, false, 0.0, waveform, nullptr, network_);
130 }
131
~Sdc()132 Sdc::~Sdc()
133 {
134 deleteConstraints();
135 }
136
137 // This does NOT call initVariables() because those variable values
138 // survive linking a new design.
139 void
clear()140 Sdc::clear()
141 {
142 removeLibertyAnnotations();
143 deleteConstraints();
144 propagated_clk_pins_.clear();
145 clocks_.clear();
146 clock_name_map_.clear();
147 clock_pin_map_.clear();
148 clock_leaf_pin_map_.clear();
149 clk_latencies_.clear();
150 edge_clk_latency_.clear();
151 if (clk_insertions_)
152 clk_insertions_->clear();
153
154 pin_clk_uncertainty_map_.clear();
155 inter_clk_uncertainties_.clear();
156
157 clk_groups_name_map_.clear();
158 clearClkGroupExclusions();
159
160 clk_gating_check_map_.clear();
161 inst_clk_gating_check_map_.clear();
162 pin_clk_gating_check_map_.clear();
163 data_checks_from_map_.clear();
164 data_checks_to_map_.clear();
165
166 input_delays_.clear();
167 input_delay_pin_map_.clear();
168 input_delay_index_ = 0;
169 input_delay_ref_pin_map_.clear();
170 input_delay_leaf_pin_map_.clear();
171 input_delay_internal_pin_map_.clear();
172
173 output_delays_.clear();
174 output_delay_pin_map_.clear();
175 output_delay_leaf_pin_map_.clear();
176
177 port_slew_limit_map_.clear();
178 cell_slew_limit_map_.clear();
179 have_clk_slew_limits_ = false;
180
181 cell_cap_limit_map_.clear();
182 port_cap_limit_map_.clear();
183 pin_cap_limit_map_.clear();
184
185 port_fanout_limit_map_.clear();
186 cell_fanout_limit_map_.clear();
187
188 disabled_pins_.clear();
189 disabled_ports_.clear();
190 disabled_lib_ports_.clear();
191 disabled_edges_.clear();
192 disabled_cell_ports_.clear();
193 disabled_inst_ports_.clear();
194
195 disabled_clk_gating_checks_inst_.clear();
196 disabled_clk_gating_checks_pin_.clear();
197
198 input_drive_map_.clear();
199 logic_value_map_.clear();
200 case_value_map_.clear();
201
202 pin_latch_borrow_limit_map_.clear();
203 inst_latch_borrow_limit_map_.clear();
204 clk_latch_borrow_limit_map_.clear();
205
206 min_pulse_width_.clear();
207
208 setWireload(nullptr, MinMaxAll::all());
209 setWireloadSelection(nullptr, MinMaxAll::all());
210 // Operating conditions are owned by Liberty libraries.
211 setOperatingConditions(nullptr, MinMaxAll::all());
212 clk_index_ = 0;
213 makeDefaultArrivalClock();
214
215 unsetTimingDerate();
216 }
217
218 void
initVariables()219 Sdc::initVariables()
220 {
221 analysis_type_ = AnalysisType::ocv;
222 use_default_arrival_clock_ = false;
223 crpr_enabled_ = true;
224 crpr_mode_ = CrprMode::same_pin;
225 propagate_gated_clock_enable_ = true;
226 preset_clr_arcs_enabled_ = false;
227 cond_default_arcs_enabled_ = true;
228 bidirect_net_paths_enabled_ = false;
229 bidirect_inst_paths_enabled_ = false;
230 recovery_removal_checks_enabled_ = true;
231 gated_clk_checks_enabled_ = true;
232 clk_thru_tristate_enabled_ = false;
233 dynamic_loop_breaking_ = false;
234 propagate_all_clks_ = false;
235 wireload_mode_ = WireloadMode::unknown;
236 max_area_ = 0.0;
237 path_delays_without_to_ = false;
238 clk_hpin_disables_valid_ = false;
239 have_clk_slew_limits_ = false;
240 }
241
242 void
deleteConstraints()243 Sdc::deleteConstraints()
244 {
245 clocks_.deleteContents();
246 delete default_arrival_clk_;
247 clock_pin_map_.deleteContents();
248 clock_leaf_pin_map_.deleteContents();
249 clk_latencies_.deleteContents();
250 if (clk_insertions_) {
251 clk_insertions_->deleteContents();
252 delete clk_insertions_;
253 clk_insertions_ = nullptr;
254 }
255
256 clk_groups_name_map_.deleteContents();
257 clearClkGroupExclusions();
258
259 pin_clk_uncertainty_map_.deleteContents();
260 inter_clk_uncertainties_.deleteContents();
261 delete clk_gating_check_;
262 clk_gating_check_ = nullptr;
263 clk_gating_check_map_.deleteContents();
264 inst_clk_gating_check_map_.deleteContents();
265 pin_clk_gating_check_map_.deleteContents();
266 input_drive_map_.deleteContents();
267 disabled_cell_ports_.deleteContents();
268 disabled_inst_ports_.deleteContents();
269 pin_min_pulse_width_map_.deleteContentsClear();
270 inst_min_pulse_width_map_.deleteContentsClear();
271 clk_min_pulse_width_map_.deleteContentsClear();
272
273 DataChecksMap::Iterator data_checks_iter1(data_checks_from_map_);
274 while (data_checks_iter1.hasNext()) {
275 DataCheckSet *checks = data_checks_iter1.next();
276 checks->deleteContents();
277 delete checks;
278 }
279
280 DataChecksMap::Iterator data_checks_iter2(data_checks_to_map_);
281 while (data_checks_iter2.hasNext()) {
282 DataCheckSet *checks = data_checks_iter2.next();
283 delete checks;
284 }
285
286 for (auto input_delay : input_delays_)
287 delete input_delay;
288 input_delay_pin_map_.deleteContents();
289 input_delay_leaf_pin_map_.deleteContents();
290 input_delay_ref_pin_map_.deleteContents();
291 input_delay_internal_pin_map_.deleteContents();
292
293 for (auto output_delay : output_delays_)
294 delete output_delay;
295 output_delay_pin_map_.deleteContents();
296 output_delay_ref_pin_map_.deleteContents();
297 output_delay_leaf_pin_map_.deleteContents();
298
299 clk_hpin_disables_.deleteContentsClear();
300 clk_hpin_disables_valid_ = false;
301
302 clearCycleAcctings();
303 deleteExceptions();
304 clearGroupPathMap();
305 deleteInstancePvts();
306 deleteDeratingFactors();
307 removeLoadCaps();
308 clk_sense_map_.clear();
309 }
310
311 void
deleteInstancePvts()312 Sdc::deleteInstancePvts()
313 {
314 // Multiple instances can share a pvt, so put them in a set
315 // so they are only deleted once.
316 PvtSet pvts;
317 for (auto mm_index : MinMax::rangeIndex()) {
318 InstancePvtMap *pvt_map = instance_pvt_maps_[mm_index];
319 InstancePvtMap::Iterator pvt_iter(pvt_map);
320 while (pvt_iter.hasNext()) {
321 Pvt *pvt = pvt_iter.next();
322 pvts.insert(pvt);
323 }
324 delete pvt_map;
325 }
326 pvts.deleteContents();
327 }
328
329 void
removeNetLoadCaps()330 Sdc::removeNetLoadCaps()
331 {
332 delete [] net_wire_cap_map_;
333 net_wire_cap_map_ = nullptr;
334
335 delete [] drvr_pin_wire_cap_map_;
336 drvr_pin_wire_cap_map_ = nullptr;
337 }
338
339 void
removeLoadCaps()340 Sdc::removeLoadCaps()
341 {
342 if (port_cap_map_) {
343 port_cap_map_->deleteContents();
344 delete port_cap_map_;
345 port_cap_map_ = nullptr;
346 }
347 removeNetLoadCaps();
348 }
349
350 void
removeLibertyAnnotations()351 Sdc::removeLibertyAnnotations()
352 {
353 DisabledCellPortsMap::Iterator disabled_iter(disabled_cell_ports_);
354 while (disabled_iter.hasNext()) {
355 DisabledCellPorts *disable = disabled_iter.next();
356 LibertyCell *cell = disable->cell();
357 if (disable->all())
358 cell->setIsDisabledConstraint(false);
359
360 LibertyPortSet::Iterator from_iter(disable->from());
361 while (from_iter.hasNext()) {
362 LibertyPort *from = from_iter.next();
363 from->setIsDisabledConstraint(false);
364 }
365
366 LibertyPortSet::Iterator to_iter(disable->to());
367 while (to_iter.hasNext()) {
368 LibertyPort *to = to_iter.next();
369 to->setIsDisabledConstraint(false);
370 }
371
372 if (disable->timingArcSets()) {
373 TimingArcSetSet::Iterator arc_iter(disable->timingArcSets());
374 while (arc_iter.hasNext()) {
375 TimingArcSet *arc_set = arc_iter.next();
376 arc_set->setIsDisabledConstraint(false);
377 }
378 }
379
380 LibertyPortPairSet::Iterator from_to_iter(disable->fromTo());
381 while (from_to_iter.hasNext()) {
382 LibertyPortPair *pair = from_to_iter.next();
383 const LibertyPort *from = pair->first;
384 const LibertyPort *to = pair->second;
385 LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
386 while (arc_iter.hasNext()) {
387 TimingArcSet *arc_set = arc_iter.next();
388 arc_set->setIsDisabledConstraint(false);
389 }
390 }
391 }
392
393 LibertyPortSet::Iterator port_iter(disabled_lib_ports_);
394 while (port_iter.hasNext()) {
395 LibertyPort *port = port_iter.next();
396 port->setIsDisabledConstraint(false);
397 }
398 }
399
400 void
initInstancePvtMaps()401 Sdc::initInstancePvtMaps()
402 {
403 for (auto mm_index : MinMax::rangeIndex())
404 instance_pvt_maps_[mm_index] = nullptr;
405 }
406
407 void
deleteNetBefore(Net * net)408 Sdc::deleteNetBefore(Net *net)
409 {
410 if (net_wire_cap_map_) {
411 for (int corner_index = 0; corner_index < corners_->count(); corner_index++) {
412 net_wire_cap_map_[corner_index].erase(net);
413 for (Pin *pin : *network_->drivers(net))
414 drvr_pin_wire_cap_map_[corner_index].erase(pin);
415 }
416 }
417 }
418
419 ////////////////////////////////////////////////////////////////
420
421 bool
isConstrained(const Pin * pin) const422 Sdc::isConstrained(const Pin *pin) const
423 {
424 Pin *pin1 = const_cast<Pin*>(pin);
425 Port *port = network_->isTopLevelPort(pin) ? network_->port(pin) : nullptr;
426 return clock_pin_map_.hasKey(pin)
427 || propagated_clk_pins_.hasKey(pin1)
428 || hasClockLatency(pin)
429 || hasClockInsertion(pin)
430 || pin_clk_uncertainty_map_.hasKey(pin)
431 || pin_clk_gating_check_map_.hasKey(pin)
432 || data_checks_from_map_.hasKey(pin)
433 || data_checks_to_map_.hasKey(pin)
434 || input_delay_pin_map_.hasKey(pin)
435 || output_delay_pin_map_.hasKey(pin)
436 || port_slew_limit_map_.hasKey(port)
437 || pin_cap_limit_map_.hasKey(pin1)
438 || port_cap_limit_map_.hasKey(port)
439 || port_fanout_limit_map_.hasKey(port)
440 || hasPortExtCap(port)
441 || disabled_pins_.hasKey(pin1)
442 || disabled_ports_.hasKey(port)
443 || disabled_clk_gating_checks_pin_.hasKey(pin1)
444 || (first_from_pin_exceptions_
445 && first_from_pin_exceptions_->hasKey(pin))
446 || (first_thru_pin_exceptions_
447 && first_thru_pin_exceptions_->hasKey(pin))
448 || (first_to_pin_exceptions_
449 && first_to_pin_exceptions_->hasKey(pin))
450 || input_drive_map_.hasKey(port)
451 || logic_value_map_.hasKey(pin)
452 || case_value_map_.hasKey(pin)
453 || pin_latch_borrow_limit_map_.hasKey(pin)
454 || pin_min_pulse_width_map_.hasKey(pin);
455 }
456
457 bool
isConstrained(const Instance * inst) const458 Sdc::isConstrained(const Instance *inst) const
459 {
460 Instance *inst1 = const_cast<Instance*>(inst);
461 return (instance_pvt_maps_[MinMax::minIndex()]
462 && instance_pvt_maps_[MinMax::minIndex()]->hasKey(inst1))
463 || (instance_pvt_maps_[MinMax::maxIndex()]
464 && instance_pvt_maps_[MinMax::maxIndex()]->hasKey(inst1))
465 || (inst_derating_factors_
466 && inst_derating_factors_->hasKey(inst))
467 || inst_clk_gating_check_map_.hasKey(inst)
468 || disabled_inst_ports_.hasKey(inst1)
469 || (first_from_inst_exceptions_
470 && first_from_inst_exceptions_->hasKey(inst))
471 || (first_thru_inst_exceptions_
472 && first_thru_inst_exceptions_->hasKey(inst))
473 || (first_to_inst_exceptions_->hasKey(inst)
474 && first_to_inst_exceptions_)
475 || inst_latch_borrow_limit_map_.hasKey(inst)
476 || inst_min_pulse_width_map_.hasKey(inst);
477 }
478
479 bool
isConstrained(const Net * net) const480 Sdc::isConstrained(const Net *net) const
481 {
482 Net *net1 = const_cast<Net*>(net);
483 return (net_derating_factors_
484 && net_derating_factors_->hasKey(net))
485 || hasNetWireCap(net1)
486 || net_res_map_.hasKey(net1)
487 || (first_thru_net_exceptions_
488 && first_thru_net_exceptions_->hasKey(net));
489 }
490
491 ////////////////////////////////////////////////////////////////
492
493 void
setAnalysisType(AnalysisType analysis_type)494 Sdc::setAnalysisType(AnalysisType analysis_type)
495 {
496 analysis_type_ = analysis_type;
497 }
498
499 void
setOperatingConditions(OperatingConditions * op_cond,const MinMaxAll * min_max)500 Sdc::setOperatingConditions(OperatingConditions *op_cond,
501 const MinMaxAll *min_max)
502 {
503 for (auto mm_index : min_max->rangeIndex())
504 operating_conditions_[mm_index] = op_cond;
505 }
506
507 void
setOperatingConditions(OperatingConditions * op_cond,const MinMax * min_max)508 Sdc::setOperatingConditions(OperatingConditions *op_cond,
509 const MinMax *min_max)
510 {
511 int mm_index = min_max->index();
512 operating_conditions_[mm_index] = op_cond;
513 }
514
515 OperatingConditions *
operatingConditions(const MinMax * min_max)516 Sdc::operatingConditions(const MinMax *min_max)
517 {
518 int mm_index = min_max->index();
519 return operating_conditions_[mm_index];
520 }
521
522 Pvt *
pvt(Instance * inst,const MinMax * min_max) const523 Sdc::pvt(Instance *inst,
524 const MinMax *min_max) const
525 {
526 InstancePvtMap *pvt_map = instance_pvt_maps_[min_max->index()];
527 if (pvt_map)
528 return pvt_map->findKey(inst);
529 else
530 return nullptr;
531 }
532
533 void
setPvt(Instance * inst,const MinMaxAll * min_max,Pvt * pvt)534 Sdc::setPvt(Instance *inst, const
535 MinMaxAll *min_max,
536 Pvt *pvt)
537 {
538 for (auto mm_index : min_max->rangeIndex()) {
539 InstancePvtMap *pvt_map = instance_pvt_maps_[mm_index];
540 if (pvt_map == nullptr) {
541 pvt_map = new InstancePvtMap;
542 instance_pvt_maps_[mm_index] = pvt_map;
543 }
544 (*pvt_map)[inst] = pvt;
545 }
546 }
547
548 ////////////////////////////////////////////////////////////////
549
550 void
setTimingDerate(TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)551 Sdc::setTimingDerate(TimingDerateType type,
552 PathClkOrData clk_data,
553 const RiseFallBoth *rf,
554 const EarlyLate *early_late,
555 float derate)
556 {
557 if (derating_factors_ == nullptr)
558 derating_factors_ = new DeratingFactorsGlobal;
559 derating_factors_->setFactor(type, clk_data, rf, early_late, derate);
560 }
561
562 void
setTimingDerate(const Net * net,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)563 Sdc::setTimingDerate(const Net *net,
564 PathClkOrData clk_data,
565 const RiseFallBoth *rf,
566 const EarlyLate *early_late,
567 float derate)
568 {
569 if (net_derating_factors_ == nullptr)
570 net_derating_factors_ = new NetDeratingFactorsMap;
571 DeratingFactorsNet *factors = net_derating_factors_->findKey(net);
572 if (factors == nullptr) {
573 factors = new DeratingFactorsNet;
574 (*net_derating_factors_)[net] = factors;
575 }
576 factors->setFactor(clk_data, rf, early_late, derate);
577 }
578
579 void
setTimingDerate(const Instance * inst,TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)580 Sdc::setTimingDerate(const Instance *inst,
581 TimingDerateType type,
582 PathClkOrData clk_data,
583 const RiseFallBoth *rf,
584 const EarlyLate *early_late,
585 float derate)
586 {
587 if (inst_derating_factors_ == nullptr)
588 inst_derating_factors_ = new InstDeratingFactorsMap;
589 DeratingFactorsCell *factors = inst_derating_factors_->findKey(inst);
590 if (factors == nullptr) {
591 factors = new DeratingFactorsCell;
592 (*inst_derating_factors_)[inst] = factors;
593 }
594 factors->setFactor(type, clk_data, rf, early_late, derate);
595 }
596
597 void
setTimingDerate(const LibertyCell * cell,TimingDerateType type,PathClkOrData clk_data,const RiseFallBoth * rf,const EarlyLate * early_late,float derate)598 Sdc::setTimingDerate(const LibertyCell *cell,
599 TimingDerateType type,
600 PathClkOrData clk_data,
601 const RiseFallBoth *rf,
602 const EarlyLate *early_late,
603 float derate)
604 {
605 if (cell_derating_factors_ == nullptr)
606 cell_derating_factors_ = new CellDeratingFactorsMap;
607 DeratingFactorsCell *factors = cell_derating_factors_->findKey(cell);
608 if (factors == nullptr) {
609 factors = new DeratingFactorsCell;
610 (*cell_derating_factors_)[cell] = factors;
611 }
612 factors->setFactor(type, clk_data, rf, early_late, derate);
613 }
614
615 float
timingDerateInstance(const Pin * pin,TimingDerateType type,PathClkOrData clk_data,const RiseFall * rf,const EarlyLate * early_late) const616 Sdc::timingDerateInstance(const Pin *pin,
617 TimingDerateType type,
618 PathClkOrData clk_data,
619 const RiseFall *rf,
620 const EarlyLate *early_late) const
621 {
622 if (inst_derating_factors_) {
623 const Instance *inst = network_->instance(pin);
624 DeratingFactorsCell *factors = inst_derating_factors_->findKey(inst);
625 if (factors) {
626 float factor;
627 bool exists;
628 factors->factor(type, clk_data, rf, early_late, factor, exists);
629 if (exists)
630 return factor;
631 }
632 }
633
634 if (cell_derating_factors_) {
635 const Instance *inst = network_->instance(pin);
636 const LibertyCell *cell = network_->libertyCell(inst);
637 if (cell) {
638 DeratingFactorsCell *factors = cell_derating_factors_->findKey(cell);
639 float factor;
640 bool exists;
641 if (factors) {
642 factors->factor(type, clk_data, rf, early_late, factor, exists);
643 if (exists)
644 return factor;
645 }
646 }
647 }
648 if (derating_factors_) {
649 float factor;
650 bool exists;
651 derating_factors_->factor(type, clk_data, rf, early_late, factor, exists);
652 if (exists)
653 return factor;
654 }
655 return 1.0;
656 }
657
658 float
timingDerateNet(const Pin * pin,PathClkOrData clk_data,const RiseFall * rf,const EarlyLate * early_late) const659 Sdc::timingDerateNet(const Pin *pin,
660 PathClkOrData clk_data,
661 const RiseFall *rf,
662 const EarlyLate *early_late) const
663 {
664 if (net_derating_factors_) {
665 const Net *net = network_->net(pin);
666 DeratingFactorsNet *factors = net_derating_factors_->findKey(net);
667 if (factors) {
668 float factor;
669 bool exists;
670 factors->factor(clk_data, rf, early_late, factor, exists);
671 if (exists)
672 return factor;
673 }
674 }
675 if (derating_factors_) {
676 float factor;
677 bool exists;
678 derating_factors_->factor(TimingDerateType::net_delay, clk_data, rf,
679 early_late, factor, exists);
680 if (exists)
681 return factor;
682 }
683 return 1.0;
684 }
685
686 void
unsetTimingDerate()687 Sdc::unsetTimingDerate()
688 {
689 deleteDeratingFactors();
690 }
691
692 void
deleteDeratingFactors()693 Sdc::deleteDeratingFactors()
694 {
695 if (net_derating_factors_) {
696 NetDeratingFactorsMap::Iterator net_iter(net_derating_factors_);
697 while (net_iter.hasNext()) {
698 DeratingFactorsNet *factors = net_iter.next();
699 delete factors;
700 }
701 delete net_derating_factors_;
702 net_derating_factors_ = nullptr;
703 }
704
705 if (inst_derating_factors_) {
706 InstDeratingFactorsMap::Iterator inst_iter(inst_derating_factors_);
707 while (inst_iter.hasNext()) {
708 DeratingFactorsCell *factors = inst_iter.next();
709 delete factors;
710 }
711 delete inst_derating_factors_;
712 inst_derating_factors_ = nullptr;
713 }
714
715 if (cell_derating_factors_) {
716 CellDeratingFactorsMap::Iterator cell_iter(cell_derating_factors_);
717 while (cell_iter.hasNext()) {
718 DeratingFactorsCell *factors = cell_iter.next();
719 delete factors;
720 }
721 delete cell_derating_factors_;
722 cell_derating_factors_ = nullptr;
723 }
724
725 delete derating_factors_;
726 derating_factors_ = nullptr;
727 }
728
729 ////////////////////////////////////////////////////////////////
730
731 void
setDriveCell(LibertyLibrary * library,LibertyCell * cell,Port * port,LibertyPort * from_port,float * from_slews,LibertyPort * to_port,const RiseFallBoth * rf,const MinMaxAll * min_max)732 Sdc::setDriveCell(LibertyLibrary *library,
733 LibertyCell *cell,
734 Port *port,
735 LibertyPort *from_port,
736 float *from_slews,
737 LibertyPort *to_port,
738 const RiseFallBoth *rf,
739 const MinMaxAll *min_max)
740 {
741 ensureInputDrive(port)->setDriveCell(library, cell, from_port, from_slews,
742 to_port, rf, min_max);
743 }
744
745 void
setInputSlew(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float slew)746 Sdc::setInputSlew(Port *port,
747 const RiseFallBoth *rf,
748 const MinMaxAll *min_max,
749 float slew)
750 {
751 ensureInputDrive(port)->setSlew(rf, min_max, slew);
752 }
753
754 void
setDriveResistance(Port * port,const RiseFallBoth * rf,const MinMaxAll * min_max,float res)755 Sdc::setDriveResistance(Port *port,
756 const RiseFallBoth *rf,
757 const MinMaxAll *min_max,
758 float res)
759 {
760 ensureInputDrive(port)->setDriveResistance(rf, min_max, res);
761 }
762
763 InputDrive *
ensureInputDrive(Port * port)764 Sdc::ensureInputDrive(Port *port)
765 {
766 InputDrive *drive = input_drive_map_.findKey(port);
767 if (drive == nullptr) {
768 drive = new InputDrive;
769 input_drive_map_[port] = drive;
770 }
771 return drive;
772 }
773
774 ////////////////////////////////////////////////////////////////
775
776 void
setSlewLimit(Clock * clk,const RiseFallBoth * rf,const PathClkOrData clk_data,const MinMax * min_max,float slew)777 Sdc::setSlewLimit(Clock *clk,
778 const RiseFallBoth *rf,
779 const PathClkOrData clk_data,
780 const MinMax *min_max,
781 float slew)
782 {
783 clk->setSlewLimit(rf, clk_data, min_max, slew);
784 have_clk_slew_limits_ = true;
785 }
786
787 bool
haveClkSlewLimits() const788 Sdc::haveClkSlewLimits() const
789 {
790 return have_clk_slew_limits_;
791 }
792
793 void
slewLimit(Clock * clk,const RiseFall * rf,const PathClkOrData clk_data,const MinMax * min_max,float & slew,bool & exists)794 Sdc::slewLimit(Clock *clk, const RiseFall *rf,
795 const PathClkOrData clk_data,
796 const MinMax *min_max,
797 float &slew,
798 bool &exists)
799 {
800 clk->slewLimit(rf, clk_data, min_max, slew, exists);
801 }
802
803 void
slewLimit(Port * port,const MinMax * min_max,float & slew,bool & exists)804 Sdc::slewLimit(Port *port,
805 const MinMax *min_max,
806 float &slew,
807 bool &exists)
808 {
809 slew = 0.0;
810 MinMaxFloatValues values;
811 port_slew_limit_map_.findKey(port, values, exists);
812 if (exists)
813 values.value(min_max, slew, exists);
814 }
815
816 void
setSlewLimit(Port * port,const MinMax * min_max,float slew)817 Sdc::setSlewLimit(Port *port,
818 const MinMax *min_max,
819 float slew)
820 {
821 MinMaxFloatValues &values = port_slew_limit_map_[port];
822 values.setValue(min_max, slew);
823 }
824
825 void
slewLimit(Cell * cell,const MinMax * min_max,float & slew,bool & exists)826 Sdc::slewLimit(Cell *cell,
827 const MinMax *min_max,
828 float &slew,
829 bool &exists)
830 {
831 slew = 0.0;
832 MinMaxFloatValues values;
833 cell_slew_limit_map_.findKey(cell, values, exists);
834 if (exists)
835 values.value(min_max, slew, exists);
836 }
837
838 void
setSlewLimit(Cell * cell,const MinMax * min_max,float slew)839 Sdc::setSlewLimit(Cell *cell,
840 const MinMax *min_max,
841 float slew)
842 {
843 MinMaxFloatValues &values = cell_slew_limit_map_[cell];
844 values.setValue(min_max, slew);
845 }
846
847 void
capacitanceLimit(Cell * cell,const MinMax * min_max,float & cap,bool & exists)848 Sdc::capacitanceLimit(Cell *cell,
849 const MinMax *min_max,
850 float &cap,
851 bool &exists)
852 {
853 cap = 0.0;
854 exists = false;
855 MinMaxFloatValues values;
856 cell_cap_limit_map_.findKey(cell, values, exists);
857 if (exists)
858 values.value(min_max, cap, exists);
859 }
860
861 void
setCapacitanceLimit(Cell * cell,const MinMax * min_max,float cap)862 Sdc::setCapacitanceLimit(Cell *cell,
863 const MinMax *min_max,
864 float cap)
865 {
866 MinMaxFloatValues &values = cell_cap_limit_map_[cell];
867 values.setValue(min_max, cap);
868 }
869
870 void
capacitanceLimit(Port * port,const MinMax * min_max,float & cap,bool & exists)871 Sdc::capacitanceLimit(Port *port,
872 const MinMax *min_max,
873 float &cap,
874 bool &exists)
875 {
876 cap = 0.0;
877 exists = false;
878 MinMaxFloatValues values;
879 port_cap_limit_map_.findKey(port, values, exists);
880 if (exists)
881 values.value(min_max, cap, exists);
882 }
883
884 void
setCapacitanceLimit(Port * port,const MinMax * min_max,float cap)885 Sdc::setCapacitanceLimit(Port *port,
886 const MinMax *min_max,
887 float cap)
888 {
889 MinMaxFloatValues &values = port_cap_limit_map_[port];
890 values.setValue(min_max, cap);
891 }
892
893 void
capacitanceLimit(Pin * pin,const MinMax * min_max,float & cap,bool & exists)894 Sdc::capacitanceLimit(Pin *pin,
895 const MinMax *min_max,
896 float &cap,
897 bool &exists)
898 {
899 cap = 0.0;
900 exists = false;
901 MinMaxFloatValues values;
902 pin_cap_limit_map_.findKey(pin, values, exists);
903 if (exists)
904 values.value(min_max, cap, exists);
905 }
906
907 void
setCapacitanceLimit(Pin * pin,const MinMax * min_max,float cap)908 Sdc::setCapacitanceLimit(Pin *pin,
909 const MinMax *min_max,
910 float cap)
911 {
912 MinMaxFloatValues &values = pin_cap_limit_map_[pin];
913 values.setValue(min_max, cap);
914 }
915
916 void
fanoutLimit(Cell * cell,const MinMax * min_max,float & fanout,bool & exists)917 Sdc::fanoutLimit(Cell *cell,
918 const MinMax *min_max,
919 float &fanout,
920 bool &exists)
921 {
922 fanout = 0.0;
923 MinMaxFloatValues values;
924 cell_fanout_limit_map_.findKey(cell, values, exists);
925 if (exists)
926 values.value(min_max, fanout, exists);
927 }
928
929 void
setFanoutLimit(Cell * cell,const MinMax * min_max,float fanout)930 Sdc::setFanoutLimit(Cell *cell,
931 const MinMax *min_max,
932 float fanout)
933 {
934 MinMaxFloatValues &values = cell_fanout_limit_map_[cell];
935 values.setValue(min_max, fanout);
936 }
937
938 void
fanoutLimit(Port * port,const MinMax * min_max,float & fanout,bool & exists)939 Sdc::fanoutLimit(Port *port,
940 const MinMax *min_max,
941 float &fanout,
942 bool &exists)
943 {
944 fanout = 0.0;
945 MinMaxFloatValues values;
946 port_fanout_limit_map_.findKey(port, values, exists);
947 if (exists)
948 values.value(min_max, fanout, exists);
949 }
950
951 void
setFanoutLimit(Port * port,const MinMax * min_max,float fanout)952 Sdc::setFanoutLimit(Port *port,
953 const MinMax *min_max,
954 float fanout)
955 {
956 MinMaxFloatValues &values = port_fanout_limit_map_[port];
957 values.setValue(min_max, fanout);
958 }
959
960 void
setMaxArea(float area)961 Sdc::setMaxArea(float area)
962 {
963 max_area_ = area;
964 }
965
966 float
maxArea() const967 Sdc::maxArea() const
968 {
969 return max_area_;
970 }
971
972 ////////////////////////////////////////////////////////////////
973
974 Clock *
makeClock(const char * name,PinSet * pins,bool add_to_pins,float period,FloatSeq * waveform,const char * comment)975 Sdc::makeClock(const char *name,
976 PinSet *pins,
977 bool add_to_pins,
978 float period,
979 FloatSeq *waveform,
980 const char *comment)
981 {
982 Clock *clk = clock_name_map_.findKey(name);
983 if (!add_to_pins)
984 deletePinClocks(clk, pins);
985 if (clk)
986 // Named clock redefinition.
987 deleteClkPinMappings(clk);
988 else {
989 // Fresh clock definition.
990 clk = new Clock(name, clk_index_++);
991 clk->setIsPropagated(propagate_all_clks_);
992 clocks_.push_back(clk);
993 // Use the copied name in the map.
994 clock_name_map_[clk->name()] = clk;
995 }
996 clk->initClk(pins, add_to_pins, period, waveform, comment, network_);
997 makeClkPinMappings(clk);
998 clearCycleAcctings();
999 invalidateGeneratedClks();
1000 clkHpinDisablesInvalid();
1001 return clk;
1002 }
1003
1004 Clock *
makeGeneratedClock(const char * name,PinSet * pins,bool add_to_pins,Pin * src_pin,Clock * master_clk,Pin * pll_out,Pin * pll_fdbk,int divide_by,int multiply_by,float duty_cycle,bool invert,bool combinational,IntSeq * edges,FloatSeq * edge_shifts,const char * comment)1005 Sdc::makeGeneratedClock(const char *name,
1006 PinSet *pins,
1007 bool add_to_pins,
1008 Pin *src_pin,
1009 Clock *master_clk,
1010 Pin *pll_out,
1011 Pin *pll_fdbk,
1012 int divide_by,
1013 int multiply_by,
1014 float duty_cycle,
1015 bool invert,
1016 bool combinational,
1017 IntSeq *edges,
1018 FloatSeq *edge_shifts,
1019 const char *comment)
1020 {
1021 Clock *clk = clock_name_map_.findKey(name);
1022 if (!add_to_pins)
1023 deletePinClocks(clk, pins);
1024 if (clk)
1025 deleteClkPinMappings(clk);
1026 else {
1027 clk = new Clock(name, clk_index_++);
1028 clocks_.push_back(clk);
1029 clock_name_map_[clk->name()] = clk;
1030 }
1031 clk->initGeneratedClk(pins, add_to_pins, src_pin, master_clk,
1032 pll_out, pll_fdbk,
1033 divide_by, multiply_by, duty_cycle,
1034 invert, combinational,
1035 edges, edge_shifts, propagate_all_clks_,
1036 comment, network_);
1037 makeClkPinMappings(clk);
1038 clearCycleAcctings();
1039 invalidateGeneratedClks();
1040 clkHpinDisablesInvalid();
1041 return clk;
1042 }
1043
1044 void
invalidateGeneratedClks() const1045 Sdc::invalidateGeneratedClks() const
1046 {
1047 for (auto clk : clocks_) {
1048 if (clk->isGenerated())
1049 clk->waveformInvalid();
1050 }
1051 }
1052
1053 // If the clock is not defined with the -add option, any pins that already
1054 // have a clock attached to them are removed from the pin. If the clock
1055 // is not the clock being defined and has no pins it is removed.
1056 void
deletePinClocks(Clock * defining_clk,PinSet * pins)1057 Sdc::deletePinClocks(Clock *defining_clk,
1058 PinSet *pins)
1059 {
1060 // Find all the clocks defined on pins to avoid finding the clock's
1061 // vertex pins multiple times.
1062 ClockSet clks;
1063 PinSet::Iterator pin_iter(pins);
1064 while (pin_iter.hasNext()) {
1065 Pin *pin = pin_iter.next();
1066 ClockSet *pin_clks = clock_pin_map_.findKey(pin);
1067 if (pin_clks) {
1068 ClockSet::Iterator clk_iter(pin_clks);
1069 while (clk_iter.hasNext()) {
1070 Clock *clk = clk_iter.next();
1071 clks.insert(clk);
1072 }
1073 }
1074 }
1075 ClockSet::Iterator clk_iter(clks);
1076 while (clk_iter.hasNext()) {
1077 Clock *clk = clk_iter.next();
1078 deleteClkPinMappings(clk);
1079 PinSet::Iterator pin_iter(pins);
1080 while (pin_iter.hasNext()) {
1081 Pin *pin = pin_iter.next();
1082 clk->deletePin(pin);
1083 }
1084 if (clk != defining_clk) {
1085 if (clk->pins().empty())
1086 removeClock(clk);
1087 else {
1088 clk->makeLeafPins(network_);
1089 // One of the remaining clock pins may use a vertex pin that
1090 // was deleted above.
1091 makeClkPinMappings(clk);
1092 }
1093 }
1094 }
1095 }
1096
1097 void
deleteClkPinMappings(Clock * clk)1098 Sdc::deleteClkPinMappings(Clock *clk)
1099 {
1100 for (Pin *pin : clk->pins()) {
1101 ClockSet *pin_clks = clock_pin_map_.findKey(pin);
1102 if (pin_clks) {
1103 pin_clks->erase(clk);
1104 if (pin_clks->empty()) {
1105 clock_pin_map_.erase(pin);
1106 delete pin_clks;
1107 }
1108 }
1109 }
1110
1111 for (const Pin *pin : clk->leafPins()) {
1112 ClockSet *pin_clks = clock_leaf_pin_map_.findKey(pin);
1113 if (pin_clks) {
1114 pin_clks->erase(clk);
1115 if (pin_clks->empty()) {
1116 clock_leaf_pin_map_.erase(pin);
1117 delete pin_clks;
1118 }
1119 }
1120 }
1121 }
1122
1123 void
makeClkPinMappings(Clock * clk)1124 Sdc::makeClkPinMappings(Clock *clk)
1125 {
1126 for (Pin *pin : clk->pins()) {
1127 ClockSet *pin_clks = clock_pin_map_.findKey(pin);
1128 if (pin_clks == nullptr) {
1129 pin_clks = new ClockSet;
1130 clock_pin_map_.insert(pin, pin_clks);
1131 }
1132 pin_clks->insert(clk);
1133 }
1134
1135 for (const Pin *pin : clk->leafPins()) {
1136 ClockSet *pin_clks = clock_leaf_pin_map_.findKey(pin);
1137 if (pin_clks == nullptr) {
1138 pin_clks = new ClockSet;
1139 clock_leaf_pin_map_.insert(pin, pin_clks);
1140 }
1141 pin_clks->insert(clk);
1142 }
1143 }
1144
1145 void
removeClock(Clock * clk)1146 Sdc::removeClock(Clock *clk)
1147 {
1148 deleteExceptionsReferencing(clk);
1149 deleteInputDelaysReferencing(clk);
1150 deleteOutputDelaysReferencing(clk);
1151 deleteClockLatenciesReferencing(clk);
1152 deleteClockInsertionsReferencing(clk);
1153 deleteInterClockUncertaintiesReferencing(clk);
1154 deleteLatchBorrowLimitsReferencing(clk);
1155 deleteMinPulseWidthReferencing(clk);
1156 deleteMasterClkRefs(clk);
1157 clockGroupsDeleteClkRefs(clk);
1158 clearCycleAcctings();
1159
1160 deleteClkPinMappings(clk);
1161 clocks_.eraseObject(clk);
1162 clock_name_map_.erase(clk->name());
1163 delete clk;
1164 }
1165
1166 // Delete references to clk as a master clock.
1167 void
deleteMasterClkRefs(Clock * clk)1168 Sdc::deleteMasterClkRefs(Clock *clk)
1169 {
1170 for (auto gclk : clocks_) {
1171 if (gclk->isGenerated()
1172 && gclk->masterClk() == clk) {
1173 gclk->setMasterClk(nullptr);
1174 }
1175 }
1176 }
1177
1178 void
clockDeletePin(Clock * clk,Pin * pin)1179 Sdc::clockDeletePin(Clock *clk,
1180 Pin *pin)
1181 {
1182 ClockSet *pin_clks = clock_pin_map_.findKey(pin);
1183 pin_clks->erase(clk);
1184 if (pin_clks->empty())
1185 clock_pin_map_.erase(pin);
1186 clk->deletePin(pin);
1187 clk->makeLeafPins(network_);
1188 makeClkPinMappings(clk);
1189 }
1190
1191 Clock *
findClock(const char * name) const1192 Sdc::findClock(const char *name) const
1193 {
1194 return clock_name_map_.findKey(name);
1195 }
1196
1197 bool
isClock(const Pin * pin) const1198 Sdc::isClock(const Pin *pin) const
1199 {
1200 ClockSet *clks = findClocks(pin);
1201 return clks && !clks->empty();
1202 }
1203
1204 bool
isLeafPinClock(const Pin * pin) const1205 Sdc::isLeafPinClock(const Pin *pin) const
1206 {
1207 ClockSet *clks = findLeafPinClocks(pin);
1208 return clks && !clks->empty();
1209 }
1210
1211 bool
isLeafPinNonGeneratedClock(const Pin * pin) const1212 Sdc::isLeafPinNonGeneratedClock(const Pin *pin) const
1213 {
1214 ClockSet *clks = findLeafPinClocks(pin);
1215 if (clks) {
1216 ClockSet::Iterator clk_iter(clks);
1217 while (clk_iter.hasNext()) {
1218 Clock *clk = clk_iter.next();
1219 if (!clk->isGenerated())
1220 return true;
1221 }
1222 return false;
1223 }
1224 else
1225 return false;
1226 }
1227
1228 ClockSet *
findLeafPinClocks(const Pin * pin) const1229 Sdc::findLeafPinClocks(const Pin *pin) const
1230 {
1231 return clock_leaf_pin_map_.findKey(pin);
1232 }
1233
1234 ClockSet *
findClocks(const Pin * pin) const1235 Sdc::findClocks(const Pin *pin) const
1236 {
1237 return clock_pin_map_.findKey(pin);
1238 }
1239
1240 void
findClocksMatching(PatternMatch * pattern,ClockSeq * clks) const1241 Sdc::findClocksMatching(PatternMatch *pattern,
1242 ClockSeq *clks) const
1243 {
1244 if (!pattern->hasWildcards()) {
1245 Clock *clk = findClock(pattern->pattern());
1246 if (clk)
1247 clks->push_back(clk);
1248 }
1249 else {
1250 for (auto clk : clocks_) {
1251 if (pattern->match(clk->name()))
1252 clks->push_back(clk);
1253 }
1254 }
1255 }
1256
1257 void
sortedClocks(ClockSeq & clks)1258 Sdc::sortedClocks(ClockSeq &clks)
1259 {
1260 for (auto clk : clocks_)
1261 clks.push_back(clk);
1262 sort(clks, ClkNameLess());
1263 }
1264
1265 ////////////////////////////////////////////////////////////////
1266
1267 class ClkHpinDisable
1268 {
1269 public:
1270 ClkHpinDisable(const Clock *clk,
1271 const Pin *from_pin,
1272 const Pin *to_pin);
clk() const1273 const Clock *clk() const { return clk_; }
fromPin() const1274 const Pin *fromPin() const { return from_pin_; }
toPin() const1275 const Pin *toPin() const { return to_pin_; }
1276
1277 private:
1278 const Clock *clk_;
1279 const Pin *from_pin_;
1280 const Pin *to_pin_;
1281 };
1282
ClkHpinDisable(const Clock * clk,const Pin * from_pin,const Pin * to_pin)1283 ClkHpinDisable::ClkHpinDisable(const Clock *clk,
1284 const Pin *from_pin,
1285 const Pin *to_pin) :
1286 clk_(clk),
1287 from_pin_(from_pin),
1288 to_pin_(to_pin)
1289 {
1290 }
1291
1292 bool
operator ()(const ClkHpinDisable * disable1,const ClkHpinDisable * disable2) const1293 ClkHpinDisableLess::operator()(const ClkHpinDisable *disable1,
1294 const ClkHpinDisable *disable2) const
1295 {
1296 int clk_index1 = disable1->clk()->index();
1297 int clk_index2 = disable2->clk()->index();
1298 if (clk_index1 == clk_index2) {
1299 const Pin *from_pin1 = disable1->fromPin();
1300 const Pin *from_pin2 = disable2->fromPin();
1301 if (from_pin1 == from_pin2) {
1302 const Pin *to_pin1 = disable1->toPin();
1303 const Pin *to_pin2 = disable2->toPin();
1304 return to_pin1 < to_pin2;
1305 }
1306 else
1307 return from_pin1 < from_pin2;
1308 }
1309 else
1310 return clk_index1 < clk_index2;
1311 }
1312
1313 class FindClkHpinDisables : public HpinDrvrLoadVisitor
1314 {
1315 public:
1316 FindClkHpinDisables(Clock *clk,
1317 const Network *network,
1318 Sdc *sdc);
1319 ~FindClkHpinDisables();
1320 bool drvrLoadExists(Pin *drvr,
1321 Pin *load);
1322
1323 protected:
1324 virtual void visit(HpinDrvrLoad *drvr_load);
1325 void makeClkHpinDisables(Pin *clk_src,
1326 Pin *drvr,
1327 Pin *load);
1328
1329 Clock *clk_;
1330 PinPairSet drvr_loads_;
1331 const Network *network_;
1332 Sdc *sdc_;
1333
1334 private:
1335 DISALLOW_COPY_AND_ASSIGN(FindClkHpinDisables);
1336 };
1337
FindClkHpinDisables(Clock * clk,const Network * network,Sdc * sdc)1338 FindClkHpinDisables::FindClkHpinDisables(Clock *clk,
1339 const Network *network,
1340 Sdc *sdc) :
1341 HpinDrvrLoadVisitor(),
1342 clk_(clk),
1343 network_(network),
1344 sdc_(sdc)
1345 {
1346 }
1347
~FindClkHpinDisables()1348 FindClkHpinDisables::~FindClkHpinDisables()
1349 {
1350 drvr_loads_.deleteContents();
1351 }
1352
1353 void
visit(HpinDrvrLoad * drvr_load)1354 FindClkHpinDisables::visit(HpinDrvrLoad *drvr_load)
1355 {
1356 Pin *drvr = drvr_load->drvr();
1357 Pin *load = drvr_load->load();
1358
1359 makeClkHpinDisables(drvr, drvr, load);
1360
1361 PinSet *hpins_from_drvr = drvr_load->hpinsFromDrvr();
1362 PinSet::Iterator hpin_iter(hpins_from_drvr);
1363 while (hpin_iter.hasNext()) {
1364 Pin *hpin = hpin_iter.next();
1365 makeClkHpinDisables(hpin, drvr, load);
1366 }
1367 drvr_loads_.insert(new PinPair(drvr, load));
1368 }
1369
1370 void
makeClkHpinDisables(Pin * clk_src,Pin * drvr,Pin * load)1371 FindClkHpinDisables::makeClkHpinDisables(Pin *clk_src,
1372 Pin *drvr,
1373 Pin *load)
1374 {
1375 ClockSet *clks = sdc_->findClocks(clk_src);
1376 ClockSet::Iterator clk_iter(clks);
1377 while (clk_iter.hasNext()) {
1378 Clock *clk = clk_iter.next();
1379 if (clk != clk_)
1380 // Do not propagate clock from source pin if another
1381 // clock is defined on a hierarchical pin between the
1382 // driver and load.
1383 sdc_->makeClkHpinDisable(clk, drvr, load);
1384 }
1385 }
1386
1387 bool
drvrLoadExists(Pin * drvr,Pin * load)1388 FindClkHpinDisables::drvrLoadExists(Pin *drvr,
1389 Pin *load)
1390 {
1391 PinPair probe(drvr, load);
1392 return drvr_loads_.hasKey(&probe);
1393 }
1394
1395 void
ensureClkHpinDisables()1396 Sdc::ensureClkHpinDisables()
1397 {
1398 if (!clk_hpin_disables_valid_) {
1399 clk_hpin_disables_.deleteContentsClear();
1400 for (auto clk : clocks_) {
1401 for (Pin *src : clk->pins()) {
1402 if (network_->isHierarchical(src)) {
1403 FindClkHpinDisables visitor1(clk, network_, this);
1404 visitHpinDrvrLoads(src, network_, &visitor1);
1405 PinSeq loads, drvrs;
1406 PinSet visited_drvrs;
1407 FindNetDrvrLoads visitor2(nullptr, visited_drvrs, loads, drvrs, network_);
1408 network_->visitConnectedPins(src, visitor2);
1409
1410 // Disable fanouts from the src driver pins that do
1411 // not go thru the hierarchical src pin.
1412 for (Pin *drvr : drvrs) {
1413 for (Pin *load : loads) {
1414 if (!visitor1.drvrLoadExists(drvr, load))
1415 makeClkHpinDisable(clk, drvr, load);
1416 }
1417 }
1418 }
1419 }
1420 }
1421 clk_hpin_disables_valid_ = true;
1422 }
1423 }
1424
1425 void
makeClkHpinDisable(Clock * clk,Pin * drvr,Pin * load)1426 Sdc::makeClkHpinDisable(Clock *clk,
1427 Pin *drvr,
1428 Pin *load)
1429 {
1430 ClkHpinDisable probe(clk, drvr, load);
1431 if (!clk_hpin_disables_.hasKey(&probe)) {
1432 ClkHpinDisable *disable = new ClkHpinDisable(clk, drvr, load);
1433 clk_hpin_disables_.insert(disable);
1434 }
1435 }
1436
1437 void
clkHpinDisablesInvalid()1438 Sdc::clkHpinDisablesInvalid()
1439 {
1440 clk_hpin_disables_valid_ = false;
1441 for (auto clk : clocks_)
1442 clk->makeLeafPins(network_);
1443 }
1444
1445 // Check that driver/load edge goes thru clock hpin.
1446 // Check for disable by hierarchical clock pin between driver and load.
1447 bool
clkDisabledByHpinThru(const Clock * clk,const Pin * from_pin,const Pin * to_pin)1448 Sdc::clkDisabledByHpinThru(const Clock *clk,
1449 const Pin *from_pin,
1450 const Pin *to_pin)
1451 {
1452 if (clk->leafPins().hasKey(const_cast<Pin*>(from_pin))) {
1453 ClkHpinDisable probe(clk, from_pin, to_pin);
1454 return clk_hpin_disables_.hasKey(&probe);
1455 }
1456 else
1457 return false;
1458 }
1459
1460 ////////////////////////////////////////////////////////////////
1461
1462 void
setPropagatedClock(Clock * clk)1463 Sdc::setPropagatedClock(Clock *clk)
1464 {
1465 clk->setIsPropagated(true);
1466 removeClockLatency(clk, nullptr);
1467 }
1468
1469 void
removePropagatedClock(Clock * clk)1470 Sdc::removePropagatedClock(Clock *clk)
1471 {
1472 clk->setIsPropagated(false);
1473 }
1474
1475 void
setPropagatedClock(Pin * pin)1476 Sdc::setPropagatedClock(Pin *pin)
1477 {
1478 propagated_clk_pins_.insert(pin);
1479 removeClockLatency(nullptr, pin);
1480 }
1481
1482 void
removePropagatedClock(Pin * pin)1483 Sdc::removePropagatedClock(Pin *pin)
1484 {
1485 propagated_clk_pins_.erase(pin);
1486 }
1487
1488 bool
isPropagatedClock(const Pin * pin)1489 Sdc::isPropagatedClock(const Pin *pin)
1490 {
1491 return propagated_clk_pins_.hasKey(const_cast<Pin*>(pin));
1492 }
1493
1494 void
setClockSlew(Clock * clk,const RiseFallBoth * rf,const MinMaxAll * min_max,float slew)1495 Sdc::setClockSlew(Clock *clk,
1496 const RiseFallBoth *rf,
1497 const MinMaxAll *min_max,
1498 float slew)
1499 {
1500 clk->setSlew(rf, min_max, slew);
1501 }
1502
1503 void
removeClockSlew(Clock * clk)1504 Sdc::removeClockSlew(Clock *clk)
1505 {
1506 clk->removeSlew();
1507 }
1508
1509 void
setClockLatency(Clock * clk,Pin * pin,const RiseFallBoth * rf,const MinMaxAll * min_max,float delay)1510 Sdc::setClockLatency(Clock *clk,
1511 Pin *pin,
1512 const RiseFallBoth *rf,
1513 const MinMaxAll *min_max,
1514 float delay)
1515 {
1516 ClockLatency probe(clk, pin);
1517 ClockLatency *latency = clk_latencies_.findKey(&probe);
1518 if (latency == nullptr) {
1519 latency = new ClockLatency(clk, pin);
1520 clk_latencies_.insert(latency);
1521 }
1522 latency->setDelay(rf, min_max, delay);
1523
1524 // set_clock_latency removes set_propagated_clock on the same object.
1525 if (clk && pin == nullptr)
1526 removePropagatedClock(clk);
1527 if (pin)
1528 removePropagatedClock(pin);
1529 }
1530
1531 void
removeClockLatency(const Clock * clk,const Pin * pin)1532 Sdc::removeClockLatency(const Clock *clk,
1533 const Pin *pin)
1534 {
1535 ClockLatency probe(clk, pin);
1536 ClockLatency *latency = clk_latencies_.findKey(&probe);
1537 if (latency)
1538 deleteClockLatency(latency);
1539 }
1540
1541 void
deleteClockLatency(ClockLatency * latency)1542 Sdc::deleteClockLatency(ClockLatency *latency)
1543 {
1544 clk_latencies_.erase(latency);
1545 delete latency;
1546 }
1547
1548 void
deleteClockLatenciesReferencing(Clock * clk)1549 Sdc::deleteClockLatenciesReferencing(Clock *clk)
1550 {
1551 ClockLatencies::Iterator latency_iter(clk_latencies_);
1552 while (latency_iter.hasNext()) {
1553 ClockLatency *latency = latency_iter.next();
1554 if (latency->clock() == clk)
1555 deleteClockLatency(latency);
1556 }
1557 }
1558
1559 bool
hasClockLatency(const Pin * pin) const1560 Sdc::hasClockLatency(const Pin *pin) const
1561 {
1562 ClockLatency probe(nullptr, pin);
1563 return clk_latencies_.hasKey(&probe);
1564 }
1565
1566 void
clockLatency(const Clock * clk,const Pin * pin,const RiseFall * rf,const MinMax * min_max,float & latency,bool & exists) const1567 Sdc::clockLatency(const Clock *clk,
1568 const Pin *pin,
1569 const RiseFall *rf,
1570 const MinMax *min_max,
1571 // Return values.
1572 float &latency,
1573 bool &exists) const
1574 {
1575 latency = 0.0;
1576 exists = false;
1577 if (pin && clk) {
1578 ClockLatency probe(clk, pin);
1579 ClockLatency *latencies = clk_latencies_.findKey(&probe);
1580 if (latencies)
1581 latencies->delay(rf, min_max, latency, exists);
1582 }
1583 if (!exists) {
1584 ClockLatency probe(nullptr, pin);
1585 ClockLatency *latencies = clk_latencies_.findKey(&probe);
1586 if (latencies)
1587 latencies->delay(rf, min_max, latency, exists);
1588 }
1589 }
1590
1591 void
clockLatency(const Clock * clk,const RiseFall * rf,const MinMax * min_max,float & latency,bool & exists) const1592 Sdc::clockLatency(const Clock *clk,
1593 const RiseFall *rf,
1594 const MinMax *min_max,
1595 // Return values.
1596 float &latency,
1597 bool &exists) const
1598 {
1599 latency = 0.0;
1600 exists = false;
1601 ClockLatency probe(clk, nullptr);
1602 ClockLatency *latencies = clk_latencies_.findKey(&probe);
1603 if (latencies)
1604 latencies->delay(rf, min_max, latency, exists);
1605 }
1606
1607 float
clockLatency(const Clock * clk,const RiseFall * rf,const MinMax * min_max) const1608 Sdc::clockLatency(const Clock *clk,
1609 const RiseFall *rf,
1610 const MinMax *min_max) const
1611 {
1612 float latency;
1613 bool exists;
1614 clockLatency(clk, rf, min_max,
1615 latency, exists);
1616 return latency;
1617 }
1618
1619 void
setClockUncertainty(Pin * pin,const SetupHoldAll * setup_hold,float uncertainty)1620 Sdc::setClockUncertainty(Pin *pin,
1621 const SetupHoldAll *setup_hold,
1622 float uncertainty)
1623 {
1624 ClockUncertainties *uncertainties = pin_clk_uncertainty_map_.findKey(pin);
1625 if (uncertainties == nullptr) {
1626 uncertainties = new ClockUncertainties;
1627 pin_clk_uncertainty_map_[pin] = uncertainties;
1628 }
1629 uncertainties->setValue(setup_hold, uncertainty);
1630 }
1631
1632 void
removeClockUncertainty(Pin * pin,const SetupHoldAll * setup_hold)1633 Sdc::removeClockUncertainty(Pin *pin,
1634 const SetupHoldAll *setup_hold)
1635 {
1636 ClockUncertainties *uncertainties = pin_clk_uncertainty_map_.findKey(pin);
1637 if (uncertainties) {
1638 uncertainties->removeValue(setup_hold);
1639 if (uncertainties->empty()) {
1640 delete uncertainties;
1641 pin_clk_uncertainty_map_.erase(pin);
1642 }
1643 }
1644 }
1645
1646 ClockUncertainties *
clockUncertainties(const Pin * pin)1647 Sdc::clockUncertainties(const Pin *pin)
1648 {
1649 return pin_clk_uncertainty_map_.findKey(pin);
1650 }
1651
1652 void
clockUncertainty(const Pin * pin,const SetupHold * setup_hold,float & uncertainty,bool & exists)1653 Sdc::clockUncertainty(const Pin *pin,
1654 const SetupHold *setup_hold,
1655 float &uncertainty,
1656 bool &exists)
1657 {
1658 ClockUncertainties *uncertainties = clockUncertainties(pin);
1659 if (uncertainties)
1660 uncertainties->value(setup_hold, uncertainty, exists);
1661 else {
1662 uncertainty = 0.0;
1663 exists = false;
1664 }
1665 }
1666
1667 void
clockUncertainty(const Clock * src_clk,const RiseFall * src_rf,const Clock * tgt_clk,const RiseFall * tgt_rf,const SetupHold * setup_hold,float & uncertainty,bool & exists)1668 Sdc::clockUncertainty(const Clock *src_clk,
1669 const RiseFall *src_rf,
1670 const Clock *tgt_clk,
1671 const RiseFall *tgt_rf,
1672 const SetupHold *setup_hold,
1673 float &uncertainty,
1674 bool &exists)
1675 {
1676 InterClockUncertainty probe(src_clk, tgt_clk);
1677 InterClockUncertainty *uncertainties =
1678 inter_clk_uncertainties_.findKey(&probe);
1679 if (uncertainties)
1680 uncertainties->uncertainty(src_rf, tgt_rf, setup_hold,
1681 uncertainty, exists);
1682 else {
1683 uncertainty = 0.0;
1684 exists = false;
1685 }
1686 }
1687
1688 void
setClockUncertainty(Clock * from_clk,const RiseFallBoth * from_rf,Clock * to_clk,const RiseFallBoth * to_rf,const SetupHoldAll * setup_hold,float uncertainty)1689 Sdc::setClockUncertainty(Clock *from_clk,
1690 const RiseFallBoth *from_rf,
1691 Clock *to_clk,
1692 const RiseFallBoth *to_rf,
1693 const SetupHoldAll *setup_hold,
1694 float uncertainty)
1695 {
1696 InterClockUncertainty probe(from_clk, to_clk);
1697 InterClockUncertainty *uncertainties =
1698 inter_clk_uncertainties_.findKey(&probe);
1699 if (uncertainties == nullptr) {
1700 uncertainties = new InterClockUncertainty(from_clk, to_clk);
1701 inter_clk_uncertainties_.insert(uncertainties);
1702 }
1703 uncertainties->setUncertainty(from_rf, to_rf, setup_hold, uncertainty);
1704 }
1705
1706 void
removeClockUncertainty(Clock * from_clk,const RiseFallBoth * from_rf,Clock * to_clk,const RiseFallBoth * to_rf,const SetupHoldAll * setup_hold)1707 Sdc::removeClockUncertainty(Clock *from_clk,
1708 const RiseFallBoth *from_rf,
1709 Clock *to_clk,
1710 const RiseFallBoth *to_rf,
1711 const SetupHoldAll *setup_hold)
1712 {
1713 InterClockUncertainty probe(from_clk, to_clk);
1714 InterClockUncertainty *uncertainties =
1715 inter_clk_uncertainties_.findKey(&probe);
1716 if (uncertainties) {
1717 uncertainties->removeUncertainty(from_rf, to_rf, setup_hold);
1718 if (uncertainties->empty()) {
1719 inter_clk_uncertainties_.erase(uncertainties);
1720 delete uncertainties;
1721 }
1722 }
1723 }
1724
1725 void
deleteInterClockUncertainty(InterClockUncertainty * uncertainties)1726 Sdc::deleteInterClockUncertainty(InterClockUncertainty *uncertainties)
1727 {
1728 inter_clk_uncertainties_.erase(uncertainties);
1729 delete uncertainties;
1730 }
1731
1732 void
deleteInterClockUncertaintiesReferencing(Clock * clk)1733 Sdc::deleteInterClockUncertaintiesReferencing(Clock *clk)
1734 {
1735 InterClockUncertaintySet::Iterator inter_iter(inter_clk_uncertainties_);
1736 while (inter_iter.hasNext()) {
1737 InterClockUncertainty *uncertainties = inter_iter.next();
1738 if (uncertainties->src() == clk
1739 || uncertainties->target() == clk)
1740 deleteInterClockUncertainty(uncertainties);
1741 }
1742 }
1743
1744 ////////////////////////////////////////////////////////////////
1745
1746 void
setClockInsertion(const Clock * clk,const Pin * pin,const RiseFallBoth * rf,const MinMaxAll * min_max,const EarlyLateAll * early_late,float delay)1747 Sdc::setClockInsertion(const Clock *clk,
1748 const Pin *pin,
1749 const RiseFallBoth *rf,
1750 const MinMaxAll *min_max,
1751 const EarlyLateAll *early_late,
1752 float delay)
1753 {
1754 if (clk_insertions_ == nullptr)
1755 clk_insertions_ = new ClockInsertions;
1756 ClockInsertion probe(clk, pin);
1757 ClockInsertion *insertion = clk_insertions_->findKey(&probe);
1758 if (insertion == nullptr) {
1759 insertion = new ClockInsertion(clk, pin);
1760 clk_insertions_->insert(insertion);
1761 }
1762 insertion->setDelay(rf, min_max, early_late, delay);
1763 }
1764
1765 void
setClockInsertion(const Clock * clk,const Pin * pin,const RiseFall * rf,const MinMax * min_max,const EarlyLate * early_late,float delay)1766 Sdc::setClockInsertion(const Clock *clk,
1767 const Pin *pin,
1768 const RiseFall *rf,
1769 const MinMax *min_max,
1770 const EarlyLate *early_late,
1771 float delay)
1772 {
1773 if (clk_insertions_ == nullptr)
1774 clk_insertions_ = new ClockInsertions;
1775 ClockInsertion probe(clk, pin);
1776 ClockInsertion *insertion = clk_insertions_->findKey(&probe);
1777 if (insertion == nullptr) {
1778 insertion = new ClockInsertion(clk, pin);
1779 clk_insertions_->insert(insertion);
1780 }
1781 insertion->setDelay(rf, min_max, early_late, delay);
1782 }
1783
1784 void
removeClockInsertion(const Clock * clk,const Pin * pin)1785 Sdc::removeClockInsertion(const Clock *clk,
1786 const Pin *pin)
1787 {
1788 if (clk_insertions_) {
1789 ClockInsertion probe(clk, pin);
1790 ClockInsertion *insertion = clk_insertions_->findKey(&probe);
1791 if (insertion != nullptr)
1792 deleteClockInsertion(insertion);
1793 }
1794 }
1795
1796 void
deleteClockInsertion(ClockInsertion * insertion)1797 Sdc::deleteClockInsertion(ClockInsertion *insertion)
1798 {
1799 clk_insertions_->erase(insertion);
1800 delete insertion;
1801 }
1802
1803 void
deleteClockInsertionsReferencing(Clock * clk)1804 Sdc::deleteClockInsertionsReferencing(Clock *clk)
1805 {
1806 ClockInsertions::Iterator insertion_iter(clk_insertions_);
1807 while (insertion_iter.hasNext()) {
1808 ClockInsertion *insertion = insertion_iter.next();
1809 if (insertion->clock() == clk)
1810 deleteClockInsertion(insertion);
1811 }
1812 }
1813
1814 float
clockInsertion(const Clock * clk,const RiseFall * rf,const MinMax * min_max,const EarlyLate * early_late) const1815 Sdc::clockInsertion(const Clock *clk,
1816 const RiseFall *rf,
1817 const MinMax *min_max,
1818 const EarlyLate *early_late) const
1819 {
1820 float insertion;
1821 bool exists;
1822 clockInsertion(clk, nullptr, rf, min_max, early_late, insertion, exists);
1823 return insertion;
1824 }
1825
1826 bool
hasClockInsertion(const Pin * pin) const1827 Sdc::hasClockInsertion(const Pin *pin) const
1828 {
1829 if (clk_insertions_) {
1830 ClockInsertion probe(nullptr, pin);
1831 return clk_insertions_->hasKey(&probe);
1832 }
1833 else
1834 return false;
1835 }
1836
1837 void
clockInsertion(const Clock * clk,const Pin * pin,const RiseFall * rf,const MinMax * min_max,const EarlyLate * early_late,float & insertion,bool & exists) const1838 Sdc::clockInsertion(const Clock *clk,
1839 const Pin *pin,
1840 const RiseFall *rf,
1841 const MinMax *min_max,
1842 const EarlyLate *early_late,
1843 // Return values.
1844 float &insertion,
1845 bool &exists) const
1846 {
1847 ClockInsertion *insert = nullptr;
1848 if (clk_insertions_) {
1849 if (clk && pin) {
1850 ClockInsertion probe(clk, pin);
1851 insert = clk_insertions_->findKey(&probe);
1852 }
1853 if (insert == nullptr && pin) {
1854 ClockInsertion probe(nullptr, pin);
1855 insert = clk_insertions_->findKey(&probe);
1856 }
1857 if (insert == nullptr && clk) {
1858 ClockInsertion probe(clk, nullptr);
1859 insert = clk_insertions_->findKey(&probe);
1860 }
1861 }
1862 if (insert)
1863 insert->delay(rf, min_max, early_late, insertion, exists);
1864 else {
1865 insertion = 0.0;
1866 exists = false;
1867 }
1868 }
1869
1870 ////////////////////////////////////////////////////////////////
1871
1872 bool
operator ()(const ClockLatency * latency1,const ClockLatency * latency2) const1873 ClockLatencyPinClkLess::operator()(const ClockLatency *latency1,
1874 const ClockLatency *latency2) const
1875 {
1876 const Clock *clk1 = latency1->clock();
1877 const Clock *clk2 = latency2->clock();
1878 const Pin *pin1 = latency1->pin();
1879 const Pin *pin2 = latency2->pin();
1880 return clk1 < clk2
1881 || (clk1 == clk2
1882 && pin1 < pin2);
1883 }
1884
1885 ////////////////////////////////////////////////////////////////
1886
1887 bool
operator ()(const ClockInsertion * insert1,const ClockInsertion * insert2) const1888 ClockInsertionPinClkLess::operator()(const ClockInsertion *insert1,
1889 const ClockInsertion *insert2)const
1890 {
1891 const Clock *clk1 = insert1->clock();
1892 const Clock *clk2 = insert2->clock();
1893 const Pin *pin1 = insert1->pin();
1894 const Pin *pin2 = insert2->pin();
1895 return (clk1 && clk2
1896 && (clk1 < clk2
1897 || (clk1 == clk2
1898 && pin1 && pin2
1899 && pin1 < pin2)))
1900 || (clk1 == nullptr && clk2)
1901 || (clk1 == nullptr && clk2 == nullptr
1902 && ((pin1 && pin2
1903 && pin1 < pin2)
1904 || (pin1 == nullptr && pin2)));
1905 }
1906
1907 ////////////////////////////////////////////////////////////////
1908
1909 ClockGroups *
makeClockGroups(const char * name,bool logically_exclusive,bool physically_exclusive,bool asynchronous,bool allow_paths,const char * comment)1910 Sdc::makeClockGroups(const char *name,
1911 bool logically_exclusive,
1912 bool physically_exclusive,
1913 bool asynchronous,
1914 bool allow_paths,
1915 const char *comment)
1916 {
1917 char *gen_name = nullptr;
1918 if (name == nullptr
1919 || name[0] == '\0')
1920 name = gen_name = makeClockGroupsName();
1921 else {
1922 ClockGroups *groups = clk_groups_name_map_.findKey(name);
1923 if (groups)
1924 removeClockGroups(groups);
1925 }
1926 ClockGroups *groups = new ClockGroups(name, logically_exclusive,
1927 physically_exclusive,
1928 asynchronous, allow_paths, comment);
1929 clk_groups_name_map_[groups->name()] = groups;
1930 stringDelete(gen_name);
1931 return groups;
1932 }
1933
1934 // Generate a name for the clock group.
1935 char *
makeClockGroupsName()1936 Sdc::makeClockGroupsName()
1937 {
1938 char *name = nullptr;
1939 int i = 0;
1940 do {
1941 i++;
1942 stringDelete(name);
1943 name = stringPrint("group%d", i);
1944 } while (clk_groups_name_map_.hasKey(name));
1945 return name;
1946 }
1947
1948 void
makeClockGroup(ClockGroups * clk_groups,ClockSet * clks)1949 Sdc::makeClockGroup(ClockGroups *clk_groups,
1950 ClockSet *clks)
1951 {
1952 clk_groups->makeClockGroup(clks);
1953 }
1954
1955 ClockGroupIterator *
clockGroupIterator()1956 Sdc::clockGroupIterator()
1957 {
1958 return new ClockGroupIterator(clk_groups_name_map_);
1959 }
1960
1961 void
ensureClkGroupExclusions()1962 Sdc::ensureClkGroupExclusions()
1963 {
1964 if (clk_group_exclusions_ == nullptr) {
1965 clk_group_exclusions_ = new ClockPairSet;
1966 clk_group_same_ = new ClockPairSet;
1967 for (auto name_clk_groups : clk_groups_name_map_)
1968 makeClkGroupExclusions(name_clk_groups.second);
1969 }
1970 }
1971
1972 void
makeClkGroupExclusions(ClockGroups * clk_groups)1973 Sdc::makeClkGroupExclusions(ClockGroups *clk_groups)
1974 {
1975 if (!(clk_groups->asynchronous()
1976 && clk_groups->allowPaths())) {
1977 ClockGroupSet *groups = clk_groups->groups();
1978 if (groups->size() == 1)
1979 makeClkGroupExclusions1(groups);
1980 else
1981 makeClkGroupExclusions(groups);
1982 }
1983 }
1984
1985 // If there is only one group all clocks not in the group
1986 // are excluded.
1987 void
makeClkGroupExclusions1(ClockGroupSet * groups)1988 Sdc::makeClkGroupExclusions1(ClockGroupSet *groups)
1989 {
1990 ClockGroupSet::Iterator group_iter1(groups);
1991 ClockGroup *group1 = group_iter1.next();
1992 ClockSet *clks1 = group1->clks();
1993 for (auto clk1 : *clks1) {
1994 for (Clock *clk2 : clocks_) {
1995 if (clk2 != clk1
1996 && !group1->isMember(clk2))
1997 clk_group_exclusions_->insert(ClockPair(clk1, clk2));
1998 }
1999 }
2000 makeClkGroupSame(group1);
2001 }
2002
2003 void
makeClkGroupExclusions(ClockGroupSet * groups)2004 Sdc::makeClkGroupExclusions(ClockGroupSet *groups)
2005 {
2006 for (auto group1 : *groups) {
2007 ClockSet *clks1 = group1->clks();
2008 for (auto group2 : *groups) {
2009 if (group1 != group2) {
2010 ClockSet *clks2 = group2->clks();
2011 for (auto clk1 : *clks1) {
2012 for (auto clk2 : *clks2) {
2013 // ClockPair is symmetric so only add one clk1/clk2 pair.
2014 if (clk1->index() < clk2->index()) {
2015 clk_group_exclusions_->insert(ClockPair(clk1, clk2));
2016 }
2017 }
2018 }
2019 }
2020 }
2021 makeClkGroupSame(group1);
2022 }
2023 }
2024
2025 void
makeClkGroupSame(ClockGroup * group)2026 Sdc::makeClkGroupSame(ClockGroup *group)
2027 {
2028 ClockSet *clks = group->clks();
2029 for (auto clk1 : *clks) {
2030 for (auto clk2 : *clks) {
2031 if (clk1->index() <= clk2->index()) {
2032 ClockPair clk_pair(clk1, clk2);
2033 if (!clk_group_same_->hasKey(clk_pair))
2034 clk_group_same_->insert(clk_pair);
2035 }
2036 }
2037 }
2038 }
2039
2040 void
clearClkGroupExclusions()2041 Sdc::clearClkGroupExclusions()
2042 {
2043 if (clk_group_exclusions_) {
2044 delete clk_group_exclusions_;
2045 delete clk_group_same_;
2046 clk_group_exclusions_ = nullptr;
2047 clk_group_same_ = nullptr;
2048 }
2049 }
2050
2051 bool
sameClockGroup(const Clock * clk1,const Clock * clk2)2052 Sdc::sameClockGroup(const Clock *clk1,
2053 const Clock *clk2)
2054 {
2055 if (clk1 && clk2) {
2056 ClockPair clk_pair(clk1, clk2);
2057 bool excluded = clk_group_exclusions_->hasKey(clk_pair);
2058 return !excluded;
2059 }
2060 else
2061 return true;
2062 }
2063
2064 bool
sameClockGroupExplicit(const Clock * clk1,const Clock * clk2)2065 Sdc::sameClockGroupExplicit(const Clock *clk1,
2066 const Clock *clk2)
2067 {
2068 ClockPair clk_pair(clk1, clk2);
2069 return clk_group_same_->hasKey(clk_pair);
2070 }
2071
2072 void
removeClockGroups(const char * name)2073 Sdc::removeClockGroups(const char *name)
2074 {
2075 ClockGroups *clk_groups = clk_groups_name_map_.findKey(name);
2076 if (clk_groups)
2077 removeClockGroups(clk_groups);
2078 }
2079
2080 void
removeClockGroupsLogicallyExclusive(const char * name)2081 Sdc::removeClockGroupsLogicallyExclusive(const char *name)
2082 {
2083 if (name) {
2084 ClockGroups *groups = clk_groups_name_map_.findKey(name);
2085 if (groups->logicallyExclusive())
2086 removeClockGroups(groups);
2087 }
2088 else {
2089 ClockGroupsNameMap::Iterator groups_iter(clk_groups_name_map_);
2090 while (groups_iter.hasNext()) {
2091 ClockGroups *groups = groups_iter.next();
2092 if (groups->logicallyExclusive())
2093 removeClockGroups(groups);
2094 }
2095 }
2096 }
2097
2098 void
removeClockGroupsPhysicallyExclusive(const char * name)2099 Sdc::removeClockGroupsPhysicallyExclusive(const char *name)
2100 {
2101 if (name) {
2102 ClockGroups *groups = clk_groups_name_map_.findKey(name);
2103 if (groups->physicallyExclusive())
2104 removeClockGroups(groups);
2105 }
2106 else {
2107 ClockGroupsNameMap::Iterator groups_iter(clk_groups_name_map_);
2108 while (groups_iter.hasNext()) {
2109 ClockGroups *groups = groups_iter.next();
2110 if (groups->physicallyExclusive())
2111 removeClockGroups(groups);
2112 }
2113 }
2114 }
2115
2116 void
removeClockGroupsAsynchronous(const char * name)2117 Sdc::removeClockGroupsAsynchronous(const char *name)
2118 {
2119 if (name) {
2120 ClockGroups *groups = clk_groups_name_map_.findKey(name);
2121 if (groups->asynchronous())
2122 removeClockGroups(groups);
2123 }
2124 else {
2125 ClockGroupsNameMap::Iterator groups_iter(clk_groups_name_map_);
2126 while (groups_iter.hasNext()) {
2127 ClockGroups *groups = groups_iter.next();
2128 if (groups->asynchronous())
2129 removeClockGroups(groups);
2130 }
2131 }
2132 }
2133
2134 void
removeClockGroups(ClockGroups * groups)2135 Sdc::removeClockGroups(ClockGroups *groups)
2136 {
2137 clk_groups_name_map_.erase(groups->name());
2138 delete groups;
2139 // Can't delete excluded clock pairs for deleted clock groups because
2140 // some other clock groups may exclude the same clock pair.
2141 clearClkGroupExclusions();
2142 }
2143
2144 void
clockGroupsDeleteClkRefs(Clock * clk)2145 Sdc::clockGroupsDeleteClkRefs(Clock *clk)
2146 {
2147 ClockGroupsNameMap::Iterator groups_iter(clk_groups_name_map_);
2148 while (groups_iter.hasNext()) {
2149 ClockGroups *groups = groups_iter.next();
2150 groups->removeClock(clk);
2151 }
2152 clearClkGroupExclusions();
2153 }
2154
2155 ////////////////////////////////////////////////////////////////
2156
2157 void
setClockSense(PinSet * pins,ClockSet * clks,ClockSense sense)2158 Sdc::setClockSense(PinSet *pins,
2159 ClockSet *clks,
2160 ClockSense sense)
2161 {
2162 if (clks && clks->empty()) {
2163 delete clks;
2164 clks = nullptr;
2165 }
2166 PinSet::Iterator pin_iter(pins);
2167 while (pin_iter.hasNext()) {
2168 Pin *pin = pin_iter.next();
2169 if (clks) {
2170 ClockSet::Iterator clk_iter(clks);
2171 while (clk_iter.hasNext()) {
2172 Clock *clk = clk_iter.next();
2173 setClockSense(pin, clk, sense);
2174 }
2175 }
2176 else
2177 setClockSense(pin, nullptr, sense);
2178 }
2179 delete pins;
2180 delete clks;
2181 }
2182
2183 void
setClockSense(const Pin * pin,const Clock * clk,ClockSense sense)2184 Sdc::setClockSense(const Pin *pin,
2185 const Clock *clk,
2186 ClockSense sense)
2187 {
2188 PinClockPair probe(pin, clk);
2189 if (clk_sense_map_.hasKey(probe))
2190 clk_sense_map_[probe] = sense;
2191 else {
2192 PinClockPair pin_clk(pin, clk);
2193 clk_sense_map_[pin_clk] = sense;
2194 }
2195 }
2196
2197 bool
clkStopPropagation(const Pin * pin,const Clock * clk) const2198 Sdc::clkStopPropagation(const Pin *pin,
2199 const Clock *clk) const
2200 {
2201 PinClockPair pin_clk(pin, clk);
2202 ClockSense sense;
2203 bool exists;
2204 clk_sense_map_.findKey(pin_clk, sense, exists);
2205 if (!exists) {
2206 PinClockPair pin_clk1(pin, nullptr);
2207 clk_sense_map_.findKey(pin_clk1, sense, exists);
2208 }
2209 return exists
2210 && sense == ClockSense::stop;
2211 }
2212
2213 bool
clkStopSense(const Pin * to_pin,const Clock * clk,const RiseFall * from_rf,const RiseFall * to_rf) const2214 Sdc::clkStopSense(const Pin *to_pin,
2215 const Clock *clk,
2216 const RiseFall *from_rf,
2217 const RiseFall *to_rf) const
2218 {
2219 PinClockPair pin_clk(to_pin, clk);
2220 ClockSense sense;
2221 bool exists;
2222 clk_sense_map_.findKey(pin_clk, sense, exists);
2223 if (!exists) {
2224 PinClockPair pin(to_pin, nullptr);
2225 clk_sense_map_.findKey(pin, sense, exists);
2226 }
2227 return exists
2228 && (sense == ClockSense::stop
2229 || (sense == ClockSense::positive
2230 && from_rf != to_rf)
2231 || (sense == ClockSense::negative
2232 && from_rf == to_rf));
2233 }
2234
2235 bool
clkStopPropagation(const Clock * clk,const Pin * from_pin,const RiseFall * from_rf,const Pin * to_pin,const RiseFall * to_rf) const2236 Sdc::clkStopPropagation(const Clock *clk,
2237 const Pin *from_pin,
2238 const RiseFall *from_rf,
2239 const Pin *to_pin,
2240 const RiseFall *to_rf) const
2241 {
2242 return clkStopPropagation(from_pin, clk)
2243 || clkStopSense(to_pin, clk, from_rf, to_rf);
2244 }
2245
PinClockPairLess(const Network * network)2246 PinClockPairLess::PinClockPairLess(const Network *network) :
2247 network_(network)
2248 {
2249 }
2250
2251 bool
operator ()(const PinClockPair & pin_clk1,const PinClockPair & pin_clk2) const2252 PinClockPairLess::operator()(const PinClockPair &pin_clk1,
2253 const PinClockPair &pin_clk2) const
2254 {
2255 const Pin *pin1 = pin_clk1.first;
2256 const Pin *pin2 = pin_clk2.first;
2257 const Clock *clk1 = pin_clk1.second;
2258 const Clock *clk2 = pin_clk2.second;
2259 return pin1 < pin2
2260 || (pin1 == pin2
2261 && ((clk1 == nullptr && clk2)
2262 || (clk1 && clk2
2263 && clk1->index() < clk2->index())));
2264 }
2265
2266 ////////////////////////////////////////////////////////////////
2267
2268 void
setClockGatingCheck(const RiseFallBoth * rf,const SetupHold * setup_hold,float margin)2269 Sdc::setClockGatingCheck(const RiseFallBoth *rf,
2270 const SetupHold *setup_hold,
2271 float margin)
2272 {
2273 if (clk_gating_check_ == nullptr)
2274 clk_gating_check_ = new ClockGatingCheck;
2275 clk_gating_check_->margins()->setValue(rf, setup_hold, margin);
2276 }
2277
2278 void
setClockGatingCheck(Clock * clk,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin)2279 Sdc::setClockGatingCheck(Clock *clk,
2280 const RiseFallBoth *rf,
2281 const SetupHold *setup_hold,
2282 float margin)
2283 {
2284 ClockGatingCheck *check = clk_gating_check_map_.findKey(clk);
2285 if (check == nullptr) {
2286 check = new ClockGatingCheck();
2287 clk_gating_check_map_[clk] = check;
2288 }
2289 check->margins()->setValue(rf, setup_hold, margin);
2290 }
2291
2292 void
setClockGatingCheck(Instance * inst,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin,LogicValue active_value)2293 Sdc::setClockGatingCheck(Instance *inst,
2294 const RiseFallBoth *rf,
2295 const SetupHold *setup_hold,
2296 float margin,
2297 LogicValue active_value)
2298 {
2299 ClockGatingCheck *check = inst_clk_gating_check_map_.findKey(inst);
2300 if (check == nullptr) {
2301 check = new ClockGatingCheck();
2302 inst_clk_gating_check_map_[inst] = check;
2303 }
2304 check->margins()->setValue(rf, setup_hold, margin);
2305 check->setActiveValue(active_value);
2306 }
2307
2308 void
setClockGatingCheck(const Pin * pin,const RiseFallBoth * rf,const SetupHold * setup_hold,float margin,LogicValue active_value)2309 Sdc::setClockGatingCheck(const Pin *pin,
2310 const RiseFallBoth *rf,
2311 const SetupHold *setup_hold,
2312 float margin,
2313 LogicValue active_value)
2314 {
2315 ClockGatingCheck *check = pin_clk_gating_check_map_.findKey(pin);
2316 if (check == nullptr) {
2317 check = new ClockGatingCheck();
2318 pin_clk_gating_check_map_[pin] = check;
2319 }
2320 check->margins()->setValue(rf, setup_hold, margin);
2321 check->setActiveValue(active_value);
2322 }
2323
2324 void
clockGatingMarginEnablePin(const Pin * enable_pin,const RiseFall * enable_rf,const SetupHold * setup_hold,bool & exists,float & margin)2325 Sdc::clockGatingMarginEnablePin(const Pin *enable_pin,
2326 const RiseFall *enable_rf,
2327 const SetupHold *setup_hold,
2328 bool &exists, float &margin)
2329 {
2330 ClockGatingCheck *check = pin_clk_gating_check_map_.findKey(enable_pin);
2331 if (check)
2332 check->margins()->value(enable_rf, setup_hold, margin, exists);
2333 else
2334 exists = false;
2335 }
2336
2337 void
clockGatingMarginInstance(Instance * inst,const RiseFall * enable_rf,const SetupHold * setup_hold,bool & exists,float & margin)2338 Sdc::clockGatingMarginInstance(Instance *inst,
2339 const RiseFall *enable_rf,
2340 const SetupHold *setup_hold,
2341 bool &exists,
2342 float &margin)
2343 {
2344 ClockGatingCheck *check = inst_clk_gating_check_map_.findKey(inst);
2345 if (check)
2346 check->margins()->value(enable_rf, setup_hold, margin, exists);
2347 else
2348 exists = false;
2349 }
2350
2351 void
clockGatingMarginClkPin(const Pin * clk_pin,const RiseFall * enable_rf,const SetupHold * setup_hold,bool & exists,float & margin)2352 Sdc::clockGatingMarginClkPin(const Pin *clk_pin,
2353 const RiseFall *enable_rf,
2354 const SetupHold *setup_hold,
2355 bool &exists,
2356 float &margin)
2357 {
2358 ClockGatingCheck *check = pin_clk_gating_check_map_.findKey(clk_pin);
2359 if (check)
2360 check->margins()->value(enable_rf, setup_hold, margin, exists);
2361 else
2362 exists = false;
2363 }
2364
2365 void
clockGatingMarginClk(const Clock * clk,const RiseFall * enable_rf,const SetupHold * setup_hold,bool & exists,float & margin)2366 Sdc::clockGatingMarginClk(const Clock *clk,
2367 const RiseFall *enable_rf,
2368 const SetupHold *setup_hold,
2369 bool &exists,
2370 float &margin)
2371 {
2372 ClockGatingCheck *check = clk_gating_check_map_.findKey(clk);
2373 if (check)
2374 check->margins()->value(enable_rf, setup_hold, margin, exists);
2375 else
2376 exists = false;
2377 }
2378
2379 void
clockGatingMargin(const RiseFall * enable_rf,const SetupHold * setup_hold,bool & exists,float & margin)2380 Sdc::clockGatingMargin(const RiseFall *enable_rf,
2381 const SetupHold *setup_hold,
2382 bool &exists,
2383 float &margin)
2384 {
2385 if (clk_gating_check_)
2386 clk_gating_check_->margins()->value(enable_rf, setup_hold, margin, exists);
2387 else
2388 exists = false;
2389 }
2390
2391 LogicValue
clockGatingActiveValue(const Pin * clk_pin,const Pin * enable_pin)2392 Sdc::clockGatingActiveValue(const Pin *clk_pin,
2393 const Pin *enable_pin)
2394 {
2395 ClockGatingCheck *check;
2396 check = pin_clk_gating_check_map_.findKey(enable_pin);
2397 if (check)
2398 return check->activeValue();
2399 Instance *inst = network_->instance(enable_pin);
2400 check = inst_clk_gating_check_map_.findKey(inst);
2401 if (check)
2402 return check->activeValue();
2403 check = pin_clk_gating_check_map_.findKey(clk_pin);
2404 if (check)
2405 return check->activeValue();
2406 return LogicValue::unknown;
2407 }
2408
2409 ////////////////////////////////////////////////////////////////
2410
2411 // Determine cycle accounting "on demand".
2412 CycleAccting *
cycleAccting(const ClockEdge * src,const ClockEdge * tgt)2413 Sdc::cycleAccting(const ClockEdge *src,
2414 const ClockEdge *tgt)
2415 {
2416 if (src == nullptr)
2417 src = tgt;
2418 CycleAccting *acct;
2419 CycleAccting probe(src, tgt);
2420 acct = cycle_acctings_.findKey(&probe);
2421 if (acct == nullptr) {
2422 UniqueLock lock(cycle_acctings_lock_);
2423 // Recheck with lock.
2424 acct = cycle_acctings_.findKey(&probe);
2425 if (acct == nullptr) {
2426 acct = new CycleAccting(src, tgt);
2427 if (src == defaultArrivalClockEdge())
2428 acct->findDefaultArrivalSrcDelays();
2429 else
2430 acct->findDelays(this);
2431 cycle_acctings_.insert(acct);
2432 }
2433 }
2434 return acct;
2435 }
2436
2437 void
reportClkToClkMaxCycleWarnings()2438 Sdc::reportClkToClkMaxCycleWarnings()
2439 {
2440 // Find cycle acctings that exceed max cycle count. Eliminate
2441 // duplicate warnings between different src/tgt clk edges.
2442 ClockPairSet clk_warnings;
2443 ClockPairSeq clk_warnings2;
2444 CycleAcctingSet::Iterator acct_iter(cycle_acctings_);
2445 while (acct_iter.hasNext()) {
2446 CycleAccting *acct = acct_iter.next();
2447 if (acct->maxCyclesExceeded()) {
2448 Clock *src = acct->src()->clock();
2449 Clock *tgt = acct->target()->clock();
2450 // Canonicalize the warning wrt src/tgt.
2451 if (src->index() > tgt->index())
2452 std::swap(src, tgt);
2453 ClockPair clk_pair(src, tgt);
2454 if (!clk_warnings.hasKey(clk_pair)) {
2455 clk_warnings.insert(clk_pair);
2456 clk_warnings2.push_back(clk_pair);
2457 }
2458 }
2459 }
2460
2461 // Sort clk pairs so that results are stable.
2462 sort(clk_warnings2, ClockPairLess());
2463
2464 for (auto pair : clk_warnings2) {
2465 report_->warn(9, "No common period was found between clocks %s and %s.",
2466 pair.first->name(),
2467 pair.second->name());
2468 }
2469 }
2470
2471 void
clearCycleAcctings()2472 Sdc::clearCycleAcctings()
2473 {
2474 cycle_acctings_.deleteContentsClear();
2475 }
2476
2477 ////////////////////////////////////////////////////////////////
2478
2479 void
setDataCheck(Pin * from,const RiseFallBoth * from_rf,Pin * to,const RiseFallBoth * to_rf,Clock * clk,const SetupHoldAll * setup_hold,float margin)2480 Sdc::setDataCheck(Pin *from,
2481 const RiseFallBoth *from_rf,
2482 Pin *to,
2483 const RiseFallBoth *to_rf,
2484 Clock *clk,
2485 const SetupHoldAll *setup_hold,
2486 float margin)
2487 {
2488 DataCheck *check = nullptr;
2489 DataCheckSet *checks = data_checks_from_map_.findKey(from);
2490 if (checks == nullptr) {
2491 checks = new DataCheckSet(DataCheckLess(network_));
2492 data_checks_from_map_[from] = checks;
2493 }
2494 else {
2495 DataCheck probe(from, to, clk);
2496 check = checks->findKey(&probe);
2497 }
2498 if (check == nullptr)
2499 check = new DataCheck(from, to, clk);
2500 check->setMargin(from_rf, to_rf, setup_hold, margin);
2501 checks->insert(check);
2502
2503 checks = data_checks_to_map_.findKey(to);
2504 if (checks == nullptr) {
2505 checks = new DataCheckSet(DataCheckLess(network_));
2506 data_checks_to_map_[to] = checks;
2507 }
2508 checks->insert(check);
2509 }
2510
2511 void
removeDataCheck(Pin * from,const RiseFallBoth * from_rf,Pin * to,const RiseFallBoth * to_rf,Clock * clk,const SetupHoldAll * setup_hold)2512 Sdc::removeDataCheck(Pin *from,
2513 const RiseFallBoth *from_rf,
2514 Pin *to,
2515 const RiseFallBoth *to_rf,
2516 Clock *clk,
2517 const SetupHoldAll *setup_hold)
2518 {
2519 DataCheck probe(from, to, clk);
2520 DataCheckSet *checks = data_checks_from_map_.findKey(from);
2521 if (checks) {
2522 DataCheck *check = checks->findKey(&probe);
2523 if (check) {
2524 check->removeMargin(from_rf, to_rf, setup_hold);
2525 if (check->empty()) {
2526 checks->erase(check);
2527 checks = data_checks_to_map_.findKey(to);
2528 if (checks)
2529 checks->erase(check);
2530 delete check;
2531 }
2532 }
2533 }
2534 }
2535
2536 DataCheckSet *
dataChecksFrom(const Pin * from) const2537 Sdc::dataChecksFrom(const Pin *from) const
2538 {
2539 return data_checks_from_map_.findKey(from);
2540 }
2541
2542 DataCheckSet *
dataChecksTo(const Pin * to) const2543 Sdc::dataChecksTo(const Pin *to) const
2544 {
2545 return data_checks_to_map_.findKey(to);
2546 }
2547
2548 ////////////////////////////////////////////////////////////////
2549
2550 void
setLatchBorrowLimit(Pin * pin,float limit)2551 Sdc::setLatchBorrowLimit(Pin *pin,
2552 float limit)
2553 {
2554 pin_latch_borrow_limit_map_[pin] = limit;
2555 }
2556
2557 void
setLatchBorrowLimit(Instance * inst,float limit)2558 Sdc::setLatchBorrowLimit(Instance *inst,
2559 float limit)
2560 {
2561 inst_latch_borrow_limit_map_[inst] = limit;
2562 }
2563
2564 void
setLatchBorrowLimit(Clock * clk,float limit)2565 Sdc::setLatchBorrowLimit(Clock *clk,
2566 float limit)
2567 {
2568 clk_latch_borrow_limit_map_[clk] = limit;
2569 }
2570
2571 void
deleteLatchBorrowLimitsReferencing(Clock * clk)2572 Sdc::deleteLatchBorrowLimitsReferencing(Clock *clk)
2573 {
2574 clk_latch_borrow_limit_map_.erase(clk);
2575 }
2576
2577 void
latchBorrowLimit(Pin * data_pin,Pin * enable_pin,Clock * clk,float & limit,bool & exists)2578 Sdc::latchBorrowLimit(Pin *data_pin,
2579 Pin *enable_pin,
2580 Clock *clk,
2581 // Return values.
2582 float &limit,
2583 bool &exists)
2584 {
2585 pin_latch_borrow_limit_map_.findKey(data_pin, limit, exists);
2586 if (!exists) {
2587 pin_latch_borrow_limit_map_.findKey(enable_pin, limit, exists);
2588 if (!exists) {
2589 Instance *inst = network_->instance(data_pin);
2590 inst_latch_borrow_limit_map_.findKey(inst, limit, exists);
2591 if (!exists)
2592 clk_latch_borrow_limit_map_.findKey(clk, limit, exists);
2593 }
2594 }
2595 }
2596
2597 ////////////////////////////////////////////////////////////////
2598
2599 void
setMinPulseWidth(const RiseFallBoth * rf,float min_width)2600 Sdc::setMinPulseWidth(const RiseFallBoth *rf,
2601 float min_width)
2602 {
2603 for (auto rf1 : rf->range())
2604 min_pulse_width_.setValue(rf1, min_width);
2605 }
2606
2607 void
setMinPulseWidth(const Pin * pin,const RiseFallBoth * rf,float min_width)2608 Sdc::setMinPulseWidth(const Pin *pin,
2609 const RiseFallBoth *rf,
2610 float min_width)
2611 {
2612 RiseFallValues *widths = pin_min_pulse_width_map_.findKey(pin);
2613 if (widths == nullptr) {
2614 widths = new RiseFallValues;
2615 pin_min_pulse_width_map_[pin] = widths;
2616 }
2617 for (auto rf1 : rf->range())
2618 widths->setValue(rf1, min_width);
2619 }
2620
2621 void
setMinPulseWidth(const Instance * inst,const RiseFallBoth * rf,float min_width)2622 Sdc::setMinPulseWidth(const Instance *inst,
2623 const RiseFallBoth *rf,
2624 float min_width)
2625 {
2626 RiseFallValues *widths = inst_min_pulse_width_map_.findKey(inst);
2627 if (widths == nullptr) {
2628 widths = new RiseFallValues;
2629 inst_min_pulse_width_map_[inst] = widths;
2630 }
2631 for (auto rf1 : rf->range())
2632 widths->setValue(rf1, min_width);
2633 }
2634
2635 void
setMinPulseWidth(const Clock * clk,const RiseFallBoth * rf,float min_width)2636 Sdc::setMinPulseWidth(const Clock *clk,
2637 const RiseFallBoth *rf,
2638 float min_width)
2639 {
2640 RiseFallValues *widths = clk_min_pulse_width_map_.findKey(clk);
2641 if (widths == nullptr) {
2642 widths = new RiseFallValues;
2643 clk_min_pulse_width_map_[clk] = widths;
2644 }
2645 for (auto rf1 : rf->range())
2646 widths->setValue(rf1, min_width);
2647 }
2648
2649 void
minPulseWidth(const Pin * pin,const Clock * clk,const RiseFall * hi_low,float & min_width,bool & exists) const2650 Sdc::minPulseWidth(const Pin *pin,
2651 const Clock *clk,
2652 const RiseFall *hi_low,
2653 float &min_width,
2654 bool &exists) const
2655 {
2656 RiseFallValues *widths = pin_min_pulse_width_map_.findKey(pin);
2657 if (widths)
2658 widths->value(hi_low, min_width, exists);
2659 else {
2660 if (pin) {
2661 const Instance *inst = network_->instance(pin);
2662 widths = inst_min_pulse_width_map_.findKey(inst);
2663 }
2664 if (widths == nullptr)
2665 widths = clk_min_pulse_width_map_.findKey(clk);
2666 if (widths)
2667 widths->value(hi_low, min_width, exists);
2668 else
2669 min_pulse_width_.value(hi_low, min_width, exists);
2670 }
2671 }
2672
2673 void
deleteMinPulseWidthReferencing(Clock * clk)2674 Sdc::deleteMinPulseWidthReferencing(Clock *clk)
2675 {
2676 RiseFallValues *widths = clk_min_pulse_width_map_.findKey(clk);
2677 if (widths) {
2678 delete widths;
2679 clk_min_pulse_width_map_.erase(clk);
2680 }
2681 }
2682
2683 ////////////////////////////////////////////////////////////////
2684
2685 InputDrive *
findInputDrive(Port * port)2686 Sdc::findInputDrive(Port *port)
2687 {
2688 return input_drive_map_.findKey(port);
2689 }
2690
2691 void
setInputDelay(Pin * pin,const RiseFallBoth * rf,Clock * clk,const RiseFall * clk_rf,Pin * ref_pin,bool source_latency_included,bool network_latency_included,const MinMaxAll * min_max,bool add,float delay)2692 Sdc::setInputDelay(Pin *pin,
2693 const RiseFallBoth *rf,
2694 Clock *clk,
2695 const RiseFall *clk_rf,
2696 Pin *ref_pin,
2697 bool source_latency_included,
2698 bool network_latency_included,
2699 const MinMaxAll *min_max,
2700 bool add,
2701 float delay)
2702 {
2703 ClockEdge *clk_edge = clk ? clk->edge(clk_rf) : nullptr;
2704 InputDelay *input_delay = findInputDelay(pin, clk_edge, ref_pin);
2705 if (input_delay == nullptr)
2706 input_delay = makeInputDelay(pin, clk_edge, ref_pin);
2707 if (add) {
2708 RiseFallMinMax *delays = input_delay->delays();
2709 delays->mergeValue(rf, min_max, delay);
2710 }
2711 else {
2712 deleteInputDelays(pin, input_delay);
2713 RiseFallMinMax *delays = input_delay->delays();
2714 delays->setValue(rf, min_max, delay);
2715 }
2716 input_delay->setSourceLatencyIncluded(source_latency_included);
2717 input_delay->setNetworkLatencyIncluded(network_latency_included);
2718 }
2719
2720 InputDelay *
makeInputDelay(Pin * pin,ClockEdge * clk_edge,Pin * ref_pin)2721 Sdc::makeInputDelay(Pin *pin,
2722 ClockEdge *clk_edge,
2723 Pin *ref_pin)
2724 {
2725 InputDelay *input_delay = new InputDelay(pin, clk_edge, ref_pin,
2726 input_delay_index_++,
2727 network_);
2728 input_delays_.insert(input_delay);
2729 InputDelaySet *inputs = input_delay_pin_map_.findKey(pin);
2730 if (inputs == nullptr) {
2731 inputs = new InputDelaySet;
2732 input_delay_pin_map_[pin] = inputs;
2733 }
2734 inputs->insert(input_delay);
2735
2736 if (ref_pin) {
2737 InputDelaySet *ref_inputs = input_delay_ref_pin_map_.findKey(ref_pin);
2738 if (ref_inputs == nullptr) {
2739 ref_inputs = new InputDelaySet;
2740 input_delay_ref_pin_map_[ref_pin] = ref_inputs;
2741 }
2742 ref_inputs->insert(input_delay);
2743 }
2744
2745 for (Pin *lpin : input_delay->leafPins()) {
2746 InputDelaySet *leaf_inputs = input_delay_leaf_pin_map_[lpin];
2747 if (leaf_inputs == nullptr) {
2748 leaf_inputs = new InputDelaySet;
2749 input_delay_leaf_pin_map_[lpin] = leaf_inputs;
2750 }
2751 leaf_inputs->insert(input_delay);
2752
2753 if (!network_->isTopLevelPort(lpin)) {
2754 InputDelaySet *internal_inputs = input_delay_internal_pin_map_[lpin];
2755 if (internal_inputs == nullptr) {
2756 internal_inputs = new InputDelaySet;
2757 input_delay_internal_pin_map_[pin] = internal_inputs;
2758 }
2759 internal_inputs->insert(input_delay);
2760 }
2761 }
2762 return input_delay;
2763 }
2764
2765 InputDelay *
findInputDelay(const Pin * pin,ClockEdge * clk_edge,Pin * ref_pin)2766 Sdc::findInputDelay(const Pin *pin,
2767 ClockEdge *clk_edge,
2768 Pin *ref_pin)
2769 {
2770 InputDelaySet *inputs = input_delay_pin_map_.findKey(pin);
2771 if (inputs) {
2772 for (InputDelay *input_delay : *inputs) {
2773 if (input_delay->clkEdge() == clk_edge
2774 && input_delay->refPin() == ref_pin)
2775 return input_delay;
2776 }
2777 }
2778 return nullptr;
2779 }
2780
2781 void
removeInputDelay(Pin * pin,RiseFallBoth * rf,Clock * clk,RiseFall * clk_rf,MinMaxAll * min_max)2782 Sdc::removeInputDelay(Pin *pin,
2783 RiseFallBoth *rf,
2784 Clock *clk,
2785 RiseFall *clk_rf,
2786 MinMaxAll *min_max)
2787 {
2788 ClockEdge *clk_edge = clk ? clk->edge(clk_rf) : nullptr;
2789 InputDelay *input_delay = findInputDelay(pin, clk_edge, nullptr);
2790 if (input_delay) {
2791 RiseFallMinMax *delays = input_delay->delays();
2792 delays->removeValue(rf, min_max);
2793 if (delays->empty())
2794 deleteInputDelay(input_delay);
2795 }
2796 }
2797
2798 void
deleteInputDelays(Pin * pin,InputDelay * except)2799 Sdc::deleteInputDelays(Pin *pin,
2800 InputDelay *except)
2801 {
2802 InputDelaySet *input_delays = input_delay_pin_map_[pin];
2803 InputDelaySet::Iterator iter(input_delays);
2804 while (iter.hasNext()) {
2805 InputDelay *input_delay = iter.next();
2806 if (input_delay != except)
2807 deleteInputDelay(input_delay);
2808 }
2809 }
2810
2811 InputDelaySet *
refPinInputDelays(const Pin * ref_pin) const2812 Sdc::refPinInputDelays(const Pin *ref_pin) const
2813 {
2814 return input_delay_ref_pin_map_.findKey(ref_pin);
2815 }
2816
2817 InputDelaySet *
inputDelaysLeafPin(const Pin * leaf_pin)2818 Sdc::inputDelaysLeafPin(const Pin *leaf_pin)
2819 {
2820 return input_delay_leaf_pin_map_.findKey(leaf_pin);
2821 }
2822
2823 bool
hasInputDelay(const Pin * leaf_pin) const2824 Sdc::hasInputDelay(const Pin *leaf_pin) const
2825 {
2826 InputDelaySet *input_delays = input_delay_leaf_pin_map_.findKey(leaf_pin);
2827 return input_delays && !input_delays->empty();
2828 }
2829
2830 bool
isInputDelayInternal(const Pin * pin) const2831 Sdc::isInputDelayInternal(const Pin *pin) const
2832 {
2833 return input_delay_internal_pin_map_.hasKey(pin);
2834 }
2835
2836 void
deleteInputDelaysReferencing(Clock * clk)2837 Sdc::deleteInputDelaysReferencing(Clock *clk)
2838 {
2839 InputDelaySet::Iterator iter(input_delays_);
2840 while (iter.hasNext()) {
2841 InputDelay *input_delay = iter.next();
2842 if (input_delay->clock() == clk)
2843 deleteInputDelay(input_delay);
2844 }
2845 }
2846
2847 void
deleteInputDelay(InputDelay * input_delay)2848 Sdc::deleteInputDelay(InputDelay *input_delay)
2849 {
2850 input_delays_.erase(input_delay);
2851
2852 Pin *pin = input_delay->pin();
2853 InputDelaySet *inputs = input_delay_pin_map_[pin];
2854 inputs->erase(input_delay);
2855
2856 for (Pin *lpin : input_delay->leafPins()) {
2857 InputDelaySet *inputs = input_delay_leaf_pin_map_[lpin];
2858 inputs->erase(input_delay);
2859 }
2860
2861 delete input_delay;
2862 }
2863
2864 ////////////////////////////////////////////////////////////////
2865
2866 void
setOutputDelay(Pin * pin,const RiseFallBoth * rf,Clock * clk,const RiseFall * clk_rf,Pin * ref_pin,bool source_latency_included,bool network_latency_included,const MinMaxAll * min_max,bool add,float delay)2867 Sdc::setOutputDelay(Pin *pin,
2868 const RiseFallBoth *rf,
2869 Clock *clk,
2870 const RiseFall *clk_rf,
2871 Pin *ref_pin,
2872 bool source_latency_included,
2873 bool network_latency_included,
2874 const MinMaxAll *min_max,
2875 bool add,
2876 float delay)
2877 {
2878 ClockEdge *clk_edge = clk ? clk->edge(clk_rf) : nullptr;
2879 OutputDelay *output_delay = findOutputDelay(pin, clk_edge, ref_pin);
2880 if (output_delay == nullptr)
2881 output_delay = makeOutputDelay(pin, clk_edge, ref_pin);
2882 if (add) {
2883 RiseFallMinMax *delays = output_delay->delays();
2884 delays->mergeValue(rf, min_max, delay);
2885 }
2886 else {
2887 deleteOutputDelays(pin, output_delay);
2888 RiseFallMinMax *delays = output_delay->delays();
2889 delays->setValue(rf, min_max, delay);
2890 }
2891 output_delay->setSourceLatencyIncluded(source_latency_included);
2892 output_delay->setNetworkLatencyIncluded(network_latency_included);
2893 }
2894
2895 OutputDelay *
findOutputDelay(const Pin * pin,ClockEdge * clk_edge,Pin * ref_pin)2896 Sdc::findOutputDelay(const Pin *pin,
2897 ClockEdge *clk_edge,
2898 Pin *ref_pin)
2899 {
2900 OutputDelaySet *outputs = output_delay_pin_map_.findKey(pin);
2901 if (outputs) {
2902 for (OutputDelay *output_delay : *outputs) {
2903 if (output_delay->clkEdge() == clk_edge
2904 && output_delay->refPin() == ref_pin)
2905 return output_delay;
2906 }
2907 }
2908 return nullptr;
2909 }
2910
2911 OutputDelay *
makeOutputDelay(Pin * pin,ClockEdge * clk_edge,Pin * ref_pin)2912 Sdc::makeOutputDelay(Pin *pin,
2913 ClockEdge *clk_edge,
2914 Pin *ref_pin)
2915 {
2916 OutputDelay *output_delay = new OutputDelay(pin, clk_edge, ref_pin,
2917 network_);
2918 output_delays_.insert(output_delay);
2919 OutputDelaySet *outputs = output_delay_pin_map_.findKey(pin);
2920 if (outputs == nullptr) {
2921 outputs = new OutputDelaySet;
2922 output_delay_pin_map_[pin] = outputs;
2923 }
2924 outputs->insert(output_delay);
2925
2926 if (ref_pin) {
2927 OutputDelaySet *ref_outputs = output_delay_ref_pin_map_.findKey(ref_pin);
2928 if (ref_outputs == nullptr) {
2929 ref_outputs = new OutputDelaySet;
2930 output_delay_ref_pin_map_[ref_pin] = ref_outputs;
2931 }
2932 ref_outputs->insert(output_delay);
2933 }
2934
2935 for (Pin *lpin : output_delay->leafPins()) {
2936 OutputDelaySet *leaf_outputs = output_delay_leaf_pin_map_[lpin];
2937 if (leaf_outputs == nullptr) {
2938 leaf_outputs = new OutputDelaySet;
2939 output_delay_leaf_pin_map_[lpin] = leaf_outputs;
2940 }
2941 leaf_outputs->insert(output_delay);
2942 }
2943 return output_delay;
2944 }
2945
2946 void
removeOutputDelay(Pin * pin,RiseFallBoth * rf,Clock * clk,RiseFall * clk_rf,MinMaxAll * min_max)2947 Sdc::removeOutputDelay(Pin *pin,
2948 RiseFallBoth *rf,
2949 Clock *clk,
2950 RiseFall *clk_rf,
2951 MinMaxAll *min_max)
2952 {
2953 ClockEdge *clk_edge = clk ? clk->edge(clk_rf) : nullptr;
2954 OutputDelay *output_delay = findOutputDelay(pin, clk_edge, nullptr);
2955 if (output_delay) {
2956 RiseFallMinMax *delays = output_delay->delays();
2957 delays->removeValue(rf, min_max);
2958 }
2959 }
2960
2961 void
deleteOutputDelays(Pin * pin,OutputDelay * except)2962 Sdc::deleteOutputDelays(Pin *pin,
2963 OutputDelay *except)
2964 {
2965 OutputDelaySet *output_delays = output_delay_pin_map_[pin];
2966 OutputDelaySet::Iterator iter(output_delays);
2967 while (iter.hasNext()) {
2968 OutputDelay *output_delay = iter.next();
2969 if (output_delay != except)
2970 deleteOutputDelay(output_delay);
2971 }
2972 }
2973
2974 OutputDelaySet *
outputDelaysLeafPin(const Pin * leaf_pin)2975 Sdc::outputDelaysLeafPin(const Pin *leaf_pin)
2976 {
2977 return output_delay_leaf_pin_map_.findKey(leaf_pin);
2978 }
2979
2980 bool
hasOutputDelay(const Pin * leaf_pin) const2981 Sdc::hasOutputDelay(const Pin *leaf_pin) const
2982 {
2983 return output_delay_leaf_pin_map_.hasKey(leaf_pin);
2984 }
2985
2986 void
deleteOutputDelaysReferencing(Clock * clk)2987 Sdc::deleteOutputDelaysReferencing(Clock *clk)
2988 {
2989 OutputDelaySet::Iterator iter(output_delays_);
2990 while (iter.hasNext()) {
2991 OutputDelay *output_delay = iter.next();
2992 if (output_delay->clock() == clk)
2993 deleteOutputDelay(output_delay);
2994 }
2995 }
2996
2997 void
deleteOutputDelay(OutputDelay * output_delay)2998 Sdc::deleteOutputDelay(OutputDelay *output_delay)
2999 {
3000 output_delays_.erase(output_delay);
3001
3002 Pin *pin = output_delay->pin();
3003 OutputDelaySet *outputs = output_delay_pin_map_[pin];
3004 outputs->erase(output_delay);
3005
3006 for (Pin *lpin : output_delay->leafPins()) {
3007 OutputDelaySet *outputs = output_delay_leaf_pin_map_[lpin];
3008 outputs->erase(output_delay);
3009 }
3010
3011 delete output_delay;
3012 }
3013
3014 ////////////////////////////////////////////////////////////////
3015
3016 void
setPortExtPinCap(Port * port,const RiseFall * rf,const MinMax * min_max,float cap)3017 Sdc::setPortExtPinCap(Port *port,
3018 const RiseFall *rf,
3019 const MinMax *min_max,
3020 float cap)
3021 {
3022 PortExtCap *port_cap = ensurePortExtPinCap(port);
3023 port_cap->setPinCap(cap, rf, min_max);
3024 }
3025
3026 void
setPortExtWireCap(Port * port,bool subtract_pin_cap,const RiseFall * rf,const Corner * corner,const MinMax * min_max,float cap)3027 Sdc::setPortExtWireCap(Port *port,
3028 bool subtract_pin_cap,
3029 const RiseFall *rf,
3030 const Corner *corner,
3031 const MinMax *min_max,
3032 float cap)
3033 {
3034 PortExtCap *port_cap = ensurePortExtPinCap(port);
3035 if (subtract_pin_cap) {
3036 Pin *pin = network_->findPin(network_->name(port));
3037 const OperatingConditions *op_cond = operatingConditions(min_max);
3038 cap -= connectedPinCap(pin, rf, op_cond, corner, min_max);
3039 if (cap < 0.0)
3040 cap = 0.0;
3041 }
3042 port_cap->setWireCap(cap, rf, min_max);
3043 }
3044
3045 PortExtCap *
portExtCap(Port * port) const3046 Sdc::portExtCap(Port *port) const
3047 {
3048 if (port_cap_map_)
3049 return port_cap_map_->findKey(port);
3050 else
3051 return nullptr;
3052 }
3053
3054 bool
hasPortExtCap(Port * port) const3055 Sdc::hasPortExtCap(Port *port) const
3056 {
3057 if (port_cap_map_)
3058 return port_cap_map_->hasKey(port);
3059 else
3060 return false;
3061 }
3062
3063 void
portExtCap(Port * port,const RiseFall * rf,const MinMax * min_max,float & pin_cap,bool & has_pin_cap,float & wire_cap,bool & has_wire_cap,int & fanout,bool & has_fanout) const3064 Sdc::portExtCap(Port *port,
3065 const RiseFall *rf,
3066 const MinMax *min_max,
3067 // Return values.
3068 float &pin_cap,
3069 bool &has_pin_cap,
3070 float &wire_cap,
3071 bool &has_wire_cap,
3072 int &fanout,
3073 bool &has_fanout) const
3074 {
3075 if (port_cap_map_) {
3076 PortExtCap *port_cap = port_cap_map_->findKey(port);
3077 if (port_cap) {
3078 port_cap->pinCap(rf, min_max, pin_cap, has_pin_cap);
3079 port_cap->wireCap(rf, min_max, wire_cap, has_wire_cap);
3080 port_cap->fanout(min_max, fanout, has_fanout);
3081 return;
3082 }
3083 }
3084 pin_cap = 0.0F;
3085 has_pin_cap = false;
3086 wire_cap = 0.0F;
3087 has_wire_cap = false;
3088 fanout = 0.0F;
3089 has_fanout = false;
3090 }
3091
3092 float
portExtCap(Port * port,const RiseFall * rf,const MinMax * min_max) const3093 Sdc::portExtCap(Port *port,
3094 const RiseFall *rf,
3095 const MinMax *min_max) const
3096 {
3097 float pin_cap, wire_cap;
3098 int fanout;
3099 bool has_pin_cap, has_wire_cap, has_fanout;
3100 portExtCap(port, rf, min_max,
3101 pin_cap, has_pin_cap,
3102 wire_cap, has_wire_cap,
3103 fanout, has_fanout);
3104 float cap = 0.0;
3105 if (has_pin_cap)
3106 cap += pin_cap;
3107 if (has_wire_cap)
3108 cap += wire_cap;
3109 return cap;
3110 }
3111
3112 bool
drvrPinHasWireCap(const Pin * pin)3113 Sdc::drvrPinHasWireCap(const Pin *pin)
3114 {
3115 return drvr_pin_wire_cap_map_
3116 && drvr_pin_wire_cap_map_->hasKey(const_cast<Pin*>(pin));
3117 }
3118
3119 void
drvrPinWireCap(const Pin * pin,const Corner * corner,const MinMax * min_max,float & cap,bool & exists) const3120 Sdc::drvrPinWireCap(const Pin *pin,
3121 const Corner *corner,
3122 const MinMax *min_max,
3123 // Return values.
3124 float &cap,
3125 bool &exists) const
3126 {
3127 if (drvr_pin_wire_cap_map_) {
3128 MinMaxFloatValues *values =
3129 drvr_pin_wire_cap_map_[corner->index()].findKey(const_cast<Pin*>(pin));
3130 if (values)
3131 return values->value(min_max, cap, exists);
3132 }
3133 cap = 0.0;
3134 exists = false;
3135 }
3136
3137 void
setNetWireCap(Net * net,bool subtract_pin_cap,const Corner * corner,const MinMax * min_max,float cap)3138 Sdc::setNetWireCap(Net *net,
3139 bool subtract_pin_cap,
3140 const Corner *corner,
3141 const MinMax *min_max,
3142 float cap)
3143 {
3144 float wire_cap = cap;
3145 if (subtract_pin_cap) {
3146 OperatingConditions *op_cond = operatingConditions(min_max);
3147 NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
3148 if (pin_iter->hasNext()) {
3149 Pin *pin = pin_iter->next();
3150 float pin_cap_rise = connectedPinCap(pin, RiseFall::rise(),
3151 op_cond, corner, min_max);
3152 float pin_cap_fall = connectedPinCap(pin, RiseFall::fall(),
3153 op_cond, corner, min_max);
3154 float pin_cap = (pin_cap_rise + pin_cap_fall) / 2.0F;
3155 wire_cap -= pin_cap;
3156 if ((wire_cap + pin_cap) < 0.0)
3157 wire_cap = -pin_cap;
3158 delete pin_iter;
3159 }
3160 }
3161 if (net_wire_cap_map_ == nullptr)
3162 net_wire_cap_map_ = new NetWireCapMap[corners_->count()];
3163 bool make_drvr_entry = !net_wire_cap_map_[corner->index()].hasKey(net);
3164 MinMaxFloatValues &values = net_wire_cap_map_[corner->index()][net];
3165 values.setValue(min_max, wire_cap);
3166
3167 // Only need to do this when there is new net_wire_cap_map_ entry.
3168 if (make_drvr_entry) {
3169 for (Pin *pin : *network_->drivers(net)) {
3170 if (drvr_pin_wire_cap_map_ == nullptr)
3171 drvr_pin_wire_cap_map_ = new PinWireCapMap[corners_->count()];
3172 drvr_pin_wire_cap_map_[corner->index()][pin] = &values;
3173 }
3174 }
3175 }
3176
3177 bool
hasNetWireCap(Net * net) const3178 Sdc::hasNetWireCap(Net *net) const
3179 {
3180 if (net_wire_cap_map_) {
3181 for (int i = 0; i < corners_->count(); i++) {
3182 if (net_wire_cap_map_[i].hasKey(net))
3183 return true;
3184 }
3185 }
3186 return false;
3187 }
3188
3189 ////////////////////////////////////////////////////////////////
3190
3191 void
connectedCap(const Pin * pin,const RiseFall * rf,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max,float & pin_cap,float & wire_cap,float & fanout,bool & has_set_load) const3192 Sdc::connectedCap(const Pin *pin,
3193 const RiseFall *rf,
3194 const OperatingConditions *op_cond,
3195 const Corner *corner,
3196 const MinMax *min_max,
3197 // Return values.
3198 float &pin_cap,
3199 float &wire_cap,
3200 float &fanout,
3201 bool &has_set_load) const
3202 {
3203 netCaps(pin, rf, op_cond, corner, min_max,
3204 pin_cap, wire_cap, fanout, has_set_load);
3205 float net_wire_cap;
3206 bool has_net_wire_cap;
3207 drvrPinWireCap(pin, corner, min_max, net_wire_cap, has_net_wire_cap);
3208 if (has_net_wire_cap) {
3209 wire_cap += net_wire_cap;
3210 has_set_load = true;
3211 }
3212 }
3213
3214 float
connectedPinCap(const Pin * pin,const RiseFall * rf,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max)3215 Sdc::connectedPinCap(const Pin *pin,
3216 const RiseFall *rf,
3217 const OperatingConditions *op_cond,
3218 const Corner *corner,
3219 const MinMax *min_max)
3220 {
3221 float pin_cap, wire_cap, fanout;
3222 bool has_set_load;
3223 connectedCap(pin, rf, op_cond, corner, min_max,
3224 pin_cap, wire_cap, fanout, has_set_load);
3225 return pin_cap;
3226 }
3227
3228 class FindNetCaps : public PinVisitor
3229 {
3230 public:
3231 FindNetCaps(const RiseFall *rf,
3232 const OperatingConditions *op_cond,
3233 const Corner *corner,
3234 const MinMax *min_max,
3235 float &pin_cap,
3236 float &wire_cap,
3237 float &fanout,
3238 bool &has_set_load,
3239 const Sdc *sdc);
3240 virtual void operator()(Pin *pin);
3241
3242 protected:
3243 const RiseFall *rf_;
3244 const OperatingConditions *op_cond_;
3245 const Corner *corner_;
3246 const MinMax *min_max_;
3247 float &pin_cap_;
3248 float &wire_cap_;
3249 float &fanout_;
3250 bool &has_set_load_;
3251 const Sdc *sdc_;
3252
3253 private:
3254 DISALLOW_COPY_AND_ASSIGN(FindNetCaps);
3255 };
3256
FindNetCaps(const RiseFall * rf,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max,float & pin_cap,float & wire_cap,float & fanout,bool & has_set_load,const Sdc * sdc)3257 FindNetCaps::FindNetCaps(const RiseFall *rf,
3258 const OperatingConditions *op_cond,
3259 const Corner *corner,
3260 const MinMax *min_max,
3261 float &pin_cap,
3262 float &wire_cap,
3263 float &fanout,
3264 bool &has_set_load,
3265 const Sdc *sdc) :
3266 PinVisitor(),
3267 rf_(rf),
3268 op_cond_(op_cond),
3269 corner_(corner),
3270 min_max_(min_max),
3271 pin_cap_(pin_cap),
3272 wire_cap_(wire_cap),
3273 fanout_(fanout),
3274 has_set_load_(has_set_load),
3275 sdc_(sdc)
3276 {
3277 }
3278
3279 void
operator ()(Pin * pin)3280 FindNetCaps::operator()(Pin *pin)
3281 {
3282 sdc_->pinCaps(pin, rf_, op_cond_, corner_, min_max_,
3283 pin_cap_, wire_cap_, fanout_, has_set_load_);
3284 }
3285
3286 // Capacitances for all pins connected to drvr_pin's net.
3287 void
netCaps(const Pin * drvr_pin,const RiseFall * rf,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max,float & pin_cap,float & wire_cap,float & fanout,bool & has_set_load) const3288 Sdc::netCaps(const Pin *drvr_pin,
3289 const RiseFall *rf,
3290 const OperatingConditions *op_cond,
3291 const Corner *corner,
3292 const MinMax *min_max,
3293 // Return values.
3294 float &pin_cap,
3295 float &wire_cap,
3296 float &fanout,
3297 bool &has_set_load) const
3298 {
3299 pin_cap = 0.0;
3300 wire_cap = 0.0;
3301 fanout = 0.0;
3302 has_set_load = false;
3303 FindNetCaps visitor(rf, op_cond, corner, min_max, pin_cap,
3304 wire_cap, fanout, has_set_load, this);
3305 network_->visitConnectedPins(const_cast<Pin*>(drvr_pin), visitor);
3306 }
3307
3308 void
pinCaps(const Pin * pin,const RiseFall * rf,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max,float & pin_cap,float & wire_cap,float & fanout,bool & has_set_load) const3309 Sdc::pinCaps(const Pin *pin,
3310 const RiseFall *rf,
3311 const OperatingConditions *op_cond,
3312 const Corner *corner,
3313 const MinMax *min_max,
3314 // Return values.
3315 float &pin_cap,
3316 float &wire_cap,
3317 float &fanout,
3318 bool &has_set_load) const
3319 {
3320 if (network_->isTopLevelPort(pin)) {
3321 Port *port = network_->port(pin);
3322 bool is_output = network_->direction(port)->isAnyOutput();
3323 float port_pin_cap, port_wire_cap;
3324 int port_fanout;
3325 bool has_pin_cap, has_wire_cap, has_fanout;
3326 portExtCap(port, rf, min_max,
3327 port_pin_cap, has_pin_cap,
3328 port_wire_cap, has_wire_cap,
3329 port_fanout, has_fanout);
3330 if (has_pin_cap)
3331 pin_cap += port_pin_cap;
3332 if (has_wire_cap)
3333 wire_cap += port_wire_cap;
3334 if (is_output) {
3335 if (has_fanout)
3336 fanout += port_fanout;
3337 // Output port counts as a fanout.
3338 fanout++;
3339 }
3340 has_set_load |= has_pin_cap || has_wire_cap;
3341 }
3342 else {
3343 LibertyPort *port = network_->libertyPort(pin);
3344 if (port) {
3345 Instance *inst = network_->instance(pin);
3346 pin_cap += portCapacitance(inst, port, rf, op_cond, corner, min_max);
3347 if (port->direction()->isAnyInput())
3348 fanout++;
3349 }
3350 }
3351 }
3352
3353 float
portCapacitance(Instance * inst,LibertyPort * port,const RiseFall * rf,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max) const3354 Sdc::portCapacitance(Instance *inst,
3355 LibertyPort *port,
3356 const RiseFall *rf,
3357 const OperatingConditions *op_cond,
3358 const Corner *corner,
3359 const MinMax *min_max) const
3360 {
3361 Pvt *inst_pvt = nullptr;
3362 if (inst)
3363 inst_pvt = pvt(inst, min_max);
3364 LibertyPort *corner_port = port->cornerPort(corner->libertyIndex(min_max));
3365 return corner_port->capacitance(rf, min_max, op_cond, inst_pvt);
3366 }
3367
3368 float
pinCapacitance(const Pin * pin,const RiseFall * rf,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max)3369 Sdc::pinCapacitance(const Pin *pin,
3370 const RiseFall *rf,
3371 const OperatingConditions *op_cond,
3372 const Corner *corner,
3373 const MinMax *min_max)
3374 {
3375 LibertyPort *port = network_->libertyPort(pin);
3376 if (port) {
3377 Instance *inst = network_->instance(pin);
3378 return portCapacitance(inst, port, rf, op_cond, corner, min_max);
3379 }
3380 else
3381 return 0.0;
3382 }
3383
3384 ////////////////////////////////////////////////////////////////
3385
3386 void
setResistance(Net * net,const MinMaxAll * min_max,float res)3387 Sdc::setResistance(Net *net,
3388 const MinMaxAll *min_max,
3389 float res)
3390 {
3391 MinMaxFloatValues &values = net_res_map_[net];
3392 values.setValue(min_max, res);
3393 }
3394
3395 void
resistance(Net * net,const MinMax * min_max,float & res,bool & exists)3396 Sdc::resistance(Net *net,
3397 const MinMax *min_max,
3398 float &res,
3399 bool &exists)
3400 {
3401 res = 0.0;
3402 MinMaxFloatValues values;
3403 net_res_map_.findKey(net, values, exists);
3404 if (exists)
3405 values.value(min_max, res, exists);
3406 }
3407
3408 void
setPortExtFanout(Port * port,const MinMax * min_max,int fanout)3409 Sdc::setPortExtFanout(Port *port,
3410 const MinMax *min_max,
3411 int fanout)
3412 {
3413 PortExtCap *port_cap = ensurePortExtPinCap(port);
3414 port_cap->setFanout(fanout, min_max);
3415 }
3416
3417 void
portExtFanout(Port * port,const MinMax * min_max,int & fanout,bool & exists)3418 Sdc::portExtFanout(Port *port,
3419 const MinMax *min_max,
3420 // Return values.
3421 int &fanout,
3422 bool &exists)
3423 {
3424 PortExtCap *port_cap = portExtCap(port);
3425 if (port_cap)
3426 port_cap->fanout(min_max, fanout, exists);
3427 else {
3428 fanout = 0.0;
3429 exists = false;
3430 }
3431 }
3432
3433 int
portExtFanout(Port * port,const MinMax * min_max)3434 Sdc::portExtFanout(Port *port,
3435 const MinMax *min_max)
3436 {
3437 int fanout;
3438 bool exists;
3439 portExtFanout(port, min_max, fanout, exists);
3440 if (exists)
3441 return fanout;
3442 else
3443 return 0.0;
3444 }
3445
3446 PortExtCap *
ensurePortExtPinCap(Port * port)3447 Sdc::ensurePortExtPinCap(Port *port)
3448 {
3449 if (port_cap_map_ == nullptr)
3450 port_cap_map_ = new PortExtCapMap;
3451 PortExtCap *port_cap = port_cap_map_->findKey(port);
3452 if (port_cap == nullptr) {
3453 port_cap = new PortExtCap(port);
3454 (*port_cap_map_)[port] = port_cap;
3455 }
3456 return port_cap;
3457 }
3458
3459 ////////////////////////////////////////////////////////////////
3460
3461 void
disable(LibertyCell * cell,LibertyPort * from,LibertyPort * to)3462 Sdc::disable(LibertyCell *cell,
3463 LibertyPort *from,
3464 LibertyPort *to)
3465 {
3466 DisabledCellPorts *disabled_cell = disabled_cell_ports_.findKey(cell);
3467 if (disabled_cell == nullptr) {
3468 disabled_cell = new DisabledCellPorts(cell);
3469 disabled_cell_ports_[cell] = disabled_cell;
3470 }
3471 if (from && to) {
3472 disabled_cell->setDisabledFromTo(from, to);
3473 LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
3474 while (arc_iter.hasNext()) {
3475 TimingArcSet *arc_set = arc_iter.next();
3476 arc_set->setIsDisabledConstraint(true);
3477 }
3478 }
3479 else if (from) {
3480 disabled_cell->setDisabledFrom(from);
3481 from->setIsDisabledConstraint(true);
3482 }
3483 else if (to) {
3484 disabled_cell->setDisabledTo(to);
3485 to->setIsDisabledConstraint(true);
3486 }
3487 else {
3488 disabled_cell->setDisabledAll();
3489 cell->setIsDisabledConstraint(true);
3490 }
3491 }
3492
3493 void
removeDisable(LibertyCell * cell,LibertyPort * from,LibertyPort * to)3494 Sdc::removeDisable(LibertyCell *cell,
3495 LibertyPort *from,
3496 LibertyPort *to)
3497 {
3498 DisabledCellPorts *disabled_cell = disabled_cell_ports_.findKey(cell);
3499 if (disabled_cell) {
3500 if (from && to) {
3501 disabled_cell->removeDisabledFromTo(from, to);
3502 LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
3503 while (arc_iter.hasNext()) {
3504 TimingArcSet *arc_set = arc_iter.next();
3505 arc_set->setIsDisabledConstraint(false);
3506 }
3507 }
3508 else if (from) {
3509 disabled_cell->removeDisabledFrom(from);
3510 from->setIsDisabledConstraint(false);
3511 }
3512 else if (to) {
3513 disabled_cell->removeDisabledTo(to);
3514 to->setIsDisabledConstraint(false);
3515 }
3516 else {
3517 disabled_cell->removeDisabledAll();
3518 cell->setIsDisabledConstraint(false);
3519 }
3520 }
3521 }
3522
3523 void
disable(TimingArcSet * arc_set)3524 Sdc::disable(TimingArcSet *arc_set)
3525 {
3526 LibertyCell *cell = arc_set->libertyCell();
3527 DisabledCellPorts *disabled_cell = disabled_cell_ports_.findKey(cell);
3528 if (disabled_cell == nullptr) {
3529 disabled_cell = new DisabledCellPorts(cell);
3530 disabled_cell_ports_[cell] = disabled_cell;
3531 }
3532 disabled_cell->setDisabled(arc_set);
3533 arc_set->setIsDisabledConstraint(true);
3534 }
3535
3536 void
removeDisable(TimingArcSet * arc_set)3537 Sdc::removeDisable(TimingArcSet *arc_set)
3538 {
3539 LibertyCell *cell = arc_set->libertyCell();
3540 DisabledCellPorts *disabled_cell = disabled_cell_ports_.findKey(cell);
3541 if (disabled_cell) {
3542 disabled_cell->removeDisabled(arc_set);
3543 arc_set->setIsDisabledConstraint(false);
3544 }
3545 }
3546
3547 void
disable(LibertyPort * port)3548 Sdc::disable(LibertyPort *port)
3549 {
3550 disabled_lib_ports_.insert(port);
3551 port->setIsDisabledConstraint(true);
3552 }
3553
3554 void
removeDisable(LibertyPort * port)3555 Sdc::removeDisable(LibertyPort *port)
3556 {
3557 disabled_lib_ports_.erase(port);
3558 port->setIsDisabledConstraint(false);
3559 }
3560
3561 void
disable(Port * port)3562 Sdc::disable(Port *port)
3563 {
3564 disabled_ports_.insert(port);
3565 }
3566
3567 void
removeDisable(Port * port)3568 Sdc::removeDisable(Port *port)
3569 {
3570 disabled_ports_.erase(port);
3571 }
3572
3573 void
disable(Instance * inst,LibertyPort * from,LibertyPort * to)3574 Sdc::disable(Instance *inst,
3575 LibertyPort *from,
3576 LibertyPort *to)
3577 {
3578 DisabledInstancePorts *disabled_inst = disabled_inst_ports_.findKey(inst);
3579 if (disabled_inst == nullptr) {
3580 disabled_inst = new DisabledInstancePorts(inst);
3581 disabled_inst_ports_[inst] = disabled_inst;
3582 }
3583 if (from && to)
3584 disabled_inst->setDisabledFromTo(from, to);
3585 else if (from)
3586 disabled_inst->setDisabledFrom(from);
3587 else if (to)
3588 disabled_inst->setDisabledTo(to);
3589 else
3590 disabled_inst->setDisabledAll();
3591 }
3592
3593 void
removeDisable(Instance * inst,LibertyPort * from,LibertyPort * to)3594 Sdc::removeDisable(Instance *inst,
3595 LibertyPort *from,
3596 LibertyPort *to)
3597 {
3598 DisabledInstancePorts *disabled_inst = disabled_inst_ports_.findKey(inst);
3599 if (disabled_inst) {
3600 if (from && to)
3601 disabled_inst->removeDisabledFromTo(from, to);
3602 else if (from)
3603 disabled_inst->removeDisabledFrom(from);
3604 else if (to)
3605 disabled_inst->removeDisabledTo(to);
3606 else
3607 disabled_inst->removeDisabledAll();
3608 }
3609 }
3610
3611 void
disable(Pin * from,Pin * to)3612 Sdc::disable(Pin *from,
3613 Pin *to)
3614 {
3615 PinPair probe(from, to);
3616 if (!disabled_wire_edges_.hasKey(&probe)) {
3617 PinPair *pair = new PinPair(from, to);
3618 disabled_wire_edges_.insert(pair);
3619 }
3620 }
3621
3622 void
removeDisable(Pin * from,Pin * to)3623 Sdc::removeDisable(Pin *from,
3624 Pin *to)
3625 {
3626 PinPair probe(from, to);
3627 disabled_wire_edges_.erase(&probe);
3628 }
3629
3630 void
disable(Edge * edge)3631 Sdc::disable(Edge *edge)
3632 {
3633 disabled_edges_.insert(edge);
3634 edge->setIsDisabledConstraint(true);
3635 }
3636
3637 void
removeDisable(Edge * edge)3638 Sdc::removeDisable(Edge *edge)
3639 {
3640 disabled_edges_.erase(edge);
3641 edge->setIsDisabledConstraint(false);
3642 }
3643
3644 bool
isDisabled(Edge * edge)3645 Sdc::isDisabled(Edge *edge)
3646 {
3647 return disabled_edges_.hasKey(edge);
3648 }
3649
3650 class DisableEdgesThruHierPin : public HierPinThruVisitor
3651 {
3652 public:
3653 DisableEdgesThruHierPin(PinPairSet *pairs,
3654 Graph *graph);
3655
3656 protected:
3657 virtual void visit(Pin *drvr,
3658 Pin *load);
3659
3660 PinPairSet *pairs_;
3661 Graph *graph_;
3662
3663 private:
3664 DISALLOW_COPY_AND_ASSIGN(DisableEdgesThruHierPin);
3665 };
3666
DisableEdgesThruHierPin(PinPairSet * pairs,Graph * graph)3667 DisableEdgesThruHierPin::DisableEdgesThruHierPin(PinPairSet *pairs,
3668 Graph *graph) :
3669 HierPinThruVisitor(),
3670 pairs_(pairs),
3671 graph_(graph)
3672 {
3673 }
3674
3675 void
visit(Pin * drvr,Pin * load)3676 DisableEdgesThruHierPin::visit(Pin *drvr,
3677 Pin *load)
3678 {
3679 PinPair probe(drvr, load);
3680 if (!pairs_->hasKey(&probe)) {
3681 PinPair *pair = new PinPair(drvr, load);
3682 pairs_->insert(pair);
3683 }
3684 }
3685
3686 void
disable(Pin * pin)3687 Sdc::disable(Pin *pin)
3688 {
3689 if (network_->isHierarchical(pin)) {
3690 // Add leaf pins thru hierarchical pin to disabled_edges_.
3691 DisableEdgesThruHierPin visitor(&disabled_wire_edges_, graph_);
3692 visitDrvrLoadsThruHierPin(pin, network_, &visitor);
3693 }
3694 else
3695 disabled_pins_.insert(pin);
3696 }
3697
3698 class RemoveDisableEdgesThruHierPin : public HierPinThruVisitor
3699 {
3700 public:
3701 RemoveDisableEdgesThruHierPin(PinPairSet *pairs,
3702 Graph *graph);
3703
3704 protected:
3705 virtual void visit(Pin *drvr, Pin *load);
3706
3707 PinPairSet *pairs_;
3708 Graph *graph_;
3709
3710 private:
3711 DISALLOW_COPY_AND_ASSIGN(RemoveDisableEdgesThruHierPin);
3712 };
3713
RemoveDisableEdgesThruHierPin(PinPairSet * pairs,Graph * graph)3714 RemoveDisableEdgesThruHierPin::RemoveDisableEdgesThruHierPin(PinPairSet *pairs,
3715 Graph *graph) :
3716 HierPinThruVisitor(),
3717 pairs_(pairs),
3718 graph_(graph)
3719 {
3720 }
3721
3722 void
visit(Pin * drvr,Pin * load)3723 RemoveDisableEdgesThruHierPin::visit(Pin *drvr,
3724 Pin *load)
3725 {
3726 PinPair probe(drvr, load);
3727 PinPair *pair = pairs_->findKey(&probe);
3728 if (pair) {
3729 pairs_->erase(pair);
3730 delete pair;
3731 }
3732 }
3733
3734 void
removeDisable(Pin * pin)3735 Sdc::removeDisable(Pin *pin)
3736 {
3737 if (network_->isHierarchical(pin)) {
3738 // Remove leaf pins thru hierarchical pin from disabled_edges_.
3739 RemoveDisableEdgesThruHierPin visitor(&disabled_wire_edges_, graph_);
3740 visitDrvrLoadsThruHierPin(pin, network_, &visitor);
3741 }
3742 else
3743 disabled_pins_.erase(pin);
3744 }
3745
3746 bool
isDisabled(const Pin * pin) const3747 Sdc::isDisabled(const Pin *pin) const
3748 {
3749 Port *port = network_->port(pin);
3750 LibertyPort *lib_port = network_->libertyPort(pin);
3751 return disabled_pins_.hasKey(const_cast<Pin*>(pin))
3752 || disabled_ports_.hasKey(port)
3753 || disabled_lib_ports_.hasKey(lib_port);
3754 }
3755
3756 bool
isDisabled(const Instance * inst,const Pin * from_pin,const Pin * to_pin,const TimingRole * role) const3757 Sdc::isDisabled(const Instance *inst,
3758 const Pin *from_pin,
3759 const Pin *to_pin,
3760 const TimingRole *role) const
3761 {
3762 if (role == TimingRole::wire()) {
3763 // Hierarchical thru pin disables.
3764 PinPair pair(const_cast<Pin*>(from_pin), const_cast<Pin*>(to_pin));
3765 return disabled_wire_edges_.hasKey(&pair);
3766 }
3767 else {
3768 LibertyCell *cell = network_->libertyCell(inst);
3769 LibertyPort *from_port = network_->libertyPort(from_pin);
3770 LibertyPort *to_port = network_->libertyPort(to_pin);
3771 DisabledInstancePorts *disabled_inst =
3772 disabled_inst_ports_.findKey(const_cast<Instance*>(inst));
3773 DisabledCellPorts *disabled_cell = disabled_cell_ports_.findKey(cell);
3774 return (disabled_inst
3775 && disabled_inst->isDisabled(from_port, to_port, role))
3776 || (disabled_cell
3777 && disabled_cell->isDisabled(from_port, to_port, role));
3778 }
3779 }
3780
3781 bool
isDisabled(TimingArcSet * arc_set) const3782 Sdc::isDisabled(TimingArcSet *arc_set) const
3783 {
3784 LibertyCell *cell = arc_set->libertyCell();
3785 if (cell) {
3786 DisabledCellPorts *disabled_cell = disabled_cell_ports_.findKey(cell);
3787 return disabled_cell
3788 && disabled_cell->isDisabled(arc_set);
3789 }
3790 else
3791 return false;
3792 }
3793
3794 DisabledInstancePortsMap *
disabledInstancePorts()3795 Sdc::disabledInstancePorts()
3796 {
3797 return &disabled_inst_ports_;
3798 }
3799
3800 DisabledCellPortsMap *
disabledCellPorts()3801 Sdc::disabledCellPorts()
3802 {
3803 return &disabled_cell_ports_;
3804 }
3805
3806 void
disableClockGatingCheck(Instance * inst)3807 Sdc::disableClockGatingCheck(Instance *inst)
3808 {
3809 disabled_clk_gating_checks_inst_.insert(inst);
3810 }
3811
3812 void
disableClockGatingCheck(Pin * pin)3813 Sdc::disableClockGatingCheck(Pin *pin)
3814 {
3815 disabled_clk_gating_checks_pin_.insert(pin);
3816 }
3817
3818 void
removeDisableClockGatingCheck(Instance * inst)3819 Sdc::removeDisableClockGatingCheck(Instance *inst)
3820 {
3821 disabled_clk_gating_checks_inst_.erase(inst);
3822 }
3823
3824 void
removeDisableClockGatingCheck(Pin * pin)3825 Sdc::removeDisableClockGatingCheck(Pin *pin)
3826 {
3827 disabled_clk_gating_checks_pin_.erase(pin);
3828 }
3829
3830 bool
isDisableClockGatingCheck(const Instance * inst)3831 Sdc::isDisableClockGatingCheck(const Instance *inst)
3832 {
3833 return disabled_clk_gating_checks_inst_.hasKey(const_cast<Instance*>(inst));
3834 }
3835
3836 bool
isDisableClockGatingCheck(const Pin * pin)3837 Sdc::isDisableClockGatingCheck(const Pin *pin)
3838 {
3839 return disabled_clk_gating_checks_pin_.hasKey(const_cast<Pin*>(pin));
3840 }
3841
3842 ////////////////////////////////////////////////////////////////
3843
3844 void
setLogicValue(Pin * pin,LogicValue value)3845 Sdc::setLogicValue(Pin *pin,
3846 LogicValue value)
3847 {
3848 logic_value_map_[pin] = value;
3849 }
3850
3851 void
logicValue(const Pin * pin,LogicValue & value,bool & exists)3852 Sdc::logicValue(const Pin *pin,
3853 LogicValue &value,
3854 bool &exists)
3855 {
3856 logic_value_map_.findKey(pin, value, exists);
3857 }
3858
3859 void
setCaseAnalysis(Pin * pin,LogicValue value)3860 Sdc::setCaseAnalysis(Pin *pin,
3861 LogicValue value)
3862 {
3863 case_value_map_[pin] = value;
3864 }
3865
3866 void
removeCaseAnalysis(Pin * pin)3867 Sdc::removeCaseAnalysis(Pin *pin)
3868 {
3869 case_value_map_.erase(pin);
3870 }
3871
3872 void
caseLogicValue(const Pin * pin,LogicValue & value,bool & exists)3873 Sdc::caseLogicValue(const Pin *pin,
3874 LogicValue &value,
3875 bool &exists)
3876 {
3877 case_value_map_.findKey(pin, value, exists);
3878 }
3879
3880 bool
hasLogicValue(const Pin * pin)3881 Sdc::hasLogicValue(const Pin *pin)
3882 {
3883 return case_value_map_.hasKey(pin)
3884 || logic_value_map_.hasKey(pin);
3885 }
3886
3887 ////////////////////////////////////////////////////////////////
3888
3889 ExceptionFrom *
makeExceptionFrom(PinSet * from_pins,ClockSet * from_clks,InstanceSet * from_insts,const RiseFallBoth * from_rf)3890 Sdc::makeExceptionFrom(PinSet *from_pins,
3891 ClockSet *from_clks,
3892 InstanceSet *from_insts,
3893 const RiseFallBoth *from_rf)
3894 {
3895 if ((from_pins && !from_pins->empty())
3896 || (from_clks && !from_clks->empty())
3897 || (from_insts && !from_insts->empty()))
3898 return new ExceptionFrom(from_pins, from_clks, from_insts, from_rf, true);
3899 else
3900 return nullptr;
3901 }
3902
3903 ExceptionThru *
makeExceptionThru(PinSet * pins,NetSet * nets,InstanceSet * insts,const RiseFallBoth * rf)3904 Sdc::makeExceptionThru(PinSet *pins,
3905 NetSet *nets,
3906 InstanceSet *insts,
3907 const RiseFallBoth *rf)
3908 {
3909 if ((pins && !pins->empty())
3910 || (nets && !nets->empty())
3911 || (insts && !insts->empty()))
3912 return new ExceptionThru(pins, nets, insts, rf, true, network_);
3913 else
3914 return nullptr;
3915 }
3916
3917 ExceptionTo *
makeExceptionTo(PinSet * pins,ClockSet * clks,InstanceSet * insts,const RiseFallBoth * rf,const RiseFallBoth * end_rf)3918 Sdc::makeExceptionTo(PinSet *pins,
3919 ClockSet *clks,
3920 InstanceSet *insts,
3921 const RiseFallBoth *rf,
3922 const RiseFallBoth *end_rf)
3923 {
3924 if ((pins && !pins->empty())
3925 || (clks && !clks->empty())
3926 || (insts && !insts->empty())
3927 || (rf != RiseFallBoth::riseFall())
3928 || (end_rf != RiseFallBoth::riseFall()))
3929 return new ExceptionTo(pins, clks, insts, rf, end_rf, true);
3930 else
3931 return nullptr;
3932 }
3933
3934 // Valid endpoints include gated clock enables which are not
3935 // known until clock arrivals are determined.
3936 bool
exceptionToInvalid(const Pin * pin)3937 Sdc::exceptionToInvalid(const Pin *pin)
3938 {
3939 Net *net = network_->net(pin);
3940 // Floating pins are invalid.
3941 if ((net == nullptr
3942 && !network_->isTopLevelPort(pin))
3943 || (net
3944 // Pins connected to power/ground are invalid.
3945 && (network_->isPower(net)
3946 || network_->isGround(net)))
3947 // Hierarchical pins are invalid.
3948 || network_->isHierarchical(pin))
3949 return true;
3950 // Register/latch Q pins are invalid.
3951 LibertyPort *port = network_->libertyPort(pin);
3952 if (port) {
3953 LibertyCell *cell = port->libertyCell();
3954 LibertyCellTimingArcSetIterator set_iter(cell, nullptr, port);
3955 while (set_iter.hasNext()) {
3956 TimingArcSet *set = set_iter.next();
3957 TimingRole *role = set->role();
3958 if (role->genericRole() == TimingRole::regClkToQ())
3959 return true;
3960 }
3961 }
3962 return false;
3963 }
3964
3965 void
makeFalsePath(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max,const char * comment)3966 Sdc::makeFalsePath(ExceptionFrom *from,
3967 ExceptionThruSeq *thrus,
3968 ExceptionTo *to,
3969 const MinMaxAll *min_max,
3970 const char *comment)
3971 {
3972 checkFromThrusTo(from, thrus, to);
3973 FalsePath *exception = new FalsePath(from, thrus, to, min_max, true,
3974 comment);
3975 addException(exception);
3976 }
3977
3978 void
makeMulticyclePath(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max,bool use_end_clk,int path_multiplier,const char * comment)3979 Sdc::makeMulticyclePath(ExceptionFrom *from,
3980 ExceptionThruSeq *thrus,
3981 ExceptionTo *to,
3982 const MinMaxAll *min_max,
3983 bool use_end_clk,
3984 int path_multiplier,
3985 const char *comment)
3986 {
3987 checkFromThrusTo(from, thrus, to);
3988 MultiCyclePath *exception = new MultiCyclePath(from, thrus, to,
3989 min_max, use_end_clk,
3990 path_multiplier, true,
3991 comment);
3992 addException(exception);
3993 }
3994
3995 void
makePathDelay(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMax * min_max,bool ignore_clk_latency,float delay,const char * comment)3996 Sdc::makePathDelay(ExceptionFrom *from,
3997 ExceptionThruSeq *thrus,
3998 ExceptionTo *to,
3999 const MinMax *min_max,
4000 bool ignore_clk_latency,
4001 float delay,
4002 const char *comment)
4003 {
4004 checkFromThrusTo(from, thrus, to);
4005 PathDelay *exception = new PathDelay(from, thrus, to, min_max,
4006 ignore_clk_latency, delay, true,
4007 comment);
4008 addException(exception);
4009 }
4010
4011 void
recordPathDelayInternalStartpoints(ExceptionPath * exception)4012 Sdc::recordPathDelayInternalStartpoints(ExceptionPath *exception)
4013 {
4014 ExceptionFrom *from = exception->from();
4015 if (from
4016 && from->hasPins()) {
4017 PinSet::Iterator pin_iter(from->pins());
4018 while (pin_iter.hasNext()) {
4019 Pin *pin = pin_iter.next();
4020 if (!(network_->isRegClkPin(pin)
4021 || network_->isTopLevelPort(pin))) {
4022 if (path_delay_internal_startpoints_ == nullptr)
4023 path_delay_internal_startpoints_ = new PinSet;
4024 path_delay_internal_startpoints_->insert(pin);
4025 }
4026 }
4027 }
4028 }
4029
4030 void
unrecordPathDelayInternalStartpoints(ExceptionFrom * from)4031 Sdc::unrecordPathDelayInternalStartpoints(ExceptionFrom *from)
4032 {
4033 if (from
4034 && from->hasPins()
4035 && path_delay_internal_startpoints_) {
4036 PinSet::Iterator pin_iter(from->pins());
4037 while (pin_iter.hasNext()) {
4038 Pin *pin = pin_iter.next();
4039 if (!(network_->isRegClkPin(pin)
4040 || network_->isTopLevelPort(pin))
4041 && !pathDelayFrom(pin))
4042 path_delay_internal_startpoints_->erase(pin);
4043 }
4044 }
4045 }
4046
4047 bool
pathDelayFrom(const Pin * pin)4048 Sdc::pathDelayFrom(const Pin *pin)
4049 {
4050 if (first_from_pin_exceptions_) {
4051 ExceptionPathSet *exceptions = first_from_pin_exceptions_->findKey(pin);
4052 ExceptionPathSet::ConstIterator exception_iter(exceptions);
4053 while (exception_iter.hasNext()) {
4054 ExceptionPath *exception = exception_iter.next();
4055 if (exception->isPathDelay())
4056 return true;
4057 }
4058 }
4059 return false;
4060 }
4061
4062 bool
isPathDelayInternalStartpoint(const Pin * pin) const4063 Sdc::isPathDelayInternalStartpoint(const Pin *pin) const
4064 {
4065 return path_delay_internal_startpoints_
4066 && path_delay_internal_startpoints_->hasKey(const_cast<Pin*>(pin));
4067 }
4068
4069 PinSet *
pathDelayInternalStartpoints() const4070 Sdc::pathDelayInternalStartpoints() const
4071 {
4072 return path_delay_internal_startpoints_;
4073 }
4074
4075 void
recordPathDelayInternalEndpoints(ExceptionPath * exception)4076 Sdc::recordPathDelayInternalEndpoints(ExceptionPath *exception)
4077 {
4078 ExceptionTo *to = exception->to();
4079 if (to
4080 && to->hasPins()) {
4081 PinSet::Iterator pin_iter(to->pins());
4082 while (pin_iter.hasNext()) {
4083 Pin *pin = pin_iter.next();
4084 if (!(hasLibertyChecks(pin)
4085 || network_->isTopLevelPort(pin))) {
4086 if (path_delay_internal_endpoints_ == nullptr)
4087 path_delay_internal_endpoints_ = new PinSet;
4088 path_delay_internal_endpoints_->insert(pin);
4089 }
4090 }
4091 }
4092 }
4093
4094 void
unrecordPathDelayInternalEndpoints(ExceptionPath * exception)4095 Sdc::unrecordPathDelayInternalEndpoints(ExceptionPath *exception)
4096 {
4097 ExceptionTo *to = exception->to();
4098 if (to
4099 && to->hasPins()
4100 && path_delay_internal_endpoints_) {
4101 PinSet::Iterator pin_iter(to->pins());
4102 while (pin_iter.hasNext()) {
4103 Pin *pin = pin_iter.next();
4104 if (!(hasLibertyChecks(pin)
4105 || network_->isTopLevelPort(pin))
4106 && !pathDelayTo(pin))
4107 path_delay_internal_endpoints_->erase(pin);
4108 }
4109 }
4110 }
4111
4112 bool
hasLibertyChecks(const Pin * pin)4113 Sdc::hasLibertyChecks(const Pin *pin)
4114 {
4115 const Instance *inst = network_->instance(pin);
4116 LibertyCell *cell = network_->libertyCell(inst);
4117 if (cell) {
4118 LibertyPort *port = network_->libertyPort(pin);
4119 if (port) {
4120 LibertyCellTimingArcSetIterator timing_iter(cell, nullptr, port);
4121 while (timing_iter.hasNext()) {
4122 TimingArcSet *arc_set = timing_iter.next();
4123 if (arc_set->role()->isTimingCheck())
4124 return true;
4125 }
4126 }
4127 }
4128 return false;
4129 }
4130
4131 bool
pathDelayTo(const Pin * pin)4132 Sdc::pathDelayTo(const Pin *pin)
4133 {
4134 if (first_to_pin_exceptions_) {
4135 ExceptionPathSet *exceptions = first_to_pin_exceptions_->findKey(pin);
4136 ExceptionPathSet::ConstIterator exception_iter(exceptions);
4137 while (exception_iter.hasNext()) {
4138 ExceptionPath *exception = exception_iter.next();
4139 if (exception->isPathDelay())
4140 return true;
4141 }
4142 }
4143 return false;
4144 }
4145
4146 bool
isPathDelayInternalEndpoint(const Pin * pin) const4147 Sdc::isPathDelayInternalEndpoint(const Pin *pin) const
4148 {
4149 return path_delay_internal_endpoints_
4150 && path_delay_internal_endpoints_->hasKey(const_cast<Pin*>(pin));
4151 }
4152
4153 ////////////////////////////////////////////////////////////////
4154
4155 void
clearGroupPathMap()4156 Sdc::clearGroupPathMap()
4157 {
4158 // GroupPath exceptions are deleted with other exceptions.
4159 // Delete group_path name strings.
4160 GroupPathIterator group_path_iter(group_path_map_);
4161 while (group_path_iter.hasNext()) {
4162 const char *name;
4163 GroupPathSet *groups;
4164 group_path_iter.next(name, groups);
4165 stringDelete(name);
4166 delete groups;
4167 }
4168 group_path_map_.clear();
4169 }
4170
4171 void
makeGroupPath(const char * name,bool is_default,ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const char * comment)4172 Sdc::makeGroupPath(const char *name,
4173 bool is_default,
4174 ExceptionFrom *from,
4175 ExceptionThruSeq *thrus,
4176 ExceptionTo *to,
4177 const char *comment)
4178 {
4179 checkFromThrusTo(from, thrus, to);
4180 if (name && is_default)
4181 report_->critical(213, "group path name and is_default are mutually exclusive.");
4182 else if (name) {
4183 GroupPath *group_path = new GroupPath(name, is_default, from, thrus, to,
4184 true, comment);
4185 addException(group_path);
4186 // A named group path can have multiple exceptions.
4187 GroupPathSet *groups = group_path_map_.findKey(name);
4188 if (groups == nullptr) {
4189 groups = new GroupPathSet;
4190 group_path_map_[stringCopy(name)] = groups;
4191 }
4192 groups->insert(group_path);
4193 }
4194 else {
4195 // is_default
4196 GroupPath *group_path = new GroupPath(name, is_default, from, thrus, to,
4197 true, comment);
4198 addException(group_path);
4199 }
4200 }
4201
4202 bool
isGroupPathName(const char * group_name)4203 Sdc::isGroupPathName(const char *group_name)
4204 {
4205 return group_path_map_.hasKey(group_name);
4206 }
4207
4208 GroupPathIterator *
groupPathIterator()4209 Sdc::groupPathIterator()
4210 {
4211 return new GroupPathIterator(group_path_map_);
4212 }
4213
4214 ////////////////////////////////////////////////////////////////
4215
4216 FilterPath *
makeFilterPath(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to)4217 Sdc::makeFilterPath(ExceptionFrom *from,
4218 ExceptionThruSeq *thrus,
4219 ExceptionTo *to)
4220 {
4221 checkFromThrusTo(from, thrus, to);
4222 FilterPath *exception = new FilterPath(from, thrus, to, true);
4223 addException(exception);
4224 // This is the only type of exception that can be returned.
4225 // There is only one of them, so it shouldn't merge.
4226 return exception;
4227 }
4228
4229 ////////////////////////////////////////////////////////////////
4230
4231 void
makeLoopExceptions()4232 Sdc::makeLoopExceptions()
4233 {
4234 GraphLoopSeq::Iterator loop_iter(levelize_->loops());
4235 while (loop_iter.hasNext()) {
4236 GraphLoop *loop = loop_iter.next();
4237 makeLoopExceptions(loop);
4238 }
4239 }
4240
4241 // Make a -thru pin false path from every edge entering the loop
4242 // around the loop and back.
4243 void
makeLoopExceptions(GraphLoop * loop)4244 Sdc::makeLoopExceptions(GraphLoop *loop)
4245 {
4246 debugPrint(debug_, "loop", 2, "Loop false path");
4247 EdgeSeq::Iterator loop_edge_iter(loop->edges());
4248 while (loop_edge_iter.hasNext()) {
4249 Edge *edge = loop_edge_iter.next();
4250 Vertex *from_vertex = edge->from(graph_);
4251 Vertex *to_vertex = edge->to(graph_);
4252 Pin *from_pin = from_vertex->pin();
4253 Pin *to_pin = to_vertex->pin();
4254 // Find edges entering the loop.
4255 VertexInEdgeIterator in_edge_iter(to_vertex, graph_);
4256 while (in_edge_iter.hasNext()) {
4257 Edge *in_edge = in_edge_iter.next();
4258 if (in_edge != edge) {
4259 Pin *loop_input_pin = in_edge->from(graph_)->pin();
4260 makeLoopException(loop_input_pin, to_pin, from_pin);
4261 // Prevent sub-loops by blocking paths on the main loop also.
4262 makeLoopException(from_pin, to_pin, loop_input_pin);
4263 }
4264 }
4265 }
4266 }
4267
4268 void
makeLoopException(Pin * loop_input_pin,Pin * loop_pin,Pin * loop_prev_pin)4269 Sdc::makeLoopException(Pin *loop_input_pin,
4270 Pin *loop_pin,
4271 Pin *loop_prev_pin)
4272 {
4273 ExceptionThruSeq *thrus = new ExceptionThruSeq;
4274 makeLoopExceptionThru(loop_input_pin, thrus);
4275 makeLoopExceptionThru(loop_pin, thrus);
4276 makeLoopExceptionThru(loop_prev_pin, thrus);
4277 makeLoopExceptionThru(loop_pin, thrus);
4278 makeLoopPath(thrus);
4279 }
4280
4281 void
makeLoopPath(ExceptionThruSeq * thrus)4282 Sdc::makeLoopPath(ExceptionThruSeq *thrus)
4283 {
4284 FalsePath *exception = new LoopPath(thrus, true);
4285 addException(exception);
4286 }
4287
4288 void
makeLoopExceptionThru(Pin * pin,ExceptionThruSeq * thrus)4289 Sdc::makeLoopExceptionThru(Pin *pin,
4290 ExceptionThruSeq *thrus)
4291 {
4292 debugPrint(debug_, "levelize", 2, " %s", network_->pathName(pin));
4293 PinSet *pins = new PinSet;
4294 pins->insert(pin);
4295 ExceptionThru *thru = makeExceptionThru(pins, nullptr, nullptr,
4296 RiseFallBoth::riseFall());
4297 thrus->push_back(thru);
4298 }
4299
4300 void
deleteLoopExceptions()4301 Sdc::deleteLoopExceptions()
4302 {
4303 ExceptionPathSet::Iterator except_iter(exceptions_);
4304 while (except_iter.hasNext()) {
4305 ExceptionPath *except = except_iter.next();
4306 if (except->isLoop())
4307 deleteException(except);
4308 }
4309 }
4310
4311 ////////////////////////////////////////////////////////////////
4312
4313 void
addException(ExceptionPath * exception)4314 Sdc::addException(ExceptionPath *exception)
4315 {
4316 debugPrint(debug_, "exception_merge", 1, "add exception for %s",
4317 exception->asString(network_));
4318
4319 if (exception->isPathDelay()) {
4320 recordPathDelayInternalStartpoints(exception);
4321 recordPathDelayInternalEndpoints(exception);
4322 if (exception->to() == nullptr)
4323 path_delays_without_to_ = true;
4324 }
4325
4326 // Check to see if the exception has from/to mixed object types.
4327 // If so, the priority of the exception is mixed.
4328 // Split it into separate exceptions that have consistent priority.
4329 ExceptionFrom *from = exception->from();
4330 if (from
4331 && (from->hasPins() || from->hasInstances())
4332 && from->hasClocks()) {
4333 PinSet *pins1 = from->pins() ? new PinSet(*from->pins()) : nullptr;
4334 InstanceSet *insts1 =
4335 from->instances() ? new InstanceSet(*from->instances()) : nullptr;
4336 ExceptionFrom *from1 = new ExceptionFrom(pins1, nullptr, insts1,
4337 from->transition(), true);
4338 ExceptionThruSeq *thrus1 = exceptionThrusClone(exception->thrus(), network_);
4339 ExceptionTo *to = exception->to();
4340 ExceptionTo *to1 = to ? to->clone() : nullptr;
4341 ExceptionPath *exception1 = exception->clone(from1, thrus1, to1, true);
4342 debugPrint(debug_, "exception_merge", 1, " split exception for %s",
4343 exception1->asString(network_));
4344 addException1(exception1);
4345
4346 ClockSet *clks2 = new ClockSet(*from->clks());
4347 ExceptionFrom *from2 = new ExceptionFrom(nullptr, clks2, nullptr,
4348 from->transition(), true);
4349 ExceptionThruSeq *thrus2 = exceptionThrusClone(exception->thrus(), network_);
4350 ExceptionTo *to2 = to ? to->clone() : nullptr;
4351 ExceptionPath *exception2 = exception->clone(from2, thrus2, to2, true);
4352 debugPrint(debug_, "exception_merge", 1, " split exception for %s",
4353 exception2->asString(network_));
4354 addException1(exception2);
4355
4356 delete exception;
4357 }
4358 else
4359 addException1(exception);
4360 }
4361
4362 void
addException1(ExceptionPath * exception)4363 Sdc::addException1(ExceptionPath *exception)
4364 {
4365 ExceptionTo *to = exception->to();
4366 if (to
4367 && (to->hasPins() || to->hasInstances())
4368 && to->hasClocks()) {
4369 ExceptionFrom *from1 = exception->from() ? exception->from()->clone() : nullptr;
4370 ExceptionThruSeq *thrus1 = exceptionThrusClone(exception->thrus(), network_);
4371 PinSet *pins1 = to->pins() ? new PinSet(*to->pins()) : nullptr;
4372 InstanceSet *insts1 = to->instances() ? new InstanceSet(*to->instances()) : nullptr;
4373 ExceptionTo *to1 = new ExceptionTo(pins1, nullptr, insts1,
4374 to->transition(),
4375 to->endTransition(), true);
4376 ExceptionPath *exception1 = exception->clone(from1, thrus1, to1, true);
4377 debugPrint(debug_, "exception_merge", 1, " split exception for %s",
4378 exception1->asString(network_));
4379 addException2(exception1);
4380
4381 ExceptionFrom *from2 = exception->from() ? exception->from()->clone() : nullptr;
4382 ExceptionThruSeq *thrus2 = exceptionThrusClone(exception->thrus(), network_);
4383 ClockSet *clks2 = new ClockSet(*to->clks());
4384 ExceptionTo *to2 = new ExceptionTo(nullptr, clks2, nullptr, to->transition(),
4385 to->endTransition(), true);
4386 ExceptionPath *exception2 = exception->clone(from2, thrus2, to2, true);
4387 debugPrint(debug_, "exception_merge", 1, " split exception for %s",
4388 exception2->asString(network_));
4389 addException2(exception2);
4390
4391 delete exception;
4392 }
4393 else
4394 addException2(exception);
4395 }
4396
4397 void
addException2(ExceptionPath * exception)4398 Sdc::addException2(ExceptionPath *exception)
4399 {
4400 if (exception->isMultiCycle() || exception->isPathDelay())
4401 deleteMatchingExceptions(exception);
4402 recordException(exception);
4403 mergeException(exception);
4404 }
4405
4406 // If a path delay/multicycle exception is redefined with a different
4407 // delay/cycle count, the new exception overrides the existing
4408 // exception. Multiple related exceptions are merged to reduce the
4409 // number of tags. To support overrides, relevant merged exceptions must be
4410 // expanded to find and delete or override the new exception.
4411 // For example, the exception
4412 // set_multi_cycle_path -from {A B} -to {C D} 2
4413 // is a merged representation of the following four exceptions:
4414 // set_multi_cycle_path -from A -to C 2
4415 // set_multi_cycle_path -from A -to D 2
4416 // set_multi_cycle_path -from B -to C 2
4417 // set_multi_cycle_path -from B -to D 2
4418 // If the following exception is later defined,
4419 // set_multi_cycle_path -from A -to C 3
4420 // The cycle count of one of the merged exceptions changes.
4421 // This prevents the original four exceptions from merging into one
4422 // exception.
4423 //
4424 // This situation is handled by breaking the original merged exception
4425 // into multiple smaller exceptions that exclude the new subset
4426 // exception. This is NOT done by expanding the merged exception,
4427 // since the number of exception points can be huge leading to serious
4428 // run time problems.
4429 //
4430 // For the example above, the merged exception is broken down into the
4431 // following set of exceptions that exclude the new subset exception.
4432 //
4433 // set_multi_cycle_path -from {B} -to {C D} 2
4434 // set_multi_cycle_path -from {A} -to {D} 2
4435 //
4436 // In general, the merged exception is broken down as follows:
4437 //
4438 // -from {merged_from - subset_from} -thru merged_thru... -to merged_to
4439 // -from merged_from -thru {merged_thru - subset_thru}... -to merged_to
4440 // -from merged_from -thru merged_thru... -to {merged_to - subset_to}
4441 //
4442 // Where the {set1 - set2} is the set difference of of the from/thru/to
4443 // objects of the merged/subset exception. If the set difference is empty,
4444 // that group of exceptions matches the subset so it should not be included
4445 // in the expansion.
4446
4447 void
deleteMatchingExceptions(ExceptionPath * exception)4448 Sdc::deleteMatchingExceptions(ExceptionPath *exception)
4449 {
4450 debugPrint(debug_, "exception_merge", 1, "find matches for %s",
4451 exception->asString(network_));
4452 ExceptionPathSet matches;
4453 findMatchingExceptions(exception, matches);
4454
4455 ExceptionPathSet expanded_matches;
4456 ExceptionPathSet::Iterator match_iter1(matches);
4457 while (match_iter1.hasNext()) {
4458 ExceptionPath *match = match_iter1.next();
4459 // Expand the matching exception into a set of exceptions that
4460 // that do not cover the new exception. Do not record them
4461 // to prevent merging with the match, which will be deleted.
4462 expandExceptionExcluding(match, exception, expanded_matches);
4463 }
4464
4465 ExceptionPathSet::Iterator match_iter2(matches);
4466 while (match_iter2.hasNext()) {
4467 ExceptionPath *match = match_iter2.next();
4468 deleteException(match);
4469 }
4470
4471 ExceptionPathSet::Iterator expanded_iter(expanded_matches);
4472 while (expanded_iter.hasNext()) {
4473 ExceptionPath *expand = expanded_iter.next();
4474 addException(expand);
4475 }
4476 }
4477
4478 void
findMatchingExceptions(ExceptionPath * exception,ExceptionPathSet & matches)4479 Sdc::findMatchingExceptions(ExceptionPath *exception,
4480 ExceptionPathSet &matches)
4481 {
4482 if (exception->from())
4483 findMatchingExceptionsFirstFrom(exception, matches);
4484 else if (exception->thrus())
4485 findMatchingExceptionsFirstThru(exception, matches);
4486 else if (exception->to())
4487 findMatchingExceptionsFirstTo(exception, matches);
4488 }
4489
4490 void
findMatchingExceptionsFirstFrom(ExceptionPath * exception,ExceptionPathSet & matches)4491 Sdc::findMatchingExceptionsFirstFrom(ExceptionPath *exception,
4492 ExceptionPathSet &matches)
4493 {
4494 ExceptionFrom *from = exception->from();
4495 if (first_from_pin_exceptions_)
4496 findMatchingExceptionsPins(exception, from->pins(),
4497 first_from_pin_exceptions_,
4498 matches);
4499 if (first_from_inst_exceptions_)
4500 findMatchingExceptionsInsts(exception, from->instances(),
4501 first_from_inst_exceptions_, matches);
4502 if (first_from_clk_exceptions_)
4503 findMatchingExceptionsClks(exception, from->clks(),
4504 first_from_clk_exceptions_,
4505 matches);
4506 }
4507
4508 void
findMatchingExceptionsFirstThru(ExceptionPath * exception,ExceptionPathSet & matches)4509 Sdc::findMatchingExceptionsFirstThru(ExceptionPath *exception,
4510 ExceptionPathSet &matches)
4511 {
4512 ExceptionThru *thru = (*exception->thrus())[0];
4513 findMatchingExceptionsPins(exception, thru->pins(),
4514 first_thru_pin_exceptions_,
4515 matches);
4516 findMatchingExceptionsInsts(exception, thru->instances(),
4517 first_thru_inst_exceptions_,
4518 matches);
4519 if (first_thru_net_exceptions_) {
4520 NetSet::Iterator net_iter(thru->nets());
4521 if (net_iter.hasNext()) {
4522 Net *net = net_iter.next();
4523 // Potential matches includes exceptions that match net that are not
4524 // the first exception point.
4525 ExceptionPathSet *potential_matches =
4526 first_thru_net_exceptions_->findKey(net);
4527 if (potential_matches) {
4528 ExceptionPathSet::Iterator match_iter(potential_matches);
4529 while (match_iter.hasNext()) {
4530 ExceptionPath *match = match_iter.next();
4531 ExceptionThru *match_thru = (*match->thrus())[0];
4532 if (match_thru->nets()->hasKey(net)
4533 && match->overrides(exception)
4534 && match->intersectsPts(exception))
4535 matches.insert(match);
4536 }
4537 }
4538 }
4539 }
4540 }
4541
4542 void
findMatchingExceptionsFirstTo(ExceptionPath * exception,ExceptionPathSet & matches)4543 Sdc::findMatchingExceptionsFirstTo(ExceptionPath *exception,
4544 ExceptionPathSet &matches)
4545 {
4546 ExceptionTo *to = exception->to();
4547 findMatchingExceptionsPins(exception, to->pins(), first_to_pin_exceptions_,
4548 matches);
4549 findMatchingExceptionsInsts(exception, to->instances(),
4550 first_to_inst_exceptions_,
4551 matches);
4552 findMatchingExceptionsClks(exception, to->clks(), first_to_clk_exceptions_,
4553 matches);
4554 }
4555
4556 void
findMatchingExceptionsClks(ExceptionPath * exception,ClockSet * clks,ClockExceptionsMap * exception_map,ExceptionPathSet & matches)4557 Sdc::findMatchingExceptionsClks(ExceptionPath *exception,
4558 ClockSet *clks,
4559 ClockExceptionsMap *exception_map,
4560 ExceptionPathSet &matches)
4561 {
4562 if (exception_map) {
4563 ExceptionPathSet clks_matches;
4564 ClockSet::Iterator clk_iter(clks);
4565 while (clk_iter.hasNext()) {
4566 Clock *clk = clk_iter.next();
4567 clks_matches.insertSet(exception_map->findKey(clk));
4568 }
4569 findMatchingExceptions(exception, &clks_matches, matches);
4570 }
4571 }
4572
4573 void
findMatchingExceptionsPins(ExceptionPath * exception,PinSet * pins,PinExceptionsMap * exception_map,ExceptionPathSet & matches)4574 Sdc::findMatchingExceptionsPins(ExceptionPath *exception,
4575 PinSet *pins,
4576 PinExceptionsMap *exception_map,
4577 ExceptionPathSet &matches)
4578 {
4579 if (exception_map) {
4580 ExceptionPathSet pins_matches;
4581 PinSet::Iterator pin_iter(pins);
4582 while (pin_iter.hasNext()) {
4583 const Pin *pin = pin_iter.next();
4584 pins_matches.insertSet(exception_map->findKey(pin));
4585 }
4586 findMatchingExceptions(exception, &pins_matches, matches);
4587 }
4588 }
4589
4590 void
findMatchingExceptionsInsts(ExceptionPath * exception,InstanceSet * insts,InstanceExceptionsMap * exception_map,ExceptionPathSet & matches)4591 Sdc::findMatchingExceptionsInsts(ExceptionPath *exception,
4592 InstanceSet *insts,
4593 InstanceExceptionsMap *exception_map,
4594 ExceptionPathSet &matches)
4595 {
4596 if (exception_map) {
4597 ExceptionPathSet insts_matches;
4598 InstanceSet::Iterator inst_iter(insts);
4599 while (inst_iter.hasNext()) {
4600 Instance *inst = inst_iter.next();
4601 insts_matches.insertSet(exception_map->findKey(inst));
4602 }
4603 findMatchingExceptions(exception, &insts_matches, matches);
4604 }
4605 }
4606
4607 void
findMatchingExceptions(ExceptionPath * exception,ExceptionPathSet * potential_matches,ExceptionPathSet & matches)4608 Sdc::findMatchingExceptions(ExceptionPath *exception,
4609 ExceptionPathSet *potential_matches,
4610 ExceptionPathSet &matches)
4611 {
4612 if (potential_matches) {
4613 ExceptionPathSet::Iterator match_iter(potential_matches);
4614 while (match_iter.hasNext()) {
4615 ExceptionPath *match = match_iter.next();
4616 if (match->overrides(exception)
4617 && match->intersectsPts(exception))
4618 matches.insert(match);
4619 }
4620 }
4621 }
4622
4623 void
expandExceptionExcluding(ExceptionPath * exception,ExceptionPath * excluding,ExceptionPathSet & expansions)4624 Sdc::expandExceptionExcluding(ExceptionPath *exception,
4625 ExceptionPath *excluding,
4626 ExceptionPathSet &expansions)
4627 {
4628 ExceptionFrom *from = exception->from();
4629 ExceptionThruSeq *thrus = exception->thrus();
4630 ExceptionTo *to = exception->to();
4631 if (from) {
4632 ExceptionFrom *from_cpy = from->clone();
4633 from_cpy->deleteObjects(excluding->from());
4634 if (from_cpy->hasObjects()) {
4635 ExceptionThruSeq *thrus_cpy = nullptr;
4636 if (thrus)
4637 thrus_cpy = clone(thrus, network_);
4638 ExceptionTo *to_cpy = nullptr;
4639 if (to)
4640 to_cpy = to->clone();
4641 ExceptionPath *expand = exception->clone(from_cpy,thrus_cpy,to_cpy,true);
4642 expansions.insert(expand);
4643 }
4644 else
4645 delete from_cpy;
4646 }
4647 if (thrus) {
4648 ExceptionThruSeq::Iterator thru_iter(thrus);
4649 ExceptionThruSeq::Iterator thru_iter2(excluding->thrus());
4650 while (thru_iter.hasNext()
4651 && thru_iter2.hasNext()) {
4652 ExceptionThru *thru = thru_iter.next();
4653 ExceptionThru *thru2 = thru_iter2.next();
4654 ExceptionThru *thru_cpy = thru->clone(network_);
4655 thru_cpy->deleteObjects(thru2);
4656 if (thru_cpy->hasObjects()) {
4657 ExceptionFrom *from_cpy = nullptr;
4658 if (from)
4659 from_cpy = from->clone();
4660 ExceptionThruSeq *thrus_cpy = new ExceptionThruSeq;
4661 ExceptionThruSeq::Iterator thru_iter1(thrus);
4662 while (thru_iter1.hasNext()) {
4663 ExceptionThru *thru1 = thru_iter1.next();
4664 if (thru1 == thru)
4665 thrus_cpy->push_back(thru_cpy);
4666 else {
4667 ExceptionThru *thru_cpy = thru->clone(network_);
4668 thrus_cpy->push_back(thru_cpy);
4669 }
4670 }
4671 ExceptionTo *to_cpy = nullptr;
4672 if (to)
4673 to_cpy = to->clone();
4674 ExceptionPath *expand = exception->clone(from_cpy, thrus_cpy, to_cpy,
4675 true);
4676 expansions.insert(expand);
4677 }
4678 else
4679 delete thru_cpy;
4680 }
4681 }
4682 if (to) {
4683 ExceptionTo *to_cpy = to->clone();
4684 to_cpy->deleteObjects(excluding->to());
4685 if (to_cpy->hasObjects()) {
4686 ExceptionFrom *from_cpy = nullptr;
4687 if (from)
4688 from_cpy = from->clone();
4689 ExceptionThruSeq *thrus_cpy = nullptr;
4690 if (thrus)
4691 thrus_cpy = clone(thrus, network_);
4692 ExceptionPath *expand = exception->clone(from_cpy,thrus_cpy,to_cpy,true);
4693 expansions.insert(expand);
4694 }
4695 else
4696 delete to_cpy;
4697 }
4698 }
4699
4700 static ExceptionThruSeq *
clone(ExceptionThruSeq * thrus,Network * network)4701 clone(ExceptionThruSeq *thrus, Network *network)
4702 {
4703 ExceptionThruSeq *thrus_cpy = new ExceptionThruSeq;
4704 ExceptionThruSeq::Iterator thru_iter(thrus);
4705 while (thru_iter.hasNext()) {
4706 ExceptionThru *thru = thru_iter.next();
4707 ExceptionThru *thru_cpy = thru->clone(network);
4708 thrus_cpy->push_back(thru_cpy);
4709 }
4710 return thrus_cpy;
4711 }
4712
4713 ////////////////////////////////////////////////////////////////
4714
4715 void
recordException(ExceptionPath * exception)4716 Sdc::recordException(ExceptionPath *exception)
4717 {
4718 exceptions_.insert(exception);
4719 recordMergeHashes(exception);
4720 recordExceptionFirstPts(exception);
4721 checkForThruHpins(exception);
4722 }
4723
4724 void
checkForThruHpins(ExceptionPath * exception)4725 Sdc::checkForThruHpins(ExceptionPath *exception)
4726 {
4727 ExceptionThruSeq *thrus = exception->thrus();
4728 if (thrus) {
4729 for (ExceptionThru *thru : *thrus) {
4730 if (thru->edges()) {
4731 have_thru_hpin_exceptions_ = true;
4732 break;
4733 }
4734 }
4735 }
4736 }
4737
4738 void
recordMergeHashes(ExceptionPath * exception)4739 Sdc::recordMergeHashes(ExceptionPath *exception)
4740 {
4741 ExceptionPtIterator missing_pt_iter(exception);
4742 while (missing_pt_iter.hasNext()) {
4743 ExceptionPt *missing_pt = missing_pt_iter.next();
4744 recordMergeHash(exception, missing_pt);
4745 }
4746 }
4747
4748 void
recordMergeHash(ExceptionPath * exception,ExceptionPt * missing_pt)4749 Sdc::recordMergeHash(ExceptionPath *exception,
4750 ExceptionPt *missing_pt)
4751 {
4752 size_t hash = exception->hash(missing_pt);
4753 debugPrint(debug_, "exception_merge", 3,
4754 "record merge hash %zu %s missing %s",
4755 hash,
4756 exception->asString(network_),
4757 missing_pt->asString(network_));
4758 ExceptionPathSet *set = exception_merge_hash_.findKey(hash);
4759 if (set == nullptr) {
4760 set = new ExceptionPathSet;
4761 exception_merge_hash_[hash] = set;
4762 }
4763 set->insert(exception);
4764 }
4765
4766 // Record a mapping from first pin/clock/instance's to a set of exceptions.
4767 // The first exception point is when the exception becomes active.
4768 // After it becomes active, its state changes as the other
4769 // exception points are traversed.
4770 void
recordExceptionFirstPts(ExceptionPath * exception)4771 Sdc::recordExceptionFirstPts(ExceptionPath *exception)
4772 {
4773 if (exception->from())
4774 recordExceptionFirstFrom(exception);
4775 else if (exception->thrus())
4776 recordExceptionFirstThru(exception);
4777 else if (exception->to())
4778 recordExceptionFirstTo(exception);
4779 }
4780
4781 void
recordExceptionFirstFrom(ExceptionPath * exception)4782 Sdc::recordExceptionFirstFrom(ExceptionPath *exception)
4783 {
4784 ExceptionFrom *from = exception->from();
4785 recordExceptionPins(exception, from->pins(), first_from_pin_exceptions_);
4786 recordExceptionInsts(exception, from->instances(),
4787 first_from_inst_exceptions_);
4788 recordExceptionClks(exception, from->clks(), first_from_clk_exceptions_);
4789 }
4790
4791 void
recordExceptionFirstThru(ExceptionPath * exception)4792 Sdc::recordExceptionFirstThru(ExceptionPath *exception)
4793 {
4794 ExceptionThru *thru = (*exception->thrus())[0];
4795 recordExceptionPins(exception, thru->pins(), first_thru_pin_exceptions_);
4796 recordExceptionInsts(exception, thru->instances(),
4797 first_thru_inst_exceptions_);
4798 recordExceptionEdges(exception, thru->edges(), first_thru_edge_exceptions_);
4799 ExceptionThruSeq::Iterator thru_iter(exception->thrus());
4800 while (thru_iter.hasNext()) {
4801 ExceptionThru *thru = thru_iter.next();
4802 recordExceptionNets(exception, thru->nets(), first_thru_net_exceptions_);
4803 }
4804 }
4805
4806 void
recordExceptionFirstTo(ExceptionPath * exception)4807 Sdc::recordExceptionFirstTo(ExceptionPath *exception)
4808 {
4809 ExceptionTo *to = exception->to();
4810 recordExceptionPins(exception, to->pins(), first_to_pin_exceptions_);
4811 recordExceptionInsts(exception, to->instances(), first_to_inst_exceptions_);
4812 recordExceptionClks(exception, to->clks(), first_to_clk_exceptions_);
4813 }
4814
4815 void
recordExceptionClks(ExceptionPath * exception,ClockSet * clks,ClockExceptionsMap * & exception_map)4816 Sdc::recordExceptionClks(ExceptionPath *exception,
4817 ClockSet *clks,
4818 ClockExceptionsMap *&exception_map)
4819 {
4820 ClockSet::Iterator clk_iter(clks);
4821 while (clk_iter.hasNext()) {
4822 Clock *clk = clk_iter.next();
4823 ExceptionPathSet *set = nullptr;
4824 if (exception_map == nullptr)
4825 exception_map = new ClockExceptionsMap;
4826 else
4827 set = exception_map->findKey(clk);
4828 if (set == nullptr) {
4829 set = new ExceptionPathSet;
4830 (*exception_map)[clk] = set;
4831 }
4832 set->insert(exception);
4833 }
4834 }
4835
4836 void
recordExceptionEdges(ExceptionPath * exception,EdgePinsSet * edges,EdgeExceptionsMap * & exception_map)4837 Sdc::recordExceptionEdges(ExceptionPath *exception,
4838 EdgePinsSet *edges,
4839 EdgeExceptionsMap *&exception_map)
4840 {
4841 EdgePinsSet::Iterator edge_iter(edges);
4842 while (edge_iter.hasNext()) {
4843 EdgePins *edge = edge_iter.next();
4844 ExceptionPathSet *set = nullptr;
4845 if (exception_map == nullptr)
4846 exception_map = new EdgeExceptionsMap;
4847 else
4848 set = exception_map->findKey(edge);
4849 if (set == nullptr) {
4850 set = new ExceptionPathSet;
4851 // Copy the EdgePins so it is owned by the map.
4852 edge = new EdgePins(*edge);
4853 exception_map->insert(edge, set);
4854 }
4855 set->insert(exception);
4856 }
4857 }
4858
4859 void
recordExceptionPins(ExceptionPath * exception,PinSet * pins,PinExceptionsMap * & exception_map)4860 Sdc::recordExceptionPins(ExceptionPath *exception,
4861 PinSet *pins,
4862 PinExceptionsMap *&exception_map)
4863 {
4864 PinSet::Iterator pin_iter(pins);
4865 while (pin_iter.hasNext()) {
4866 const Pin *pin = pin_iter.next();
4867 ExceptionPathSet *set = nullptr;
4868 if (exception_map == nullptr)
4869 exception_map = new PinExceptionsMap;
4870 else
4871 set = exception_map->findKey(pin);
4872 if (set == nullptr) {
4873 set = new ExceptionPathSet;
4874 exception_map->insert(pin, set);
4875 }
4876 set->insert(exception);
4877 }
4878 }
4879
4880 void
recordExceptionHpin(ExceptionPath * exception,Pin * pin,PinExceptionsMap * & exception_map)4881 Sdc::recordExceptionHpin(ExceptionPath *exception,
4882 Pin *pin,
4883 PinExceptionsMap *&exception_map)
4884 {
4885 ExceptionPathSet *set = nullptr;
4886 if (exception_map == nullptr)
4887 exception_map = new PinExceptionsMap;
4888 else
4889 set = exception_map->findKey(pin);
4890 if (set == nullptr) {
4891 set = new ExceptionPathSet;
4892 exception_map->insert(pin, set);
4893 }
4894 set->insert(exception);
4895 }
4896
4897 void
recordExceptionInsts(ExceptionPath * exception,InstanceSet * insts,InstanceExceptionsMap * & exception_map)4898 Sdc::recordExceptionInsts(ExceptionPath *exception,
4899 InstanceSet *insts,
4900 InstanceExceptionsMap *&exception_map)
4901 {
4902 InstanceSet::Iterator inst_iter(insts);
4903 while (inst_iter.hasNext()) {
4904 Instance *inst = inst_iter.next();
4905 ExceptionPathSet *set = nullptr;
4906 if (exception_map == nullptr)
4907 exception_map = new InstanceExceptionsMap;
4908 else
4909 set = exception_map->findKey(inst);
4910 if (set == nullptr) {
4911 set = new ExceptionPathSet;
4912 (*exception_map)[inst] = set;
4913 }
4914 set->insert(exception);
4915 }
4916 }
4917
4918 void
recordExceptionNets(ExceptionPath * exception,NetSet * nets,NetExceptionsMap * & exception_map)4919 Sdc::recordExceptionNets(ExceptionPath *exception,
4920 NetSet *nets,
4921 NetExceptionsMap *&exception_map)
4922 {
4923 NetSet::Iterator net_iter(nets);
4924 while (net_iter.hasNext()) {
4925 const Net *net = net_iter.next();
4926 ExceptionPathSet *set = nullptr;
4927 if (exception_map == nullptr)
4928 exception_map = new NetExceptionsMap;
4929 else
4930 set = exception_map->findKey(net);
4931 if (set == nullptr) {
4932 set = new ExceptionPathSet;
4933 (*exception_map)[net] = set;
4934 }
4935 set->insert(exception);
4936 }
4937 }
4938
4939 // Exceptions of the same type can be merged if they differ in exactly
4940 // one exception point (-from, -thru or -to).
4941 // For example, the following exceptions:
4942 // set_false_path -from {A B} -to C
4943 // set_false_path -from {A B} -to D
4944 // can be merged to form:
4945 // set_false_path -from {A B} -to {C D}
4946 //
4947 // A hash is generated for each exception missing one exception point
4948 // to find potential matches. If a match is found, the exceptions are
4949 // merged. Next we try to merge the surviving exception until we run
4950 // out of merges.
4951 void
mergeException(ExceptionPath * exception)4952 Sdc::mergeException(ExceptionPath *exception)
4953 {
4954 ExceptionPath *merged = findMergeMatch(exception);
4955 while (merged)
4956 merged = findMergeMatch(merged);
4957 }
4958
4959 // Return the merged result.
4960 ExceptionPath *
findMergeMatch(ExceptionPath * exception)4961 Sdc::findMergeMatch(ExceptionPath *exception)
4962 {
4963 bool first_pt = true;
4964 ExceptionPtIterator missing_pt_iter(exception);
4965 while (missing_pt_iter.hasNext()) {
4966 ExceptionPt *missing_pt = missing_pt_iter.next();
4967 size_t hash = exception->hash(missing_pt);
4968 ExceptionPathSet *matches = exception_merge_hash_.findKey(hash);
4969 if (matches) {
4970 ExceptionPathSet::Iterator match_iter(matches);
4971 while (match_iter.hasNext()) {
4972 ExceptionPath *match = match_iter.next();
4973 ExceptionPt *match_missing_pt;
4974 if (match != exception
4975 // Exceptions are not merged if their priorities are
4976 // different. This allows exceptions to be pruned during
4977 // search at the endpoint.
4978 && exception->mergeable(match)
4979 && match->mergeablePts(exception, missing_pt, match_missing_pt)) {
4980 debugPrint(debug_, "exception_merge", 1, "merge %s",
4981 exception->asString(network_));
4982 debugPrint(debug_, "exception_merge", 1, " with %s",
4983 match->asString(network_));
4984 // Unrecord the exception that is being merged away.
4985 unrecordException(exception);
4986 unrecordMergeHashes(match);
4987 missing_pt->mergeInto(match_missing_pt);
4988 recordMergeHashes(match);
4989 // First point maps only change if the exception point that
4990 // is being merged is the first exception point.
4991 if (first_pt)
4992 recordExceptionFirstPts(match);
4993 // Have to wait until after exception point merge to delete
4994 // the exception.
4995 delete exception;
4996 return match;
4997 }
4998 }
4999 }
5000 first_pt = false;
5001 }
5002 return nullptr;
5003 }
5004
5005 ////////////////////////////////////////////////////////////////
5006
5007 void
deleteExceptions()5008 Sdc::deleteExceptions()
5009 {
5010 ExceptionPathSet::Iterator except_iter(exceptions_);
5011 while (except_iter.hasNext()) {
5012 delete except_iter.next();
5013 }
5014 exceptions_.clear();
5015
5016 deleteExceptionMap(first_from_pin_exceptions_);
5017 deleteExceptionMap(first_from_clk_exceptions_);
5018 deleteExceptionMap(first_from_inst_exceptions_);
5019 deleteExceptionMap(first_to_pin_exceptions_);
5020 deleteExceptionMap(first_to_clk_exceptions_);
5021 deleteExceptionMap(first_to_inst_exceptions_);
5022 deleteExceptionMap(first_thru_pin_exceptions_);
5023 deleteExceptionMap(first_thru_inst_exceptions_);
5024 deleteExceptionMap(first_thru_net_exceptions_);
5025 deleteExceptionMap(first_thru_edge_exceptions_);
5026
5027 delete path_delay_internal_startpoints_;
5028 path_delay_internal_startpoints_ = nullptr;
5029
5030 delete path_delay_internal_endpoints_;
5031 path_delay_internal_endpoints_ = nullptr;
5032
5033 deleteExceptionPtHashMapSets(exception_merge_hash_);
5034 exception_merge_hash_.clear();
5035 have_thru_hpin_exceptions_ = false;
5036 }
5037
5038 void
deleteExceptionPtHashMapSets(ExceptionPathPtHash & map)5039 Sdc::deleteExceptionPtHashMapSets(ExceptionPathPtHash &map)
5040 {
5041 ExceptionPathPtHash::Iterator set_iter(map);
5042 while (set_iter.hasNext())
5043 delete set_iter.next();
5044 }
5045
5046 void
deleteExceptionMap(PinExceptionsMap * & exception_map)5047 Sdc::deleteExceptionMap(PinExceptionsMap *&exception_map)
5048 {
5049 PinExceptionsMap::Iterator set_iter(exception_map);
5050 while (set_iter.hasNext()) {
5051 const Pin *pin;
5052 ExceptionPathSet *set;
5053 set_iter.next(pin, set);
5054 delete set;
5055 }
5056 delete exception_map;
5057 exception_map = nullptr;
5058 }
5059
5060 void
deleteExceptionMap(InstanceExceptionsMap * & exception_map)5061 Sdc::deleteExceptionMap(InstanceExceptionsMap *&exception_map)
5062 {
5063 InstanceExceptionsMap::Iterator set_iter(exception_map);
5064 while (set_iter.hasNext()) {
5065 const Instance *inst;
5066 ExceptionPathSet *set;
5067 set_iter.next(inst, set);
5068 delete set;
5069 }
5070 delete exception_map;
5071 exception_map = nullptr;
5072 }
5073
5074 void
deleteExceptionMap(NetExceptionsMap * & exception_map)5075 Sdc::deleteExceptionMap(NetExceptionsMap *&exception_map)
5076 {
5077 NetExceptionsMap::Iterator set_iter(exception_map);
5078 while (set_iter.hasNext()) {
5079 const Net *net;
5080 ExceptionPathSet *set;
5081 set_iter.next(net, set);
5082 delete set;
5083 }
5084 delete exception_map;
5085 exception_map = nullptr;
5086 }
5087
5088 void
deleteExceptionMap(ClockExceptionsMap * & exception_map)5089 Sdc::deleteExceptionMap(ClockExceptionsMap *&exception_map)
5090 {
5091 ClockExceptionsMap::Iterator set_iter(exception_map);
5092 while (set_iter.hasNext()) {
5093 const Clock *clk;
5094 ExceptionPathSet *set;
5095 set_iter.next(clk, set);
5096 delete set;
5097 }
5098 delete exception_map;
5099 exception_map = nullptr;
5100 }
5101
5102 void
deleteExceptionMap(EdgeExceptionsMap * & exception_map)5103 Sdc::deleteExceptionMap(EdgeExceptionsMap *&exception_map)
5104 {
5105 EdgeExceptionsMap::Iterator set_iter(exception_map);
5106 while (set_iter.hasNext()) {
5107 const EdgePins *edge_pins;
5108 ExceptionPathSet *set;
5109 set_iter.next(edge_pins, set);
5110 delete set;
5111 delete edge_pins;
5112 }
5113 delete exception_map;
5114 exception_map = nullptr;
5115 }
5116
5117 ////////////////////////////////////////////////////////////////
5118
5119 void
deleteExceptionsReferencing(Clock * clk)5120 Sdc::deleteExceptionsReferencing(Clock *clk)
5121 {
5122 ExceptionPathSet::ConstIterator exception_iter(exceptions_);
5123 while (exception_iter.hasNext()) {
5124 ExceptionPath *exception = exception_iter.next();
5125 bool deleted = false;
5126 ExceptionFrom *from = exception->from();
5127 if (from) {
5128 ClockSet *clks = from->clks();
5129 if (clks && clks->hasKey(clk)) {
5130 unrecordException(exception);
5131 from->deleteClock(clk);
5132 if (from->hasObjects())
5133 recordException(exception);
5134 else {
5135 deleteException(exception);
5136 deleted = true;
5137 }
5138 }
5139 }
5140
5141 if (!deleted) {
5142 ExceptionTo *to = exception->to();
5143 if (to) {
5144 ClockSet *clks = to->clks();
5145 if (clks && clks->hasKey(clk)) {
5146 unrecordException(exception);
5147 to->deleteClock(clk);
5148 if (to->hasObjects())
5149 recordException(exception);
5150 else
5151 deleteException(exception);
5152 }
5153 }
5154 }
5155 }
5156 }
5157
5158 void
deleteException(ExceptionPath * exception)5159 Sdc::deleteException(ExceptionPath *exception)
5160 {
5161 debugPrint(debug_, "exception_merge", 2, "delete %s",
5162 exception->asString(network_));
5163 unrecordException(exception);
5164 delete exception;
5165 }
5166
5167 void
unrecordException(ExceptionPath * exception)5168 Sdc::unrecordException(ExceptionPath *exception)
5169 {
5170 unrecordMergeHashes(exception);
5171 unrecordExceptionFirstPts(exception);
5172 exceptions_.erase(exception);
5173 }
5174
5175 void
unrecordMergeHashes(ExceptionPath * exception)5176 Sdc::unrecordMergeHashes(ExceptionPath *exception)
5177 {
5178 ExceptionPtIterator missing_pt_iter(exception);
5179 while (missing_pt_iter.hasNext()) {
5180 ExceptionPt *missing_pt = missing_pt_iter.next();
5181 unrecordMergeHash(exception, missing_pt);
5182 }
5183 }
5184
5185 void
unrecordMergeHash(ExceptionPath * exception,ExceptionPt * missing_pt)5186 Sdc::unrecordMergeHash(ExceptionPath *exception,
5187 ExceptionPt *missing_pt)
5188 {
5189 size_t hash = exception->hash(missing_pt);
5190 debugPrint(debug_, "exception_merge", 3,
5191 "unrecord merge hash %zu %s missing %s",
5192 hash,
5193 exception->asString(network_),
5194 missing_pt->asString(network_));
5195 ExceptionPathSet *matches = exception_merge_hash_.findKey(hash);
5196 if (matches)
5197 matches->erase(exception);
5198 }
5199
5200 void
unrecordExceptionFirstPts(ExceptionPath * exception)5201 Sdc::unrecordExceptionFirstPts(ExceptionPath *exception)
5202 {
5203 ExceptionFrom *from = exception->from();
5204 ExceptionThruSeq *thrus = exception->thrus();
5205 ExceptionTo *to = exception->to();
5206 if (from) {
5207 unrecordExceptionPins(exception, from->pins(), first_from_pin_exceptions_);
5208 unrecordExceptionClks(exception, from->clks(), first_from_clk_exceptions_);
5209 unrecordExceptionInsts(exception, from->instances(),
5210 first_from_inst_exceptions_);
5211 }
5212 else if (thrus) {
5213 ExceptionThru *thru = (*thrus)[0];
5214 unrecordExceptionPins(exception, thru->pins(), first_thru_pin_exceptions_);
5215 unrecordExceptionInsts(exception, thru->instances(),
5216 first_thru_inst_exceptions_);
5217 unrecordExceptionNets(exception, thru->nets(), first_thru_net_exceptions_);
5218 unrecordExceptionEdges(exception, thru->edges(),
5219 first_thru_edge_exceptions_);
5220 }
5221 else if (to) {
5222 unrecordExceptionPins(exception, to->pins(), first_to_pin_exceptions_);
5223 unrecordExceptionClks(exception, to->clks(), first_to_clk_exceptions_);
5224 unrecordExceptionInsts(exception, to->instances(),
5225 first_to_inst_exceptions_);
5226 }
5227 }
5228
5229 void
unrecordExceptionClks(ExceptionPath * exception,ClockSet * clks,ClockExceptionsMap * exception_map)5230 Sdc::unrecordExceptionClks(ExceptionPath *exception,
5231 ClockSet *clks,
5232 ClockExceptionsMap *exception_map)
5233 {
5234 ClockSet::Iterator clk_iter(clks);
5235 while (clk_iter.hasNext()) {
5236 Clock *clk = clk_iter.next();
5237 ExceptionPathSet *set = exception_map->findKey(clk);
5238 if (set)
5239 set->erase(exception);
5240 }
5241 }
5242
5243 void
unrecordExceptionPins(ExceptionPath * exception,PinSet * pins,PinExceptionsMap * exception_map)5244 Sdc::unrecordExceptionPins(ExceptionPath *exception,
5245 PinSet *pins,
5246 PinExceptionsMap *exception_map)
5247 {
5248 PinSet::Iterator pin_iter(pins);
5249 while (pin_iter.hasNext()) {
5250 const Pin *pin = pin_iter.next();
5251 ExceptionPathSet *set = exception_map->findKey(pin);
5252 if (set)
5253 set->erase(exception);
5254 }
5255 }
5256
5257 void
unrecordExceptionInsts(ExceptionPath * exception,InstanceSet * insts,InstanceExceptionsMap * exception_map)5258 Sdc::unrecordExceptionInsts(ExceptionPath *exception,
5259 InstanceSet *insts,
5260 InstanceExceptionsMap *exception_map)
5261 {
5262 InstanceSet::Iterator inst_iter(insts);
5263 while (inst_iter.hasNext()) {
5264 Instance *inst = inst_iter.next();
5265 ExceptionPathSet *set = exception_map->findKey(inst);
5266 if (set)
5267 set->erase(exception);
5268 }
5269 }
5270
5271 void
unrecordExceptionEdges(ExceptionPath * exception,EdgePinsSet * edges,EdgeExceptionsMap * exception_map)5272 Sdc::unrecordExceptionEdges(ExceptionPath *exception,
5273 EdgePinsSet *edges,
5274 EdgeExceptionsMap *exception_map)
5275 {
5276 EdgePinsSet::Iterator edge_iter(edges);
5277 while (edge_iter.hasNext()) {
5278 EdgePins *edge = edge_iter.next();
5279 ExceptionPathSet *set = exception_map->findKey(edge);
5280 if (set)
5281 set->erase(exception);
5282 }
5283 }
5284
5285 void
unrecordExceptionNets(ExceptionPath * exception,NetSet * nets,NetExceptionsMap * exception_map)5286 Sdc::unrecordExceptionNets(ExceptionPath *exception,
5287 NetSet *nets,
5288 NetExceptionsMap *exception_map)
5289 {
5290 NetSet::Iterator net_iter(nets);
5291 while (net_iter.hasNext()) {
5292 const Net *net = net_iter.next();
5293 ExceptionPathSet *set = exception_map->findKey(net);
5294 if (set)
5295 set->erase(exception);
5296 }
5297 }
5298
5299 void
unrecordExceptionHpin(ExceptionPath * exception,Pin * pin,PinExceptionsMap * & exception_map)5300 Sdc::unrecordExceptionHpin(ExceptionPath *exception,
5301 Pin *pin,
5302 PinExceptionsMap *&exception_map)
5303 {
5304 ExceptionPathSet *set = exception_map->findKey(pin);
5305 if (set)
5306 set->erase(exception);
5307 }
5308
5309 ////////////////////////////////////////////////////////////////
5310
5311 class ExpandException : public ExpandedExceptionVisitor
5312 {
5313 public:
5314 ExpandException(ExceptionPath *exception,
5315 ExceptionPathSet &expansions,
5316 Network *network);
5317 virtual void visit(ExceptionFrom *from, ExceptionThruSeq *thrus,
5318 ExceptionTo *to);
5319
5320 private:
5321 ExceptionPathSet &expansions_;
5322
5323 private:
5324 DISALLOW_COPY_AND_ASSIGN(ExpandException);
5325 };
5326
ExpandException(ExceptionPath * exception,ExceptionPathSet & expansions,Network * network)5327 ExpandException::ExpandException(ExceptionPath *exception,
5328 ExceptionPathSet &expansions,
5329 Network *network) :
5330 ExpandedExceptionVisitor(exception, network),
5331 expansions_(expansions)
5332 {
5333 }
5334
5335 void
visit(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to)5336 ExpandException::visit(ExceptionFrom *from,
5337 ExceptionThruSeq *thrus,
5338 ExceptionTo *to)
5339 {
5340 ExceptionFrom *from_clone = nullptr;
5341 if (from)
5342 from_clone = from->clone();
5343 ExceptionThruSeq *thrus_clone = nullptr;
5344 if (thrus) {
5345 thrus_clone = new ExceptionThruSeq;
5346 ExceptionThruSeq::Iterator thru_iter(thrus);
5347 while (thru_iter.hasNext()) {
5348 ExceptionThru *thru = thru_iter.next();
5349 thrus_clone->push_back(thru->clone(network_));
5350 }
5351 }
5352 ExceptionTo *to_clone = nullptr;
5353 if (to)
5354 to_clone = to->clone();
5355 ExceptionPath *expand = exception_->clone(from_clone, thrus_clone,
5356 to_clone, true);
5357 expansions_.insert(expand);
5358 }
5359
5360 // Expand exception from/thrus/to sets so there is only one exception
5361 // point in each from/thru/to.
5362 void
expandException(ExceptionPath * exception,ExceptionPathSet & expansions)5363 Sdc::expandException(ExceptionPath *exception,
5364 ExceptionPathSet &expansions)
5365 {
5366 ExpandException expander(exception, expansions, network_);
5367 expander.visitExpansions();
5368 }
5369
5370 ////////////////////////////////////////////////////////////////
5371
5372 void
resetPath(ExceptionFrom * from,ExceptionThruSeq * thrus,ExceptionTo * to,const MinMaxAll * min_max)5373 Sdc::resetPath(ExceptionFrom *from,
5374 ExceptionThruSeq *thrus,
5375 ExceptionTo *to,
5376 const MinMaxAll *min_max)
5377 {
5378 checkFromThrusTo(from, thrus, to);
5379 ExceptionPathSet::Iterator except_iter(exceptions_);
5380 while (except_iter.hasNext()) {
5381 ExceptionPath *match = except_iter.next();
5382 if (match->resetMatch(from, thrus, to, min_max)) {
5383 debugPrint(debug_, "exception_match", 3, "reset match %s",
5384 match->asString(network_));
5385 ExceptionPathSet expansions;
5386 expandException(match, expansions);
5387 deleteException(match);
5388 ExceptionPathSet::Iterator expand_iter(expansions);
5389 while (expand_iter.hasNext()) {
5390 ExceptionPath *expand = expand_iter.next();
5391 if (expand->resetMatch(from, thrus, to, min_max)) {
5392 unrecordPathDelayInternalStartpoints(expand->from());
5393 unrecordPathDelayInternalEndpoints(expand);
5394 delete expand;
5395 }
5396 else
5397 addException(expand);
5398 }
5399 }
5400 }
5401 }
5402
5403 ////////////////////////////////////////////////////////////////
5404
5405 bool
exceptionFromStates(const Pin * pin,const RiseFall * rf,const Clock * clk,const RiseFall * clk_rf,const MinMax * min_max,ExceptionStateSet * & states) const5406 Sdc::exceptionFromStates(const Pin *pin,
5407 const RiseFall *rf,
5408 const Clock *clk,
5409 const RiseFall *clk_rf,
5410 const MinMax *min_max,
5411 ExceptionStateSet *&states) const
5412 {
5413 return exceptionFromStates(pin, rf, clk, clk_rf, min_max, true, states);
5414 }
5415
5416 bool
exceptionFromStates(const Pin * pin,const RiseFall * rf,const Clock * clk,const RiseFall * clk_rf,const MinMax * min_max,bool include_filter,ExceptionStateSet * & states) const5417 Sdc::exceptionFromStates(const Pin *pin,
5418 const RiseFall *rf,
5419 const Clock *clk,
5420 const RiseFall *clk_rf,
5421 const MinMax *min_max,
5422 bool include_filter,
5423 ExceptionStateSet *&states) const
5424 {
5425 bool srch_from = true;
5426 if (pin) {
5427 if (srch_from && first_from_pin_exceptions_)
5428 srch_from &= exceptionFromStates(first_from_pin_exceptions_->findKey(pin),
5429 nullptr, rf, min_max, include_filter,
5430 states);
5431 if (srch_from && first_thru_pin_exceptions_)
5432 srch_from &= exceptionFromStates(first_thru_pin_exceptions_->findKey(pin),
5433 nullptr, rf, min_max, include_filter,
5434 states);
5435
5436 if (srch_from
5437 && (first_from_inst_exceptions_ || first_thru_inst_exceptions_)) {
5438 Instance *inst = network_->instance(pin);
5439 if (srch_from && first_from_inst_exceptions_)
5440 srch_from &= exceptionFromStates(first_from_inst_exceptions_->findKey(inst),
5441 pin, rf, min_max, include_filter,
5442 states);
5443 if (srch_from && first_thru_inst_exceptions_)
5444 srch_from &= exceptionFromStates(first_thru_inst_exceptions_->findKey(inst),
5445 pin, rf, min_max, include_filter,
5446 states);
5447 }
5448 }
5449 if (srch_from && clk && first_from_clk_exceptions_)
5450 srch_from &= exceptionFromStates(first_from_clk_exceptions_->findKey(clk),
5451 pin, clk_rf, min_max, include_filter,
5452 states);
5453 if (!srch_from) {
5454 delete states;
5455 states = nullptr;
5456 }
5457 return srch_from;
5458 }
5459
5460 bool
exceptionFromStates(const ExceptionPathSet * exceptions,const Pin * pin,const RiseFall * rf,const MinMax * min_max,bool include_filter,ExceptionStateSet * & states) const5461 Sdc::exceptionFromStates(const ExceptionPathSet *exceptions,
5462 const Pin *pin,
5463 const RiseFall *rf,
5464 const MinMax *min_max,
5465 bool include_filter,
5466 ExceptionStateSet *&states) const
5467 {
5468 if (exceptions) {
5469 ExceptionPathSet::ConstIterator exception_iter(exceptions);
5470 while (exception_iter.hasNext()) {
5471 ExceptionPath *exception = exception_iter.next();
5472 if (exception->matches(min_max, false)
5473 && (exception->from() == nullptr
5474 || exception->from()->transition()->matches(rf))
5475 && (include_filter || !exception->isFilter())) {
5476 ExceptionState *state = exception->firstState();
5477 if (state->matchesNextThru(nullptr, pin, rf, min_max, network_))
5478 // -from clk -thru reg/clk
5479 state = state->nextState();
5480 // If the exception is -from and has no -to transition it is
5481 // complete out of the gate.
5482 if (state->isComplete()
5483 && exception->isFalse()) {
5484 // Leave the completed false path state as a marker on the tag,
5485 // but flush all other exception states because they are lower
5486 // priority.
5487 if (states == nullptr)
5488 states = new ExceptionStateSet;
5489 states->clear();
5490 states->insert(state);
5491 // No need to examine other exceptions from this
5492 // pin/clock/instance.
5493 return false;
5494 }
5495 if (states == nullptr)
5496 states = new ExceptionStateSet;
5497 states->insert(state);
5498 }
5499 }
5500 }
5501 return true;
5502 }
5503
5504 void
exceptionFromClkStates(const Pin * pin,const RiseFall * rf,const Clock * clk,const RiseFall * clk_rf,const MinMax * min_max,ExceptionStateSet * & states) const5505 Sdc::exceptionFromClkStates(const Pin *pin,
5506 const RiseFall *rf,
5507 const Clock *clk,
5508 const RiseFall *clk_rf,
5509 const MinMax *min_max,
5510 ExceptionStateSet *&states) const
5511 {
5512 if (pin) {
5513 if (first_from_pin_exceptions_)
5514 exceptionFromStates(first_from_pin_exceptions_->findKey(pin),
5515 nullptr, rf, min_max, true, states);
5516 if (first_from_inst_exceptions_) {
5517 Instance *inst = network_->instance(pin);
5518 exceptionFromStates(first_from_inst_exceptions_->findKey(inst),
5519 pin, rf, min_max, true, states);
5520 }
5521 }
5522 if (first_from_clk_exceptions_)
5523 exceptionFromStates(first_from_clk_exceptions_->findKey(clk),
5524 pin, clk_rf, min_max, true, states);
5525 }
5526
5527 void
filterRegQStates(const Pin * to_pin,const RiseFall * to_rf,const MinMax * min_max,ExceptionStateSet * & states) const5528 Sdc::filterRegQStates(const Pin *to_pin,
5529 const RiseFall *to_rf,
5530 const MinMax *min_max,
5531 ExceptionStateSet *&states) const
5532 {
5533 if (first_from_pin_exceptions_) {
5534 const ExceptionPathSet *exceptions =
5535 first_from_pin_exceptions_->findKey(to_pin);
5536 if (exceptions) {
5537 ExceptionPathSet::ConstIterator exception_iter(exceptions);
5538 while (exception_iter.hasNext()) {
5539 ExceptionPath *exception = exception_iter.next();
5540 // Hack for filter -from reg/Q.
5541 if (exception->isFilter()
5542 && exception->matchesFirstPt(to_rf, min_max)) {
5543 ExceptionState *state = exception->firstState();
5544 if (states == nullptr)
5545 states = new ExceptionStateSet;
5546 states->insert(state);
5547 }
5548 }
5549 }
5550 }
5551 }
5552
5553 void
exceptionThruStates(const Pin * from_pin,const Pin * to_pin,const RiseFall * to_rf,const MinMax * min_max,ExceptionStateSet * & states) const5554 Sdc::exceptionThruStates(const Pin *from_pin,
5555 const Pin *to_pin,
5556 const RiseFall *to_rf,
5557 const MinMax *min_max,
5558 ExceptionStateSet *&states) const
5559 {
5560 if (first_thru_pin_exceptions_)
5561 exceptionThruStates(first_thru_pin_exceptions_->findKey(to_pin),
5562 to_rf, min_max, states);
5563 if (first_thru_edge_exceptions_) {
5564 EdgePins edge_pins(const_cast<Pin*>(from_pin), const_cast<Pin*>(to_pin));
5565 exceptionThruStates(first_thru_edge_exceptions_->findKey(&edge_pins),
5566 to_rf, min_max, states);
5567 }
5568 if (first_thru_inst_exceptions_
5569 && (network_->direction(to_pin)->isAnyOutput()
5570 || network_->isLatchData(to_pin))) {
5571 const Instance *to_inst = network_->instance(to_pin);
5572 exceptionThruStates(first_thru_inst_exceptions_->findKey(to_inst),
5573 to_rf, min_max, states);
5574 }
5575 }
5576
5577 void
exceptionThruStates(const ExceptionPathSet * exceptions,const RiseFall * to_rf,const MinMax * min_max,ExceptionStateSet * & states) const5578 Sdc::exceptionThruStates(const ExceptionPathSet *exceptions,
5579 const RiseFall *to_rf,
5580 const MinMax *min_max,
5581 // Return value.
5582 ExceptionStateSet *&states) const
5583 {
5584 if (exceptions) {
5585 ExceptionPathSet::ConstIterator exception_iter(exceptions);
5586 while (exception_iter.hasNext()) {
5587 ExceptionPath *exception = exception_iter.next();
5588 if (exception->matchesFirstPt(to_rf, min_max)) {
5589 ExceptionState *state = exception->firstState();
5590 if (states == nullptr)
5591 states = new ExceptionStateSet;
5592 states->insert(state);
5593 }
5594 }
5595 }
5596 }
5597
5598 void
exceptionTo(ExceptionPathType type,const Pin * pin,const RiseFall * rf,const ClockEdge * clk_edge,const MinMax * min_max,bool match_min_max_exactly,ExceptionPath * & hi_priority_exception,int & hi_priority) const5599 Sdc::exceptionTo(ExceptionPathType type,
5600 const Pin *pin,
5601 const RiseFall *rf,
5602 const ClockEdge *clk_edge,
5603 const MinMax *min_max,
5604 bool match_min_max_exactly,
5605 // Return values.
5606 ExceptionPath *&hi_priority_exception,
5607 int &hi_priority) const
5608 {
5609 if (first_to_inst_exceptions_) {
5610 Instance *inst = network_->instance(pin);
5611 exceptionTo(first_to_inst_exceptions_->findKey(inst), type, pin, rf,
5612 clk_edge, min_max, match_min_max_exactly,
5613 hi_priority_exception, hi_priority);
5614 }
5615 if (first_to_pin_exceptions_)
5616 exceptionTo(first_to_pin_exceptions_->findKey(pin), type, pin, rf,
5617 clk_edge, min_max, match_min_max_exactly,
5618 hi_priority_exception, hi_priority);
5619 if (clk_edge && first_to_clk_exceptions_)
5620 exceptionTo(first_to_clk_exceptions_->findKey(clk_edge->clock()),
5621 type, pin, rf, clk_edge, min_max, match_min_max_exactly,
5622 hi_priority_exception, hi_priority);
5623 }
5624
5625 void
exceptionTo(const ExceptionPathSet * to_exceptions,ExceptionPathType type,const Pin * pin,const RiseFall * rf,const ClockEdge * clk_edge,const MinMax * min_max,bool match_min_max_exactly,ExceptionPath * & hi_priority_exception,int & hi_priority) const5626 Sdc::exceptionTo(const ExceptionPathSet *to_exceptions,
5627 ExceptionPathType type,
5628 const Pin *pin,
5629 const RiseFall *rf,
5630 const ClockEdge *clk_edge,
5631 const MinMax *min_max,
5632 bool match_min_max_exactly,
5633 // Return values.
5634 ExceptionPath *&hi_priority_exception,
5635 int &hi_priority) const
5636 {
5637 if (to_exceptions) {
5638 ExceptionPathSet::ConstIterator exception_iter(to_exceptions);
5639 while (exception_iter.hasNext()) {
5640 ExceptionPath *exception = exception_iter.next();
5641 exceptionTo(exception, type, pin, rf, clk_edge,
5642 min_max, match_min_max_exactly,
5643 hi_priority_exception, hi_priority);
5644 }
5645 }
5646 }
5647
5648 void
exceptionTo(ExceptionPath * exception,ExceptionPathType type,const Pin * pin,const RiseFall * rf,const ClockEdge * clk_edge,const MinMax * min_max,bool match_min_max_exactly,ExceptionPath * & hi_priority_exception,int & hi_priority) const5649 Sdc::exceptionTo(ExceptionPath *exception,
5650 ExceptionPathType type,
5651 const Pin *pin,
5652 const RiseFall *rf,
5653 const ClockEdge *clk_edge,
5654 const MinMax *min_max,
5655 bool match_min_max_exactly,
5656 // Return values.
5657 ExceptionPath *&hi_priority_exception,
5658 int &hi_priority) const
5659 {
5660 if ((type == ExceptionPathType::any
5661 || exception->type() == type)
5662 && exceptionMatchesTo(exception, pin, rf, clk_edge, min_max,
5663 match_min_max_exactly, false)) {
5664 int priority = exception->priority(min_max);
5665 if (hi_priority_exception == nullptr
5666 || priority > hi_priority
5667 || (priority == hi_priority
5668 && exception->tighterThan(hi_priority_exception))) {
5669 hi_priority = priority;
5670 hi_priority_exception = exception;
5671 }
5672 }
5673 }
5674
5675 bool
exceptionMatchesTo(ExceptionPath * exception,const Pin * pin,const RiseFall * rf,const ClockEdge * clk_edge,const MinMax * min_max,bool match_min_max_exactly,bool require_to_pin) const5676 Sdc::exceptionMatchesTo(ExceptionPath *exception,
5677 const Pin *pin,
5678 const RiseFall *rf,
5679 const ClockEdge *clk_edge,
5680 const MinMax *min_max,
5681 bool match_min_max_exactly,
5682 bool require_to_pin) const
5683 {
5684 ExceptionTo *to = exception->to();
5685 return exception->matches(min_max, match_min_max_exactly)
5686 && ((to == nullptr
5687 && !require_to_pin)
5688 || (to
5689 && to->matches(pin, clk_edge, rf, network_)));
5690 }
5691
5692 bool
isCompleteTo(ExceptionState * state,const Pin * pin,const RiseFall * rf,const ClockEdge * clk_edge,const MinMax * min_max,bool match_min_max_exactly,bool require_to_pin) const5693 Sdc::isCompleteTo(ExceptionState *state,
5694 const Pin *pin,
5695 const RiseFall *rf,
5696 const ClockEdge *clk_edge,
5697 const MinMax *min_max,
5698 bool match_min_max_exactly,
5699 bool require_to_pin) const
5700 {
5701 return state->nextThru() == nullptr
5702 && exceptionMatchesTo(state->exception(), pin, rf, clk_edge,
5703 min_max, match_min_max_exactly, require_to_pin);
5704 }
5705
5706 ////////////////////////////////////////////////////////////////
5707
5708 Wireload *
wireloadDefaulted(const MinMax * min_max)5709 Sdc::wireloadDefaulted(const MinMax *min_max)
5710 {
5711 Wireload *wireload1 = wireload(min_max);
5712 if (wireload1 == nullptr) {
5713 LibertyLibrary *default_lib = network_->defaultLibertyLibrary();
5714 if (default_lib)
5715 wireload1 = default_lib->defaultWireload();
5716 }
5717 return wireload1;
5718 }
5719
5720 Wireload *
wireload(const MinMax * min_max)5721 Sdc::wireload(const MinMax *min_max)
5722 {
5723 return wireload_[min_max->index()];
5724 }
5725
5726 void
setWireload(Wireload * wireload,const MinMaxAll * min_max)5727 Sdc::setWireload(Wireload *wireload,
5728 const MinMaxAll *min_max)
5729 {
5730 for (auto mm_index : min_max->rangeIndex())
5731 wireload_[mm_index] = wireload;
5732 }
5733
5734 void
setWireloadMode(WireloadMode mode)5735 Sdc::setWireloadMode(WireloadMode mode)
5736 {
5737 wireload_mode_ = mode;
5738 }
5739
5740 WireloadMode
wireloadMode()5741 Sdc::wireloadMode()
5742 {
5743 return wireload_mode_;
5744 }
5745
5746 const WireloadSelection *
wireloadSelection(const MinMax * min_max)5747 Sdc::wireloadSelection(const MinMax *min_max)
5748 {
5749 const WireloadSelection *sel = wireload_selection_[min_max->index()];
5750 if (sel == nullptr) {
5751 // Look for a default.
5752 LibertyLibrary *lib = network_->defaultLibertyLibrary();
5753 if (lib) {
5754 WireloadSelection *default_sel = lib->defaultWireloadSelection();
5755 if (default_sel) {
5756 sel = default_sel;
5757 setWireloadSelection(default_sel, MinMaxAll::all());
5758 }
5759 }
5760 }
5761 return sel;
5762 }
5763
5764 void
setWireloadSelection(WireloadSelection * selection,const MinMaxAll * min_max)5765 Sdc::setWireloadSelection(WireloadSelection *selection,
5766 const MinMaxAll *min_max)
5767 {
5768 for (auto mm_index : min_max->rangeIndex())
5769 wireload_selection_[mm_index] = selection;
5770 }
5771
5772 ////////////////////////////////////////////////////////////////
5773
5774 bool
crprEnabled() const5775 Sdc::crprEnabled() const
5776 {
5777 return crpr_enabled_;
5778 }
5779
5780 void
setCrprEnabled(bool enabled)5781 Sdc::setCrprEnabled(bool enabled)
5782 {
5783 crpr_enabled_ = enabled;
5784 }
5785
5786 CrprMode
crprMode() const5787 Sdc::crprMode() const
5788 {
5789 return crpr_mode_;
5790 }
5791
5792 void
setCrprMode(CrprMode mode)5793 Sdc::setCrprMode(CrprMode mode)
5794 {
5795 crpr_mode_ = mode;
5796 }
5797
5798 bool
crprActive() const5799 Sdc::crprActive() const
5800 {
5801 return analysis_type_ == AnalysisType::ocv
5802 && crpr_enabled_;
5803 }
5804
5805 bool
propagateGatedClockEnable() const5806 Sdc::propagateGatedClockEnable() const
5807 {
5808 return propagate_gated_clock_enable_;
5809 }
5810
5811 void
setPropagateGatedClockEnable(bool enable)5812 Sdc::setPropagateGatedClockEnable(bool enable)
5813 {
5814 propagate_gated_clock_enable_ = enable;
5815 }
5816
5817 bool
presetClrArcsEnabled() const5818 Sdc::presetClrArcsEnabled() const
5819 {
5820 return preset_clr_arcs_enabled_;
5821 }
5822
5823 void
setPresetClrArcsEnabled(bool enable)5824 Sdc::setPresetClrArcsEnabled(bool enable)
5825 {
5826 preset_clr_arcs_enabled_ = enable;
5827 }
5828
5829 bool
condDefaultArcsEnabled() const5830 Sdc::condDefaultArcsEnabled() const
5831 {
5832 return cond_default_arcs_enabled_;
5833 }
5834
5835 void
setCondDefaultArcsEnabled(bool enabled)5836 Sdc::setCondDefaultArcsEnabled(bool enabled)
5837 {
5838 cond_default_arcs_enabled_ = enabled;
5839 }
5840
5841 bool
isDisabledCondDefault(Edge * edge) const5842 Sdc::isDisabledCondDefault(Edge *edge) const
5843 {
5844 return !cond_default_arcs_enabled_
5845 && edge->timingArcSet()->isCondDefault();
5846 }
5847
5848 bool
bidirectInstPathsEnabled() const5849 Sdc::bidirectInstPathsEnabled() const
5850 {
5851 return bidirect_inst_paths_enabled_;
5852 }
5853
5854 void
setBidirectInstPathsEnabled(bool enabled)5855 Sdc::setBidirectInstPathsEnabled(bool enabled)
5856 {
5857 bidirect_inst_paths_enabled_ = enabled;
5858 }
5859
5860 // Delay calculation propagates slews from a bidirect driver
5861 // to the bidirect port and back through the bidirect driver when
5862 // sta_bidirect_inst_paths_enabled_ is true.
5863 bool
bidirectDrvrSlewFromLoad(const Pin * pin) const5864 Sdc::bidirectDrvrSlewFromLoad(const Pin *pin) const
5865 {
5866 return bidirect_inst_paths_enabled_
5867 && network_->direction(pin)->isBidirect()
5868 && network_->isTopLevelPort(pin);
5869 }
5870
5871 bool
bidirectNetPathsEnabled() const5872 Sdc::bidirectNetPathsEnabled() const
5873 {
5874 return bidirect_inst_paths_enabled_;
5875 }
5876
5877 void
setBidirectNetPathsEnabled(bool enabled)5878 Sdc::setBidirectNetPathsEnabled(bool enabled)
5879 {
5880 bidirect_inst_paths_enabled_ = enabled;
5881 }
5882
5883 bool
recoveryRemovalChecksEnabled() const5884 Sdc::recoveryRemovalChecksEnabled() const
5885 {
5886 return recovery_removal_checks_enabled_;
5887 }
5888
5889 void
setRecoveryRemovalChecksEnabled(bool enabled)5890 Sdc::setRecoveryRemovalChecksEnabled(bool enabled)
5891 {
5892 recovery_removal_checks_enabled_ = enabled;
5893 }
5894
5895 bool
gatedClkChecksEnabled() const5896 Sdc::gatedClkChecksEnabled() const
5897 {
5898 return gated_clk_checks_enabled_;
5899 }
5900
5901 void
setGatedClkChecksEnabled(bool enabled)5902 Sdc::setGatedClkChecksEnabled(bool enabled)
5903 {
5904 gated_clk_checks_enabled_ = enabled;
5905 }
5906
5907 bool
dynamicLoopBreaking() const5908 Sdc::dynamicLoopBreaking() const
5909 {
5910 return dynamic_loop_breaking_;
5911 }
5912
5913 void
setDynamicLoopBreaking(bool enable)5914 Sdc::setDynamicLoopBreaking(bool enable)
5915 {
5916 if (dynamic_loop_breaking_ != enable) {
5917 if (levelize_->levelized()) {
5918 if (enable)
5919 makeLoopExceptions();
5920 else
5921 deleteLoopExceptions();
5922 }
5923 dynamic_loop_breaking_ = enable;
5924 }
5925 }
5926
5927 bool
propagateAllClocks() const5928 Sdc::propagateAllClocks() const
5929 {
5930 return propagate_all_clks_;
5931 }
5932
5933 void
setPropagateAllClocks(bool prop)5934 Sdc::setPropagateAllClocks(bool prop)
5935 {
5936 propagate_all_clks_ = prop;
5937 }
5938
5939 bool
clkThruTristateEnabled() const5940 Sdc::clkThruTristateEnabled() const
5941 {
5942 return clk_thru_tristate_enabled_;
5943 }
5944
5945 void
setClkThruTristateEnabled(bool enable)5946 Sdc::setClkThruTristateEnabled(bool enable)
5947 {
5948 clk_thru_tristate_enabled_ = enable;
5949 }
5950
5951 ClockEdge *
defaultArrivalClockEdge() const5952 Sdc::defaultArrivalClockEdge() const
5953 {
5954 return default_arrival_clk_->edge(RiseFall::rise());
5955 }
5956
5957 bool
useDefaultArrivalClock()5958 Sdc::useDefaultArrivalClock()
5959 {
5960 return use_default_arrival_clock_;
5961 }
5962
5963 void
setUseDefaultArrivalClock(bool enable)5964 Sdc::setUseDefaultArrivalClock(bool enable)
5965 {
5966 use_default_arrival_clock_ = enable;
5967 }
5968
5969 ////////////////////////////////////////////////////////////////
5970
5971 void
connectPinAfter(Pin * pin)5972 Sdc::connectPinAfter(Pin *pin)
5973 {
5974 if (have_thru_hpin_exceptions_) {
5975 PinSet *drvrs = network_->drivers(pin);
5976 ExceptionPathSet::Iterator except_iter(exceptions_);
5977 while (except_iter.hasNext()) {
5978 ExceptionPath *exception = except_iter.next();
5979 ExceptionPt *first_pt = exception->firstPt();
5980 ExceptionThruSeq::Iterator thru_iter(exception->thrus());
5981 while (thru_iter.hasNext()) {
5982 ExceptionThru *thru = thru_iter.next();
5983 if (thru->edges()) {
5984 thru->connectPinAfter(drvrs, network_);
5985 if (first_pt == thru)
5986 recordExceptionEdges(exception, thru->edges(),
5987 first_thru_edge_exceptions_);
5988 }
5989 }
5990 }
5991 }
5992 }
5993
5994 void
disconnectPinBefore(Pin * pin)5995 Sdc::disconnectPinBefore(Pin *pin)
5996 {
5997 if (have_thru_hpin_exceptions_) {
5998 ExceptionPathSet::Iterator except_iter(exceptions_);
5999 while (except_iter.hasNext()) {
6000 ExceptionPath *exception = except_iter.next();
6001 ExceptionPt *first_pt = exception->firstPt();
6002 ExceptionThruSeq::Iterator thru_iter(exception->thrus());
6003 while (thru_iter.hasNext()) {
6004 ExceptionThru *thru = thru_iter.next();
6005 if (thru->edges()) {
6006 thru->disconnectPinBefore(pin, network_);
6007 if (thru == first_pt)
6008 recordExceptionEdges(exception, thru->edges(),
6009 first_thru_edge_exceptions_);
6010 }
6011 }
6012 }
6013 }
6014 }
6015
6016 void
clkHpinDisablesChanged(Pin * pin)6017 Sdc::clkHpinDisablesChanged(Pin *pin)
6018 {
6019 if (isLeafPinClock(pin))
6020 clkHpinDisablesInvalid();
6021 }
6022
6023 ////////////////////////////////////////////////////////////////
6024
6025 // Find the leaf load pins corresponding to pin.
6026 // If the pin is hierarchical, the leaf pins are:
6027 // hierarchical input - load pins inside the hierarchical instance
6028 // hierarchical output - load pins outside the hierarchical instance
6029 void
findLeafLoadPins(Pin * pin,const Network * network,PinSet * leaf_pins)6030 findLeafLoadPins(Pin *pin,
6031 const Network *network,
6032 PinSet *leaf_pins)
6033 {
6034 if (network->isHierarchical(pin)) {
6035 PortDirection *dir = network->direction(pin);
6036 bool is_input = dir->isAnyInput();
6037 bool is_output = dir->isAnyOutput();
6038 const Instance *hinst = network->instance(pin);
6039 PinConnectedPinIterator *pin_iter = network->connectedPinIterator(pin);
6040 while (pin_iter->hasNext()) {
6041 Pin *pin1 = pin_iter->next();
6042 bool is_inside = network->isInside(pin1, hinst);
6043 if (((is_input && is_inside)
6044 || (is_output && !is_inside))
6045 && network->isLoad(pin1))
6046 leaf_pins->insert(pin1);
6047 }
6048 delete pin_iter;
6049 }
6050 else
6051 leaf_pins->insert(pin);
6052 }
6053
6054 // Find the leaf driver pins corresponding to pin.
6055 // If the pin is hierarchical, the leaf pins are:
6056 // hierarchical input - driver pins outside the hierarchical instance
6057 // hierarchical output - driver pins inside the hierarchical instance
6058 void
findLeafDriverPins(Pin * pin,const Network * network,PinSet * leaf_pins)6059 findLeafDriverPins(Pin *pin,
6060 const Network *network,
6061 PinSet *leaf_pins)
6062 {
6063 if (network->isHierarchical(pin)) {
6064 PortDirection *dir = network->direction(pin);
6065 bool is_input = dir->isAnyInput();
6066 bool is_output = dir->isAnyOutput();
6067 const Instance *hinst = network->instance(pin);
6068 PinConnectedPinIterator *pin_iter = network->connectedPinIterator(pin);
6069 while (pin_iter->hasNext()) {
6070 Pin *pin1 = pin_iter->next();
6071 bool is_inside = network->isInside(pin1, hinst);
6072 if (((is_input && !is_inside)
6073 || (is_output && is_inside))
6074 && network->isDriver(pin1))
6075 leaf_pins->insert(pin1);
6076 }
6077 delete pin_iter;
6078 }
6079 else
6080 leaf_pins->insert(pin);
6081 }
6082
6083 ////////////////////////////////////////////////////////////////
6084
ClockIterator(Sdc * sdc)6085 ClockIterator::ClockIterator(Sdc *sdc) :
6086 ClockSeq::Iterator(sdc->clocks())
6087 {
6088 }
6089
ClockIterator(ClockSeq & clocks)6090 ClockIterator::ClockIterator(ClockSeq &clocks) :
6091 ClockSeq::Iterator(clocks)
6092 {
6093 }
6094
6095 ////////////////////////////////////////////////////////////////
6096
ClockGroupIterator(Sdc * sdc)6097 ClockGroupIterator::ClockGroupIterator(Sdc *sdc) :
6098 ClockGroupsNameMap::Iterator(sdc->clk_groups_name_map_)
6099 {
6100 }
6101
ClockGroupIterator(ClockGroupsNameMap & clk_groups_name_map)6102 ClockGroupIterator::ClockGroupIterator(ClockGroupsNameMap &clk_groups_name_map) :
6103 ClockGroupsNameMap::Iterator(clk_groups_name_map)
6104 {
6105 }
6106
6107 ////////////////////////////////////////////////////////////////
6108
GroupPathIterator(Sdc * sdc)6109 GroupPathIterator::GroupPathIterator(Sdc *sdc) :
6110 GroupPathIterator(sdc->group_path_map_)
6111 {
6112 }
6113
GroupPathIterator(GroupPathMap & group_path_map)6114 GroupPathIterator::GroupPathIterator(GroupPathMap &group_path_map) :
6115 GroupPathMap::Iterator(group_path_map)
6116 {
6117 }
6118
6119 } // namespace
6120