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 #include <dbRtTree.h>
33 #include <dbShape.h>
34 #include <dbWireCodec.h>
35 #include <stdio.h>
36 
37 #include <algorithm>
38 
39 #include "db.h"
40 #include "dbSearch.h"
41 #include "rcx/extRCap.h"
42 #include "rcx/extSpef.h"
43 #include "rcx/exttree.h"
44 #include "utl/Logger.h"
45 
46 namespace rcx {
47 
48 using utl::RCX;
49 
setPowerExtOptions(bool skip_power_stubs,const char * exclude_cells,bool skip_m1_caps,const char * source_file)50 void extMain::setPowerExtOptions(bool skip_power_stubs,
51                                  const char* exclude_cells, bool skip_m1_caps,
52                                  const char* source_file) {
53   _power_extract_only = true;
54   _skip_power_stubs = skip_power_stubs;
55   _power_exclude_cell_list = exclude_cells;
56   _skip_m1_caps = skip_m1_caps;
57   _power_source_file = NULL;
58   if (source_file != NULL)
59     _power_source_file = strdup(source_file);
60 }
markExcludedCells()61 bool extMain::markExcludedCells() {
62   if (!_power_exclude_cell_list || _power_exclude_cell_list[0] == '\0')
63     return false;
64 
65   std::vector<odb::dbMaster*> masters;
66   if (!_block->findSomeMaster(_power_exclude_cell_list, masters))
67     return false;
68 
69   uint cnt = masters.size();
70   for (uint ii = 0; ii < cnt; ii++) {
71     odb::dbMaster* m = masters[ii];
72     m->setSpecialPower(true);
73     logger_->info(RCX, 299, "Marked Master {} as special power cell",
74                   m->getConstName());
75   }
76 
77   return true;
78 }
79 
getPowerViaRes(odb::dbBox * v,float val)80 float extMain::getPowerViaRes(odb::dbBox* v, float val) {
81   bool dbg = false;
82   if (dbg)
83     writeViaName(stdout, v, 0, "\n");
84   uint cutCount = 0;
85   float res = val;
86   uint level;
87   uint width;
88   odb::dbTechVia* tvia = v->getTechVia();
89   if (tvia != NULL) {
90     res = tvia->getResistance();
91     if (dbg)
92       fprintf(stdout, "\tDB Tech Via %s Res = %g\n", tvia->getConstName(), res);
93     if (res <= 0.0) {
94       res = computeViaResistance(v, cutCount);
95       if (dbg)
96         fprintf(stdout, "\tComputed Tech Via Res = %g\n", res);
97       if (res <= 0.0) {
98         level = tvia->getBottomLayer()->getRoutingLevel();
99         width = tvia->getBottomLayer()->getWidth();
100         res = getResistance(level, width, width, 0);
101         if (cutCount > 0)
102           res /= cutCount;
103         if (dbg)
104           fprintf(stdout, "\tSquare Via Res = %g\n", res);
105       }
106     }
107   } else {
108     odb::dbVia* bvia = v->getBlockVia();
109     res = computeViaResistance(v, cutCount);
110     if (dbg)
111       fprintf(stdout, "\tComputed Block Via %s Res = %g\n",
112               bvia->getConstName(), res);
113     if (res <= 0.0) {
114       level = bvia->getBottomLayer()->getRoutingLevel();
115       width = bvia->getBottomLayer()->getWidth();
116       res = getResistance(level, width, width, 0);
117       if (cutCount > 0)
118         res /= cutCount;
119       if (dbg)
120         fprintf(stdout, "\tSquare Block Via Res = %g\n", res);
121     }
122   }
123   return res;
124 }
125 /*
126 class sortInst_y
127 {
128 public:
129     bool operator()( odb::dbInst *i1, odb::dbInst *i2)
130     {
131         odb::dbBox *bb1= i1->getBBox();
132         odb::dbBox *bb2= i2->getBBox();
133         if ( bb1->yMin() != bb2->xMin())
134                 return bb1->xMin() < bb2->xMin();
135         return bb1->xMax() < bb2->xMax();
136     }
137 };
138 */
139 class sortInst_y {
140  public:
operator ()(odb::dbInst * i1,odb::dbInst * i2)141   bool operator()(odb::dbInst* i1, odb::dbInst* i2) {
142     odb::dbBox* bb1 = i1->getBBox();
143     odb::dbBox* bb2 = i2->getBBox();
144     return bb1->yMin() < bb2->yMin();
145   }
146 };
147 /*
148 class sortInst_x
149 {
150 public:
151     bool operator()( odb::dbInst *i1, odb::dbInst *i2)
152     {
153         odb::dbBox *bb1= i1->getBBox();
154         odb::dbBox *bb2= i2->getBBox();
155         //if ( bb1->xMin() != bb2->yMin())
156                 return bb1->yMin() < bb2->yMin();
157         //return bb1->yMax() < bb2->yMax();
158     }
159 };
160 */
161 class sortInst_x {
162  public:
operator ()(odb::dbInst * i1,odb::dbInst * i2)163   bool operator()(odb::dbInst* i1, odb::dbInst* i2) {
164     odb::dbBox* bb1 = i1->getBBox();
165     odb::dbBox* bb2 = i2->getBBox();
166     return bb1->xMin() < bb2->xMin();
167   }
168 };
169 // static void print_wire( odb::dbWire * wire );
writeViaRC(FILE * fp,uint level,odb::dbTechLayer * layer,odb::dbBox * v,odb::dbBox * w)170 void extMain::writeViaRC(FILE* fp, uint level, odb::dbTechLayer* layer,
171                          odb::dbBox* v, odb::dbBox* w) {
172   uint top;
173   uint bot = _block->getSearchDb()->getViaLevels(v, top);
174 
175   fprintf(fp, "R_%d_%d_v%d ", v->xMin(), v->yMin(), v->getId());
176   writeViaName(fp, v, bot, " ");
177 
178   level = _block->getSearchDb()->getViaLevels(w, top);
179   writeViaName(fp, w, top, " ");
180   float res = getPowerViaRes(v, 0.1);
181   fprintf(fp, " %g\n", res);
182 
183   _stackedViaResCnt++;
184 }
writeResNode(char * nodeName,odb::dbCapNode * capNode,uint level)185 void extMain::writeResNode(char* nodeName, odb::dbCapNode* capNode,
186                            uint level) {
187   if (!_wireInfra)
188     return writeResNodeRC(nodeName, capNode, level);
189   if (capNode->isITerm()) {
190     sprintf(nodeName, "I%d", capNode->getNode());
191   } else if (capNode->isInternal()) {
192     if (_junct2viaMap->geti(capNode->getNode()) == 0)
193       // sprintf(nodeName, "n%d", capNode->getId());
194       writeInternalNode_xy(capNode, nodeName);
195     else {
196       int vid = _junct2viaMap->geti(capNode->getNode());
197 
198       odb::dbBox* v = NULL;
199       if (vid > 0) {
200         v = odb::dbSBox::getSBox(_block, vid);
201 
202         odb::dbStringProperty* p = odb::dbStringProperty::find(v, "_inode");
203         if (p != NULL)
204           sprintf(nodeName, "%s_%d", p->getValue().c_str(), level);
205         else
206           writeViaName(nodeName, v, level, " ");
207       } else {
208         v = odb::dbBox::getBox(_tech, -vid);
209         char* name = getPowerSourceName(level, -vid);
210         sprintf(nodeName, "%s ", name);
211       }
212       if (level > 0)
213         _via2JunctionMap->set(v->getId(), capNode->getId());
214     }
215   }
216 }
writeNegativeCoords(char * buf,int netId,int x,int y,int level,const char * post)217 void extMain::writeNegativeCoords(char* buf, int netId, int x, int y, int level,
218                                   const char* post) {
219   const char* mx = "";
220   if (x < 0) {
221     mx = "m";
222     x = -x;
223   }
224   const char* my = "";
225   if (y < 0) {
226     my = "m";
227     y = -y;
228   }
229   if (level < 0)
230     sprintf(buf, "%sn%d_%s%d_%s%d", _node_blk_prefix, netId, mx, x, my, y);
231   else
232     sprintf(buf, "%sn%d_%s%d_%s%d_%d%s", _node_blk_prefix, netId, mx, x, my, y,
233             level, post);
234 }
createNode_xy(odb::dbCapNode * capNode,int x,int y,int level,odb::dbITerm * iterm)235 void extMain::createNode_xy(odb::dbCapNode* capNode, int x, int y, int level,
236                             odb::dbITerm* iterm) {
237   if (_junct2viaMap->geti(capNode->getNode()) != 0)
238     return;
239   if (capNode->isName())
240     return;
241 
242   int netId = _netUtil->getCurrentNet()->getId();
243 
244   // HERE NODE_NAMING
245   /*
246           char *mx= "";
247           if (x<0)
248           {
249                   mx="m";
250                   x= -x;
251           }
252           char *my= "";
253           if (y<0)
254           {
255                   my="m";
256                   y= -y;
257           }
258           char buf[2048];
259           sprintf(buf, "%sn%d_%s%d_%s%d_%d", _node_blk_prefix, netId, mx, x, my,
260      y, level);
261   */
262   char buf[2048];
263   writeNegativeCoords(buf, netId, x, y, level);
264 
265   odb::dbStringProperty::create(capNode, "_inode", buf);
266   capNode->setNameFlag();
267   if (iterm == NULL)
268     return;
269 
270   odb::dbStringProperty* p = odb::dbStringProperty::find(iterm, "_inode");
271   if (p != NULL) {
272     odb::dbStringProperty::destroy(p);
273     sprintf(buf, "%s %s", buf, p->getValue().c_str());
274   }
275   odb::dbStringProperty::create(iterm, "_inode", buf);
276 }
writeInternalNode_xy(odb::dbCapNode * capNode,char * buff)277 void extMain::writeInternalNode_xy(odb::dbCapNode* capNode, char* buff) {
278   if (!capNode->isName()) {
279     sprintf(buff, " n%d ", capNode->getId());
280   } else {
281     odb::dbStringProperty* p = odb::dbStringProperty::find(capNode, "_inode");
282     sprintf(buff, " %s ", p->getValue().c_str());
283   }
284 }
writeInternalNode_xy(odb::dbCapNode * capNode,FILE * fp)285 void extMain::writeInternalNode_xy(odb::dbCapNode* capNode, FILE* fp) {
286   if (!capNode->isName()) {
287     fprintf(fp, " n%d ", capNode->getId());
288   } else {
289     odb::dbStringProperty* p = odb::dbStringProperty::find(capNode, "_inode");
290     fprintf(fp, " %s ", p->getValue().c_str());
291   }
292 }
writeResNode(FILE * fp,odb::dbCapNode * capNode,uint level)293 void extMain::writeResNode(FILE* fp, odb::dbCapNode* capNode, uint level) {
294   if (capNode->isITerm()) {
295     fprintf(fp, " I%d ", capNode->getNode());
296   } else if (capNode->isInternal()) {
297     if (_junct2viaMap->geti(capNode->getNode()) == 0)
298       // fprintf(fp, " n%d ", capNode->getId());
299       writeInternalNode_xy(capNode, fp);
300     else {
301       int vid = _junct2viaMap->geti(capNode->getNode());
302       odb::dbBox* v = NULL;
303       if (vid > 0) {
304         v = odb::dbSBox::getSBox(_block, vid);
305 
306         odb::dbStringProperty* p = odb::dbStringProperty::find(v, "_inode");
307         if (p != NULL)
308           fprintf(fp, "%s_%d ", p->getValue().c_str(), level);
309         else
310           writeViaName(fp, v, level, " ");
311       } else {
312         v = odb::dbBox::getBox(_tech, -vid);
313         char* name = getPowerSourceName(level, -vid);
314         fprintf(fp, "%s ", name);
315         // sprintf(nodeName, "%s", name);
316       }
317       if (level > 0)
318         _via2JunctionMap->set(v->getId(), capNode->getId());
319     }
320   }
321 }
writeResNodeRC(char * capNodeName,odb::dbCapNode * capNode,uint level)322 void extMain::writeResNodeRC(char* capNodeName, odb::dbCapNode* capNode,
323                              uint level) {
324   if (capNode->isITerm()) {
325     sprintf(capNodeName, " I%d ", capNode->getNode());
326   } else if (capNode->isInternal()) {
327     writeInternalNode_xy(capNode, capNodeName);
328     uint vid = capNode->getNode();
329     if (vid > 0) {  // viaid= nodeId
330       if (level > 0)
331         _via2JunctionMap->set(vid, capNode->getId());
332     }
333   }
334 }
writeResNodeRC(FILE * fp,odb::dbCapNode * capNode,uint level)335 void extMain::writeResNodeRC(FILE* fp, odb::dbCapNode* capNode, uint level) {
336   if (capNode->isITerm()) {
337     // COMMENT 032613 -- use property to match via coords
338     odb::dbITerm* iterm = odb::dbITerm::getITerm(_block, capNode->getNode());
339     odb::dbStringProperty* p = odb::dbStringProperty::find(capNode, "_inode");
340     if (p != NULL)
341       fprintf(fp, " %s ", p->getValue().c_str());
342   } else if (capNode->isInternal()) {
343     writeInternalNode_xy(capNode, fp);
344     uint vid = capNode->getNode();
345     if (vid > 0) {  // viaid= nodeId
346       if (level > 0)
347         _via2JunctionMap->set(vid, capNode->getId());
348     }
349   }
350 }
writeOneCapNode(FILE * fp,odb::dbCapNode * capNode,uint level,bool onlyVias)351 void extMain::writeOneCapNode(FILE* fp, odb::dbCapNode* capNode, uint level,
352                               bool onlyVias) {
353   if (capNode->isITerm()) {
354     if (capNode->getNet()->isMarked())  // VDD
355       _vddItermIdTable.push_back(capNode->getNode());
356     else
357       _gndItermIdTable.push_back(capNode->getNode());
358   }
359   // float cap= 1.0e-15;
360   // float cap = capNode->getCapacitance();
361   float cap = 1.0e-15 * _capNode_map[capNode->getId()];
362   char capNodeName[128];
363   if (!onlyVias) {
364     writeResNodeRC(capNodeName, capNode, level);
365     fprintf(fp, "C_0_%d %s 0 %g\n", capNode->getId(), capNodeName, cap);
366     writeSubcktNode(capNodeName, level > 1, capNode->getNet()->isMarked());
367   } else if (capNode->isInternal()) {
368     // if (_junct2viaMap->geti(capNode->getNode())==0)
369     // continue;
370 
371     writeResNodeRC(capNodeName, capNode, level);
372     fprintf(fp, "C_0_%d %s 0 %g\n", capNode->getId(), capNodeName, cap);
373     uint vid = capNode->getNode();
374     if (vid > 0)
375       // if (_junct2viaMap->geti(capNode->getNode())>0)
376       writeSubcktNode(capNodeName, level > 1, capNode->getNet()->isMarked());
377   }
378 }
writeCapNodesRC(FILE * fp,odb::dbNet * net,uint level,bool onlyVias,std::vector<odb::dbCapNode * > & capNodeTable)379 void extMain::writeCapNodesRC(FILE* fp, odb::dbNet* net, uint level,
380                               bool onlyVias,
381                               std::vector<odb::dbCapNode*>& capNodeTable) {
382   for (uint ii = 0; ii < capNodeTable.size(); ii++) {
383     odb::dbCapNode* capNode = capNodeTable[ii];
384     writeOneCapNode(fp, capNode, level, onlyVias);
385   }
386 }
writeCapNodesRC(FILE * fp,odb::dbNet * net,uint level,bool onlyVias,bool skipFirst)387 void extMain::writeCapNodesRC(FILE* fp, odb::dbNet* net, uint level,
388                               bool onlyVias, bool skipFirst) {
389   odb::dbSet<odb::dbCapNode> cSet = net->getCapNodes();
390 
391   uint setCnt = cSet.size();
392   if (setCnt == 0)
393     return;
394   cSet.reverse();
395   odb::dbSet<odb::dbCapNode>::iterator rc_itr;
396 
397   uint cnt = 0;
398   rc_itr = cSet.begin();
399   if (skipFirst) {
400     if (setCnt > 3) {
401       cnt++;
402       ++rc_itr;
403     } else
404       cnt--;
405   }
406   for (; rc_itr != cSet.end(); ++rc_itr) {
407     odb::dbCapNode* capNode = *rc_itr;
408     cnt++;
409     if (cnt == setCnt - 1)
410       continue;
411     if (capNode->isITerm()) {
412       if (capNode->getNet()->isMarked())  // VDD
413         _vddItermIdTable.push_back(capNode->getNode());
414       else
415         _gndItermIdTable.push_back(capNode->getNode());
416     }
417     // float cap= 1.0e-15;
418     // float cap = capNode->getCapacitance();
419     float cap = 1.0e-15 * _capNode_map[capNode->getId()];
420     char capNodeName[128];
421     if (!onlyVias) {
422       writeResNodeRC(capNodeName, capNode, level);
423       fprintf(fp, "C_0_%d %s 0 %g\n", capNode->getId(), capNodeName, cap);
424       writeSubcktNode(capNodeName, level > 1, capNode->getNet()->isMarked());
425     } else if (capNode->isInternal()) {
426       // if (_junct2viaMap->geti(capNode->getNode())==0)
427       // continue;
428 
429       writeResNodeRC(capNodeName, capNode, level);
430       fprintf(fp, "C_0_%d %s 0 %g\n", capNode->getId(), capNodeName, cap);
431       uint vid = capNode->getNode();
432       if (vid > 0)
433         // if (_junct2viaMap->geti(capNode->getNode())>0)
434         writeSubcktNode(capNodeName, level > 1, capNode->getNet()->isMarked());
435     }
436   }
437 }
writeCapNodes(FILE * fp,odb::dbNet * net,uint level,bool onlyVias,bool skipFirst)438 void extMain::writeCapNodes(FILE* fp, odb::dbNet* net, uint level,
439                             bool onlyVias, bool skipFirst) {
440   odb::dbSet<odb::dbCapNode> cSet = net->getCapNodes();
441   cSet.reverse();
442   odb::dbSet<odb::dbCapNode>::iterator rc_itr;
443   // Cpn_0_vM2_1     vM2_1 0 5.41778e-16
444   rc_itr = cSet.begin();
445   if (skipFirst)
446     ++rc_itr;
447   for (; rc_itr != cSet.end(); ++rc_itr) {
448     odb::dbCapNode* capNode = *rc_itr;
449     if (capNode->isITerm()) {
450       if (capNode->getNet()->isMarked())  // VDD
451         _vddItermIdTable.push_back(capNode->getNode());
452       else
453         _gndItermIdTable.push_back(capNode->getNode());
454     }
455     // float cap= 1.0e-15;
456     // float cap = capNode->getCapacitance();
457     float cap = 1.0e-15 * _capNode_map[capNode->getId()];
458     char capNodeName[128];
459     if (!onlyVias) {
460       writeResNode(capNodeName, capNode, level);
461       fprintf(fp, "Cpn_0_%d %s 0 %g\n", capNode->getId(), capNodeName, cap);
462       writeSubcktNode(capNodeName, level > 1, capNode->getNet()->isMarked());
463     } else if (capNode->isInternal()) {
464       // if (_junct2viaMap->geti(capNode->getNode())==0)
465       // continue;
466 
467       writeResNode(capNodeName, capNode, level);
468       fprintf(fp, "Cpn_0_%d %s 0 %g\n", capNode->getId(), capNodeName, cap);
469       if (_junct2viaMap->geti(capNode->getNode()) > 0)
470         writeSubcktNode(capNodeName, level > 1, capNode->getNet()->isMarked());
471     }
472   }
473 }
writeSubcktNode(char * capNodeName,bool highMetal,bool vdd)474 void extMain::writeSubcktNode(char* capNodeName, bool highMetal, bool vdd) {
475   // vdd=true
476   FILE* fp = _subCktNodeFP[highMetal][vdd];
477 
478   if (++_subCktNodeCnt[vdd][highMetal] % 8 == 0)
479     fprintf(fp, " \\\n");
480 
481   fprintf(fp, " %s", capNodeName);
482 }
micronCoords(int xy)483 float extMain::micronCoords(int xy) {
484   float v = 1.0 * xy;
485   v /= _block->getDbUnitsPerMicron();
486 
487   return v;
488 }
distributeCap(FILE * fp,odb::dbNet * net)489 float extMain::distributeCap(FILE* fp, odb::dbNet* net) {
490   odb::dbSet<odb::dbCapNode> cSet = net->getCapNodes();
491   odb::dbSet<odb::dbCapNode>::iterator c_itr;
492   for (c_itr = cSet.begin(); c_itr != cSet.end(); ++c_itr) {
493     odb::dbCapNode* capNode = *c_itr;
494     _capNode_map[capNode->getId()] = 0.0;
495   }
496   float totCap = 0.0;
497 
498   odb::dbSet<odb::dbRSeg> rSet = net->getRSegs();
499   odb::dbSet<odb::dbRSeg>::iterator rc_itr;
500 
501   for (rc_itr = rSet.begin(); rc_itr != rSet.end(); ++rc_itr) {
502     odb::dbRSeg* rc = *rc_itr;
503     float cap = rc->getCapacitance(0);
504     // rc->getShapeId(), cap);
505 
506     odb::dbCapNode* src = rc->getSourceCapNode();
507     odb::dbCapNode* tgt = rc->getTargetCapNode();
508     /*
509                     float c = _capNode_map[src->getId()];
510                     _capNode_map[src->getId()]= c+cap/2;
511 
512                     c = _capNode_map[tgt->getId()];
513                     _capNode_map[tgt->getId()]= c+cap/2;
514     */
515     _capNode_map[src->getId()] += cap / 2;
516     _capNode_map[tgt->getId()] += cap / 2;
517 
518     if (fp != NULL)
519       fprintf(fp, "R_%d_%d_s%d %g %g %g\n", net->getId(), rc->getId(),
520               rc->getShapeId(), cap, _capNode_map[src->getId()],
521               _capNode_map[tgt->getId()]);
522 
523     totCap += cap;
524   }
525   return totCap;
526 }
setNodeCoords_xy(odb::dbNet * net,int level)527 uint extMain::setNodeCoords_xy(odb::dbNet* net, int level) {
528   uint maxJunctionId = 0;
529   bool RCflag = true;
530 
531   if (_dbgPowerFlow)
532     logger_->info(RCX, 300, "setNodeCoords_xy Net= {}", net->getConstName());
533   odb::dbWire* wire = net->getWire();
534 
535   if (!RCflag) {
536     odb::dbWireShapeItr shapes;
537     odb::dbShape s;
538     for (shapes.begin(wire); shapes.next(s);) {
539       uint sid = shapes.getShapeId();
540       int vid;
541       wire->getProperty(sid, vid);
542       // if (_dbgPowerFlow)
543       logger_->info(RCX, 301, "sID= {} RC{}  {} {} {} {}", sid, vid, s.xMin(),
544                     s.yMin(), s.xMax(), s.yMax());
545       if (vid == 0)
546         continue;
547       odb::dbRSeg* rc = odb::dbRSeg::getRSeg(net->getBlock(), vid);
548       odb::dbCapNode* src = rc->getSourceCapNode();
549       odb::dbCapNode* tgt = rc->getTargetCapNode();
550       createNode_xy(src, s.xMin(), s.yMin(), level);
551       createNode_xy(tgt, s.xMax(), s.yMax(), level);
552     }
553     if (_dbgPowerFlow)
554       logger_->info(RCX, 302, "End Net= {}", net->getConstName());
555     return 0;
556   }
557   odb::dbSet<odb::dbRSeg> rSet = net->getRSegs();
558   odb::dbSet<odb::dbRSeg>::iterator rc_itr;
559 
560   for (rc_itr = rSet.begin(); rc_itr != rSet.end(); ++rc_itr) {
561     odb::dbRSeg* rc = *rc_itr;
562     if (rc->getShapeId() == 0) {
563       odb::dbCapNode* src = rc->getSourceCapNode();
564       odb::dbCapNode* tgt = rc->getTargetCapNode();
565       continue;
566     }
567     int x = 0;
568     int y = 0;
569     rc->getCoords(x, y);
570     odb::dbShape s;
571     wire->getShape(rc->getShapeId(), s);
572 
573     odb::dbCapNode* src = rc->getSourceCapNode();
574     if (!src->isName()) {
575       // createNode_xy(src, x, y, level);
576       createNode_xy(src, s.xMin(), s.yMin(), level);
577     }
578 
579     char buff[64];
580     writeInternalNode_xy(src, buff);
581 
582     odb::dbCapNode* tgt = rc->getTargetCapNode();
583 
584     if (!tgt->isInternal())
585       continue;
586 
587     if (maxJunctionId < rc->getShapeId())
588       maxJunctionId = rc->getShapeId();
589     odb::dbITerm* iterm = _junct2iterm->geti(rc->getShapeId());
590     // 102912 createNode_xy(tgt, s.xMax(), s.yMax(), level, iterm);
591     createNode_xy(tgt, x, y, level, iterm);
592     writeInternalNode_xy(tgt, buff);
593   }
594   return maxJunctionId;
595 }
596 
writeRes(FILE * fp,odb::dbNet * net,uint level,uint width,uint dir,bool skipFirst)597 double extMain::writeRes(FILE* fp, odb::dbNet* net, uint level, uint width,
598                          uint dir, bool skipFirst) {
599   double totRes = 0.0;
600 
601   if ((level > 1) && (_globGeom != NULL)) {
602     fprintf(_globGeom, "prop netName %s endprop\n", net->getConstName());
603   }
604 
605   odb::dbSet<odb::dbRSeg> rSet = net->getRSegs();
606   odb::dbSet<odb::dbRSeg>::iterator rc_itr;
607 
608   // 102912 for( rc_itr = rSet.begin(); rc_itr != rSet.end(); ++rc_itr )
609   rc_itr = rSet.begin();
610   if (skipFirst)
611     ++rc_itr;
612   for (; rc_itr != rSet.end(); ++rc_itr) {
613     odb::dbRSeg* rc = *rc_itr;
614     // fprintf(fp, "R_%s_%d_s%d", net->getConstName(), rc->getId(),
615     // rc->getShapeId());
616     fprintf(fp, "R_%d_%d_s%d ", net->getId(), rc->getId(), rc->getShapeId());
617 
618     odb::dbCapNode* src = rc->getSourceCapNode();
619     odb::dbCapNode* tgt = rc->getTargetCapNode();
620     writeResNode(fp, src, level);
621     writeResNode(fp, tgt, level);
622 
623     // double res= _resFactor * rc->getResistance(0);
624     double res = rc->getResistance(0);
625     totRes += res;
626     fprintf(fp, " %g   ", res);
627     fprintf(fp, " dtemp=0 tc1=0.00265     tc2=-2.641e-07\n");
628 
629     // if ((level>1) && (_globGeom!=NULL) && (rc->getShapeId()>0))
630     if ((level > 1) && (_globGeom != NULL)) {
631       odb::dbWire* wire = net->getWire();
632       odb::dbShape s;
633       wire->getShape(rc->getShapeId(), s);
634 
635       char srcNode[128];
636       char dstNode[128];
637       writeResNode(srcNode, src, level);
638       writeResNode(dstNode, tgt, level);
639 
640       float W = micronCoords(width);
641       fprintf(_globGeom, "path Metal%d %g %s %s ", level, W, srcNode, dstNode);
642       fprintf(_globGeom, "((%g %g) ", micronCoords(s.xMin()),
643               micronCoords(s.yMin()));
644       if (dir > 0) {
645         fprintf(_globGeom, " (%g %g)) endpath\n", micronCoords(s.xMax()),
646                 micronCoords(s.yMin()));
647       } else {
648         fprintf(_globGeom, " (%g %g)) endpath\n", micronCoords(s.xMin()),
649                 micronCoords(s.yMax()));
650       }
651     }
652   }
653   if (level == 1)
654     return totRes;
655   return totRes;
656 }
657 // COMMENT -- 032913
replaceItermCoords(odb::dbNet * net,uint dir,int xy[2])658 void extMain::replaceItermCoords(odb::dbNet* net, uint dir, int xy[2]) {
659   odb::dbSet<odb::dbCapNode> cSet = net->getCapNodes();
660   odb::dbSet<odb::dbCapNode>::iterator rc_itr = cSet.begin();
661   for (; rc_itr != cSet.end(); ++rc_itr) {
662     odb::dbCapNode* capNode = *rc_itr;
663 
664     if (capNode->isInternal())
665       continue;
666     if (capNode->isITerm()) {
667       odb::dbStringProperty* p = odb::dbStringProperty::find(capNode, "_inode");
668       if (p == NULL)
669         continue;
670       char buff[128];
671       sprintf(buff, " %s ", p->getValue().c_str());
672 
673       Ath__parser parser;
674 
675       int n1 = parser.mkWords(buff, "_");
676       int ixy[2];
677 
678       ixy[0] = parser.getInt(1);
679       ixy[1] = parser.getInt(2);
680       ixy[dir] = xy[dir];
681 
682       char buff2[128];
683       sprintf(buff2, "%s_%d_%d_%d", parser.get(0), ixy[0], ixy[1],
684               parser.getInt(3));
685 
686       p->setValue(buff2);
687 
688       odb::dbITerm* iterm = odb::dbITerm::getITerm(_block, capNode->getNode());
689       odb::dbInst* inst = iterm->getInst();
690       odb::dbMaster* master = inst->getMaster();
691 
692       fprintf(_blkInfo, "%s %s %s [%s] %s \n", inst->getConstName(),
693               master->getConstName(), getBlockType(master),
694               iterm->getMTerm()->getConstName(), buff2);
695 
696       odb::dbBox* bb = inst->getBBox();
697       // fprintf(_coordsFP, "std_cell %d %d  %d %d   I%d %s\n",
698       fprintf(_coordsFP, "%s %d %d  %d %d   %s %s\n", getBlockType(master),
699               bb->xMin(), bb->yMin(), bb->getDX(), bb->getDY(), buff2,
700               inst->getConstName());
701     }
702   }
703 }
findViaMainCoord(odb::dbNet * net,char * buff)704 void extMain::findViaMainCoord(odb::dbNet* net, char* buff) {
705   odb::dbSet<odb::dbRSeg> rSet = net->getRSegs();
706   odb::dbSet<odb::dbRSeg>::iterator rc_itr;
707   uint cnt = 0;
708   rc_itr = rSet.begin();
709   for (; rc_itr != rSet.end(); ++rc_itr) {
710     odb::dbRSeg* rc = *rc_itr;
711 
712     odb::dbCapNode* src = rc->getSourceCapNode();
713     odb::dbCapNode* tgt = rc->getTargetCapNode();
714     if (tgt->isInternal()) {
715       odb::dbStringProperty* p = odb::dbStringProperty::find(tgt, "_inode");
716       if (p == NULL)
717         continue;
718       sprintf(buff, " %s ", p->getValue().c_str());
719       return;
720     }
721   }
722 }
writeResRC(FILE * fp,odb::dbNet * net,uint level,uint width,uint dir,bool skipFirst,bool reverse,bool onlyVias,bool writeCapNodes,int xy[2])723 double extMain::writeResRC(FILE* fp, odb::dbNet* net, uint level, uint width,
724                            uint dir, bool skipFirst, bool reverse,
725                            bool onlyVias, bool writeCapNodes, int xy[2]) {
726   if ((level > 1) && (_globGeom != NULL))
727     fprintf(_globGeom, "prop netName %s endprop\n", net->getConstName());
728 
729   odb::dbSet<odb::dbRSeg> rSet = net->getRSegs();
730   uint setCnt = rSet.size();
731   if (setCnt == 0)
732     return 0;
733   if (reverse)
734     rSet.reverse();
735 
736   odb::dbSet<odb::dbRSeg>::iterator rc_itr;
737   uint cnt = 0;
738   rc_itr = rSet.begin();
739   if (skipFirst) {
740     if (setCnt > 1) {
741       cnt++;
742       ++rc_itr;
743     } else
744       cnt--;
745   }
746   uint n = 0;
747 
748   double totRes = 0.0;
749   for (; rc_itr != rSet.end();) {
750     odb::dbRSeg* rc = *rc_itr;
751 
752     odb::dbCapNode* src = rc->getSourceCapNode();
753     odb::dbCapNode* tgt = rc->getTargetCapNode();
754 
755     if (writeCapNodes) {
756       if (n == 0)
757         writeOneCapNode(fp, src, level, onlyVias);
758 
759       writeOneCapNode(fp, tgt, level, onlyVias);
760       n++;
761     }
762     fprintf(fp, "R_%d ", rc->getId());
763     writeResNodeRC(fp, src, level);
764     writeResNodeRC(fp, tgt, level);
765 
766     // double res= _resFactor * rc->getResistance(0);
767     double res = rc->getResistance(0);
768     totRes += res;
769     fprintf(fp, " %g   ", res);
770     fprintf(fp, " dtemp=0 tc1=0.00265 tc2=-2.641e-07\n");
771     /* TODO
772                     if ((level>1) && (_globGeom!=NULL))
773                     {
774                             odb::dbWire *wire= net->getWire();
775                             odb::odb::dbShape s;
776                             wire->getShape( rc->getShapeId(), s );
777 
778                             char srcNode[128];
779                             char dstNode[128];
780                             writeResNode(srcNode, src, level);
781                             writeResNode(dstNode, tgt, level);
782 
783                             float W=micronCoords(width);
784                             fprintf(_globGeom,"path Metal%d %g %s %s ", level,
785        W,srcNode, dstNode); fprintf(_globGeom, "((%g %g) ",
786                                     micronCoords(s.xMin()),
787        micronCoords(s.yMin())); if (dir>0)
788                             {
789                                     fprintf(_globGeom, " (%g %g)) endpath\n",
790                                     micronCoords(s.xMax()),
791        micronCoords(s.yMin())); } else { fprintf(_globGeom, " (%g %g))
792        endpath\n", micronCoords(s.xMin()), micronCoords(s.yMax()));
793                             }
794                     }
795     */
796     ++rc_itr;
797     if (skipFirst) {
798       if (rc_itr != rSet.end())
799         continue;
800     }
801   }
802   if (level == 1)
803     return totRes;
804   return totRes;
805 }
806 
specialMasterType(odb::dbInst * inst)807 bool extMain::specialMasterType(odb::dbInst* inst) {
808   odb::dbMaster* master = inst->getMaster();
809   if ((master->getType() == odb::dbMasterType::CORE_FEEDTHRU) ||
810       (master->getType() == odb::dbMasterType::PAD_SPACER))
811       //(master->getType()==odb::dbMasterType::NONE))
812   {
813     return true;
814   }
815   if (inst->getUserFlag3())
816     return true;
817 
818   return false;
819 }
820 
getBlockType(odb::dbMaster * m)821 const char* extMain::getBlockType(odb::dbMaster* m) {
822   const char* name = m->getConstName();
823   if ((name[0] == 'F') && (name[1] == 'I') && (name[2] == 'L') &&
824       (name[3] == 'L'))
825     return "is_filler_decap";
826 
827   if (m->isFiller())
828     return "is_filler_decap";
829   else
830     return "is_std";
831 }
832 
fisrt_markInst_UserFlag(odb::dbInst * inst,odb::dbNet * net)833 bool extMain::fisrt_markInst_UserFlag(odb::dbInst* inst, odb::dbNet* net) {
834   if (net->getSigType() == odb::dbSigType::POWER) {
835     if (inst->getUserFlag1())
836       return false;
837 
838     inst->setUserFlag1();
839     return true;
840   }
841   if (net->getSigType() == odb::dbSigType::GROUND) {
842     if (inst->getUserFlag2())
843       return false;
844 
845     inst->setUserFlag2();
846     return true;
847   }
848 
849   throw ZException("Unexpected signal type");
850 }
851 
findConnect(odb::dbInst * inst,odb::dbNet * net,odb::dbNet * targetNet)852 odb::dbITerm* extMain::findConnect(odb::dbInst* inst, odb::dbNet* net,
853                                    odb::dbNet* targetNet) {
854   odb::dbITerm* iterm = NULL;
855 
856   odb::dbMaster* master = inst->getMaster();
857   if (specialMasterType(inst))
858     return NULL;
859 
860   uint instId = inst->getId();
861 
862   odb::dbSet<odb::dbITerm> iterms = inst->getITerms();
863   odb::dbSet<odb::dbITerm>::iterator iterm_itr;
864 
865   odb::dbITerm* foundIterm = NULL;
866   for (iterm_itr = iterms.begin(); iterm_itr != iterms.end(); ++iterm_itr) {
867     odb::dbITerm* iterm = *iterm_itr;
868     if (iterm->getNet() == NULL)
869       continue;
870     if (!((iterm->getSigType() == odb::dbSigType::GROUND) ||
871           (iterm->getSigType() == odb::dbSigType::POWER)))
872       continue;
873 
874     if (net == iterm->getNet()) {
875       if (master->isSpecialPower())
876         return NULL;
877 
878       if (fisrt_markInst_UserFlag(inst, net)) {
879         /* COMMENT -- tranfer to createPowerNode
880                                 fprintf(_blkInfo, "%s %s %s [%s] I%d\n",
881            inst->getConstName(), master->getConstName(), getBlockType(master),
882                                         iterm->getMTerm()->getConstName(),
883            iterm->getId());
884 
885                                 odb::dbBox *bb= inst->getBBox();
886                                 //fprintf(_coordsFP, "std_cell %d %d  %d %d I%d
887            %s\n", fprintf(_coordsFP, "%s %d %d  %d %d   I%d %s\n",
888                                         getBlockType(master),
889                                         bb->xMin(), bb->yMin(),
890                                         bb->getDX(), bb->getDY(),
891                                         iterm->getId(),
892                                         inst->getConstName());
893         */
894         foundIterm = iterm;
895       }
896 
897       if (net->getSigType() == odb::dbSigType::POWER)
898         inst->setUserFlag1();
899       if (net->getSigType() == odb::dbSigType::GROUND)
900         inst->setUserFlag2();
901     }
902   }
903   if (foundIterm != NULL) {
904     // no TIE lo/hi 3/26/2013  iterm2Vias_cells(inst, foundIterm);
905     return foundIterm;
906   }
907   return NULL;
908 
909   odb::dbSet<odb::dbMTerm> mterms = master->getMTerms();
910   odb::dbSet<odb::dbMTerm>::iterator itr;
911 
912   for (itr = mterms.begin(); itr != mterms.end(); ++itr) {
913     odb::dbMTerm* mterm = (odb::dbMTerm*)*itr;
914     if (mterm->getSigType() != net->getSigType())
915       continue;
916 
917     iterm = odb::dbITerm::connect(inst, targetNet, mterm);
918     break;
919   }
920   if (iterm == NULL) {
921     logger_->warn(RCX, 303, "Cannot connect to Inst: {} of {} for power net {}",
922                   inst->getConstName(), master->getConstName(),
923                   net->getConstName());
924     odb::dbBox* bb = inst->getBBox();
925     logger_->warn(RCX, 304, "   @ {} {}  {} {}", bb->xMin(), bb->yMin(),
926                   bb->getDX(), bb->getDY());
927   } else {
928     // fprintf(_blkInfo, "%s %s is_std [%s] I%d\n", inst->getConstName(),
929     if (!master->isSpecialPower()) {
930       if (fisrt_markInst_UserFlag(inst, net)) {
931         fprintf(_blkInfo, "%s %s %s [%s] I%d\n", inst->getConstName(),
932                 master->getConstName(), getBlockType(master),
933                 iterm->getMTerm()->getConstName(), iterm->getId());
934         odb::dbBox* bb = inst->getBBox();
935         fprintf(_coordsFP, "%s %d %d  %d %d   I%d %s\n", getBlockType(master),
936                 bb->xMin(), bb->yMin(), bb->getDX(), bb->getDY(),
937                 iterm->getId(), inst->getConstName());
938         if (net->getSigType() == odb::dbSigType::POWER)
939           inst->setUserFlag1();
940         if (net->getSigType() == odb::dbSigType::GROUND)
941           inst->setUserFlag2();
942       }
943     }
944   }
945   return iterm;
946 }
947 
getLayerSearchBoundaries(odb::dbTechLayer * layer,int * xyLo,int * xyHi,uint * pitch)948 uint extMain::getLayerSearchBoundaries(odb::dbTechLayer* layer, int* xyLo,
949                                        int* xyHi, uint* pitch) {
950   odb::Rect maxRect;
951   _block->getDieArea(maxRect);
952 
953   uint width = layer->getWidth();
954   uint p = layer->getPitch();
955   if (p <= 0)
956     logger_->error(RCX, 477, "Layer %s has pitch %u !!", layer->getConstName(),
957                    *pitch);
958 
959   pitch[0] = 0;
960   pitch[1] = 0;
961   uint dir = 0;
962   if (layer->getDirection() == odb::dbTechLayerDir::HORIZONTAL)
963     dir = 1;
964   pitch[dir] = p;
965 
966   std::vector<int> trackXY(32000);
967   odb::dbTrackGrid* tg = _block->findTrackGrid(layer);
968   if (tg) {
969     tg->getGridX(trackXY);
970     xyLo[0] = trackXY[0] - width / 2;
971     tg->getGridY(trackXY);
972     xyLo[1] = trackXY[0] - width / 2;
973   } else {
974     xyLo[0] = maxRect.xMin();
975     xyLo[1] = maxRect.yMin();
976   }
977   xyHi[0] = maxRect.xMax();
978   xyHi[1] = maxRect.yMax();
979   return dir;
980 }
mergeRails(uint dir,std::vector<odb::dbBox * > & boxTable,std::vector<odb::Rect * > & mergeTable)981 uint extMain::mergeRails(uint dir, std::vector<odb::dbBox*>& boxTable,
982                          std::vector<odb::Rect*>& mergeTable) {
983   uint n = boxTable.size();
984   for (uint ii = 0; ii < n; ii++) {
985     odb::dbBox* w1 = boxTable[ii];
986     if (w1->isVisited())
987       continue;
988     w1->setVisited(true);
989     if (_dbgPowerFlow)
990       fprintf(stdout, "\t\t\tmerge w1: %d %d %d %d\n", w1->xMin(), w1->yMin(),
991               w1->xMax(), w1->yMax());
992 
993     odb::Rect* r1 =
994         new odb::Rect(w1->xMin(), w1->yMin(), w1->xMax(), w1->yMax());
995     mergeTable.push_back(r1);
996   }
997   return mergeTable.size();
998 }
getITermConn2(uint dir,odb::dbWireEncoder & encoder,odb::dbWire * wire,odb::dbNet * net,int * xy,int * xy2)999 uint extMain::getITermConn2(uint dir, odb::dbWireEncoder& encoder,
1000                             odb::dbWire* wire, odb::dbNet* net, int* xy,
1001                             int* xy2) {
1002   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1003 
1004   int WIDTH2 = (xy2[dir] - xy[dir]);
1005   // odb::dbTechLayerRule *wRule=_netUtil->getRule(level,WIDTH2);
1006 
1007   std::vector<odb::dbInst*> instTable;
1008   uint instCnt =
1009       blkSearch->getInstBoxes(xy[0], xy[1], xy2[0], xy2[1], instTable);
1010   /*
1011   if (instCnt>0)
1012   if (_dbgPowerFlow)
1013   fprintf(stdout, "\tgetITermConn[%d]: %d %d  %d %d\n", instCnt, xy[0], xy[1],
1014   xy2[0], xy2[1]);
1015   */
1016 
1017   int prevX = xy[0];
1018   int prevY = xy[1];
1019   sortInst_x sort_by_x;
1020   std::sort(instTable.begin(), instTable.end(), sort_by_x);
1021   for (uint jj = 0; jj < instCnt; jj++) {
1022     odb::dbInst* inst = instTable[jj];
1023     int instId = inst->getId();
1024     odb::dbBox* bb = inst->getBBox();
1025     const char* debug = "";
1026     if (strcmp(inst->getConstName(), debug) == 0) {
1027       logger_->info(RCX, 401,
1028                     "inst= {} net={} \tgetITermConn[{}]: {} {}  {} {}",
1029                     inst->getConstName(), net->getConstName(), instCnt, xy[0],
1030                     xy[1], xy2[0], xy2[1]);
1031       logger_->info(RCX, 398, "inst BBox= X {} {}  Y {} {}", bb->xMin(),
1032                     bb->xMax(), bb->yMin(), bb->yMax());
1033       logger_->info(RCX, 395, "instCount={} ----- --------- Prev X {}  Y {} ",
1034                     instCnt, prevX, prevY);
1035       for (uint kk = 0; kk < instCnt; kk++) {
1036         odb::dbInst* ii = instTable[kk];
1037         int instId = inst->getId();
1038         odb::dbBox* b = ii->getBBox();
1039         logger_->info(RCX, 389, "I[{}] {:10d} {:10d}  {:10d} {:10d}", kk,
1040                       b->xMin(), b->yMin(), b->xMax(), b->yMax());
1041       }
1042     }
1043     if ((net->getSigType() == odb::dbSigType::POWER) && inst->getUserFlag1())
1044       continue;
1045     if ((net->getSigType() == odb::dbSigType::GROUND) && inst->getUserFlag2())
1046       continue;
1047 
1048     if (dir > 0) {
1049       if (bb->xMin() > xy2[0] + WIDTH2 / 2)
1050         continue;
1051       if (bb->xMax() < (xy[0] - WIDTH2 / 2))
1052         continue;
1053     } else {
1054       if (bb->yMin() > xy2[1] + WIDTH2 / 2)
1055         continue;
1056       if (bb->yMax() < xy[1] - WIDTH2 / 2)
1057         continue;
1058     }
1059     int bbXY[2] = {bb->xMin(), bb->yMin()};
1060     int bbXY2[2] = {bb->xMax(), bb->yMax()};
1061     /*
1062                     if (dir>0)
1063                             bbXY[!dir]= (bb->xMin()+bb->xMax())/2;
1064                     else
1065                             bbXY[!dir]= (bb->yMin()+bb->yMax())/2;
1066     */
1067 
1068     int n = !dir;
1069     if (!(((bbXY[n] >= xy[n]) && (bbXY[n] < xy2[n])) ||
1070           ((bbXY2[n] >= xy[n]) && (bbXY2[n] < xy2[n]))))
1071       continue;
1072     odb::dbITerm* iterm = findConnect(inst, net, wire->getNet());
1073     if (strcmp(inst->getConstName(), debug) == 0)
1074       fprintf(stdout, "\t Before Connection\n");
1075     if (iterm == NULL) {
1076       continue;
1077     }
1078     if (strcmp(inst->getConstName(), debug) == 0)
1079       fprintf(stdout, "\t\t Connected!!!\n");
1080 
1081     int ixy[2];
1082     ixy[0] = xy[0];
1083     ixy[1] = xy[1];
1084     if (dir > 0)
1085       ixy[!dir] = bb->xMin();
1086     else
1087       ixy[!dir] = bb->yMin();
1088     int BB[2];
1089     if (dir > 0)
1090       BB[0] = (bb->xMin() + bb->xMax()) / 2;
1091     else
1092       BB[1] = (bb->yMin() + bb->yMax()) / 2;
1093 
1094     sameJunctionPoint(ixy, BB, WIDTH2, dir);
1095 
1096     uint jid = encoder.addPoint(ixy[0], ixy[1]);
1097     encoder.addITerm(iterm);
1098 
1099     xy[!dir] = ixy[!dir];
1100   }
1101   uint cnt = 0;
1102   for (uint jj = 0; jj < instCnt; jj++) {
1103     if (cnt > 4)
1104       break;
1105     odb::dbInst* inst = instTable[jj];
1106     if (specialMasterType(inst))
1107       continue;
1108     if (inst->getMaster()->isSpecialPower())
1109       continue;
1110 
1111     if (((net->getSigType() == odb::dbSigType::POWER) &&
1112          !inst->getUserFlag1()) ||
1113         ((net->getSigType() == odb::dbSigType::GROUND) &&
1114          !inst->getUserFlag2())) {
1115       odb::dbBox* bb = inst->getBBox();
1116       cnt++;
1117     }
1118     // inst->clearUserFlag1();
1119     // inst->clearUserFlag2();
1120   }
1121   // if (cnt>0)
1122   // exit(0);
1123 
1124   return instCnt;
1125 }
1126 //#define DEBUG_INST_NAME "ledc_3.OPTHOLD_G_11905"
getITermConnRC(odb::dbCapNode * srcCapNode,uint level,uint dir,odb::dbNet * net,int * xy,int * xy2)1127 odb::dbCapNode* extMain::getITermConnRC(odb::dbCapNode* srcCapNode, uint level,
1128                                         uint dir, odb::dbNet* net, int* xy,
1129                                         int* xy2) {
1130   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1131 
1132   int WIDTH2 = (xy2[dir] - xy[dir]);
1133   // odb::dbTechLayerRule *wRule=_netUtil->getRule(level,WIDTH2);
1134 
1135   std::vector<odb::dbInst*> instTable;
1136   uint instCnt =
1137       blkSearch->getInstBoxes(xy[0], xy[1], xy2[0], xy2[1], instTable);
1138 
1139   int prevX = xy[0];
1140   int prevY = xy[1];
1141   sortInst_x sort_by_x;
1142   std::sort(instTable.begin(), instTable.end(), sort_by_x);
1143 
1144   std::vector<odb::Rect> rectTable;
1145 
1146   for (uint kk = 0; kk < instCnt; kk++) {
1147     odb::dbInst* inst = instTable[kk];
1148     odb::dbBox* b = inst->getBBox();
1149     odb::Rect rb;
1150     b->getBox(rb);
1151     rectTable.push_back(rb);
1152 
1153 #ifdef DEBUG_INST_NAME
1154     if (strcmp(inst->getConstName(), DEBUG_INST_NAME) == 0) {
1155       logger_->info(RCX, 403,
1156                     "inst= {} net={} \tgetITermConn[{}]: {} {}  {} {}",
1157                     inst->getConstName(), net->getConstName(), instCnt, xy[0],
1158                     xy[1], xy2[0], xy2[1]);
1159       logger_->info(RCX, 399, "inst BBox= X {} {}  Y {} {}", rb.xMin(),
1160                     rb.xMax(), rb.yMin(), rb.yMax());
1161       logger_->info(RCX, 396, "instCount={} ----- --------- Prev X {}  Y {} ",
1162                     instCnt, prevX, prevY);
1163       for (uint kk = 0; kk < instCnt; kk++) {
1164         odb::dbInst* ii = instTable[kk];
1165         int instId = inst->getId();
1166         odb::dbBox* b = ii->getBBox();
1167         logger_->info(RCX, 390, "I[{}] {:10d} {:10d}  {:10d} {:10d}", kk,
1168                       b->xMin(), b->yMin(), b->xMax(), b->yMax());
1169       }
1170     }
1171 #endif
1172   }
1173   /*
1174           for (uint jj= 0; jj<instCnt; jj++)
1175           {
1176                   odb::dbInst *inst= instTable[jj];
1177                   int instId= inst->getId();
1178                   odb::dbBox *b= inst->getBBox();
1179                   odb::Rect rb= rectTable[jj];
1180 
1181                   if (jj<instCnt-1)
1182                   {
1183                           odb::Rect rc= rectTable[jj+1];
1184                           if (rb.xMax()>rc.xMin()) // overallping
1185                           {
1186                                   if (rb.xMax()>rc.xMax()) // switch inndices
1187                                   {
1188                                           rb.set_xlo(rc.xMax());
1189 
1190                                           rectTable[jj]= rc;
1191                                           rectTable[jj+1]= rb;
1192 
1193                                           instTable[jj]= instTable[jj+1];
1194                                           instTable[jj+1]= inst;
1195                                   }
1196                                   else if (rb.xMax()<rc.xMax())
1197                                   {
1198                                           rc.set_xlo(rb.xMax());
1199                                   }
1200                                   else
1201                                   {
1202                                           rc.set_xlo( rc.xMin() + WIDTH2/2);
1203                                           rb.set_xhi( rc.xMax() - WIDTH2/2);
1204                                   }
1205                           }
1206                   }
1207           }
1208   */
1209   for (uint jj = 0; jj < instCnt; jj++) {
1210     odb::dbInst* inst = instTable[jj];
1211     int instId = inst->getId();
1212     odb::dbBox* b = inst->getBBox();
1213     odb::Rect rb = rectTable[jj];
1214 
1215     const char* debug = " ";
1216 #ifdef DEBUG_INST_NAME
1217     debug = DEBUG_INST_NAME;
1218     if (strcmp(inst->getConstName(), debug) == 0) {
1219       logger_->info(RCX, 402,
1220                     "inst= {} net={} \tgetITermConn[{}]: {} {}  {} {}",
1221                     inst->getConstName(), net->getConstName(), instCnt, xy[0],
1222                     xy[1], xy2[0], xy2[1]);
1223       logger_->info(RCX, 306, "inst BBox= X {} {}  Y {} {}", rb.xMin(),
1224                     rb.xMax(), rb.yMin(), rb.yMax());
1225       logger_->info(RCX, 397, "instCount={} ----- --------- Prev X {}  Y {} ",
1226                     instCnt, prevX, prevY);
1227       for (uint kk = 0; kk < instCnt; kk++) {
1228         odb::Rect rrb = rectTable[kk];
1229         odb::dbInst* ii = instTable[kk];
1230         int instId = inst->getId();
1231         odb::dbBox* b = ii->getBBox();
1232         logger_->info(RCX, 391, "I[{}] {:10d} {:10d}  {:10d} {:10d}", kk,
1233                       b->xMin(), b->yMin(), b->xMax(), b->yMax());
1234         logger_->info(RCX, 394, "I[{}] {:10d} {:10d}  {:10d} {:10d}", kk,
1235                       rrb.xMin(), rrb.yMin(), rrb.xMax(), rrb.yMax());
1236       }
1237     }
1238 #endif
1239     if ((net->getSigType() == odb::dbSigType::POWER) && inst->getUserFlag1())
1240       continue;
1241     if ((net->getSigType() == odb::dbSigType::GROUND) && inst->getUserFlag2())
1242       continue;
1243 
1244     int bbXY[2] = {rb.xMin(), rb.yMin()};
1245     int bbXY2[2] = {rb.xMax(), rb.yMax()};
1246 
1247     int n = !dir;
1248 
1249     odb::dbITerm* iterm = findConnect(inst, net, srcCapNode->getNet());
1250     if (iterm == NULL)
1251       continue;
1252 
1253     int ixy[2];
1254     ixy[0] = xy[0];
1255     ixy[1] = xy[1];
1256     if (dir > 0)
1257       ixy[!dir] = rb.xMin();
1258     else
1259       ixy[!dir] = rb.yMin();
1260 
1261     srcCapNode =
1262         makePowerRes(srcCapNode, dir, ixy, level, WIDTH2, iterm->getId(), 1);
1263 
1264     if ((_dbgPowerFlow) ||
1265         ((debug != NULL) && (strcmp(inst->getConstName(), debug) == 0)))
1266       logger_->info(RCX, 309, "\t\tITERM [{}]: {} {}   <{}> {}", jj, ixy[0],
1267                     ixy[1], iterm->getId(), inst->getConstName());
1268 
1269     xy[!dir] = ixy[!dir];
1270   }
1271   return srcCapNode;
1272 }
getITermConn(uint dir,odb::dbWireEncoder & encoder,odb::dbWire * wire,odb::dbNet * net,int * xy,int * xy2)1273 uint extMain::getITermConn(uint dir, odb::dbWireEncoder& encoder,
1274                            odb::dbWire* wire, odb::dbNet* net, int* xy,
1275                            int* xy2) {
1276   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1277 
1278   int WIDTH2 = (xy2[dir] - xy[dir]);
1279   // odb::dbTechLayerRule *wRule=_netUtil->getRule(level,WIDTH2);
1280 
1281   std::vector<odb::dbInst*> instTable;
1282   uint instCnt =
1283       blkSearch->getInstBoxes(xy[0], xy[1], xy2[0], xy2[1], instTable);
1284 
1285   int prevX = xy[0];
1286   int prevY = xy[1];
1287   sortInst_x sort_by_x;
1288   std::sort(instTable.begin(), instTable.end(), sort_by_x);
1289 
1290   std::vector<odb::Rect> rectTable;
1291   for (uint kk = 0; kk < instCnt; kk++) {
1292     odb::dbInst* inst = instTable[kk];
1293     odb::dbBox* b = inst->getBBox();
1294     odb::Rect rb;
1295     b->getBox(rb);
1296     rectTable.push_back(rb);
1297   }
1298   for (uint jj = 0; jj < instCnt; jj++) {
1299     odb::dbInst* inst = instTable[jj];
1300     int instId = inst->getId();
1301     odb::dbBox* b = inst->getBBox();
1302     odb::Rect rb = rectTable[jj];
1303 
1304     if (jj < instCnt - 1) {
1305       odb::Rect rc = rectTable[jj + 1];
1306       if (rb.xMax() > rc.xMin())  // overallping
1307       {
1308         if (rb.xMax() > rc.xMax())  // switch inndices
1309         {
1310           rb.set_xlo(rc.xMax());
1311 
1312           rectTable[jj] = rc;
1313           rectTable[jj + 1] = rb;
1314 
1315           instTable[jj] = instTable[jj + 1];
1316           instTable[jj + 1] = inst;
1317         } else if (rb.xMax() < rc.xMax()) {
1318           rc.set_xlo(rb.xMax());
1319         } else {
1320           rc.set_xlo(rc.xMin() + WIDTH2 / 2);
1321           rb.set_xhi(rc.xMax() - WIDTH2 / 2);
1322         }
1323       }
1324     }
1325   }
1326   for (uint jj = 0; jj < instCnt; jj++) {
1327     odb::dbInst* inst = instTable[jj];
1328     int instId = inst->getId();
1329     odb::dbBox* b = inst->getBBox();
1330     odb::Rect rb = rectTable[jj];
1331 
1332     const char* debug = " ";
1333     if (strcmp(inst->getConstName(), debug) == 0) {
1334       logger_->info(RCX, 305,
1335                     "inst= {} net={} \tgetITermConn[{}]: {} {}  {} {}",
1336                     inst->getConstName(), net->getConstName(), instCnt, xy[0],
1337                     xy[1], xy2[0], xy2[1]);
1338       logger_->info(RCX, 400, "inst BBox= X {} {}  Y {} {}", rb.xMin(),
1339                     rb.xMax(), rb.yMin(), rb.yMax());
1340       logger_->info(RCX, 307, "instCount={} ----- --------- Prev X {}  Y {} ",
1341                     instCnt, prevX, prevY);
1342       for (uint kk = 0; kk < instCnt; kk++) {
1343         odb::Rect rrb = rectTable[kk];
1344         odb::dbInst* ii = instTable[kk];
1345         int instId = inst->getId();
1346         odb::dbBox* b = ii->getBBox();
1347         logger_->info(RCX, 392, "I[{}] {:10d} {:10d}  {:10d} {:10d}", kk,
1348                       b->xMin(), b->yMin(), b->xMax(), b->yMax());
1349         logger_->info(RCX, 308, "I[{}] {:10d} {:10d}  {:10d} {:10d}", kk,
1350                       rrb.xMin(), rrb.yMin(), rrb.xMax(), rrb.yMax());
1351       }
1352     }
1353     if ((net->getSigType() == odb::dbSigType::POWER) && inst->getUserFlag1())
1354       continue;
1355     if ((net->getSigType() == odb::dbSigType::GROUND) && inst->getUserFlag2())
1356       continue;
1357 
1358     if (strcmp(inst->getConstName(), debug) == 0)
1359       fprintf(stdout, "\t Before Ccheck\n");
1360     /*
1361                     if (dir>0) {
1362                             if (rb.xMin()>xy2[0]+WIDTH2/2)
1363                                     continue;
1364                             if (rb.xMax()<(xy[0]-WIDTH2/2))
1365                                     continue;
1366                     }
1367                     else {
1368                             if (rb.yMin()>xy2[1]+WIDTH2/2)
1369                                     continue;
1370                             if (rb.yMax()<xy[1]-WIDTH2/2)
1371                                     continue;
1372                     }
1373     */
1374     int bbXY[2] = {rb.xMin(), rb.yMin()};
1375     int bbXY2[2] = {rb.xMax(), rb.yMax()};
1376 
1377     // if (dir>0)
1378     // bbXY[!dir]= (bb->xMin()+bb->xMax())/2;
1379     // else
1380     // bbXY[!dir]= (bb->yMin()+bb->yMax())/2;
1381 
1382     int n = !dir;
1383     /*
1384                     if (!(  ( (bbXY[n]>=xy[n]) && (bbXY[n]<xy2[n])) ||
1385                     ((bbXY2[n]>=xy[n]) && (bbXY2[n]<xy2[n]))) )
1386                             continue;
1387     */
1388 
1389     odb::dbITerm* iterm = findConnect(inst, net, wire->getNet());
1390     if (strcmp(inst->getConstName(), debug) == 0)
1391       fprintf(stdout, "\t Before Connection\n");
1392 
1393     if (iterm == NULL) {
1394       continue;
1395     }
1396 
1397     if (strcmp(inst->getConstName(), debug) == 0)
1398       fprintf(stdout, "\t\t Connected!!!\n");
1399 
1400     int ixy[2];
1401     ixy[0] = xy[0];
1402     ixy[1] = xy[1];
1403     if (dir > 0)
1404       ixy[!dir] = rb.xMin();
1405     else
1406       ixy[!dir] = rb.yMin();
1407     int BB[2];
1408     if (dir > 0)
1409       BB[0] = (rb.xMin() + rb.xMax()) / 2;
1410     else
1411       BB[1] = (rb.yMin() + rb.yMax()) / 2;
1412 
1413     sameJunctionPoint(ixy, BB, WIDTH2, dir);
1414     // look at ..connect2( to see old code
1415 
1416     encoder.addPoint(ixy[0], ixy[1]);
1417     encoder.addITerm(iterm);
1418 
1419     if ((_dbgPowerFlow) ||
1420         ((debug != NULL) && (strcmp(inst->getConstName(), debug) == 0)))
1421       logger_->info(RCX, 393, "I[{}] {:10d} {:10d}  {:10d} {:10d}", jj, ixy[0],
1422                     ixy[1], iterm->getId(), inst->getConstName());
1423 
1424     xy[!dir] = ixy[!dir];
1425   }
1426   return instCnt;
1427 }
1428 class sortRect_y {
1429  public:
operator ()(odb::Rect * bb1,odb::Rect * bb2)1430   bool operator()(odb::Rect* bb1, odb::Rect* bb2) {
1431     if (bb1->yMin() != bb2->yMin())
1432       return bb1->yMin() < bb2->yMin();
1433     return bb1->yMax() < bb2->yMax();
1434   }
1435 };
1436 class sortRect_x {
1437  public:
operator ()(odb::Rect * bb1,odb::Rect * bb2)1438   bool operator()(odb::Rect* bb1, odb::Rect* bb2) {
1439     if (bb1->xMin() != bb2->xMin())
1440       return bb1->xMin() < bb2->xMin();
1441     return bb1->xMax() < bb2->xMax();
1442   }
1443 };
1444 
getSpecialItermShapes(odb::dbInst * inst,odb::dbNet * specialNet,uint dir,uint level,int * xy,int * xy2,std::vector<odb::Rect * > & rectTable,std::vector<odb::dbITerm * > & itermTable)1445 void extMain::getSpecialItermShapes(odb::dbInst* inst, odb::dbNet* specialNet,
1446                                     uint dir, uint level, int* xy, int* xy2,
1447                                     std::vector<odb::Rect*>& rectTable,
1448                                     std::vector<odb::dbITerm*>& itermTable) {
1449   odb::Rect bb(xy[0], xy[1], xy2[0], xy2[1]);
1450 
1451   odb::dbSet<odb::dbITerm> iterms = inst->getITerms();
1452   odb::dbSet<odb::dbITerm>::iterator iterm_itr;
1453 
1454   for (iterm_itr = iterms.begin(); iterm_itr != iterms.end(); ++iterm_itr) {
1455     odb::dbITerm* iterm = *iterm_itr;
1456 
1457     if (iterm->getNet() == NULL)
1458       continue;
1459     if (iterm->getNet() != specialNet)
1460       continue;
1461 
1462     std::vector<odb::Rect*> table;
1463     odb::dbShape s;
1464     odb::dbITermShapeItr term_shapes;
1465     for (term_shapes.begin(iterm); term_shapes.next(s);) {
1466       if (s.isVia())
1467         continue;
1468       if (s.getTechLayer()->getRoutingLevel() != level)
1469         continue;
1470 
1471       // odb::Rect r(s.xMin(), s.yMin(), s.xMax(), s.yMax());
1472       odb::Rect* r = new odb::Rect(s.xMin(), s.yMin(), s.xMax(), s.yMax());
1473 
1474       if (bb.overlaps(*r))
1475         table.push_back(r);
1476       else if (r->overlaps(bb))
1477         table.push_back(r);
1478     }
1479     if (table.size() > 1) {
1480       if (dir > 0)  // horiz
1481       {
1482         sortRect_x sort_by_x;
1483         std::sort(table.begin(), table.end(), sort_by_x);
1484       } else {
1485         sortRect_y sort_by_y;
1486         std::sort(table.begin(), table.end(), sort_by_y);
1487       }
1488     }
1489     for (uint kk = 0; kk < table.size(); kk++) {
1490       odb::Rect* t = table[kk];
1491       rectTable.push_back(t);
1492       itermTable.push_back(iterm);
1493     }
1494   }
1495 }
1496 
getITermPhysicalConn(uint dir,uint level,odb::dbWireEncoder & encoder,odb::dbWire * wire,odb::dbNet * net,int * xy,int * xy2)1497 uint extMain::getITermPhysicalConn(uint dir, uint level,
1498                                    odb::dbWireEncoder& encoder,
1499                                    odb::dbWire* wire, odb::dbNet* net, int* xy,
1500                                    int* xy2) {
1501   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1502 
1503   int WIDTH2 = (xy2[dir] - xy[dir]);
1504   // odb::dbTechLayerRule *wRule=_netUtil->getRule(level,WIDTH2);
1505 
1506   std::vector<odb::dbInst*> instTable;
1507   uint instCnt =
1508       blkSearch->getInstBoxes(xy[0], xy[1], xy2[0], xy2[1], instTable);
1509 
1510   int prevX = xy[0];
1511   int prevY = xy[1];
1512 
1513   if (dir > 0)  // horiz
1514   {
1515     sortInst_x sort_by_x;
1516     std::sort(instTable.begin(), instTable.end(), sort_by_x);
1517   } else {
1518     sortInst_y sort_by_y;
1519     std::sort(instTable.begin(), instTable.end(), sort_by_y);
1520   }
1521 
1522   std::vector<odb::Rect*> rectTable;
1523   std::vector<odb::dbITerm*> itermTable;
1524   for (uint kk = 0; kk < instCnt; kk++) {
1525     odb::dbInst* inst = instTable[kk];
1526     getSpecialItermShapes(inst, net, dir, level, xy, xy2, rectTable,
1527                           itermTable);
1528   }
1529 
1530   if (_dbgPowerFlow)
1531       // if (true)
1532   {
1533     logger_->info(RCX, 310,
1534                   "getITermPhysicalConn dir={} net={} {}: {} {}  {} {}", dir,
1535                   net->getConstName(), instCnt, xy[0], xy[1], xy2[0], xy2[1]);
1536     for (uint k = 0; k < rectTable.size(); k++) {
1537       odb::Rect* rb = rectTable[k];
1538       odb::dbITerm* iterm = itermTable[k];
1539       logger_->info(RCX, 387, "\tishape X {} {}  Y {} {} {} {} ", rb->xMin(),
1540                     rb->xMax(), rb->yMin(), rb->yMax(),
1541                     iterm->getInst()->getConstName(),
1542                     iterm->getMTerm()->getConstName());
1543     }
1544   }
1545   for (uint k = 0; k < rectTable.size(); k++) {
1546     odb::Rect* rb = rectTable[k];
1547     odb::dbITerm* iterm = itermTable[k];
1548     int bbXY[2] = {rb->xMin(), rb->yMin()};
1549     int bbXY2[2] = {rb->xMax(), rb->yMax()};
1550 
1551     // if (dir>0)
1552     // bbXY[!dir]= (bb->xMin()+bb->xMax())/2;
1553     // else
1554     // bbXY[!dir]= (bb->yMin()+bb->yMax())/2;
1555 
1556     int n = !dir;
1557     // if (!(  ( (bbXY[n]>=xy[n]) && (bbXY[n]<xy2[n])) ||
1558     //((bbXY2[n]>=xy[n]) && (bbXY2[n]<xy2[n]))) )
1559     // continue;
1560 
1561     int ixy[2];
1562     ixy[0] = xy[0];
1563     ixy[1] = xy[1];
1564     if (dir > 0)
1565       ixy[!dir] = rb->xMin();
1566     else
1567       ixy[!dir] = rb->yMin();
1568     int BB[2];
1569     if (dir > 0)
1570       BB[0] = (rb->xMin() + rb->xMax()) / 2;
1571     else
1572       BB[1] = (rb->yMin() + rb->yMax()) / 2;
1573 
1574     // sameJunctionPoint(ixy, BB, WIDTH2, dir);
1575     // look at ..connect2( to see old code
1576 
1577     uint jid = encoder.addPoint(ixy[0], ixy[1]);
1578     // encoder.addITerm(iterm);
1579     _junct2iterm->set(jid, iterm);
1580 
1581     xy[!dir] = ixy[!dir];
1582   }
1583   return instCnt;
1584 }
getITermPhysicalConnRC(odb::dbCapNode * srcCapNode,uint level,uint dir,odb::dbNet * net,int * xy,int * xy2,bool macro)1585 odb::dbCapNode* extMain::getITermPhysicalConnRC(odb::dbCapNode* srcCapNode,
1586                                                 uint level, uint dir,
1587                                                 odb::dbNet* net, int* xy,
1588                                                 int* xy2, bool macro) {
1589   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1590 
1591   int WIDTH2 = (xy2[dir] - xy[dir]);
1592   // odb::dbTechLayerRule *wRule=_netUtil->getRule(level,WIDTH2);
1593 
1594   std::vector<odb::dbInst*> instTable;
1595   uint instCnt =
1596       blkSearch->getInstBoxes(xy[0], xy[1], xy2[0], xy2[1], instTable);
1597 
1598   int prevX = xy[0];
1599   int prevY = xy[1];
1600 
1601   if (dir > 0)  // horiz
1602   {
1603     sortInst_x sort_by_x;
1604     std::sort(instTable.begin(), instTable.end(), sort_by_x);
1605   } else {
1606     sortInst_y sort_by_y;
1607     std::sort(instTable.begin(), instTable.end(), sort_by_y);
1608   }
1609 
1610   std::vector<odb::Rect*> rectTable;
1611   std::vector<odb::dbITerm*> itermTable;
1612   for (uint kk = 0; kk < instCnt; kk++) {
1613     odb::dbInst* inst = instTable[kk];
1614     getSpecialItermShapes(inst, net, dir, level, xy, xy2, rectTable,
1615                           itermTable);
1616   }
1617   if (_dbgPowerFlow)
1618       // if (true)
1619   {
1620     logger_->info(RCX, 388,
1621                   "getITermPhysicalConn dir={} net={} {}: {} {}  {} {}", dir,
1622                   net->getConstName(), instCnt, xy[0], xy[1], xy2[0], xy2[1]);
1623     for (uint k = 0; k < rectTable.size(); k++) {
1624       odb::Rect* rb = rectTable[k];
1625       odb::dbITerm* iterm = itermTable[k];
1626       logger_->info(RCX, 311, "\tishape X {} {}  Y {} {} {} {} ", rb->xMin(),
1627                     rb->xMax(), rb->yMin(), rb->yMax(),
1628                     iterm->getInst()->getConstName(),
1629                     iterm->getMTerm()->getConstName());
1630     }
1631   }
1632   for (uint k = 0; k < rectTable.size(); k++) {
1633     odb::Rect* rb = rectTable[k];
1634     odb::dbITerm* iterm = itermTable[k];
1635     if (!((iterm->getSigType() == odb::dbSigType::POWER) ||
1636           (iterm->getSigType() == odb::dbSigType::GROUND)))
1637       continue;  // COMMENT -- skip tie lo/hi -- 032613
1638 
1639     if (macro)  // if not hierarchical block but macro, check if for any
1640                 // connection! only one is allowed
1641     {
1642       odb::dbStringProperty* p = odb::dbStringProperty::find(iterm, "_inode");
1643       if (p != NULL)
1644         continue;
1645     }
1646 
1647     int n = !dir;
1648 
1649     int ixy[2];
1650     ixy[0] = xy[0];
1651     ixy[1] = xy[1];
1652     if (dir > 0)
1653       ixy[!dir] = rb->xMin();
1654     else
1655       ixy[!dir] = rb->yMin();
1656 
1657     srcCapNode =
1658         makePowerRes(srcCapNode, dir, ixy, level, WIDTH2, iterm->getId(), 1);
1659     // TO DELETE _junct2iterm _junct2iterm->set(srcCapNode->getId(), iterm);
1660 
1661     xy[!dir] = ixy[!dir];
1662   }
1663   return srcCapNode;
1664 }
1665 
1666 class sortBox_y {
1667  public:
operator ()(odb::dbBox * bb1,odb::dbBox * bb2)1668   bool operator()(odb::dbBox* bb1, odb::dbBox* bb2) {
1669     return bb1->yMin() < bb2->yMin();
1670   }
1671 };
1672 class sortBox_x {
1673  public:
operator ()(odb::dbBox * bb1,odb::dbBox * bb2)1674   bool operator()(odb::dbBox* bb1, odb::dbBox* bb2) {
1675     // if ( bb1->xMin() != bb2->xMin())
1676     return bb1->xMin() < bb2->xMin();
1677     // return bb1->xMax() < bb2->xMax();
1678   }
1679 };
1680 class sortBox_level {
1681   odb::dbBlockSearch* _blkSearch;
1682 
1683  public:
sortBox_level(odb::dbBlockSearch * blkSearch)1684   sortBox_level(odb::dbBlockSearch* blkSearch) { _blkSearch = blkSearch; }
1685 
1686  public:
operator ()(odb::dbBox * bb1,odb::dbBox * bb2)1687   bool operator()(odb::dbBox* bb1, odb::dbBox* bb2) {
1688     uint top;
1689     uint bot1 = _blkSearch->getViaLevels(bb1, top);
1690     uint bot2 = _blkSearch->getViaLevels(bb2, top);
1691 
1692     return bot1 < bot2;
1693   }
1694 };
1695 
overlapWithMacro(odb::Rect & w)1696 bool extMain::overlapWithMacro(odb::Rect& w) {
1697   for (uint ii = 0; ii < _powerMacroTable.size(); ii++) {
1698     odb::dbInst* inst = _powerMacroTable[ii];
1699     odb::Rect r0;
1700     odb::dbBox* bb = inst->getBBox();
1701     bb->getBox(r0);
1702 
1703     if (r0.inside(w))
1704       return true;
1705   }
1706   return false;
1707 }
skipSideMetal(std::vector<odb::dbBox * > & viaTable,uint level,odb::dbNet * net,odb::Rect * w)1708 bool extMain::skipSideMetal(std::vector<odb::dbBox*>& viaTable, uint level,
1709                             odb::dbNet* net, odb::Rect* w) {
1710   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1711   int width = w->minDXDY();
1712   int len = w->maxDXDY();
1713   /*
1714           int xy1[2]= {w->xMin(), w->yMin()};
1715           int xy[2];
1716           xy[0]= xy1[0];
1717           xy[1]= xy1[1];
1718   */
1719   uint Met[2];
1720   odb::dbBox* vTable[2];
1721   uint vCnt = 0;
1722 
1723   uint viaCnt = viaTable.size();
1724   for (uint ii = 0; ii < viaCnt; ii++) {
1725     // int xy2[2]= {w->xMax(), w->yMax()};
1726 
1727     odb::dbBox* v = viaTable[ii];
1728 
1729     uint top;
1730     uint bot = blkSearch->getViaLevels(v, top);
1731     if (!((level == bot) || (level == top)))
1732       continue;
1733 
1734     if (vCnt > 1)
1735       return false;
1736 
1737     Met[vCnt] = bot;
1738     vTable[vCnt++] = v;
1739   }
1740   if (vCnt < 2)
1741     return false;
1742 
1743   odb::dbBox* v0 = vTable[0];
1744   odb::dbBox* v1 = vTable[1];
1745   odb::Rect r0;
1746   odb::Rect r1;
1747   v0->getBox(r0);
1748   v1->getBox(r1);
1749   bool overlap = r0.overlaps(r1);
1750 
1751   if ((Met[0] == Met[1]) &&
1752       ((Met[0] + 1) == level))  // conn from met1 rail to v12 to m2 to v12
1753                                 // tie lo/hi connectivity
1754   {
1755     if (overlap)
1756       return false;
1757 
1758     return true;  // COMMENT 03/26/13 -- small wire with 2 vias
1759 
1760     if ((_via_map[v0] != NULL) && (_via_map[v1] != NULL))
1761       return false;
1762 
1763     if ((_via_map[v0] != NULL) && (!overlapWithMacro(r1)))
1764       return true;
1765     if ((_via_map[v1] != NULL) && (!overlapWithMacro(r0)))
1766       return true;
1767   }
1768   if (Met[0] != Met[1])  // small metal between 2 stacked vias : satisfy DRC ??
1769   {
1770     if (overlap)
1771       return true;
1772   }
1773   return false;
1774 }
sortViasXY(uint dir,std::vector<odb::dbBox * > & viaTable)1775 void extMain::sortViasXY(uint dir, std::vector<odb::dbBox*>& viaTable) {
1776   if (dir > 0)  // horiz
1777   {
1778     sortBox_x sort_by_x;
1779     std::sort(viaTable.begin(), viaTable.end(), sort_by_x);
1780   } else {
1781     sortBox_y sort_by_y;
1782     std::sort(viaTable.begin(), viaTable.end(), sort_by_y);
1783   }
1784 }
getViaResNode(odb::dbBox * v,const char * propName)1785 char* extMain::getViaResNode(odb::dbBox* v, const char* propName) {
1786   // odb::dbIntProperty *p= (odb::dbIntProperty*) odb::dbIntProperty::find(v,
1787   // propName);
1788   odb::dbIntProperty* p = odb::dbIntProperty::find(v, propName);
1789   if (p == NULL)
1790     return NULL;
1791   uint capId = p->getValue();
1792   odb::dbCapNode* capNode = odb::dbCapNode::getCapNode(_block, capId);
1793 
1794   char buf[2048];
1795   odb::dbStringProperty* ppp = odb::dbStringProperty::find(capNode, "_inode");
1796   if (ppp == NULL)
1797     return NULL;
1798 
1799   char* retStr = new char[128];
1800   strcpy(retStr, ppp->getValue().c_str());
1801   return retStr;
1802 }
addUpperVia(uint ii,odb::dbBox * v)1803 void extMain::addUpperVia(uint ii, odb::dbBox* v) {
1804   _viaUpperTable[ii].push_back(v);
1805 }
writeViaResistorsRC(FILE * fp,uint ii,FILE * fp1)1806 void extMain::writeViaResistorsRC(FILE* fp, uint ii, FILE* fp1) {
1807   if (fp == NULL)
1808     return;
1809   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1810 
1811   uint vCnt = _viaUpperTable[ii].size();
1812   for (uint jj = 0; jj < vCnt; jj++) {
1813     odb::dbBox* v = _viaUpperTable[ii][jj];
1814     if (v->isMarked())
1815       continue;
1816 
1817     v->setMarked(true);
1818 
1819     uint top;
1820     uint bot = blkSearch->getViaLevels(v, top);
1821     // 10312012
1822     float res = getPowerViaRes(v, 0.1);
1823     char bufRes[128];
1824     sprintf(bufRes, "%g", res);
1825     odb::dbStringProperty* p = odb::dbStringProperty::find(v, "_Res");
1826     if (p != NULL)
1827       sprintf(bufRes, "%s", p->getValue().c_str());
1828 
1829     char* srcNode = getViaResNode(v, "_up_node");
1830     char* dstNode = getViaResNode(v, "_down_node");
1831 
1832     // if ((srcNode==NULL)&&(dstNode==NULL))
1833     if ((srcNode == NULL) || (dstNode == NULL)) {
1834       continue;
1835     }
1836     if (dstNode == NULL) {
1837       continue;
1838     }
1839 
1840     if (srcNode == NULL) {
1841       logger_->info(RCX, 312, "src is NULL R_M{}M{}_{}", bot, top, v->getId());
1842       srcNode = new char[64];
1843       sprintf(srcNode, "%s_%d", dstNode, bot);
1844     }
1845     fprintf(fp, "R_M%dM%d_%d ", bot, top, v->getId());
1846     fprintf(fp, " %s %s %s\n", srcNode, dstNode, bufRes);
1847     if (fp1 != NULL) {
1848       fprintf(fp1, "R_M%dM%d_%d ", bot, top, v->getId());
1849       fprintf(fp1, " %s %s %s\n", srcNode, dstNode, bufRes);
1850     }
1851   }
1852   for (uint jj = 0; jj < vCnt; jj++) {
1853     odb::dbBox* v = _viaUpperTable[ii][jj];
1854     v->setMarked(false);
1855   }
1856   _viaUpperTable[ii].clear();
1857 }
writeViaResistors(FILE * fp,uint ii,FILE * fp1,bool skipWireConn)1858 void extMain::writeViaResistors(FILE* fp, uint ii, FILE* fp1,
1859                                 bool skipWireConn) {
1860   if (skipWireConn)
1861     return writeViaResistorsRC(fp, ii, fp1);
1862 
1863   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
1864 
1865   uint vCnt = _viaUpperTable[ii].size();
1866   /*
1867           for (uint jj= 0; jj<vCnt; jj++) {
1868                   odb::dbBox *v= _viaUpperTable[ii][jj];
1869                   v->setMarked(false);
1870           }
1871   */
1872   for (uint jj = 0; jj < vCnt; jj++) {
1873     odb::dbBox* v = _viaUpperTable[ii][jj];
1874     if (v->isMarked())
1875       continue;
1876 
1877     uint top;
1878     uint bot = blkSearch->getViaLevels(v, top);
1879     // 10312012
1880     float res = getPowerViaRes(v, 0.1);
1881 
1882     fprintf(fp, "R_M%dM%d_%d ", bot, top, v->getId());
1883     if (!_nodeCoords) {
1884       fprintf(fp, "vM%dM%d_%d_%d", bot, top, top, v->getId());
1885       fprintf(fp, " vM%dM%d_%d_%d", bot, top, bot, v->getId());
1886       fprintf(fp, " %g\n", res);
1887       if (fp1 != NULL) {
1888         fprintf(fp1, "R_M%dM%d_%d_%d ", bot, top, v->xMin(), v->yMin());
1889         fprintf(fp1, "vM%dM%d_%d_%d", bot, top, top, v->getId());
1890         fprintf(fp1, " vM%dM%d_%d_%d", bot, top, bot, v->getId());
1891         fprintf(fp1, " %g\n", res);
1892       }
1893     } else {
1894       char srcNode[128];
1895       char dstNode[128];
1896       writeViaName_xy(srcNode, v, bot, top, top);
1897       writeViaName_xy(dstNode, v, bot, top, bot);
1898 
1899       // fprintf(fp, " %s %s %g\n", srcNode, dstNode, res);
1900       char buf[2048];
1901       odb::dbStringProperty* p = odb::dbStringProperty::find(v, "_Res");
1902       if (p != NULL)
1903         fprintf(fp, " %s %s %s\n", srcNode, dstNode, p->getValue().c_str());
1904       else
1905         fprintf(fp, " %s %s %g\n", srcNode, dstNode, res);
1906 
1907       if (fp1 != NULL) {
1908         fprintf(fp1, "R_M%dM%d_%d_%d ", bot, top, v->xMin(), v->yMin());
1909         if (p != NULL)
1910           fprintf(fp1, " %s %s %s\n", srcNode, dstNode, p->getValue().c_str());
1911         else
1912           fprintf(fp1, " %s %s %g\n", srcNode, dstNode, res);
1913       }
1914     }
1915     v->setMarked(true);
1916   }
1917 }
sameJunctionPoint(int xy[2],int BB[2],uint width,uint dir)1918 bool extMain::sameJunctionPoint(int xy[2], int BB[2], uint width, uint dir) {
1919   width = 0;
1920   int dd[2] = {xy[0] - _prevX, xy[1] - _prevY};
1921   if ((dir > 0) && (dd[0] <= width / 2)) {
1922     xy[0] = BB[0];
1923     return true;
1924   } else if ((dir == 0) && (dd[1] <= width / 2)) {
1925     xy[1] = BB[1];
1926     return true;
1927   }
1928   _prevX = xy[0];
1929   _prevY = xy[1];
1930   return false;
1931 }
addGroupVias(uint level,odb::Rect * w,std::vector<odb::dbBox * > & viaTable)1932 uint extMain::addGroupVias(uint level, odb::Rect* w,
1933                            std::vector<odb::dbBox*>& viaTable) {
1934   uint cnt = 0;
1935   for (uint ll = 0; ll < _multiViaBoxTable[level].size(); ll++) {
1936     odb::dbBox* v = _multiViaBoxTable[level][ll];
1937     odb::Rect vr;
1938     v->getBox(vr);
1939     if (!w->overlaps(vr))
1940       continue;
1941     odb::dbTechVia* via = v->getTechVia();
1942 
1943     viaTable.push_back(v);
1944     cnt++;
1945   }
1946   return cnt;
1947 }
createNode_xy_RC(char * buf,odb::dbCapNode * capNode,int x,int y,int level)1948 void extMain::createNode_xy_RC(char* buf, odb::dbCapNode* capNode, int x, int y,
1949                                int level) {
1950   int netId = _netUtil->getCurrentNet()->getId();
1951   writeNegativeCoords(buf, netId, x, y, level);
1952 
1953   odb::dbStringProperty::create(capNode, "_inode", buf);
1954   capNode->setNameFlag();
1955 }
getPowerCapNode(odb::dbNet * net,int xy,uint level)1956 odb::dbCapNode* extMain::getPowerCapNode(odb::dbNet* net, int xy, uint level) {
1957   odb::dbCapNode* cap = odb::dbCapNode::create(net, 0, _foreign);
1958 
1959   cap->setInternalFlag();
1960   cap->setBranchFlag();
1961 
1962   cap->setNode(0);
1963 
1964   char buf[2048];
1965   createNode_xy_RC(buf, cap, _last_node_xy[0], _last_node_xy[1], level);
1966 
1967   return cap;
1968 }
makePowerRes(odb::dbCapNode * srcCap,uint dir,int xy[2],uint level,uint width,uint objId,int type)1969 odb::dbCapNode* extMain::makePowerRes(odb::dbCapNode* srcCap, uint dir,
1970                                       int xy[2], uint level, uint width,
1971                                       uint objId, int type) {
1972   bool dbg = false;
1973   bool foreign = false;
1974   odb::dbCapNode* dstCap = odb::dbCapNode::create(srcCap->getNet(), 0, foreign);
1975   dstCap->setNode(objId);  // it can be 0 if first/last node of the rail
1976 
1977   char CapNodeName[2048];
1978   createNode_xy_RC(CapNodeName, dstCap, xy[0], xy[1], level);
1979 
1980   if (type < 0)  // internal node
1981   {
1982     dstCap->setInternalFlag();
1983     dstCap->setBranchFlag();
1984   } else if (type == 0)  // via
1985   {
1986     dstCap->setInternalFlag();
1987     dstCap->setBranchFlag();
1988   } else {
1989     dstCap->setITermFlag();
1990     odb::dbITerm* iterm = odb::dbITerm::getITerm(_block, objId);
1991     odb::dbStringProperty* p = odb::dbStringProperty::find(iterm, "_inode");
1992     if (p != NULL) {
1993       odb::dbStringProperty::destroy(p);
1994       // sprintf(buf, "%s %s",  buf, p->getValue().c_str());
1995     }
1996     odb::dbStringProperty::create(iterm, "_inode", strdup(CapNodeName));
1997   }
1998   uint pathDir = 0;
1999   odb::dbRSeg* rc =
2000       odb::dbRSeg::create(srcCap->getNet(), xy[0], xy[1], pathDir, true);
2001 
2002   uint rid = rc->getId();
2003 
2004   rc->setSourceNode(srcCap->getId());
2005   rc->setTargetNode(dstCap->getId());
2006 
2007   int len = xy[!dir] - _last_node_xy[!dir];
2008   len -= width;
2009   if (len <= 0)
2010     len += width;
2011   if (len <= 0)
2012     len = width;
2013 
2014   double res = getResistance(level, width, len, 0);
2015   rc->setResistance(res);
2016 
2017   if (dbg) {
2018     if (xy[!dir] - _last_node_xy[!dir] <= 0) {
2019       logger_->info(
2020           RCX, 313,
2021           "R_{} level{} dir={}   xy[{}]={:10d}  _last_node_xy[{}]={:10d}   "
2022           "  len= {:10d} width= {:d} calc_len= {:d} res={:g}",
2023           rid, level, dir, !dir, xy[!dir], !dir, _last_node_xy[!dir],
2024           xy[!dir] - _last_node_xy[!dir], width, len, res);
2025     }
2026   }
2027 
2028   double cap = _modelTable->get(0)->getTotCapOverSub(level) * len;
2029   rc->setCapacitance(cap);
2030 
2031   _last_node_xy[0] = xy[0];
2032   _last_node_xy[1] = xy[1];
2033 
2034   return dstCap;
2035 }
viaTagByCapNode(odb::dbBox * v,odb::dbCapNode * cap)2036 void extMain::viaTagByCapNode(odb::dbBox* v, odb::dbCapNode* cap) {
2037   odb::dbIntProperty* p = odb::dbIntProperty::find(v, "_up_node");
2038   if (p == NULL)
2039     odb::dbIntProperty::create(v, "_up_node", cap->getId());
2040   else
2041     odb::dbIntProperty::create(v, "_down_node", cap->getId());
2042 }
viaAndInstConnRC(uint dir,uint width,odb::dbTechLayer * layer,odb::dbNet * net,odb::dbNet * orig_power_net,odb::Rect * w,bool skipSideMetalFlag)2043 uint extMain::viaAndInstConnRC(uint dir, uint width, odb::dbTechLayer* layer,
2044                                odb::dbNet* net, odb::dbNet* orig_power_net,
2045                                odb::Rect* w, bool skipSideMetalFlag) {
2046   int EXT = 0;
2047   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
2048   // ----------------------------
2049   // --------------------------
2050   // -i-V--i---i---i--V---i---V--i-
2051   //    -------------------------
2052   std::vector<odb::dbBox*> viaTable;
2053   int level = layer->getRoutingLevel();
2054 
2055   uint viaCnt = blkSearch->getPowerWiresAndVias(
2056       w->xMin(), w->yMin(), w->xMax(), w->yMax(), level, orig_power_net, false,
2057       viaTable);
2058   uint wireCnt = 0;
2059   if (skipSideMetalFlag) {
2060     if ((level == 2) && (skipSideMetal(viaTable, level, net, w)))
2061       return 0;
2062     if ((level == 3) && (skipSideMetal(viaTable, level, net, w)))
2063       return 0;
2064     if ((level == 5) && (skipSideMetal(viaTable, level, net, w)))
2065       return 0;
2066   }
2067   bool isVDDnet = false;
2068   if (orig_power_net->getSigType() == odb::dbSigType::POWER)
2069     isVDDnet = true;
2070 
2071   int LAST_VIA_MAX[2] = {w->xMin(), w->yMin()};
2072 
2073   int xy1[2] = {w->xMin(), w->yMin()};
2074 
2075   int xy[2];
2076   xy[0] = xy1[0];
2077   xy[1] = xy1[1];
2078   int lastXY[2] = {w->xMin(), w->yMin()};
2079 
2080   _last_node_xy[0] = xy[0];
2081   _last_node_xy[1] = xy[1];
2082   odb::dbCapNode* srcCapNode = NULL;
2083   if (level >= 1)  // for first rcseg
2084   {
2085     _last_node_xy[!dir] -= width / 2;
2086     srcCapNode = getPowerCapNode(net, xy[!dir] - width / 2, level);  // pseudo
2087     srcCapNode = makePowerRes(srcCapNode, dir, xy, level, width, 0, 0);
2088   } else
2089     srcCapNode = getPowerCapNode(net, xy[!dir], level);
2090 
2091   std::vector<odb::dbBox*> processedViaTable;
2092 
2093   uint gridViaCnt = viaCnt;
2094   uint powerSrcCnt = addPowerSources(viaTable, isVDDnet, level, w);
2095   uint gViaCnt = addGroupVias(level + 1, w, viaTable);
2096   gViaCnt += addGroupVias(level, w, viaTable);
2097   sortViasXY(dir, viaTable);
2098   uint jid = 0;
2099   viaCnt = viaTable.size();
2100   if (_dbgPowerFlow)
2101     // if (level==5)
2102     logger_->info(RCX, 386, "viaAndInstConnRC[{}={}+{}+{}]: {} {}  {} {}",
2103                   viaCnt, gViaCnt, gridViaCnt, powerSrcCnt, w->xMin(),
2104                   w->yMin(), w->xMax(), w->yMax());
2105   for (uint ii = 0; ii < viaCnt; ii++) {
2106     int xy2[2] = {w->xMax(), w->yMax()};
2107 
2108     odb::dbBox* v = viaTable[ii];
2109 
2110     int viaXY[2] = {v->xMin(), v->yMin()};
2111 
2112     uint top;
2113     uint bot = blkSearch->getViaLevels(v, top);
2114 
2115     odb::Rect vr;
2116     v->getBox(vr);
2117     if (!w->overlaps(vr))
2118       continue;
2119 
2120     char* sname = NULL;
2121     if (v->isVisited())
2122       continue;
2123 
2124     if (!((level == bot) || (level == top))) {
2125       if ((bot == 0) && (top == 0)) {
2126         sname = getPowerSourceName(isVDDnet, level, v->getId());
2127         logger_->info(RCX, 315, "    powerLocName= {}", sname);
2128 
2129         if (sname == NULL)
2130           continue;
2131       } else {
2132         continue;
2133       }
2134     }
2135 
2136     v->setVisited(true);
2137     processedViaTable.push_back(v);
2138     if (dir > 0)
2139       xy2[!dir] = (v->xMin() + v->xMax()) / 2;
2140     // xy2[!dir]= v->xMin();
2141     else
2142       xy2[!dir] = (v->yMin() + v->yMax()) / 2;
2143     // xy2[!dir]= v->yMin();
2144 
2145     // V--I---I---I--V---
2146     uint itermCnt = 0;
2147 
2148     if (level == 1) {
2149       // TODO if (!skipSideMetalFlag && (_via_id_map[v->getId()]==NULL))
2150       // continue;
2151       srcCapNode =
2152           getITermConnRC(srcCapNode, level, dir, orig_power_net, xy, xy2);
2153     } else if (topHierBlock()) {
2154       srcCapNode = getITermPhysicalConnRC(srcCapNode, level, dir,
2155                                           orig_power_net, xy, xy2, false);
2156     } else  // 03/03/13 -- connectivity to the power wire only -- will mark
2157             // iterm!
2158     {
2159       bool macro = true;
2160 
2161       // 03132013 -- the wire is trying to connect! -- the via should connect
2162       // with iterm2vias
2163       srcCapNode = getITermPhysicalConnRC(srcCapNode, level, dir,
2164                                           orig_power_net, xy, xy2, macro);
2165     }
2166     LAST_VIA_MAX[0] = v->xMax();  //
2167     LAST_VIA_MAX[1] = v->yMax();  //
2168 
2169     srcCapNode =
2170         makePowerRes(srcCapNode, dir, xy2, level, width, v->getId(), 0);
2171     viaTagByCapNode(v, srcCapNode);
2172 
2173     if (_dbgPowerFlow) {
2174       char* prop = getViaResNode(v, "_up_node");
2175       logger_->info(RCX, 316, "M{} via[{}]: {}  {} {}  {} {}", level,
2176                     v->getId(), prop, v->xMin(), v->yMin(), v->xMax(),
2177                     v->yMax());
2178     }
2179 
2180     xy[!dir] = xy2[!dir];
2181     xy2[dir] = xy1[dir];
2182     lastXY[dir] = xy2[dir];
2183     lastXY[!dir] = xy2[!dir];
2184     if (level == 1) {
2185       _viaM1Table->push_back(v);
2186       if (skipSideMetalFlag)
2187         _via_map[v] = net;
2188     } else {
2189       if (sname == NULL)
2190         addUpperVia(isVDDnet, v);
2191       else {
2192         odb::dbStringProperty* p =
2193             odb::dbStringProperty::find(srcCapNode, "_inode");
2194         if (p != NULL)
2195           p->setValue(sname);
2196         else
2197           odb::dbStringProperty::create(srcCapNode, "_inode", sname);
2198 
2199         addPowerSourceName(isVDDnet, sname);
2200       }
2201     }
2202   }
2203   for (uint ii = 0; ii < processedViaTable.size(); ii++)
2204     processedViaTable[ii]->setVisited(false);
2205 
2206   int lastXY2[2] = {w->xMax(), w->yMax()};
2207   if (topHierBlock()) {
2208     srcCapNode = getITermPhysicalConnRC(srcCapNode, level, dir, orig_power_net,
2209                                         lastXY, lastXY2, false);
2210   } else if ((level == 1) && (lastXY[!dir] < lastXY2[!dir])) {
2211     srcCapNode =
2212         getITermConnRC(srcCapNode, level, dir, orig_power_net, lastXY, lastXY2);
2213     // if (itermCnt>0)
2214     // fprintf(stdout, "Last Wire iterm= %d\n", itermCnt);
2215   } else if (level > 1)  // 03/03/13 -- connectivity to the power wire only --
2216                          // will mark iterm!
2217   {
2218     srcCapNode = getITermPhysicalConnRC(srcCapNode, level, dir, orig_power_net,
2219                                         lastXY, lastXY2, true);
2220   }
2221   /* TODO
2222           if (lastXY[!dir]<lastXY2[!dir]) {
2223                   lastXY2[dir]= lastXY[dir];
2224                   srcCapNode= makePowerRes(srcCapNode, dir, lastXY2, level,
2225      width, 0, -1);
2226           }
2227   */
2228   return lastXY[!dir];
2229 }
viaAndInstConn(uint dir,uint width,odb::dbTechLayer * layer,odb::dbWireEncoder & encoder,odb::dbWire * wire,odb::dbNet * net,odb::Rect * w,bool skipSideMetalFlag)2230 uint extMain::viaAndInstConn(uint dir, uint width, odb::dbTechLayer* layer,
2231                              odb::dbWireEncoder& encoder, odb::dbWire* wire,
2232                              odb::dbNet* net, odb::Rect* w,
2233                              bool skipSideMetalFlag) {
2234   int EXT = 0;
2235   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
2236   // ----------------------------
2237   // --------------------------
2238   // -i-V--i---i---i--V---i---V--i-
2239   //    -------------------------
2240   std::vector<odb::dbBox*> viaTable;
2241   std::vector<odb::dbBox*> crossWireTable;
2242   int level = layer->getRoutingLevel();
2243 
2244   // int width= w->minDXDY();
2245 
2246   uint viaCnt = blkSearch->getPowerWiresAndVias(
2247       w->xMin(), w->yMin(), w->xMax(), w->yMax(), level, net, false, viaTable);
2248 
2249   uint wireCnt = 0;
2250   if (skipSideMetalFlag) {
2251     if ((level == 2) && (skipSideMetal(viaTable, level, net, w)))
2252       return 0;
2253     if ((level == 3) && (skipSideMetal(viaTable, level, net, w)))
2254       return 0;
2255     if ((level == 5) && (skipSideMetal(viaTable, level, net, w)))
2256       return 0;
2257   }
2258   bool isVDDnet = false;
2259   if (net->getSigType() == odb::dbSigType::POWER)
2260     isVDDnet = true;
2261   odb::dbTechLayerRule* wRule = _netUtil->getRule(level, width);
2262   // wRule->setWireExtension(width);
2263   encoder.newPath(layer, odb::dbWireType::ROUTED, wRule);
2264 
2265   int xy1[2] = {w->xMin(), w->yMin()};
2266   /*
2267           if (dir==0) // vertical
2268                   xy1[0]= w->xMin()+width/2;
2269           else
2270                   xy1[1]= w->yMin()+width/2;
2271   */
2272   int xy[2];
2273   xy[0] = xy1[0];
2274   xy[1] = xy1[1];
2275   int lastXY[2] = {w->xMin(), w->yMin()};
2276 
2277   encoder.addPoint(w->xMin(), w->yMin(), 0, 0);
2278 
2279   if (_dbgPowerFlow)
2280     // if (level==7)
2281     logger_->info(RCX, 314, "viaAndInstConn[{}]: {} {}  {} {}", viaCnt,
2282                   w->xMin(), w->yMin(), w->xMax(), w->yMax());
2283 
2284   std::vector<odb::dbBox*> processedViaTable;
2285 
2286   uint powerSrcCnt = addPowerSources(viaTable, isVDDnet, level, w);
2287   uint gViaCnt = addGroupVias(level + 1, w, viaTable);
2288   gViaCnt += addGroupVias(level, w, viaTable);
2289   sortViasXY(dir, viaTable);
2290   uint jid = 0;
2291   viaCnt = viaTable.size();
2292   for (uint ii = 0; ii < viaCnt; ii++) {
2293     int xy2[2] = {w->xMax(), w->yMax()};
2294 
2295     odb::dbBox* v = viaTable[ii];
2296 
2297     odb::Rect vr;
2298     v->getBox(vr);
2299     if (!w->overlaps(vr)) {
2300       continue;
2301     }
2302 
2303     char* sname = NULL;
2304     if (v->isVisited())
2305       continue;
2306 
2307     v->setVisited(true);
2308     processedViaTable.push_back(v);
2309 
2310     uint top;
2311     uint bot = blkSearch->getViaLevels(v, top);
2312     if (!((level == bot) || (level == top))) {
2313       if ((bot == 0) && (top == 0)) {
2314         sname = getPowerSourceName(isVDDnet, level, v->getId());
2315         if (sname == NULL)
2316           continue;
2317       } else {
2318         continue;
2319       }
2320     }
2321     if (dir > 0)
2322       xy2[!dir] = (v->xMin() + v->xMax()) / 2;
2323     else
2324       xy2[!dir] = (v->yMin() + v->yMax()) / 2;
2325     // V--I---I---I--V---
2326     uint itermCnt = 0;
2327 
2328     if (level == 1) {
2329       if (!skipSideMetalFlag && (_via_id_map[v->getId()] == NULL))
2330         continue;
2331       itermCnt = getITermConn(dir, encoder, wire, net, xy, xy2);
2332     } else if (topHierBlock()) {
2333       itermCnt = getITermPhysicalConn(dir, level, encoder, wire, net, xy, xy2);
2334     }
2335 
2336     xy[!dir] = xy2[!dir];
2337 
2338     xy2[dir] = xy1[dir];
2339     int BB[2] = {v->xMax(), v->yMax()};
2340     sameJunctionPoint(xy2, BB, width, dir);
2341     jid = encoder.addPoint(xy2[0], xy2[1], v->getId());  // viapoint
2342     if (_dbgPowerFlow) {
2343       logger_->info(RCX, 317, "\t\tencoder.addPoint [{}]: {} {} VIA={}", ii,
2344                     xy2[0], xy2[1], v->getId());
2345       logger_->info(RCX, 318, "\t\tvia: id={} {} {}  {} {}", v->getId(),
2346                     v->xMin(), v->yMin(), v->xMax(), v->yMax());
2347     }
2348     if (sname == NULL)
2349       _junct2viaMap->set(jid, v->getId());
2350     else
2351       _junct2viaMap->set(jid, -v->getId());
2352 
2353     lastXY[dir] = xy2[dir];
2354     lastXY[!dir] = xy2[!dir];
2355     if (level == 1) {
2356       _viaM1Table->push_back(v);
2357       if (skipSideMetalFlag)
2358         _via_map[v] = wire->getNet();
2359     } else {
2360       if (sname == NULL)
2361         addUpperVia(isVDDnet, v);
2362       else
2363         addPowerSourceName(isVDDnet, sname);
2364     }
2365   }
2366   for (uint ii = 0; ii < processedViaTable.size(); ii++) {
2367     /* added DKF 09052012 - begin
2368     odb::dbBox *v= viaTable[ii];
2369     uint top;
2370     uint bot= blkSearch->getViaLevels(v, top);
2371     if (bot==1)
2372     // added DKF 09052012 - end */
2373     processedViaTable[ii]->setVisited(false);
2374   }
2375 
2376   int lastXY2[2] = {w->xMax(), w->yMax()};
2377   if (topHierBlock()) {
2378     uint itermCnt =
2379         getITermPhysicalConn(dir, level, encoder, wire, net, lastXY, lastXY2);
2380   } else if ((level == 1) && (lastXY[!dir] < lastXY2[!dir])) {
2381     uint itermCnt = getITermConn(dir, encoder, wire, net, lastXY, lastXY2);
2382     // if (itermCnt>0)
2383     // fprintf(stdout, "Last Wire iterm= %d\n", itermCnt);
2384   }
2385   if (lastXY[!dir] < lastXY2[!dir]) {
2386     lastXY2[dir] = lastXY[dir];
2387     //       jid= encoder.addPoint(lastXY2[0], lastXY2[1]); // viapoint
2388     jid = encoder.addPoint(lastXY2[0], lastXY2[1]);  // viapoint
2389   }
2390 
2391   // encoder.end();
2392   return lastXY[!dir];
2393 }
createRailNet(odb::dbNet * pnet,odb::dbTechLayer * layer,odb::Rect * w)2394 odb::dbNet* extMain::createRailNet(odb::dbNet* pnet, odb::dbTechLayer* layer,
2395                                    odb::Rect* w) {
2396   char buf_name[128];
2397   sprintf(buf_name, "%s_%s_%d_%d_%d_%d", pnet->getConstName(),
2398           layer->getConstName(), w->xMin(), w->yMin(), w->xMax(), w->yMax());
2399 
2400   odb::dbNet* power_net = odb::dbNet::create(_block, buf_name);
2401   // fprintf(stdout, "Created net %d %s\n", power_net->getId(),
2402   // power_net->getConstName());
2403   return power_net;
2404 }
powerWireConnRC(odb::Rect * w,uint dir,odb::dbTechLayer * layer,odb::dbNet * net)2405 void extMain::powerWireConnRC(odb::Rect* w, uint dir, odb::dbTechLayer* layer,
2406                               odb::dbNet* net) {
2407   int length = w->maxDXDY();
2408   int width = w->minDXDY();
2409 
2410   odb::dbNet* power_net = createRailNet(net, layer, w);
2411   if (net->getSigType() == odb::dbSigType::POWER)
2412     power_net->setMark(true);
2413 
2414   _junct2viaMap->clear(0);
2415   uint jid = 0;
2416 
2417   uint len = w->maxDXDY();
2418   uint level = layer->getRoutingLevel();
2419 
2420   double Res = getResistance(level, width, len, 0);
2421 
2422   FILE* cirFP = _globCir;
2423   if (level == 1)
2424     cirFP = _stdCir;
2425   fprintf(cirFP,
2426           "\n\n*** EST. RAIL [M%d] : L=%g W=%g R=%g coords: %g %g %g %g\n",
2427           level, micronCoords(len), micronCoords(width), Res,
2428           micronCoords(w->xMin()), micronCoords(w->yMin()),
2429           micronCoords(w->xMax()), micronCoords(w->yMax()));
2430 
2431   bool skipSideMetalFlag = true;  // COMMENT 032613 skip tie lo/hi
2432   viaAndInstConnRC(dir, width, layer, power_net, net, w, skipSideMetalFlag);
2433 
2434   bool skipEnds = true;
2435   // if (level==1)
2436   // skipEnds= false;
2437   bool onlyVias = false;
2438 
2439   bool writeCapNodes = false;
2440   bool reverseRs = true;
2441   float totCap = 0;
2442   fprintf(cirFP, "\n*layer:M%d,%s net:%d\n\n", level, net->getConstName(),
2443           net->getId());
2444   char buff[120];
2445   findViaMainCoord(power_net, buff);
2446   Ath__parser parser;
2447 
2448   int n1 = parser.mkWords(buff, "_");
2449   int xy[2];
2450   bool ok2replace = true;
2451   if (n1 > 2) {
2452     xy[0] = parser.getInt(1);
2453     xy[1] = parser.getInt(2);
2454   } else {
2455     ok2replace = false;
2456   }
2457 
2458   if ((level > 1) || (!_skip_m1_caps)) {
2459     totCap = distributeCap(NULL, power_net);
2460     writeCapNodes = true;
2461 
2462     // writeResRC(cirFP, power_net, level, width, dir, skipEnds, reverseRs,
2463     // onlyVias, true); reverseRs= false;
2464 
2465     // writeCapNodesRC(cirFP, power_net, level, onlyVias, capNodeTable);
2466     // writeCapNodesRC(cirFP, power_net, level, onlyVias, skipEnds);
2467   }
2468   if (ok2replace)
2469     replaceItermCoords(power_net, dir, xy);
2470 
2471   double totRes = writeResRC(cirFP, power_net, level, width, dir, skipEnds,
2472                              reverseRs, onlyVias, writeCapNodes, xy);
2473 
2474   fprintf(
2475       cirFP,
2476       "*** COMP. BlockOnRail [M%d] resistance : %g capacitance : %g -- %s\n\n",
2477       level, totRes, totCap, power_net->getConstName());
2478   if (level > 1)  // macros
2479     writeMacroItermConns(power_net);
2480 }
writeMacroItermConns(odb::dbNet * net)2481 void extMain::writeMacroItermConns(odb::dbNet* net) {
2482   odb::dbSet<odb::dbCapNode> cSet = net->getCapNodes();
2483   // cSet.reverse();
2484   odb::dbSet<odb::dbCapNode>::iterator rc_itr;
2485 
2486   rc_itr = cSet.begin();
2487   for (; rc_itr != cSet.end(); ++rc_itr) {
2488     odb::dbCapNode* capNode = *rc_itr;
2489     if (!capNode->isITerm())
2490       continue;
2491 
2492     odb::dbITerm* iterm = odb::dbITerm::getITerm(_block, capNode->getNode());
2493     if (iterm == NULL)
2494       continue;
2495 
2496     odb::dbStringProperty* p = odb::dbStringProperty::find(iterm, "_inode");
2497 
2498     if (p == NULL)
2499       continue;
2500 
2501     fprintf(_blkInfo, "%s %s %s [%s] %s\n", iterm->getInst()->getConstName(),
2502             iterm->getInst()->getMaster()->getConstName(), "is_macro",
2503             iterm->getMTerm()->getConstName(), p->getValue().c_str());
2504 
2505     odb::dbStringProperty::destroy(p);
2506   }
2507 }
2508 
powerWireConn(odb::Rect * w,uint dir,odb::dbTechLayer * layer,odb::dbNet * net)2509 void extMain::powerWireConn(odb::Rect* w, uint dir, odb::dbTechLayer* layer,
2510                             odb::dbNet* net) {
2511   int length = w->maxDXDY();
2512   int width = w->minDXDY();
2513 
2514   odb::dbNet* power_net = createRailNet(net, layer, w);
2515   if (net->getSigType() == odb::dbSigType::POWER)
2516     power_net->setMark(true);
2517 
2518   odb::dbWire* wire = odb::dbWire::create(power_net);
2519   odb::dbWireEncoder encoder;
2520   encoder.begin(wire);
2521 
2522   double railResTot = 0.0;
2523 
2524   _junct2viaMap->clear(0);
2525   uint jid = 0;
2526 
2527   uint len = w->maxDXDY();
2528   uint level = layer->getRoutingLevel();
2529 
2530   double Res = getResistance(level, width, len, 0);
2531 
2532   FILE* outFP = _globCir;
2533   if (level == 1)
2534     outFP = _stdCir;
2535   fprintf(outFP,
2536           "\n\n*** EST. RAIL [M%d] : L=%g W=%g R=%g coords: %g %g %g %g\n",
2537           level, micronCoords(len), micronCoords(width), Res,
2538           micronCoords(w->xMin()), micronCoords(w->yMin()),
2539           micronCoords(w->xMax()), micronCoords(w->yMax()));
2540 
2541   jid = viaAndInstConn(dir, width, layer, encoder, wire, net, w, false);
2542 
2543   // add last piece
2544 
2545   encoder.end();
2546 
2547   // wire->printWire();
2548   // print_shapes(wire);
2549 
2550   // int wireLength= power_net->getWire()->length();
2551   set_adjust_colinear(true);
2552   bool skipStartWarning = true;
2553   makeNetRCsegs(power_net, skipStartWarning);
2554   set_adjust_colinear(false);
2555   uint maxShapeId = setNodeCoords_xy(power_net, level);
2556 
2557   bool skipFirst = true;
2558   bool onlyVias = false;
2559   if (level == 1) {
2560     fprintf(_stdCir, "\n*layer:M%d,%s net:%d\n\n", level, net->getConstName(),
2561             net->getId());
2562     onlyVias = true;
2563     // 042711
2564     float totCap = 0;
2565     if (!_skip_m1_caps) {
2566       // totCap= distributeCap(_stdCir, power_net);
2567       totCap = distributeCap(NULL, power_net);
2568       writeCapNodes(_stdCir, power_net, level, onlyVias, skipFirst);
2569     }
2570     double totRes = writeRes(_stdCir, power_net, level, width, dir, skipFirst);
2571 
2572     fprintf(_stdCir,
2573             "*** COMP. BlockOnRail [M%d] resistance : %g capacitance : %g -- "
2574             "%s\n\n",
2575             level, totRes, totCap, power_net->getConstName());
2576   } else {
2577     fprintf(_globCir, "\n*layer:M%d,%s net:%d\n\n", level, net->getConstName(),
2578             net->getId());
2579     // float totCap= distributeCap(_globCir, power_net);
2580     float totCap = distributeCap(NULL, power_net);
2581     writeCapNodes(_globCir, power_net, level, onlyVias, skipFirst);
2582     double totRes = writeRes(_globCir, power_net, level, width, dir, skipFirst);
2583 
2584     fprintf(_globCir,
2585             "*** COMP. BlockOnRail [M%d] resistance : %g capacitance : %g fF "
2586             "-- %s\n\n",
2587             level, totRes, totCap, power_net->getConstName());
2588     // HERE wire->printWire();
2589     // print_shapes(stdout, wire);
2590     for (uint ii = 1; ii <= maxShapeId; ii++) {
2591       odb::dbITerm* iterm = _junct2iterm->geti(ii);
2592       if (iterm == NULL)
2593         continue;
2594       odb::dbStringProperty* p = odb::dbStringProperty::find(iterm, "_inode");
2595       _junct2iterm->set(ii, NULL);
2596       if (p == NULL)
2597         continue;
2598 
2599       fprintf(_blkInfo, "%s %s %s [%s] %s\n", iterm->getInst()->getConstName(),
2600               iterm->getInst()->getMaster()->getConstName(), "is_macro",
2601               iterm->getMTerm()->getConstName(), p->getValue().c_str());
2602 
2603       odb::dbStringProperty::destroy(p);
2604     }
2605     // getProp
2606     // write glob.info
2607   }
2608 
2609   // wire->printWire();
2610   // print_shapes(wire);
2611   // R_0_0_0_0       cM1_100 cM1_66924       0.0875  dtemp=0 tc1=0.00265
2612   // tc2=-2.641e-07
2613 }
2614 /*
2615 class sortBox_x
2616 {
2617 public:
2618     bool operator()( odb::dbBox *i1, odb::dbBox *i2)
2619     {
2620         return i1->xMin() < i2->xMin();
2621     }
2622 };
2623 class sortBox_y
2624 {
2625 public:
2626     bool operator()( odb::dbBox *i1, odb::dbBox *i2)
2627     {
2628         return i1->yMin() < i2->yMin();
2629     }
2630 };
2631 */
2632 
matchLayerDir(odb::dbBox * rail,odb::dbTechLayerDir layerDir,int level,bool debug)2633 bool extMain::matchLayerDir(odb::dbBox* rail, odb::dbTechLayerDir layerDir,
2634                             int level, bool debug) {
2635   int dir = rail->getDir();
2636   if (layerDir == odb::dbTechLayerDir::HORIZONTAL) {
2637     if (dir == 1)
2638       return true;
2639   } else {
2640     if (dir == 0)
2641       return true;
2642   }
2643   if (debug)
2644     logger_->info(RCX, 319, "R{} DIR={} {} {} {} {} -- {} {}", level, dir,
2645                   rail->xMin(), rail->yMin(), rail->xMax(), rail->yMax(),
2646                   rail->getDX(), rail->getDY());
2647   return false;
2648 }
addSboxesOnSearch(odb::dbNet * net)2649 uint extMain::addSboxesOnSearch(odb::dbNet* net) {
2650   Ath__array1D<uint>* table = new Ath__array1D<uint>();
2651 
2652   uint cnt = 0;
2653   odb::dbSet<odb::dbSWire> swires = net->getSWires();
2654   odb::dbSet<odb::dbSWire>::iterator itr;
2655 
2656   for (itr = swires.begin(); itr != swires.end(); ++itr) {
2657     odb::dbSWire* swire = *itr;
2658     odb::dbSet<odb::dbSBox> wires = swire->getWires();
2659     odb::dbSet<odb::dbSBox>::iterator box_itr;
2660 
2661     for (box_itr = wires.begin(); box_itr != wires.end(); ++box_itr) {
2662       odb::dbSBox* s = *box_itr;
2663       if (s->isVia())
2664         continue;
2665 
2666       odb::Rect r;
2667       s->getBox(r);
2668       cnt++;
2669 
2670       uint wtype = 11;
2671       uint level = s->getTechLayer()->getRoutingLevel();
2672 
2673       int trackNum = _search->addBox(r.xMin(), r.yMin(), r.xMax(), r.yMax(),
2674                                      level, s->getId(), 0, wtype);
2675 
2676       if (false) {
2677         for (uint dir = 0; dir < 2; dir++) {
2678           Ath__grid* grid = _search->getGrid(dir, level);
2679           if (grid == NULL)
2680             continue;
2681           table->resetCnt();
2682           uint boxCnt = grid->getBoxes(trackNum, table);
2683 
2684           if (boxCnt > 0) {
2685             odb::Rect* v = getRect_SBox(table, 0, false, 0, wtype);
2686             logger_->info(RCX, 320, "track[{}] {} AddBox {} {} {} {} dir={}",
2687                           level, trackNum, v->xMin(), v->yMin(), v->xMax(),
2688                           v->yMax(), dir);
2689           }
2690         }
2691       }
2692     }
2693   }
2694   return cnt;
2695 }
filterPowerGeoms(odb::dbSBox * s,uint targetDir,uint & maxWidth)2696 bool extMain::filterPowerGeoms(odb::dbSBox* s, uint targetDir, uint& maxWidth) {
2697   bool dbg = false;
2698 
2699   uint w = s->getWidth(targetDir);
2700 
2701   if (dbg)
2702     logger_->info(RCX, 321,
2703                   "targetDir={}  maxWidth={}   D={} W={} L={}-- {} {}   {} {}",
2704                   targetDir, maxWidth, s->getDir(), w, s->getLength(targetDir),
2705                   s->xMin(), s->yMin(), s->xMax(), s->yMax());
2706 
2707   if ((s->getDir() == -1) || (s->getDir() != targetDir))  // -1 == square
2708   {
2709     if (dbg)
2710       logger_->info(
2711           RCX, 322,
2712           "filterPowerGeoms: targetDiri<> {} maxDith={} -- {} {}   {} {}",
2713           s->getDir(), maxWidth, s->xMin(), s->yMin(), s->xMax(), s->yMax());
2714     return true;
2715   }
2716 
2717   if (maxWidth < w)
2718     maxWidth = w;
2719 
2720   if (w < maxWidth) {
2721     if (dbg)
2722       logger_->info(
2723           RCX, 323,
2724           "filterPowerGeoms: smallWidth<> {} maxDith={} -- {} {}   {} {}", w,
2725           maxWidth, s->xMin(), s->yMin(), s->xMax(), s->yMax());
2726     return true;
2727   }
2728   return false;
2729 }
getRect_SBox(Ath__array1D<uint> * table,uint ii,bool filter,uint targetDir,uint & maxWidth)2730 odb::Rect* extMain::getRect_SBox(Ath__array1D<uint>* table, uint ii,
2731                                  bool filter, uint targetDir, uint& maxWidth) {
2732   uint boxId = table->get(ii);
2733 
2734   if (_sbox_id_map[boxId] != NULL)
2735     return NULL;
2736 
2737   odb::dbSBox* s = odb::dbSBox::getSBox(_block, boxId);
2738   if (filter) {
2739     if (filterPowerGeoms(s, targetDir, maxWidth))
2740       return NULL;
2741   }
2742 
2743   odb::Rect* r = new odb::Rect();
2744   s->getBox(*r);
2745 
2746   _sbox_id_map[boxId] = s;
2747 
2748   return r;
2749 }
2750 
overlapPowerWires(std::vector<odb::Rect * > & mergeTableHi,std::vector<odb::Rect * > & mergeTableLo,std::vector<odb::Rect * > & resultTable)2751 uint extMain::overlapPowerWires(std::vector<odb::Rect*>& mergeTableHi,
2752                                 std::vector<odb::Rect*>& mergeTableLo,
2753                                 std::vector<odb::Rect*>& resultTable) {
2754   uint cnt = 0;
2755   bool dbg = false;
2756   for (uint ii = 0; ii < mergeTableHi.size(); ii++) {
2757     odb::Rect* r = mergeTableHi[ii];
2758     if (dbg)
2759       r->print("\n--- ");
2760     for (uint jj = 0; jj < mergeTableLo.size(); jj++) {
2761       odb::Rect* s = mergeTableLo[jj];
2762       if (dbg)
2763         s->print("i   ");
2764       odb::Rect* v = new odb::Rect();
2765       if (r->overlaps(*s)) {
2766         r->intersection(*s, *v);
2767         if (dbg)
2768           v->print("o   ");
2769         cnt++;
2770         resultTable.push_back(v);
2771       }
2772     }
2773   }
2774   return cnt;
2775 }
mergePowerWires(uint dir,uint level,std::vector<odb::Rect * > & mergeTable)2776 uint extMain::mergePowerWires(uint dir, uint level,
2777                               std::vector<odb::Rect*>& mergeTable) {
2778   bool dbg = false;
2779   uint cnt = 0;
2780   Ath__grid* grid = _search->getGrid(dir, level);
2781   // odb::dbBlockSearch *blkSearch= _block->getSearchDb();
2782   // Ath__grid *grid = blkSearch->getGrid(dir, level);
2783   grid->setSearchDomain(0);
2784 
2785   Ath__array1D<uint>* table = new Ath__array1D<uint>();
2786   uint trackCnt = grid->getTrackCnt();
2787 
2788   uint maxWidth = 0;
2789   for (uint ii = 0; ii < trackCnt; ii++) {
2790     table->resetCnt();
2791     uint boxCnt = grid->getBoxes(ii, table);
2792     if (boxCnt == 0)
2793       continue;
2794 
2795     bool filterSmallGeoms = level == 1;
2796     odb::Rect* v = NULL;
2797     uint kk = 0;
2798     odb::Rect* r = NULL;
2799     for (; kk < boxCnt; kk++) {
2800       v = getRect_SBox(table, kk, filterSmallGeoms, dir, maxWidth);
2801       if (v == NULL)
2802         continue;
2803       break;
2804     }
2805 
2806     if (v == NULL)
2807       continue;
2808 
2809     odb::Rect* a = new odb::Rect(*v);
2810     // a->print("First to merge--");
2811     // if (filterSmallGeoms) a->print("First to merge--");
2812 
2813     cnt++;
2814     mergeTable.push_back(a);
2815     for (uint jj = kk + 1; jj < boxCnt; jj++) {
2816       odb::Rect* r = getRect_SBox(table, jj, filterSmallGeoms, dir, maxWidth);
2817       if (r == NULL)
2818         continue;
2819 
2820       // if (filterSmallGeoms) r->print("before merging--");
2821 
2822       if (r->intersects(*a)) {
2823         // r->merge(*a);
2824         a->merge(*r);  // TODO
2825                        // fprintf(stdout, " ...... MERGED!\n");
2826       } else {
2827         // fprintf(stdout, " ...... START MERGE!\n");
2828         if (dbg)
2829           a->print("R--");
2830         a = new odb::Rect(*r);
2831         if (dbg)
2832           a->print("\n---");
2833         mergeTable.push_back(a);
2834         cnt++;
2835       }
2836     }
2837     // if (filterSmallGeoms) a->print("merged after filetering --");
2838   }
2839   return cnt;
2840 }
createMultiVia(uint top,uint bot,odb::Rect * r)2841 odb::dbBox* extMain::createMultiVia(uint top, uint bot, odb::Rect* r) {
2842   odb::dbTech* tech = _block->getDb()->getTech();
2843 
2844   char source_name[256];
2845   sprintf(source_name, "v%d_%d__", r->xMin(), r->yMin());
2846 
2847   odb::dbTechVia* techVia = odb::dbTechVia::create(tech, source_name);
2848 
2849   odb::dbTechLayer* toplayer = tech->findRoutingLayer(top);
2850   odb::dbTechLayer* botlayer = tech->findRoutingLayer(bot);
2851 
2852   // odb::dbBox *v = _netUtil->createTechVia(x, y, x+1, y+1, level, level+1);
2853 
2854   odb::dbBox* topb = odb::dbBox::create(techVia, toplayer, r->xMin(), r->yMin(),
2855                                         r->xMax(), r->yMax());
2856   odb::dbBox* botb = odb::dbBox::create(techVia, botlayer, r->xMin(), r->yMin(),
2857                                         r->xMax(), r->yMax());
2858 
2859   odb::dbVia* via =
2860       odb::dbVia::create(_block, source_name, techVia, odb::dbOrientType::R0);
2861   odb::dbBox* v = via->getBBox();
2862   // odb::dbTechVia *tvia= v->getTechVia();
2863 
2864   return v;
2865 }
mergeViasOnMetal_1(odb::Rect * w,odb::dbNet * pNet,uint level,std::vector<odb::dbBox * > & viaTable)2866 void extMain::mergeViasOnMetal_1(odb::Rect* w, odb::dbNet* pNet, uint level,
2867                                  std::vector<odb::dbBox*>& viaTable) {
2868   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
2869 
2870   for (uint kk = 0; kk < viaTable.size(); kk++)  // all vias on rail
2871   {
2872     odb::dbBox* v = viaTable[kk];
2873     uint top;
2874     uint bot = blkSearch->getViaLevels(v, top);
2875     if (bot > 1)
2876       continue;
2877 
2878     odb::Rect vr;
2879     v->getBox(vr);
2880     if (!w->overlaps(vr))
2881       continue;
2882 
2883     v->setVisited(false);
2884     std::vector<odb::dbBox*> upViaTable;
2885     uint cnt = blkSearch->getPowerWiresAndVias(v->xMin(), v->yMin(), v->xMax(),
2886                                                v->yMax(), level, pNet, false,
2887                                                upViaTable);
2888 
2889     if (mergeStackedViasOpt(_globCir, pNet, upViaTable, v, _viaStackGlobCir) >
2890         0)
2891       _via_id_map[v->getId()] = pNet;
2892     else
2893       _via_id_map[v->getId()] = NULL;
2894 
2895     v->setVisited(false);
2896   }
2897 }
formOverlapVias(std::vector<odb::Rect * > mergeTable[16],odb::dbNet * pNet)2898 void extMain::formOverlapVias(std::vector<odb::Rect*> mergeTable[16],
2899                               odb::dbNet* pNet) {
2900   bool dbg = false;
2901   std::vector<odb::Rect*> overlapTable[16];
2902 
2903   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
2904   int layerCount = _tech->getRoutingLayerCount();
2905 
2906   for (uint level = layerCount; level > 1; level--) {
2907     if (mergeTable[level].size() == 0)
2908       continue;
2909 
2910     if (dbg)
2911       logger_->info(RCX, 324, "OVERLAPS ---- LEVEL= {} ----", level);
2912     uint ocnt = overlapPowerWires(mergeTable[level], mergeTable[level - 1],
2913                                   overlapTable[level]);
2914     _overlapPowerWireCnt += overlapTable[level].size();
2915     for (uint jj = 0; jj < overlapTable[level].size(); jj++) {
2916       odb::Rect* w = overlapTable[level][jj];
2917       if (dbg)
2918         w->print("--- ");
2919 
2920       std::vector<odb::dbBox*> viaTable;
2921       uint viaCnt = blkSearch->getPowerWiresAndVias(w->xMin(), w->yMin(),
2922                                                     w->xMax(), w->yMax(), level,
2923                                                     pNet, false, viaTable);
2924 
2925       std::vector<odb::dbBox*> overlapviaTable;
2926       uint vCnt = 0;
2927       for (uint ii = 0; ii < viaCnt; ii++) {
2928         odb::dbBox* v = viaTable[ii];
2929         uint top;
2930         uint bot = blkSearch->getViaLevels(v, top);
2931         if (!((level == bot) || (level == top)))
2932           continue;
2933 
2934         odb::Rect vr;
2935         v->getBox(vr);
2936         if (!w->overlaps(vr))
2937           continue;
2938 
2939         overlapviaTable.push_back(v);  // ADD 111312
2940 
2941         vCnt++;
2942       }
2943       if (vCnt > 1) {
2944         for (uint ii = 0; ii < vCnt; ii++) {
2945           odb::dbBox* w1 = overlapviaTable[ii];
2946           w1->setVisited(true);
2947         }
2948         odb::dbBox* W = overlapviaTable[0];  // ADD 111312
2949 
2950         // TODO SET RESISTANCE writeNegativeCoords(buf, pNet->getId(),
2951         // w->xMin(), w->yMin(), level, "MULTI");
2952         char buf[128];
2953         float res = getPowerViaRes(W, 0.1);
2954         writeNegativeCoords(buf, pNet->getId(), w->xMin(), w->yMin(), -1, "");
2955         odb::dbStringProperty::create(W, "_inode", buf);
2956 
2957         sprintf(buf, "%g", res / vCnt);
2958         odb::dbStringProperty::create(W, "_Res", buf);
2959         /*
2960                                         fprintf(stdout, "W   %12d %12d %12d %12d
2961            -- %d %d : id=%d\n", W->xMin(), W->yMin(), W->xMax(), W->yMax(),
2962            W->getDX(), W->getDY(), W->getId());
2963         */
2964 
2965         /*
2966                                         odb::dbVia *mv0= W->getBlockVia();
2967                                         odb::dbTechLayer *routelayer=
2968            tech->findRoutingLayer(level); odb::dbBox::create(mv0, routelayer,
2969            w->xMin(), w->yMin(), w->xMax(), w->yMax() ); W= mv0->getBBox();
2970 
2971                                         odb::dbTechVia *mv1= W->getTechVia();
2972                                         fprintf(stdout, "WMod   %12d %12d %12d
2973            %12d -- %d %d : id=%d\n", W->xMin(), W->yMin(), W->xMax(), W->yMax(),
2974            W->getDX(), W->getDY(), W->getId());
2975 
2976         */
2977         /* 12032012
2978                                         _multiViaTable[level].push_back(w);
2979                                         _viaOverlapPowerCnt += vCnt;
2980                                         odb::dbBox *v= createMultiVia(level,
2981            level-1, w);
2982         */
2983         //_multiViaBoxTable[level].push_back(v);
2984 
2985         _multiViaBoxTable[level].push_back(W);
2986       }
2987     }
2988     if (dbg)
2989       logger_->info(RCX, 325, "NEW VIAS ---- LEVEL= {} ----", level);
2990     for (uint kk = 0; kk < _multiViaBoxTable[level].size(); kk++) {
2991       // odb::Rect *w= _multiViaTable[level][kk];
2992       odb::dbBox* v = _multiViaBoxTable[level][kk];
2993       if (dbg) {
2994         // w->print("V     ");
2995         fprintf(stdout, "B%d    %12d %12d %12d %12d\n", v->isVisited(),
2996                 v->xMin(), v->yMin(), v->xMax(), v->yMax());
2997       }
2998     }
2999     _multiViaCnt += _multiViaTable[level].size();
3000   }
3001 }
railConnOpt(odb::dbNet * pNet)3002 void extMain::railConnOpt(odb::dbNet* pNet) {
3003   bool dbg = false;
3004   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
3005   odb::dbTech* tech = _block->getDb()->getTech();
3006   odb::dbBox* bb = _block->getBBox();
3007   odb::Rect BB;
3008   bb->getBox(BB);
3009 
3010   initPowerSearch();
3011 
3012   _powerWireCnt += addSboxesOnSearch(pNet);
3013   int layerCount = _tech->getRoutingLayerCount();
3014   std::vector<odb::Rect*> mergeTable[16];
3015   std::vector<odb::Rect*> mergeTableNOT[16];
3016   for (uint level = layerCount; level > 0; level--) {
3017     odb::dbTechLayer* routelayer = tech->findRoutingLayer(level);
3018     odb::dbTechLayerDir layerDir = routelayer->getDirection();
3019     uint dir = 0;
3020     if (layerDir == odb::dbTechLayerDir::HORIZONTAL)
3021       dir = 1;
3022 
3023     if (dbg)
3024       logger_->info(RCX, 326, "--- MERGE ---- DIR={} - LEVEL= {} ----", dir,
3025                     level);
3026     uint powerWireCnt = mergePowerWires(dir, level, mergeTable[level]);
3027     _mergedPowerWireCnt += powerWireCnt;
3028     powerWireCnt = mergePowerWires(!dir, level, mergeTableNOT[level]);
3029     _mergedPowerWireCnt += powerWireCnt;
3030     for (uint jj = 0; jj < mergeTable[level].size(); jj++) {
3031       odb::Rect* r = mergeTable[level][jj];
3032       if (dbg)
3033         r->print("--- ");
3034       // if (level==1) r->print("AFTER MERGE --- ");
3035     }
3036     for (uint jj = 0; jj < mergeTableNOT[level].size(); jj++) {
3037       odb::Rect* r = mergeTableNOT[level][jj];
3038       if (dbg)
3039         r->print("--- ");
3040       // if (level==1) r->print("AFTER MERGE --- ");
3041     }
3042   }
3043   std::vector<odb::Rect*> overlapTable[16];
3044 
3045   for (uint level = layerCount; level > 1; level--) {
3046     _multiViaTable[level].clear();
3047     _multiViaBoxTable[level].clear();
3048   }
3049   formOverlapVias(mergeTable, pNet);
3050   formOverlapVias(mergeTableNOT, pNet);
3051 
3052   for (uint level = layerCount; level > 1; level--) {
3053     for (uint kk = 0; kk < _multiViaTable[level].size(); kk++) {
3054       odb::dbBox* v = _multiViaBoxTable[level][kk];
3055       v->setVisited(false);
3056       // fprintf(stdout, "B%d L%d %d  %12d %12d %12d %12d\n",
3057       // v->isVisited(), level, v->getId(), v->xMin(), v->yMin(), v->xMax(),
3058       // v->yMax());
3059     }
3060   }
3061   if (_overlapPowerWireCnt > 0)
3062     logger_->info(
3063         RCX, 327,
3064         "After Net: {} {} -- {} power Wires, into {} merged wires, {} wire "
3065         "overlaps, {} multi-via objects ==> created {} compound Via Objects",
3066         pNet->getId(), pNet->getConstName(), _powerWireCnt, _mergedPowerWireCnt,
3067         _overlapPowerWireCnt, _viaOverlapPowerCnt, _multiViaCnt);
3068 
3069   for (uint level = layerCount; level > 0; level--) {
3070     odb::dbTechLayer* routelayer = tech->findRoutingLayer(level);
3071     odb::dbTechLayerDir layerDir = routelayer->getDirection();
3072     uint dir = 0;
3073     if (layerDir == odb::dbTechLayerDir::HORIZONTAL)
3074       dir = 1;
3075 
3076     if (_wireInfra) {
3077       if (level == 1) {
3078         for (uint kk = 0; kk < mergeTable[1].size(); kk++) {
3079           odb::Rect* w = mergeTable[1][kk];
3080           std::vector<odb::dbBox*> viaTable;
3081           uint viaCnt = blkSearch->getPowerWiresAndVias(w->xMin(), w->yMin(),
3082                                                         w->xMax(), w->yMax(), 1,
3083                                                         pNet, false, viaTable);
3084 
3085           mergeViasOnMetal_1(w, pNet, 1, viaTable);
3086         }
3087       }
3088     }
3089     for (uint kk = 0; kk < mergeTable[level].size(); kk++) {
3090       odb::Rect* r = mergeTable[level][kk];
3091       // HERE
3092       if (level == 0) {
3093         logger_->info(RCX, 384, "powerWireConn: M{}  {} {} {} {} -- {} {}",
3094                       level, r->xMin(), r->yMin(), r->xMax(), r->yMax(),
3095                       r->dx(), r->dy());
3096       }
3097       if (_wireInfra)
3098         powerWireConn(r, dir, routelayer, pNet);
3099       else
3100         powerWireConnRC(r, dir, routelayer, pNet);
3101     }
3102     for (uint kk = 0; kk < mergeTableNOT[level].size(); kk++) {
3103       odb::Rect* r = mergeTableNOT[level][kk];
3104       // HERE
3105       if (level == 0) {
3106         logger_->info(RCX, 328, "powerWireConn: M{}  {} {} {} {} -- {} {}",
3107                       level, r->xMin(), r->yMin(), r->xMax(), r->yMax(),
3108                       r->dx(), r->dy());
3109       }
3110       if (_wireInfra)
3111         powerWireConn(r, !dir, routelayer, pNet);
3112       else
3113         powerWireConnRC(r, !dir, routelayer, pNet);
3114     }
3115   }
3116   if (!_wireInfra) {
3117     for (uint kk = 0; kk < _viaM1Table->size(); kk++)
3118         // for (uint kk= 0; kk<_viaM1_VDDtable.size(); kk++)
3119     {
3120       // odb::dbBox *v= _viaM1_VDDtable[kk];
3121       odb::dbBox* v = (*_viaM1Table)[kk];
3122 
3123       v->setVisited(false);
3124       std::vector<odb::dbBox*> upViaTable;
3125       uint cnt = blkSearch->getPowerWiresAndVias(v->xMin(), v->yMin(),
3126                                                  v->xMax(), v->yMax(), 1, pNet,
3127                                                  false, upViaTable);
3128 
3129       if (mergeStackedViasOpt(_globCir, pNet, upViaTable, v, _viaStackGlobCir) >
3130           0)
3131         _via_id_map[v->getId()] = pNet;
3132 
3133       v->setVisited(false);
3134     }
3135   }
3136 }
railConn(odb::dbNet * pNet)3137 void extMain::railConn(odb::dbNet* pNet) {
3138   bool debug = false;
3139   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
3140   odb::dbTech* tech = _block->getDb()->getTech();
3141   odb::dbBox* bb = _block->getBBox();
3142   odb::Rect BB;
3143   bb->getBox(BB);
3144 
3145   logger_->info(RCX, 329, "BBOX: {} {} {} {} {} {}", bb->xMin(), bb->yMin(),
3146                 bb->xMax(), bb->yMax(), BB.dx(), BB.dy());
3147 
3148   std::vector<odb::dbBox*> mergeTable[16];
3149 
3150   std::vector<odb::dbBox*> boxTable;
3151   int layerCount = _tech->getRoutingLayerCount();
3152   for (uint level = layerCount; level > 0; level--) {
3153     boxTable.clear();
3154     uint n = blkSearch->getPowerWires(bb->xMin(), bb->yMin(), bb->xMax(),
3155                                       bb->yMax(), level, pNet, boxTable);
3156     if (n == 0)
3157       continue;
3158 
3159     odb::dbTechLayer* routelayer = tech->findRoutingLayer(level);
3160     odb::dbTechLayerDir layerDir = routelayer->getDirection();
3161 
3162     uint maxLen = 0;
3163     logger_->info(RCX, 330, "{} M{} power wires of net {} found:", n, level,
3164                   pNet->getConstName());
3165     int dirCnt[2];
3166     dirCnt[0] = 0;
3167     dirCnt[1] = 0;
3168 
3169     uint dir = 0;
3170     if (layerDir == odb::dbTechLayerDir::HORIZONTAL) {
3171       sortBox_y sort_by_y;
3172       std::sort(boxTable.begin(), boxTable.end(), sort_by_y);
3173       dir = 1;
3174     } else {
3175       sortBox_x sort_by_x;
3176       std::sort(boxTable.begin(), boxTable.end(), sort_by_x);
3177     }
3178 
3179     // uint m= mergeTable[level].size();
3180     uint m = boxTable.size();
3181     if (debug)
3182       logger_->info(RCX, 331, "{} power RAILS found", m);
3183     for (uint jj = 0; jj < m; jj++) {
3184       // odb::dbBox *rail= mergeTable[level][jj];
3185       odb::dbBox* rail = boxTable[jj];
3186       if (debug)
3187         logger_->info(RCX, 385, "R{} DIR={} {} {} {} {} -- {} {}", level, dir,
3188                       rail->xMin(), rail->yMin(), rail->xMax(), rail->yMax(),
3189                       rail->getDX(), rail->getDY());
3190       std::vector<odb::dbBox*> railMergeTable;
3191       if (!matchLayerDir(rail, layerDir, level, false))  // squares not
3192         continue;
3193       railMergeTable.push_back(rail);
3194       if (layerDir == odb::dbTechLayerDir::HORIZONTAL) {
3195         int midXY = (rail->yMin() + rail->yMax()) / 2;
3196         jj++;
3197         for (; jj < m; jj++) {
3198           odb::dbBox* w = boxTable[jj];
3199           if (!matchLayerDir(w, layerDir, level, false))  // squares not
3200             continue;
3201           int mid = (w->yMin() + w->yMax()) / 2;
3202           if ((w->yMax() == rail->yMax()) || (w->yMin() == rail->yMin()) ||
3203               ((mid <= midXY + 0.5 * w->getDY()) && (mid >= midXY)) ||
3204               ((mid >= midXY - 0.5 * w->getDY()) && (mid <= midXY)))
3205             railMergeTable.push_back(w);
3206           else {
3207             jj--;
3208             break;
3209           }
3210         }
3211         sortBox_x sort_by_x;
3212         std::sort(railMergeTable.begin(), railMergeTable.end(), sort_by_x);
3213       } else {
3214         int midXY = (rail->xMin() + rail->xMax()) / 2;
3215         jj++;
3216         for (; jj < m; jj++) {
3217           odb::dbBox* w = boxTable[jj];
3218           if (!matchLayerDir(w, layerDir, level, false))  // squares not
3219             continue;
3220           int mid = (w->xMin() + w->xMax()) / 2;
3221           if ((w->xMax() == rail->xMax()) || (w->xMin() == rail->xMin()) ||
3222               ((mid <= midXY + 0.5 * w->getDX()) && (mid >= midXY)) ||
3223               ((mid >= midXY - 0.5 * w->getDX()) && (mid <= midXY)))
3224             railMergeTable.push_back(w);
3225           else {
3226             jj--;
3227             break;
3228           }
3229         }
3230         sortBox_y sort_by_y;
3231         std::sort(railMergeTable.begin(), railMergeTable.end(), sort_by_y);
3232       }
3233       for (uint kk = 0; kk < railMergeTable.size(); kk++) {
3234         odb::dbBox* w = railMergeTable[kk];
3235         if (debug) {
3236           logger_->info(RCX, 332, "\t{} {} {} {} -- {} {}", w->xMin(),
3237                         w->yMin(), w->xMax(), w->yMax(), w->getDX(),
3238                         w->getDY());
3239         }
3240         odb::Rect r;
3241         w->getBox(r);
3242         kk++;
3243         for (; kk < railMergeTable.size(); kk++) {
3244           odb::dbBox* v = railMergeTable[kk];
3245           // if (layerDir==odb::dbTechLayerDir::HORIZONTAL)
3246           //{
3247           odb::Rect a;
3248           v->getBox(a);
3249           if (r.intersects(a)) {
3250             r.merge(a);  // TODO
3251             if (debug) {
3252               logger_->info(RCX, 333, "\t\tM {} {} {} {} ", v->xMin(),
3253                             v->yMin(), v->xMax(), v->yMax());
3254             }
3255           } else {
3256             kk--;
3257             break;
3258           }
3259           //}
3260         }
3261         if (debug)
3262           logger_->info(RCX, 334, "Merged: {} {} {} {} -- {} {}", r.xMin(),
3263                         r.yMin(), r.xMax(), r.yMax(), r.dx(), r.dy());
3264         if (level == 1) {
3265           std::vector<odb::dbBox*> viaTable;
3266           uint viaCnt = blkSearch->getPowerWiresAndVias(
3267               r.xMin(), r.yMin(), r.xMax(), r.yMax(), level, pNet, false,
3268               viaTable);
3269 
3270           for (uint kk = 0; kk < viaCnt; kk++)  // all vias on rail
3271           {
3272             odb::dbBox* v = viaTable[kk];
3273             uint top;
3274             uint bot = blkSearch->getViaLevels(v, top);
3275             if (bot > 1)
3276               continue;
3277 
3278             v->setVisited(false);
3279             std::vector<odb::dbBox*> upViaTable;
3280             uint cnt = blkSearch->getPowerWiresAndVias(
3281                 v->xMin(), v->yMin(), v->xMax(), v->yMax(), level, pNet, false,
3282                 upViaTable);
3283 
3284             if (mergeStackedVias(_globCir, pNet, upViaTable, v,
3285                                  _viaStackGlobCir) > 0)
3286               _via_id_map[v->getId()] = pNet;
3287 
3288             v->setVisited(false);
3289           }
3290         }
3291         if (layerDir == odb::dbTechLayerDir::HORIZONTAL) {
3292           if (r.dx() <= r.dy()) {
3293             if (debug)
3294               logger_->info(RCX, 382, "Skip: M{}  {} {} {} {} -- {} {}", level,
3295                             r.xMin(), r.yMin(), r.xMax(), r.yMax(), r.dx(),
3296                             r.dy());
3297             continue;
3298           }
3299         } else {
3300           if (r.dy() <= r.dx()) {
3301             if (debug)
3302               logger_->info(RCX, 335, "Skip: M{}  {} {} {} {} -- {} {}", level,
3303                             r.xMin(), r.yMin(), r.xMax(), r.yMax(), r.dx(),
3304                             r.dy());
3305             continue;
3306           }
3307         }
3308         // if (debug)
3309         logger_->info(RCX, 383, "powerWireConn: M{}  {} {} {} {} -- {} {}",
3310                       level, r.xMin(), r.yMin(), r.xMax(), r.yMax(), r.dx(),
3311                       r.dy());
3312         powerWireConn(&r, dir, routelayer, pNet);
3313       }
3314     }
3315   }
3316 }
print_shapes(FILE * fp,odb::dbWire * wire)3317 uint extMain::print_shapes(FILE* fp, odb::dbWire* wire) {
3318   odb::dbWireShapeItr shapes;
3319   odb::dbShape s;
3320 
3321   uint tLen = 0;
3322   for (shapes.begin(wire); shapes.next(s);) {
3323     uint width = s.getDY();
3324     uint len = s.getDX();
3325     if (width > s.getDX()) {
3326       width = s.getDX();
3327       len = s.getDY();
3328     }
3329     tLen += len;
3330     fprintf(fp, "L=%d sid=%d  m=%d  %d %d  %d %d\n", len, shapes.getShapeId(),
3331             s.getTechLayer()->getRoutingLevel(), s.xMin(), s.yMin(), s.xMax(),
3332             s.yMax());
3333   }
3334   return tLen;
3335 }
setupNanoFiles(odb::dbNet * net)3336 void extMain::setupNanoFiles(odb::dbNet* net) {
3337   odb::dbSigType type = net->getSigType();
3338 
3339   if (type == odb::dbSigType::POWER) {
3340     _coordsFP = _coordsVDD;
3341     _blkInfo = _blkInfoVDD;
3342     _viaInfo = _viaInfoVDD;
3343     _globGeom = _globGeomVDD;
3344     _globCir = _globCirVDD;
3345     _viaStackGlobCir = _viaStackGlobVDD;
3346     _stdCir = _stdCirVDD;
3347     _globCirHead = _globCirHeadVDD;
3348     _stdCirHead = _stdCirHeadVDD;
3349     _viaM1Table = &_viaM1_VDDtable;
3350     _viaUpTable = &_viaUp_VDDtable;
3351   } else if (type == odb::dbSigType::GROUND) {
3352     _coordsFP = _coordsGND;
3353     _blkInfo = _blkInfoGND;
3354     _viaInfo = _viaInfoGND;
3355     _globCir = _globCirGND;
3356     _viaStackGlobCir = _viaStackGlobGND;
3357     _globGeom = _globGeomGND;
3358     _stdCir = _stdCirGND;
3359     _globCirHead = _globCirHeadGND;
3360     _stdCirHead = _stdCirHeadGND;
3361     _viaM1Table = &_viaM1_GNDtable;
3362     _viaUpTable = &_viaUp_GNDtable;
3363   }
3364 }
setPrefix(char * prefix)3365 void extMain::setPrefix(char* prefix) {
3366   sprintf(prefix, "");
3367   if (strlen(_node_blk_prefix) > 0)
3368     sprintf(prefix, "%s/%s", _node_blk_prefix, _node_inst_prefix);
3369 }
openNanoFile(const char * name,const char * name2,const char * suffix,const char * perms)3370 FILE* extMain::openNanoFile(const char* name, const char* name2,
3371                             const char* suffix, const char* perms) {
3372   char prefix[256];
3373   sprintf(prefix, "");
3374   if (strlen(_node_blk_prefix) > 0) {
3375     char syscmd[256];
3376     sprintf(syscmd, "mkdir -p %s", _node_blk_prefix);
3377     system(syscmd);
3378     setPrefix(prefix);
3379     // sprintf(prefix, "%s/", _node_blk_prefix);
3380   }
3381   char buf[1024];
3382   sprintf(buf, "%s%s_%s.%s", prefix, name, name2, suffix);
3383 
3384   FILE* fp = fopen(buf, perms);
3385   if (fp == NULL) {
3386     fprintf(stderr, "Cannot open file %s with %s\n", buf, perms);
3387     exit(1);
3388   }
3389   return fp;
3390 }
netDirPrefix(char * prefix,char * netName)3391 void extMain::netDirPrefix(char* prefix, char* netName) {
3392   sprintf(prefix, "%s/%s/%s", _node_blk_dir, netName, _node_inst_prefix);
3393   char syscmd[2056];
3394   sprintf(syscmd, "mkdir -p %s/%s", _node_blk_dir, netName);
3395   system(syscmd);
3396 }
openNanoFileNet(char * netname,const char * name,const char * name2,const char * suffix,const char * perms)3397 FILE* extMain::openNanoFileNet(char* netname, const char* name,
3398                                const char* name2, const char* suffix,
3399                                const char* perms) {
3400   char hier_prefix[2048];
3401   netDirPrefix(hier_prefix, netname);
3402 
3403   char buf[2048];
3404   sprintf(buf, "%s%s_%s.%s", hier_prefix, name, name2, suffix);
3405 
3406   FILE* fp = fopen(buf, perms);
3407   if (fp == NULL) {
3408     fprintf(stderr, "Cannot open file %s with %s\n", buf, perms);
3409     exit(1);
3410   }
3411   return fp;
3412 }
writeSubckt(FILE * fp,const char * keyword,const char * vdd,const char * std,const char * cont)3413 void extMain::writeSubckt(FILE* fp, const char* keyword, const char* vdd,
3414                           const char* std, const char* cont) {
3415   // fprintf(fp, "\n*** Nefelus RC - 2/16/10\n");
3416   fprintf(fp, "\n%s %s_%s_%s %s ", keyword, vdd, std, _block->getConstName(),
3417           cont);
3418 }
writeGeomHeader(FILE * fp,const char * vdd)3419 void extMain::writeGeomHeader(FILE* fp, const char* vdd) {
3420   fprintf(fp, "VeloceRF\n");
3421   fprintf(fp, "startgeom\n");
3422   fprintf(fp, "top_level_pins %c\n", '%');
3423   fprintf(fp, "obj %s  %c\n", vdd, '%');
3424   fprintf(fp, "prop netName %s  endprop\n", vdd);
3425 }
openNanoFilesDomain(odb::dbNet * pNet)3426 void extMain::openNanoFilesDomain(odb::dbNet* pNet) {
3427   const char* vdd = "GND";
3428   const char* ptype = "ground";
3429   int ii = 0;
3430   if (pNet->getSigType() == odb::dbSigType::POWER) {
3431     vdd = "VDD";
3432     ii = 1;
3433     ptype = "power";
3434   }
3435   char* netName = (char*)pNet->getConstName();
3436   char sysCmd[4000];
3437   if (strcmp(_node_blk_dir, "./") == 0)
3438     sprintf(sysCmd, "echo %s %s %s >> Extract.info", netName, netName, ptype);
3439   else
3440     sprintf(sysCmd, "echo %s %s/%s %s >> Extract.info", netName, _node_blk_dir,
3441             netName, ptype);
3442   system(sysCmd);
3443 
3444   _subCktNodeFP[0][ii] = openNanoFileNet(netName, "std", vdd, "subckt", "w");
3445   _subCktNodeFP[1][ii] = openNanoFileNet(netName, "glob", vdd, "subckt", "w");
3446 
3447   writeSubckt(_subCktNodeFP[0][ii], ".subckt", vdd, "std", " \\\n");
3448   writeSubckt(_subCktNodeFP[1][ii], ".subckt", vdd, "glob", " \\\n");
3449 
3450   _subCktNodeCnt[0][0] = 0;
3451   _subCktNodeCnt[0][1] = 0;
3452   _subCktNodeCnt[1][0] = 0;
3453   _subCktNodeCnt[1][1] = 0;
3454 
3455   if (pNet->getSigType() == odb::dbSigType::POWER) {
3456     _blkInfoVDD = openNanoFileNet(netName, "Block", "VDD", "info", "w");
3457     fprintf(_blkInfoVDD, "%c\n", _block->getHierarchyDelimeter());
3458 
3459     _viaInfoVDD = openNanoFileNet(netName, "Via", "VDD", "info", "w");
3460     _stdCirVDD = openNanoFileNet(netName, "std", "VDD", "cir", "w");
3461     _globGeomVDD = openNanoFileNet(netName, "glob", "VDD", "geom", "w");
3462     writeGeomHeader(_globGeomVDD, "VDD");
3463 
3464     _globCirVDD = openNanoFileNet(netName, "glob", "VDD", "cir", "w");
3465 
3466     _coordsVDD = openNanoFileNet(netName, "ViaBlock", "VDD", "coords", "w");
3467     fprintf(_coordsVDD, "DbUnitsPerMicron %d\n", _block->getDbUnitsPerMicron());
3468 
3469     _viaStackGlobVDD = openNanoFileNet(netName, "glob_vias", "VDD", "cir", "w");
3470 
3471     _blkInfoGND = NULL;
3472     _viaInfoGND = NULL;
3473     _stdCirGND = NULL;
3474     _globGeomGND = NULL;
3475     _globCirGND = NULL;
3476     _coordsGND = NULL;
3477     _viaStackGlobGND = NULL;
3478   } else {
3479     _blkInfoGND = openNanoFileNet(netName, "Block", "GND", "info", "w");
3480     fprintf(_blkInfoGND, "%c\n", _block->getHierarchyDelimeter());
3481     _viaInfoGND = openNanoFileNet(netName, "Via", "GND", "info", "w");
3482     _stdCirGND = openNanoFileNet(netName, "std", "GND", "cir", "w");
3483 
3484     _globGeomGND = openNanoFileNet(netName, "glob", "GND", "geom", "w");
3485     writeGeomHeader(_globGeomGND, "GND");
3486 
3487     _globCirGND = openNanoFileNet(netName, "glob", "GND", "cir", "w");
3488     _coordsGND = openNanoFileNet(netName, "ViaBlock", "GND", "coords", "w");
3489     fprintf(_coordsGND, "DbUnitsPerMicron %d\n", _block->getDbUnitsPerMicron());
3490 
3491     _viaStackGlobGND = openNanoFileNet(netName, "glob_vias", "GND", "cir", "w");
3492 
3493     _blkInfoVDD = NULL;
3494     _viaInfoVDD = NULL;
3495     _stdCirVDD = NULL;
3496     _globGeomVDD = NULL;
3497     _globCirVDD = NULL;
3498     _coordsVDD = NULL;
3499     _viaStackGlobVDD = NULL;
3500   }
3501 }
openNanoFiles()3502 void extMain::openNanoFiles() {
3503   _subCktNodeFP[0][0] = openNanoFile("std", "GND", "subckt", "w");
3504   _subCktNodeFP[1][0] = openNanoFile("glob", "GND", "subckt", "w");
3505   _subCktNodeFP[0][1] = openNanoFile("std", "VDD", "subckt", "w");
3506   _subCktNodeFP[1][1] = openNanoFile("glob", "VDD", "subckt", "w");
3507 
3508   writeSubckt(_subCktNodeFP[0][1], ".subckt", "VDD", "std", " \\\n");
3509   writeSubckt(_subCktNodeFP[1][1], ".subckt", "VDD", "glob", " \\\n");
3510   writeSubckt(_subCktNodeFP[0][0], ".subckt", "GND", "std", " \\\n");
3511   writeSubckt(_subCktNodeFP[1][0], ".subckt", "GND", "glob", " \\\n");
3512 
3513   _subCktNodeCnt[0][0] = 0;
3514   _subCktNodeCnt[0][1] = 0;
3515   _subCktNodeCnt[1][0] = 0;
3516   _subCktNodeCnt[1][1] = 0;
3517 
3518   _blkInfoVDD = openNanoFile("Block", "VDD", "info", "w");
3519   fprintf(_blkInfoVDD, "%c\n", _block->getHierarchyDelimeter());
3520 
3521   _viaInfoVDD = openNanoFile("Via", "VDD", "info", "w");
3522 
3523   _blkInfoGND = openNanoFile("Block", "GND", "info", "w");
3524   // fprintf(_blkInfoGND, ".\n");
3525   fprintf(_blkInfoGND, "%c\n", _block->getHierarchyDelimeter());
3526 
3527   _viaInfoGND = openNanoFile("Via", "GND", "info", "w");
3528 
3529   _stdCirVDD = openNanoFile("std", "VDD", "cir", "w");
3530   // writeSubckt(_stdCirVDD, ".subckt", "VDD", "std", "");
3531 
3532   _globGeomVDD = openNanoFile("glob", "VDD", "geom", "w");
3533   writeGeomHeader(_globGeomVDD, "VDD");
3534 
3535   _globCirVDD = openNanoFile("glob", "VDD", "cir", "w");
3536   // writeSubckt(_globCirVDD, ".subckt", "VDD", "glob", "\\");
3537 
3538   _stdCirGND = openNanoFile("std", "GND", "cir", "w");
3539   // writeSubckt(_stdCirGND, ".subckt", "GND", "std", "");
3540 
3541   _globGeomGND = openNanoFile("glob", "GND", "geom", "w");
3542   writeGeomHeader(_globGeomGND, "GND");
3543 
3544   _globCirGND = openNanoFile("glob", "GND", "cir", "w");
3545   // writeSubckt(_globCirGND, ".subckt", "GND", "glob", "\\");
3546 
3547   _coordsVDD = openNanoFile("ViaBlock", "VDD", "coords", "w");
3548   _coordsGND = openNanoFile("ViaBlock", "GND", "coords", "w");
3549 
3550   fprintf(_coordsGND, "DbUnitsPerMicron %d\n", _block->getDbUnitsPerMicron());
3551   fprintf(_coordsVDD, "DbUnitsPerMicron %d\n", _block->getDbUnitsPerMicron());
3552   _viaStackGlobGND = openNanoFile("glob_vias", "GND", "cir", "w");
3553   _viaStackGlobVDD = openNanoFile("glob_vias", "VDD", "cir", "w");
3554 }
printItermNodeSubCkt(FILE * fp,std::vector<uint> & iTable)3555 void extMain::printItermNodeSubCkt(FILE* fp, std::vector<uint>& iTable) {
3556   uint n = iTable.size();
3557   for (uint ii = 0; ii < n; ii++) {
3558     uint id = iTable[ii];
3559 
3560     if ((ii + 1) % 20 == 0)
3561       fprintf(fp, "\\ \n");
3562     fprintf(fp, "I%d ", id);
3563   }
3564   fprintf(fp, " \\ \n");
3565 }
printViaNodeSubCkt(FILE * fp,std::vector<odb::dbBox * > & viaTable)3566 void extMain::printViaNodeSubCkt(FILE* fp, std::vector<odb::dbBox*>& viaTable) {
3567   uint viaCnt = viaTable.size();
3568   for (uint ii = 0; ii < viaCnt; ii++) {
3569     odb::dbBox* v = viaTable[ii];
3570     v->setVisited(false);
3571   }
3572   for (uint ii = 0; ii < viaCnt; ii++) {
3573     odb::dbBox* v = viaTable[ii];
3574 
3575     if (v->isVisited())
3576       continue;
3577     v->setVisited(true);
3578 
3579     writeViaName(fp, v, 0, " ");
3580     if ((ii + 1) % 20 == 0)
3581       fprintf(fp, "\\ \n");
3582   }
3583 }
3584 
closeNanoFilesDomainVDD(char * netName)3585 void extMain::closeNanoFilesDomainVDD(char* netName) {
3586   fclose(_subCktNodeFP[0][1]);
3587   fclose(_subCktNodeFP[1][1]);
3588 
3589   FILE* vddFP = openNanoFileNet(netName, "std", "VDD", "SUBCKT", "w");
3590   printItermNodeSubCkt(vddFP, _vddItermIdTable);
3591   printViaNodeSubCkt(vddFP, _viaM1_VDDtable);
3592   fclose(vddFP);
3593 
3594   vddFP = openNanoFileNet(netName, "glob", "VDD", "SUBCKT", "w");
3595   printViaNodeSubCkt(vddFP, _viaUp_VDDtable);
3596   fclose(vddFP);
3597 
3598   fclose(_blkInfoVDD);
3599   fclose(_viaInfoVDD);
3600 
3601   writeSubckt(_stdCirVDD, ".ends", "VDD", "std", "\n");
3602   fclose(_stdCirVDD);
3603 
3604   writeSubckt(_globCirVDD, ".ends", "VDD", "glob", "\n");
3605   fclose(_globCirVDD);
3606 
3607   fclose(_coordsVDD);
3608 
3609   addSubcktStatementDomain("glob_VDD.cir", "glob_VDD.subckt", netName);
3610   addSubcktStatementDomain("std_VDD.cir", "std_VDD.subckt", netName);
3611   fclose(_viaStackGlobVDD);
3612 }
closeNanoFilesDomainGND(char * netName)3613 void extMain::closeNanoFilesDomainGND(char* netName) {
3614   fclose(_subCktNodeFP[0][0]);
3615   fclose(_subCktNodeFP[1][0]);
3616 
3617   FILE* gndFP = openNanoFileNet(netName, "std", "GND", "SUBCKT", "w");
3618   printItermNodeSubCkt(gndFP, _gndItermIdTable);
3619   printViaNodeSubCkt(gndFP, _viaM1_GNDtable);
3620   fclose(gndFP);
3621 
3622   gndFP = openNanoFileNet(netName, "glob", "GND", "SUBCKT", "w");
3623   printViaNodeSubCkt(gndFP, _viaUp_GNDtable);
3624   fclose(gndFP);
3625 
3626   fclose(_blkInfoGND);
3627   fclose(_viaInfoGND);
3628 
3629   writeSubckt(_stdCirGND, ".ends", "GND", "std", "\n");
3630   fclose(_stdCirGND);
3631 
3632   writeSubckt(_globCirGND, ".ends", "GND", "glob", "\n");
3633   fclose(_globCirGND);
3634 
3635   fclose(_coordsGND);
3636 
3637   addSubcktStatementDomain("glob_GND.cir", "glob_GND.subckt", netName);
3638   addSubcktStatementDomain("std_GND.cir", "std_GND.subckt", netName);
3639   fclose(_viaStackGlobGND);
3640 }
closeNanoFiles()3641 void extMain::closeNanoFiles() {
3642   fclose(_subCktNodeFP[0][0]);
3643   fclose(_subCktNodeFP[1][0]);
3644   fclose(_subCktNodeFP[0][1]);
3645   fclose(_subCktNodeFP[1][1]);
3646 
3647   FILE* vddFP = openNanoFile("std", "VDD", "SUBCKT", "w");
3648   printItermNodeSubCkt(vddFP, _vddItermIdTable);
3649   printViaNodeSubCkt(vddFP, _viaM1_VDDtable);
3650   fclose(vddFP);
3651 
3652   vddFP = openNanoFile("glob", "VDD", "SUBCKT", "w");
3653   printViaNodeSubCkt(vddFP, _viaUp_VDDtable);
3654   fclose(vddFP);
3655 
3656   FILE* gndFP = openNanoFile("std", "GND", "SUBCKT", "w");
3657   printItermNodeSubCkt(gndFP, _gndItermIdTable);
3658   printViaNodeSubCkt(gndFP, _viaM1_GNDtable);
3659   fclose(gndFP);
3660 
3661   gndFP = openNanoFile("glob", "GND", "SUBCKT", "w");
3662   printViaNodeSubCkt(gndFP, _viaUp_GNDtable);
3663   fclose(gndFP);
3664 
3665   fclose(_blkInfoVDD);
3666   fclose(_viaInfoVDD);
3667   fclose(_blkInfoGND);
3668   fclose(_viaInfoGND);
3669 
3670   writeSubckt(_stdCirVDD, ".ends", "VDD", "std", "\n");
3671   fclose(_stdCirVDD);
3672 
3673   writeSubckt(_globCirVDD, ".ends", "VDD", "glob", "\n");
3674   fclose(_globCirVDD);
3675 
3676   writeSubckt(_stdCirGND, ".ends", "GND", "std", "\n");
3677   fclose(_stdCirGND);
3678 
3679   writeSubckt(_globCirGND, ".ends", "GND", "glob", "\n");
3680   fclose(_globCirGND);
3681 
3682   fclose(_coordsVDD);
3683   fclose(_coordsGND);
3684 
3685   addSubcktStatement("glob_VDD.cir", "glob_VDD.subckt");
3686   addSubcktStatement("glob_GND.cir", "glob_GND.subckt");
3687   addSubcktStatement("std_VDD.cir", "std_VDD.subckt");
3688   addSubcktStatement("std_GND.cir", "std_GND.subckt");
3689   /*
3690           system("mv glob_VDD.cir glob_VDD.cir.TMP ; cat glob_VDD.subckt
3691      glob_VDD.cir.TMP > glob_VDD.cir"); system("mv glob_GND.cir glob_GND.cir.TMP
3692      ; cat std_GND.subckt glob_GND.cir.TMP > glob_GND.cir"); system("mv
3693      std_VDD.cir std_VDD.cir.TMP ; cat std_VDD.subckt std_VDD.cir.TMP >
3694      std_VDD.cir"); system("mv std_GND.cir std_GND.cir.TMP ; cat std_GND.subckt
3695      std_GND.cir.TMP > std_GND.cir");
3696           */
3697   //.ends VDD_std_jpeg_e_ring_bad
3698   fclose(_viaStackGlobGND);
3699   fclose(_viaStackGlobVDD);
3700 }
addSubcktStatementDomain(const char * cirFile1,const char * subcktFile1,const char * netName)3701 void extMain::addSubcktStatementDomain(const char* cirFile1,
3702                                        const char* subcktFile1,
3703                                        const char* netName) {
3704   char cirFile[256];
3705   char subcktFile[256];
3706   if (strlen(_node_blk_prefix) > 0) {
3707     char prefix[256];
3708     sprintf(cirFile, "%s/%s/%s%s", _node_blk_dir, netName, _node_inst_prefix,
3709             cirFile1);
3710     sprintf(subcktFile, "%s/%s/%s%s", _node_blk_dir, netName, _node_inst_prefix,
3711             subcktFile1);
3712   } else {
3713     sprintf(cirFile, "%s/%s", netName, cirFile1);
3714     sprintf(subcktFile, "%s/%s", netName, subcktFile1);
3715   }
3716 
3717   char cmd[2048];
3718   sprintf(cmd, "mv %s %s.TMP ; cat %s %s.TMP > %s", cirFile, cirFile,
3719           subcktFile, cirFile, cirFile);
3720 
3721   system(cmd);
3722 
3723   // system("mv glob_VDD.cir glob_VDD.cir.TMP ; cat glob_VDD.subckt
3724   // glob_VDD.cir.TMP > glob_VDD.cir");
3725 }
addSubcktStatement(const char * cirFile1,const char * subcktFile1)3726 void extMain::addSubcktStatement(const char* cirFile1,
3727                                  const char* subcktFile1) {
3728   char prefix[256];
3729   char cirFile[256];
3730   char subcktFile[256];
3731   if (strlen(_node_blk_prefix) > 0) {
3732     setPrefix(prefix);
3733 
3734     sprintf(cirFile, "%s%s", prefix, cirFile1);
3735     sprintf(subcktFile, "%s%s", prefix, subcktFile1);
3736   } else {
3737     sprintf(cirFile, "%s", cirFile1);
3738     sprintf(subcktFile, "%s", subcktFile1);
3739   }
3740 
3741   char cmd[2048];
3742   sprintf(cmd, "mv %s %s.TMP ; cat %s %s.TMP > %s", cirFile, cirFile,
3743           subcktFile, cirFile, cirFile);
3744   system(cmd);
3745 
3746   // system("mv glob_VDD.cir glob_VDD.cir.TMP ; cat glob_VDD.subckt
3747   // glob_VDD.cir.TMP > glob_VDD.cir");
3748 }
isSignalNet(odb::dbNet * net)3749 bool extMain::isSignalNet(odb::dbNet* net) {
3750   odb::dbSigType type = net->getSigType();
3751 
3752   return ((type == odb::dbSigType::POWER) || (type == odb::dbSigType::GROUND))
3753              ? false
3754              : true;
3755 }
3756 // COMMENT 04/17/2013
3757 // Start Connecting from the Top Layers and connect to the first Iterm Shape
iterm2Vias(odb::dbInst * inst,odb::dbNet * net)3758 uint extMain::iterm2Vias(odb::dbInst* inst, odb::dbNet* net) {
3759   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
3760 
3761   const char* ptype = "POWER";
3762   if (net->getSigType() == odb::dbSigType::GROUND)
3763     ptype = "GROUND";
3764 
3765   std::vector<odb::dbBox*> connShapeTable[32];
3766   std::vector<odb::dbITerm*> connItermTable[32];
3767 
3768   odb::dbSet<odb::dbITerm> iterms = inst->getITerms();
3769   odb::dbSet<odb::dbITerm>::iterator iitr;
3770 
3771   for (iitr = iterms.begin(); iitr != iterms.end(); ++iitr) {
3772     odb::dbITerm* tr = *iitr;
3773 
3774     if (tr->getSigType() != net->getSigType())
3775       continue;
3776     if (tr->getNet() != net)
3777       continue;
3778 
3779     odb::dbStringProperty* p = odb::dbStringProperty::find(tr, "_inode");
3780     if (p != NULL)
3781       continue;  // already connected thru wire connection
3782 
3783     uint vcnt = 0;
3784 
3785     odb::dbITermShapeItr term_shapes;
3786     odb::dbShape s;
3787     for (term_shapes.begin(tr); term_shapes.next(s);) {
3788       if (s.isVia())
3789         continue;
3790 
3791       std::vector<odb::dbBox*> viaTable;
3792       uint level = s.getTechLayer()->getRoutingLevel();
3793       if (level == 1)
3794         continue;
3795 
3796       uint viaCnt = blkSearch->getPowerWiresAndVias(
3797           s.xMin(), s.yMin(), s.xMax(), s.yMax(), level, net, false, viaTable);
3798 
3799       if (viaCnt == 0)
3800         continue;
3801 
3802       for (uint ii = 0; ii < viaCnt; ii++) {
3803         odb::dbBox* w = viaTable[ii];
3804         odb::dbSWire* swire = (odb::dbSWire*)w->getBoxOwner();
3805         if (swire->getNet() != net)
3806           continue;
3807 
3808         uint top;
3809         uint bot = blkSearch->getViaLevels(w, top);
3810         if (top < 3)
3811           continue;
3812         if (!((level == bot) || (level == top)))
3813           continue;
3814 
3815         if (w->xMin() > s.xMax())
3816           continue;
3817         if (w->yMin() > s.yMax())
3818           continue;
3819         if (w->xMax() < s.xMin())
3820           continue;
3821         if (w->yMax() < s.yMin())
3822           continue;
3823 
3824         connShapeTable[top].push_back(w);
3825         connItermTable[top].push_back(tr);
3826       }
3827     }
3828   }
3829   for (int level = 31; level > 1; level--) {
3830     if (connShapeTable[level].size() == 0)
3831       continue;
3832 
3833     for (int jj = 0; jj < connShapeTable[level].size(); jj++) {
3834       odb::dbBox* w = connShapeTable[level][jj];
3835       odb::dbITerm* tr = connItermTable[level][jj];
3836 
3837       if (tr->isSetMark())
3838         continue;
3839 
3840       if (!inst->getMaster()->isSpecialPower()) {
3841         char* srcNode = getViaResNode(w, "_up_node");
3842         if (srcNode == NULL)
3843           continue;
3844 
3845         // fprintf(_blkInfo, "%d %d %d %d i2v  %s %s %s [%s] ",
3846         // s.xMin(),s.yMin(),s.xMax(),s.yMax(),
3847         fprintf(_blkInfo, "%s %s %s [%s] ", inst->getConstName(),
3848                 inst->getMaster()->getConstName(),
3849                 // getBlockType(inst->getMaster()),
3850                 "is_macro", tr->getMTerm()->getConstName());
3851 
3852         fprintf(_blkInfo, "%s\n", srcNode);
3853         _viaUpTable->push_back(w);
3854         // connect upwards with vias that coonect to the upper grid
3855         w->setVisited(false);
3856         std::vector<odb::dbBox*> upViaTable;
3857         uint cnt = blkSearch->getPowerWiresAndVias(w->xMin(), w->yMin(),
3858                                                    w->xMax(), w->yMax(), level,
3859                                                    net, false, upViaTable);
3860 
3861         if (mergeStackedViasOpt(_globCir, net, upViaTable, w, _viaStackGlobCir,
3862                                 level) > 0)
3863           _via_id_map[w->getId()] = net;
3864         else
3865           _via_id_map[w->getId()] = NULL;
3866 
3867         logger_->info(RCX, 336, "\tTERM {} is Connected at {}",
3868                       tr->getMTerm()->getConstName(), srcNode);
3869         tr->setMark(1);
3870         break;
3871       }
3872 
3873       // w->setUserFlag1();
3874     }
3875   }
3876   return 0;
3877 }
3878 /* COMMENT 04/17/2013
3879 uint extMain::iterm2Vias(odb::dbInst *inst, odb::dbNet *net)
3880 {
3881         odb::dbBlockSearch *blkSearch= _block->getSearchDb();
3882 
3883         const char *ptype= "POWER";
3884         if (net->getSigType()==odb::dbSigType::GROUND)
3885                 ptype= "GROUND";
3886 
3887         std::vector<odb::dbBox *> connShapeTable[32];
3888 
3889         odb::dbSet<odb::dbITerm> iterms = inst->getITerms();
3890         odb::dbSet<odb::dbITerm>::iterator iitr;
3891 
3892         for(iitr = iterms.begin(); iitr != iterms.end(); ++iitr) {
3893                 odb::dbITerm *tr = *iitr;
3894 
3895                 if (tr->getSigType() != net->getSigType())
3896                         continue;
3897                 if (tr->getNet() != net)
3898                         continue;
3899 
3900                 odb::dbStringProperty *p= odb::dbStringProperty::find(tr,
3901 "_inode"); if (p!=NULL) continue; // already connected thru wire connection
3902 
3903                 uint vcnt= 0;
3904 
3905                 odb::dbITermShapeItr term_shapes;
3906                 odb::odb::dbShape s;
3907                 for( term_shapes.begin(tr); term_shapes.next(s); )
3908                 {
3909                         if (s.isVia())
3910                                 continue;
3911 
3912                         std::vector<odb::dbBox *> viaTable;
3913                         uint level= s.getTechLayer()->getRoutingLevel();
3914                         if (level==1)
3915                                 continue;
3916 
3917                         uint viaCnt= blkSearch->getPowerWiresAndVias(
3918                                 s.xMin(),s.yMin(),s.xMax(),s.yMax(),
3919                                         level, net, false, viaTable);
3920 
3921                         if (viaCnt==0)
3922                                 continue;
3923 
3924                         for (uint ii= 0; ii<viaCnt; ii++)
3925                         {
3926                                 odb::dbBox *w= viaTable[ii];
3927 
3928                                 //if (w->getUserFlag1())
3929                                         //continue;
3930 
3931                                 uint top;
3932                                 uint bot= blkSearch->getViaLevels(w, top);
3933                                 if (top<3)
3934                                         continue;
3935                                 if (!((level==bot) || (level==top)))
3936                                         continue;
3937 
3938                                 if (w->xMin()>s.xMax())
3939                                         continue;
3940                                 if (w->yMin()>s.yMax())
3941                                         continue;
3942                                 if (w->xMax()<s.xMin())
3943                                         continue;
3944                                 if (w->yMax()<s.yMin())
3945                                         continue;
3946 //ADD resistor between iterm and Via
3947 //have to mark vias for double counting
3948 
3949                                 if (!inst->getMaster()->isSpecialPower())
3950                                 {
3951                                         char * srcNode= getViaResNode(w,
3952 "_up_node"); if (srcNode==NULL) continue;
3953 
3954                                         //fprintf(_blkInfo, "%d %d %d %d i2v  %s
3955 %s %s [%s] ",
3956 //s.xMin(),s.yMin(),s.xMax(),s.yMax(),
3957                                         fprintf(_blkInfo, "%s %s [%s] ",
3958                                                 inst->getConstName(),
3959                                                 inst->getMaster()->getConstName(),
3960                                                 getBlockType(inst->getMaster()),
3961                                                 tr->getMTerm()->getConstName());
3962 
3963                                                 fprintf(_blkInfo, "%s\n",
3964 srcNode); _viaUpTable->push_back(w);
3965                                 }
3966 
3967                                 //w->setUserFlag1();
3968 
3969                                 tr->setMark(1);
3970                                 vcnt ++;
3971                         }
3972                 }
3973         }
3974         return 0;
3975 }
3976 */
iterm2Vias_cells(odb::dbInst * inst,odb::dbITerm * connectedPowerIterm)3977 uint extMain::iterm2Vias_cells(odb::dbInst* inst,
3978                                odb::dbITerm* connectedPowerIterm) {
3979   if (inst->getMaster()->isSpecialPower())
3980     return 0;
3981 
3982   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
3983 
3984   odb::dbNet* net = connectedPowerIterm->getNet();
3985 
3986   const char* ptype = "POWER";
3987   if (net->getSigType() == odb::dbSigType::GROUND)
3988     ptype = "GROUND";
3989 
3990   odb::dbSet<odb::dbITerm> iterms = inst->getITerms();
3991   odb::dbSet<odb::dbITerm>::iterator iitr;
3992 
3993   for (iitr = iterms.begin(); iitr != iterms.end(); ++iitr) {
3994     odb::dbITerm* tr = *iitr;
3995 
3996     if (tr->isSetMark())
3997       continue;
3998     if (tr->getNet() != net)
3999       continue;
4000     if (tr == connectedPowerIterm)
4001       continue;
4002 
4003     odb::dbStringProperty* p = odb::dbStringProperty::find(tr, "_inode");
4004     if (p != NULL)
4005       continue;  // already connected thru wire connection
4006 
4007     uint vcnt = 0;
4008 
4009     odb::dbITermShapeItr term_shapes;
4010     odb::dbShape s;
4011     for (term_shapes.begin(tr); term_shapes.next(s);) {
4012       if (s.isVia())
4013         continue;
4014 
4015       std::vector<odb::dbBox*> viaTable;
4016       uint level = s.getTechLayer()->getRoutingLevel();
4017 
4018       uint viaCnt = blkSearch->getPowerWiresAndVias(
4019           s.xMin(), s.yMin(), s.xMax(), s.yMax(), level, net, false, viaTable);
4020 
4021       if (viaCnt == 0)
4022         continue;
4023 
4024       for (uint ii = 0; ii < viaCnt; ii++) {
4025         odb::dbBox* w = viaTable[ii];
4026 
4027         // if (w->getUserFlag1())
4028         // continue;
4029 
4030         uint top;
4031         uint bot = blkSearch->getViaLevels(w, top);
4032 
4033         if (!((level == bot) || (level == top)))
4034           continue;
4035 
4036         if (w->xMin() > s.xMax())
4037           continue;
4038         if (w->yMin() > s.yMax())
4039           continue;
4040         if (w->xMax() < s.xMin())
4041           continue;
4042         if (w->yMax() < s.yMin())
4043           continue;
4044         // ADD resistor between iterm and Via
4045         // have to mark vias for double counting
4046 
4047         fprintf(_blkInfo, "%s %s %s [%s] ", inst->getConstName(),
4048                 inst->getMaster()->getConstName(),
4049                 getBlockType(inst->getMaster()),
4050                 tr->getMTerm()->getConstName());
4051 
4052         writeViaName(_blkInfo, w, 0, "\n");
4053         // fprintf(_blkInfo, " I%d\n", tr->getId());
4054         _viaUpTable->push_back(w);
4055 
4056         // w->setUserFlag1();
4057 
4058         tr->setMark(1);
4059         vcnt++;
4060       }
4061       if (tr->isSetMark())
4062         break;
4063     }
4064   }
4065   return 0;
4066 }
mergeStackedViasOpt(FILE * fp,odb::dbNet * net,std::vector<odb::dbBox * > & viaSearchTable,odb::dbBox * botVia,FILE * fp1,uint viaStackLevel)4067 uint extMain::mergeStackedViasOpt(FILE* fp, odb::dbNet* net,
4068                                   std::vector<odb::dbBox*>& viaSearchTable,
4069                                   odb::dbBox* botVia, FILE* fp1,
4070                                   uint viaStackLevel) {
4071   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
4072   odb::dbBox* v = botVia;
4073 
4074   char srcNode[128];
4075   char resName[128];
4076   char dstNode[128];
4077 
4078   float totRes = 0;
4079   if (!botVia->isVisited()) {
4080     totRes = getPowerViaRes(botVia, 0.1);
4081     botVia->setVisited(true);
4082     _stackedViaResCnt++;
4083   }
4084   float res = 0.0;
4085   uint viaCnt = viaSearchTable.size();
4086 
4087   std::vector<odb::dbBox*> viaLevelTable[16];
4088   for (uint ii = 0; ii < viaCnt; ii++) {
4089     odb::dbBox* w = viaSearchTable[ii];
4090 
4091     odb::Rect vr;
4092     v->getBox(vr);
4093 
4094     odb::Rect wr;
4095     w->getBox(wr);
4096 
4097     if (!wr.overlaps(vr))
4098       continue;
4099 
4100     uint top;
4101     uint bot = blkSearch->getViaLevels(w, top);
4102     viaLevelTable[bot].push_back(w);
4103   }
4104 
4105   odb::dbBox* topVia = NULL;
4106   int stackLevel = 0;
4107   int stackCnt = 0;
4108   std::vector<odb::dbBox*> viaTable;
4109   for (uint jj = viaStackLevel; jj < 16; jj++) {
4110     if (viaLevelTable[jj].size() == 0)
4111       continue;
4112 
4113     stackCnt++;
4114 
4115     odb::dbBox* a = viaLevelTable[jj][0];
4116 
4117     viaTable.push_back(a);
4118 
4119     if (_wireInfra && !(_via2JunctionMap->geti(a->getId()) > 0))
4120       continue;
4121     if (!_wireInfra) {
4122       if (jj == 1)
4123         continue;
4124 
4125       char* topNode = getViaResNode(a, "_down_node");
4126       if (topNode == NULL)
4127         topNode = getViaResNode(a, "_up_node");
4128       if (topNode == NULL)
4129         continue;
4130     }
4131 
4132     stackLevel = jj;
4133     topVia = a;
4134     break;
4135     // fprintf(stdout, "\tstack[%d] %d %d v%d\n ", jj, a->xMin(), a->yMin(),
4136     // a->getId());
4137   }
4138   viaCnt = viaTable.size();
4139   for (uint ii = 0; ii < viaCnt; ii++) {
4140     odb::dbBox* w = viaTable[ii];
4141     w->setVisited(false);
4142   }
4143   if ((topVia != NULL) && (stackCnt == stackLevel)) {
4144     // fprintf(stdout, "\tFOUND TOP stack[%d] %d %d v%d\n ", stackCnt,
4145     // topVia->xMin(), topVia->yMin(), topVia->getId());
4146   } else if (topVia == NULL) {
4147     if ((stackCnt == 0) || (viaTable.size() > stackCnt)) {
4148       return 0;
4149     }
4150     topVia = viaTable[viaTable.size() - 1];
4151   }
4152 
4153   for (uint ii = 0; ii < viaCnt; ii++) {
4154     odb::dbBox* w = viaTable[ii];
4155     uint vid = w->getId();
4156 
4157     res = getPowerViaRes(w, 0.1);
4158     totRes += res;
4159   }
4160   if (topVia == NULL) {
4161     logger_->warn(RCX, 337, "Via_{} {} {} has no overlaps from above!",
4162                   botVia->getId(), botVia->xMin(), botVia->yMin());
4163     return 0;
4164   }
4165   if (botVia == topVia)  // TO_TEST????
4166   {
4167     /*
4168                     sprintf(srcNode,"");
4169                     char * botNode= getViaResNode(botVia, "_up_node");
4170                     if (botNode!=NULL)
4171                     sprintf(srcNode,"%s", botNode);
4172     */
4173     return 0;
4174   }
4175 
4176   uint top;
4177   uint bot = blkSearch->getViaLevels(botVia, top);
4178 
4179   sprintf(resName, "R_%d_%d_v%d ", botVia->xMin(), botVia->yMin(),
4180           botVia->getId());
4181   bot = blkSearch->getViaLevels(topVia, top);
4182   if (_wireInfra) {
4183     writeViaName(srcNode, botVia, bot, " ");
4184     writeViaName(dstNode, topVia, top, " ");
4185   } else {
4186     char* botNode = getViaResNode(botVia, "_up_node");
4187     sprintf(srcNode, "%s", botNode);
4188     char* topNode = getViaResNode(topVia, "_down_node");
4189     if (topNode == NULL)
4190       topNode = getViaResNode(topVia, "_up_node");
4191     if (topNode == NULL) {
4192       logger_->warn(RCX, 338, "NOT CONNECTED M1: Via_{} {} {} {} {}",
4193                     botVia->getId(), botVia->xMin(), botVia->yMin(),
4194                     botVia->xMax(), botVia->yMax());
4195       return 0;
4196     }
4197     sprintf(dstNode, "%s", topNode);
4198   }
4199   // fprintf(stdout, "\t\t%s %s %s %g\n", resName, srcNode, dstNode, totRes);
4200   fprintf(fp, "%s %s %s %g\n", resName, srcNode, dstNode, totRes);
4201 
4202   _totViaResCnt++;
4203 
4204   topVia->setMarked(true);
4205 
4206   if (fp1 != NULL) {
4207     fprintf(fp1, "%s %s %s %g\n", resName, srcNode, dstNode, totRes);
4208   }
4209   return 1;
4210 }
4211 
mergeStackedVias(FILE * fp,odb::dbNet * net,std::vector<odb::dbBox * > & viaSearchTable,odb::dbBox * botVia,FILE * fp1)4212 uint extMain::mergeStackedVias(FILE* fp, odb::dbNet* net,
4213                                std::vector<odb::dbBox*>& viaSearchTable,
4214                                odb::dbBox* botVia, FILE* fp1) {
4215   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
4216   odb::dbBox* v = botVia;
4217   odb::dbBox* w = NULL;
4218 
4219   float totRes = 0;
4220   if (!botVia->isVisited()) {
4221     totRes = getPowerViaRes(botVia, 0.1);
4222     botVia->setVisited(true);
4223     _stackedViaResCnt++;
4224   }
4225   float res = 0.0;
4226   uint viaCnt = viaSearchTable.size();
4227 
4228   std::vector<odb::dbBox*> viaLevelTable[16];
4229   for (uint ii = 0; ii < viaCnt; ii++) {
4230     w = viaSearchTable[ii];
4231 
4232     uint top;
4233     uint bot = blkSearch->getViaLevels(w, top);
4234     viaLevelTable[bot].push_back(w);
4235     // uint vid= w->getId();
4236   }
4237 
4238   std::vector<odb::dbBox*> viaTable;
4239   for (uint jj = 1; jj < 16; jj++) {
4240     if (viaLevelTable[jj].size() == 0)
4241       continue;
4242 
4243     odb::dbBox* a = viaLevelTable[jj][0];
4244     viaTable.push_back(a);
4245   }
4246   fprintf(stdout, "M1: Via_%d %d %d \n", botVia->getId(), botVia->xMin(),
4247           botVia->yMin());
4248   viaCnt = viaTable.size();
4249   for (uint ii = 0; ii < viaCnt; ii++) {
4250     w = viaTable[ii];
4251     uint vid = w->getId();
4252 
4253     fprintf(stdout, "\t ---- mergeStackedVias %d %d v%d\n ", w->xMin(),
4254             w->yMin(), botVia->getId());
4255     if (w->getId() == 283584) {
4256     }
4257     if (w->isVisited())
4258       continue;
4259 
4260     if (w->xMin() > v->xMax())
4261       continue;
4262     if (w->yMin() > v->yMax())
4263       continue;
4264     if (w->xMax() < v->xMin())
4265       continue;
4266     if (w->yMax() < v->yMin())
4267       continue;
4268 
4269     fprintf(stdout, "\tmergeStackedVias %d %d v%d\n ", w->xMin(), w->yMin(),
4270             botVia->getId());
4271     res = getPowerViaRes(w, 0.1);
4272     totRes += res;
4273 
4274     v = w;
4275     _stackedViaResCnt++;
4276 
4277     if (_via2JunctionMap->geti(w->getId()) > 0) {
4278       /*
4279                       fprintf(stdout, "M1: Via_%d %d %d \n",
4280                               botVia->getId(), botVia->xMin(), botVia->yMin());
4281       fprintf(stdout, "mergeStackedVias %d %d v%d\n ", w->xMin(), w->yMin(),
4282       botVia->getId());
4283       */
4284       break;
4285     }
4286     w->setVisited(true);
4287   }
4288   for (uint ii = 0; ii < viaCnt; ii++) {
4289     w = viaTable[ii];
4290     w->setVisited(false);
4291   }
4292   if (w == NULL) {
4293     logger_->warn(RCX, 339, "Via_{} {} {} has no overlaps from above!",
4294                   botVia->getId(), botVia->xMin(), botVia->yMin());
4295     return 0;
4296   }
4297   if (botVia == w)  // TO_TEST????
4298     return 0;
4299 
4300   uint top;
4301   uint bot = blkSearch->getViaLevels(botVia, top);
4302   char resName[128];
4303   char srcNode[128];
4304   char dstNode[128];
4305 
4306   sprintf(resName, "R_%d_%d_v%d ", botVia->xMin(), botVia->yMin(),
4307           botVia->getId());
4308   writeViaName(srcNode, botVia, bot, " ");
4309   bot = blkSearch->getViaLevels(w, top);
4310   writeViaName(dstNode, w, top, " ");
4311   fprintf(stdout, "\t\t%s %s %s %g\n", resName, srcNode, dstNode, totRes);
4312   fprintf(fp, "%s %s %s %g\n", resName, srcNode, dstNode, totRes);
4313   /*
4314           fprintf(fp, "R_%d_%d_v%d ", botVia->xMin(), botVia->yMin(),
4315      botVia->getId()); writeViaName(fp, botVia, bot, " ");
4316 
4317           bot= blkSearch->getViaLevels(w, top);
4318           writeViaName(fp, w, top, " ");
4319           fprintf(fp, " %g\n", totRes);
4320   */
4321   _totViaResCnt++;
4322 
4323   w->setMarked(true);
4324 
4325   if (fp1 != NULL) {
4326     fprintf(fp1, "%s %s %s %g\n", resName, srcNode, dstNode, totRes);
4327   }
4328   return 1;
4329 }
4330 
getPowerNets(std::vector<odb::dbNet * > & powerNetTable)4331 uint extMain::getPowerNets(std::vector<odb::dbNet*>& powerNetTable) {
4332   odb::dbSet<odb::dbNet> nets = _block->getNets();
4333   odb::dbSet<odb::dbNet>::iterator net_itr;
4334   for (net_itr = nets.begin(); net_itr != nets.end(); ++net_itr) {
4335     odb::dbNet* net = *net_itr;
4336 
4337     if (isSignalNet(net))
4338       continue;
4339 
4340     powerNetTable.push_back(net);
4341   }
4342   return powerNetTable.size();
4343 }
findHighLevelPinMacros(std::vector<odb::dbInst * > & instTable)4344 uint extMain::findHighLevelPinMacros(std::vector<odb::dbInst*>& instTable) {
4345   odb::dbSet<odb::dbInst> insts = _block->getInsts();
4346   odb::dbSet<odb::dbInst>::iterator i_itr;
4347   for (i_itr = insts.begin(); i_itr != insts.end(); ++i_itr) {
4348     odb::dbInst* inst = *i_itr;
4349     /*
4350                     odb::dbBox *bb= inst->getBBox();
4351     */
4352 
4353     inst->clearUserFlag3();
4354     if (inst->getMaster()->getMTermCount() > 16) {
4355       instTable.push_back(inst);
4356       inst->setUserFlag3();
4357     }
4358   }
4359   return instTable.size();
4360 }
topHierBlock()4361 bool extMain::topHierBlock() {
4362   odb::dbSet<odb::dbBlock> children = _block->getChildren();
4363   if (children.size() > 0)
4364     return true;
4365   else
4366     return false;
4367 }
allocMappingTables(int n1,int n2,int n3)4368 void extMain::allocMappingTables(int n1, int n2, int n3) {
4369   _junct2iterm = new Ath__array1D<odb::dbITerm*>(n1);
4370   _junct2viaMap = new Ath__array1D<int>(n2);
4371   _via2JunctionMap = new Ath__array1D<int>(n3);
4372 }
initMappingTables()4373 void extMain::initMappingTables() {
4374   uint n = _junct2iterm->getSize();
4375   for (uint kk = 0; kk < n; kk++)
4376     _junct2iterm->set(kk, NULL);
4377 
4378   n = _junct2viaMap->getSize();
4379   for (uint kk = 0; kk < n; kk++)
4380     _junct2viaMap->set(kk, 0);
4381 
4382   n = _via2JunctionMap->getSize();
4383   for (uint kk = 0; kk < n; kk++)
4384     _via2JunctionMap->set(kk, 0);
4385 }
initPowerSearch()4386 uint extMain::initPowerSearch() {
4387   uint sigtype = 9;
4388   uint pwrtype = 11;
4389 
4390   uint pitchTable[16];
4391   uint widthTable[16];
4392   for (uint ii = 0; ii < 16; ii++) {
4393     pitchTable[ii] = 0;
4394     widthTable[ii] = 0;
4395   }
4396   uint dirTable[16];
4397   int baseX[16];
4398   int baseY[16];
4399 
4400   // if (_search!=NULL)
4401   // delete _search;
4402   // odb::Rect extRect;
4403   uint layerCnt = initSearchForNets(baseX, baseY, pitchTable, widthTable,
4404                                     dirTable, _extMaxRect, false);
4405 
4406   return layerCnt;
4407 }
setupDirNaming()4408 void extMain::setupDirNaming() {
4409   sprintf(_node_blk_dir, "./");
4410   sprintf(_node_blk_prefix, "");
4411   sprintf(_node_inst_prefix, "");
4412   odb::dbInst* ii = _block->getParentInst();
4413   if (ii != NULL) {
4414     logger_->info(RCX, 340, "Extract Hier Block {} name= {} of Inst {} {}",
4415                   _block->getId(), _block->getConstName(), ii->getId(),
4416                   ii->getConstName());
4417 
4418     _block->getDieArea(_extMaxRect);
4419     // odb::dbBox *bb= ii->getBBox();
4420     // bb->getBox(_extMaxRect);
4421 
4422     sprintf(_node_blk_dir, "B%d", _block->getId());
4423     sprintf(_node_blk_prefix, "B%d_", _block->getId());
4424     sprintf(_node_inst_prefix, "%s_", ii->getConstName());
4425   } else {
4426     odb::dbSet<odb::dbBlock> children = _block->getChildren();
4427     if (children.size() > 0) {
4428       sprintf(_node_blk_dir, "B%d", _block->getId());
4429       sprintf(_node_blk_prefix, "B%d_", _block->getId());
4430       sprintf(_node_inst_prefix, "%s_", _block->getConstName());
4431 
4432       logger_->info(RCX, 341, "Extract Top Block {} name= {} ", _block->getId(),
4433                     _block->getConstName());
4434 
4435     } else {
4436       logger_->info(RCX, 342, "Extract Block {} name= {}", _block->getId(),
4437                     _block->getConstName());
4438     }
4439     _block->getDieArea(_extMaxRect);
4440   }
4441   logger_->info(RCX, 343, "nodeBlockPrefix={} nodeInstPrefix={}",
4442                 _node_blk_prefix, _node_inst_prefix);
4443 }
4444 
4445 // START
powerRCGen()4446 uint extMain::powerRCGen() {
4447   _wireInfra = false;
4448 
4449   _powerWireCnt = 0;
4450   _mergedPowerWireCnt = 0;
4451   _overlapPowerWireCnt = 0;
4452   _viaOverlapPowerCnt = 0;
4453   _multiViaCnt = 0;
4454 
4455   _nodeCoords = true;  // coord based node naming
4456   _netUtil = new odb::dbCreateNetUtil();
4457   _netUtil->setBlock(_block, false);
4458   _dbgPowerFlow = false;
4459 
4460   allocMappingTables(100000, 10000, 10000000);
4461 
4462   setupDirNaming();
4463 
4464   logger_->info(RCX, 344, "Extract Bounding Box {} {} {} {}",
4465                 _extMaxRect.xMin(), _extMaxRect.yMin(), _extMaxRect.xMax(),
4466                 _extMaxRect.yMax());
4467 
4468   _supplyViaMap[0] = NULL;  // check to see whether
4469   if (_power_source_file != NULL)
4470     readPowerSupplyCoords(_power_source_file);
4471 
4472   odb::dbSet<odb::dbTechLayer> layers = _tech->getLayers();
4473   odb::dbSet<odb::dbTechLayer>::iterator itr;
4474 
4475   // openNanoFiles();
4476   //_junct2iterm= new Ath__array1D<odb::dbITerm*>(100000);
4477   //_junct2viaMap= new Ath__array1D<int>(10000);
4478   //_via2JunctionMap= new Ath__array1D<int>(10000000);
4479 
4480   findHighLevelPinMacros(_powerMacroTable);
4481   logger_->info(RCX, 345, "Found {:lu} macro blocks", _powerMacroTable.size());
4482 
4483   markExcludedCells();
4484 
4485   std::vector<odb::dbNet*> powerNetTable;
4486   uint pNetCnt = getPowerNets(powerNetTable);
4487 
4488   // odb::dbBox *bb = _block->getBBox();
4489   char msg1[1024];
4490   sprintf(msg1, "\nExtracting %d nets ", pNetCnt);
4491   AthResourceLog(msg1, 0);
4492 
4493   // for (int ii= pNetCnt-1; ii>=0; ii--)
4494   for (uint ii = 0; ii < pNetCnt; ii++) {
4495     _sbox_id_map.clear();
4496 
4497     _viaM1_VDDtable.clear();
4498     _viaUp_VDDtable.clear();
4499     _viaM1_GNDtable.clear();
4500     _viaUp_GNDtable.clear();
4501 
4502     _viaUpperTable[0].clear();
4503     _viaUpperTable[1].clear();
4504 
4505     initMappingTables();
4506 
4507     odb::dbNet* net = powerNetTable[ii];
4508 
4509     openNanoFilesDomain(net);
4510     setupNanoFiles(net);
4511     _netUtil->setCurrentNet(net);
4512 
4513     logger_->info(RCX, 346, "Extracting net {} ... ", net->getConstName());
4514 
4515     // 103012 Release railConn(net);
4516 
4517     railConnOpt(net);
4518 
4519     if (_nodeCoords) {
4520       writeViaResistors(_globCirVDD, 1, _viaStackGlobVDD, !_wireInfra);
4521       writeViaResistors(_globCirGND, 0, _viaStackGlobGND, !_wireInfra);
4522     }
4523     sprintf(msg1, "\nFinished %s ", net->getConstName());
4524     AthResourceLog(msg1, 0);
4525 
4526     for (uint jj = 0; jj < _powerMacroTable.size(); jj++) {
4527       odb::dbInst* inst = _powerMacroTable[jj];
4528       logger_->info(RCX, 347, "--- Connectivity of macro {} with net {} ... ",
4529                     inst->getConstName(), net->getConstName());
4530       iterm2Vias(inst, net);
4531       AthResourceLog("-- Finished Macro", 0);
4532     }
4533 
4534     bool m1Vias = true;
4535     writeViasAndClose(net, m1Vias);
4536   }
4537   if (!_nodeCoords) {
4538     writeViaResistors(_globCirVDD, 1, _viaStackGlobVDD);
4539     writeViaResistors(_globCirGND, 0, _viaStackGlobGND);
4540   }
4541 
4542   return 0;
4543 }
writeViasAndClose(odb::dbNet * net,bool m1Vias)4544 void extMain::writeViasAndClose(odb::dbNet* net, bool m1Vias) {
4545   writeViaInfo(_viaInfoVDD, true);
4546   writeViaInfo(_viaInfoGND, false);
4547   writeViaInfo(_viaInfoVDD, _viaUp_VDDtable, !m1Vias, true);
4548   writeViaInfo(_viaInfoVDD, _viaM1_VDDtable, m1Vias, true);
4549 
4550   writeViaInfo(_viaInfoGND, _viaUp_GNDtable, !m1Vias, false);
4551   writeViaInfo(_viaInfoGND, _viaM1_GNDtable, m1Vias, false);
4552 
4553   writeViaCoords(_coordsGND, _viaM1_GNDtable, m1Vias);
4554   writeViaCoords(_coordsVDD, _viaM1_VDDtable, m1Vias);
4555   writeViaCoords(_coordsGND, _viaUp_GNDtable, !m1Vias);
4556   writeViaCoords(_coordsVDD, _viaUp_VDDtable, !m1Vias);
4557 
4558   if (net->getSigType() == odb::dbSigType::POWER)
4559     closeNanoFilesDomainVDD((char*)net->getConstName());
4560   else
4561     closeNanoFilesDomainGND((char*)net->getConstName());
4562 }
writeViaName_xy(char * nodeName,odb::dbBox * v,uint bot,uint top,uint level,const char * post)4563 void extMain::writeViaName_xy(char* nodeName, odb::dbBox* v, uint bot, uint top,
4564                               uint level, const char* post) {
4565   odb::dbSWire* s = (odb::dbSWire*)v->getBoxOwner();
4566   odb::dbNet* net = s->getNet();
4567 
4568   bool change = true;
4569   if (change) {
4570     // HERE NODE_NAMING
4571     if (level <= 2)
4572       level = 1;
4573 
4574     char* srcNode = getViaResNode(v, "_up_node");
4575 
4576     char buf[2048];
4577     odb::dbStringProperty* p = odb::dbStringProperty::find(v, "_inode");
4578     if (p != NULL)
4579       sprintf(nodeName, "%s_%d%s", p->getValue().c_str(), level, post);
4580     else
4581       writeNegativeCoords(nodeName, net->getId(), v->xMin(), v->yMin(), level,
4582                           post);
4583     return;
4584   }
4585 
4586   if (level == 1)
4587     sprintf(nodeName, "n%d_%d_%d%s ", net->getId(), v->xMin(), v->yMin(), post);
4588   else if (level > 1) {
4589     if (bot == level)
4590       sprintf(nodeName, "n%d_%d_%d%s ", net->getId(), v->xMin(), v->yMin(),
4591               post);
4592     else
4593       sprintf(nodeName, "n%d_%d_%d%s ", net->getId(), v->xMax(), v->yMax(),
4594               post);
4595   } else
4596     sprintf(nodeName, "n%d_%d_%d ", net->getId(), v->xMin(), v->yMin());
4597 }
writeViaName(char * nodeName,odb::dbBox * v,uint level,const char * post)4598 void extMain::writeViaName(char* nodeName, odb::dbBox* v, uint level,
4599                            const char* post) {
4600   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
4601   uint top;
4602   uint bot = blkSearch->getViaLevels(v, top);
4603   if (_nodeCoords) {
4604     writeViaName_xy(nodeName, v, bot, top, level, post);
4605     return;
4606   }
4607   if (level == 1)
4608     sprintf(nodeName, "v%d_%d%s", v->getId(), level, post);
4609   else if (level > 1)
4610     sprintf(nodeName, "vM%dM%d_%d_%d%s", bot, top, level, v->getId(), post);
4611   else
4612     sprintf(nodeName, "vM%dM%d_%d%s", bot, top, v->getId(), post);
4613 }
writeViaName(FILE * fp,odb::dbBox * v,uint level,const char * post)4614 void extMain::writeViaName(FILE* fp, odb::dbBox* v, uint level,
4615                            const char* post) {
4616   if (!_wireInfra) {
4617     char* srcNode = getViaResNode(v, "_up_node");
4618     if (srcNode != NULL)
4619       fprintf(fp, "%s%s", srcNode, post);
4620 
4621     return;
4622   }
4623   char nodeName[64];
4624   writeViaName(nodeName, v, level, post);
4625   fprintf(fp, "%s", nodeName);
4626 }
writeViaNameCoords(FILE * fp,odb::dbBox * v)4627 void extMain::writeViaNameCoords(FILE* fp, odb::dbBox* v) {
4628   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
4629   uint top;
4630   uint bot = blkSearch->getViaLevels(v, top);
4631 
4632   writeViaName(fp, v, 0, "");
4633   fprintf(fp, " %d %d  %d %d\n", v->xMin(), v->yMin(), v->getDX(), v->getDY());
4634   writeViaName(fp, v, bot, "");
4635   fprintf(fp, " %d %d  %d %d\n", v->xMin(), v->yMin(), v->getDX(), v->getDY());
4636   writeViaName(fp, v, top, "");
4637   fprintf(fp, " %d %d  %d %d\n", v->xMin(), v->yMin(), v->getDX(), v->getDY());
4638 }
writeViaInfo(FILE * fp,bool power)4639 void extMain::writeViaInfo(FILE* fp, bool power) {
4640   if (fp == NULL)
4641     return;  // called from GND for VDD net ; 01282013
4642   if (_powerSourceTable[power].size() == 0)
4643     return;
4644 
4645   for (uint ii = 0; ii < _powerSourceTable[power].size(); ii++) {
4646     char* sname = _powerSourceTable[power][ii];
4647     fprintf(fp, "@%s\n", sname);
4648   }
4649   for (uint ii = 0; ii < _powerSourceTable[power].size(); ii++) {
4650     char* sname = _powerSourceTable[power][ii];
4651     fprintf(fp, "%s\n", sname);
4652   }
4653 }
writeViaInfo(FILE * fp,std::vector<odb::dbBox * > & viaTable,bool m1Vias,bool power)4654 uint extMain::writeViaInfo(FILE* fp, std::vector<odb::dbBox*>& viaTable,
4655                            bool m1Vias, bool power) {
4656   uint viaCnt = viaTable.size();
4657   if (viaCnt == 0)
4658     return 0;
4659 
4660   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
4661 
4662   for (uint ii = 0; ii < viaCnt; ii++) {
4663     odb::dbBox* v = viaTable[ii];
4664     v->setVisited(false);
4665   }
4666 
4667   if (m1Vias) {
4668     if (_powerSourceTable[power].size() == 0) {
4669       odb::dbBox* v = viaTable[0];
4670       fprintf(fp, "@");
4671 
4672       uint top;
4673       uint bot = blkSearch->getViaLevels(v, top);
4674 
4675       writeViaName(fp, v, bot, "\n");
4676     }
4677   }
4678 
4679   for (uint ii = 0; ii < viaCnt; ii++) {
4680     odb::dbBox* v = viaTable[ii];
4681     if (v->isVisited())
4682       continue;
4683     v->setVisited(true);
4684 
4685     if (m1Vias) {
4686       if (_via_id_map[v->getId()] != NULL) {
4687         uint top;
4688         uint bot = blkSearch->getViaLevels(v, top);
4689         writeViaName(fp, v, bot, "\n");
4690       }
4691       continue;
4692     }
4693     fprintf(fp, "[");
4694     writeViaName(fp, v, 0, "]\n");
4695   }
4696   fprintf(fp, "\n");
4697   return viaCnt;
4698 }
writeViaCoords(FILE * fp,std::vector<odb::dbBox * > & viaTable,bool m1Vias)4699 uint extMain::writeViaCoords(FILE* fp, std::vector<odb::dbBox*>& viaTable,
4700                              bool m1Vias) {
4701   uint viaCnt = viaTable.size();
4702   if (viaCnt == 0)
4703     return 0;
4704 
4705   for (uint ii = 0; ii < viaCnt; ii++) {
4706     odb::dbBox* v = viaTable[ii];
4707     if (m1Vias) {
4708       fprintf(fp, "std_via ");
4709       writeViaNameCoords(fp, v);
4710       continue;
4711     }
4712     fprintf(fp, "glob_via ");
4713     writeViaNameCoords(fp, v);
4714   }
4715   fprintf(fp, "\n");
4716   return viaCnt;
4717 }
writeViaInfo_old(FILE * fp,std::vector<odb::dbBox * > & viaTable,bool m1Vias)4718 uint extMain::writeViaInfo_old(FILE* fp, std::vector<odb::dbBox*>& viaTable,
4719                                bool m1Vias) {
4720   odb::dbBlockSearch* blkSearch = _block->getSearchDb();
4721 
4722   uint viaCnt = viaTable.size();
4723   if (viaCnt == 0)
4724     return 0;
4725 
4726   if (m1Vias) {
4727     odb::dbBox* v = viaTable[0];
4728     // fprintf(fp, "@vM1_%d\n", v->getId());
4729     uint top;
4730     uint bot = blkSearch->getViaLevels(v, top);
4731     fprintf(fp, "@vM%dM%d_%d_%d_%d\n", bot, top, v->getId(), v->xMin(),
4732             v->yMin());
4733   }
4734 
4735   for (uint ii = 0; ii < viaCnt; ii++) {
4736     odb::dbBox* v = viaTable[ii];
4737     uint top;
4738     uint bot = blkSearch->getViaLevels(v, top);
4739     if (m1Vias) {
4740       // fprintf(fp, "vM1_%d\n", v->getId());
4741       fprintf(fp, "vM%dM%d_%d_%d_%d\n", bot, top, v->getId(), v->xMin(),
4742               v->yMin());
4743       continue;
4744     }
4745     fprintf(fp, "[vM%dM%d_%d_%d_%d]\n", bot, top, v->getId(), v->xMin(),
4746             v->yMin());
4747   }
4748   fprintf(fp, "\n");
4749   return viaCnt;
4750 }
4751 
computeViaResistance(odb::dbBox * viaBox,uint & cutCount)4752 float extMain::computeViaResistance(odb::dbBox* viaBox, uint& cutCount) {
4753   cutCount = 1;
4754   std::vector<odb::dbShape> shapes;
4755   viaBox->getViaBoxes(shapes);
4756 
4757   if (shapes.size() == 0)
4758     return 0;
4759 
4760   std::vector<odb::dbShape>::iterator shape_itr;
4761 
4762   uint cut_count = 0;
4763   float totRes = 0.0;
4764   for (shape_itr = shapes.begin(); shape_itr != shapes.end(); ++shape_itr) {
4765     odb::dbShape s = *shape_itr;
4766 
4767     if (s.getTechLayer()->getType() != odb::dbTechLayerType::CUT)
4768       continue;
4769 
4770     cut_count++;
4771     totRes += s.getTechLayer()->getResistance();
4772   }
4773   float avgCutRes = totRes / cut_count;
4774 
4775   float Res = avgCutRes / cut_count;
4776   cutCount = cut_count;
4777   return Res;
4778 }
readPowerSupplyCoords(char * filename)4779 uint extMain::readPowerSupplyCoords(char* filename) {
4780   int layerCount = _tech->getRoutingLayerCount() + 1;
4781   for (uint ii = 0; ii < 2; ii++) {
4782     _supplyViaMap[ii] = new Ath__array1D<char*>* [layerCount];
4783     _supplyViaTable[ii] = new Ath__array1D<odb::dbBox*>* [layerCount];
4784     for (uint jj = 0; jj < layerCount; jj++) {
4785       _supplyViaMap[ii][jj] = new Ath__array1D<char*>(100000);
4786       _supplyViaTable[ii][jj] = new Ath__array1D<odb::dbBox*>(1024);
4787     }
4788   }
4789   int cnt = 0;
4790   int db_units = _block->getDbUnitsPerMicron();
4791   Ath__parser parser;
4792   // parser.addSeparator("\r");
4793   parser.openFile(filename);
4794   while (parser.parseNextLine() > 0) {
4795     if (parser.getWordCnt() < 5) {
4796       logger_->warn(RCX, 348, "Less than 5 tokens in line {}",
4797                     parser.getLineNum());
4798       parser.printWords(NULL);
4799       continue;
4800     }
4801     char* layer_name = parser.get(3);
4802     odb::dbTechLayer* layer = _tech->findLayer(layer_name);
4803     if (layer == NULL) {
4804       logger_->warn(RCX, 349, "Layer {} might be undefined in LEF at line: ",
4805                     layer_name);
4806       parser.printWords(NULL);
4807       continue;
4808     }
4809     if (layer->getRoutingLevel() >= _tech->getRoutingLayerCount()) {
4810       logger_->warn(RCX, 350, "Layer Name {} cannot be the top layer at line: ",
4811                     layer_name);
4812       parser.printWords(NULL);
4813       logger_->warn(RCX, 351, "the above line will be skipped!");
4814       continue;
4815     }
4816     parser.printWords(NULL);
4817     bool power = false;
4818     if (parser.isKeyword(4, "POWER")) {
4819       power = true;
4820     }
4821     char* source_name = parser.get(0);
4822     double x_microns = parser.getDouble(1);
4823     int x = Ath__double2int(db_units * x_microns);
4824     double y_microns = parser.getDouble(2);
4825     int y = Ath__double2int(db_units * y_microns);
4826 
4827     int level = layer->getRoutingLevel();
4828     odb::dbTechLayer* layer_plus_1 = _tech->findRoutingLayer(level + 1);
4829 
4830     odb::dbTechVia* techVia = odb::dbTechVia::create(_tech, source_name);
4831     odb::dbBox* bot = odb::dbBox::create(techVia, layer, x, y, x + 1, y + 1);
4832     odb::dbBox* top =
4833         odb::dbBox::create(techVia, layer_plus_1, x, y, x + 1, y + 1);
4834 
4835     // odb::dbBox *v = _netUtil->createTechVia(x, y, x+1, y+1, level, level+1);
4836     odb::dbBox* v = techVia->getBBox();
4837 
4838     _supplyViaTable[power][level]->add(v);
4839     _supplyViaMap[power][level]->set(v->getId(), strdup(source_name));
4840 
4841     cnt++;
4842     char* sname = _supplyViaMap[power][level]->geti(v->getId());
4843     logger_->info(RCX, 352, "{} {} {} {} {} -- viaId= {} viaBoxId={} {} {}",
4844                   sname, x, y, level, power, techVia->getId(), v->getId(),
4845                   bot->getId(), top->getId());
4846   }
4847   logger_->info(RCX, 353, "Have read {} power/ground sources", cnt);
4848   return cnt;
4849 }
getPowerSourceName(bool power,uint level,uint vid)4850 char* extMain::getPowerSourceName(bool power, uint level, uint vid) {
4851   if (_supplyViaMap[0] == NULL)
4852     return NULL;
4853 
4854   return _supplyViaMap[power][level]->geti(vid);
4855 }
addPowerSources(std::vector<odb::dbBox * > & viaTable,bool power,uint level,odb::Rect * powerWire)4856 uint extMain::addPowerSources(std::vector<odb::dbBox*>& viaTable, bool power,
4857                               uint level, odb::Rect* powerWire) {
4858   if (_supplyViaTable[0] == NULL)
4859     return 0;
4860 
4861   uint n = _supplyViaTable[power][level]->getCnt();
4862   uint cnt = 0;
4863   for (uint ii = 0; ii < n; ii++) {
4864     odb::dbBox* v = _supplyViaTable[power][level]->get(ii);
4865     odb::Rect via;
4866     v->getBox(via);
4867     if (!powerWire->contains(via))
4868       continue;
4869     // v->setMarked(true);
4870     viaTable.push_back(v);
4871     cnt++;
4872     logger_->info(RCX, 354, "    viaSource@ {} {}  {} {}", v->xMin(), v->yMin(),
4873                   v->xMax(), v->yMax());
4874     logger_->info(RCX, 355,
4875                   "    connected with power wire at level {} :  {} {}  {} {}",
4876                   level, powerWire->xMin(), powerWire->yMin(),
4877                   powerWire->xMax(), powerWire->yMax());
4878   }
4879   if (cnt > 0)
4880     logger_->info(RCX, 356,
4881                   "added {} [type={}] power/ground sources on level {}", cnt,
4882                   power, level);
4883   return n;
4884 }
getPowerSourceName(uint level,uint vid)4885 char* extMain::getPowerSourceName(uint level, uint vid) {
4886   odb::dbNet* net = _netUtil->getCurrentNet();
4887   bool isVDDnet = false;
4888   if (net->getSigType() == odb::dbSigType::POWER)
4889     isVDDnet = true;
4890 
4891   char* name = getPowerSourceName(isVDDnet, level, vid);
4892   return name;
4893 }
addPowerSourceName(uint ii,char * sname)4894 void extMain::addPowerSourceName(uint ii, char* sname) {
4895   _powerSourceTable[ii].push_back(sname);
4896 }
4897 
4898 }  // namespace rcx
4899