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