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