1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #include "dbFlatten.h"
34 
35 #include "db.h"
36 #include "dbCapNode.h"
37 #include "dbInst.h"
38 #include "dbNet.h"
39 #include "dbObstruction.h"
40 #include "dbSWire.h"
41 #include "dbShape.h"
42 #include "dbTransform.h"
43 #include "dbWire.h"
44 #include "dbWireOpcode.h"
45 #include "utl/Logger.h"
46 
47 namespace odb {
48 
dbFlatten()49 dbFlatten::dbFlatten()
50     : _do_not_copy_power_wires(true),
51       _copy_shields(true),
52       _create_boundary_regions(false),
53       _create_bterm_map(false),
54       _copy_parasitics(false),
55       _hier_d(0),
56       _next_bterm_map_id(0)
57 {
58 }
59 
~dbFlatten()60 dbFlatten::~dbFlatten()
61 {
62 }
63 
flatten(dbBlock * block,int level)64 bool dbFlatten::flatten(dbBlock* block, int level)
65 {
66   _hier_d = block->getHierarchyDelimeter();
67   _next_bterm_map_id = 0;
68   dbProperty* bterm_map = NULL;
69 
70   if (_create_bterm_map) {
71     dbProperty* p = dbProperty::find(block, "_ADS_BTERM_MAP");
72 
73     if (p != NULL)
74       dbProperty::destroy(p);
75 
76     std::string name = block->getName();
77     bterm_map = dbStringProperty::create(block, "_ADS_BTERM_MAP", name.c_str());
78   }
79 
80   bool error = false;
81   dbSet<dbInst> insts = block->getInsts();
82   dbSet<dbInst>::iterator itr;
83 
84   for (itr = insts.begin(); itr != insts.end(); ++itr) {
85     dbInst* inst = *itr;
86     dbBlock* child = inst->getChild();
87 
88     if (child)
89       if (!flatten(block, child, level, bterm_map))
90         error = true;
91   }
92 
93   for (itr = insts.begin(); itr != insts.end();) {
94     dbInst* inst = *itr;
95     dbBlock* child = inst->getChild();
96 
97     if (child) {
98       inst->unbindBlock();
99       dbBlock::destroy(child);
100       itr = dbInst::destroy(itr);
101     } else
102       ++itr;
103   }
104 
105   return !error;
106 }
107 
108 /* // flatten = flatten child block into parent
109 //
110 //           ..........o Parent (inst/block)
111 //           .        / \
112 //           .       /   \
113 //           .      / ... \
114 //           .     /
115 //           .    o Child (inst/block)
116 //           .   / \
117 //           .  /   \
118 //           . / ... \
119 //           ./
120 //           o Grandchild (inst)
121 // */
flatten(dbBlock * parent,dbBlock * child,int level,dbProperty * bterm_map)122 bool dbFlatten::flatten(dbBlock* parent,
123                         dbBlock* child,
124                         int level,
125                         dbProperty* bterm_map)
126 {
127   bool error = false;
128 
129   if (level == 0)
130     return true;
131 
132   if (bterm_map) {
133     std::string name = child->getName();
134     std::string propName("_ADS_BTERM_MAP");
135     propName += "_";
136     propName += name.c_str();
137     bterm_map
138         = dbStringProperty::create(bterm_map, propName.c_str(), name.c_str());
139   }
140 
141   // Descend hierarchy and flatten
142   dbSet<dbInst> insts = child->getInsts();
143   dbSet<dbInst>::iterator itr;
144 
145   for (itr = insts.begin(); itr != insts.end(); ++itr) {
146     dbInst* inst = *itr;
147     dbBlock* grandchild = inst->getChild();
148 
149     if (grandchild)
150       flatten(child, grandchild, level - 1, bterm_map);
151   }
152 
153   child->getParentInst()->getTransform(_transform);
154 
155   ////////////////////////////
156   // Copy child data to parent
157   ////////////////////////////
158 
159   _net_map.clear();
160   _via_map.clear();
161   _inst_map.clear();
162   _layer_rule_map.clear();
163   _reg_map.clear();
164 
165   ////////////////////////////
166   // Copy vias
167   ////////////////////////////
168   dbVia::copy(parent, child);
169   dbSet<dbVia> vias = child->getVias();
170   dbSet<dbVia>::iterator vitr;
171   for (vitr = vias.begin(); vitr != vias.end(); ++vitr) {
172     dbVia* v = *vitr;
173     std::string name = v->getName();
174     _via_map[v] = parent->findVia(name.c_str());
175   }
176 
177   ////////////////////////////
178   // Copy non-default_rules
179   ////////////////////////////
180   dbSet<dbTechNonDefaultRule> ndrules = child->getNonDefaultRules();
181   dbSet<dbTechNonDefaultRule>::iterator nditr;
182   for (nditr = ndrules.begin(); nditr != ndrules.end(); ++nditr) {
183     dbTechNonDefaultRule* rule = *nditr;
184     copyNonDefaultRule(parent, child->getParentInst(), rule);
185   }
186 
187   ////////////////////////////
188   // Copy nets
189   ////////////////////////////
190   dbSet<dbNet> nets = child->getNets();
191   dbSet<dbNet>::iterator nitr;
192 
193   for (nitr = nets.begin(); nitr != nets.end(); ++nitr) {
194     dbNet* src = *nitr;
195     dbNet* dst = copyNet(parent, src);
196 
197     if (dst == NULL)
198       error = true;
199 
200     _net_map[src] = dst;
201   }
202 
203   ////////////////////////////
204   // Copy instances
205   ////////////////////////////
206   for (itr = insts.begin(); itr != insts.end();) {
207     dbInst* inst = *itr;
208     dbBlock* grandchild = inst->getChild();
209 
210     if (grandchild) {
211       inst->unbindBlock();
212       dbBlock::destroy(grandchild);
213       itr = dbInst::destroy(itr);
214     } else {
215       if (!copyInst(parent, child->getParentInst(), inst))
216         error = true;
217 
218       ++itr;
219     }
220   }
221 
222   ////////////////////////////
223   // Copy the wires seperately
224   ////////////////////////////
225   for (nitr = nets.begin(); nitr != nets.end(); ++nitr) {
226     dbNet* src = *nitr;
227     dbNet* dst = _net_map[src];
228 
229     if (dst)
230       copyNetWires(dst, src, level, bterm_map);
231   }
232 
233   ////////////////////////////
234   // Copy obstructions
235   ////////////////////////////
236   dbSet<dbObstruction> obstructions = child->getObstructions();
237   dbSet<dbObstruction>::iterator oitr;
238 
239   for (oitr = obstructions.begin(); oitr != obstructions.end(); ++oitr) {
240     dbObstruction* o = *oitr;
241     copyObstruction(parent, o);
242   }
243 
244   ////////////////////////////
245   // Copy blocakges
246   ////////////////////////////
247   dbSet<dbBlockage> blocakges = child->getBlockages();
248   dbSet<dbBlockage>::iterator bitr;
249 
250   for (bitr = blocakges.begin(); bitr != blocakges.end(); ++bitr) {
251     dbBlockage* b = *bitr;
252     copyBlockage(parent, b);
253   }
254 
255   ////////////////////////////
256   // Copy regions
257   ////////////////////////////
258   dbSet<dbRegion> regions = child->getRegions();
259   dbSet<dbRegion>::iterator rgitr;
260 
261   for (rgitr = regions.begin(); rgitr != regions.end(); ++rgitr) {
262     dbRegion* rg = *rgitr;
263     if (rg->getParent() == NULL)
264       copyRegion(parent, child->getParentInst(), NULL, rg);
265   }
266 
267   if (_create_boundary_regions) {
268     std::string name = child->getParentInst()->getName();
269     name += _hier_d;
270     name += "ADS_BLOCK_REGION";
271     dbRegion* block_region = dbRegion::create(parent, name.c_str());
272     Rect bndry;
273     child->getDieArea(bndry);
274     _transform.apply(bndry);
275     dbBox::create(
276         block_region, bndry.xMin(), bndry.yMin(), bndry.xMax(), bndry.yMax());
277 
278     for (rgitr = regions.begin(); rgitr != regions.end(); ++rgitr) {
279       dbRegion* rg = *rgitr;
280 
281       if (rg->getParent() == NULL)
282         block_region->addChild(_reg_map[rg]);
283     }
284 
285     for (itr = insts.begin(); itr != insts.end(); ++itr) {
286       dbInst* inst = *itr;
287 
288       if (inst->getRegion() == NULL)
289         block_region->addInst(_inst_map[inst]);
290     }
291   }
292 
293   _net_map.clear();
294   _via_map.clear();
295   _inst_map.clear();
296   _layer_rule_map.clear();
297   _reg_map.clear();
298   _node_map.clear();
299   return !error;
300 }
301 
302 /*
303 // copyInst - This method copies the Grandchild from the Child to the Parent
304 node
305 //
306 //           ..........o Parent (inst/block)
307 //           .        / \
308 //           .       /   \
309 //           .      / ... \
310 //           .     /
311 //           .    o Child (inst/block)
312 //           .   / \
313 //           .  /   \
314 //           . / ... \
315 //           ./
316 //           o Grandchild (inst)
317 //
318 */
copyInst(dbBlock * parent,dbInst * child,dbInst * grandchild)319 bool dbFlatten::copyInst(dbBlock* parent, dbInst* child, dbInst* grandchild)
320 {
321   std::string name = child->getName();
322   name += _hier_d;
323   name += grandchild->getName();
324 
325   dbInst* inst = dbInst::create(parent, grandchild->getMaster(), name.c_str());
326   _inst_map[grandchild] = inst;
327 
328   // Copy placement
329   dbTransform gt;
330   grandchild->getTransform(gt);
331   gt.concat(_transform);
332   inst->setTransform(gt);
333   inst->setPlacementStatus(child->getPlacementStatus());
334 
335   // Copy connections
336   dbSet<dbITerm> iterms = grandchild->getITerms();
337   dbSet<dbITerm>::iterator itr;
338 
339   for (itr = iterms.begin(); itr != iterms.end(); ++itr) {
340     dbITerm* child_iterm = *itr;
341     dbNet* child_net = child_iterm->getNet();
342 
343     if (child_net != NULL) {
344       dbNet* parent_net = _net_map[child_net];
345 
346       if (parent_net == NULL)
347         continue;  // error
348 
349       dbITerm* parent_iterm = inst->getITerm(child_iterm->getMTerm());
350       dbITerm::connect(parent_iterm, parent_net);
351     }
352   }
353 
354   // Copy misc. attributes
355   copyAttrs(inst, child);
356   return true;
357 }
358 
copyNet(dbBlock * parent_block,dbNet * child_net)359 dbNet* dbFlatten::copyNet(dbBlock* parent_block, dbNet* child_net)
360 {
361   dbSet<dbBTerm> bterms = child_net->getBTerms();
362 
363   if (!bterms.empty()) {
364     // external net, find a parent
365     dbSet<dbBTerm>::iterator itr;
366 
367     for (itr = bterms.begin(); itr != bterms.end(); ++itr) {
368       dbBTerm* bterm = *itr;
369       dbITerm* iterm = bterm->getITerm();
370       dbNet* net = iterm->getNet();
371 
372       if (net)
373         return net;
374     }
375 
376     // None of the iterms were connected to a net in the parent-inst.
377     // Create a new net?
378     // TODO: Does this case need special consideration...
379   }
380 
381   // internal net, export up hierarchy
382   dbInst* inst = child_net->getBlock()->getParentInst();
383   std::string name = inst->getName();
384   name += _hier_d;
385   name += child_net->getName();
386   dbNet* net = dbNet::create(parent_block, name.c_str());
387 
388   if (net == NULL) {
389     // TODO:
390     parent_block->getImpl()->getLogger()->warn(
391         utl::ODB, 281, "Failed to create net {}", name);
392     return NULL;
393   }
394 
395   // copy attrs
396   copyAttrs(net, child_net);
397   return net;
398 }
399 
printShapes(FILE * fp,dbWire * wire,bool skip_rcSegs)400 void dbFlatten::printShapes(FILE* fp, dbWire* wire, bool skip_rcSegs)
401 {
402   dbWireShapeItr shapes;
403   dbShape s;
404 
405   for (shapes.begin(wire); shapes.next(s);) {
406     uint sid = shapes.getShapeId();
407     Rect r;
408     s.getBox(r);
409     fprintf(fp,
410             "J%d -- %d %d %d %d\n",
411             sid,
412             r.xMin(),
413             r.yMin(),
414             r.xMax(),
415             r.yMax());
416   }
417   if (skip_rcSegs)
418     return;
419   fprintf(fp, "\ncapNOdes\n");
420   dbSet<dbCapNode> nodeSet = wire->getNet()->getCapNodes();
421   dbSet<dbCapNode>::iterator rc_itr;
422   for (rc_itr = nodeSet.begin(); rc_itr != nodeSet.end(); ++rc_itr) {
423     dbCapNode* node = *rc_itr;
424 
425     uint node_num = node->getNode();
426     uint sid = node->getShapeId();
427     fprintf(fp, "cap%d  node%d  J%d\n", node->getId(), node_num, sid);
428   }
429   dbBlock* block = wire->getNet()->getBlock();
430   dbSet<dbRSeg> rSet = wire->getNet()->getRSegs();
431   dbSet<dbRSeg>::iterator rcitr;
432 
433   fprintf(fp, "\nRSEGS\n");
434   for (rcitr = rSet.begin(); rcitr != rSet.end(); ++rcitr) {
435     dbRSeg* rc = *rcitr;
436     dbCapNode* capNode = dbCapNode::getCapNode(block, rc->getTargetNode());
437 
438     uint shapeId = rc->getShapeId();
439     dbCapNode* srcNode = rc->getSourceCapNode();
440 
441     fprintf(fp, "%d J%d rc%d ", srcNode->getNode(), shapeId, rc->getId());
442 
443     // if (!_foreign && shapeId==0)
444     if (shapeId == 0) {
445       fprintf(fp, "\n");
446       continue;
447     }
448 
449     dbShape s;
450     wire->getShape(shapeId, s);
451     if (s.isVia())
452       continue;
453 
454     Rect r;
455     s.getBox(r);
456 
457     fprintf(fp, "--  %d %d %d %d --", r.xMin(), r.yMin(), r.xMax(), r.yMax());
458 
459     if (capNode->isITerm() || capNode->isBTerm()) {
460       fprintf(fp, "B%d I%d -- ", capNode->isBTerm(), capNode->isITerm());
461       // continue;
462     }
463 
464     int rsegId;
465     wire->getProperty(shapeId, rsegId);
466 
467     fprintf(fp,
468             " prop%d tgt%d node%d\n",
469             rsegId,
470             rc->getTargetNode(),
471             capNode->getId());
472   }
473 }
setOldShapeIds(dbWire * wire)474 void dbFlatten::setOldShapeIds(dbWire* wire)
475 {
476   dbWireShapeItr shapes;
477   dbShape s;
478 
479   for (shapes.begin(wire); shapes.next(s);) {
480     uint sid = shapes.getShapeId();
481     dbShape s;
482     wire->getShape(sid, s);
483     if (s.isVia())
484       continue;
485     wire->setProperty(sid, -sid);
486   }
487 }
mapOld2newIds(dbWire * wire,FILE * fp)488 void dbFlatten::mapOld2newIds(dbWire* wire, FILE* fp)
489 {
490   if (fp != NULL)
491     fprintf(fp, "\nmapOld2newIds\n");
492   dbWireShapeItr shapes;
493   dbShape s;
494 
495   for (shapes.begin(wire); shapes.next(s);) {
496     uint sid = shapes.getShapeId();
497     dbShape s;
498     wire->getShape(sid, s);
499     if (s.isVia())
500       continue;
501     int n;
502     wire->getProperty(sid, n);
503     if (n >= 0)
504       continue;
505     _shape_rc_map[-n] = sid;
506     if (fp != NULL)
507       fprintf(fp, "old shapeId %d to new %d\n", -n, sid);
508   }
509 }
setShapeProperties(dbWire * wire)510 void dbFlatten::setShapeProperties(dbWire* wire)
511 {
512   dbBlock* block = wire->getNet()->getBlock();
513   dbSet<dbRSeg> rSet = wire->getNet()->getRSegs();
514   dbSet<dbRSeg>::iterator rcitr;
515   for (rcitr = rSet.begin(); rcitr != rSet.end(); ++rcitr) {
516     dbRSeg* rc = *rcitr;
517     dbCapNode* capNode = dbCapNode::getCapNode(block, rc->getTargetNode());
518     if (capNode->isITerm() || capNode->isBTerm())
519       continue;
520 
521     uint shapeId = rc->getShapeId();
522 
523     // if (!_foreign && shapeId==0)
524     if (shapeId == 0)
525       continue;
526 
527     wire->setProperty(shapeId, -rc->getId());
528   }
529 }
530 
debugNetWires(FILE * fp,dbNet * dst,dbNet * src,const char * msg)531 FILE* dbFlatten::debugNetWires(FILE* fp,
532                                dbNet* dst,
533                                dbNet* src,
534                                const char* msg)
535 {
536   if (fp == NULL) {
537     char buf[32];
538     sprintf(buf, "%d", dst->getId());
539     fp = fopen(buf, "w");
540 
541     if (fp == NULL) {
542       src->getImpl()->getLogger()->error(
543           utl::ODB, 26, "Cannot Open file {} to write", buf);
544       return nullptr;
545     }
546   }
547   fprintf(fp, "%s  -------------------------------\n", msg);
548 
549   if (src != NULL) {
550     fprintf(
551         fp, "Rsegs for SRC : %s --------------------\n", src->getConstName());
552     printRSegs(fp, src);
553     fprintf(fp, "\tsrc Wire -- net %s\n\n", src->getConstName());
554     if (src->getWire() != NULL) {
555       src->getWire()->printWire(fp, 0, 0);
556       printShapes(fp, src->getWire());
557     }
558   }
559   if (dst != NULL) {
560     fprintf(
561         fp, "Rsegs for DST : %s --------------------\n", dst->getConstName());
562     printRSegs(fp, dst);
563     fprintf(fp, "\n\tdst Wire -- net %s\n\n", dst->getConstName());
564     if (dst->getWire() != NULL) {
565       dst->getWire()->printWire(fp, 0, 0);
566       printShapes(fp, dst->getWire());
567     }
568   }
569   return fp;
570 }
copyNetWires(dbNet * dst,dbNet * src,int level,dbProperty * bterm_map)571 void dbFlatten::copyNetWires(dbNet* dst,
572                              dbNet* src,
573                              int level,
574                              dbProperty* bterm_map)
575 {
576   FILE* fp = NULL;
577   if (isDebug("FLATTEN", "R"))
578     fp = debugNetWires(NULL, dst, src, "Before CopyWires");
579 
580   copyWires(dst, src, level, bterm_map, _copy_parasitics);
581   copySWires(dst, src);
582 
583   if (fp != NULL) {
584     debugNetWires(fp, dst, NULL, "After CopyWires");
585     fclose(fp);
586   }
587 }
588 
copyAttrs(dbInst * dst_,dbInst * src_)589 void dbFlatten::copyAttrs(dbInst* dst_, dbInst* src_)
590 {
591   _dbInst* dst = (_dbInst*) dst_;
592   _dbInst* src = (_dbInst*) src_;
593 
594   dst->_flags._user_flag_1 = src->_flags._user_flag_1;
595   dst->_flags._user_flag_2 = src->_flags._user_flag_2;
596   dst->_flags._user_flag_3 = src->_flags._user_flag_3;
597   dst->_flags._size_only = src->_flags._size_only;
598   dst->_flags._dont_touch = src->_flags._dont_touch;
599   dst->_flags._dont_size = src->_flags._dont_size;
600   dst->_flags._source = src->_flags._source;
601   dst->_weight = src->_weight;
602 }
603 
copyAttrs(dbNet * dst_,dbNet * src_)604 void dbFlatten::copyAttrs(dbNet* dst_, dbNet* src_)
605 {
606   _dbNet* dst = (_dbNet*) dst_;
607   _dbNet* src = (_dbNet*) src_;
608 
609   dst->_flags._sig_type = src->_flags._sig_type;
610   dst->_flags._wire_type = src->_flags._wire_type;
611   dst->_flags._special = src->_flags._special;
612   dst->_flags._wild_connect = src->_flags._wild_connect;
613   dst->_flags._wire_ordered = src->_flags._wire_ordered;
614   dst->_flags._buffered = src->_flags._buffered;
615   dst->_flags._disconnected = src->_flags._disconnected;
616   dst->_flags._spef = src->_flags._spef;
617   dst->_flags._select = src->_flags._select;
618   dst->_flags._mark = src->_flags._mark;
619   dst->_flags._mark_1 = src->_flags._mark_1;
620   dst->_flags._wire_altered = src->_flags._wire_altered;
621   dst->_flags._extracted = src->_flags._extracted;
622   dst->_flags._rc_graph = src->_flags._rc_graph;
623   dst->_flags._reduced = src->_flags._reduced;
624   dst->_flags._set_io = src->_flags._set_io;
625   dst->_flags._io = src->_flags._io;
626   dst->_flags._dont_touch = src->_flags._dont_touch;
627   dst->_flags._size_only = src->_flags._size_only;
628   dst->_flags._fixed_bump = src->_flags._fixed_bump;
629   dst->_flags._source = src->_flags._source;
630   dst->_flags._rc_disconnected = src->_flags._rc_disconnected;
631   dst->_weight = src->_weight;
632   dst->_xtalk = src->_xtalk;
633   dst->_non_default_rule = src->_non_default_rule;
634 }
635 
copyWires(dbNet * dst_,dbNet * src_,int level,dbProperty * bterm_map,bool copyParasitics)636 void dbFlatten::copyWires(dbNet* dst_,
637                           dbNet* src_,
638                           int level,
639                           dbProperty* bterm_map,
640                           bool copyParasitics)
641 {
642   //_dbNet * dst = (_dbNet *) dst_;
643   _dbNet* src = (_dbNet*) src_;
644 
645   if (src->_wire) {
646     _dbWire* src_wire = (_dbWire*) src_->getWire();
647 
648     if (canCopyWire((dbWire*) src_wire, src->_flags._sig_type)) {
649       if (copyParasitics)
650         setOldShapeIds(src_->getWire());
651 
652       if (dst_->getWire()) {
653         dbVector<unsigned char> opcodes;
654         dbVector<int> data;
655         opcodes.reserve(src_wire->_opcodes.size());
656         opcodes = src_wire->_opcodes;
657         data.reserve(src_wire->_data.size());
658         data = src_wire->_data;
659         fixWire(opcodes, data, src_->getBlock(), level, bterm_map);
660         appendWire(opcodes, data, dst_->getWire());
661       } else {
662         _dbWire* dst_wire = (_dbWire*) dbWire::create(dst_);
663         dst_wire->_opcodes.reserve(src_wire->_opcodes.size());
664         dst_wire->_opcodes = src_wire->_opcodes;
665         dst_wire->_data.reserve(src_wire->_data.size());
666         dst_wire->_data = src_wire->_data;
667         fixWire(dst_wire->_opcodes,
668                 dst_wire->_data,
669                 src_->getBlock(),
670                 level,
671                 bterm_map);
672       }
673       if (copyParasitics) {
674         dbSet<dbRSeg> rSet = dst_->getRSegs();
675         rSet.reverse();
676 
677         rSet = dst_->getRSegs();
678         rSet.reverse();
679       }
680     }
681   }
682 
683   if (src->_global_wire) {
684     _dbWire* src_wire = (_dbWire*) src_->getGlobalWire();
685 
686     if (canCopyWire((dbWire*) src_wire, src->_flags._sig_type)) {
687       if (dst_->getGlobalWire()) {
688         dbVector<unsigned char> opcodes;
689         dbVector<int> data;
690         opcodes.reserve(src_wire->_opcodes.size());
691         opcodes = src_wire->_opcodes;
692         data.reserve(src_wire->_data.size());
693         data = src_wire->_data;
694         fixWire(opcodes, data, src_->getBlock(), level, bterm_map);
695         appendWire(opcodes, data, dst_->getGlobalWire());
696       } else {
697         _dbWire* dst_wire = (_dbWire*) dbWire::create(dst_, true);
698         dst_wire->_opcodes.reserve(src_wire->_opcodes.size());
699         dst_wire->_opcodes = src_wire->_opcodes;
700         dst_wire->_data.reserve(src_wire->_data.size());
701         dst_wire->_data = src_wire->_data;
702         fixWire(dst_wire->_opcodes,
703                 dst_wire->_data,
704                 src_->getBlock(),
705                 level,
706                 bterm_map);
707       }
708     }
709   }
710 }
711 
fixWire(dbVector<unsigned char> & opcodes,dbVector<int> & data,dbBlock * src,int level,dbProperty * bterm_map)712 void dbFlatten::fixWire(dbVector<unsigned char>& opcodes,
713                         dbVector<int>& data,
714                         dbBlock* src,
715                         int level,
716                         dbProperty* bterm_map)
717 {
718   uint i;
719   uint n = opcodes.size();
720   uint point_cnt = 0;
721   int curX = 0;
722   int curY = 0;
723   std::vector<Point> jct_points;
724   jct_points.resize(opcodes.size());
725 
726   for (i = 0; i < n; ++i) {
727     unsigned char opcode = opcodes[i] & WOP_OPCODE_MASK;
728 
729     switch (opcode) {
730       case WOP_PATH:
731       case WOP_SHORT:
732       case WOP_VWIRE: {
733         point_cnt = 0;
734         break;
735       }
736 
737       case WOP_JUNCTION: {
738         Point p = jct_points[data[i]];
739         curX = p.x();
740         curY = p.y();
741         point_cnt = 0;
742         break;
743       }
744 
745       case WOP_X: {
746         curX = data[i];
747 
748         if (point_cnt != 0) {
749           Point p(curX, curY);
750           jct_points[i] = p;
751           _transform.apply(p);
752           data[i] = p.x();
753         } else {
754           curY = data[++i];
755           Point p(curX, curY);
756           jct_points[i - 1] = p;
757           jct_points[i] = p;
758           _transform.apply(p);
759           data[i - 1] = p.x();
760           data[i] = p.y();
761         }
762 
763         point_cnt++;
764         break;
765       }
766 
767       case WOP_Y: {
768         point_cnt++;
769         curY = data[i];
770         Point p(curX, curY);
771         jct_points[i] = p;
772         _transform.apply(p);
773         data[i] = p.y();
774         break;
775       }
776 
777       case WOP_COLINEAR: {
778         point_cnt++;
779         jct_points[i] = Point(curX, curY);
780         break;
781       }
782 
783       case WOP_VIA: {
784         uint vid = data[i];
785         dbVia* src_via = dbVia::getVia(src, vid);
786         dbVia* dst_via = _via_map[src_via];
787         data[i] = dst_via->getImpl()->getOID();
788         break;
789       }
790 
791       case WOP_ITERM: {
792         dbITerm* src_iterm = dbITerm::getITerm(src, data[i]);
793         /*notice(0, "WOP_ITERM: src_iterm= %d I%d/%s %s\n",
794                 src_iterm->getId(), src_iterm->getInst()->getId(),
795                 src_iterm->getMTerm()->getConstName(),
796            src_iterm->getInst()->getConstName());
797         */
798 
799         // Check for hierarchical iterm, if iterm's block will be flattened then
800         // discard this iterm
801         if (src_iterm->getBTerm()) {
802           // notice(0, "------------------------------> WOP_ITERM:\n");
803           if (level > 1) {
804             opcodes[i] = WOP_NOP;
805             data[i] = 0;
806             break;
807           }
808         }
809 
810         dbInst* src_inst = src_iterm->getInst();
811         dbInst* dst_inst = _inst_map[src_inst];
812         assert(dst_inst);
813         dbMTerm* mterm = src_iterm->getMTerm();
814         dbITerm* dst_iterm = dst_inst->getITerm(mterm);
815         data[i] = dst_iterm->getImpl()->getOID();
816         break;
817       }
818 
819       case WOP_BTERM: {
820         assert(bterm_map == NULL);
821         opcodes[i] = WOP_NOP;
822         data[i] = 0;
823         break;
824       }
825 
826       case WOP_RULE: {
827         if (opcodes[i] & WOP_BLOCK_RULE) {
828           dbTechLayerRule* rule
829               = dbTechLayerRule::getTechLayerRule(src, data[i]);
830           data[i] = _layer_rule_map[rule]->getImpl()->getOID();
831         }
832       }
833     }
834   }
835 }
836 
appendWire(dbVector<unsigned char> & opcodes,dbVector<int> & data,dbWire * dst_)837 void dbFlatten::appendWire(dbVector<unsigned char>& opcodes,
838                            dbVector<int>& data,
839                            dbWire* dst_)
840 {
841   _dbWire* dst = (_dbWire*) dst_;
842 
843   uint sz = dst->_opcodes.size();
844   dst->_opcodes.insert(dst->_opcodes.end(), opcodes.begin(), opcodes.end());
845   dst->_data.insert(dst->_data.end(), data.begin(), data.end());
846 
847   // Fix up the junction-ids
848   int i;
849   int n = dst->_opcodes.size();
850 
851   for (i = sz; i < n; ++i) {
852     unsigned char opcode = dst->_opcodes[i] & WOP_OPCODE_MASK;
853     if ((opcode == WOP_SHORT) || (opcode == WOP_JUNCTION)
854         || (opcode == WOP_VWIRE))
855       dst->_data[i] += sz;
856   }
857 }
858 
copySWires(dbNet * dst,dbNet * src)859 void dbFlatten::copySWires(dbNet* dst, dbNet* src)
860 {
861   dbSet<dbSWire> swires = src->getSWires();
862   dbSet<dbSWire>::iterator itr;
863 
864   for (itr = swires.begin(); itr != swires.end(); ++itr) {
865     dbSWire* src_wire = *itr;
866 
867     if (canCopySWire(src_wire, src->getSigType()))
868       copySWire(dst, src, src_wire);
869   }
870 }
871 
copySWire(dbNet * dst,dbNet * src,dbSWire * src_swire)872 void dbFlatten::copySWire(dbNet* dst, dbNet* src, dbSWire* src_swire)
873 {
874   dbSWire* dst_swire
875       = dbSWire::create(dst, src->getWireType(), src_swire->getShield());
876 
877   dbSet<dbSBox> wires = src_swire->getWires();
878 
879   dbSet<dbSBox>::iterator itr;
880 
881   for (itr = wires.begin(); itr != wires.end(); ++itr) {
882     dbSBox* w = *itr;
883 
884     if (!w->isVia()) {
885       Rect r;
886       w->getBox(r);
887       _transform.apply(r);
888       dbSBox::create(dst_swire,
889                      w->getTechLayer(),
890                      r.xMin(),
891                      r.yMin(),
892                      r.xMax(),
893                      r.yMax(),
894                      w->getWireShapeType());
895     } else {
896       int x, y;
897       w->getViaXY(x, y);
898       Point p(x, y);
899       _transform.apply(p);
900 
901       if (w->getTechVia())
902         dbSBox::create(
903             dst_swire, (dbTechVia*) w, p.x(), p.y(), w->getWireShapeType());
904       else {
905         dbVia* v = _via_map[(dbVia*) w];
906         dbSBox::create(dst_swire, v, p.x(), p.y(), w->getWireShapeType());
907       }
908     }
909   }
910 }
911 
canCopyWire(dbWire *,dbSigType::Value sig_type)912 bool dbFlatten::canCopyWire(dbWire* /* unused: wire_ */,
913                             dbSigType::Value sig_type)
914 {
915   //_dbWire * wire = (_dbWire *) wire_;
916 
917   if (_do_not_copy_power_wires) {
918     if (sig_type == dbSigType::POWER || sig_type == dbSigType::GROUND)
919       return false;
920   }
921 
922   return true;
923 }
924 
canCopySWire(dbSWire * wire_,dbSigType::Value sig_type)925 bool dbFlatten::canCopySWire(dbSWire* wire_, dbSigType::Value sig_type)
926 {
927   _dbSWire* wire = (_dbSWire*) wire_;
928 
929   if (_do_not_copy_power_wires) {
930     if (wire->_flags._wire_type == dbWireType::SHIELD && _copy_shields)
931       return true;
932 
933     if (sig_type == dbSigType::POWER || sig_type == dbSigType::GROUND)
934       return false;
935   }
936 
937   return true;
938 }
939 
copyObstruction(dbBlock * dst_block,dbObstruction * src_)940 void dbFlatten::copyObstruction(dbBlock* dst_block, dbObstruction* src_)
941 {
942   _dbObstruction* src = (_dbObstruction*) src_;
943 
944   dbBox* box = src_->getBBox();
945   Rect r;
946   box->getBox(r);
947   _transform.apply(r);
948 
949   _dbObstruction* dst
950       = (_dbObstruction*) dbObstruction::create(dst_block,
951                                                 box->getTechLayer(),
952                                                 r.xMin(),
953                                                 r.yMin(),
954                                                 r.xMax(),
955                                                 r.yMax(),
956                                                 _inst_map[src_->getInstance()]);
957   dst->_flags = src->_flags;
958   dst->_min_spacing = src->_min_spacing;
959   dst->_effective_width = src->_effective_width;
960 }
961 
copyBlockage(dbBlock * dst_block,dbBlockage * src)962 void dbFlatten::copyBlockage(dbBlock* dst_block, dbBlockage* src)
963 {
964   dbBox* box = src->getBBox();
965   Rect r;
966   box->getBox(r);
967   _transform.apply(r);
968 
969   // dbBlockage * dst = dbBlockage::create( dst_block,
970   dbBlockage::create(dst_block,
971                      r.xMin(),
972                      r.yMin(),
973                      r.xMax(),
974                      r.yMax(),
975                      _inst_map[src->getInstance()]);
976 }
977 
978 //
979 // Copy "src" region of the child_inst to parent_block.
980 //
copyRegion(dbBlock * parent_block,dbInst * child_inst,dbRegion * parent_region,dbRegion * src)981 void dbFlatten::copyRegion(dbBlock* parent_block,
982                            dbInst* child_inst,
983                            dbRegion* parent_region,
984                            dbRegion* src)
985 {
986   std::string name = child_inst->getName();
987   name += _hier_d;
988   name += src->getName();
989 
990   dbRegion* dst;
991 
992   if (parent_region)
993     dst = dbRegion::create(parent_region, name.c_str());
994   else
995     dst = dbRegion::create(parent_block, name.c_str());
996 
997   if (dst == NULL) {
998     // TODO:
999     parent_block->getImpl()->getLogger()->warn(
1000         utl::ODB, 272, "Failed to create region {}", name);
1001     return;
1002   }
1003 
1004   _reg_map[src] = dst;
1005   dst->setRegionType(src->getRegionType());
1006   dst->setInvalid(src->isInvalid());
1007 
1008   dbSet<dbBox> boxes = src->getBoundaries();
1009   dbSet<dbBox>::iterator bitr = boxes.begin();
1010 
1011   for (; bitr != boxes.end(); ++bitr) {
1012     dbBox* box = *bitr;
1013     Rect r;
1014     box->getBox(r);
1015     _transform.apply(r);
1016     dbBox::create(dst, r.xMin(), r.yMin(), r.xMax(), r.yMax());
1017   }
1018 
1019   dbSet<dbInst> insts = src->getRegionInsts();
1020   dbSet<dbInst>::iterator iitr = insts.begin();
1021 
1022   for (; iitr != insts.end(); ++iitr) {
1023     dbInst* inst = *iitr;
1024     dst->addInst(_inst_map[inst]);
1025   }
1026 
1027   dbSet<dbRegion> children = src->getChildren();
1028   dbSet<dbRegion>::iterator citr = children.begin();
1029 
1030   for (; citr != children.end(); ++citr) {
1031     dbRegion* child = *citr;
1032     copyRegion(parent_block, child_inst, dst, child);
1033   }
1034 }
1035 
copyNonDefaultRule(dbBlock * parent,dbInst * child_inst,dbTechNonDefaultRule * src_rule)1036 dbTechNonDefaultRule* dbFlatten::copyNonDefaultRule(
1037     dbBlock* parent,
1038     dbInst* child_inst,
1039     dbTechNonDefaultRule* src_rule)
1040 {
1041   std::string name = child_inst->getName();
1042   name += _hier_d;
1043   name += src_rule->getName();
1044 
1045   dbTechNonDefaultRule* dst_rule
1046       = dbTechNonDefaultRule::create(parent, name.c_str());
1047 
1048   if (dst_rule == NULL)
1049     return NULL;
1050 
1051   dst_rule->setHardSpacing(src_rule->getHardSpacing());
1052 
1053   std::vector<dbTechVia*> vias;
1054   src_rule->getUseVias(vias);
1055 
1056   std::vector<dbTechVia*>::iterator vitr;
1057 
1058   for (vitr = vias.begin(); vitr != vias.end(); ++vitr)
1059     dst_rule->addUseVia(*vitr);
1060 
1061   std::vector<dbTechViaGenerateRule*> rules;
1062   src_rule->getUseViaRules(rules);
1063 
1064   std::vector<dbTechViaGenerateRule*>::iterator ritr;
1065 
1066   for (ritr = rules.begin(); ritr != rules.end(); ++ritr)
1067     dst_rule->addUseViaRule(*ritr);
1068 
1069   dbTech* tech = parent->getDb()->getTech();
1070   dbSet<dbTechLayer> layers = tech->getLayers();
1071   dbSet<dbTechLayer>::iterator layitr;
1072 
1073   for (layitr = layers.begin(); layitr != layers.end(); ++layitr) {
1074     dbTechLayer* layer = *layitr;
1075     int count;
1076 
1077     if (src_rule->getMinCuts(layer, count))
1078       dst_rule->setMinCuts(layer, count);
1079   }
1080 
1081   std::vector<dbTechLayerRule*> layer_rules;
1082   src_rule->getLayerRules(layer_rules);
1083 
1084   std::vector<dbTechLayerRule*>::iterator layer_rules_itr;
1085 
1086   for (layer_rules_itr = layer_rules.begin();
1087        layer_rules_itr != layer_rules.end();
1088        ++layer_rules_itr) {
1089     dbTechLayerRule* src_lay_rule = *layer_rules_itr;
1090     dbTechLayerRule* dst_lay_rule
1091         = dbTechLayerRule::create(src_rule, src_lay_rule->getLayer());
1092     _layer_rule_map[src_lay_rule] = dst_lay_rule;
1093 
1094     dst_lay_rule->setWidth(src_lay_rule->getWidth());
1095     dst_lay_rule->setSpacing(src_lay_rule->getSpacing());
1096     dst_lay_rule->setWireExtension(src_lay_rule->getWireExtension());
1097   }
1098 
1099   return dst_rule;
1100 }
createParentCapNode(dbCapNode * node,dbNet * dstNet)1101 bool dbFlatten::createParentCapNode(dbCapNode* node, dbNet* dstNet)
1102 {
1103   bool foreign = false;
1104 
1105   debugPrint(node->getImpl()->getLogger(),
1106              utl::ODB,
1107              "FLATTEN",
1108              3,
1109              "Cap {} num {}",
1110              node->getId(),
1111              node->getNode());
1112 
1113   dbCapNode* cap = NULL;
1114   if (!node->isBTerm()) {  //
1115     cap = dbCapNode::create(dstNet, 0, foreign);
1116     _node_map[node->getId()] = cap->getId();
1117   }
1118   if (node->isInternal()) {  //
1119     cap->setInternalFlag();
1120     uint nodeNum = _shape_rc_map[node->getNode()];
1121     cap->setNode(nodeNum);
1122     debugPrint(node->getImpl()->getLogger(),
1123                utl::ODB,
1124                "FLATTEN",
1125                3,
1126                "\t--> {}     {}",
1127                cap->getId(),
1128                cap->getNode());
1129   } else if (node->isITerm()) {  //
1130     dbITerm* src_iterm = node->getITerm();
1131     dbInst* src_inst = src_iterm->getInst();
1132 
1133     dbInst* dst_inst = _inst_map[src_inst];
1134     assert(dst_inst);
1135     dbMTerm* mterm = src_iterm->getMTerm();
1136     dbITerm* dst_iterm = dst_inst->getITerm(mterm);
1137     cap->setNode(dst_iterm->getId());
1138     cap->setITermFlag();
1139     debugPrint(node->getImpl()->getLogger(),
1140                utl::ODB,
1141                "FLATTEN",
1142                3,
1143                "\t--> {}     {}",
1144                cap->getId(),
1145                cap->getNode());
1146   } else if (node->isBTerm()) {  //
1147 
1148     dbBTerm* bterm = node->getBTerm();
1149     dbITerm* iterm = bterm->getITerm();
1150     uint parentId = adjustParentNode2(dstNet, iterm->getId());
1151     _node_map[node->getId()] = parentId;
1152 
1153     debugPrint(node->getImpl()->getLogger(),
1154                utl::ODB,
1155                "FLATTEN",
1156                3,
1157                "\t\tG BTerm {} --> {} <-- {} ==> {} {}",
1158                node->getId(),
1159                bterm->getConstName(),
1160                iterm->getId(),
1161                _node_map[node->getId()],
1162                parentId);
1163   }
1164   return true;
1165 }
adjustParentNode2(dbNet * dstNet,uint srcTermId)1166 uint dbFlatten::adjustParentNode2(dbNet* dstNet, uint srcTermId)
1167 {
1168   dbSet<dbCapNode> capNodes = dstNet->getCapNodes();
1169   dbSet<dbCapNode>::iterator cap_node_itr = capNodes.begin();
1170   for (; cap_node_itr != capNodes.end(); ++cap_node_itr) {
1171     dbCapNode* node = *cap_node_itr;
1172     if (!node->isITerm())
1173       continue;
1174 
1175     uint nodeNum = node->getNode();
1176     dbITerm* iterm = node->getITerm();
1177     if (iterm->getId() != srcTermId)
1178       continue;
1179 
1180     uint jid = node->getShapeId();
1181     debugPrint(node->getImpl()->getLogger(),
1182                utl::ODB,
1183                "FLATTEN",
1184                3,
1185                "\tadjustParentNode {} J{} N{} srcTermId={}",
1186                node->getId(),
1187                jid,
1188                nodeNum,
1189                srcTermId);
1190 
1191     node->resetITermFlag();
1192     node->setInternalFlag();
1193 
1194     node->setNode(jid);
1195 
1196     return node->getId();
1197   }
1198   return 0;
1199 }
checkNode(dbCapNode * src,uint srcTermId)1200 dbCapNode* dbFlatten::checkNode(dbCapNode* src, uint srcTermId)
1201 {
1202   if (src == NULL)
1203     return NULL;
1204   if (!src->isITerm())
1205     return NULL;
1206 
1207   debugPrint(src->getImpl()->getLogger(),
1208              utl::ODB,
1209              "FLATTEN",
1210              3,
1211              "\tcheckNode node={} i{} rcTermId={}",
1212              src->getId(),
1213              src->getITerm()->getId(),
1214              srcTermId);
1215 
1216   if (src->getITerm()->getId() == srcTermId)
1217     return src;
1218 
1219   return NULL;
1220 }
adjustParentNode(dbNet * dstNet,uint srcTermId)1221 uint dbFlatten::adjustParentNode(dbNet* dstNet, uint srcTermId)
1222 {
1223   dbSet<dbRSeg> rsegs = dstNet->getRSegs();
1224   dbSet<dbRSeg>::iterator rseg_itr = rsegs.begin();
1225   for (; rseg_itr != rsegs.end(); ++rseg_itr) {
1226     dbRSeg* rseg = *rseg_itr;
1227 
1228     uint jid = rseg->getShapeId();
1229     debugPrint(dstNet->getImpl()->getLogger(),
1230                utl::ODB,
1231                "FLATTEN",
1232                3,
1233                "\tadjustParentNode J{} rseg{} {} {} srcTermId={}",
1234                jid,
1235                rseg->getId(),
1236                rseg->getSourceNode(),
1237                rseg->getTargetNode(),
1238                srcTermId);
1239     if ((rseg->getSourceNode() > 0) && (rseg->getTargetNode() > 0))
1240       continue;
1241     dbCapNode* src = rseg->getSourceCapNode();
1242     dbCapNode* tgt = rseg->getTargetCapNode();
1243 
1244     dbCapNode* node = checkNode(src, srcTermId);
1245     if (node == NULL) {
1246       node = checkNode(tgt, srcTermId);
1247       if (node == NULL)
1248         continue;
1249     }
1250 
1251     // uint jid= rseg->getShapeId();
1252 
1253     debugPrint(dstNet->getImpl()->getLogger(),
1254                utl::ODB,
1255                "FLATTEN",
1256                3,
1257                "\tadjustParentNode rseg{} J{} {} {} srcTermId={}",
1258                rseg->getId(),
1259                jid,
1260                src->getId(),
1261                tgt->getId(),
1262                srcTermId);
1263 
1264     node->resetITermFlag();
1265     node->setInternalFlag();
1266 
1267     node->setNode(jid);
1268 
1269     return node->getId();
1270   }
1271   return 0;
1272 }
1273 
createTop1stRseg(dbNet *,dbNet * dst)1274 void dbFlatten::createTop1stRseg(dbNet* /* unused: src */, dbNet* dst)
1275 {
1276   if (dst->getWire() != NULL)
1277     return;
1278 
1279   dbCapNode* cap = dbCapNode::create(dst, 0, /*_foreign*/ false);
1280   // cap->setNode(iterm->getId());
1281   cap->setInternalFlag();
1282   dbRSeg* rc = dbRSeg::create(dst, 0, 0, 0, true);
1283   rc->setTargetNode(cap->getId());
1284 }
1285 
createCapNodes(dbNet * src,dbNet * dst,bool noDstWires)1286 uint dbFlatten::createCapNodes(dbNet* src, dbNet* dst, bool noDstWires)
1287 {
1288   _shape_rc_map.clear();
1289   mapOld2newIds(dst->getWire(), NULL);
1290 
1291   if (noDstWires)
1292     createTop1stRseg(src, dst);
1293 
1294   // uint maxCap= dst->maxInternalCapNum()+1;
1295 
1296   debugPrint(src->getImpl()->getLogger(),
1297              utl::ODB,
1298              "FLATTEN",
1299              3,
1300              "\tCapNodes: {} {}",
1301              src->getConstName(),
1302              dst->getConstName());
1303 
1304   uint gCnt = 0;
1305   dbSet<dbCapNode> capNodes = src->getCapNodes();
1306   dbSet<dbCapNode>::iterator cap_node_itr = capNodes.begin();
1307   for (; cap_node_itr != capNodes.end(); ++cap_node_itr) {
1308     dbCapNode* node = *cap_node_itr;
1309 
1310     gCnt += createParentCapNode(node, dst);
1311   }
1312   return gCnt;
1313 }
1314 
setCorrectRsegIds(dbNet * dst)1315 uint dbFlatten::setCorrectRsegIds(dbNet* dst)
1316 {
1317   dbWire* wire = dst->getWire();
1318 
1319   dbSet<dbRSeg> rsegs = dst->getRSegs();
1320 
1321   uint rCnt = 0;
1322   dbSet<dbRSeg>::iterator rseg_itr = rsegs.begin();
1323   for (; rseg_itr != rsegs.end(); ++rseg_itr) {
1324     dbRSeg* rseg = *rseg_itr;
1325 
1326     uint sid = rseg->getShapeId();
1327     if (sid == 0) {
1328       dst->getImpl()->getLogger()->warn(utl::ODB,
1329                                         27,
1330                                         "rsegId {} has zero shape : {}",
1331                                         rseg->getId(),
1332                                         dst->getConstName());
1333       continue;
1334     }
1335     if (!rseg->getTargetCapNode()->isInternal())
1336       continue;
1337 
1338     int rsegId;
1339     wire->getProperty(sid, rsegId);
1340     if (rsegId > 0)
1341       continue;
1342     rCnt++;
1343     // notice(0, "old %d new %d\n", rsegId, rseg->getId());
1344     wire->setProperty(sid, rseg->getId());
1345   }
1346   return rCnt;
1347 }
createRSegs(dbNet * src,dbNet * dst)1348 uint dbFlatten::createRSegs(dbNet* src, dbNet* dst)
1349 {
1350   debugPrint(src->getImpl()->getLogger(),
1351              utl::ODB,
1352              "FLATTEN",
1353              18,
1354              "\tRSegs: {} {}",
1355              src->getConstName(),
1356              dst->getConstName());
1357 
1358   dbBlock* block = dst->getBlock();
1359   // extMain::printRSegs(parentNet);
1360 
1361   dbSet<dbRSeg> rsegs = src->getRSegs();
1362 
1363   uint rCnt = 0;
1364   dbSet<dbRSeg>::iterator rseg_itr = rsegs.begin();
1365   for (; rseg_itr != rsegs.end(); ++rseg_itr) {
1366     dbRSeg* rseg = *rseg_itr;
1367 
1368     // int x, y;
1369     // TODO rseg->getCoords(x, y);
1370     // TODO uint pathDir= rseg->pathLowToHigh() ? 0 : 1;
1371     dbRSeg* rc = dbRSeg::create(dst, 0, 0, 0, true);
1372 
1373     uint tgtId = rseg->getTargetNode();
1374     uint srcId = rseg->getSourceNode();
1375 
1376     rc->setSourceNode(_node_map[srcId]);
1377     rc->setTargetNode(_node_map[tgtId]);
1378 
1379     for (int corner = 0; corner < block->getCornerCount(); corner++) {
1380       double res = rseg->getResistance(corner);
1381       double cap = rseg->getCapacitance(corner);
1382 
1383       rc->setResistance(res, corner);
1384       rc->setCapacitance(cap, corner);
1385       debugPrint(src->getImpl()->getLogger(),
1386                  utl::ODB,
1387                  "FLATTEN",
1388                  18,
1389                  "\t\tsrc:{}->{} - tgt:{}->{} - {}  {}",
1390                  srcId,
1391                  _node_map[srcId],
1392                  tgtId,
1393                  _node_map[tgtId],
1394                  res,
1395                  cap);
1396     }
1397     rCnt++;
1398   }
1399   setCorrectRsegIds(dst);
1400   return rCnt;
1401 }
printRSegs(FILE * fp,dbNet * net)1402 uint dbFlatten::printRSegs(FILE* fp, dbNet* net)
1403 {
1404   if (fp == NULL)
1405     net->getImpl()->getLogger()->info(
1406         utl::ODB, 28, "\t\t\tprintRSegs: {}", net->getConstName());
1407   else
1408     fprintf(fp, "\t\t\tprintRSegs: %s\n", net->getConstName());
1409 
1410   dbSet<dbRSeg> rsegs = net->getRSegs();
1411 
1412   uint rCnt = 0;
1413   dbSet<dbRSeg>::iterator rseg_itr = rsegs.begin();
1414   for (; rseg_itr != rsegs.end(); ++rseg_itr) {
1415     dbRSeg* rseg = *rseg_itr;
1416 
1417     if (fp == NULL)
1418       net->getImpl()->getLogger()->info(utl::ODB,
1419                                         29,
1420                                         "\t\t\t\t\trsegId: {} J{} -- ",
1421                                         rseg->getId(),
1422                                         rseg->getShapeId());
1423     else
1424       fprintf(fp,
1425               "\t\t\t\t\trsegId: %d J%d -- ",
1426               rseg->getId(),
1427               rseg->getShapeId());
1428 
1429     dbCapNode* src = rseg->getSourceCapNode();
1430     if (fp == NULL) {
1431       if (src == NULL)
1432         net->getImpl()->getLogger()->info(utl::ODB, 30, " 0 --");
1433       else
1434         net->getImpl()->getLogger()->info(utl::ODB,
1435                                           31,
1436                                           " {} I{} B{} -- ",
1437                                           src->getNode(),
1438                                           src->isITerm(),
1439                                           src->isBTerm());
1440     } else {
1441       if (src == NULL)
1442         fprintf(fp, " 0 --");
1443       else
1444         fprintf(fp,
1445                 " %d I%d B%d -- ",
1446                 src->getNode(),
1447                 src->isITerm(),
1448                 src->isBTerm());
1449     }
1450     dbCapNode* tgt = rseg->getTargetCapNode();
1451     if (fp == NULL) {
1452       if (tgt == NULL)
1453         net->getImpl()->getLogger()->info(utl::ODB, 32, " 0");
1454       else
1455         net->getImpl()->getLogger()->info(utl::ODB,
1456                                           33,
1457                                           " {} I{} B{}",
1458                                           tgt->getNode(),
1459                                           tgt->isITerm(),
1460                                           tgt->isBTerm());
1461 
1462     } else {
1463       if (tgt == NULL)
1464         fprintf(fp, " 0\n");
1465       else
1466         fprintf(fp,
1467                 " %d I%d B%d\n",
1468                 tgt->getNode(),
1469                 tgt->isITerm(),
1470                 tgt->isBTerm());
1471     }
1472     rCnt++;
1473   }
1474   return rCnt;
1475 }
1476 }  // namespace odb
1477