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 "darr.h"
34 #include "rcx/extRCap.h"
35 #include "rcx/extSpef.h"
36 #include "rcx/exttree.h"
37 #include "utl/Logger.h"
38
39 namespace rcx {
40
41 using utl::RCX;
42
43 using odb::dbBlock;
44 using odb::dbBox;
45 using odb::dbBTerm;
46 using odb::dbCapNode;
47 using odb::dbCCSeg;
48 using odb::dbChip;
49 using odb::dbDatabase;
50 using odb::dbNet;
51 using odb::dbRSeg;
52 using odb::dbSet;
53 using odb::dbShape;
54 using odb::dbSigType;
55 using odb::dbTech;
56 using odb::dbTechLayer;
57 using odb::dbTechLayerDir;
58 using odb::dbTechLayerType;
59 using odb::dbWire;
60 using odb::dbWirePath;
61 using odb::dbWirePathItr;
62 using odb::dbWirePathShape;
63 using odb::gs;
64 using odb::ISdb;
65 using odb::Rect;
66 using odb::SEQ;
67 using odb::ZPtr;
68
init(odb::dbDatabase * db,Logger * logger)69 void extMain::init(odb::dbDatabase* db, Logger* logger) {
70 _db = db;
71 _block = NULL;
72 _blockId = 0;
73 logger_ = logger;
74 }
75
destroyExtSdb(std::vector<dbNet * > & nets,void * _ext)76 void extMain::destroyExtSdb(std::vector<dbNet*>& nets, void* _ext) {
77 if (_ext == NULL)
78 return;
79 extMain* ext = (extMain*)_ext;
80 ext->removeSdb(nets);
81 }
82
addDummyCorners(dbBlock * block,uint cnt,Logger * logger)83 void extMain::addDummyCorners(dbBlock* block, uint cnt, Logger* logger) {
84 extMain* tmiExt = (extMain*)block->getExtmi();
85 if (tmiExt == NULL) {
86 logger->error(RCX, 252, "Ext object on dbBlock is NULL!");
87 return;
88 }
89 tmiExt->addDummyCorners(cnt);
90 }
91
initExtractedCorners(dbBlock * block)92 void extMain::initExtractedCorners(dbBlock* block) {
93 extMain* tmiExt = (extMain*)block->getExtmi();
94 if (tmiExt == NULL) {
95 tmiExt = new extMain(0);
96 tmiExt->init((dbDatabase*)block->getDataBase(), logger_);
97 }
98 if (tmiExt->_processCornerTable)
99 return;
100 tmiExt->getPrevControl();
101 tmiExt->getExtractedCorners();
102 }
103
getExtCornerIndex(dbBlock * block,const char * cornerName)104 int extMain::getExtCornerIndex(dbBlock* block, const char* cornerName) {
105 extMain* tmiExt = (extMain*)block->getExtmi();
106 if (tmiExt == NULL) {
107 tmiExt = new extMain(0);
108 tmiExt->init((dbDatabase*)block->getDataBase(), logger_);
109 }
110 int idx = tmiExt->getDbCornerIndex(cornerName);
111 return idx;
112 }
113
114 // wis 1
writeIncrementalSpef(Darr<dbNet * > & buf_nets,dbBlock * block,INCR_SPEF_TYPE isftype,bool coupled_rc,bool dual_incr_spef)115 void extMain::writeIncrementalSpef(Darr<dbNet*>& buf_nets, dbBlock* block,
116 INCR_SPEF_TYPE isftype, bool coupled_rc,
117 bool dual_incr_spef) {
118 std::vector<dbNet*> bnets;
119 int nn;
120 for (nn = 0; nn < buf_nets.n(); nn++)
121 bnets.push_back(buf_nets.get(nn));
122 if (isftype == ISPEF_ORIGINAL_PLUS_HALO || isftype == ISPEF_NEW_PLUS_HALO) {
123 std::vector<dbNet*> ccHaloNets;
124 block->getCcHaloNets(bnets, ccHaloNets);
125 INCR_SPEF_TYPE type =
126 isftype == ISPEF_ORIGINAL_PLUS_HALO ? ISPEF_ORIGINAL : ISPEF_NEW;
127 writeIncrementalSpef(bnets, ccHaloNets, block, type, coupled_rc,
128 dual_incr_spef); // wis 3
129 } else
130 writeIncrementalSpef(bnets, block, isftype, coupled_rc,
131 dual_incr_spef); // wis 4
132 }
133
134 // wis 2
writeIncrementalSpef(Darr<dbNet * > & buf_nets,std::vector<dbNet * > & ccHaloNets,dbBlock * block,INCR_SPEF_TYPE isftype,bool coupled_rc,bool dual_incr_spef)135 void extMain::writeIncrementalSpef(Darr<dbNet*>& buf_nets,
136 std::vector<dbNet*>& ccHaloNets,
137 dbBlock* block, INCR_SPEF_TYPE isftype,
138 bool coupled_rc, bool dual_incr_spef) {
139 std::vector<dbNet*> bnets;
140 int nn;
141 for (nn = 0; nn < buf_nets.n(); nn++)
142 bnets.push_back(buf_nets.get(nn));
143 uint jj;
144 for (jj = 0; jj < ccHaloNets.size(); jj++)
145 bnets.push_back(ccHaloNets[jj]);
146 writeIncrementalSpef(bnets, block, isftype, coupled_rc,
147 dual_incr_spef); // wis 4
148 }
149
150 // wis 3
writeIncrementalSpef(std::vector<dbNet * > & buf_nets,std::vector<dbNet * > & ccHaloNets,dbBlock * block,INCR_SPEF_TYPE isftype,bool coupled_rc,bool dual_incr_spef)151 void extMain::writeIncrementalSpef(std::vector<dbNet*>& buf_nets,
152 std::vector<dbNet*>& ccHaloNets,
153 dbBlock* block, INCR_SPEF_TYPE isftype,
154 bool coupled_rc, bool dual_incr_spef) {
155 std::vector<dbNet*> bnets;
156 uint jj;
157 for (jj = 0; jj < buf_nets.size(); jj++)
158 bnets.push_back(buf_nets[jj]);
159 for (jj = 0; jj < ccHaloNets.size(); jj++)
160 bnets.push_back(ccHaloNets[jj]);
161 writeIncrementalSpef(bnets, block, isftype, coupled_rc,
162 dual_incr_spef); // wis 4
163 }
164
165 // wis 4
writeIncrementalSpef(std::vector<dbNet * > & buf_nets,dbBlock * block,INCR_SPEF_TYPE isftype,bool coupled_rc,bool dual_incr_spef)166 void extMain::writeIncrementalSpef(std::vector<dbNet*>& buf_nets,
167 dbBlock* block, INCR_SPEF_TYPE isftype,
168 bool coupled_rc, bool dual_incr_spef) {
169 extMain* tmiExt = (extMain*)block->getExtmi();
170 if (tmiExt == NULL) {
171 tmiExt = new extMain(0);
172 tmiExt->init((dbDatabase*)block->getDataBase(), logger_);
173 // tmiExt -> setDesign((char *)block->getConstName());
174 }
175 tmiExt->writeIncrementalSpef(buf_nets, isftype, coupled_rc,
176 dual_incr_spef); // wis 5
177 }
178
179 // wis 5
writeIncrementalSpef(std::vector<dbNet * > & bnets,INCR_SPEF_TYPE isftype,bool coupled_rc,bool dual_incr_spef)180 void extMain::writeIncrementalSpef(std::vector<dbNet*>& bnets,
181 INCR_SPEF_TYPE isftype, bool coupled_rc,
182 bool dual_incr_spef) {
183 if (isftype == ISPEF_ORIGINAL && !_origSpefFilePrefix)
184 return;
185 if (isftype == ISPEF_NEW && !_newSpefFilePrefix)
186 return;
187 std::vector<dbNet*> dumnet;
188 bool fullIncrSpef =
189 coupled_rc && !dual_incr_spef && !_noFullIncrSpef ? true : false;
190 std::vector<dbNet*>* pbnets = fullIncrSpef ? &dumnet : &bnets;
191 if (!_spef || _spef->getBlock() != _block) {
192 if (_spef)
193 delete _spef;
194 _spef = new extSpef(_tech, _block, logger_, this);
195 // copy block name for incremental spef - needed for magma
196 // Mattias - Nov 19/07
197 _spef->setDesign((char*)_block->getName().c_str());
198 }
199 _spef->_writeNameMap = _writeNameMap;
200 _spef->preserveFlag(_prevControl->_foreign);
201 _spef->_independentExtCorners = _prevControl->_independentExtCorners;
202 char filename[1024];
203 char cName[128];
204 char seqName[64];
205 const char* newp = "/tmp/new";
206 if (_newSpefFilePrefix)
207 newp = _newSpefFilePrefix;
208 const char* oldp = "/tmp/orig";
209 if (_origSpefFilePrefix)
210 oldp = _origSpefFilePrefix;
211 uint cCnt = _block->getCornerCount();
212 uint nn;
213 for (nn = 0; nn < cCnt; nn++) {
214 _spef->_active_corner_cnt = 1;
215 _spef->_active_corner_number[0] = nn;
216 // _spef->_db_ext_corner= nn;
217 _block->getExtCornerName(nn, &cName[0]);
218 if (cName[0] == '\0')
219 sprintf(&cName[0], "MinMax%d", nn);
220 if (_bufSpefCnt && (1 == 0))
221 sprintf(&seqName[0], "%d.%s", _bufSpefCnt++, &cName[0]);
222 else
223 sprintf(&seqName[0], "%s", &cName[0]);
224 if (isftype == ISPEF_ORIGINAL)
225 sprintf(filename, "%s.%s", oldp, &seqName[0]);
226 else
227 sprintf(filename, "%s.%s", newp, &seqName[0]);
228 writeIncrementalSpef(filename, *pbnets, nn, dual_incr_spef); // wis 6
229 }
230 delete _spef;
231 _spef = NULL;
232 }
233
234 // wis 6
writeIncrementalSpef(char * filename,std::vector<dbNet * > & bnets,uint nn,bool dual_incr_spef)235 void extMain::writeIncrementalSpef(char* filename, std::vector<dbNet*>& bnets,
236 uint nn, bool dual_incr_spef) {
237 uint cnt;
238 char fname[1200];
239 if (!dual_incr_spef) {
240 debugPrint(logger_, RCX, "spef_out", 1,
241 "EXT_SPEF:"
242 "I "
243 "Writing Spef to File {}",
244 filename);
245 sprintf(&fname[0], "%s.%d.spef", filename, nn);
246 if (openSpefFile(fname, 1) > 0)
247 logger_->info(RCX, 483, "Can't open file \"{}\" to write spef.", filename);
248 else
249 cnt = _spef->writeBlock(
250 NULL /*nodeCoord*/, _excludeCells, "PF" /*capUnit*/,
251 "OHM" /*resUnit*/, false /*stopAfterMap*/, bnets /*tnets*/,
252 false /*wClock*/, false /*wConn*/, false /*wCap*/,
253 false /*wOnlyCCcap*/, false /*wRes*/, false /*noCnum*/,
254 false /*initOnly*/, _incrNoBackSlash /*noBackSlash*/,
255 false /*flatten*/, false /*parallel*/);
256 return;
257 }
258 std::vector<uint> oldNetCap;
259 std::vector<uint> oldNetRseg;
260 _block->replaceOldParasitics(bnets, oldNetCap, oldNetRseg);
261 sprintf(&fname[0], "%s.1.%d.spef", filename, nn);
262 if (openSpefFile(fname, 1) > 0)
263 logger_->info(RCX, 59, "Can't open file \"{}\" to write spef.", fname);
264 else
265 cnt = _spef->writeBlock(
266 NULL /*nodeCoord*/, _excludeCells, "PF" /*capUnit*/, "OHM" /*resUnit*/,
267 false /*stopAfterMap*/, bnets /*tnets*/, false /*wClock*/,
268 false /*wConn*/, false /*wCap*/, false /*wOnlyCCcap*/, false /*wRes*/,
269 false /*noCnum*/, false /*initOnly*/, _incrNoBackSlash /*noBackSlash*/,
270 false /*flatten*/, false /*parallel*/);
271 _block->restoreOldParasitics(bnets, oldNetCap, oldNetRseg);
272 sprintf(&fname[0], "%s.2.%d.spef", filename, nn);
273 if (openSpefFile(fname, 1) > 0)
274 logger_->info(RCX, 61, "Can't open file \"{}\" to write spef.", fname);
275 else
276 cnt = _spef->writeBlock(
277 NULL /*nodeCoord*/, _excludeCells, "PF" /*capUnit*/, "OHM" /*resUnit*/,
278 false /*stopAfterMap*/, bnets /*tnets*/, false /*wClock*/,
279 false /*wConn*/, false /*wCap*/, false /*wOnlyCCcap*/, false /*wRes*/,
280 false /*noCnum*/, false /*initOnly*/, _incrNoBackSlash /*noBackSlash*/,
281 false /*flatten*/, false /*parallel*/);
282 }
283
writeSpef(char * filename,std::vector<dbNet * > & tnets,int corner,char * coord)284 void extMain::writeSpef(char* filename, std::vector<dbNet*>& tnets, int corner,
285 char* coord) {
286 if (!_spef || _spef->getBlock() != _block) {
287 if (_spef)
288 delete _spef;
289 _spef = new extSpef(_tech, _block, logger_, this);
290 }
291 _spef->setDesign((char*)_block->getConstName());
292 uint cCnt = _block->getCornerCount();
293 if (corner >= 0) {
294 _spef->_active_corner_cnt = 1;
295 _spef->_active_corner_number[0] = corner;
296 } else {
297 _spef->_active_corner_cnt = cCnt;
298 for (uint nn = 0; nn < cCnt; nn++)
299 _spef->_active_corner_number[nn] = nn;
300 }
301 uint cnt;
302 if (openSpefFile(filename, 1) > 0) {
303 logger_->info(RCX, 62, "Can't open file \"{}\" to write spef.", filename);
304 return;
305 } else
306 cnt = _spef->writeBlock(
307 coord /*nodeCoord*/, NULL /*excludeCell*/, "PF" /*capUnit*/,
308 "OHM" /*resUnit*/, false /*stopAfterMap*/, tnets /*tnets*/,
309 false /*wClock*/, false /*wConn*/, false /*wCap*/, false /*wOnlyCCcap*/,
310 false /*wRes*/, false /*noCnum*/, false /*initOnly*/,
311 false /*noBackSlash*/, false /*flatten*/, false /*parallel*/);
312 delete _spef;
313 _spef = NULL;
314 }
315
adjustRC(double resFactor,double ccFactor,double gndcFactor)316 void extMain::adjustRC(double resFactor, double ccFactor, double gndcFactor) {
317 double res_factor = resFactor / _resFactor;
318 _resFactor = resFactor;
319 _resModify = resFactor == 1.0 ? false : true;
320 double cc_factor = ccFactor / _ccFactor;
321 _ccFactor = ccFactor;
322 _ccModify = ccFactor == 1.0 ? false : true;
323 double gndc_factor = gndcFactor / _gndcFactor;
324 _gndcFactor = gndcFactor;
325 _gndcModify = gndcFactor == 1.0 ? false : true;
326 _block->adjustRC(res_factor, cc_factor, gndc_factor);
327 }
328
getMultiples(uint cnt,uint base)329 uint extMain::getMultiples(uint cnt, uint base) {
330 return ((cnt / base) + 1) * base;
331 }
setupMapping(uint itermCnt)332 void extMain::setupMapping(uint itermCnt) {
333 if (_btermTable)
334 return;
335 uint btermCnt = 0;
336 if ((itermCnt == 0) && (_block != NULL)) {
337 btermCnt = _block->getBTerms().size();
338 btermCnt = getMultiples(btermCnt, 1024);
339
340 itermCnt = _block->getITerms().size();
341 itermCnt = getMultiples(itermCnt, 1024);
342 } else if (itermCnt == 0) {
343 btermCnt = 512;
344 itermCnt = 64000;
345 }
346 _btermTable = new Ath__array1D<int>(btermCnt);
347 _itermTable = new Ath__array1D<int>(itermCnt);
348 _nodeTable = new Ath__array1D<int>(16000);
349 }
extMain(uint menuId)350 extMain::extMain(uint menuId)
351 : _db(nullptr),
352 _tech(nullptr),
353 _block(nullptr),
354 _spef(nullptr),
355 _origSpefFilePrefix(nullptr),
356 _newSpefFilePrefix(nullptr),
357 _excludeCells(nullptr),
358 _ibox(nullptr),
359 _seqPool(nullptr),
360 _dgContextBaseTrack(nullptr),
361 _dgContextLowTrack(nullptr),
362 _dgContextHiTrack(nullptr),
363 _dgContextTrackBase(nullptr),
364 _prevControl(nullptr),
365 _wireBinTable(nullptr),
366 _cntxBinTable(nullptr),
367 _cntxInstTable(nullptr),
368 _tiles(nullptr),
369 _blkInfoVDD(nullptr),
370 _viaInfoVDD(nullptr),
371 _blkInfoGND(nullptr),
372 _viaInfoGND(nullptr),
373 _stdCirVDD(nullptr),
374 _globCirVDD(nullptr),
375 _globGeomVDD(nullptr),
376 _stdCirGND(nullptr),
377 _globCirGND(nullptr),
378 _stdCirHeadVDD(nullptr),
379 _globCirHeadVDD(nullptr),
380 _globGeomGND(nullptr),
381 _stdCirHeadGND(nullptr),
382 _globCirHeadGND(nullptr),
383 _blkInfo(nullptr),
384 _viaInfo(nullptr),
385 _globCir(nullptr),
386 _globGeom(nullptr),
387 _stdCir(nullptr),
388 _globCirHead(nullptr),
389 _stdCirHead(nullptr),
390 _viaStackGlobCir(nullptr),
391 _viaStackGlobVDD(nullptr),
392 _viaStackGlobGND(nullptr),
393 _junct2viaMap(nullptr),
394 _netUtil(nullptr),
395 _viaM1Table(nullptr),
396 _viaUpTable(nullptr),
397 _via2JunctionMap(nullptr),
398 _supplyViaMap{nullptr, nullptr},
399 _supplyViaTable{nullptr, nullptr},
400 _coordsFP(nullptr),
401 _coordsGND(nullptr),
402 _coordsVDD(nullptr),
403 _subCktNodeFP{{nullptr, nullptr}, {nullptr, nullptr}},
404 _junct2iterm(nullptr) {
405 _previous_percent_extracted = 0;
406 _power_extract_only = false;
407 _skip_power_stubs = false;
408 _power_exclude_cell_list = NULL;
409
410 _modelTable = new Ath__array1D<extRCModel*>(8);
411
412 _btermTable = NULL;
413 _itermTable = NULL;
414 _nodeTable = NULL;
415
416 _extNetSDB = NULL;
417 _extCcapSDB = NULL;
418 _reExtCcapSDB = NULL;
419
420 _reuseMetalFill = false;
421 _usingMetalPlanes = 0;
422 _alwaysNewGs = true;
423 _ccUp = 0;
424 _couplingFlag = 0;
425 _debug = 0;
426 _ccContextDepth = 0;
427 _mergeViaRes = false;
428 _mergeResBound = 0.0;
429 _mergeParallelCC = false;
430 _unifiedMeasureInit = true;
431 _reportNetNoWire = false;
432 _netNoWireCnt = 0;
433
434 _resFactor = 1.0;
435 _resModify = false;
436 _ccFactor = 1.0;
437 _ccModify = false;
438 _gndcFactor = 1.0;
439 _gndcModify = false;
440
441 _menuId = menuId;
442 _dbPowerId = 1;
443 _dbSignalId = 2;
444 _CCsegId = 3;
445 /*
446 _dbPowerId= ZSUBMENUID(_menuId, 1);
447 _dbSignalId= ZSUBMENUID(_menuId, 2);
448 _CCsegId= ZSUBMENUID(_menuId, 3);
449 */
450
451 _CCnoPowerSource = 0;
452 _CCnoPowerTarget = 0;
453
454 _coupleThreshold = 0.1; // fF
455 _lefRC = false;
456
457 _singlePlaneLayerMap = NULL;
458 _overUnderPlaneLayerMap = NULL;
459 _usingMetalPlanes = false;
460 _alwaysNewGs = true;
461 _geomSeq = NULL;
462
463 _dgContextArray = NULL;
464
465 _ccContextLength = NULL;
466 _ccContextArray = NULL;
467 _ccMergedContextLength = NULL;
468 _ccMergedContextArray = NULL;
469 _tContextArray = NULL;
470
471 _noModelRC = false;
472
473 _currentModel = NULL;
474 _geoThickTable = NULL;
475
476 _measureRcCnt = -1;
477 _shapeRcCnt = -1;
478 _updateTotalCcnt = -1;
479 _printFile = NULL;
480 _ptFile = NULL;
481
482 _extRun = 0;
483 _independentExtCorners = false;
484 _foreign = false;
485 _overCell = false;
486 _diagFlow = false;
487 _processCornerTable = NULL;
488 _scaledCornerTable = NULL;
489 _batchScaleExt = true;
490 _cornerCnt = 0;
491 _rotatedGs = false;
492
493 _getBandWire = false;
494 _searchFP = NULL;
495 _search = NULL;
496 _printBandInfo = false;
497
498 _writeNameMap = true;
499 _fullIncrSpef = false;
500 _noFullIncrSpef = false;
501 _adjust_colinear = false;
502 _power_source_file = NULL;
503 }
504
initDgContextArray()505 void extMain::initDgContextArray() {
506 _dgContextDepth = 3;
507 _dgContextPlanes = _dgContextDepth * 2 + 1;
508 _dgContextArray = new Ath__array1D<SEQ*>** [_dgContextPlanes];
509 _dgContextBaseTrack = new uint[_dgContextPlanes];
510 _dgContextLowTrack = new int[_dgContextPlanes];
511 _dgContextHiTrack = new int[_dgContextPlanes];
512 _dgContextTrackBase = new int* [_dgContextPlanes];
513 if (_diagFlow)
514 // _dgContextTracks = (_couplingFlag%10)*2 + 1;
515 _dgContextTracks = _couplingFlag * 2 + 1;
516 else
517 _dgContextTracks = _couplingFlag * 2 + 1;
518 for (uint jj = 0; jj < _dgContextPlanes; jj++) {
519 _dgContextTrackBase[jj] = new int[1024];
520 _dgContextArray[jj] = new Ath__array1D<SEQ*>* [_dgContextTracks];
521 for (uint tt = 0; tt < _dgContextTracks; tt++) {
522 _dgContextArray[jj][tt] = new Ath__array1D<SEQ*>(1024);
523 }
524 }
525 }
526
removeDgContextArray()527 void extMain::removeDgContextArray() {
528 if (!_dgContextPlanes || !_dgContextArray)
529 return;
530 delete[] _dgContextBaseTrack;
531 delete[] _dgContextLowTrack;
532 delete[] _dgContextHiTrack;
533 for (uint jj = 0; jj < _dgContextPlanes; jj++) {
534 delete[] _dgContextTrackBase[jj];
535 for (uint tt = 0; tt < _dgContextTracks; tt++)
536 delete _dgContextArray[jj][tt];
537 delete[] _dgContextArray[jj];
538 }
539 delete[] _dgContextTrackBase;
540 delete[] _dgContextArray;
541 _dgContextArray = NULL;
542 }
543
initContextArray()544 void extMain::initContextArray() {
545 if (_ccContextArray)
546 return;
547 uint layerCnt = getExtLayerCnt(_tech);
548 _ccContextLength = (uint*)calloc(sizeof(uint), layerCnt + 1);
549 _ccContextArray = new Ath__array1D<int>* [layerCnt + 1];
550 _ccContextArray[0] = NULL;
551 uint ii;
552 for (ii = 1; ii <= layerCnt; ii++)
553 _ccContextArray[ii] = new Ath__array1D<int>(1024);
554 _ccMergedContextLength = (uint*)calloc(sizeof(uint), layerCnt + 1);
555 _ccMergedContextArray = new Ath__array1D<int>* [layerCnt + 1];
556 _ccMergedContextArray[0] = NULL;
557 for (ii = 1; ii <= layerCnt; ii++)
558 _ccMergedContextArray[ii] = new Ath__array1D<int>(1024);
559 _tContextArray = new Ath__array1D<int>(1024);
560 }
561
getExtLayerCnt(dbTech * tech)562 uint extMain::getExtLayerCnt(dbTech* tech) {
563 dbSet<dbTechLayer> layers = tech->getLayers();
564 dbSet<dbTechLayer>::iterator itr;
565
566 uint n = 0;
567 for (itr = layers.begin(); itr != layers.end(); ++itr) {
568 dbTechLayer* layer = *itr;
569 dbTechLayerType type = layer->getType();
570
571 if (type.getValue() != dbTechLayerType::ROUTING)
572 continue;
573
574 n++;
575 }
576 return n;
577 }
addExtModel(dbTech * tech)578 uint extMain::addExtModel(dbTech* tech) {
579 _lefRC = true;
580
581 if (tech == NULL)
582 tech = _tech;
583
584 _extDbCnt = 3;
585
586 uint layerCnt = getExtLayerCnt(tech);
587
588 extRCModel* m = NULL;
589 /*
590 if (_modelTable->getCnt()>0)
591 m= _modelTable->get(0);
592 */
593 if (m == NULL) {
594 m = new extRCModel(layerCnt, "TYPICAL", logger_);
595 _modelTable->add(m);
596 }
597
598 int dbunit = _block->getDbUnitsPerMicron();
599 double dbFactor = 1;
600 if (dbunit > 1000)
601 dbFactor = dbunit * 0.001;
602
603 dbSet<dbTechLayer> layers = tech->getLayers();
604 dbSet<dbTechLayer>::iterator itr;
605
606 uint n = 0;
607 for (itr = layers.begin(); itr != layers.end(); ++itr) {
608 dbTechLayer* layer = *itr;
609 dbTechLayerType type = layer->getType();
610
611 if (type.getValue() != dbTechLayerType::ROUTING)
612 continue;
613
614 n = layer->getRoutingLevel();
615
616 uint w = layer->getWidth(); // nm
617
618 double areacap = layer->getCapacitance() / (dbFactor * dbFactor);
619 double cap = layer->getCapacitance();
620
621 // double cap
622 // = layer->getCapacitance()
623 // / (dbFactor * dbFactor); // PF per square micron : totCap= cap * LW
624 double res = layer->getResistance(); // OHMS per square
625 // uint w = layer->getWidth(); // nm
626 // res /= w; // OHMS per nm
627 // cap *= 0.001 * w; // FF per nm : 0.00
628 cap *= 0.001 * 2;
629
630 m->addLefTotRC(n, 0, cap, res);
631
632 double c1 = m->getTotCapOverSub(n);
633 double r1 = m->getRes(n);
634
635 _minWidthTable[n] = w;
636
637 _resistanceTable[0][n] = r1;
638 _capacitanceTable[0][n] = c1;
639 }
640 return layerCnt;
641 }
getRCmodel(uint n)642 extRCModel* extMain::getRCmodel(uint n) {
643 if (_modelTable->getCnt() <= 0)
644 return NULL;
645
646 return _modelTable->get(n);
647 }
getResCapTable(bool lefRC)648 uint extMain::getResCapTable(bool lefRC) {
649 calcMinMaxRC();
650 _currentModel = getRCmodel(0);
651
652 dbSet<dbTechLayer> layers = _tech->getLayers();
653 dbSet<dbTechLayer>::iterator itr;
654
655 extMeasure m;
656 m._underMet = 0;
657 m._overMet = 0;
658
659 uint cnt = 0;
660 uint n = 0;
661 bool allRzero = true;
662 for (itr = layers.begin(); itr != layers.end(); ++itr) {
663 dbTechLayer* layer = *itr;
664 dbTechLayerType type = layer->getType();
665
666 if (type.getValue() != dbTechLayerType::ROUTING)
667 continue;
668
669 n = layer->getRoutingLevel();
670
671 uint w = layer->getWidth(); // nm
672 _minWidthTable[n] = w;
673
674 m._width = w;
675 m._met = n;
676
677 uint sp = layer->getSpacing(); // nm
678
679 _minDistTable[n] = sp;
680 if (sp == 0) {
681 sp = layer->getPitch() - layer->getWidth();
682 _minDistTable[n] = sp;
683 }
684 double resTable[20];
685 bool newResModel = true;
686 if (newResModel) {
687 for (uint jj = 0; jj < _modelMap.getCnt(); jj++) {
688 resTable[jj] = 0.0;
689 }
690 calcRes0(resTable, n, w, 1);
691 }
692 for (uint jj = 0; jj < _modelMap.getCnt(); jj++) {
693 uint modelIndex = _modelMap.get(jj);
694 extMetRCTable* rcModel = _currentModel->getMetRCTable(modelIndex);
695
696 double res = layer->getResistance(); // OHMS per square
697 if (res != 0.0)
698 allRzero = false;
699 _resistanceTable[jj][n] = res;
700
701 _capacitanceTable[jj][n] = 0.0;
702
703 extDistRC* rc = rcModel->getOverFringeRC(&m);
704
705 if (rc != NULL) {
706 double r1 = rc->getRes();
707 _capacitanceTable[jj][n] = rc->getFringe();
708 debugPrint(logger_, RCX, "extrules", 1,
709 "EXT_RES: "
710 "R "
711 "Layer= {} met= {} w= {} cc= {:g} fr= {:g} res= {:g} "
712 "model_res= {:g} new_model_res= {:g} ",
713 layer->getConstName(), n, w, rc->getCoupling(),
714 rc->getFringe(), res, r1, resTable[jj]);
715 }
716
717 extDistRC* rc0 = rcModel->getOverFringeRC(&m, 0);
718
719 if (!_lef_res) {
720 if (newResModel) {
721 _resistanceTable[jj][n] = resTable[jj];
722 } else {
723 if (rc0 != NULL) {
724 double r1 = rc->getRes();
725 _resistanceTable[jj][n] = r1;
726 }
727 }
728 } else {
729 debugPrint(logger_, RCX, "extrules", 1,
730 "EXT_RES_LEF: "
731 "R "
732 "Layer= {} met= {} lef_res= {:g}\n",
733 layer->getConstName(), n, res);
734 }
735 }
736 cnt++;
737 }
738 return cnt;
739 }
checkLayerResistance()740 bool extMain::checkLayerResistance() {
741 dbSet<dbTechLayer> layers = _tech->getLayers();
742 dbSet<dbTechLayer>::iterator itr;
743
744 uint cnt = 0;
745 for (itr = layers.begin(); itr != layers.end(); ++itr) {
746 dbTechLayer* layer = *itr;
747 dbTechLayerType type = layer->getType();
748
749 if (type.getValue() != dbTechLayerType::ROUTING)
750 continue;
751
752 double res = layer->getResistance(); // OHMS per square
753
754 if (res <= 0.0) {
755 logger_->warn(RCX, 139, "Missing Resistance value for layer {}",
756 layer->getConstName());
757 cnt++;
758 }
759 }
760 if (cnt > 0) {
761 logger_->warn(RCX, 138,
762 "{} layers are missing resistance value; Check LEF file. "
763 "Extraction cannot proceed! Exiting",
764 cnt);
765 return false;
766 }
767 return true;
768 }
getLefResistance(uint level,uint width,uint len,uint model)769 double extMain::getLefResistance(uint level, uint width, uint len, uint model) {
770 double res = _resistanceTable[model][level];
771 double n = 1.0 * len;
772
773 if (_lefRC || _lef_res)
774 n /= width;
775
776 double r = n * res;
777
778 return r;
779 }
getResistance(uint level,uint width,uint len,uint model)780 double extMain::getResistance(uint level, uint width, uint len, uint model) {
781 /*
782 if (_lefRC) {
783 double res= _resistanceTable[0][level];
784 // double res= _modelTable->get(0)->getRes(level);
785 res *= len;
786 return res;
787
788 }
789 return getLefResistance(level, width, len, model);
790 */
791 return getLefResistance(level, width, len, model);
792 /*This the flow to use extrule esistance. Disable now but will be used in
793 future. if (_lefRC) {
794 // TO TEST regrs. test and relpace :
795 return getLefResistance(level, width, len, model);
796 }
797 else {
798 if (_minWidthTable[level]==width) {
799 double res= _resistanceTable[0][level];
800 res *= 2*len;
801 return res;
802 } else {
803 extMeasure m;
804 m._underMet= 0;
805 m._overMet= 0;
806 m._width= width;
807 m._met= level;
808 uint modelIndex= _modelMap.get(model);
809 extDistRC
810 *rc=_currentModel->getMetRCTable(modelIndex)->getOverFringeRC(&m); double
811 res= rc->getRes(); res *= 2*len; return res;
812 }
813 }
814 */
815 }
setBlockFromChip()816 void extMain::setBlockFromChip() {
817 _tech = _db->getTech();
818 _block = _db->getChip()->getBlock();
819 _blockId = _block->getId();
820 _prevControl = _block->getExtControl();
821 #ifndef _WIN32
822 _block->setExtmi(this);
823 #endif
824
825 if(_spef != nullptr) {
826 _spef = nullptr;
827 _extracted = false;
828 }
829
830 _bufSpefCnt = 0;
831 _origSpefFilePrefix = nullptr;
832 _newSpefFilePrefix = nullptr;
833 _excludeCells = nullptr;
834 }
835
setBlock(dbBlock * block)836 void extMain::setBlock(dbBlock* block) {
837 _block = block;
838 _prevControl = _block->getExtControl();
839 #ifndef _WIN32
840 _block->setExtmi(this);
841 #endif
842 _blockId = _block->getId();
843 if (_spef) {
844 _spef = NULL;
845 _extracted = false;
846 }
847 _bufSpefCnt = 0;
848 _origSpefFilePrefix = NULL;
849 _newSpefFilePrefix = NULL;
850 _excludeCells = NULL;
851 }
makeGuiBoxes(uint extGuiBoxType)852 uint extMain::makeGuiBoxes(uint extGuiBoxType) {
853 uint cnt = 0;
854 return cnt;
855 }
856
computeXcaps(uint boxType)857 uint extMain::computeXcaps(uint boxType) {
858 ZPtr<ISdb> ccCapSdb = _reExtract ? _reExtCcapSDB : _extCcapSDB;
859 if (ccCapSdb == NULL)
860 return 0;
861
862 uint cnt = 0;
863 ccCapSdb->searchWireIds(_x1, _y1, _x2, _y2, true, NULL);
864
865 ccCapSdb->startIterator();
866
867 bool mergeParallel = _mergeParallelCC;
868 uint wireId = 0;
869 while ((wireId = ccCapSdb->getNextWireId())) {
870 uint len, dist, id1, id2;
871 ccCapSdb->getCCdist(wireId, &dist, &len, &id1, &id2);
872
873 uint extId1;
874 uint junctionId1;
875 uint wtype1;
876 _extNetSDB->getIds(id1, &extId1, &junctionId1, &wtype1);
877
878 if (wtype1 == _dbPowerId)
879 continue;
880
881 uint extId2, junctionId2, wtype2;
882 _extNetSDB->getIds(id2, &extId2, &junctionId2, &wtype2);
883
884 if (wtype2 == _dbPowerId)
885 continue;
886
887 dbRSeg* rseg1 = dbRSeg::getRSeg(_block, extId1);
888 dbRSeg* rseg2 = dbRSeg::getRSeg(_block, extId2);
889
890 dbNet* srcNet = rseg1->getNet();
891 dbNet* tgtNet = rseg2->getNet();
892
893 if (srcNet == tgtNet)
894 continue;
895
896 // dbCCSeg *ccap= dbCCSeg::create(srcNet, rseg1->getTargetNode(),
897 // tgtNet, rseg2->getTargetNode(), mergeParallel);
898 dbCCSeg* ccap = dbCCSeg::create(
899 dbCapNode::getCapNode(_block, rseg1->getTargetNode()),
900 dbCapNode::getCapNode(_block, rseg2->getTargetNode()), mergeParallel);
901
902 uint lcnt = _block->getCornerCount();
903 for (uint ii = 0; ii < lcnt; ii++) {
904 if (mergeParallel)
905 ccap->addCapacitance(len / dist + ii, ii);
906 else
907 ccap->setCapacitance(len / dist + ii, ii);
908 }
909
910 cnt++;
911 }
912 return cnt;
913 }
914
getLoCoupling()915 double extMain::getLoCoupling() { return _coupleThreshold; }
916
getFringe(uint met,uint width,uint modelIndex,double & areaCap)917 double extMain::getFringe(uint met, uint width, uint modelIndex,
918 double& areaCap) {
919 areaCap = 0.0;
920 if (_noModelRC)
921 return 0.0;
922
923 if (_lefRC)
924 // return _modelTable->get(0)->getTotCapOverSub(met);
925 return _capacitanceTable[0][met];
926
927 if (width == _minWidthTable[met])
928 return _capacitanceTable[modelIndex][met];
929
930 // just in case
931
932 extMeasure m;
933
934 m._met = met;
935 m._width = width;
936 m._underMet = 0;
937 m._ccContextLength = _ccContextLength;
938 m._ccContextArray = _ccContextArray;
939 m._ccMergedContextLength = _ccMergedContextLength;
940 m._ccMergedContextArray = _ccMergedContextArray;
941
942 extDistRC* rc = _metRCTable.get(modelIndex)->getOverFringeRC(&m);
943
944 /* TODO 10292011
945 if (width>10*_minWidthTable[met]) {
946 extDistRC *rc1= m.areaCapOverSub(modelIndex,
947 _metRCTable.get(modelIndex)); areaCap = rc1->_fringe; return 0.0;
948 }
949 */
950 if (rc == NULL)
951 return 0.0;
952 return rc->getFringe();
953 }
updateTotalCap(dbRSeg * rseg,double frCap,double ccCap,double deltaFr,uint modelIndex)954 void extMain::updateTotalCap(dbRSeg* rseg, double frCap, double ccCap,
955 double deltaFr, uint modelIndex) {
956 if (_eco && !rseg->getNet()->isWireAltered())
957 return;
958
959 double cap = frCap + ccCap - deltaFr;
960
961 double tot = rseg->getCapacitance(modelIndex);
962 tot += cap;
963
964 rseg->setCapacitance(tot, modelIndex);
965 // double T= rseg->getCapacitance(modelIndex);
966 }
updateTotalRes(dbRSeg * rseg1,dbRSeg * rseg2,extMeasure * m,double * delta,uint modelCnt)967 void extMain::updateTotalRes(dbRSeg* rseg1, dbRSeg* rseg2, extMeasure* m,
968 double* delta, uint modelCnt) {
969 for (uint modelIndex = 0; modelIndex < modelCnt; modelIndex++) {
970 extDistRC* rc = m->_rc[modelIndex];
971
972 double res = rc->_res - delta[modelIndex];
973 if (_resModify)
974 res *= _resFactor;
975
976 if ((rseg1 != NULL) && !(_eco && !rseg1->getNet()->isWireAltered())) {
977 double tot = rseg1->getResistance(modelIndex);
978 tot += res;
979
980 /*
981 if (_updateTotalCcnt >= 0)
982 {
983 if (_printFile == NULL)
984 _printFile =fopen ("updateRes.1", "w");
985 _updateTotalCcnt++;
986 fprintf (_printFile, "%d %d %g %g\n", _updateTotalCcnt, rseg->getId(),
987 tot, cap);
988 }
989 */
990
991 rseg1->setResistance(tot, modelIndex);
992 // double T= rseg1->getResistance(modelIndex);
993 }
994 if ((rseg2 != NULL) && !(_eco && !rseg2->getNet()->isWireAltered())) {
995 double tot = rseg2->getResistance(modelIndex);
996 tot += res;
997
998 /*
999 if (_updateTotalCcnt >= 0)
1000 {
1001 if (_printFile == NULL)
1002 _printFile =fopen ("updateRes.1", "w");
1003 _updateTotalCcnt++;
1004 fprintf (_printFile, "%d %d %g %g\n", _updateTotalCcnt, rseg->getId(),
1005 tot, cap);
1006 }
1007 */
1008
1009 rseg2->setResistance(tot, modelIndex);
1010 // double T= rseg2->getResistance(modelIndex);
1011 }
1012 }
1013 }
1014
updateTotalCap(dbRSeg * rseg,extMeasure * m,double * deltaFr,uint modelCnt,bool includeCoupling,bool includeDiag)1015 void extMain::updateTotalCap(dbRSeg* rseg, extMeasure* m, double* deltaFr,
1016 uint modelCnt, bool includeCoupling,
1017 bool includeDiag) {
1018 if (_eco && !rseg->getNet()->isWireAltered())
1019 return;
1020
1021 double tot, cap;
1022 int extDbIndex, sci, scDbIdx;
1023 for (uint modelIndex = 0; modelIndex < modelCnt; modelIndex++) {
1024 extDistRC* rc = m->_rc[modelIndex];
1025
1026 double frCap = rc->_fringe;
1027
1028 double ccCap = 0.0;
1029 if (includeCoupling)
1030 ccCap = rc->_coupling;
1031
1032 double diagCap = 0.0;
1033 if (includeDiag)
1034 diagCap = rc->_diag;
1035
1036 #ifdef HI_ACC_1
1037 cap = frCap + ccCap + diagCap - deltaFr[modelIndex];
1038 #else
1039 cap = frCap + ccCap - deltaFr[modelIndex];
1040 #endif
1041 if (_gndcModify)
1042 cap *= _gndcFactor;
1043
1044 extDbIndex = getProcessCornerDbIndex(modelIndex);
1045 tot = rseg->getCapacitance(extDbIndex);
1046 tot += cap;
1047 if (_updateTotalCcnt >= 0) {
1048 if (_printFile == NULL)
1049 _printFile = fopen("updateCap.1", "w");
1050 _updateTotalCcnt++;
1051 fprintf(_printFile, "%d %d %g %g\n", _updateTotalCcnt, rseg->getId(), tot,
1052 cap);
1053 }
1054
1055 rseg->setCapacitance(tot, extDbIndex);
1056 // double T= rseg->getCapacitance(extDbIndex);
1057 getScaledCornerDbIndex(modelIndex, sci, scDbIdx);
1058 if (sci == -1)
1059 continue;
1060 getScaledGndC(sci, cap);
1061 tot = rseg->getCapacitance(scDbIdx);
1062 tot += cap;
1063 rseg->setCapacitance(tot, scDbIdx);
1064 }
1065 }
1066
updateCCCap(dbRSeg * rseg1,dbRSeg * rseg2,double ccCap)1067 void extMain::updateCCCap(dbRSeg* rseg1, dbRSeg* rseg2, double ccCap) {
1068 dbCCSeg* ccap = dbCCSeg::create(
1069 dbCapNode::getCapNode(_block, rseg1->getTargetNode()),
1070 dbCapNode::getCapNode(_block, rseg2->getTargetNode()), true);
1071 /*
1072 dbCCSeg *ccap= dbCCSeg::create(rseg1->getNet(),
1073 rseg1->getTargetNode(), rseg2->getNet(), rseg2->getTargetNode(), true);
1074 */
1075 bool mergeParallel = true;
1076
1077 uint lcnt = _block->getCornerCount();
1078 lcnt = 1;
1079 for (uint ii = 0; ii < lcnt; ii++) {
1080 if (mergeParallel)
1081 ccap->addCapacitance(ccCap, ii);
1082 else
1083 ccap->setCapacitance(ccCap, ii);
1084 }
1085 }
getRowCol(int xy,int base,uint bucket,uint bound)1086 int extGeoThickTable::getRowCol(int xy, int base, uint bucket, uint bound) {
1087 int delta = (xy - base);
1088 if (delta <= 0)
1089 return delta;
1090
1091 int rowCol = delta / bucket;
1092 if (rowCol >= (int)bound)
1093 return -1;
1094
1095 return rowCol;
1096 }
1097
getSquare(int x,int y,uint * rowCol)1098 extGeoVarTable* extGeoThickTable::getSquare(int x, int y, uint* rowCol) {
1099 int row = getRowCol(y, _ll[1], _tileSize, _rowCnt);
1100 if (row < 0)
1101 return NULL;
1102
1103 int col = getRowCol(x, _ll[0], _tileSize, _colCnt);
1104 if (col < 0)
1105 return NULL;
1106
1107 rowCol[1] = row;
1108 rowCol[0] = col;
1109
1110 return _thickTable[row][col];
1111 }
getLowerBound(uint dir,uint * rowCol)1112 int extGeoThickTable::getLowerBound(uint dir, uint* rowCol) {
1113 return _thickTable[rowCol[0]][rowCol[1]]->getLowerBound(dir);
1114 }
getUpperBound(uint dir,uint * rowCol)1115 int extGeoThickTable::getUpperBound(uint dir, uint* rowCol) {
1116 return _thickTable[rowCol[1]][rowCol[0]]->getLowerBound(dir) + _tileSize;
1117 }
addVarTable(int x,int y,double nom,double e,Ath__array1D<double> * A,bool simpleVersion,bool calcDiff)1118 extGeoVarTable* extGeoThickTable::addVarTable(int x, int y, double nom,
1119 double e, Ath__array1D<double>* A,
1120 bool simpleVersion,
1121 bool calcDiff) {
1122 uint row = (y - _ll[1]) / _tileSize;
1123 assert((row >= 0) && (row < _rowCnt));
1124
1125 uint col = (x - _ll[0]) / _tileSize;
1126 assert((col >= 0) && (col < _colCnt));
1127
1128 extGeoVarTable* b =
1129 new extGeoVarTable(x, y, nom, e, A, simpleVersion, calcDiff);
1130
1131 _thickTable[row][col] = b;
1132
1133 return b;
1134 }
1135
extGeoThickTable(int x1,int y1,int x2,int y2,uint tileSize,Ath__array1D<double> * A,uint units)1136 extGeoThickTable::extGeoThickTable(int x1, int y1, int x2, int y2,
1137 uint tileSize, Ath__array1D<double>* A,
1138 uint units) {
1139 _tileSize = tileSize;
1140 // char *_layerName;
1141
1142 int nm = units;
1143 _ll[0] = x1 * nm;
1144 _ll[1] = y1 * nm;
1145 _ur[0] = x2 * nm;
1146 _ur[1] = y2 * nm;
1147 _rowCnt = (_ur[1] - _ll[1]) / tileSize + 1;
1148 _colCnt = (_ur[0] - _ll[0]) / tileSize + 1;
1149
1150 _thickTable = new extGeoVarTable** [_rowCnt];
1151 for (uint ii = 0; ii < _rowCnt; ii++) {
1152 _thickTable[ii] = new extGeoVarTable* [_colCnt];
1153 for (uint jj = 0; jj < _colCnt; jj++) {
1154 _thickTable[ii][jj] = NULL;
1155 }
1156 }
1157 _widthTable = NULL;
1158 if (A->getCnt() == 0)
1159 return;
1160
1161 int n = A->getCnt() - 1; // last is ( --- TO BE FIXED!!!
1162 if (n == 0)
1163 return;
1164
1165 _widthTable = new Ath__array1D<uint>(n);
1166 for (int i = 0; i < n; i++) {
1167 int w = Ath__double2int(A->get(i));
1168 _widthTable->add(w);
1169 }
1170 }
~extGeoThickTable()1171 extGeoThickTable::~extGeoThickTable() {
1172 if (_widthTable != NULL)
1173 delete _widthTable;
1174
1175 if (_thickTable == NULL)
1176 return;
1177
1178 for (uint ii = 0; ii < _rowCnt; ii++) {
1179 for (uint jj = 0; jj < _colCnt; jj++) {
1180 if (_thickTable[ii][jj] != NULL)
1181 delete _thickTable[ii][jj];
1182 }
1183 delete[] _thickTable[ii];
1184 }
1185 delete[] _thickTable;
1186 }
getVal(uint n,double & nom)1187 double extGeoVarTable::getVal(uint n, double& nom) {
1188 nom = _nominal;
1189 return _diffTable->get(n);
1190 }
getThicknessDiff(int n,double & delta_th)1191 bool extGeoVarTable::getThicknessDiff(int n, double& delta_th) {
1192 if (_fractionDiff) {
1193 if (n < 0)
1194 n = 0;
1195 delta_th = _diffTable->get(n);
1196 return true;
1197 }
1198 double thickDiff = _diffTable->get(n);
1199 if (_simpleVersion) {
1200 delta_th = (thickDiff - _nominal) / _nominal;
1201 return true;
1202 } else {
1203 delta_th = 0.001 * _nominal * (1 + thickDiff);
1204 return true;
1205
1206 // double diff= (th-thRef)/thRef;
1207 }
1208 }
getThicknessDiff(int x,int y,uint w,double & delta_th)1209 bool extGeoThickTable::getThicknessDiff(int x, int y, uint w,
1210 double& delta_th) {
1211 uint rowCol[2];
1212
1213 extGeoVarTable* sq1 = getSquare(x, y, rowCol);
1214 if (sq1 == NULL)
1215 return false;
1216
1217 int n = -1;
1218 if (_widthTable != NULL)
1219 n = _widthTable->findNextBiggestIndex(w);
1220
1221 return sq1->getThicknessDiff(n, delta_th);
1222 }
getLowerBound(uint dir)1223 int extGeoVarTable::getLowerBound(uint dir) {
1224 if (dir > 0)
1225 return _y;
1226 else
1227 return _x;
1228 }
1229
extGeoVarTable(int x,int y,double nom,double e,Ath__array1D<double> * A,bool simpleVersion,bool calcDiff)1230 extGeoVarTable::extGeoVarTable(int x, int y, double nom, double e,
1231 Ath__array1D<double>* A, bool simpleVersion,
1232 bool calcDiff) {
1233 _x = x;
1234 _y = y;
1235 _nominal = nom;
1236 _epsilon = e;
1237
1238 _fractionDiff = false;
1239 _varCoeffTable = NULL;
1240 _diffTable = NULL;
1241
1242 uint n = A->getCnt();
1243 if (n == 0)
1244 return;
1245
1246 _varCoeffTable = new Ath__array1D<double>(n);
1247 _diffTable = new Ath__array1D<double>(n);
1248
1249 if (simpleVersion && calcDiff) {
1250 for (uint ii = 0; ii < n; ii++) {
1251 double v = A->get(ii);
1252
1253 _varCoeffTable->add(v);
1254
1255 double th = (v - _nominal) / _nominal;
1256 _diffTable->add(th);
1257 }
1258 _fractionDiff = true;
1259 return;
1260 }
1261 _varCoeffTable = new Ath__array1D<double>(n);
1262 for (uint ii = 0; ii < n; ii++)
1263 _varCoeffTable->add(A->get(ii));
1264 }
~extGeoVarTable()1265 extGeoVarTable::~extGeoVarTable() {
1266 if (_diffTable != NULL)
1267 delete _diffTable;
1268 if (_varCoeffTable != NULL)
1269 delete _varCoeffTable;
1270 }
ccReportProgress()1271 void extMain::ccReportProgress() {
1272 uint repChunk = 1000000;
1273 if ((_totSegCnt > 0) && (_totSegCnt % repChunk == 0)) {
1274 // if ((_totSignalSegCnt>0)&&(_totSignalSegCnt%5000000==0))
1275 // fprintf(stdout, "Have processed %d total segments, %d signal
1276 // segments, %d CC caps, and stored %d CC caps\n", _totSegCnt,
1277 //_totSignalSegCnt, _totCCcnt, _totBigCCcnt);
1278 logger_->info(RCX, 140,
1279 "Have processed {} total segments, {} signal segments, {} CC "
1280 "caps, and stored {} CC caps",
1281 _totSegCnt, _totSignalSegCnt, _totCCcnt, _totBigCCcnt);
1282 }
1283 }
1284 int ttttsrcnet = 66;
1285 int tttttgtnet = 66;
1286 int ttttm = 0;
printNet(dbNet * net,uint netId)1287 void extMain::printNet(dbNet* net, uint netId) {
1288 if (netId == net->getId())
1289 net->printNetName(stdout);
1290 }
IsDebugNets(dbNet * srcNet,dbNet * tgtNet,uint debugNetId)1291 bool IsDebugNets(dbNet* srcNet, dbNet* tgtNet, uint debugNetId) {
1292 if (srcNet != NULL && srcNet->getId() == debugNetId)
1293 return true;
1294 if (tgtNet != NULL && tgtNet->getId() == debugNetId)
1295 return true;
1296
1297 return false;
1298 }
measureRC(CoupleOptions & options)1299 void extMain::measureRC(CoupleOptions& options) {
1300 _totSegCnt++;
1301 int rsegId1 = options[1]; // dbRSeg id for SRC segment
1302 int rsegId2 = options[2]; // dbRSeg id for Target segment
1303
1304 if ((rsegId1 < 0) && (rsegId2 < 0)) // power nets
1305 return;
1306
1307 extMeasure m;
1308 m.defineBox(options);
1309 m._ccContextLength = _ccContextLength;
1310 m._ccContextArray = _ccContextArray;
1311 m._ccMergedContextLength = _ccMergedContextLength;
1312 m._ccMergedContextArray = _ccMergedContextArray;
1313
1314 // fprintf(stdout, "extCompute:: met= %d len= %d dist= %d <===>
1315 // modelCnt= %d layerCnt= %d\n", met, len, dist,
1316 // m->getModelCnt(), m->getLayerCnt());
1317
1318 uint debugNetId = _debug_net_id;
1319
1320 dbRSeg* rseg1 = NULL;
1321 dbNet* srcNet = NULL;
1322 if (rsegId1 > 0) {
1323 rseg1 = dbRSeg::getRSeg(_block, rsegId1);
1324 srcNet = rseg1->getNet();
1325 printNet(srcNet, debugNetId);
1326 }
1327
1328 dbRSeg* rseg2 = NULL;
1329 dbNet* tgtNet = NULL;
1330 if (rsegId2 > 0) {
1331 rseg2 = dbRSeg::getRSeg(_block, rsegId2);
1332 tgtNet = rseg2->getNet();
1333 printNet(tgtNet, debugNetId);
1334 }
1335 if (_lefRC)
1336 return;
1337
1338 bool watchNets = IsDebugNets(srcNet, tgtNet, debugNetId);
1339 m._ouPixelTableIndexMap = _overUnderPlaneLayerMap;
1340 m._pixelTable = _geomSeq;
1341
1342 _totSignalSegCnt++;
1343
1344 _currentModel = getRCmodel(0);
1345 m._currentModel = _currentModel;
1346 for (uint ii = 0; ii < _metRCTable.getCnt(); ii++) {
1347 m._metRCTable.add(_metRCTable.get(ii));
1348 }
1349 if (m._met >= _currentModel->getLayerCnt()) // TO_TEST
1350 return;
1351
1352 m._layerCnt = _currentModel->getLayerCnt();
1353
1354 double deltaFr[20];
1355 for (uint jj = 0; jj < m._metRCTable.getCnt(); jj++) {
1356 deltaFr[jj] = 0.0;
1357 m._rc[jj]->_coupling = 0.0;
1358 m._rc[jj]->_fringe = 0.0;
1359 m._rc[jj]->_diag = 0.0;
1360 m._rc[jj]->_res = 0.0;
1361 m._rc[jj]->_sep = 0;
1362 }
1363
1364 uint totLenCovered = 0;
1365 if (_usingMetalPlanes) {
1366 if (_ccContextArray && ((!srcNet || (int)srcNet->getId() == ttttsrcnet) ||
1367 (!tgtNet || (int)tgtNet->getId() == tttttgtnet)) &&
1368 (!ttttm || m._met == ttttm)) {
1369 int pxy = m._dir ? m._ll[0] : m._ll[1];
1370 int pbase = m._dir ? m._ur[1] : m._ur[0];
1371 // fprintf(stdout, "Context of layer %d, xy=%d len=%d
1372 // base=%d width=%d :\n", m._met, pxy, m._len, pbase, m._s_nm);
1373 logger_->info(RCX, 141,
1374 "Context of layer {} xy={} len={} base={} width={}", m._met,
1375 pxy, m._len, pbase, m._s_nm);
1376 uint ii, jj;
1377 for (ii = 1; ii <= _ccContextDepth &&
1378 (int)ii + m._met < _currentModel->getLayerCnt();
1379 ii++) {
1380 logger_->info(RCX, 142, " layer {}", ii + m._met);
1381 for (jj = 0; jj < _ccContextArray[ii + m._met]->getCnt(); jj++)
1382 logger_->info(RCX, 476, " {}: {}", jj,
1383 _ccContextArray[ii + m._met]->get(jj));
1384 }
1385 for (ii = 1; ii <= _ccContextDepth && m._met - ii > 0; ii++) {
1386 logger_->info(RCX, 65, " layer {}", m._met - ii);
1387 for (jj = 0; jj < _ccContextArray[m._met - ii]->getCnt(); jj++)
1388 logger_->info(RCX, 143, " {}: {}", jj,
1389 _ccContextArray[m._met - ii]->get(jj));
1390 }
1391 }
1392 // for (uint ii= 0; _ccContextArray!=NULL && m._met>1 &&
1393 // ii<_ccContextArray[m._met]->getCnt(); ii++) {
1394 // fprintf(stdout, "ii= %d
1395 // -- %d\n", ii, _ccContextArray[m._met]->get(ii));
1396 // }
1397 totLenCovered = m.measureOverUnderCap();
1398 }
1399 int lenOverSub = m._len - totLenCovered;
1400
1401 // int mUnder= m._underMet; // will be replaced
1402 if (m._dist < 0) { // dist is infinit
1403
1404 if (totLenCovered > 0) {
1405 m._underMet = 0;
1406 for (uint jj = 0; jj < m._metRCTable.getCnt(); jj++) {
1407 extDistRC* rc = m._metRCTable.get(jj)->getOverFringeRC(&m);
1408 deltaFr[jj] = rc->getFringe() * totLenCovered;
1409 }
1410 }
1411 } else { // dist based
1412
1413 if (lenOverSub > 0) {
1414 m._underMet = 0;
1415 m.computeOverRC(lenOverSub);
1416 }
1417 // deltaFr[jj]= getFringe(m._met, m._width, jj) * m._len; TO_TEST
1418 m.getFringe(m._len, deltaFr);
1419
1420 if ((rsegId1 > 0) && (rsegId2 > 0)) { // signal nets
1421
1422 _totCCcnt++; // TO_TEST
1423
1424 if (m._rc[_minModelIndex]->_coupling < _coupleThreshold) { // TO_TEST
1425 updateTotalCap(rseg1, &m, deltaFr, m._metRCTable.getCnt(), true);
1426 updateTotalCap(rseg2, &m, deltaFr, m._metRCTable.getCnt(), true);
1427
1428 _totSmallCCcnt++;
1429
1430 return;
1431 }
1432 _totBigCCcnt++;
1433
1434 dbCCSeg* ccap = dbCCSeg::create(
1435 dbCapNode::getCapNode(_block, rseg1->getTargetNode()),
1436 dbCapNode::getCapNode(_block, rseg2->getTargetNode()), true);
1437 // dbCCSeg *ccap= dbCCSeg::create(srcNet,
1438 // rseg1->getTargetNode(), tgtNet, rseg2->getTargetNode(), true);
1439
1440 int extDbIndex, sci, scDbIdx;
1441 for (uint jj = 0; jj < m._metRCTable.getCnt(); jj++) {
1442 extDbIndex = getProcessCornerDbIndex(jj);
1443 ccap->addCapacitance(m._rc[jj]->_coupling, extDbIndex);
1444 getScaledCornerDbIndex(jj, sci, scDbIdx);
1445 if (sci != -1) {
1446 double cap = m._rc[jj]->_coupling;
1447 getScaledGndC(sci, cap);
1448 ccap->addCapacitance(cap, scDbIdx);
1449 }
1450 }
1451 updateTotalCap(rseg1, &m, deltaFr, m._metRCTable.getCnt(), false);
1452 updateTotalCap(rseg2, &m, deltaFr, m._metRCTable.getCnt(), false);
1453 } else if (rseg1 != NULL) {
1454 updateTotalCap(rseg1, &m, deltaFr, m._metRCTable.getCnt(), true);
1455 } else if (rseg2 != NULL) {
1456 updateTotalCap(rseg2, &m, deltaFr, m._metRCTable.getCnt(), true);
1457 }
1458 }
1459 ccReportProgress();
1460 }
extCompute(CoupleOptions & options,void * computePtr)1461 void extCompute(CoupleOptions& options, void* computePtr) {
1462 extMain* mmm = (extMain*)computePtr;
1463 mmm->measureRC(options);
1464 }
1465 extern CoupleOptions coupleOptionsNull;
1466
extCompute1(CoupleOptions & options,void * computePtr)1467 void extCompute1(CoupleOptions& options, void* computePtr) {
1468 extMeasure* mmm = (extMeasure*)computePtr;
1469 if (options != coupleOptionsNull && options[0] < 0) {
1470 if (options[5] == 1)
1471 mmm->initTargetSeq();
1472 else
1473 mmm->getDgOverlap(options);
1474 } else if (options != coupleOptionsNull)
1475 mmm->measureRC(options);
1476 else
1477 mmm->printDgContext();
1478 }
1479
makeTree(uint netId)1480 uint extMain::makeTree(uint netId) {
1481 if (netId == 0)
1482 return 0;
1483
1484 extRcTree* tree = new extRcTree(_block, logger_);
1485
1486 uint test = 0;
1487 double max_cap = 10.00;
1488 tree->makeTree(dbNet::getNet(_block, netId), max_cap, test, true, true, 1.0,
1489 _block->getSearchDb());
1490 return 0;
1491 }
1492
1493 } // namespace rcx
1494