1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #include <wire.h>
34 
35 #include <map>
36 #include <vector>
37 
38 #include "rcx/extRCap.h"
39 #include "rcx/extSpef.h"
40 #include "utl/Logger.h"
41 
42 #define MAXINT 0x7FFFFFFF;
43 //#define HI_ACC_10312011
44 
45 #define DEBUG_NET_ID 228157
46 
47 namespace rcx {
48 
49 #ifdef DEBUG_NET_ID
50 FILE* fp;
51 #endif
52 
53 using utl::RCX;
54 
55 using odb::dbBlock;
56 using odb::dbBox;
57 using odb::dbBTerm;
58 using odb::dbCapNode;
59 using odb::dbCCSeg;
60 using odb::dbChip;
61 using odb::dbNet;
62 using odb::dbRSeg;
63 using odb::dbSet;
64 using odb::dbShape;
65 using odb::dbSigType;
66 using odb::dbTech;
67 using odb::dbTechLayer;
68 using odb::dbTechLayerDir;
69 using odb::dbTechLayerType;
70 using odb::dbWire;
71 using odb::dbWirePath;
72 using odb::dbWirePathItr;
73 using odb::dbWirePathShape;
74 using odb::ISdb;
75 using odb::Rect;
76 using odb::ZPtr;
77 
print_RC(dbRSeg * rc)78 void extMain::print_RC(dbRSeg* rc) {
79   dbShape s;
80   dbWire* w = rc->getNet()->getWire();
81   w->getShape(rc->getShapeId(), s);
82   print_shape(s, rc->getSourceNode(), rc->getTargetNode());
83 }
print_shape(dbShape & shape,uint j1,uint j2)84 uint extMain::print_shape(dbShape& shape, uint j1, uint j2) {
85   uint dx = shape.xMax() - shape.xMin();
86   uint dy = shape.yMax() - shape.yMin();
87   if (shape.isVia()) {
88     dbTechVia* tech_via = shape.getTechVia();
89     std::string vname = tech_via->getName();
90 
91     logger_->info(RCX, 438, "VIA {} ( {} {} )  jids= ( {} {} )", vname.c_str(),
92                   shape.xMin() + dx / 2, shape.yMin() + dy / 2, j1, j2);
93   } else {
94     dbTechLayer* layer = shape.getTechLayer();
95     std::string lname = layer->getName();
96     logger_->info(RCX, 437, "RECT {} ( {} {} ) ( {} {} )  jids= ( {} {} )",
97                   lname.c_str(), shape.xMin(), shape.yMin(), shape.xMax(),
98                   shape.yMax(), j1, j2);
99 
100     if (dx < dy)
101       return dy;
102     else
103       return dx;
104   }
105   return 0;
106 }
107 
computePathDir(Point & p1,Point & p2,uint * length)108 uint extMain::computePathDir(Point& p1, Point& p2, uint* length) {
109   int len;
110   if (p2.getX() == p1.getX())
111     len = p2.getY() - p1.getY();
112   else
113     len = p2.getX() - p1.getX();
114 
115   if (len > 0) {
116     *length = len;
117     return 0;
118   } else {
119     *length = -len;
120     return 1;
121   }
122 }
123 
resetSumRCtable()124 void extMain::resetSumRCtable() {
125   _sumUpdated = 0;
126   _tmpSumCapTable[0] = 0.0;
127   _tmpSumResTable[0] = 0.0;
128   if (!_lefRC) {
129     for (uint ii = 1; ii < _metRCTable.getCnt(); ii++) {
130       _tmpSumCapTable[ii] = 0.0;
131       _tmpSumResTable[ii] = 0.0;
132     }
133   }
134 }
135 
addToSumRCtable()136 void extMain::addToSumRCtable() {
137   _sumUpdated = 1;
138   if (_lefRC) {
139     _tmpSumCapTable[0] += _tmpCapTable[0];
140     _tmpSumResTable[0] += _tmpResTable[0];
141   } else {
142     for (uint ii = 0; ii < _metRCTable.getCnt(); ii++) {
143       _tmpSumCapTable[ii] += _tmpCapTable[ii];
144       _tmpSumResTable[ii] += _tmpResTable[ii];
145     }
146   }
147 }
148 
copyToSumRCtable()149 void extMain::copyToSumRCtable() {
150   if (_lefRC) {
151     _tmpSumCapTable[0] = _tmpCapTable[0];
152     _tmpSumResTable[0] = _tmpResTable[0];
153   } else {
154     for (uint ii = 0; ii < _metRCTable.getCnt(); ii++) {
155       _tmpSumCapTable[ii] = _tmpCapTable[ii];
156       _tmpSumResTable[ii] = _tmpResTable[ii];
157     }
158   }
159 }
set_adjust_colinear(bool v)160 void extMain::set_adjust_colinear(bool v) { _adjust_colinear = v; }
161 
getViaResistance(dbTechVia * tvia)162 double extMain::getViaResistance(dbTechVia* tvia) {
163   // if (_viaResHash[tvia->getConstName()])
164   double res = 0;
165   dbSet<dbBox> boxes = tvia->getBoxes();
166   dbSet<dbBox>::iterator bitr;
167 
168   for (bitr = boxes.begin(); bitr != boxes.end(); ++bitr) {
169     dbBox* box = *bitr;
170     dbTechLayer* layer1 = box->getTechLayer();
171     if (layer1->getType() == dbTechLayerType::CUT)
172       res = layer1->getResistance();
173 
174     /* This works
175 
176     debug("EXT_RES",
177           "V",
178           "getViaResistance: {} {} %g ohms\n",
179           tvia->getConstName(),
180           layer1->getConstName(),
181           layer1->getResistance());
182 
183           */
184   }
185   return res;
186 }
getViaResistance_b(dbVia * tvia,dbNet * net)187 double extMain::getViaResistance_b(dbVia* tvia, dbNet* net) {
188   // if (_viaResHash[tvia->getConstName()])
189   double tot_res = 0;
190   dbSet<dbBox> boxes = tvia->getBoxes();
191   dbSet<dbBox>::iterator bitr;
192 
193   uint cutCnt = 0;
194   for (bitr = boxes.begin(); bitr != boxes.end(); ++bitr) {
195     dbBox* box = *bitr;
196     dbTechLayer* layer1 = box->getTechLayer();
197     if (layer1->getType() == dbTechLayerType::CUT) {
198       tot_res += layer1->getResistance();
199       cutCnt++;
200       // debug("EXT_RES", "R", "getViaResistance_b: {} {} {} %g ohms\n", cutCnt,
201       // tvia->getConstName(),  layer1->getConstName(),
202       // layer1->getResistance());
203     }
204   }
205   double Res = tot_res;
206   if (cutCnt > 1) {
207     float avgCutRes = tot_res / cutCnt;
208     Res = avgCutRes / cutCnt;
209   }
210   if (net != NULL && net->getId() == _debug_net_id) {
211     debugPrint(logger_, RCX, "extrules", 1,
212                "EXT_RES:"
213                "R"
214                "\tgetViaResistance_b: cutCnt= {} {}  {:g} ohms",
215                cutCnt, tvia->getConstName(), Res);
216   }
217   return Res;
218 }
219 
getViaCapacitance(dbShape svia,dbNet * net)220 void extMain::getViaCapacitance(dbShape svia, dbNet* net) {
221   bool USE_DB_UNITS = false;
222 
223   uint cnt = 0;
224 
225   const char* tcut = "tcut";
226   const char* bcut = "bcut";
227 
228   std::vector<dbShape> shapes;
229   dbShape::getViaBoxes(svia, shapes);
230 
231   int Width[32];
232   int Len[32];
233   int Level[32];
234   for (uint jj = 1; jj < 32; jj++) {
235     Level[jj] = 0;
236     Width[jj] = 0;
237     Len[jj] = 0;
238   }
239 
240   int maxLenBot = 0;
241   int maxWidthBot = 0;
242   int maxLenTop = 0;
243   int maxWidthTop = 0;
244 
245   int bot = 0;
246   int top = 1000;
247 
248   std::vector<dbShape>::iterator shape_itr;
249   for (shape_itr = shapes.begin(); shape_itr != shapes.end(); ++shape_itr) {
250     dbShape s = *shape_itr;
251 
252     if (s.getTechLayer()->getType() == dbTechLayerType::CUT)
253       continue;
254 
255     int x1 = s.xMin();
256     int y1 = s.yMin();
257     int x2 = s.xMax();
258     int y2 = s.yMax();
259     int dx = x2 - x1;
260     int dy = y2 - y1;
261     int width = MIN(dx, dy);
262     int len = MAX(dx, dy);
263 
264     uint level = s.getTechLayer()->getRoutingLevel();
265     if (Len[level] < len) {
266       Len[level] = len;
267       Width[level] = width;
268       Level[level] = level;
269     }
270     if (USE_DB_UNITS) {
271       width = GetDBcoords2(width);
272       len = GetDBcoords2(len);
273     }
274 
275     if (net->getId() == _debug_net_id) {
276       debugPrint(logger_, RCX, "extrules", 1,
277                  "VIA_CAP:"
278                  "C"
279                  "\tgetViaCapacitance: {} {}   {} {}  M{}  W {}  LEN {} n{}",
280                  x1, x2, y1, y2, level, width, len, _debug_net_id);
281     }
282   }
283   for (uint jj = 1; jj < 32; jj++) {
284     if (Level[jj] == 0)
285       continue;
286 
287     int w = Width[jj];
288     int len = Len[jj];
289 
290     if (USE_DB_UNITS) {
291       w = GetDBcoords2(w);
292       len = GetDBcoords2(len);
293     }
294     for (uint ii = 0; ii < _metRCTable.getCnt(); ii++) {
295       double areaCap;
296       double c1 = getFringe(jj, w, ii, areaCap);
297 
298       _tmpCapTable[ii] = len * 2 * c1;
299       if (net->getId() == _debug_net_id) {
300         debugPrint(logger_, RCX, "extrules", 1,
301                    "VIA_CAP:"
302                    "C"
303                    "\tgetViaCapacitance: M{}  W {}  LEN {} eC={:.3f} tC={:.3f} "
304                    " {} n{}",
305                    jj, w, len, c1, _tmpCapTable[ii], ii, _debug_net_id);
306       }
307     }
308   }
309 }
310 
getShapeRC(dbNet * net,dbShape & s,Point & prevPoint,dbWirePathShape & pshape)311 void extMain::getShapeRC(dbNet* net, dbShape& s, Point& prevPoint,
312                          dbWirePathShape& pshape) {
313   bool USE_DB_UNITS = false;
314   double res = 0.0;
315   double areaCap;
316   uint len;
317   uint level = 0;
318   if (s.isVia()) {
319     uint width = 0;
320     dbTechVia* tvia = s.getTechVia();
321     if (tvia != NULL) {
322       int i = 0;
323       level = tvia->getBottomLayer()->getRoutingLevel();
324       width = tvia->getBottomLayer()->getWidth();
325       res = tvia->getResistance();
326       if (res == 0)
327         res = getViaResistance(tvia);
328       if (res > 0)
329         tvia->setResistance(res);
330       if (res <= 0.0)
331         res = getResistance(level, width, width, 0);
332     } else {
333       dbVia* bvia = s.getVia();
334       if (bvia != NULL) {
335         level = bvia->getBottomLayer()->getRoutingLevel();
336         width = bvia->getBottomLayer()->getWidth();
337         len = width;
338         res = getViaResistance_b(bvia, net);
339 
340         if (res <= 0.0)
341           res = getResistance(level, width, len, 0);
342       }
343     }
344     if (level > 0) {
345       if (_lefRC) {
346         _tmpCapTable[0] = width * 2 * getFringe(level, width, 0, areaCap);
347         _tmpCapTable[0] += 2 * areaCap * width * width;
348         _tmpResTable[0] = res;
349       } else {
350         getViaCapacitance(s, net);
351         for (uint ii = 0; ii < _metRCTable.getCnt(); ii++) {
352           //_tmpCapTable[ii] = width * 2 * getFringe(level, width, ii, areaCap);
353           //_tmpCapTable[ii] += 2 * areaCap * width * width;
354           _tmpResTable[ii] = res;
355         }
356       }
357     }
358   } else {
359     computePathDir(prevPoint, pshape.point, &len);
360     level = s.getTechLayer()->getRoutingLevel();
361     uint width = MIN(pshape.shape.xMax() - pshape.shape.xMin(),
362                      pshape.shape.yMax() - pshape.shape.yMin());
363     len = MAX(pshape.shape.xMax() - pshape.shape.xMin(),
364               pshape.shape.yMax() - pshape.shape.yMin());
365     if (_adjust_colinear) {
366       len -= width;
367       if (len <= 0)
368         len += width;
369     }
370 
371     if (_lefRC) {
372       double res = getResistance(level, width, len, 0);
373       ;
374       double unitCap = getFringe(level, width, 0, areaCap);
375       double tot = len * width * unitCap;
376       double frTot = len * 2 * unitCap;
377 
378       _tmpCapTable[0] = frTot;
379       _tmpCapTable[0] += 2 * areaCap * len * width;
380       _tmpResTable[0] = res;
381 
382     } else if (_lef_res) {
383       double res = getResistance(level, width, len, 0);
384       _tmpResTable[0] = res;
385     } else {
386       if (USE_DB_UNITS)
387         width = GetDBcoords2(width);
388       double SUB_MULT = 1.0;
389 
390       for (uint ii = 0; ii < _metRCTable.getCnt(); ii++) {
391         double c1 = getFringe(level, width, ii, areaCap);
392         c1 *= SUB_MULT;
393 #ifdef HI_ACC_10312011
394         if (width < 400)
395           _tmpCapTable[ii] =
396               (len + width) * 2 * getFringe(level, width, ii, areaCap);
397         else
398           _tmpCapTable[ii] = len * 2 * getFringe(level, width, ii, areaCap);
399 #else
400         if (USE_DB_UNITS)
401           len = GetDBcoords2(len);
402 
403         // DF 720	_tmpCapTable[ii]= len*2*c1;
404         _tmpCapTable[ii] = 0;
405 #endif
406         // _tmpCapTable[ii] += 2 * areaCap * len * width;
407         bool newResModel = true;
408         if (!newResModel) {
409           double r = getResistance(level, width, len, ii);
410           _tmpResTable[ii] = r;
411           _tmpResTable[ii] = 0;
412         } else {
413           double r = getResistance(level, width, len, ii);
414           _tmpResTable[ii] = r;
415         }
416       }
417     }
418   }
419   if (_shapeRcCnt >= 0) {
420     if (_printFile == NULL)
421       _printFile = fopen("shapeRc.1", "w");
422     _shapeRcCnt++;
423     fprintf(_printFile, "%d %g %g\n", _shapeRcCnt, _tmpCapTable[0],
424             _tmpResTable[0]);
425   }
426   if ((!s.isVia()) && (_couplingFlag > 0)) {
427     dbTechLayer* layer = s.getTechLayer();
428     uint level = layer->getRoutingLevel();
429 
430     int x1 = s.xMin();
431     int y1 = s.yMin();
432     int x2 = s.xMax();
433     int y2 = s.yMax();
434 
435     if (_usingMetalPlanes && !_alwaysNewGs)
436       _geomSeq->box(x1, y1, x2, y2, level);
437 
438     if (_useDbSdb) {
439       // net->getWire()->setProperty (pshape.junction_id, rc->getId());
440       if (_eco)
441         _extNetSDB->addBox(x1, y1, x2, y2, level, net->getId(),
442                            pshape.junction_id, _dbSignalId);
443     }
444     // else
445     // _extNetSDB->addBox(x1, y1, x2, y2, level, rc->getId(),
446     // pshape.junction_id, _dbSignalId);
447 
448     if (!_allNet) {
449       _ccMinX = MIN(x1, _ccMinX);
450       _ccMinY = MIN(y1, _ccMinY);
451       _ccMaxX = MAX(x2, _ccMaxX);
452       _ccMaxY = MAX(y2, _ccMaxY);
453     }
454   }
455   prevPoint = pshape.point;
456 }
457 
setResCapFromLef(dbRSeg * rc,uint targetCapId,dbShape & s,uint len)458 void extMain::setResCapFromLef(dbRSeg* rc, uint targetCapId, dbShape& s,
459                                uint len) {
460   double cap = 0.0;
461   double res = 0.0;
462 
463   if (s.isVia()) {
464     dbTechVia* via = s.getTechVia();
465 
466     res = via->getResistance();
467 
468     if (_couplingFlag == 0) {
469       uint n = via->getBottomLayer()->getRoutingLevel();
470       len = 2 * via->getBottomLayer()->getWidth();
471       cap = _modelTable->get(0)->getTotCapOverSub(n) * len;
472     }
473   } else {
474     uint level = s.getTechLayer()->getRoutingLevel();
475     res = _modelTable->get(0)->getRes(level) * len;
476 
477     // if (_couplingFlag==0)
478     cap = _modelTable->get(0)->getTotCapOverSub(level) * len;
479   }
480   for (uint ii = 0; ii < _extDbCnt; ii++) {
481     double xmult = 1.0 + 0.1 * ii;
482     rc->setResistance(xmult * res, ii);
483 
484     // if (_couplingFlag==0)
485     rc->setCapacitance(xmult * cap, ii);
486   }
487 }
setResAndCap(dbRSeg * rc,double * restbl,double * captbl)488 void extMain::setResAndCap(dbRSeg* rc, double* restbl, double* captbl) {
489   int pcdbIdx, sci, scdbIdx;
490   double res, cap;
491   if (_lefRC) {
492     res = _resModify ? restbl[0] * _resFactor : restbl[0];
493     rc->setResistance(res, 0);
494     cap = _gndcModify ? captbl[0] * _gndcFactor : captbl[0];
495     cap = _netGndcCalibration ? cap * _netGndcCalibFactor : cap;
496     rc->setCapacitance(cap, 0);
497     return;
498   }
499   // TO_TEST
500   for (uint ii = 0; ii < _extDbCnt; ii++) {
501     pcdbIdx = getProcessCornerDbIndex(ii);
502     res = _resModify ? restbl[ii] * _resFactor : restbl[ii];
503     rc->setResistance(res, pcdbIdx);
504     cap = _gndcModify ? captbl[ii] * _gndcFactor : captbl[ii];
505     cap = _netGndcCalibration ? cap * _netGndcCalibFactor : cap;
506     // DF 1120 rc->setCapacitance(cap, pcdbIdx);
507     getScaledCornerDbIndex(ii, sci, scdbIdx);
508     if (sci == -1)
509       continue;
510     getScaledRC(sci, res, cap);
511     rc->setResistance(res, scdbIdx);
512     rc->setCapacitance(cap, scdbIdx);
513   }
514   /*
515   for (uint ii= 1; ii<_extDbCnt; ii++)
516   {
517           double xmult = 1.0 + 0.1*ii;
518           rc->setResistance(xmult*res, ii);
519           // if (_couplingFlag==0)
520                   rc->setCapacitance(xmult*cap, ii);
521   }
522   */
523 }
524 
resetMapping(dbBTerm * bterm,dbITerm * iterm,uint junction)525 void extMain::resetMapping(dbBTerm* bterm, dbITerm* iterm, uint junction) {
526   if (bterm != NULL) {
527     _btermTable->set(bterm->getId(), 0);
528   } else if (iterm != NULL) {
529     _itermTable->set(iterm->getId(), 0);
530   }
531   _nodeTable->set(junction, 0);
532 }
setBranchCapNodeId(dbNet * net,uint junction)533 void extMain::setBranchCapNodeId(dbNet* net, uint junction) {
534   int capId = _nodeTable->geti(junction);
535   if (capId != 0)
536     return;
537 
538   dbCapNode* cap = dbCapNode::create(net, 0, _foreign);
539 
540   cap->setInternalFlag();
541   cap->setBranchFlag();
542 
543   cap->setNode(junction);
544 
545   capId = cap->getId();
546 
547   _nodeTable->set(junction, -capId);
548   return;
549 }
550 
isTermPathEnded(dbBTerm * bterm,dbITerm * iterm)551 bool extMain::isTermPathEnded(dbBTerm* bterm, dbITerm* iterm) {
552   int ttttcvbs = 0;
553   dbNet* net;
554   if (bterm) {
555     net = bterm->getNet();
556     if (bterm->isSetMark()) {
557       if (ttttcvbs)
558         logger_->info(RCX, 108, "Net {} multiple-ended at bterm {}",
559                       net->getId(), bterm->getId());
560       return true;
561     }
562     _connectedBTerm.push_back(bterm);
563     bterm->setMark(1);
564   } else if (iterm) {
565     net = iterm->getNet();
566     if (iterm->isSetMark()) {
567       if (ttttcvbs)
568         logger_->info(RCX, 109, "Net {} multiple-ended at iterm {}",
569                       net->getId(), iterm->getId());
570       return true;
571     }
572     _connectedITerm.push_back(iterm);
573     iterm->setMark(1);
574   }
575   return false;
576 }
577 
getCapNodeId(dbNet * net,dbBTerm * bterm,dbITerm * iterm,uint junction,bool branch)578 uint extMain::getCapNodeId(dbNet* net, dbBTerm* bterm, dbITerm* iterm,
579                            uint junction, bool branch) {
580   if (iterm != NULL) {
581     uint id = iterm->getId();
582     uint capId = _itermTable->geti(id);
583     if (capId > 0) {
584 #ifdef DEBUG_NET_ID
585       if (iterm->getNet()->getId() == DEBUG_NET_ID)
586         fprintf(fp, "\tOLD I_TERM %d  capNode %d\n", id, capId);
587 #endif
588       //(dbCapNode::getCapNode(_block, capId))->incrChildrenCnt();
589 
590       return capId;
591     }
592     dbCapNode* cap = dbCapNode::create(net, 0, _foreign);
593 
594     cap->setNode(iterm->getId());
595     cap->setITermFlag();
596 
597     capId = cap->getId();
598 
599     _itermTable->set(id, capId);
600     int tcapId = _nodeTable->geti(junction) == -1 ? -capId : capId;
601     _nodeTable->set(junction, tcapId);  // allow get capId using junction
602 #ifdef DEBUG_NET_ID
603     if (iterm->getNet()->getId() == DEBUG_NET_ID)
604       fprintf(fp, "\tNEW I_TERM %d capNode %d\n", id, capId);
605 #endif
606     return capId;
607   } else if (bterm != NULL) {
608     uint id = bterm->getId();
609     uint capId = _btermTable->geti(id);
610     if (capId > 0) {
611 //(dbCapNode::getCapNode(_block, capId))->incrChildrenCnt();
612 #ifdef DEBUG_NET_ID
613       if (bterm->getNet()->getId() == DEBUG_NET_ID)
614         fprintf(fp, "\tOLD B_TERM %d  capNode %d\n", id, capId);
615 #endif
616       return capId;
617     }
618 
619     dbCapNode* cap = dbCapNode::create(net, 0, _foreign);
620 
621     cap->setNode(bterm->getId());
622     cap->setBTermFlag();
623     // cap->incrChildrenCnt();
624 
625     capId = cap->getId();
626 
627     _btermTable->set(id, capId);
628     int tcapId = _nodeTable->geti(junction) == -1 ? -capId : capId;
629     _nodeTable->set(junction, tcapId);  // allow get capId using junction
630 
631 #ifdef DEBUG_NET_ID
632     if (bterm->getNet()->getId() == DEBUG_NET_ID)
633       fprintf(fp, "\tNEW B_TERM %d  capNode %d\n", id, capId);
634 #endif
635     return capId;
636   } else {
637     int capId = _nodeTable->geti(junction);
638     if (capId != 0 && capId != -1) {
639       capId = abs(capId);
640       dbCapNode* cap = dbCapNode::getCapNode(_block, capId);
641       // cap->incrChildrenCnt();
642       if (branch) {
643         cap->setBranchFlag();
644       }
645       if (cap->getNet()->getId() == _debug_net_id) {
646         if (branch) {
647           if (cap->getNet()->getId() == DEBUG_NET_ID)
648             debugPrint(logger_, RCX, "rcseg", 1,
649                        "RCSEG:"
650                        "C"
651                        "\tOLD BRANCH {}  capNode {}",
652                        junction, cap->getId());
653         } else {
654           if (cap->getNet()->getId() == DEBUG_NET_ID)
655             debugPrint(logger_, RCX, "rcseg", 1,
656                        "RCSEG"
657                        "C"
658                        "\tOLD INTERNAL {}  capNode {}",
659                        junction, cap->getId());
660         }
661       }
662       return capId;
663     }
664 
665     dbCapNode* cap = dbCapNode::create(net, 0, _foreign);
666 
667     cap->setInternalFlag();
668     //		if (branch)
669     //			cap->setBranchFlag();
670 
671     cap->setNode(junction);
672 
673     if (capId == -1) {
674       // cap->incrChildrenCnt();
675       if (branch)
676         cap->setBranchFlag();
677     }
678     if (cap->getNet()->getId() == DEBUG_NET_ID) {
679       if (branch) {
680         debugPrint(logger_, RCX, "rcseg", 1,
681                    "RCSEG:"
682                    "C"
683                    "\tNEW BRANCH {}  capNode {}",
684                    junction, cap->getId());
685       } else
686         debugPrint(logger_, RCX, "rcseg", 1,
687                    "RCSEG:"
688                    "C"
689                    "\tNEW INTERNAL {}  capNode {}",
690                    junction, cap->getId());
691     }
692 
693     uint ncapId = cap->getId();
694     int tcapId = capId == 0 ? ncapId : -ncapId;
695     _nodeTable->set(junction, tcapId);
696     return ncapId;
697   }
698 }
resetMapNodes(dbNet * net)699 uint extMain::resetMapNodes(dbNet* net) {
700   //	uint rcCnt= 0;
701   //	uint netId= net->getId();
702 
703   dbWire* wire = net->getWire();
704   if (wire == NULL) {
705     if (_reportNetNoWire)
706       logger_->info(RCX, 110, "Net {} has no wires.", net->getName().c_str());
707     _netNoWireCnt++;
708     return 0;
709   }
710   uint cnt = 0;
711 
712   dbWirePath path;
713   dbWirePathShape pshape;
714 
715   dbWirePathItr pitr;
716 
717   for (pitr.begin(wire); pitr.getNextPath(path);) {
718     resetMapping(path.bterm, path.iterm, path.junction_id);
719 
720     while (pitr.getNextShape(pshape)) {
721       resetMapping(pshape.bterm, pshape.iterm, pshape.junction_id);
722       cnt++;
723     }
724   }
725   return cnt;
726 }
addRSeg(dbNet * net,std::vector<uint> & rsegJid,uint & srcId,Point & prevPoint,dbWirePath & path,dbWirePathShape & pshape,bool isBranch,double * restbl,double * captbl)727 dbRSeg* extMain::addRSeg(dbNet* net, std::vector<uint>& rsegJid, uint& srcId,
728                          Point& prevPoint, dbWirePath& path,
729                          dbWirePathShape& pshape, bool isBranch, double* restbl,
730                          double* captbl) {
731   // if (!path.iterm && !path.bterm &&isTermPathEnded(pshape.bterm,
732   // pshape.iterm))
733   if (!path.bterm && isTermPathEnded(pshape.bterm, pshape.iterm)) {
734     rsegJid.clear();
735     return NULL;
736   }
737   uint jidl = rsegJid.size();
738   // assert (jidl>0);
739   uint dstId = getCapNodeId(net, pshape.bterm, pshape.iterm, pshape.junction_id,
740                             isBranch);
741   if (dstId == srcId) {
742     char tname[200];
743     tname[0] = '\0';
744     if (pshape.bterm)
745       sprintf(&tname[0], ", on bterm %d %s", pshape.bterm->getId(),
746               (char*)pshape.bterm->getConstName());
747     else if (pshape.iterm)
748       sprintf(&tname[0], ", on iterm %d %s/%s", pshape.iterm->getId(),
749               (char*)pshape.iterm->getInst()->getConstName(),
750               (char*)pshape.iterm->getMTerm()->getConstName());
751     logger_->warn(RCX, 111, "Net {} {} has a loop at x={} y={} {}.",
752                   net->getId(), (char*)net->getConstName(), pshape.point.getX(),
753                   pshape.point.getY(), &tname[0]);
754     return NULL;
755   }
756 
757   if (net->getId() == _debug_net_id)
758     print_shape(pshape.shape, srcId, dstId);
759 
760   uint length;
761   uint pathDir = computePathDir(prevPoint, pshape.point, &length);
762   int jx = 0;
763   int jy = 0;
764   if (pshape.junction_id)
765     net->getWire()->getCoord((int)pshape.junction_id, jx, jy);
766   dbRSeg* rc = dbRSeg::create(net, jx, jy, pathDir, true);
767   // dbRSeg::setRSeg(rc, net, pshape.junction_id, pathDir, true);
768 
769   uint rsid = rc->getId();
770   for (uint jj = 0; jj < jidl; jj++)
771     net->getWire()->setProperty(rsegJid[jj], rsid);
772   rsegJid.clear();
773 
774   rc->setSourceNode(srcId);
775   rc->setTargetNode(dstId);
776 
777   if (srcId > 0)
778     (dbCapNode::getCapNode(_block, srcId))->incrChildrenCnt();
779   if (dstId > 0)
780     (dbCapNode::getCapNode(_block, dstId))->incrChildrenCnt();
781 
782   setResAndCap(rc, restbl, captbl);
783 
784   if (net->getId() == _debug_net_id)
785     debugPrint(logger_, RCX, "rcseg", 1,
786                "RCSEG:"
787                "R"
788                "\tshapeId= {}  rseg= {}  ({} {}) {:g}",
789                pshape.junction_id, rsid, srcId, dstId, rc->getCapacitance(0));
790 
791   srcId = dstId;
792   prevPoint = pshape.point;
793   return rc;
794 }
getFirstShape(dbNet * net,dbShape & s)795 bool extMain::getFirstShape(dbNet* net, dbShape& s) {
796   dbWirePath path;
797   dbWirePathShape pshape;
798 
799   dbWirePathItr pitr;
800   dbWire* wire = net->getWire();
801 
802   bool status = false;
803   for (pitr.begin(wire); pitr.getNextPath(path);) {
804     pitr.getNextShape(pshape);
805     s = pshape.shape;
806     status = true;
807     break;
808   }
809   return status;
810 }
811 
getShortSrcJid(uint jid)812 uint extMain::getShortSrcJid(uint jid) {
813   for (uint jj = 0; jj < _shortTgtJid.size(); jj++) {
814     if (_shortTgtJid[jj] == jid)
815       return _shortSrcJid[jj];
816   }
817   return jid;
818 }
819 
markPathHeadTerm(dbWirePath & path)820 void extMain::markPathHeadTerm(dbWirePath& path) {
821   if (path.bterm) {
822     _connectedBTerm.push_back(path.bterm);
823     path.bterm->setMark(1);
824   } else if (path.iterm) {
825     _connectedITerm.push_back(path.iterm);
826     path.iterm->setMark(1);
827   }
828 }
829 
make1stRSeg(dbNet * net,dbWirePath & path,uint cnid,bool skipStartWarning)830 void extMain::make1stRSeg(dbNet* net, dbWirePath& path, uint cnid,
831                           bool skipStartWarning) {
832   int tx = 0;
833   int ty = 0;
834   if (path.bterm) {
835     if (!path.bterm->getFirstPinLocation(tx, ty))
836       logger_->error(RCX, 112, "Can't locate bterm {}",
837                      path.bterm->getConstName());
838   } else if (path.iterm) {
839     if (!path.iterm->getAvgXY(&tx, &ty))
840       logger_->error(RCX, 113, "Can't locate iterm {}/{} ( {} )",
841                      path.iterm->getInst()->getConstName(),
842                      path.iterm->getMTerm()->getConstName(),
843                      path.iterm->getInst()->getMaster()->getConstName());
844   } else if (!skipStartWarning)
845     logger_->warn(RCX, 114,
846                   "Net {} {} does not start from an iterm or a bterm.",
847                   net->getId(), net->getConstName());
848   if (net->get1stRSegId())
849     logger_->error(RCX, 115, "Net {} {} already has rseg!", net->getId(),
850                    net->getConstName());
851   dbRSeg* rc = dbRSeg::create(net, tx, ty, 0, true);
852   rc->setTargetNode(cnid);
853 }
854 
makeNetRCsegs(dbNet * net,bool skipStartWarning)855 uint extMain::makeNetRCsegs(dbNet* net, bool skipStartWarning) {
856   //_debug= true;
857   net->setRCgraph(true);
858 
859   // uint netId= net->getId();
860 
861   uint rcCnt1 = resetMapNodes(net);
862   if (rcCnt1 <= 0)
863     return 0;
864 
865   _netGndcCalibFactor = net->getGndcCalibFactor();
866   _netGndcCalibration = _netGndcCalibFactor == 1.0 ? false : true;
867   uint rcCnt = 0;
868   dbWirePath path;
869   dbWirePathShape pshape, ppshape;
870   Point prevPoint, sprevPoint;
871 
872   // std::vector<uint> rsegJid;
873   _rsegJid.clear();
874   _shortSrcJid.clear();
875   _shortTgtJid.clear();
876 
877   dbWirePathItr pitr;
878   dbWire* wire = net->getWire();
879   uint srcId, srcJid;
880 
881   uint netId = net->getId();
882 #ifdef DEBUG_NET_ID
883   if (netId == DEBUG_NET_ID) {
884     fp = fopen("rsegs", "w");
885     fprintf(fp, "BEGIN NET %d %d\n", netId, path.junction_id);
886   }
887 #endif
888   if (netId == _debug_net_id) {
889     debugPrint(logger_, RCX, "rcseg", 1,
890                "RCSEG:"
891                "R "
892                "makeNetRCsegs: BEGIN NET {} {}",
893                netId, path.junction_id);
894   }
895 
896   if (_mergeResBound != 0.0 || _mergeViaRes) {
897     for (pitr.begin(wire); pitr.getNextPath(path);) {
898       if (!path.bterm && !path.iterm && path.is_branch && path.junction_id)
899         _nodeTable->set(path.junction_id, -1);
900       // setBranchCapNodeId(net, path.junction_id);
901 
902       if (path.is_short)  // wfs 090106
903       {
904         _nodeTable->set(path.short_junction, -1);
905         srcJid = path.short_junction;
906         for (uint tt = 0; tt < _shortTgtJid.size(); tt++) {
907           if (_shortTgtJid[tt] == srcJid) {
908             srcJid = _shortSrcJid[tt];  // forward short
909             break;
910           }
911         }
912         _shortSrcJid.push_back(srcJid);
913         _shortTgtJid.push_back(path.junction_id);
914       }
915       while (pitr.getNextShape(pshape))
916         ;
917     }
918   }
919   bool netHeadMarked = false;
920   for (pitr.begin(wire); pitr.getNextPath(path);) {
921     if (netId == _debug_net_id)
922       debugPrint(logger_, RCX, "rcseg", 1,
923                  "RCSEG:"
924                  "R "
925                  "makeNetRCsegs:  path.junction_id {}",
926                  path.junction_id);
927 
928     if (!path.iterm && !path.bterm && !path.is_branch && path.is_short)
929       srcId =
930           getCapNodeId(net, NULL, NULL, getShortSrcJid(path.junction_id), true);
931     else
932       srcId = getCapNodeId(net, path.bterm, path.iterm,
933                            getShortSrcJid(path.junction_id), path.is_branch);
934     if (!netHeadMarked) {
935       netHeadMarked = true;
936       // markPathHeadTerm(path); // may call markPathHeadTerm() later
937       make1stRSeg(net, path, srcId, skipStartWarning);
938     }
939 
940     // srcId= getCapNodeId(net, path.bterm, path.iterm, path.junction_id,
941     // path.is_branch);
942 
943     // wfs 090106, adding 0.0001 rseg for short
944     // if (!path.iterm && !path.bterm && !path.is_branch && path.is_short) {
945     //  uint shortId = getCapNodeId(net, NULL, NULL, path.short_junction, true);
946     //  dbRSeg *rc= dbRSeg::create(net, path.junction_id, 0, true);
947     //  rc->setSourceNode(shortId);
948     //  rc->setTargetNode(srcId);
949     //  srcId = shortId;
950     //  for (int jj=0;jj<_extDbCnt;jj++) {
951     //    rc->setResistance(0.0001,jj);
952     //    rc->setCapacitance(0.0,jj);
953     //  }
954 
955     bool ADD_VIA_JUNCTION = false;
956     prevPoint = path.point;
957     sprevPoint = prevPoint;
958     resetSumRCtable();
959     while (pitr.getNextShape(pshape)) {
960       dbShape s = pshape.shape;
961 
962       if (netId == _debug_net_id) {
963         if (s.isVia()) {
964           debugPrint(logger_, RCX, "rcseg", 1,
965                      "RCSEG:"
966                      "R "
967                      "makeNetRCsegs: {} VIA",
968                      pshape.junction_id);
969         } else
970           debugPrint(logger_, RCX, "rcseg", 1,
971                      "RCSEG:"
972                      "R "
973                      "makeNetRCsegs: {} WIRE",
974                      pshape.junction_id);
975       }
976 
977       getShapeRC(net, s, sprevPoint, pshape);
978       if (_mergeResBound == 0.0) {
979         if (!s.isVia())
980           _rsegJid.push_back(pshape.junction_id);
981         else if (ADD_VIA_JUNCTION)
982           _rsegJid.push_back(pshape.junction_id);
983 
984         addToSumRCtable();
985 
986         if (!_mergeViaRes || !s.isVia() || pshape.bterm || pshape.iterm ||
987             _nodeTable->geti(pshape.junction_id) < 0) {
988           dbRSeg* rc =
989               addRSeg(net, _rsegJid, srcId, prevPoint, path, pshape,
990                       path.is_branch, _tmpSumResTable, _tmpSumCapTable);
991           if (s.isVia() && rc != NULL) {
992             // seg->_flags->_spare_bits_29=1;
993             createShapeProperty(net, pshape.junction_id, rc->getId());
994           }
995           resetSumRCtable();
996           rcCnt++;
997         } else
998           ppshape = pshape;
999         continue;
1000       }
1001       if (_tmpResTable[0] >= _mergeResBound && _tmpSumResTable[0] == 0.0) {
1002         if (!s.isVia())
1003           _rsegJid.push_back(pshape.junction_id);
1004         addRSeg(net, _rsegJid, srcId, prevPoint, path, pshape, path.is_branch,
1005                 _tmpResTable, _tmpCapTable);
1006         rcCnt++;
1007         continue;
1008       }
1009       if ((_tmpResTable[0] + _tmpSumResTable[0]) >= _mergeResBound) {
1010         addRSeg(net, _rsegJid, srcId, prevPoint, path, ppshape, path.is_branch,
1011                 _tmpSumResTable, _tmpSumCapTable);
1012         rcCnt++;
1013         if (!s.isVia())
1014           _rsegJid.push_back(pshape.junction_id);
1015         copyToSumRCtable();
1016       } else {
1017         if (!s.isVia())
1018           _rsegJid.push_back(pshape.junction_id);
1019         addToSumRCtable();
1020       }
1021       if (pshape.bterm || pshape.iterm ||
1022           _nodeTable->geti(pshape.junction_id) < 0 ||
1023           _tmpSumResTable[0] >= _mergeResBound) {
1024         addRSeg(net, _rsegJid, srcId, prevPoint, path, pshape, path.is_branch,
1025                 _tmpSumResTable, _tmpSumCapTable);
1026         rcCnt++;
1027         resetSumRCtable();
1028       } else
1029         ppshape = pshape;
1030     }
1031     // if (_tmpSumResTable[0] != 0.0 || _tmpSumCapTable[0] != 0.0)
1032     // if (_tmpSumResTable[0] != 0.0)
1033     if (_sumUpdated) {
1034       addRSeg(net, _rsegJid, srcId, prevPoint, path, ppshape, path.is_branch,
1035               _tmpSumResTable, _tmpSumCapTable);
1036       rcCnt++;
1037     }
1038   }
1039   dbSet<dbRSeg> rSet = net->getRSegs();
1040   rSet.reverse();
1041 
1042 #ifdef DEBUG_NET_ID
1043   if (netId == DEBUG_NET_ID) {
1044     fprintf(fp, "END NET %d\n", netId);
1045     fclose(fp);
1046   }
1047 #endif
1048 
1049   return rcCnt;
1050 }
1051 
createShapeProperty(dbNet * net,int id,int id_val)1052 void extMain::createShapeProperty(dbNet* net, int id, int id_val) {
1053   char buff[64];
1054   sprintf(buff, "%d", id);
1055   char const* pchar = strdup(buff);
1056   dbIntProperty::create(net, pchar, id_val);
1057   sprintf(buff, "RC_%d", id_val);
1058   pchar = strdup(buff);
1059   dbIntProperty::create(net, pchar, id);
1060 }
getShapeProperty(dbNet * net,int id)1061 int extMain::getShapeProperty(dbNet* net, int id) {
1062   char buff[64];
1063   sprintf(buff, "%d", id);
1064   char const* pchar = strdup(buff);
1065   dbIntProperty* p = dbIntProperty::find(net, pchar);
1066   if (p == NULL)
1067     return 0;
1068   int rcid = p->getValue();
1069   return rcid;
1070 }
getShapeProperty_rc(dbNet * net,int rc_id)1071 int extMain::getShapeProperty_rc(dbNet* net, int rc_id) {
1072   char buff[64];
1073   sprintf(buff, "RC_%d", rc_id);
1074   char const* pchar = strdup(buff);
1075   dbIntProperty* p = dbIntProperty::find(net, pchar);
1076   if (p == NULL)
1077     return 0;
1078   int sid = p->getValue();
1079   return sid;
1080 }
1081 
getExtBbox(int * x1,int * y1,int * x2,int * y2)1082 uint extMain::getExtBbox(int* x1, int* y1, int* x2, int* y2) {
1083   *x1 = _x1;
1084   *x2 = _x2;
1085   *y1 = _y1;
1086   *y2 = _y2;
1087 
1088   return 0;
1089 }
getExtAreaCoords(const char * bbox)1090 bool extMain::getExtAreaCoords(const char* bbox) {
1091   /*
1092   const char * token = strtok( bbox, " \t\n" );
1093       const char * busbitchars = strtok(NULL, "\"");
1094 */
1095   return false;
1096 }
getCcSdb()1097 ZPtr<ISdb> extMain::getCcSdb() { return _extCcapSDB; }
getNetSdb()1098 ZPtr<ISdb> extMain::getNetSdb() { return _extNetSDB; }
setExtractionBbox(const char * bbox)1099 void extMain::setExtractionBbox(const char* bbox) {
1100   if ((bbox == NULL) || (strcmp(bbox, "") == 0)) {
1101     Rect r;
1102     _block->getDieArea(r);
1103     _x1 = r.xMin();
1104     _y1 = r.yMin();
1105     _x2 = r.xMax();
1106     _y2 = r.yMax();
1107 
1108     _extNetSDB->setMaxArea(_x1, _y1, _x2, _y2);
1109   }
1110 
1111   if (getExtAreaCoords(bbox))
1112     _extNetSDB->setMaxArea(_x1, _y1, _x2, _y2);
1113   else {
1114     Rect r;
1115     _block->getDieArea(r);
1116 
1117     _x1 = r.xMin();
1118     _y1 = r.yMin();
1119     _x2 = r.xMax();
1120     _y2 = r.yMax();
1121 
1122     _extNetSDB->setMaxArea(_x1, _y1, _x2, _y2);
1123   }
1124 }
1125 
setupSearchDb(const char * bbox,uint debug,ZInterface * Interface)1126 uint extMain::setupSearchDb(const char* bbox, uint debug,
1127                             ZInterface* Interface) {
1128   if (_couplingFlag == 0)
1129     return 0;
1130   // Ath__overlapAdjust overlapAdj = Z_endAdjust;
1131   Ath__overlapAdjust overlapAdj = Z_noAdjust;
1132   if (_reExtract) {
1133     if (_extNetSDB == NULL || _extNetSDB->getSearchPtr() == NULL) {
1134       logger_->info(RCX, 116, "No existing extraction sdb. Can't reExtract.");
1135       return 0;
1136     }
1137     _extNetSDB->setExtControl(
1138         _block, _useDbSdb, (uint)overlapAdj, _CCnoPowerSource, _CCnoPowerTarget,
1139         _ccUp, _allNet, _ccContextDepth, _ccContextArray, _ccContextLength,
1140         _dgContextArray, &_dgContextDepth, &_dgContextPlanes, &_dgContextTracks,
1141         &_dgContextBaseLvl, &_dgContextLowLvl, &_dgContextHiLvl,
1142         _dgContextBaseTrack, _dgContextLowTrack, _dgContextHiTrack,
1143         _dgContextTrackBase, _seqPool);
1144     //		if (_reExtCcapSDB && _reExtCcapSDB->getSearchPtr())
1145     //			_reExtCcapSDB->cleanSdb();
1146     //		else
1147     //		{
1148     //			if (adsNewComponent( Interface->_context, ZCID(Sdb),
1149     //_reExtCcapSDB
1150     //)!= Z_OK)
1151     //			{
1152     //				assert(0);
1153     //			}
1154     //			ZALLOCATED(_reExtCcapSDB);
1155     //		}
1156     //
1157     //		_reExtCcapSDB->initSearchForNets(_tech, _block);
1158     //		_reExtCcapSDB->setDefaultWireType(_CCsegId);
1159     return 0;
1160   }
1161   if (adsNewComponent(Interface->_context, ZCID(Sdb), _extNetSDB) != Z_OK) {
1162     assert(0);
1163   }
1164   ZALLOCATED(_extNetSDB);
1165 
1166   _extNetSDB->initSearchForNets(_tech, _block);
1167 
1168   setExtractionBbox(bbox);
1169 
1170   if (_couplingFlag > 1)
1171     _extNetSDB->setExtControl(
1172         _block, _useDbSdb, (uint)overlapAdj, _CCnoPowerSource, _CCnoPowerTarget,
1173         _ccUp, _allNet, _ccContextDepth, _ccContextArray, _ccContextLength,
1174         _dgContextArray, &_dgContextDepth, &_dgContextPlanes, &_dgContextTracks,
1175         &_dgContextBaseLvl, &_dgContextLowLvl, &_dgContextHiLvl,
1176         _dgContextBaseTrack, _dgContextLowTrack, _dgContextHiTrack,
1177         _dgContextTrackBase, _seqPool);
1178   if (!_CCnoPowerSource && !_CCnoPowerTarget)
1179     _extNetSDB->addPowerNets(_block, _dbPowerId, true);
1180   // TODO-EXT: add obstructions
1181 
1182   if (_debug && (_couplingFlag > 1)) {
1183     if (adsNewComponent(Interface->_context, ZCID(Sdb), _extCcapSDB) != Z_OK) {
1184       assert(0);
1185     }
1186     ZALLOCATED(_extCcapSDB);
1187 
1188     _extCcapSDB->initSearchForNets(_tech, _block);
1189     _extCcapSDB->setDefaultWireType(_CCsegId);
1190   }
1191 
1192   return 0;
1193 }
1194 
removeSdb(std::vector<dbNet * > & nets)1195 void extMain::removeSdb(std::vector<dbNet*>& nets) {
1196   if (_extNetSDB == NULL || _extNetSDB->getSearchPtr() == NULL)
1197     return;
1198   dbNet::markNets(nets, _block, true);
1199   _extNetSDB->removeMarkedNetWires();
1200   dbNet::markNets(nets, _block, false);
1201 }
1202 
removeCC(std::vector<dbNet * > & nets)1203 void extMain::removeCC(std::vector<dbNet*>& nets) {
1204   for (uint ii = 0; ii < 15; ii++)
1205     logger_->warn(RCX, 255, "Need to CODE removeCC.");
1206   /*
1207           int cnt = 0;
1208           bool destroyOnlySrc;
1209           dbNet *net;
1210           dbSet<dbNet> bnet = _block->getNets();
1211           dbSet<dbNet>::iterator nitr;
1212           if (nets.size() == 0)
1213           {
1214                   destroyOnlySrc = true;
1215                   for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1216                   {
1217                           net = (dbNet *) *nitr;
1218                           cnt += net->destroyCCSegs(destroyOnlySrc);
1219                   }
1220                   notice (0, "delete {} CC segments.\n", cnt);
1221                   return;
1222           }
1223           int j;
1224           for (j=0;j<nets.size();j++)
1225           {
1226                   net = nets[j];
1227                   net->setMark(true);
1228                   net->selectCCSegs();
1229           }
1230           for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1231           {
1232                   net = (dbNet *) *nitr;
1233                   if (net->isSelect()==false)
1234                           continue;
1235                   net->setSelect(false);
1236                   net->detachSelectedCCSegs();
1237           }
1238           destroyOnlySrc = false;
1239           for (j=0;j<nets.size();j++)
1240           {
1241                   net = nets[j];
1242                   net->setMark(false);
1243                   cnt += net->destroyCCSegs(destroyOnlySrc);
1244           }
1245           notice (0, "delete {} CC segments.\n", cnt);
1246   */
1247 }
1248 
1249 /*
1250 void extMain::unlinkCC(std::vector<dbNet *> & nets)
1251 {
1252         int cnt = 0;
1253         bool destroyOnlySrc;
1254         dbNet *net;
1255         dbSet<dbNet> bnet = _block->getNets();
1256         dbSet<dbNet>::iterator nitr;
1257         if (nets.size() == 0)
1258         {
1259                 destroyOnlySrc = true;
1260                 for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1261                 {
1262                         net = (dbNet *) *nitr;
1263                         net->unlinkCCSegs();
1264                         cnt++;
1265                 }
1266                 notice (0, "unlink CC segments of {} nets.\n", cnt);
1267                 return;
1268         }
1269         int j;
1270         for (j=0;j<nets.size();j++)
1271         {
1272                 net = nets[j];
1273                 net->setMark(true);
1274                 net->selectCCSegs();
1275         }
1276         for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1277         {
1278                 net = (dbNet *) *nitr;
1279                 if (net->isSelect()==false)
1280                         continue;
1281                 net->setSelect(false);
1282                 net->detachSelectedCCSegs();
1283         }
1284         destroyOnlySrc = false;
1285         for (j=0;j<nets.size();j++)
1286         {
1287                 net = nets[j];
1288                 net->setMark(false);
1289                 net->unlinkCCSegs();
1290                 cnt++;
1291         }
1292         notice (0, "unlink CC segments of {} nets.\n", cnt);
1293 }
1294 
1295 void extMain::removeCapNode(std::vector<dbNet *> & nets)
1296 {
1297         int j;
1298         int cnt = 0;
1299         dbNet *net;
1300         dbSet<dbNet> bnet = _block->getNets();
1301         dbSet<dbNet>::iterator nitr;
1302         if (nets.size() == 0)
1303         {
1304                 for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1305                 {
1306                         net = (dbNet *) *nitr;
1307                         cnt += net->destroyCapNodes();
1308                 }
1309                 notice (0, "delete {} Cap Nodes.\n", cnt);
1310                 return;
1311         }
1312         for (j=0;j<nets.size();j++)
1313         {
1314                 net = nets[j];
1315                 cnt += net->destroyCapNodes();
1316         }
1317         notice (0, "delete {} Cap Nodes.\n", cnt);
1318 }
1319 
1320 void extMain::unlinkCapNode(std::vector<dbNet *> & nets)
1321 {
1322         int j;
1323         int cnt = 0;
1324         dbNet *net;
1325         dbSet<dbNet> bnet = _block->getNets();
1326         dbSet<dbNet>::iterator nitr;
1327         if (nets.size() == 0)
1328         {
1329                 for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1330                 {
1331                         net = (dbNet *) *nitr;
1332                         net->unlinkCapNodes();
1333                         cnt++;
1334                 }
1335                 notice (0, "delete {} Cap Nodes.\n", cnt);
1336                 return;
1337         }
1338         for (j=0;j<nets.size();j++)
1339         {
1340                 net = nets[j];
1341                 net->unlinkCapNodes();
1342                 cnt++;
1343         }
1344         notice (0, "unlink Cap Nodes of {} nets.\n", cnt);
1345 }
1346 
1347 void extMain::removeRSeg(std::vector<dbNet *> & nets)
1348 {
1349         int j;
1350         int cnt = 0;
1351         dbNet *net;
1352         dbSet<dbNet> bnet = _block->getNets();
1353         dbSet<dbNet>::iterator nitr;
1354         if (nets.size() == 0)
1355         {
1356                 for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1357                 {
1358                         net = (dbNet *) *nitr;
1359                         cnt += net->destroyRSegs();
1360                 }
1361                 notice (0, "delete {} RC segments.\n", cnt);
1362                 return;
1363         }
1364         for (j=0;j<nets.size();j++)
1365         {
1366                 net = nets[j];
1367                 cnt += net->destroyRSegs();
1368         }
1369         notice (0, "delete {} RC segments.\n", cnt);
1370 }
1371 
1372 void extMain::unlinkRSeg(std::vector<dbNet *> & nets)
1373 {
1374         int j;
1375         int cnt = 0;
1376         dbNet *net;
1377         dbSet<dbNet> bnet = _block->getNets();
1378         dbSet<dbNet>::iterator nitr;
1379         if (nets.size() == 0)
1380         {
1381                 for( nitr = bnet.begin(); nitr != bnet.end(); ++nitr)
1382                 {
1383                         net = (dbNet *) *nitr;
1384                         net->unlinkRSegs();
1385                         cnt++;
1386                 }
1387                 notice (0, "unlink RC segments of {} nets.\n", cnt);
1388                 return;
1389         }
1390         for (j=0;j<nets.size();j++)
1391         {
1392                 net = nets[j];
1393                 net->unlinkRSegs();
1394                 cnt++;
1395         }
1396         notice (0, "unlink RC segments of {} nets.\n", cnt);
1397 }
1398 */
removeExt(std::vector<dbNet * > & nets)1399 void extMain::removeExt(std::vector<dbNet*>& nets) {
1400   // removeSdb (nets);
1401   _block->destroyParasitics(nets);
1402   // removeCC (nets);
1403   // removeRSeg (nets);
1404   // removeCapNode (nets);
1405   _extracted = false;
1406   if (_spef)
1407     _spef->reinit();
1408 }
removeExt()1409 void extMain::removeExt() {
1410   std::vector<dbNet*> rnets;
1411   dbSet<dbNet> bnets = _block->getNets();
1412   dbSet<dbNet>::iterator net_itr;
1413   dbNet* net;
1414   for (net_itr = bnets.begin(); net_itr != bnets.end(); ++net_itr) {
1415     net = *net_itr;
1416     dbSigType type = net->getSigType();
1417     if ((type == dbSigType::POWER) || (type == dbSigType::GROUND))
1418       continue;
1419     rnets.push_back(net);
1420   }
1421   removeExt(rnets);
1422 }
1423 /*
1424 void extMain::unlinkExt(std::vector<dbNet *> & nets)
1425 {
1426         unlinkCC (nets);
1427         unlinkRSeg (nets);
1428         unlinkCapNode (nets);
1429         _extracted = false;
1430         if (_spef)
1431                 _spef->reinit();
1432 }
1433 */
v_printWireNeighbor(void * ip,uint met,void * v_swire,void * v_topNeighbor,void * v_botNeighbor)1434 void v_printWireNeighbor(void* ip, uint met, void* v_swire, void* v_topNeighbor,
1435                          void* v_botNeighbor) {}
1436 void extCompute(CoupleOptions& inputTable, void* extModel);
1437 void extCompute1(CoupleOptions& inputTable, void* extModel);
1438 
readCmpStats(const char * name,uint & tileSize,int & X1,int & Y1,int & X2,int & Y2)1439 uint extMain::readCmpStats(const char* name, uint& tileSize, int& X1, int& Y1,
1440                            int& X2, int& Y2) {
1441   int x1 = X1;
1442   int y1 = Y1;
1443   int x2 = X2;
1444   int y2 = Y2;
1445   uint lcnt = 0;
1446   Ath__parser parser;
1447   FILE* fp = fopen(name, "r");
1448   if (fp == NULL) {
1449     logger_->warn(RCX, 373, "Can't open file {}.", name);
1450     return 0;
1451   }
1452   bool simple_flavor = false;
1453   uint nm = 1000;
1454   parser.setInputFP(fp);
1455   while (parser.parseNextLine() > 0) {
1456     if (parser.isKeyword(0, "VERSION")) {
1457       if (parser.isKeyword(1, "alpha"))
1458         simple_flavor = true;
1459 
1460       continue;
1461     }
1462     if (parser.isKeyword(0, "BLOCK")) {
1463       continue;
1464     }
1465     if (parser.isKeyword(0, "TILE_SIZE")) {
1466       tileSize = parser.getInt(1);
1467       continue;
1468     }
1469     if (parser.isKeyword(0, "BEGIN") && parser.isKeyword(1, "LAYER_MAPPING")) {
1470       while (parser.parseNextLine() > 0) {
1471         if (!parser.isKeyword(0, "END")) {
1472           continue;
1473         }
1474         break;
1475       }
1476       continue;
1477     }
1478     if (parser.isKeyword(0, "BEGIN") &&
1479         (simple_flavor || parser.isKeyword(2, "("))) {
1480       lcnt++;
1481       while (parser.parseNextLine() > 0) {
1482         if (parser.isKeyword(0, "END"))
1483           break;
1484 
1485         int X = Ath__double2int(parser.getDouble(0) * nm);
1486         int Y = Ath__double2int(parser.getDouble(1) * nm);
1487         x1 = MIN(x1, X);
1488         y1 = MIN(y1, Y);
1489         x2 = MAX(x2, X);
1490         y2 = MAX(y2, Y);
1491       }
1492       break;
1493     }
1494   }
1495   X1 = x1;
1496   Y1 = y1;
1497   X2 = x2;
1498   Y2 = y2;
1499   // fclose(fp);
1500   return lcnt;
1501 }
1502 
readCmpFile(const char * name)1503 uint extMain::readCmpFile(const char* name) {
1504   logger_->info(RCX, 117, "Read CMP file {} ...", name);
1505 
1506   uint tileSize;
1507   int X1 = MAXINT;
1508   int Y1 = MAXINT;
1509   int X2 = -MAXINT;
1510   int Y2 = -MAXINT;
1511   readCmpStats(name, tileSize, X1, Y1, X2, Y2);
1512 
1513   uint lefLayerCnt = 20;  // need an API here
1514   _geoThickTable = new extGeoThickTable* [lefLayerCnt + 1];
1515   for (uint ii = 0; ii <= lefLayerCnt; ii++)
1516     _geoThickTable[ii] = NULL;
1517 
1518   Ath__array1D<double> widthTable;
1519   Ath__array1D<double> B;
1520 
1521   bool simple_flavor = false;
1522   double angstrom2nm = 0.0001;
1523 
1524   uint lCnt = 0;
1525   uint cnt = 0;
1526   Ath__parser parser1;
1527   // parser1.addSeparator("\r");
1528   parser1.openFile((char*)name);
1529   while (parser1.parseNextLine() > 0) {
1530     if (parser1.isKeyword(0, "VERSION")) {
1531       if (parser1.isKeyword(1, "alpha"))
1532         simple_flavor = true;
1533 
1534       continue;
1535     }
1536     if (parser1.isKeyword(0, "BLOCK")) {
1537       continue;
1538     }
1539     if (parser1.isKeyword(0, "TILE_SIZE")) {
1540       continue;
1541     }
1542     if (parser1.isKeyword(0, "BEGIN") &&
1543         parser1.isKeyword(1, "LAYER_MAPPING")) {
1544       while (parser1.parseNextLine() > 0) {
1545         if (!parser1.isKeyword(0, "END")) {
1546           continue;
1547         }
1548         break;
1549       }
1550       continue;
1551     }
1552     if (parser1.isKeyword(0, "BEGIN") &&
1553         (simple_flavor || parser1.isKeyword(2, "("))) {
1554       lCnt++;
1555       uint level = lCnt;
1556       double nominalThickness = 0.5;
1557       char* layerName = NULL;
1558       if (simple_flavor) {
1559         layerName = parser1.get(1);
1560         nominalThickness = parser1.getDouble(2) * angstrom2nm;
1561         dbTechLayer* techLayer = _tech->findLayer(layerName);
1562         if (techLayer == NULL) {
1563           logger_->error(RCX, 118,
1564                          "Can't find the corresponding LEF layer for <{}>",
1565                          layerName);
1566         }
1567         level = techLayer->getRoutingLevel();
1568       }
1569       widthTable.resetCnt();
1570       parser1.getDoubleArray(&widthTable, 3);
1571       _geoThickTable[level] =
1572           new extGeoThickTable(X1, Y1, X2, Y2, tileSize, &widthTable, 1);
1573 
1574       uint nm = 1000;
1575       parser1.printWords(stdout);
1576       while (parser1.parseNextLine() > 0) {
1577         if (parser1.isKeyword(0, "END"))
1578           break;
1579 
1580         cnt++;
1581         // parser1.printWords(stdout);
1582         int X = Ath__double2int(parser1.getDouble(0) * nm);
1583         int Y = Ath__double2int(parser1.getDouble(1) * nm);
1584 
1585         double th = 0.0;
1586         double ild = 0.0;
1587 
1588         if (!simple_flavor) {
1589           th = parser1.getDouble(2);
1590           ild = parser1.getDouble(3);
1591         } else {
1592           th = nominalThickness;
1593         }
1594 
1595         B.resetCnt();
1596         if (simple_flavor)
1597           parser1.getDoubleArray(&B, 4, angstrom2nm);
1598         else
1599           parser1.getDoubleArray(&B, 4);
1600 
1601         _geoThickTable[lCnt]
1602             ->addVarTable(X, Y, th, ild, &B, simple_flavor, simple_flavor);
1603       }
1604       break;
1605     }
1606   }
1607   logger_->info(
1608       RCX, 119,
1609       "Finished reading {} variability tiles of size {} nm die: ({} {}) ({} "
1610       "{}) {}",
1611       cnt, tileSize, X1, Y1, X2, Y2, name);
1612 
1613   return cnt;
1614 }
setMinTypMax(bool min,bool typ,bool max,const char * cmp_file,bool density_model,bool litho,int setMin,int setTyp,int setMax,uint extDbCnt)1615 int extMain::setMinTypMax(bool min, bool typ, bool max, const char* cmp_file,
1616                           bool density_model, bool litho, int setMin,
1617                           int setTyp, int setMax, uint extDbCnt) {
1618   _modelMap.resetCnt(0);
1619   _metRCTable.resetCnt(0);
1620   _currentModel = NULL;
1621   if (cmp_file != NULL) {
1622     readCmpFile(cmp_file);
1623     _currentModel = getRCmodel(0);
1624     for (uint ii = 0; ii < 2; ii++) {
1625       _modelMap.add(0);
1626       _metRCTable.add(_currentModel->getMetRCTable(0));
1627     }
1628     if (!_eco)
1629       _block->setCornerCount(2);
1630     _extDbCnt = 2;
1631   } else if (extDbCnt > 1) {  // extract first <extDbCnt>
1632     if (!_eco)
1633       _block->setCornerCount(extDbCnt);
1634     _extDbCnt = extDbCnt;
1635     //		uint cnt= 0;
1636 
1637     int dbIndex = -1;
1638     dbIndex = _modelMap.add(_minModelIndex);
1639     //_block->setExtMinCorner(dbIndex);
1640 
1641     dbIndex = _modelMap.add(_typModelIndex);
1642     //_block->setExtTypCorner(dbIndex);
1643 
1644     if (extDbCnt > 2) {
1645       dbIndex = _modelMap.add(_maxModelIndex);
1646       //_block->setExtMaxCorner(dbIndex);
1647     }
1648   } else if (min || max || typ) {
1649     int dbIndex = -1;
1650     if (min) {
1651       dbIndex = _modelMap.add(_minModelIndex);
1652       //_block->setExtMinCorner(dbIndex);
1653     }
1654     if (typ) {
1655       dbIndex = _modelMap.add(_typModelIndex);
1656       //_block->setExtTypCorner(dbIndex);
1657     }
1658     if (max) {
1659       dbIndex = _modelMap.add(_maxModelIndex);
1660       //_block->setExtMaxCorner(dbIndex);
1661     }
1662     _extDbCnt = _modelMap.getCnt();
1663 
1664     if (!_eco)
1665       _block->setCornerCount(_extDbCnt);
1666   } else if ((setMin >= 0) || (setMax >= 0) || (setTyp >= 0)) {
1667     int dbIndex = -1;
1668     if (setMin >= 0) {
1669       dbIndex = _modelMap.add(setMin);
1670       //_block->setExtMinCorner(dbIndex);
1671     }
1672     if (setTyp >= 0) {
1673       dbIndex = _modelMap.add(setTyp);
1674       //_block->setExtMinCorner(dbIndex);
1675     }
1676     if (setMax >= 0) {
1677       dbIndex = _modelMap.add(setMax);
1678       //_block->setExtMinCorner(dbIndex);
1679     }
1680     _extDbCnt = _modelMap.getCnt();
1681 
1682     if (!_eco)
1683       _block->setCornerCount(_extDbCnt);
1684   } else if (extDbCnt == 1) {  // extract first <extDbCnt>
1685     if (!_eco)
1686       _block->setCornerCount(extDbCnt);
1687     _extDbCnt = extDbCnt;
1688     _modelMap.add(0);
1689     //_block->setExtMaxCorner(dbIndex);
1690   } else if (density_model) {
1691   } else if (litho) {
1692   }
1693 
1694   if (_currentModel == NULL) {
1695     _currentModel = getRCmodel(0);
1696     // for (uint ii= 0; (_couplingFlag>0) && (!_lefRC) && ii<_modelMap.getCnt();
1697     // ii++) {
1698     for (uint ii = 0; (!_lefRC) && ii < _modelMap.getCnt(); ii++) {
1699       uint jj = _modelMap.get(ii);
1700       _metRCTable.add(_currentModel->getMetRCTable(jj));
1701     }
1702   }
1703   _cornerCnt = _extDbCnt;  // the Cnt's are the same in the old flow
1704 
1705   return 0;
1706 }
extCorner()1707 extCorner::extCorner() {
1708   _name = NULL;
1709   _model = 0;
1710   _dbIndex = -1;
1711   _scaledCornerIdx = -1;
1712   _resFactor = 1.0;
1713   _ccFactor = 1.0;
1714   _gndFactor = 1.0;
1715 }
getExtractedCorners()1716 void extMain::getExtractedCorners() {
1717   if (_prevControl == NULL)
1718     return;
1719   if (_prevControl->_extractedCornerList == NULL)
1720     return;
1721   if (_processCornerTable != NULL)
1722     return;
1723 
1724   Ath__parser parser;
1725   uint pCornerCnt = parser.mkWords(_prevControl->_extractedCornerList, " ");
1726   if (pCornerCnt <= 0)
1727     return;
1728 
1729   _processCornerTable = new Ath__array1D<extCorner*>();
1730 
1731   uint cornerCnt = 0;
1732   uint ii, jj;
1733   char cName[128];
1734   for (ii = 0; ii < pCornerCnt; ii++) {
1735     extCorner* t = new extCorner();
1736     t->_model = parser.getInt(ii);
1737 
1738     t->_dbIndex = cornerCnt++;
1739     _processCornerTable->add(t);
1740   }
1741 
1742   if (_prevControl->_derivedCornerList == NULL) {
1743     makeCornerMapFromExtControl();
1744     return;
1745   }
1746 
1747   uint sCornerCnt = parser.mkWords(_prevControl->_derivedCornerList, " ");
1748   if (sCornerCnt <= 0)
1749     return;
1750 
1751   if (_scaledCornerTable == NULL)
1752     _scaledCornerTable = new Ath__array1D<extCorner*>();
1753 
1754   for (ii = 0; ii < sCornerCnt; ii++) {
1755     extCorner* t = new extCorner();
1756     t->_model = parser.getInt(ii);
1757     for (jj = 0; jj < pCornerCnt; jj++) {
1758       if (t->_model != _processCornerTable->get(jj)->_model)
1759         continue;
1760       t->_extCornerPtr = _processCornerTable->get(jj);
1761       break;
1762     }
1763     _block->getExtCornerName(pCornerCnt + ii, &cName[0]);
1764     if (jj == pCornerCnt)
1765       logger_->warn(RCX, 120,
1766                     "No matching process corner for scaled corner {}, model {}",
1767                     &cName[0], t->_model);
1768     t->_dbIndex = cornerCnt++;
1769     _scaledCornerTable->add(t);
1770   }
1771   Ath__array1D<double> A;
1772 
1773   parser.mkWords(_prevControl->_resFactorList, " ");
1774   parser.getDoubleArray(&A, 0);
1775   for (ii = 0; ii < sCornerCnt; ii++) {
1776     extCorner* t = _scaledCornerTable->get(ii);
1777     t->_resFactor = A.get(ii);
1778   }
1779   parser.mkWords(_prevControl->_ccFactorList, " ");
1780   A.resetCnt();
1781   parser.getDoubleArray(&A, 0);
1782   for (ii = 0; ii < sCornerCnt; ii++) {
1783     extCorner* t = _scaledCornerTable->get(ii);
1784     t->_ccFactor = A.get(ii);
1785   }
1786   parser.mkWords(_prevControl->_gndcFactorList, " ");
1787   A.resetCnt();
1788   parser.getDoubleArray(&A, 0);
1789   for (ii = 0; ii < sCornerCnt; ii++) {
1790     extCorner* t = _scaledCornerTable->get(ii);
1791     t->_gndFactor = A.get(ii);
1792   }
1793   makeCornerMapFromExtControl();
1794 }
makeCornerMapFromExtControl()1795 void extMain::makeCornerMapFromExtControl() {
1796   if (_prevControl->_cornerIndexList == NULL)
1797     return;
1798   if (_processCornerTable == NULL)
1799     return;
1800   // if (_scaledCornerTable==NULL)
1801   //	return;
1802 
1803   Ath__parser parser;
1804   uint wordCnt = parser.mkWords(_prevControl->_cornerIndexList, " ");
1805   if (wordCnt <= 0)
1806     return;
1807 
1808   char cName[128];
1809   for (uint ii = 0; ii < wordCnt; ii++) {
1810     int index = parser.getInt(ii);
1811     extCorner* t = NULL;
1812     if (index > 0) {  // extracted corner
1813       t = _processCornerTable->get(index - 1);
1814       t->_dbIndex = ii;
1815     } else {
1816       t = _scaledCornerTable->get((-index) - 1);
1817     }
1818     t->_dbIndex = ii;
1819     _block->getExtCornerName(ii, &cName[0]);
1820     t->_name = strdup(&cName[0]);
1821   }
1822 }
addRCCorner(const char * name,int model,int userDefined)1823 char* extMain::addRCCorner(const char* name, int model, int userDefined) {
1824   _remote = 0;
1825   if (model >= 100) {
1826     _remote = 1;
1827     model = model - 100;
1828   }
1829   if (_processCornerTable == NULL)
1830     _processCornerTable = new Ath__array1D<extCorner*>();
1831 
1832   uint ii = 0;
1833   for (; ii < _processCornerTable->getCnt(); ii++) {
1834     extCorner* s = _processCornerTable->get(ii);
1835     if (s->_model == model) {
1836       logger_->info(
1837           RCX, 433,
1838           "A process corner {} for Extraction RC Model {} has already been "
1839           "defined, skipping definition",
1840           s->_name, model);
1841       return NULL;
1842     }
1843   }
1844   extCorner* t = new extCorner();
1845   t->_model = model;
1846   t->_dbIndex = _cornerCnt++;
1847   _processCornerTable->add(t);
1848   if (name != NULL)
1849     t->_name = strdup(name);
1850   else {
1851     char buff[16];
1852     sprintf(buff, "MinMax%d", model);
1853     t->_name = strdup(buff);
1854   }
1855   t->_extCornerPtr = NULL;
1856 
1857   if (userDefined == 1)
1858     logger_->info(RCX, 431, "Defined process_corner {} with ext_model_index {}",
1859                   t->_name, model);
1860   else if (userDefined == 0)
1861     logger_->info(RCX, 434,
1862                   "Defined process_corner {} with ext_model_index {} (using "
1863                   "extRulesFile defaults)",
1864                   t->_name, model);
1865 
1866   if (!_remote)
1867     makeCornerNameMap();
1868   return t->_name;
1869 }
addRCCornerScaled(const char * name,uint model,float resFactor,float ccFactor,float gndFactor)1870 char* extMain::addRCCornerScaled(const char* name, uint model, float resFactor,
1871                                  float ccFactor, float gndFactor) {
1872   if (_processCornerTable == NULL) {
1873     logger_->info(
1874         RCX, 472,
1875         "The corresponding process corner has to be defined using the "
1876         "command <define_process_corner>");
1877     return NULL;
1878   }
1879 
1880   uint jj = 0;
1881   extCorner* pc = NULL;
1882   for (; jj < _processCornerTable->getCnt(); jj++) {
1883     pc = _processCornerTable->get(jj);
1884     if (pc->_model == (int)model)
1885       break;
1886   }
1887   if (jj == _processCornerTable->getCnt()) {
1888     logger_->info(
1889         RCX, 121,
1890         "The corresponding process corner has to be defined using the "
1891         "command <define_process_corner>");
1892     return NULL;
1893   }
1894   if (_scaledCornerTable == NULL)
1895     _scaledCornerTable = new Ath__array1D<extCorner*>();
1896 
1897   uint ii = 0;
1898   for (; ii < _scaledCornerTable->getCnt(); ii++) {
1899     extCorner* s = _scaledCornerTable->get(ii);
1900 
1901     if ((name != NULL) && (strcmp(s->_name, name) == 0)) {
1902       // if (s->_model==model) {
1903       logger_->info(
1904           RCX, 122,
1905           "A process corner for Extraction RC Model {} has already been "
1906           "defined, skipping definition",
1907           model);
1908       return NULL;
1909     }
1910   }
1911   pc->_scaledCornerIdx = _scaledCornerTable->getCnt();
1912   extCorner* t = new extCorner();
1913   t->_model = model;
1914   t->_dbIndex = _cornerCnt++;
1915   t->_resFactor = resFactor;
1916   t->_ccFactor = ccFactor;
1917   t->_gndFactor = gndFactor;
1918   t->_extCornerPtr = pc;
1919 
1920   _scaledCornerTable->add(t);
1921   if (name != NULL)
1922     t->_name = strdup(name);
1923   else {
1924     char buff[16];
1925     sprintf(buff, "derived_MinMax%d", model);
1926     t->_name = strdup(buff);
1927   }
1928   makeCornerNameMap();
1929   return t->_name;
1930 }
cleanCornerTables()1931 void extMain::cleanCornerTables() {
1932   if (_scaledCornerTable != NULL) {
1933     for (uint ii = 0; ii < _scaledCornerTable->getCnt(); ii++) {
1934       extCorner* s = _scaledCornerTable->get(ii);
1935 
1936       free(s->_name);
1937       delete s;
1938     }
1939     delete _scaledCornerTable;
1940   }
1941   _scaledCornerTable = NULL;
1942   if (_processCornerTable != NULL) {
1943     for (uint ii = 0; ii < _processCornerTable->getCnt(); ii++) {
1944       extCorner* s = _processCornerTable->get(ii);
1945 
1946       free(s->_name);
1947       delete s;
1948     }
1949     delete _processCornerTable;
1950   }
1951   _processCornerTable = NULL;
1952 }
1953 
getProcessCornerDbIndex(int pcidx)1954 int extMain::getProcessCornerDbIndex(int pcidx) {
1955   if (_processCornerTable == NULL)
1956     return pcidx;
1957   assert(pcidx >= 0 && pcidx < (int)_processCornerTable->getCnt());
1958   return (_processCornerTable->get(pcidx)->_dbIndex);
1959 }
1960 
getScaledCornerDbIndex(int pcidx,int & scidx,int & scdbIdx)1961 void extMain::getScaledCornerDbIndex(int pcidx, int& scidx, int& scdbIdx) {
1962   scidx = -1;
1963   if (_batchScaleExt || _processCornerTable == NULL)
1964     return;
1965   assert(pcidx >= 0 && pcidx < (int)_processCornerTable->getCnt());
1966   scidx = _processCornerTable->get(pcidx)->_scaledCornerIdx;
1967   if (scidx != -1)
1968     scdbIdx = _scaledCornerTable->get(scidx)->_dbIndex;
1969 }
1970 
getScaledRC(int sidx,double & res,double & cap)1971 void extMain::getScaledRC(int sidx, double& res, double& cap) {
1972   extCorner* sc = _scaledCornerTable->get(sidx);
1973   res = sc->_resFactor == 1.0 ? res : res * sc->_resFactor;
1974   cap = sc->_gndFactor == 1.0 ? cap : cap * sc->_gndFactor;
1975 }
1976 
getScaledGndC(int sidx,double & cap)1977 void extMain::getScaledGndC(int sidx, double& cap) {
1978   extCorner* sc = _scaledCornerTable->get(sidx);
1979   cap = sc->_gndFactor == 1.0 ? cap : cap * sc->_gndFactor;
1980 }
1981 
getScaledCC(int sidx,double & cap)1982 void extMain::getScaledCC(int sidx, double& cap) {
1983   extCorner* sc = _scaledCornerTable->get(sidx);
1984   cap = sc->_ccFactor == 1.0 ? cap : cap * sc->_ccFactor;
1985 }
1986 
deleteCorners()1987 void extMain::deleteCorners() {
1988   cleanCornerTables();
1989   _block->setCornerCount(1);
1990 }
1991 
getCorners(std::list<std::string> & ecl)1992 void extMain::getCorners(std::list<std::string>& ecl) {
1993   char buffer[64];
1994   uint ii;
1995   for (ii = 0; _processCornerTable && ii < _processCornerTable->getCnt();
1996        ii++) {
1997     std::string s1c("");
1998     extCorner* ec = _processCornerTable->get(ii);
1999     sprintf(buffer, "%s %d %d", ec->_name, ec->_model + 1, ec->_dbIndex);
2000     s1c += buffer;
2001     ecl.push_back(s1c);
2002   }
2003   for (ii = 0; _scaledCornerTable && ii < _scaledCornerTable->getCnt(); ii++) {
2004     std::string s1c("");
2005     extCorner* ec = _scaledCornerTable->get(ii);
2006     sprintf(buffer, "%s %d %d", ec->_name, -(ec->_model + 1), ec->_dbIndex);
2007     s1c += buffer;
2008     ecl.push_back(s1c);
2009   }
2010 }
2011 
getDbCornerIndex(const char * name)2012 int extMain::getDbCornerIndex(const char* name) {
2013   if (_scaledCornerTable != NULL) {
2014     for (uint ii = 0; ii < _scaledCornerTable->getCnt(); ii++) {
2015       extCorner* s = _scaledCornerTable->get(ii);
2016 
2017       if (strcmp(s->_name, name) == 0)
2018         return s->_dbIndex;
2019     }
2020   }
2021   if (_processCornerTable != NULL) {
2022     for (uint ii = 0; ii < _processCornerTable->getCnt(); ii++) {
2023       extCorner* s = _processCornerTable->get(ii);
2024 
2025       if (strcmp(s->_name, name) == 0)
2026         return s->_dbIndex;
2027     }
2028   }
2029   return -1;
2030 }
getDbCornerModel(const char * name)2031 int extMain::getDbCornerModel(const char* name) {
2032   if (_scaledCornerTable != NULL) {
2033     for (uint ii = 0; ii < _scaledCornerTable->getCnt(); ii++) {
2034       extCorner* s = _scaledCornerTable->get(ii);
2035 
2036       if (strcmp(s->_name, name) == 0)
2037         return s->_model;
2038     }
2039   }
2040   if (_processCornerTable != NULL) {
2041     for (uint ii = 0; ii < _processCornerTable->getCnt(); ii++) {
2042       extCorner* s = _processCornerTable->get(ii);
2043 
2044       if (strcmp(s->_name, name) == 0)
2045         return s->_model;
2046     }
2047   }
2048   return -1;
2049 }
2050 // void extMain::makeCornerNameMap(char *buff, int cornerCnt, bool spef)
makeCornerNameMap()2051 void extMain::makeCornerNameMap() {
2052   // This function updates the dbExtControl object and
2053   // creates the corner information to be stored at dbBlock object
2054 
2055   int A[128];
2056   extCorner** map = new extCorner* [_cornerCnt];
2057   for (uint jj = 0; jj < _cornerCnt; jj++) {
2058     map[jj] = NULL;
2059     A[jj] = 0;
2060   }
2061 
2062   char cornerList[128];
2063   strcpy(cornerList, "");
2064 
2065   if (_scaledCornerTable != NULL) {
2066     char extList[128];
2067     char resList[128];
2068     char ccList[128];
2069     char gndcList[128];
2070     strcpy(extList, "");
2071     strcpy(ccList, "");
2072     strcpy(resList, "");
2073     strcpy(gndcList, "");
2074     for (uint ii = 0; ii < _scaledCornerTable->getCnt(); ii++) {
2075       extCorner* s = _scaledCornerTable->get(ii);
2076 
2077       // if (spef) {
2078       //	map[s->_model]= s;
2079       //	A[s->_model]= -(ii+1);
2080       //}
2081       // else {
2082       //	map[s->_dbIndex]= s;
2083       //	A[s->_dbIndex]= -(ii+1);
2084       //}
2085       map[s->_dbIndex] = s;
2086       A[s->_dbIndex] = -(ii + 1);
2087 
2088       sprintf(extList, "%s %d", extList, s->_model);
2089       sprintf(resList, "%s %g", resList, s->_resFactor);
2090       sprintf(ccList, "%s %g", ccList, s->_ccFactor);
2091       sprintf(gndcList, "%s %g", gndcList, s->_gndFactor);
2092     }
2093     if (_prevControl->_derivedCornerList)
2094       free(_prevControl->_derivedCornerList);
2095     if (_prevControl->_resFactorList)
2096       free(_prevControl->_resFactorList);
2097     if (_prevControl->_ccFactorList)
2098       free(_prevControl->_ccFactorList);
2099     if (_prevControl->_gndcFactorList)
2100       free(_prevControl->_gndcFactorList);
2101     _prevControl->_derivedCornerList = strdup(extList);
2102     _prevControl->_resFactorList = strdup(resList);
2103     _prevControl->_ccFactorList = strdup(ccList);
2104     _prevControl->_gndcFactorList = strdup(gndcList);
2105   }
2106   if (_processCornerTable != NULL) {
2107     char extList[128];
2108     strcpy(extList, "");
2109 
2110     for (uint ii = 0; ii < _processCornerTable->getCnt(); ii++) {
2111       extCorner* s = _processCornerTable->get(ii);
2112 
2113       // if (spef) {
2114       //	A[s->_model]= ii+1;
2115       //	map[s->_model]= s;
2116       //}
2117       // else {
2118       //	A[s->_dbIndex]= ii+1;
2119       //	map[s->_dbIndex]= s;
2120       //}
2121       A[s->_dbIndex] = ii + 1;
2122       map[s->_dbIndex] = s;
2123 
2124       sprintf(extList, "%s %d", extList, s->_model);
2125     }
2126     if (_prevControl->_extractedCornerList)
2127       free(_prevControl->_extractedCornerList);
2128     _prevControl->_extractedCornerList = strdup(extList);
2129   }
2130   // if (_extDbCnt<=0) {
2131   // 	delete [] map;
2132   // 	return;
2133   // }
2134   char aList[128];
2135   strcpy(aList, "");
2136 
2137   for (uint k = 0; k < _cornerCnt; k++) {
2138     sprintf(aList, "%s %d", aList, A[k]);
2139   }
2140   if (_prevControl->_cornerIndexList)
2141     free(_prevControl->_cornerIndexList);
2142   _prevControl->_cornerIndexList = strdup(aList);
2143 
2144   char buff[1024];
2145   if (map[0] == NULL)
2146     sprintf(buff, "%s %d", buff, 0);
2147   else
2148     sprintf(buff, "%s", map[0]->_name);
2149 
2150   for (uint ii = 1; ii < _cornerCnt; ii++) {
2151     extCorner* s = map[ii];
2152     if (s == NULL)
2153       sprintf(buff, "%s %d", buff, ii);
2154     else
2155       sprintf(buff, "%s %s", buff, s->_name);
2156   }
2157   if (!_remote) {
2158     _block->setCornerCount(_cornerCnt);
2159     _block->setCornerNameList(buff);
2160   }
2161 
2162   delete[] map;
2163   updatePrevControl();
2164 }
setCorners(const char * rulesFileName,const char * cmp_file)2165 bool extMain::setCorners(const char* rulesFileName, const char* cmp_file) {
2166   if (cmp_file != NULL)
2167     readCmpFile(cmp_file);
2168 
2169   _modelMap.resetCnt(0);
2170   uint ii;
2171   /*	for (ii= 0; ii<_processCornerTable->getCnt(); ii++) {
2172                   extCorner *s= _processCornerTable->get(ii);
2173                   _modelMap.add(s->_model);
2174           }*/
2175   _metRCTable.resetCnt(0);
2176 
2177   if (rulesFileName != NULL) {  // read rules
2178 
2179     int dbunit = _block->getDbUnitsPerMicron();
2180     double dbFactor = 1;
2181     if (dbunit > 1000)
2182       dbFactor = dbunit * 0.001;
2183 
2184     extRCModel* m = new extRCModel("MINTYPMAX", logger_);
2185     _modelTable->add(m);
2186 
2187     uint cornerTable[10];
2188     uint extDbCnt = 0;
2189 
2190     _minModelIndex = 0;
2191     _maxModelIndex = 0;
2192     _typModelIndex = 0;
2193     if (_processCornerTable != NULL) {
2194       for (uint ii = 0; ii < _processCornerTable->getCnt(); ii++) {
2195         extCorner* s = _processCornerTable->get(ii);
2196         cornerTable[extDbCnt++] = s->_model;
2197         _modelMap.add(ii);
2198       }
2199     }
2200 
2201     logger_->info(RCX, 435, "Reading extraction model file {} ...",
2202                   rulesFileName);
2203 
2204     if (!fopen(rulesFileName, "r"))
2205       logger_->error(RCX, 468, "Can't open extraction model file {}",
2206                      rulesFileName);
2207 
2208     if (!(m->readRules((char*)rulesFileName, false, true, true, true, true,
2209                        extDbCnt, cornerTable, dbFactor))) {
2210       delete m;
2211       return false;
2212     }
2213 
2214     int modelCnt = getRCmodel(0)->getModelCnt();
2215 
2216     // If RCX reads wrong extRules file format
2217     if (modelCnt == 0)
2218       logger_->error(RCX, 487,
2219                      "No RC model read from the extraction model! "
2220                      "Ensure the right extRules file is used!");
2221 
2222     if (cmp_file != NULL) {  // find 0.0% variability and make it first
2223       _currentModel = getRCmodel(0);
2224 
2225       int n_0 = _currentModel->findVariationZero(0.0);
2226       if (_processCornerTable != NULL) {
2227         cleanCornerTables();
2228         logger_->info(RCX, 124,
2229                       "Deleted already defined corners, only one corner will "
2230                       "automatically defined when option cmp_file is used");
2231       }
2232       addRCCorner("CMP", n_0, 0);
2233       _modelMap.add(n_0);
2234       _metRCTable.add(_currentModel->getMetRCTable(n_0));
2235       _extDbCnt = _processCornerTable->getCnt();
2236 
2237       assert(_cornerCnt == _extDbCnt);
2238 
2239       _block->setCornerCount(_cornerCnt, _extDbCnt, NULL);
2240       return true;
2241     } else if (_processCornerTable == NULL) {
2242       for (int ii = 0; ii < modelCnt; ii++) {
2243         addRCCorner(NULL, ii, 0);
2244         _modelMap.add(ii);
2245       }
2246     }
2247   }
2248   _currentModel = getRCmodel(0);
2249   for (ii = 0; (_couplingFlag > 0) && (!_lefRC) && ii < _modelMap.getCnt();
2250        ii++) {
2251     uint jj = _modelMap.get(ii);
2252     _metRCTable.add(_currentModel->getMetRCTable(jj));
2253   }
2254   _extDbCnt = _processCornerTable->getCnt();
2255 
2256   uint scaleCornerCnt = 0;
2257   if (_scaledCornerTable != NULL)
2258     scaleCornerCnt = _scaledCornerTable->getCnt();
2259 
2260   assert(_cornerCnt == _extDbCnt + scaleCornerCnt);
2261 
2262   // char cornerNameList[1024];
2263   // makeCornerNameMap(cornerNameList, _cornerCnt, false);
2264 
2265   _block->setCornerCount(_cornerCnt, _extDbCnt, NULL);
2266   return true;
2267 }
2268 
addDummyCorners(uint cornerCnt)2269 void extMain::addDummyCorners(uint cornerCnt) {
2270   for (uint ii = 0; ii < cornerCnt; ii++)
2271     addRCCorner(NULL, ii, -1);
2272 }
2273 
updatePrevControl()2274 void extMain::updatePrevControl() {
2275   _prevControl->_independentExtCorners = _independentExtCorners;
2276   _prevControl->_foreign = _foreign;
2277   _prevControl->_rsegCoord = _rsegCoord;
2278   _prevControl->_overCell = _overCell;
2279   _prevControl->_extracted = _extracted;
2280   _prevControl->_lefRC = _lefRC;
2281   // _prevControl->_extDbCnt = _extDbCnt;
2282   _prevControl->_cornerCnt = _cornerCnt;
2283   _prevControl->_ccPreseveGeom = _ccPreseveGeom;
2284   _prevControl->_ccUp = _ccUp;
2285   _prevControl->_couplingFlag = _couplingFlag;
2286   _prevControl->_coupleThreshold = _coupleThreshold;
2287   _prevControl->_mergeResBound = _mergeResBound;
2288   _prevControl->_mergeViaRes = _mergeViaRes;
2289   _prevControl->_mergeParallelCC = _mergeParallelCC;
2290   _prevControl->_useDbSdb = _useDbSdb;
2291   _prevControl->_CCnoPowerSource = _CCnoPowerSource;
2292   _prevControl->_CCnoPowerTarget = _CCnoPowerTarget;
2293   _prevControl->_usingMetalPlanes = _usingMetalPlanes;
2294   if (_prevControl->_ruleFileName)
2295     free(_prevControl->_ruleFileName);
2296   if (_currentModel && _currentModel->getRuleFileName())
2297     _prevControl->_ruleFileName = strdup(_currentModel->getRuleFileName());
2298 }
2299 
getPrevControl()2300 void extMain::getPrevControl() {
2301   if (!_prevControl)
2302     return;
2303   _independentExtCorners = _prevControl->_independentExtCorners;
2304   _foreign = _prevControl->_foreign;
2305   _rsegCoord = _prevControl->_rsegCoord;
2306   _overCell = _prevControl->_overCell;
2307   _extracted = _prevControl->_extracted;
2308   _lefRC = _prevControl->_lefRC;
2309   // _extDbCnt = _prevControl->_extDbCnt;
2310   _cornerCnt = _prevControl->_cornerCnt;
2311   _ccPreseveGeom = _prevControl->_ccPreseveGeom;
2312   _ccUp = _prevControl->_ccUp;
2313   _couplingFlag = _prevControl->_couplingFlag;
2314   _coupleThreshold = _prevControl->_coupleThreshold;
2315   _mergeResBound = _prevControl->_mergeResBound;
2316   _mergeViaRes = _prevControl->_mergeViaRes;
2317   _mergeParallelCC = _prevControl->_mergeParallelCC;
2318   _useDbSdb = _prevControl->_useDbSdb;
2319   _CCnoPowerSource = _prevControl->_CCnoPowerSource;
2320   _CCnoPowerTarget = _prevControl->_CCnoPowerTarget;
2321   _usingMetalPlanes = _prevControl->_usingMetalPlanes;
2322   //	if ((_prevControl->_ruleFileName && !_currentModel->getRuleFileName())
2323   //||
2324   //	    (!_prevControl->_ruleFileName && !_currentModel->getRuleFileName())
2325   //|| (strcmp(_prevControl->_ruleFileName,_currentModel->getRuleFileName())))
2326 }
2327 
makeBlockRCsegs(bool btermThresholdFlag,const char * cmp_file,bool density_model,bool litho,const char * netNames,const char * bbox,const char * ibox,uint cc_up,uint ccFlag,int ccBandTracks,uint use_signal_table,double resBound,bool mergeViaRes,uint debug,int preserve_geom,bool re_extract,bool eco,bool gs,bool rlog,ZPtr<ISdb> netSdb,double ccThres,int contextDepth,bool overCell,const char * extRules,ZInterface * Interface)2328 uint extMain::makeBlockRCsegs(bool btermThresholdFlag, const char* cmp_file,
2329                               bool density_model, bool litho,
2330                               const char* netNames, const char* bbox,
2331                               const char* ibox, uint cc_up, uint ccFlag,
2332                               int ccBandTracks, uint use_signal_table,
2333                               double resBound, bool mergeViaRes, uint debug,
2334                               int preserve_geom, bool re_extract, bool eco,
2335                               bool gs, bool rlog, ZPtr<ISdb> netSdb,
2336                               double ccThres, int contextDepth, bool overCell,
2337                               const char* extRules, ZInterface* Interface) {
2338   uint debugNetId = 0;
2339   if (preserve_geom < 0) {
2340     debugNetId = -preserve_geom;
2341     preserve_geom = 0;
2342   }
2343 
2344   _cc_band_tracks = ccBandTracks;
2345   _use_signal_tables = use_signal_table;
2346 
2347   if (debug == 703) {
2348     logger_->info(RCX, 473, "Initial Tiling {} ...",
2349                   getBlock()->getName().c_str());
2350 
2351     Rect maxRect;
2352     _block->getDieArea(maxRect);
2353     logger_->info(RCX, 125, "Tiling for die area {}x{} = {} {}  {} {}",
2354                   maxRect.dx(), maxRect.dy(), maxRect.xMin(), maxRect.yMin(),
2355                   maxRect.xMax(), maxRect.yMax());
2356 
2357     _use_signal_tables = 3;
2358     createWindowsDB(rlog, maxRect, ccBandTracks, ccFlag, use_signal_table);
2359     return 0;
2360   }
2361   if (debug == 803) {
2362     Rect maxRect;
2363     _block->getDieArea(maxRect);
2364 
2365     _use_signal_tables = 3;
2366     uint wireCnt = fillWindowsDB(rlog, maxRect, use_signal_table);
2367     logger_->info(RCX, 126, "Block {} has {} ext Wires",
2368                   getBlock()->getName().c_str(), wireCnt);
2369     return wireCnt;
2370   }
2371   bool initTiling = false;
2372   bool windowFlow = false;
2373   bool skipExtractionAfterRcGen = false;
2374   bool doExt = false;
2375   if (debug == 101) {
2376     _batchScaleExt = false;
2377     debug = 0;
2378   } else if (debug == 100) {
2379     _reuseMetalFill = true;
2380     debug = 0;
2381   } else if (debug == 99) {
2382     _extNetSDB = netSdb;
2383     return 0;  // "-test 99", to check sdb tracks and wires
2384   } else if (debug == 103) {
2385     _getBandWire = true;
2386     debug = 0;
2387   } else if (debug == 104) {
2388     _printBandInfo = true;
2389     debug = 0;
2390   } else if (debug == 105) {
2391     _getBandWire = true;
2392     _printBandInfo = true;
2393     debug = 0;
2394   } else if (debug == 106) {
2395     _extRun = 0;
2396     removeExt();
2397     debug = 0;
2398   } else if (debug == 104) {
2399     _extRun = 0;
2400     removeExt();
2401     debug = 0;
2402   } else if (debug == 501) {
2403     windowFlow = true;
2404     debug = 0;
2405     _getBandWire = false;
2406   } else if (debug == 503) {
2407     windowFlow = true;
2408     debug = 0;
2409     _getBandWire = false;
2410     doExt = true;
2411   } else if (debug == 603) {
2412     windowFlow = false;
2413     debug = 0;
2414     _getBandWire = false;
2415     doExt = false;
2416     skipExtractionAfterRcGen = true;
2417   } else if (debug == 773) {
2418     windowFlow = false;
2419     debug = 0;
2420     _getBandWire = false;
2421     doExt = false;
2422     skipExtractionAfterRcGen = false;
2423     initTiling = true;
2424   }
2425   _diagFlow = true;
2426 
2427   int detailRlog = 0;
2428   int ttttRemoveSdb = 1;
2429   int ttttRemoveGs = 1;
2430   int setBlockPtfile = 0;
2431   std::vector<dbNet*> inets;
2432   if ((_prevControl->_ruleFileName == NULL) &&
2433       (!_lefRC && (getRCmodel(0) == NULL) && (extRules == NULL))) {
2434     logger_->warn(RCX, 127,
2435                   "No RC model was read with command <load_model>, "
2436                   "will not perform extraction!");
2437     return 0;
2438   }
2439   if (!re_extract) {
2440     _couplingFlag = ccFlag;
2441     _coupleThreshold = ccThres;
2442     _reExtract = re_extract;
2443     _ccPreseveGeom = preserve_geom;
2444 
2445     _debug = debug;
2446     if (!_lefRC) {
2447       _usingMetalPlanes = gs;
2448       _ccUp = cc_up;
2449       _couplingFlag = ccFlag;
2450       _ccContextDepth = contextDepth;
2451       if (_usingMetalPlanes)
2452         _overCell = overCell;
2453     } else {
2454       _usingMetalPlanes = 0;
2455       _ccUp = 0;
2456       _couplingFlag = 0;
2457       _ccContextDepth = 0;
2458     }
2459     _mergeViaRes = mergeViaRes;
2460     _mergeResBound = resBound;
2461   }
2462   _eco = eco;
2463   if (eco && _extRun == 0) {
2464     getPrevControl();
2465     getExtractedCorners();
2466   }
2467   if (!eco) {
2468     if (netSdb && netSdb == _extNetSDB)
2469       netSdb->reMakeSdb(_tech, _block);
2470   }
2471   // if ( _extRun==0 || (!re_extract && !eco )) {
2472   if ((_processCornerTable != NULL) ||
2473       ((_processCornerTable == NULL) && (extRules != NULL))) {
2474     char* rulesfile = extRules ? (char*)extRules : _prevControl->_ruleFileName;
2475     if (debug != 777) {
2476       if (!setCorners(rulesfile,
2477                       cmp_file)) {  // DKF:12/22 -- cmp_file for testing,
2478                                     // eventually: rulesFileName
2479         logger_->info(RCX, 128, "skipping Extraction ...");
2480         return 0;
2481       }
2482     }
2483     // if (cmp_file!=NULL)
2484     //	readCmpFile(cmp_file);
2485   }
2486   // removed opptions
2487   // else if (setMinTypMax(minModel, typModel, maxModel, cmp_file,
2488   // density_model, litho, 	setMin, setTyp, setMax, extDbCnt)<0) {
2489   else if (setMinTypMax(false, false, false, cmp_file, density_model, litho, -1,
2490                         -1, -1, 1) < 0) {
2491     logger_->warn(RCX, 129, "Wrong combination of corner related options!");
2492     return 0;
2493   }
2494   _foreign = false;  // extract after read_spef
2495   // }
2496 
2497   if (ibox) {
2498     logger_->info(RCX, 130, "Ibox = {}", ibox);
2499     Ath__parser* parser = new Ath__parser();
2500     parser->mkWords(ibox, NULL);
2501     _ibox = new Rect(atoi(parser->get(0)), atoi(parser->get(1)),
2502                      atoi(parser->get(2)), atoi(parser->get(3)));
2503     logger_->info(RCX, 131, "_ibox = {} {} {} {}", _ibox->xMin(), _ibox->yMin(),
2504                   _ibox->xMax(), _ibox->yMax());
2505     eco = true;
2506   } else
2507     _ibox = NULL;
2508   if (eco) {
2509     _block->getWireUpdatedNets(inets, _ibox);
2510     if (inets.size() != 0)
2511       logger_->info(RCX, 132, "Eco extract {} nets.", inets.size());
2512     else {
2513       logger_->info(RCX, 133, "No nets to eco extract.");
2514       return 1;
2515     }
2516     removeExt(inets);
2517     _reExtract = true;
2518     _allNet = false;
2519     preserve_geom = 1;
2520   } else {
2521     _allNet = !((dbBlock*)_block)->findSomeNet(netNames, inets);
2522   }
2523 
2524   // if (remove_ext)
2525   //{
2526   //	removeExt (inets);
2527   //	return 1;
2528   //}
2529   // if (unlink_ext)
2530   //{
2531   // unlinkExt (inets);
2532   //	return 1;
2533   //}
2534   // if (remove_cc)
2535   //{
2536   //	removeCC (inets);
2537   //	return 1;
2538   //}
2539 
2540   if (!_reExtract || _extRun == 0 || _alwaysNewGs) {
2541     //_block->setCornerCount(extDbCnt);
2542     //_extDbCnt = extDbCnt;
2543 
2544     //		if (log)
2545     //			AthResourceLog ("Start Planes", 0);
2546 
2547     if (!_lefRC) {
2548       if (_cc_band_tracks == 0) {
2549         //#ifndef NEW_GS_FLOW
2550         if (_usingMetalPlanes && (_geoThickTable == NULL)) {
2551           if (rlog)
2552             AthResourceLog("before initPlanes", detailRlog);
2553           initPlanes(_currentModel->getLayerCnt() + 1);
2554           if (rlog)
2555             AthResourceLog("after initPlanes", detailRlog);
2556           addPowerGs();
2557           if (rlog)
2558             AthResourceLog("after addPowerGs", detailRlog);
2559           if (_alwaysNewGs)
2560             addSignalGs();
2561           if (rlog)
2562             AthResourceLog("after addSignalGs", detailRlog);
2563           if (_overCell)
2564             addInstShapesOnPlanes();
2565           if (rlog)
2566             AthResourceLog("after addInstShapesOnPlanes", detailRlog);
2567         }
2568       }
2569       //#endif
2570       if (_ccContextDepth)
2571         initContextArray();
2572     }
2573     initDgContextArray();
2574   }
2575   _extRun++;
2576   if (rlog)
2577     AthResourceLog("start extract", detailRlog);
2578 
2579 #ifdef ZDEBUG
2580   Interface->event("CC", "_couplingFlag", Z_INT, _couplingFlag, NULL);
2581 #endif
2582 
2583   extMeasure m;
2584   m.setLogger(logger_);
2585 
2586   _seqPool = m._seqPool;
2587   _useDbSdb = false;
2588   if (netSdb) {
2589     _extNetSDB = netSdb;
2590     Ath__overlapAdjust overlapAdj = Z_noAdjust;
2591     _useDbSdb = true;
2592     _extNetSDB->setExtControl(
2593         _block, _useDbSdb, (uint)overlapAdj, _CCnoPowerSource, _CCnoPowerTarget,
2594         _ccUp, _allNet, _ccContextDepth, _ccContextArray, _ccContextLength,
2595         _dgContextArray, &_dgContextDepth, &_dgContextPlanes, &_dgContextTracks,
2596         &_dgContextBaseLvl, &_dgContextLowLvl, &_dgContextHiLvl,
2597         _dgContextBaseTrack, _dgContextLowTrack, _dgContextHiTrack,
2598         _dgContextTrackBase, _seqPool);
2599     setExtractionBbox(bbox);
2600   }
2601   // else
2602   else if (_cc_band_tracks == 0) {
2603     setupSearchDb(bbox, debug, Interface);
2604   }
2605 
2606   dbNet* net;
2607   uint j;
2608   for (j = 0; j < inets.size(); j++) {
2609     net = inets[j];
2610     net->setMark(true);
2611   }
2612   dbSet<dbNet> bnets = _block->getNets();
2613   dbSet<dbNet>::iterator net_itr;
2614 
2615   uint cnt = 0;
2616 
2617   if (!_allNet) {
2618     _ccMinX = MAX_INT;
2619     _ccMinY = MAX_INT;
2620     _ccMaxX = -MAX_INT;
2621     _ccMaxY = -MAX_INT;
2622   }
2623   if (_couplingFlag > 1 && !_lefRC) {
2624     // if (!getResCapTable(true))
2625     //	return 1;
2626     getResCapTable(true);
2627   }
2628 
2629   logger_->info(RCX, 436, "RC segment generation {} (max_merge_res {}) ...",
2630                 getBlock()->getName().c_str(), _mergeResBound);
2631   uint itermCntEst = 3 * bnets.size();
2632   setupMapping(itermCntEst);
2633 
2634   if (_reuseMetalFill)
2635     _extNetSDB->adjustMetalFill();
2636   //	uint netCnt= 0;
2637   //	for( net_itr = bnets.begin(); !windowFlow && net_itr != bnets.end();
2638   //++net_itr ) {
2639 
2640   dbIntProperty* p = (dbIntProperty*)dbProperty::find(_block, "_currentDir");
2641 
2642   if ((p == NULL) && (debug != 777) && !initTiling) {
2643     if (_power_extract_only) {
2644       powerRCGen();
2645       return 1;
2646     }
2647 
2648     for (net_itr = bnets.begin(); net_itr != bnets.end(); ++net_itr) {
2649       net = *net_itr;
2650 
2651       dbSigType type = net->getSigType();
2652       if ((type == dbSigType::POWER) || (type == dbSigType::GROUND))
2653         continue;
2654       if (!_allNet && !net->isMarked())
2655         continue;
2656 
2657       _connectedBTerm.clear();
2658       _connectedITerm.clear();
2659       cnt += makeNetRCsegs(net);
2660       uint tt;
2661       for (tt = 0; tt < _connectedBTerm.size(); tt++)
2662         ((dbBTerm*)_connectedBTerm[tt])->setMark(0);
2663       for (tt = 0; tt < _connectedITerm.size(); tt++)
2664         ((dbITerm*)_connectedITerm[tt])->setMark(0);
2665       // break;
2666     }
2667 
2668     logger_->info(RCX, 40, "Final {} rc segments", cnt);
2669   } else if (debug == 777) {
2670     _debug = 0;
2671   } else
2672     _debug = 0;
2673 
2674   if (rlog)
2675     AthResourceLog("after makeNetRCsegs", detailRlog);
2676   int ttttPrintDgContext = 0;
2677   if (!skipExtractionAfterRcGen && (_couplingFlag > 1)) {
2678     logger_->info(RCX, 439, "Coupling Cap extraction {} ...",
2679                   getBlock()->getName().c_str());
2680 
2681     uint CCflag = _couplingFlag;
2682     //		if (_couplingFlag>20) {
2683     //			CCflag= _couplingFlag % 10;
2684     //		}
2685 
2686     if (!_allNet)
2687       _extNetSDB->setMaxArea(_ccMinX, _ccMinY, _ccMaxX, _ccMaxY);
2688 
2689     // ZPtr<ISdb> ccCapSdb = _reExtract ? _reExtCcapSDB : _extCcapSDB;
2690     ZPtr<ISdb> ccCapSdb = _extCcapSDB;
2691 
2692     _totCCcnt = 0;
2693     _totSmallCCcnt = 0;
2694     _totBigCCcnt = 0;
2695     _totSegCnt = 0;
2696     _totSignalSegCnt = 0;
2697 
2698     uint intersectCnt;
2699     if (_usingMetalPlanes && (_geoThickTable == NULL)) {
2700       intersectCnt = makeIntersectPlanes(0);
2701       if (rlog)
2702         AthResourceLog("after makeIntersectPlanes", detailRlog);
2703     }
2704 
2705     uint ccCnt;
2706     if (_debug) {
2707       if (_debug != 102)
2708         ccCnt =
2709             _extNetSDB->couplingCaps(ccCapSdb, CCflag, Interface, NULL, NULL);
2710     } else {
2711       logger_->info(RCX, 440,
2712                     "Coupling threshhold is {:.4f} fF, coupling capacitance "
2713                     "less than {:.4f} "
2714                     "fF will be grounded.",
2715                     _coupleThreshold, _coupleThreshold);
2716       if (_unifiedMeasureInit) {
2717         m._extMain = this;
2718         m._block = _block;
2719         m._diagFlow = _diagFlow;
2720 
2721         m._resFactor = _resFactor;
2722         m._resModify = _resModify;
2723         m._ccFactor = _ccFactor;
2724         m._ccModify = _ccModify;
2725         m._gndcFactor = _gndcFactor;
2726         m._gndcModify = _gndcModify;
2727 
2728         m._dgContextArray = _dgContextArray;
2729         m._dgContextDepth = &_dgContextDepth;
2730         m._dgContextPlanes = &_dgContextPlanes;
2731         m._dgContextTracks = &_dgContextTracks;
2732         m._dgContextBaseLvl = &_dgContextBaseLvl;
2733         m._dgContextLowLvl = &_dgContextLowLvl;
2734         m._dgContextHiLvl = &_dgContextHiLvl;
2735         m._dgContextBaseTrack = _dgContextBaseTrack;
2736         m._dgContextLowTrack = _dgContextLowTrack;
2737         m._dgContextHiTrack = _dgContextHiTrack;
2738         m._dgContextTrackBase = _dgContextTrackBase;
2739         if (ttttPrintDgContext)
2740           m._dgContextFile = fopen("dgCtxtFile", "w");
2741         m._dgContextCnt = 0;
2742 
2743         m._ccContextLength = _ccContextLength;
2744         m._ccContextArray = _ccContextArray;
2745 
2746         m._ouPixelTableIndexMap = _overUnderPlaneLayerMap;
2747         m._pixelTable = _geomSeq;
2748         m._minModelIndex = 0;  // couplimg threshold will be appled to this cap
2749         m._maxModelIndex = 0;
2750         m._currentModel = _currentModel;
2751         m._diagModel = _currentModel[0].getDiagModel();
2752         for (uint ii = 0; !_lefRC && ii < _modelMap.getCnt(); ii++) {
2753           uint jj = _modelMap.get(ii);
2754           m._metRCTable.add(_currentModel->getMetRCTable(jj));
2755         }
2756         // m._layerCnt= getExtLayerCnt(_tech); // TEST
2757         // m._layerCnt= _currentModel->getLayerCnt(); // TEST
2758         uint techLayerCnt = getExtLayerCnt(_tech) + 1;
2759         uint modelLayerCnt = _currentModel->getLayerCnt();
2760         m._layerCnt =
2761             techLayerCnt < modelLayerCnt ? techLayerCnt : modelLayerCnt;
2762         if (techLayerCnt == 5 && modelLayerCnt == 8)
2763           m._layerCnt = modelLayerCnt;
2764         //				m._cornerMapTable[0]= 1;
2765         //				m._cornerMapTable[1]= 0;
2766         m.getMinWidth(_tech);
2767         m.allocOUpool();
2768 
2769         m._btermThreshold = btermThresholdFlag;
2770 
2771         m._debugFP = NULL;
2772         m._netId = 0;
2773         debugNetId = 0;
2774         if (debugNetId > 0) {
2775           m._netId = debugNetId;
2776           char bufName[32];
2777           sprintf(bufName, "%d", debugNetId);
2778           m._debugFP = fopen(bufName, "w");
2779         }
2780 
2781         //#ifndef NEW_GS_FLOW
2782         if (_cc_band_tracks == 0) {
2783           ccCnt = _extNetSDB->couplingCaps(ccCapSdb, _couplingFlag, Interface,
2784                                            extCompute1, &m);
2785         } else {
2786           //#else
2787           Rect maxRect;
2788           _block->getDieArea(maxRect);
2789 
2790           if (initTiling) {
2791             logger_->info(RCX, 123, "Initial Tiling {} ...",
2792                           getBlock()->getName().c_str());
2793             _use_signal_tables = 3;
2794             createWindowsDB(rlog, maxRect, ccBandTracks, ccFlag,
2795                             use_signal_table);
2796             return 0;
2797           }
2798           if (windowFlow)
2799             couplingWindowFlow(rlog, maxRect, _cc_band_tracks, _couplingFlag,
2800                                doExt, &m, extCompute1);
2801           else
2802             couplingFlow(rlog, maxRect, _cc_band_tracks, _couplingFlag, &m,
2803                          extCompute1);
2804 
2805           if (m._debugFP != NULL)
2806             fclose(m._debugFP);
2807         }
2808         //#endif
2809       } else {
2810         ccCnt = _extNetSDB->couplingCaps(ccCapSdb, CCflag, Interface,
2811                                          extCompute, this);
2812       }
2813       if (m._dgContextFile) {
2814         fclose(m._dgContextFile);
2815         m._dgContextFile = NULL;
2816       }
2817     }
2818     removeDgContextArray();
2819     if (_printFile) {
2820       fclose(_printFile);
2821       _printFile = NULL;
2822       if (setBlockPtfile)
2823         _block->setPtFile(NULL);
2824       _measureRcCnt = _shapeRcCnt = _updateTotalCcnt = -1;
2825     }
2826 
2827     // than
2828     // and {} caps greater than %g)", 			_totCCcnt,
2829     // _totSmallCCcnt, _totBigCCcnt, _coupleThreshold);
2830 
2831     if (rlog)
2832       AthResourceLog("after couplingCaps", detailRlog);
2833 
2834     if (_debug)
2835       computeXcaps(0);
2836 
2837     //		if (rlog)
2838     //			AthResourceLog ("CCcap", detailRlog);
2839 
2840     if (preserve_geom != 1 && !_useDbSdb) {
2841       if ((_extNetSDB != NULL) && (preserve_geom == 3 || preserve_geom == 0)) {
2842         _extNetSDB->cleanSdb();
2843         _extNetSDB = NULL;
2844       }
2845       if (ccCapSdb != NULL && (preserve_geom == 2 || preserve_geom == 0))
2846         ccCapSdb->cleanSdb();
2847       if (rlog)
2848         AthResourceLog("FreeCCgeom", detailRlog);
2849     }
2850   }
2851 
2852   if (ttttRemoveSdb)
2853     _extNetSDB = NULL;
2854   if (ttttRemoveGs) {
2855     if (rlog)
2856       AthResourceLog("before removeSeq", detailRlog);
2857     if (_geomSeq)
2858       delete _geomSeq;
2859     if (rlog)
2860       AthResourceLog("after removeSeq", detailRlog);
2861     _geomSeq = NULL;
2862   }
2863   _extracted = true;
2864   updatePrevControl();
2865   int numOfNet, numOfRSeg, numOfCapNode, numOfCCSeg;
2866   _block->getExtCount(numOfNet, numOfRSeg, numOfCapNode, numOfCCSeg);
2867   if (numOfRSeg)
2868     logger_->info(RCX, 45, "Extract {} nets, {} rsegs, {} caps, {} ccs",
2869                   numOfNet - 2, numOfRSeg, numOfCapNode, numOfCCSeg);
2870   else
2871     logger_->warn(RCX, 107, "Nothing is extracted out of {} nets!",
2872                   numOfNet - 2);
2873   if (_allNet) {
2874     for (net_itr = bnets.begin(); net_itr != bnets.end(); ++net_itr) {
2875       net = *net_itr;
2876 
2877       dbSigType type = net->getSigType();
2878       if ((type == dbSigType::POWER) || (type == dbSigType::GROUND))
2879         continue;
2880       net->setWireAltered(false);
2881     }
2882   } else {
2883     for (j = 0; j < inets.size(); j++) {
2884       net = inets[j];
2885       net->setMark(false);
2886       net->setWireAltered(false);
2887     }
2888   }
2889   if (rlog)
2890     AthResourceLog("before remove Model", detailRlog);
2891 
2892   if (!windowFlow) {
2893     // delete _currentModel;
2894     _modelTable->resetCnt(0);
2895     if (rlog)
2896       AthResourceLog("After remove Model", detailRlog);
2897   }
2898   if (_batchScaleExt)
2899     genScaledExt();
2900 
2901   return 1;
2902 }
2903 /*
2904 void extMain::genScaledExt()
2905 {
2906         if (_processCornerTable == NULL)
2907                 return;
2908         uint frdbid, todbid, scid;
2909         uint ii= 0;
2910         extCorner *pc, *sc;
2911         for (; ii< _processCornerTable->getCnt(); ii++) {
2912                 pc = _processCornerTable->get(ii);
2913                 scid = pc->_scaledCornerIdx;
2914                 if (scid == -1)
2915                         continue;
2916                 frdbid = pc->_dbIndex;
2917                 sc = _scaledCornerTable->get(scid);
2918                 todbid = sc->_dbIndex;
2919                 _block->copyExtDb(frdbid, todbid, _cornerCnt, sc->_resFactor,
2920 sc->_ccFactor, sc->_gndFactor);
2921         }
2922 }
2923 */
genScaledExt()2924 void extMain::genScaledExt() {
2925   if (_processCornerTable == NULL || _scaledCornerTable == NULL)
2926     return;
2927 
2928   uint ii = 0;
2929   for (; ii < _scaledCornerTable->getCnt(); ii++) {
2930     extCorner* sc = _scaledCornerTable->get(ii);
2931     extCorner* pc = sc->_extCornerPtr;
2932     if (pc == NULL)
2933       continue;
2934 
2935     uint frdbid = pc->_dbIndex;
2936     uint todbid = sc->_dbIndex;
2937 
2938     _block->copyExtDb(frdbid, todbid, _cornerCnt, sc->_resFactor, sc->_ccFactor,
2939                       sc->_gndFactor);
2940   }
2941 }
2942 
getTotalNetCap(uint netId,uint cornerNum)2943 double extMain::getTotalNetCap(uint netId, uint cornerNum) {
2944   dbNet* net = dbNet::getNet(_block, netId);
2945 
2946   dbSet<dbCapNode> nodeSet = net->getCapNodes();
2947 
2948   dbSet<dbCapNode>::iterator rc_itr;
2949 
2950   double cap = 0.0;
2951   for (rc_itr = nodeSet.begin(); rc_itr != nodeSet.end(); ++rc_itr) {
2952     dbCapNode* node = *rc_itr;
2953 
2954     cap += node->getCapacitance(cornerNum);
2955   }
2956   return cap;
2957 }
openSpefFile(char * filename,uint mode)2958 uint extMain::openSpefFile(char* filename, uint mode) {
2959   uint debug = 0;
2960   if (filename == NULL)
2961     debug = 1;
2962   else if (strcmp(filename, "") == 0)
2963     debug = 1;
2964 
2965   if (debug > 0)
2966     filename = NULL;
2967 
2968   if (mode > 0) {
2969     if (!_spef->setOutSpef(filename))
2970       return 1;
2971   } else {
2972     if (!_spef->setInSpef(filename))
2973       return 1;
2974   }
2975   return 0;
2976 }
writeSPEF(bool stop)2977 uint extMain::writeSPEF(bool stop) {
2978   if (stop)
2979     return _spef->stopWrite();
2980   return 0;
2981 }
getSpef()2982 extSpef* extMain::getSpef() { return _spef; }
write_spef_nets(bool flatten,bool parallel)2983 uint extMain::write_spef_nets(bool flatten, bool parallel) {
2984   return _spef->write_spef_nets(flatten, parallel);
2985 }
2986 
writeSPEF(uint netId,bool single_pi,uint debug,int corner,const char * corner_name)2987 uint extMain::writeSPEF(uint netId, bool single_pi, uint debug, int corner,
2988                         const char* corner_name) {
2989   if (_block == NULL) {
2990     logger_->info(RCX, 474,
2991                   "Can't execute write_spef command. There's no block in db!");
2992     return 0;
2993   }
2994   if (!_spef || _spef->getBlock() != _block) {
2995     if (_spef)
2996       delete _spef;
2997     _spef = new extSpef(_tech, _block, logger_, this);
2998   }
2999   dbNet* net = dbNet::getNet(_block, netId);
3000 
3001   int n = _spef->getWriteCorner(corner, corner_name);
3002   if (n < -10)
3003     return 0;
3004 
3005   _spef->_db_ext_corner = n;
3006 
3007   _spef->set_single_pi(single_pi);
3008   _spef->writeNet(net, 0.0, debug);
3009   _spef->set_single_pi(false);
3010 
3011   std::vector<dbNet*> nets;
3012   nets.push_back(net);
3013   _block->destroyCCs(nets);
3014 
3015   return 0;
3016 }
getWriteCorner(int corner,const char * names)3017 int extSpef::getWriteCorner(int corner, const char* names) {
3018   int cCnt = _block->getCornerCount();
3019   if ((corner >= 0) && (corner < cCnt)) {
3020     _active_corner_cnt = 1;
3021     _active_corner_number[0] = corner;
3022     return corner;
3023   }
3024 
3025   if ((corner >= 0) && (corner >= cCnt)) {
3026     logger_->warn(RCX, 135,
3027                   "Corner {} is out of range; There are {} corners in DB!",
3028                   corner, cCnt);
3029     return -10;
3030   }
3031 
3032   if (names == NULL || names[0] == '\0')  // all corners
3033   {
3034     _active_corner_cnt = cCnt;
3035     for (int kk = 0; kk < cCnt; kk++)
3036       _active_corner_number[kk] = kk;
3037     return -1;
3038   }
3039 
3040   _active_corner_cnt = 0;
3041   int cn = 0;
3042   Ath__parser parser;
3043   parser.mkWords(names, NULL);
3044   for (int ii = 0; ii < parser.getWordCnt(); ii++) {
3045     cn = _block->getExtCornerIndex(parser.get(ii));
3046     if (cn < 0) {
3047       logger_->info(RCX, 136, "Can't find corner name {} in the parasitics DB!",
3048                     parser.get(ii));
3049       continue;
3050     }
3051     _active_corner_number[_active_corner_cnt++] = cn;
3052   }
3053   return cn;
3054 }
3055 
writeSPEF(char * filename,char * netNames,bool useIds,bool noNameMap,char * nodeCoord,bool termJxy,const char * excludeCells,const char * capUnit,const char * resUnit,bool gzFlag,bool stopAfterMap,bool wClock,bool wConn,bool wCap,bool wOnlyCCcap,bool wRes,bool noCnum,bool initOnly,bool single_pi,bool noBackSlash,int corner,const char * corner_name,bool flatten,bool parallel)3056 uint extMain::writeSPEF(char* filename, char* netNames, bool useIds,
3057                         bool noNameMap, char* nodeCoord, bool termJxy,
3058                         const char* excludeCells, const char* capUnit,
3059                         const char* resUnit, bool gzFlag, bool stopAfterMap,
3060                         bool wClock, bool wConn, bool wCap, bool wOnlyCCcap,
3061                         bool wRes, bool noCnum, bool initOnly, bool single_pi,
3062                         bool noBackSlash, int corner, const char* corner_name,
3063                         bool flatten, bool parallel) {
3064   if (_block == NULL) {
3065     logger_->info(RCX, 475,
3066                   "Can't execute write_spef command. There's no block in db");
3067     return 0;
3068   }
3069   if (!_spef || _spef->getBlock() != _block) {
3070     if (_spef)
3071       delete _spef;
3072     _spef = new extSpef(_tech, _block, logger_, this);
3073   }
3074   _spef->_termJxy = termJxy;
3075   _spef->incr_wRun();
3076 
3077   if (excludeCells && strcmp(excludeCells, "FULLINCRSPEF") == 0) {
3078     excludeCells = NULL;
3079     _fullIncrSpef = true;
3080   }
3081   if (excludeCells && strcmp(excludeCells, "NOFULLINCRSPEF") == 0) {
3082     excludeCells = NULL;
3083     _noFullIncrSpef = true;
3084   }
3085   _writeNameMap = noNameMap ? false : true;
3086   _spef->_writeNameMap = _writeNameMap;
3087   _spef->setUseIdsFlag(useIds);
3088   int cntnet, cntrseg, cntcapn, cntcc;
3089   _block->getExtCount(cntnet, cntrseg, cntcapn, cntcc);
3090   if (cntrseg == 0 || cntcapn == 0) {
3091     logger_->info(
3092         RCX, 134,
3093         "Can't execute write_spef command. There's no extraction data.");
3094     return 0;
3095   }
3096   if (_extRun == 0) {
3097     getPrevControl();
3098     getExtractedCorners();
3099   }
3100   // if (_block->getRSegs() == NULL)
3101 
3102   // _spef->preserveFlag(preserveCapValues);
3103   _spef->preserveFlag(_foreign);
3104 
3105   if (gzFlag)
3106     _spef->setGzipFlag(gzFlag);
3107 
3108   /*	if ( (! preserveCapValues)&& (! useIds))
3109                   _spef->preserveFlag(true);
3110   */
3111   _spef->setDesign((char*)_block->getName().c_str());
3112 
3113   uint cnt = 0;
3114   if (openSpefFile(filename, 1) > 0)
3115     logger_->info(RCX, 137, "Can't open file \"{}\" to write spef.", filename);
3116   else {
3117     _spef->set_single_pi(single_pi);
3118     int n = _spef->getWriteCorner(corner, corner_name);
3119     if (n < -1)
3120       return 0;
3121     _spef->_db_ext_corner = n;
3122     _spef->_independentExtCorners = _independentExtCorners;
3123 
3124     std::vector<dbNet*> inets;
3125     ((dbBlock*)_block)->findSomeNet(netNames, inets);
3126     cnt = _spef->writeBlock(nodeCoord, excludeCells, capUnit, resUnit,
3127                             stopAfterMap, inets, wClock, wConn, wCap,
3128                             wOnlyCCcap, wRes, noCnum, initOnly, noBackSlash,
3129                             flatten, parallel);
3130     if (initOnly)
3131       return cnt;
3132   }
3133   delete _spef;
3134   _spef = NULL;
3135 
3136   return cnt;
3137 }
3138 
readSPEF(char * filename,char * netNames,bool force,bool useIds,bool rConn,char * nodeCoord,bool rCap,bool rOnlyCCcap,bool rRes,float cc_thres,float cc_gnd_factor,float length_unit,bool m_map,bool noCapNumCollapse,char * capNodeMapFile,bool log,int corner,double low,double up,char * excludeSubWord,char * subWord,char * statsFile,const char * dbCornerName,const char * calibrateBaseCorner,int spefCorner,int fixLoop,bool keepLoadedCorner,bool stampWire,ZPtr<ISdb> netSdb,uint testParsing,bool moreToRead,bool diff,bool calib,int app_print_limit)3139 uint extMain::readSPEF(char* filename, char* netNames, bool force, bool useIds,
3140                        bool rConn, char* nodeCoord, bool rCap, bool rOnlyCCcap,
3141                        bool rRes, float cc_thres, float cc_gnd_factor,
3142                        float length_unit, bool m_map, bool noCapNumCollapse,
3143                        char* capNodeMapFile, bool log, int corner, double low,
3144                        double up, char* excludeSubWord, char* subWord,
3145                        char* statsFile, const char* dbCornerName,
3146                        const char* calibrateBaseCorner, int spefCorner,
3147                        int fixLoop, bool keepLoadedCorner, bool stampWire,
3148                        ZPtr<ISdb> netSdb, uint testParsing, bool moreToRead,
3149                        bool diff, bool calib, int app_print_limit) {
3150   if (!_spef || _spef->getBlock() != _block) {
3151     if (_spef)
3152       delete _spef;
3153     _spef = new extSpef(_tech, _block, logger_, this);
3154   }
3155   _spef->_moreToRead = moreToRead;
3156   _spef->incr_rRun();
3157 
3158   _spef->setUseIdsFlag(useIds, diff, calib);
3159   if (_extRun == 0)
3160     getPrevControl();
3161   _spef->_independentExtCorners = _independentExtCorners;
3162   _spef->setCornerCnt(_cornerCnt);
3163   if (!diff && !calib)
3164     _foreign = true;
3165   if (diff) {
3166     if (!_extracted) {
3167       logger_->warn(RCX, 4, "There is no extraction db!");
3168       return 0;
3169     }
3170   } else if (_extracted && !force && !keepLoadedCorner &&
3171              !_independentExtCorners) {
3172     logger_->warn(RCX, 3, "Read SPEF into extracted db!");
3173     // return 0;
3174   }
3175 
3176   if (openSpefFile(filename, 0) > 0)
3177     return 0;
3178 
3179   _spef->_noCapNumCollapse = noCapNumCollapse;
3180   _spef->_capNodeFile = NULL;
3181   if (capNodeMapFile && capNodeMapFile[0] != '\0') {
3182     _spef->_capNodeFile = fopen(capNodeMapFile, "w");
3183     if (_spef->_capNodeFile == NULL)
3184       logger_->warn(RCX, 5, "Can't open SPEF file {} to write.",
3185                     capNodeMapFile);
3186   }
3187   if (log)
3188     AthResourceLog("start readSpef", 0);
3189   std::vector<dbNet*> inets;
3190 
3191   if (_block != NULL)
3192     _block->findSomeNet(netNames, inets);
3193 
3194   uint cnt = _spef->readBlock(
3195       0, inets, force, rConn, nodeCoord, rCap, rOnlyCCcap, rRes, cc_thres,
3196       length_unit, _extracted, keepLoadedCorner, stampWire, netSdb, testParsing,
3197       app_print_limit, m_map, corner, low, up, excludeSubWord, subWord,
3198       statsFile, dbCornerName, calibrateBaseCorner, spefCorner, fixLoop,
3199       _rsegCoord);
3200   genScaledExt();
3201 
3202   if (_spef->_capNodeFile)
3203     fclose(_spef->_capNodeFile);
3204 
3205   if (log)
3206     AthResourceLog("finish readSpef", 0);
3207 
3208   if (diff || cnt == 0) {
3209     delete _spef;
3210     _spef = NULL;
3211     return 0;
3212   }
3213   int numOfNet, numOfRSeg, numOfCapNode, numOfCCSeg;
3214   _block->getExtCount(numOfNet, numOfRSeg, numOfCapNode, numOfCCSeg);
3215   logger_->info(RCX, 376, "DB created {} nets, {} rsegs, {} caps, {} ccs",
3216                 numOfNet - 2, numOfRSeg, numOfCapNode, numOfCCSeg);
3217   if (_spef->getAppPrintLimit()) {
3218     int* appcnt = _spef->getAppCnt();
3219     for (int ii = 0; ii < 16; ii++)
3220       appcnt[ii] = 0;
3221     dbSet<dbCCSeg> ccSet = _block->getCCSegs();
3222     dbSet<dbCCSeg>::iterator cc_itr;
3223     for (cc_itr = ccSet.begin(); cc_itr != ccSet.end(); ++cc_itr) {
3224       dbCCSeg* cc = *cc_itr;
3225       appcnt[cc->getInfileCnt()]++;
3226     }
3227     logger_->info(RCX, 480,
3228                   "    cc appearance count -- 1:{} 2:{} 3:{} 4:{} 5:{} 6:{} "
3229                   "7:{} 8:{} 9:{} 10:{} 11:{} 12:{} 13:{} 14:{} 15:{} 16:{}",
3230                   appcnt[0], appcnt[1], appcnt[2], appcnt[3], appcnt[4],
3231                   appcnt[5], appcnt[6], appcnt[7], appcnt[8], appcnt[9],
3232                   appcnt[10], appcnt[11], appcnt[12], appcnt[13], appcnt[14],
3233                   appcnt[15]);
3234     _spef->printAppearance(appcnt, 16);
3235   }
3236   if (!moreToRead) {
3237     _extracted = true;
3238     if (cc_gnd_factor != 0.0)
3239       _block->groundCC(cc_gnd_factor);
3240     delete _spef;
3241     _spef = NULL;
3242   }
3243   _extRun++;
3244   updatePrevControl();
3245 
3246   return cnt;
3247 }
readSPEFincr(char * filename)3248 uint extMain::readSPEFincr(char* filename) {
3249   // assume header/name_map/ports same as first file
3250 
3251   if (!_spef->setInSpef(filename, true))
3252     return 0;
3253 
3254   uint cnt = _spef->readBlockIncr(0);
3255 
3256   // writeSPEF("out.spef", true, true, true);
3257 
3258   return cnt;
3259 }
match(char * filename,bool m_map,const char * dbCornerName,int corner,int spefCorner)3260 uint extMain::match(char* filename, bool m_map, const char* dbCornerName,
3261                     int corner, int spefCorner) {
3262   if (!_spef || _spef->getBlock() != _block) {
3263     if (_spef)
3264       delete _spef;
3265     _spef = new extSpef(_tech, _block, logger_, this);
3266   }
3267   _spef->setCalibLimit(0.0, 0.0);
3268   readSPEF(filename, NULL /*netNames*/, false /*force*/, false /*useIds*/,
3269            false /*rConn*/, NULL /*N*/, false /*rCap*/, false /*rOnlyCCcap*/,
3270            false /*rRes*/, -1.0 /*cc_thres*/, 0.0 /*cc_gnd_factor*/,
3271            1.0 /*length_unit*/, m_map, false /*noCapNumCollapse*/,
3272            NULL /*capNodeMapFile*/, false /*log*/, corner, 0.0 /*low*/,
3273            0.0 /*up*/, NULL /*excludeSubWord*/, NULL /*subWord*/,
3274            NULL /*statsFile*/, dbCornerName, NULL /*calibrateBaseCorner*/,
3275            spefCorner, 0 /*fix_loop*/, false /*keepLoadedCorner*/,
3276            false /*stampWire*/, NULL /*netSdb*/, 0 /*testParsing*/,
3277            false /*moreToRead*/, true /*diff*/, true /*calibrate*/,
3278            0 /*app_print_limit*/);
3279   return 0;
3280 }
3281 
calibrate(char * filename,bool m_map,float upperLimit,float lowerLimit,const char * dbCornerName,int corner,int spefCorner)3282 uint extMain::calibrate(char* filename, bool m_map, float upperLimit,
3283                         float lowerLimit, const char* dbCornerName, int corner,
3284                         int spefCorner) {
3285   if (!_spef || _spef->getBlock() != _block) {
3286     if (_spef)
3287       delete _spef;
3288     _spef = new extSpef(_tech, _block, logger_, this);
3289   }
3290   _spef->setCalibLimit(upperLimit, lowerLimit);
3291   readSPEF(filename, NULL /*netNames*/, false /*force*/, false /*useIds*/,
3292            false /*rConn*/, NULL /*N*/, false /*rCap*/, false /*rOnlyCCcap*/,
3293            false /*rRes*/, -1.0 /*cc_thres*/, 0.0 /*cc_gnd_factor*/,
3294            1.0 /*length_unit*/, m_map, false /*noCapNumCollapse*/,
3295            NULL /*capNodeMapFile*/, false /*log*/, corner, 0.0 /*low*/,
3296            0.0 /*up*/, NULL /*excludeSubWord*/, NULL /*subWord*/,
3297            NULL /*statsFile*/, dbCornerName, NULL /*calibrateBaseCorner*/,
3298            spefCorner, 0 /*fix_loop*/, false /*keepLoadedCorner*/,
3299            false /*stampWire*/, NULL /*netSdb*/, 0 /*testParsing*/,
3300            false /*moreToRead*/, true /*diff*/, true /*calibrate*/,
3301            0 /*app_print_limit*/);
3302   return 0;
3303 }
3304 
setUniqueExttreeCorner()3305 void extMain::setUniqueExttreeCorner() {
3306   getPrevControl();
3307   _independentExtCorners = true;
3308   updatePrevControl();
3309   _block->setCornersPerBlock(1);
3310 }
3311 
3312 }  // namespace rcx
3313