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