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