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 "ConcreteParasitics.hh"
18
19 #include <limits>
20 #include <algorithm> // max
21
22 #include "Report.hh"
23 #include "Debug.hh"
24 #include "Error.hh"
25 #include "Mutex.hh"
26 #include "Set.hh"
27 #include "MinMax.hh"
28 #include "Network.hh"
29 #include "Wireload.hh"
30 #include "Liberty.hh"
31 #include "Sdc.hh"
32 #include "Parasitics.hh"
33 #include "ReduceParasitics.hh"
34 #include "MakeConcreteParasitics.hh"
35 #include "Parasitics.hh"
36 #include "ConcreteParasiticsPvt.hh"
37 #include "Corner.hh"
38
39 // Multiple inheritance is used to share elmore and pi model base
40 // classes, but care is taken to make sure there are no loops in the
41 // inheritance graph (ConcreteParasitic only included once).
42
43 namespace sta {
44
45 using std::max;
46
~ConcreteParasitic()47 ConcreteParasitic::~ConcreteParasitic()
48 {
49 }
50
51 bool
isPiElmore() const52 ConcreteParasitic::isPiElmore() const
53 {
54 return false;
55 }
56
57 bool
isPiModel() const58 ConcreteParasitic::isPiModel() const
59 {
60 return false;
61 }
62
63 bool
isPiPoleResidue() const64 ConcreteParasitic::isPiPoleResidue() const
65 {
66 return false;
67 }
68
69 bool
isPoleResidue() const70 ConcreteParasitic::isPoleResidue() const
71 {
72 return false;
73 }
74
75 bool
isParasiticNetwork() const76 ConcreteParasitic::isParasiticNetwork() const
77 {
78 return false;
79 }
80
81 void
piModel(float &,float &,float &) const82 ConcreteParasitic::piModel(float &,
83 float &,
84 float &) const
85 {
86 }
87
88 void
setPiModel(float,float,float)89 ConcreteParasitic::setPiModel(float,
90 float,
91 float)
92 {
93 }
94
95 bool
isReducedParasiticNetwork() const96 ConcreteParasitic::isReducedParasiticNetwork() const
97 {
98 return false;
99 }
100
101 void
setIsReduced(bool)102 ConcreteParasitic::setIsReduced(bool)
103 {
104 }
105
106 void
findElmore(const Pin *,float &,bool & exists) const107 ConcreteParasitic::findElmore(const Pin *,
108 float &,
109 bool &exists) const
110 {
111 exists = false;
112 }
113
114 void
setElmore(const Pin *,float)115 ConcreteParasitic::setElmore(const Pin *,
116 float)
117 {
118 }
119
120 Parasitic *
findPoleResidue(const Pin *) const121 ConcreteParasitic::findPoleResidue(const Pin *) const
122 {
123 return nullptr;
124 }
125
126 void
setPoleResidue(const Pin *,ComplexFloatSeq *,ComplexFloatSeq *)127 ConcreteParasitic::setPoleResidue(const Pin *,
128 ComplexFloatSeq *,
129 ComplexFloatSeq *)
130 {
131 }
132
133 ParasiticDeviceIterator *
deviceIterator()134 ConcreteParasitic::deviceIterator()
135 {
136 return nullptr;
137 }
138
139 ParasiticNodeIterator *
nodeIterator()140 ConcreteParasitic::nodeIterator()
141 {
142 return nullptr;
143 }
144
145 ////////////////////////////////////////////////////////////////
146
ConcreteElmore()147 ConcreteElmore::ConcreteElmore() :
148 loads_(nullptr)
149 {
150 }
151
~ConcreteElmore()152 ConcreteElmore::~ConcreteElmore()
153 {
154 delete loads_;
155 }
156
157 void
findElmore(const Pin * load_pin,float & elmore,bool & exists) const158 ConcreteElmore::findElmore(const Pin *load_pin,
159 float &elmore,
160 bool &exists) const
161 {
162 if (loads_)
163 loads_->findKey(load_pin, elmore, exists);
164 else
165 exists = false;
166 }
167
168 void
deleteLoad(const Pin * load_pin)169 ConcreteElmore::deleteLoad(const Pin *load_pin)
170 {
171 loads_->erase(load_pin);
172 }
173
174 void
setElmore(const Pin * load_pin,float elmore)175 ConcreteElmore::setElmore(const Pin *load_pin,
176 float elmore)
177 {
178 if (loads_ == nullptr)
179 loads_ = new ConcreteElmoreLoadMap;
180 (*loads_)[load_pin] = elmore;
181 }
182
183 ////////////////////////////////////////////////////////////////
184
ConcretePi(float c2,float rpi,float c1)185 ConcretePi::ConcretePi(float c2,
186 float rpi,
187 float c1) :
188 c2_(c2),
189 rpi_(rpi),
190 c1_(c1),
191 is_reduced_(false)
192 {
193 }
194
195 float
capacitance() const196 ConcretePi::capacitance() const
197 {
198 return c1_ + c2_;
199 }
200
201 void
setPiModel(float c2,float rpi,float c1)202 ConcretePi::setPiModel(float c2,
203 float rpi,
204 float c1)
205 {
206 c2_ = c2;
207 rpi_ = rpi;
208 c1_ = c1;
209 }
210
211 void
piModel(float & c2,float & rpi,float & c1) const212 ConcretePi::piModel(float &c2,
213 float &rpi,
214 float &c1) const
215 {
216 c2 = c2_;
217 rpi = rpi_;
218 c1 = c1_;
219 }
220
221 void
setIsReduced(bool reduced)222 ConcretePi::setIsReduced(bool reduced)
223 {
224 is_reduced_ = reduced;
225 }
226
227 ////////////////////////////////////////////////////////////////
228
ConcretePiElmore(float c2,float rpi,float c1)229 ConcretePiElmore::ConcretePiElmore(float c2,
230 float rpi,
231 float c1) :
232 ConcretePi(c2, rpi, c1),
233 ConcreteElmore()
234 {
235 }
236
237 float
capacitance() const238 ConcretePiElmore::capacitance() const
239 {
240 return ConcretePi::capacitance();
241 }
242
243 void
piModel(float & c2,float & rpi,float & c1) const244 ConcretePiElmore::piModel(float &c2,
245 float &rpi,
246 float &c1) const
247 {
248 ConcretePi::piModel(c2, rpi, c1);
249 }
250
251 void
setPiModel(float c2,float rpi,float c1)252 ConcretePiElmore::setPiModel(float c2,
253 float rpi,
254 float c1)
255 {
256 ConcretePi::setPiModel(c2, rpi, c1);
257 }
258
259 bool
isReducedParasiticNetwork() const260 ConcretePiElmore::isReducedParasiticNetwork() const
261 {
262 return ConcretePi::isReducedParasiticNetwork();
263 }
264
265 void
setIsReduced(bool reduced)266 ConcretePiElmore::setIsReduced(bool reduced)
267 {
268 ConcretePi::setIsReduced(reduced);
269 }
270
271 void
findElmore(const Pin * load_pin,float & elmore,bool & exists) const272 ConcretePiElmore::findElmore(const Pin *load_pin,
273 float &elmore,
274 bool &exists) const
275 {
276 ConcreteElmore::findElmore(load_pin, elmore, exists);
277 }
278
279 void
setElmore(const Pin * load_pin,float elmore)280 ConcretePiElmore::setElmore(const Pin *load_pin,
281 float elmore)
282 {
283 ConcreteElmore::setElmore(load_pin, elmore);
284 }
285
286 ////////////////////////////////////////////////////////////////
287
ConcretePiElmoreEstimated(float c2,float rpi,float c1,float elmore_res,float elmore_cap,bool elmore_use_load_cap,const RiseFall * rf,const OperatingConditions * op,const Corner * corner,const MinMax * min_max,Sdc * sdc)288 ConcretePiElmoreEstimated::ConcretePiElmoreEstimated(float c2,
289 float rpi,
290 float c1,
291 float elmore_res,
292 float elmore_cap,
293 bool elmore_use_load_cap,
294 const RiseFall *rf,
295 const OperatingConditions *op,
296 const Corner *corner,
297 const MinMax *min_max,
298 Sdc *sdc):
299 ConcretePi(c2, rpi, c1),
300 elmore_res_(elmore_res),
301 elmore_cap_(elmore_cap),
302 elmore_use_load_cap_(elmore_use_load_cap),
303 rf_(rf),
304 op_cond_(op),
305 corner_(corner),
306 min_max_(min_max),
307 sdc_(sdc)
308 {
309 }
310
311 float
capacitance() const312 ConcretePiElmoreEstimated::capacitance() const
313 {
314 return ConcretePi::capacitance();
315 }
316
317 void
piModel(float & c2,float & rpi,float & c1) const318 ConcretePiElmoreEstimated::piModel(float &c2,
319 float &rpi,
320 float &c1) const
321 {
322 ConcretePi::piModel(c2, rpi, c1);
323 }
324
325 void
findElmore(const Pin * load_pin,float & elmore,bool & exists) const326 ConcretePiElmoreEstimated::findElmore(const Pin *load_pin,
327 float &elmore,
328 bool &exists) const
329 {
330 float load_cap = 0.0;
331 if (elmore_use_load_cap_)
332 load_cap = sdc_->pinCapacitance(load_pin, rf_, op_cond_,
333 corner_, min_max_);
334 elmore = elmore_res_ * (elmore_cap_ + load_cap);
335 exists = true;
336 }
337
338 void
setElmore(const Pin *,float)339 ConcretePiElmoreEstimated::setElmore(const Pin *,
340 float)
341 {
342 // Cannot set elmore on estimated parasitic.
343 }
344
345 ////////////////////////////////////////////////////////////////
346
347 ConcretePoleResidue::
ConcretePoleResidue(ComplexFloatSeq * poles,ComplexFloatSeq * residues)348 ConcretePoleResidue(ComplexFloatSeq *poles,
349 ComplexFloatSeq *residues) :
350 poles_(poles),
351 residues_(residues)
352 {
353 }
354
~ConcretePoleResidue()355 ConcretePoleResidue::~ConcretePoleResidue()
356 {
357 delete poles_;
358 delete residues_;
359 }
360
361 size_t
poleResidueCount() const362 ConcretePoleResidue::poleResidueCount() const
363 {
364 return poles_->size();
365 }
366
367 void
poleResidue(int index,ComplexFloat & pole,ComplexFloat & residue) const368 ConcretePoleResidue::poleResidue(int index,
369 ComplexFloat &pole,
370 ComplexFloat &residue) const
371 {
372 pole = (*poles_)[index];
373 residue = (*residues_)[index];
374 }
375
376 void
setPoleResidue(ComplexFloatSeq * poles,ComplexFloatSeq * residues)377 ConcretePoleResidue::setPoleResidue(ComplexFloatSeq *poles,
378 ComplexFloatSeq *residues)
379 {
380 poles_ = poles;
381 residues_ = residues;
382 }
383
384 ////////////////////////////////////////////////////////////////
385
ConcretePiPoleResidue(float c2,float rpi,float c1)386 ConcretePiPoleResidue::ConcretePiPoleResidue(float c2,
387 float rpi,
388 float c1) :
389 ConcretePi(c2, rpi, c1),
390 load_pole_residue_(nullptr)
391 {
392 }
393
~ConcretePiPoleResidue()394 ConcretePiPoleResidue::~ConcretePiPoleResidue()
395 {
396 if (load_pole_residue_) {
397 load_pole_residue_->deleteContents();
398 delete load_pole_residue_;
399 }
400 }
401
402 float
capacitance() const403 ConcretePiPoleResidue::capacitance() const
404 {
405 return ConcretePi::capacitance();
406 }
407
408 void
piModel(float & c2,float & rpi,float & c1) const409 ConcretePiPoleResidue::piModel(float &c2,
410 float &rpi,
411 float &c1) const
412 {
413 ConcretePi::piModel(c2, rpi, c1);
414 }
415
416 void
setPiModel(float c2,float rpi,float c1)417 ConcretePiPoleResidue::setPiModel(float c2,
418 float rpi,
419 float c1)
420 {
421 ConcretePi::setPiModel(c2, rpi, c1);
422 }
423
424 bool
isReducedParasiticNetwork() const425 ConcretePiPoleResidue::isReducedParasiticNetwork() const
426 {
427 return ConcretePi::isReducedParasiticNetwork();
428 }
429
430 void
setIsReduced(bool reduced)431 ConcretePiPoleResidue::setIsReduced(bool reduced)
432 {
433 ConcretePi::setIsReduced(reduced);
434 }
435
436 Parasitic *
findPoleResidue(const Pin * load_pin) const437 ConcretePiPoleResidue::findPoleResidue(const Pin *load_pin) const
438 {
439 if (load_pole_residue_)
440 return load_pole_residue_->findKey(load_pin);
441 else
442 return nullptr;
443 }
444
445 void
setPoleResidue(const Pin * load_pin,ComplexFloatSeq * poles,ComplexFloatSeq * residues)446 ConcretePiPoleResidue::setPoleResidue(const Pin *load_pin,
447 ComplexFloatSeq *poles,
448 ComplexFloatSeq *residues)
449 {
450 if (load_pole_residue_ == nullptr)
451 load_pole_residue_ = new ConcretePoleResidueMap;
452 ConcretePoleResidue *pole_residue = load_pole_residue_->findKey(load_pin);
453 if (pole_residue == nullptr) {
454 pole_residue = new ConcretePoleResidue(poles, residues);
455 (*load_pole_residue_)[load_pin] = pole_residue;
456 }
457 else
458 pole_residue->setPoleResidue(poles, residues);
459 }
460
461 void
deleteLoad(const Pin * load_pin)462 ConcretePiPoleResidue::deleteLoad(const Pin *load_pin)
463 {
464 ConcretePoleResidue *pole_residue = load_pole_residue_->findKey(load_pin);
465 if (pole_residue) {
466 load_pole_residue_->erase(load_pin);
467 delete pole_residue;
468 }
469 }
470
471 ////////////////////////////////////////////////////////////////
472
ConcreteParasiticNode()473 ConcreteParasiticNode::ConcreteParasiticNode() :
474 cap_(0.0)
475 {
476 }
477
478 void
incrCapacitance(float cap)479 ConcreteParasiticNode::incrCapacitance(float cap)
480 {
481 cap_ += cap;
482 }
483
484 float
capacitance() const485 ConcreteParasiticNode::capacitance() const
486 {
487 return cap_;
488 }
489
490 void
addDevice(ConcreteParasiticDevice * device)491 ConcreteParasiticNode::addDevice(ConcreteParasiticDevice *device)
492 {
493 devices_.push_back(device);
494 }
495
496 ////////////////////////////////////////////////////////////////
497
ConcreteParasiticSubNode(const Net * net,int id)498 ConcreteParasiticSubNode::ConcreteParasiticSubNode(const Net *net,
499 int id) :
500 ConcreteParasiticNode(),
501 net_(net),
502 id_(id)
503 {
504 }
505
506 const char *
name(const Network * network) const507 ConcreteParasiticSubNode::name(const Network *network) const
508 {
509 const char *net_name = network->pathName(net_);
510 return stringPrintTmp("%s:%d", net_name, id_);
511 }
512
513 ////////////////////////////////////////////////////////////////
514
ConcreteParasiticPinNode(const Pin * pin)515 ConcreteParasiticPinNode::ConcreteParasiticPinNode(const Pin *pin) :
516 ConcreteParasiticNode(),
517 pin_(pin)
518 {
519 }
520
521 const char *
name(const Network * network) const522 ConcreteParasiticPinNode::name(const Network *network) const
523 {
524 return network->pathName(pin_);
525 }
526
527 ////////////////////////////////////////////////////////////////
528
ConcreteParasiticDevice(const char * name,ConcreteParasiticNode * node,float value)529 ConcreteParasiticDevice::ConcreteParasiticDevice(const char *name,
530 ConcreteParasiticNode *node,
531 float value) :
532 name_(name),
533 node_(node),
534 value_(value)
535 {
536 }
537
~ConcreteParasiticDevice()538 ConcreteParasiticDevice::~ConcreteParasiticDevice()
539 {
540 if (name_)
541 stringDelete(name_);
542 }
543
544 ConcreteParasiticResistor::
ConcreteParasiticResistor(const char * name,ConcreteParasiticNode * node,ConcreteParasiticNode * other_node,float res)545 ConcreteParasiticResistor(const char *name,
546 ConcreteParasiticNode *node,
547 ConcreteParasiticNode *other_node,
548 float res) :
549 ConcreteParasiticDevice(name, node, res),
550 other_node_(other_node)
551 {
552 }
553
554 ParasiticNode *
otherNode(ParasiticNode * node) const555 ConcreteParasiticResistor::otherNode(ParasiticNode *node) const
556 {
557 if (node == node_)
558 return other_node_;
559 else if (node == other_node_)
560 return node_;
561 else
562 return nullptr;
563 }
564
565 void
replaceNode(ConcreteParasiticNode * from_node,ConcreteParasiticNode * to_node)566 ConcreteParasiticResistor::replaceNode(ConcreteParasiticNode *from_node,
567 ConcreteParasiticNode *to_node)
568 {
569 if (from_node == node_)
570 node_ = to_node;
571 else
572 other_node_ = to_node;
573 }
574
575 ////////////////////////////////////////////////////////////////
576
ConcreteCouplingCap(const char * name,ConcreteParasiticNode * node,float cap)577 ConcreteCouplingCap::ConcreteCouplingCap(const char *name,
578 ConcreteParasiticNode *node,
579 float cap) :
580 ConcreteParasiticDevice(name, node, cap)
581 {
582 }
583
584 void
replaceNode(ConcreteParasiticNode * from_node,ConcreteParasiticNode * to_node)585 ConcreteCouplingCap::replaceNode(ConcreteParasiticNode *from_node,
586 ConcreteParasiticNode *to_node)
587 {
588 if (from_node == node_)
589 node_ = to_node;
590 }
591
592 ////////////////////////////////////////////////////////////////
593
594 ConcreteCouplingCapInt::
ConcreteCouplingCapInt(const char * name,ConcreteParasiticNode * node,ConcreteParasiticNode * other_node,float cap)595 ConcreteCouplingCapInt(const char *name,
596 ConcreteParasiticNode *node,
597 ConcreteParasiticNode *other_node,
598 float cap) :
599 ConcreteCouplingCap(name, node, cap),
600 other_node_(other_node)
601 {
602 }
603
604 ParasiticNode *
otherNode(ParasiticNode * node) const605 ConcreteCouplingCapInt::otherNode(ParasiticNode *node) const
606 {
607 if (node == node_)
608 return other_node_;
609 else if (node == other_node_)
610 return node_;
611 else
612 return nullptr;
613 }
614
615 void
replaceNode(ConcreteParasiticNode * from_node,ConcreteParasiticNode * to_node)616 ConcreteCouplingCapInt::replaceNode(ConcreteParasiticNode *from_node,
617 ConcreteParasiticNode *to_node)
618 {
619 if (from_node == node_)
620 node_ = to_node;
621 else
622 other_node_ = to_node;
623 }
624
625 ////////////////////////////////////////////////////////////////
626
627 ConcreteCouplingCapExtNode::
ConcreteCouplingCapExtNode(const char * name,ConcreteParasiticNode * node,Net *,int,float cap)628 ConcreteCouplingCapExtNode(const char *name,
629 ConcreteParasiticNode *node,
630 Net *,
631 int,
632 float cap) :
633 ConcreteCouplingCap(name, node, cap)
634 {
635 }
636
637 ParasiticNode *
otherNode(ParasiticNode *) const638 ConcreteCouplingCapExtNode::otherNode(ParasiticNode *) const
639 {
640 return nullptr;
641 }
642
643 void
replaceNode(ConcreteParasiticNode * from_node,ConcreteParasiticNode * to_node)644 ConcreteCouplingCapExtNode::replaceNode(ConcreteParasiticNode *from_node,
645 ConcreteParasiticNode *to_node)
646 {
647 if (from_node == node_)
648 node_ = to_node;
649 }
650
651 ////////////////////////////////////////////////////////////////
652
653 ConcreteCouplingCapExtPin::
ConcreteCouplingCapExtPin(const char * name,ConcreteParasiticNode * node,Pin *,float cap)654 ConcreteCouplingCapExtPin(const char *name,
655 ConcreteParasiticNode *node,
656 Pin *,
657 float cap) :
658 ConcreteCouplingCap(name, node, cap)
659 {
660 }
661
662 ParasiticNode *
otherNode(ParasiticNode *) const663 ConcreteCouplingCapExtPin::otherNode(ParasiticNode *) const
664 {
665 return nullptr;
666 }
667
668 void
replaceNode(ConcreteParasiticNode * from_node,ConcreteParasiticNode * to_node)669 ConcreteCouplingCapExtPin::replaceNode(ConcreteParasiticNode *from_node,
670 ConcreteParasiticNode *to_node)
671 {
672 if (from_node == node_)
673 node_ = to_node;
674 }
675
676 ////////////////////////////////////////////////////////////////
677
ConcreteParasiticNetwork(bool includes_pin_caps)678 ConcreteParasiticNetwork::ConcreteParasiticNetwork(bool includes_pin_caps) :
679 max_node_id_(0),
680 includes_pin_caps_(includes_pin_caps)
681 {
682 }
683
~ConcreteParasiticNetwork()684 ConcreteParasiticNetwork::~ConcreteParasiticNetwork()
685 {
686 deleteDevices();
687 deleteNodes();
688 }
689
690 void
deleteNodes()691 ConcreteParasiticNetwork::deleteNodes()
692 {
693 ConcreteParasiticSubNodeMap::Iterator node_iter1(sub_nodes_);
694 while (node_iter1.hasNext()) {
695 NetId *net_id;
696 ConcreteParasiticSubNode *node;
697 node_iter1.next(net_id, node);
698 delete net_id;
699 delete node;
700 }
701 pin_nodes_.deleteContents();
702 }
703
704 void
deleteDevices()705 ConcreteParasiticNetwork::deleteDevices()
706 {
707 ConcreteParasiticDeviceSet devices1;
708 devices(&devices1);
709 devices1.deleteContents();
710 }
711
712 ParasiticNodeIterator *
nodeIterator()713 ConcreteParasiticNetwork::nodeIterator()
714 {
715 ConcreteParasiticNodeSeq *nodes = new ConcreteParasiticNodeSeq();
716 ConcreteParasiticPinNodeMap::Iterator node_iter2(pin_nodes_);
717 while (node_iter2.hasNext()) {
718 ConcreteParasiticPinNode *node = node_iter2.next();
719 nodes->push_back(node);
720 }
721 ConcreteParasiticSubNodeMap::Iterator node_iter1(sub_nodes_);
722 while (node_iter1.hasNext()) {
723 ConcreteParasiticSubNode *node = node_iter1.next();
724 nodes->push_back(node);
725 }
726 return new ConcreteParasiticNodeSeqIterator(nodes);
727 }
728
729 ParasiticDeviceIterator *
deviceIterator()730 ConcreteParasiticNetwork::deviceIterator()
731 {
732 ConcreteParasiticDeviceSet *devices1 = new ConcreteParasiticDeviceSet();
733 devices(devices1);
734 return new ConcreteParasiticDeviceSetIterator(devices1);
735 }
736
737 void
devices(ConcreteParasiticDeviceSet * devices)738 ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet *devices)
739 {
740 // Collect devices into a set so they are only deleted once
741 // because multiple sub-nodes or pin nodes can refer to them.
742 ConcreteParasiticSubNodeMap::Iterator node_iter1(sub_nodes_);
743 while (node_iter1.hasNext()) {
744 ConcreteParasiticSubNode *node = node_iter1.next();
745 ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
746 while (device_iter.hasNext()) {
747 ConcreteParasiticDevice *device = device_iter.next();
748 devices->insert(device);
749 }
750 }
751
752 ConcreteParasiticPinNodeMap::Iterator node_iter2(pin_nodes_);
753 while (node_iter2.hasNext()) {
754 ConcreteParasiticPinNode *node = node_iter2.next();
755 ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
756 while (device_iter.hasNext()) {
757 ConcreteParasiticDevice *device = device_iter.next();
758 devices->insert(device);
759 }
760 }
761 }
762
763 float
capacitance() const764 ConcreteParasiticNetwork::capacitance() const
765 {
766 float cap = 0.0;
767 ConcreteParasiticSubNodeMap::ConstIterator sub_node_iter(sub_nodes_);
768 while (sub_node_iter.hasNext()) {
769 ConcreteParasiticSubNode *node = sub_node_iter.next();
770 cap += node->capacitance();
771 }
772
773 ConcreteParasiticPinNodeMap::ConstIterator pin_node_iter(pin_nodes_);
774 while (pin_node_iter.hasNext()) {
775 ConcreteParasiticPinNode *node = pin_node_iter.next();
776 cap += node->capacitance();
777 }
778 return cap;
779 }
780
781 ConcreteParasiticNode *
ensureParasiticNode(const Net * net,int id)782 ConcreteParasiticNetwork::ensureParasiticNode(const Net *net,
783 int id)
784 {
785 NetId net_id(net, id);
786 ConcreteParasiticSubNode *node = sub_nodes_.findKey(&net_id);
787 if (node == nullptr) {
788 node = new ConcreteParasiticSubNode(net, id);
789 sub_nodes_[new NetId(net, id)] = node;
790 max_node_id_ = max((int) max_node_id_, id);
791 }
792 return node;
793 }
794
795 ConcreteParasiticNode *
findNode(const Pin * pin)796 ConcreteParasiticNetwork::findNode(const Pin *pin)
797 {
798 return pin_nodes_.findKey(pin);
799 }
800
801 void
disconnectPin(const Pin * pin,Net * net)802 ConcreteParasiticNetwork::disconnectPin(const Pin *pin,
803 Net *net)
804 {
805 ConcreteParasiticNode *node = pin_nodes_.findKey(pin);
806 if (node) {
807 // Make a subnode to replace the pin node.
808 ConcreteParasiticNode *subnode = ensureParasiticNode(net,max_node_id_+1);
809 // Hand over the devices.
810 ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
811 while (device_iter.hasNext()) {
812 ConcreteParasiticDevice *device = device_iter.next();
813 subnode->addDevice(device);
814 device->replaceNode(node, subnode);
815 }
816
817 pin_nodes_.erase(pin);
818 delete node;
819 }
820 }
821
822 ConcreteParasiticNode *
ensureParasiticNode(const Pin * pin)823 ConcreteParasiticNetwork::ensureParasiticNode(const Pin *pin)
824 {
825 ConcreteParasiticPinNode *node = pin_nodes_.findKey(pin);
826 if (node == nullptr) {
827 node = new ConcreteParasiticPinNode(pin);
828 pin_nodes_[pin] = node;
829 }
830 return node;
831 }
832
833 bool
operator ()(const NetId * net_id1,const NetId * net_id2) const834 NetIdLess::operator()(const NetId *net_id1,
835 const NetId *net_id2) const
836 {
837 const Net *net1 = net_id1->first;
838 const Net *net2 = net_id2->first;
839 int id1 = net_id1->second;
840 int id2 = net_id2->second;
841 return net1 < net2
842 || (net1 == net2
843 && id1 < id2);
844 }
845
846 ////////////////////////////////////////////////////////////////
847
848 Parasitics *
makeConcreteParasitics(StaState * sta)849 makeConcreteParasitics(StaState *sta)
850 {
851 return new ConcreteParasitics(sta);
852 }
853
ConcreteParasitics(StaState * sta)854 ConcreteParasitics::ConcreteParasitics(StaState *sta) :
855 Parasitics(sta)
856 {
857 }
858
~ConcreteParasitics()859 ConcreteParasitics::~ConcreteParasitics()
860 {
861 clear();
862 }
863
864 bool
haveParasitics()865 ConcreteParasitics::haveParasitics()
866 {
867 return !drvr_parasitic_map_.empty()
868 || !parasitic_network_map_.empty();
869 }
870
871 void
clear()872 ConcreteParasitics::clear()
873 {
874 deleteParasitics();
875 }
876
877 int
parasiticAnalysisPtIndex(const ParasiticAnalysisPt * ap,const RiseFall * rf) const878 ConcreteParasitics::parasiticAnalysisPtIndex(const ParasiticAnalysisPt *ap,
879 const RiseFall *rf) const
880 {
881 return ap->index() * RiseFall::index_count + rf->index();
882 }
883
884 void
deleteParasitics()885 ConcreteParasitics::deleteParasitics()
886 {
887 int ap_count = corners_->parasiticAnalysisPtCount();
888 int ap_rf_count = ap_count * RiseFall::index_count;
889 for (auto drvr_parasitics : drvr_parasitic_map_) {
890 ConcreteParasitic **parasitics = drvr_parasitics.second;
891 if (parasitics) {
892 for (int i = 0; i < ap_rf_count; i++)
893 delete parasitics[i];
894 delete [] parasitics;
895 }
896 }
897 drvr_parasitic_map_.clear();
898
899 for (auto net_parasitics : parasitic_network_map_) {
900 ConcreteParasiticNetwork **parasitics = net_parasitics.second;
901 if (parasitics) {
902 for (int i = 0; i < ap_count; i++)
903 delete parasitics[i];
904 delete [] parasitics;
905 }
906 }
907 parasitic_network_map_.clear();
908 }
909
910 void
deleteParasitics(const Pin * drvr_pin,const ParasiticAnalysisPt * ap)911 ConcreteParasitics::deleteParasitics(const Pin *drvr_pin,
912 const ParasiticAnalysisPt *ap)
913 {
914 ConcreteParasitic **parasitics = drvr_parasitic_map_[drvr_pin];
915 if (parasitics) {
916 for (auto tr : RiseFall::range()) {
917 int ap_rf_index = parasiticAnalysisPtIndex(ap, tr);
918 delete parasitics[ap_rf_index];
919 parasitics[ap_rf_index] = nullptr;
920 }
921 }
922 }
923
924 void
deleteParasitics(const Net * net,const ParasiticAnalysisPt * ap)925 ConcreteParasitics::deleteParasitics(const Net *net,
926 const ParasiticAnalysisPt *ap)
927 {
928 PinSet *drivers = network_->drivers(net);
929 for (auto drvr_pin : *drivers)
930 deleteParasitics(drvr_pin, ap);
931
932 ConcreteParasiticNetwork **parasitics = parasitic_network_map_[net];
933 if (parasitics) {
934 delete parasitics[ap->index()];
935 parasitics[ap->index()] = nullptr;
936 }
937 }
938
939 void
deleteUnsavedParasitic(Parasitic * parasitic)940 ConcreteParasitics::deleteUnsavedParasitic(Parasitic *parasitic)
941 {
942 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
943 delete cparasitic;
944 }
945
946 void
save()947 ConcreteParasitics::save()
948 {
949 // No database to save to.
950 }
951
952 float
capacitance(Parasitic * parasitic) const953 ConcreteParasitics::capacitance(Parasitic *parasitic) const
954 {
955 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
956 return cparasitic->capacitance();
957 }
958
959 bool
isReducedParasiticNetwork(Parasitic * parasitic) const960 ConcreteParasitics::isReducedParasiticNetwork(Parasitic *parasitic) const
961 {
962 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
963 return cparasitic->isReducedParasiticNetwork();
964 }
965
966 void
setIsReducedParasiticNetwork(Parasitic * parasitic,bool is_reduced)967 ConcreteParasitics::setIsReducedParasiticNetwork(Parasitic *parasitic,
968 bool is_reduced)
969 {
970 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
971 cparasitic->setIsReduced(is_reduced);
972 }
973
974 void
disconnectPinBefore(const Pin * pin)975 ConcreteParasitics::disconnectPinBefore(const Pin *pin)
976 {
977 if (haveParasitics()) {
978 deleteReducedParasitics(pin);
979
980 Net *net = findParasiticNet(pin);
981 if (net) {
982 ConcreteParasiticNetwork **parasitics = parasitic_network_map_[net];
983 if (parasitics) {
984 int ap_count = corners_->parasiticAnalysisPtCount();
985 for (int i = 0; i < ap_count; i++) {
986 ConcreteParasiticNetwork *parasitic = parasitics[i];
987 if (parasitic)
988 parasitic->disconnectPin(pin, net);
989 }
990 }
991 }
992 }
993 }
994
995 void
loadPinCapacitanceChanged(const Pin * pin)996 ConcreteParasitics::loadPinCapacitanceChanged(const Pin *pin)
997 {
998 // Delete reduced models that depend on load pin capacitances.
999 deleteReducedParasitics(pin);
1000 }
1001
1002 // Delete reduced models on pin's net.
1003 void
deleteReducedParasitics(const Pin * pin)1004 ConcreteParasitics::deleteReducedParasitics(const Pin *pin)
1005 {
1006 if (!drvr_parasitic_map_.empty()) {
1007 PinSet *drivers = network_->drivers(pin);
1008 if (drivers) {
1009 for (auto drvr_pin : *drivers)
1010 deleteDrvrReducedParasitics(drvr_pin);
1011 }
1012 }
1013 }
1014
1015 void
deleteDrvrReducedParasitics(const Pin * drvr_pin)1016 ConcreteParasitics::deleteDrvrReducedParasitics(const Pin *drvr_pin)
1017 {
1018 UniqueLock lock(lock_);
1019 ConcreteParasitic **parasitics = drvr_parasitic_map_[drvr_pin];
1020 if (parasitics) {
1021 int ap_count = corners_->parasiticAnalysisPtCount();
1022 int ap_rf_count = ap_count * RiseFall::index_count;
1023 for (int i = 0; i < ap_rf_count; i++)
1024 delete parasitics[i];
1025 delete [] parasitics;
1026 }
1027 drvr_parasitic_map_[drvr_pin] = nullptr;
1028 }
1029
1030 ////////////////////////////////////////////////////////////////
1031
1032 bool
isPiElmore(Parasitic * parasitic) const1033 ConcreteParasitics::isPiElmore(Parasitic *parasitic) const
1034 {
1035 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1036 return cparasitic && cparasitic->isPiElmore();
1037 }
1038
1039 Parasitic *
findPiElmore(const Pin * drvr_pin,const RiseFall * rf,const ParasiticAnalysisPt * ap) const1040 ConcreteParasitics::findPiElmore(const Pin *drvr_pin,
1041 const RiseFall *rf,
1042 const ParasiticAnalysisPt *ap) const
1043 {
1044 if (!drvr_parasitic_map_.empty()) {
1045 int ap_rf_index = parasiticAnalysisPtIndex(ap, rf);
1046 UniqueLock lock(lock_);
1047 ConcreteParasitic **parasitics = drvr_parasitic_map_.findKey(drvr_pin);
1048 if (parasitics) {
1049 ConcreteParasitic *parasitic = parasitics[ap_rf_index];
1050 if (parasitic == nullptr && rf == RiseFall::fall()) {
1051 ap_rf_index = parasiticAnalysisPtIndex(ap, RiseFall::rise());
1052 parasitic = parasitics[ap_rf_index];
1053 }
1054 if (parasitic && parasitic->isPiElmore())
1055 return parasitic;
1056 }
1057 }
1058 return nullptr;
1059 }
1060
1061 Parasitic *
makePiElmore(const Pin * drvr_pin,const RiseFall * rf,const ParasiticAnalysisPt * ap,float c2,float rpi,float c1)1062 ConcreteParasitics::makePiElmore(const Pin *drvr_pin,
1063 const RiseFall *rf,
1064 const ParasiticAnalysisPt *ap,
1065 float c2,
1066 float rpi,
1067 float c1)
1068 {
1069 UniqueLock lock(lock_);
1070 ConcreteParasitic **parasitics = drvr_parasitic_map_.findKey(drvr_pin);
1071 if (parasitics == nullptr) {
1072 int ap_count = corners_->parasiticAnalysisPtCount();
1073 int ap_rf_count = ap_count * RiseFall::index_count;
1074 parasitics = new ConcreteParasitic*[ap_rf_count];
1075 for (int i = 0; i < ap_rf_count; i++)
1076 parasitics[i] = nullptr;
1077 drvr_parasitic_map_[drvr_pin] = parasitics;
1078 }
1079 int ap_rf_index = parasiticAnalysisPtIndex(ap, rf);
1080 ConcreteParasitic *parasitic = parasitics[ap_rf_index];
1081 ConcretePiElmore *pi_elmore = nullptr;
1082 if (parasitic) {
1083 if (parasitic->isPiElmore()) {
1084 pi_elmore = dynamic_cast<ConcretePiElmore*>(parasitic);
1085 pi_elmore->setPiModel(c2, rpi, c1);
1086 }
1087 else {
1088 delete parasitic;
1089 pi_elmore = new ConcretePiElmore(c2, rpi, c1);
1090 parasitics[ap_rf_index] = pi_elmore;
1091 }
1092 }
1093 else {
1094 pi_elmore = new ConcretePiElmore(c2, rpi, c1);
1095 parasitics[ap_rf_index] = pi_elmore;
1096 }
1097 return pi_elmore;
1098 }
1099
1100 ////////////////////////////////////////////////////////////////
1101
1102 bool
isPiModel(Parasitic * parasitic) const1103 ConcreteParasitics::isPiModel(Parasitic *parasitic) const
1104 {
1105 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1106 return cparasitic && cparasitic->isPiModel();
1107 }
1108
1109 void
piModel(Parasitic * parasitic,float & c2,float & rpi,float & c1) const1110 ConcreteParasitics::piModel(Parasitic *parasitic,
1111 float &c2,
1112 float &rpi,
1113 float &c1) const
1114 {
1115 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1116 cparasitic->piModel(c2, rpi, c1);
1117 }
1118
1119 void
setPiModel(Parasitic * parasitic,float c2,float rpi,float c1)1120 ConcreteParasitics::setPiModel(Parasitic *parasitic,
1121 float c2,
1122 float rpi,
1123 float c1)
1124 {
1125 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1126 cparasitic->setPiModel(c2, rpi, c1);
1127 }
1128
1129 ////////////////////////////////////////////////////////////////
1130
1131 void
findElmore(Parasitic * parasitic,const Pin * load_pin,float & elmore,bool & exists) const1132 ConcreteParasitics::findElmore(Parasitic *parasitic,
1133 const Pin *load_pin,
1134 float &elmore,
1135 bool &exists) const
1136 {
1137 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1138 cparasitic->findElmore(load_pin, elmore, exists);
1139 }
1140
1141 void
setElmore(Parasitic * parasitic,const Pin * load_pin,float elmore)1142 ConcreteParasitics::setElmore(Parasitic *parasitic,
1143 const Pin *load_pin,
1144 float elmore)
1145 {
1146 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1147 cparasitic->setElmore(load_pin, elmore);
1148 }
1149
1150 ////////////////////////////////////////////////////////////////
1151
1152 bool
isPiPoleResidue(Parasitic * parasitic) const1153 ConcreteParasitics::isPiPoleResidue(Parasitic* parasitic) const
1154 {
1155 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1156 return cparasitic && cparasitic->isPiPoleResidue();
1157 }
1158
1159 Parasitic *
findPiPoleResidue(const Pin * drvr_pin,const RiseFall * rf,const ParasiticAnalysisPt * ap) const1160 ConcreteParasitics::findPiPoleResidue(const Pin *drvr_pin,
1161 const RiseFall *rf,
1162 const ParasiticAnalysisPt *ap) const
1163 {
1164 if (!drvr_parasitic_map_.empty()) {
1165 int ap_rf_index = parasiticAnalysisPtIndex(ap, rf);
1166 UniqueLock lock(lock_);
1167 ConcreteParasitic **parasitics = drvr_parasitic_map_.findKey(drvr_pin);
1168 if (parasitics) {
1169 ConcreteParasitic *parasitic = parasitics[ap_rf_index];
1170 if (parasitic == nullptr && rf == RiseFall::fall()) {
1171 ap_rf_index = parasiticAnalysisPtIndex(ap, RiseFall::rise());
1172 parasitic = parasitics[ap_rf_index];
1173 }
1174 if (parasitic->isPiPoleResidue())
1175 return parasitic;
1176 }
1177 }
1178 return nullptr;
1179 }
1180
1181 Parasitic *
makePiPoleResidue(const Pin * drvr_pin,const RiseFall * rf,const ParasiticAnalysisPt * ap,float c2,float rpi,float c1)1182 ConcreteParasitics::makePiPoleResidue(const Pin *drvr_pin,
1183 const RiseFall *rf,
1184 const ParasiticAnalysisPt *ap,
1185 float c2,
1186 float rpi,
1187 float c1)
1188 {
1189 UniqueLock lock(lock_);
1190 ConcreteParasitic **parasitics = drvr_parasitic_map_.findKey(drvr_pin);
1191 if (parasitics == nullptr) {
1192 int ap_count = corners_->parasiticAnalysisPtCount();
1193 int ap_rf_count = ap_count * RiseFall::index_count;
1194 parasitics = new ConcreteParasitic*[ap_rf_count];
1195 for (int i = 0; i < ap_rf_count; i++)
1196 parasitics[i] = nullptr;
1197 drvr_parasitic_map_[drvr_pin] = parasitics;
1198 }
1199 int ap_rf_index = parasiticAnalysisPtIndex(ap, rf);
1200 ConcreteParasitic *parasitic = parasitics[ap_rf_index];
1201 ConcretePiPoleResidue *pi_pole_residue = nullptr;
1202 if (parasitic) {
1203 if (parasitic->isPiElmore()) {
1204 pi_pole_residue = dynamic_cast<ConcretePiPoleResidue*>(parasitic);
1205 pi_pole_residue->setPiModel(c2, rpi, c1);
1206 }
1207 else {
1208 delete parasitic;
1209 pi_pole_residue = new ConcretePiPoleResidue(c2, rpi, c1);
1210 parasitics[ap_rf_index] = pi_pole_residue;
1211 }
1212 }
1213 else {
1214 pi_pole_residue = new ConcretePiPoleResidue(c2, rpi, c1);
1215 parasitics[ap_rf_index] = pi_pole_residue;
1216 }
1217 return pi_pole_residue;
1218 }
1219
1220 Parasitic *
findPoleResidue(const Parasitic * parasitic,const Pin * load_pin) const1221 ConcreteParasitics::findPoleResidue(const Parasitic *parasitic,
1222 const Pin *load_pin) const
1223 {
1224 const ConcreteParasitic *cparasitic =
1225 static_cast<const ConcreteParasitic*>(parasitic);
1226 return cparasitic->findPoleResidue(load_pin);
1227 }
1228
1229 void
setPoleResidue(Parasitic * parasitic,const Pin * load_pin,ComplexFloatSeq * poles,ComplexFloatSeq * residues)1230 ConcreteParasitics::setPoleResidue(Parasitic *parasitic,
1231 const Pin *load_pin,
1232 ComplexFloatSeq *poles,
1233 ComplexFloatSeq *residues)
1234 {
1235 ConcreteParasitic *cparasitic =
1236 static_cast<ConcreteParasitic*>(parasitic);
1237 cparasitic->setPoleResidue(load_pin, poles, residues);
1238 }
1239
1240 ////////////////////////////////////////////////////////////////
1241
1242 bool
isPoleResidue(const Parasitic * parasitic) const1243 ConcreteParasitics::isPoleResidue(const Parasitic *parasitic) const
1244 {
1245 const ConcreteParasitic *cparasitic =
1246 static_cast<const ConcreteParasitic*>(parasitic);
1247 return cparasitic->isPoleResidue();
1248 }
1249
1250 size_t
poleResidueCount(const Parasitic * parasitic) const1251 ConcreteParasitics::poleResidueCount(const Parasitic *parasitic) const
1252 {
1253 const ConcretePoleResidue *pr_parasitic =
1254 static_cast<const ConcretePoleResidue*>(parasitic);
1255 return pr_parasitic->poleResidueCount();
1256 }
1257
1258 void
poleResidue(const Parasitic * parasitic,int pole_index,ComplexFloat & pole,ComplexFloat & residue) const1259 ConcreteParasitics::poleResidue(const Parasitic *parasitic,
1260 int pole_index,
1261 ComplexFloat &pole,
1262 ComplexFloat &residue) const
1263 {
1264 const ConcretePoleResidue *pr_parasitic =
1265 static_cast<const ConcretePoleResidue*>(parasitic);
1266 pr_parasitic->poleResidue(pole_index, pole, residue);
1267 }
1268
1269 ////////////////////////////////////////////////////////////////
1270
1271 bool
isParasiticNetwork(Parasitic * parasitic) const1272 ConcreteParasitics::isParasiticNetwork(Parasitic *parasitic) const
1273 {
1274 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1275 return cparasitic && cparasitic->isParasiticNetwork();
1276 }
1277
1278 Parasitic *
findParasiticNetwork(const Net * net,const ParasiticAnalysisPt * ap) const1279 ConcreteParasitics::findParasiticNetwork(const Net *net,
1280 const ParasiticAnalysisPt *ap) const
1281 {
1282 if (!parasitic_network_map_.empty()) {
1283 UniqueLock lock(lock_);
1284 if (!parasitic_network_map_.empty()) {
1285 ConcreteParasiticNetwork **parasitics=parasitic_network_map_.findKey(net);
1286 if (parasitics)
1287 return parasitics[ap->index()];
1288 }
1289 }
1290 return nullptr;
1291 }
1292
1293 Parasitic *
findParasiticNetwork(const Pin * pin,const ParasiticAnalysisPt * ap) const1294 ConcreteParasitics::findParasiticNetwork(const Pin *pin,
1295 const ParasiticAnalysisPt *ap) const
1296 {
1297 if (!parasitic_network_map_.empty()) {
1298 UniqueLock lock(lock_);
1299 if (!parasitic_network_map_.empty()) {
1300 // Only call findParasiticNet if parasitics exist.
1301 Net *net = findParasiticNet(pin);
1302 ConcreteParasiticNetwork **parasitics=parasitic_network_map_.findKey(net);
1303 if (parasitics)
1304 return parasitics[ap->index()];
1305 }
1306 }
1307 return nullptr;
1308 }
1309
1310 Parasitic *
makeParasiticNetwork(const Net * net,bool includes_pin_caps,const ParasiticAnalysisPt * ap)1311 ConcreteParasitics::makeParasiticNetwork(const Net *net,
1312 bool includes_pin_caps,
1313 const ParasiticAnalysisPt *ap)
1314 {
1315 UniqueLock lock(lock_);
1316 ConcreteParasiticNetwork **parasitics = parasitic_network_map_.findKey(net);
1317 if (parasitics == nullptr) {
1318 int ap_count = corners_->parasiticAnalysisPtCount();
1319 parasitics = new ConcreteParasiticNetwork*[ap_count];
1320 for (int i = 0; i < ap_count; i++)
1321 parasitics[i] = nullptr;
1322 parasitic_network_map_[net] = parasitics;
1323 }
1324 int ap_index = ap->index();
1325 ConcreteParasiticNetwork *parasitic = parasitics[ap_index];
1326 if (parasitic)
1327 delete parasitic;
1328 parasitic = new ConcreteParasiticNetwork(includes_pin_caps);
1329 parasitics[ap_index] = parasitic;
1330 return parasitic;
1331 }
1332
1333 void
deleteParasiticNetwork(const Net * net,const ParasiticAnalysisPt * ap)1334 ConcreteParasitics::deleteParasiticNetwork(const Net *net,
1335 const ParasiticAnalysisPt *ap)
1336 {
1337 if (!parasitic_network_map_.empty()) {
1338 UniqueLock lock(lock_);
1339 ConcreteParasiticNetwork **parasitics = parasitic_network_map_.findKey(net);
1340 if (parasitics) {
1341 int ap_index = ap->index();
1342 delete parasitics[ap_index];
1343 parasitics[ap_index] = nullptr;
1344 }
1345 }
1346 }
1347
1348 bool
includesPinCaps(Parasitic * parasitic) const1349 ConcreteParasitics::includesPinCaps(Parasitic *parasitic) const
1350 {
1351 ConcreteParasiticNetwork *cparasitic =
1352 static_cast<ConcreteParasiticNetwork*>(parasitic);
1353 return cparasitic->includesPinCaps();
1354 }
1355
1356 ParasiticNode *
ensureParasiticNode(Parasitic * parasitic,const Net * net,int id)1357 ConcreteParasitics::ensureParasiticNode(Parasitic *parasitic,
1358 const Net *net,
1359 int id)
1360 {
1361 ConcreteParasiticNetwork *cparasitic =
1362 static_cast<ConcreteParasiticNetwork*>(parasitic);
1363 return cparasitic->ensureParasiticNode(net, id);
1364 }
1365
1366 ParasiticNode *
ensureParasiticNode(Parasitic * parasitic,const Pin * pin)1367 ConcreteParasitics::ensureParasiticNode(Parasitic *parasitic,
1368 const Pin *pin)
1369 {
1370 ConcreteParasiticNetwork *cparasitic =
1371 static_cast<ConcreteParasiticNetwork*>(parasitic);
1372 return cparasitic->ensureParasiticNode(pin);
1373 }
1374
1375 void
incrCap(ParasiticNode * node,float cap,const ParasiticAnalysisPt *)1376 ConcreteParasitics::incrCap(ParasiticNode *node,
1377 float cap,
1378 const ParasiticAnalysisPt *)
1379 {
1380 ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
1381 cnode->incrCapacitance(cap);
1382 }
1383
1384 void
makeCouplingCap(const char * name,ParasiticNode * node,ParasiticNode * other_node,float cap,const ParasiticAnalysisPt *)1385 ConcreteParasitics::makeCouplingCap(const char *name,
1386 ParasiticNode *node,
1387 ParasiticNode *other_node,
1388 float cap,
1389 const ParasiticAnalysisPt *)
1390 {
1391 ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
1392 ConcreteParasiticNode *other_cnode =
1393 static_cast<ConcreteParasiticNode*>(other_node);
1394 ConcreteCouplingCap *coupling_cap =
1395 new ConcreteCouplingCapInt(name, cnode, other_cnode, cap);
1396 cnode->addDevice(coupling_cap);
1397 other_cnode->addDevice(coupling_cap);
1398 }
1399
1400 void
makeCouplingCap(const char * name,ParasiticNode * node,Net * other_node_net,int other_node_id,float cap,const ParasiticAnalysisPt *)1401 ConcreteParasitics::makeCouplingCap(const char *name,
1402 ParasiticNode *node,
1403 Net *other_node_net,
1404 int other_node_id,
1405 float cap,
1406 const ParasiticAnalysisPt *)
1407 {
1408 ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
1409 ConcreteCouplingCap *coupling_cap =
1410 new ConcreteCouplingCapExtNode(name, cnode, other_node_net,
1411 other_node_id, cap);
1412 cnode->addDevice(coupling_cap);
1413 }
1414
1415 void
makeCouplingCap(const char * name,ParasiticNode * node,Pin * other_node_pin,float cap,const ParasiticAnalysisPt *)1416 ConcreteParasitics::makeCouplingCap(const char *name,
1417 ParasiticNode *node,
1418 Pin *other_node_pin,
1419 float cap,
1420 const ParasiticAnalysisPt *)
1421 {
1422 ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
1423 ConcreteCouplingCap *coupling_cap =
1424 new ConcreteCouplingCapExtPin(name, cnode, other_node_pin, cap);
1425 cnode->addDevice(coupling_cap);
1426 }
1427
1428 void
makeResistor(const char * name,ParasiticNode * node1,ParasiticNode * node2,float res,const ParasiticAnalysisPt *)1429 ConcreteParasitics::makeResistor(const char *name,
1430 ParasiticNode *node1,
1431 ParasiticNode *node2,
1432 float res,
1433 const ParasiticAnalysisPt *)
1434 {
1435 ConcreteParasiticNode *cnode1 = static_cast<ConcreteParasiticNode*>(node1);
1436 ConcreteParasiticNode *cnode2 = static_cast<ConcreteParasiticNode*>(node2);
1437 ConcreteParasiticDevice *resistor =
1438 new ConcreteParasiticResistor(name, cnode1, cnode2, res);
1439 cnode1->addDevice(resistor);
1440 cnode2->addDevice(resistor);
1441 }
1442
1443 ParasiticDeviceIterator *
deviceIterator(Parasitic * parasitic)1444 ConcreteParasitics::deviceIterator(Parasitic *parasitic)
1445 {
1446 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1447 return cparasitic->deviceIterator();
1448 }
1449
1450 ParasiticNodeIterator *
nodeIterator(Parasitic * parasitic)1451 ConcreteParasitics::nodeIterator(Parasitic *parasitic)
1452 {
1453 ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
1454 return cparasitic->nodeIterator();
1455 }
1456
1457 float
nodeGndCap(const ParasiticNode * node,const ParasiticAnalysisPt *) const1458 ConcreteParasitics::nodeGndCap(const ParasiticNode *node,
1459 const ParasiticAnalysisPt *) const
1460 {
1461 const ConcreteParasiticNode *cnode =
1462 static_cast<const ConcreteParasiticNode*>(node);
1463 return cnode->capacitance();
1464 }
1465
1466 const char *
name(const ParasiticNode * node)1467 ConcreteParasitics::name(const ParasiticNode *node)
1468 {
1469 const ConcreteParasiticNode *cnode =
1470 static_cast<const ConcreteParasiticNode*>(node);
1471 return cnode->name(network_);
1472 }
1473
1474 const Pin *
connectionPin(const ParasiticNode * node) const1475 ConcreteParasitics::connectionPin(const ParasiticNode *node) const
1476 {
1477 const ConcreteParasiticNode *cnode =
1478 static_cast<const ConcreteParasiticNode*>(node);
1479 if (cnode->isPinNode()) {
1480 const ConcreteParasiticPinNode *pin_node =
1481 dynamic_cast<const ConcreteParasiticPinNode*>(cnode);
1482 return pin_node->pin();
1483 }
1484 else
1485 return nullptr;
1486 }
1487
1488 ParasiticNode *
findNode(Parasitic * parasitic,const Pin * pin) const1489 ConcreteParasitics::findNode(Parasitic *parasitic,
1490 const Pin *pin) const
1491 {
1492 ConcreteParasiticNetwork *cparasitic =
1493 static_cast<ConcreteParasiticNetwork*>(parasitic);
1494 return cparasitic->findNode(pin);
1495 }
1496
1497 ParasiticDeviceIterator *
deviceIterator(ParasiticNode * node) const1498 ConcreteParasitics::deviceIterator(ParasiticNode *node) const
1499 {
1500 ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
1501 return new ConcreteParasiticDeviceSeqIterator(cnode->devices());
1502 }
1503
1504 const char *
name(const ParasiticDevice * device) const1505 ConcreteParasitics::name(const ParasiticDevice *device) const
1506 {
1507 const ConcreteParasiticDevice *cdevice =
1508 static_cast<const ConcreteParasiticDevice*>(device);
1509 return cdevice->name();
1510 }
1511
1512 bool
isResistor(const ParasiticDevice * device) const1513 ConcreteParasitics::isResistor(const ParasiticDevice *device) const
1514 {
1515 const ConcreteParasiticDevice *cdevice =
1516 static_cast<const ConcreteParasiticDevice*>(device);
1517 return cdevice->isResistor();
1518 }
1519
1520 bool
isCouplingCap(const ParasiticDevice * device) const1521 ConcreteParasitics::isCouplingCap(const ParasiticDevice *device) const
1522 {
1523 const ConcreteParasiticDevice *cdevice =
1524 static_cast<const ConcreteParasiticDevice*>(device);
1525 return cdevice->isCouplingCap();
1526 }
1527
1528 float
value(const ParasiticDevice * device,const ParasiticAnalysisPt *) const1529 ConcreteParasitics::value(const ParasiticDevice *device,
1530 const ParasiticAnalysisPt *) const
1531 {
1532 const ConcreteParasiticDevice *cdevice =
1533 static_cast<const ConcreteParasiticDevice*>(device);
1534 return cdevice->value();
1535 }
1536
1537 ParasiticNode *
node1(const ParasiticDevice * device) const1538 ConcreteParasitics::node1(const ParasiticDevice *device) const
1539 {
1540 const ConcreteParasiticDevice *cdevice =
1541 static_cast<const ConcreteParasiticDevice*>(device);
1542 return cdevice->node1();
1543 }
1544
1545 ParasiticNode *
node2(const ParasiticDevice * device) const1546 ConcreteParasitics::node2(const ParasiticDevice *device) const
1547 {
1548 const ConcreteParasiticDevice *cdevice =
1549 static_cast<const ConcreteParasiticDevice*>(device);
1550 return cdevice->node2();
1551 }
1552
1553 ParasiticNode *
otherNode(const ParasiticDevice * device,ParasiticNode * node) const1554 ConcreteParasitics::otherNode(const ParasiticDevice *device,
1555 ParasiticNode *node) const
1556 {
1557 const ConcreteParasiticDevice *cdevice =
1558 static_cast<const ConcreteParasiticDevice*>(device);
1559 return cdevice->otherNode(node);
1560 }
1561
1562 ////////////////////////////////////////////////////////////////
1563
1564 void
reduceTo(Parasitic * parasitic,const Net * net,ReducedParasiticType reduce_to,const OperatingConditions * op_cond,const Corner * corner,const MinMax * cnst_min_max,const ParasiticAnalysisPt * ap)1565 ConcreteParasitics::reduceTo(Parasitic *parasitic,
1566 const Net *net,
1567 ReducedParasiticType reduce_to,
1568 const OperatingConditions *op_cond,
1569 const Corner *corner,
1570 const MinMax *cnst_min_max,
1571 const ParasiticAnalysisPt *ap)
1572 {
1573 switch (reduce_to) {
1574 case ReducedParasiticType::pi_elmore:
1575 reduceToPiElmore(parasitic, net, op_cond, corner, cnst_min_max, ap);
1576 break;
1577 case ReducedParasiticType::pi_pole_residue2:
1578 reduceToPiPoleResidue2(parasitic, net, op_cond, corner,
1579 cnst_min_max, ap);
1580 break;
1581 case ReducedParasiticType::arnoldi:
1582 case ReducedParasiticType::none:
1583 break;
1584 }
1585 }
1586
1587 void
reduceToPiElmore(Parasitic * parasitic,const Net * net,const OperatingConditions * op_cond,const Corner * corner,const MinMax * cnst_min_max,const ParasiticAnalysisPt * ap)1588 ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
1589 const Net *net,
1590 const OperatingConditions *op_cond,
1591 const Corner *corner,
1592 const MinMax *cnst_min_max,
1593 const ParasiticAnalysisPt *ap)
1594 {
1595 debugPrint(debug_, "parasitic_reduce", 1, "Reduce net %s",
1596 network_->pathName(net));
1597 NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
1598 while (pin_iter->hasNext()) {
1599 const Pin *pin = pin_iter->next();
1600 if (network_->isDriver(pin)) {
1601 sta::reduceToPiElmore(parasitic, pin, ap->couplingCapFactor(),
1602 op_cond, corner, cnst_min_max, ap, this);
1603 }
1604 }
1605 delete pin_iter;
1606 }
1607
1608 void
reduceToPiElmore(Parasitic * parasitic,const Pin * drvr_pin,const OperatingConditions * op_cond,const Corner * corner,const MinMax * cnst_min_max,const ParasiticAnalysisPt * ap)1609 ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
1610 const Pin *drvr_pin,
1611 const OperatingConditions *op_cond,
1612 const Corner *corner,
1613 const MinMax *cnst_min_max,
1614 const ParasiticAnalysisPt *ap)
1615 {
1616 sta::reduceToPiElmore(parasitic, drvr_pin, ap->couplingCapFactor(),
1617 op_cond, corner, cnst_min_max, ap, this);
1618 }
1619
1620 void
reduceToPiPoleResidue2(Parasitic * parasitic,const Net * net,const OperatingConditions * op_cond,const Corner * corner,const MinMax * cnst_min_max,const ParasiticAnalysisPt * ap)1621 ConcreteParasitics::reduceToPiPoleResidue2(Parasitic *parasitic,
1622 const Net *net,
1623 const OperatingConditions *op_cond,
1624 const Corner *corner,
1625 const MinMax *cnst_min_max,
1626 const ParasiticAnalysisPt *ap)
1627 {
1628 debugPrint(debug_, "parasitic_reduce", 1, "Reduce net %s",
1629 network_->pathName(net));
1630 NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
1631 while (pin_iter->hasNext()) {
1632 const Pin *pin = pin_iter->next();
1633 if (network_->isDriver(pin))
1634 sta::reduceToPiPoleResidue2(parasitic, pin, ap->couplingCapFactor(),
1635 op_cond, corner, cnst_min_max, ap, this);
1636 }
1637 delete pin_iter;
1638 }
1639
1640 void
reduceToPiPoleResidue2(Parasitic * parasitic,const Pin * drvr_pin,const OperatingConditions * op_cond,const Corner * corner,const MinMax * cnst_min_max,const ParasiticAnalysisPt * ap)1641 ConcreteParasitics::reduceToPiPoleResidue2(Parasitic *parasitic,
1642 const Pin *drvr_pin,
1643 const OperatingConditions *op_cond,
1644 const Corner *corner,
1645 const MinMax *cnst_min_max,
1646 const ParasiticAnalysisPt *ap)
1647 {
1648 sta::reduceToPiPoleResidue2(parasitic, drvr_pin,
1649 ap->couplingCapFactor(),
1650 op_cond, corner, cnst_min_max,
1651 ap, this);
1652 }
1653
1654 ////////////////////////////////////////////////////////////////
1655
1656 Parasitic *
estimatePiElmore(const Pin * drvr_pin,const RiseFall * rf,const Wireload * wireload,float fanout,float net_pin_cap,const OperatingConditions * op_cond,const Corner * corner,const MinMax * min_max,const ParasiticAnalysisPt *)1657 ConcreteParasitics::estimatePiElmore(const Pin *drvr_pin,
1658 const RiseFall *rf,
1659 const Wireload *wireload,
1660 float fanout,
1661 float net_pin_cap,
1662 const OperatingConditions *op_cond,
1663 const Corner *corner,
1664 const MinMax *min_max,
1665 const ParasiticAnalysisPt *)
1666 {
1667 float c2, rpi, c1, elmore_res, elmore_cap;
1668 bool elmore_use_load_cap;
1669 estimatePiElmore(drvr_pin, rf, wireload, fanout, net_pin_cap,
1670 op_cond, corner, min_max, this,
1671 c2, rpi, c1,
1672 elmore_res, elmore_cap, elmore_use_load_cap);
1673
1674 if (c1 > 0.0 || c2 > 0.0)
1675 return new ConcretePiElmoreEstimated(c2, rpi, c1, elmore_res, elmore_cap,
1676 elmore_use_load_cap,
1677 rf, op_cond, corner, min_max,
1678 sdc_);
1679 else
1680 return nullptr;
1681 }
1682
1683 ////////////////////////////////////////////////////////////////
1684
1685 ConcreteParasiticDeviceSeqIterator::
ConcreteParasiticDeviceSeqIterator(ConcreteParasiticDeviceSeq * devices)1686 ConcreteParasiticDeviceSeqIterator(ConcreteParasiticDeviceSeq *devices) :
1687 iter_(devices)
1688 {
1689 }
1690
1691 ConcreteParasiticDeviceSetIterator::
ConcreteParasiticDeviceSetIterator(ConcreteParasiticDeviceSet * devices)1692 ConcreteParasiticDeviceSetIterator(ConcreteParasiticDeviceSet *devices) :
1693 iter_(devices)
1694 {
1695 }
1696
~ConcreteParasiticDeviceSetIterator()1697 ConcreteParasiticDeviceSetIterator::~ConcreteParasiticDeviceSetIterator()
1698 {
1699 delete iter_.container();
1700 }
1701
1702 ConcreteParasiticNodeSeqIterator::
ConcreteParasiticNodeSeqIterator(ConcreteParasiticNodeSeq * nodes)1703 ConcreteParasiticNodeSeqIterator(ConcreteParasiticNodeSeq *nodes) :
1704 iter_(nodes)
1705 {
1706 }
1707
~ConcreteParasiticNodeSeqIterator()1708 ConcreteParasiticNodeSeqIterator::~ConcreteParasiticNodeSeqIterator()
1709 {
1710 delete iter_.container();
1711 }
1712
1713 } // namespace
1714