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