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 <dbExtControl.h>
34 #include <math.h>
35 
36 #include <algorithm>
37 
38 #include "parse.h"
39 #include "rcx/extRCap.h"
40 #include "rcx/extSpef.h"
41 #include "utl/Logger.h"
42 
43 //#ifdef _WIN32
44 #define ATH__fprintf fprintf
45 #define ATH__fopen fopen
46 #define ATH__fclose fclose
47 //#endif
48 
49 namespace rcx {
50 
51 using utl::RCX;
52 
writeHierInstNameMap()53 uint extSpef::writeHierInstNameMap() {
54   odb::dbSet<odb::dbInst> insts = _block->getInsts();
55   odb::dbSet<odb::dbInst>::iterator itr;
56 
57   uint instCnt = 0;
58   for (itr = insts.begin(); itr != insts.end(); ++itr) {
59     odb::dbInst* inst = *itr;
60     odb::dbBlock* child = inst->getChild();
61 
62     if (child == NULL)
63       continue;
64 
65     odb::dbIntProperty::create(child, "_instSpefMapBase", _baseNameMap);
66     int baseMapId = extSpef::getIntProperty(child, "_instSpefMapBase");
67     debugPrint(logger_, RCX, "hierspef", 1,
68                "[HEXT:S]"
69                "\ninstMapBase {} : {}  {}",
70                baseMapId, child->getConstName(), inst->getConstName());
71 
72     uint mapId = 0;
73     odb::dbSet<odb::dbInst> binsts = child->getInsts();
74     odb::dbSet<odb::dbInst>::iterator bitr;
75     for (bitr = binsts.begin(); bitr != binsts.end(); ++bitr) {
76       odb::dbInst* ii = *bitr;
77 
78       mapId = _baseNameMap + ii->getId();
79 
80       char* nname = (char*)ii->getConstName();
81       char* nname1 = tinkerSpefName(nname);
82       ATH__fprintf(_outFP, "*%d %s/%s\n", mapId, inst->getConstName(), nname1);
83       debugPrint(logger_, RCX, "hierspef", 1, "[HEXT:S]", "\t{} {}/{}", mapId,
84                  inst->getConstName(), nname1);
85 
86       instCnt++;
87     }
88     _baseNameMap = mapId;
89     debugPrint(logger_, RCX, "hierspef", 1,
90                "[HEXT:S]"
91                "END_MAP {} inames : {}\n",
92                instCnt, child->getConstName());
93   }
94   return instCnt;
95 }
getIntProperty(odb::dbBlock * block,const char * name)96 int extSpef::getIntProperty(odb::dbBlock* block, const char* name) {
97   odb::dbProperty* p = odb::dbProperty::find(block, name);
98 
99   if (p == NULL)
100     return 0;
101 
102   odb::dbIntProperty* ip = (odb::dbIntProperty*)p;
103   return ip->getValue();
104 }
105 
writeHierNetNameMap()106 uint extSpef::writeHierNetNameMap() {
107   odb::dbSet<odb::dbInst> insts = _block->getInsts();
108   odb::dbSet<odb::dbInst>::iterator itr;
109 
110   uint netCnt = 0;
111   for (itr = insts.begin(); itr != insts.end(); ++itr) {
112     odb::dbInst* inst = *itr;
113     odb::dbBlock* child = inst->getChild();
114 
115     if (child == NULL)
116       continue;
117 
118     odb::dbIntProperty::create(child, "_netSpefMapBase", _baseNameMap);
119     int baseMapId = extSpef::getIntProperty(child, "_netSpefMapBase");
120 
121     debugPrint(logger_, RCX, "hierspef", 1,
122                "[HEXT:S]"
123                "\nnetMapBase {} : {}  {}",
124                baseMapId, child->getConstName(), inst->getConstName());
125 
126     uint mapId = 0;
127     odb::dbSet<odb::dbNet> nets = child->getNets();
128     odb::dbSet<odb::dbNet>::iterator bitr;
129     for (bitr = nets.begin(); bitr != nets.end(); ++bitr) {
130       odb::dbNet* ii = *bitr;
131 
132       if (ii->getBTermCount() > 0)
133         continue;
134 
135       mapId = _baseNameMap + ii->getId();
136 
137       char* nname = (char*)ii->getConstName();
138       char* nname1 = tinkerSpefName(nname);
139       ATH__fprintf(_outFP, "*%d %s/%s\n", mapId, inst->getConstName(), nname1);
140       debugPrint(logger_, RCX, "hierspef", 1, "[HEXT:S]", "\t{} {}/{}", mapId,
141                  inst->getConstName(), nname1);
142       netCnt++;
143     }
144     _baseNameMap = mapId;
145     debugPrint(logger_, RCX, "hierspef", 1,
146                "[HEXT:S]"
147                "\tNET_MAP_END ({} internal nets) : {}\n",
148                netCnt, child->getConstName());
149   }
150   // OPTIMIZE this ; have to do due to 1st "null" rseg;
151   // if not, appending rsegs creates a havoc!
152 
153   odb::dbSet<odb::dbNet> topnets = _block->getNets();
154   odb::dbSet<odb::dbNet>::iterator bitr;
155   for (bitr = topnets.begin(); bitr != topnets.end(); ++bitr) {
156     odb::dbNet* ii = *bitr;
157 
158     // extMain::printRSegs(ii);
159     odb::dbSet<odb::dbRSeg> rSet = ii->getRSegs();
160     rSet.reverse();
161     // extMain::printRSegs(ii);
162   }
163   return netCnt;
164 }
markCCsegs(odb::dbBlock * blk,bool flag)165 uint extMain::markCCsegs(odb::dbBlock* blk, bool flag) {
166   odb::dbSet<odb::dbCCSeg> ccs = blk->getCCSegs();
167   odb::dbSet<odb::dbCCSeg>::iterator ccitr;
168   for (ccitr = ccs.begin(); ccitr != ccs.end(); ++ccitr) {
169     odb::dbCCSeg* cc = *ccitr;
170     cc->setMark(flag);
171   }
172   return ccs.size();
173 }
174 
addRCtoTop(odb::dbBlock * blk,bool write_spef)175 uint extMain::addRCtoTop(odb::dbBlock* blk, bool write_spef) {
176   logger_->info(RCX, 232, "Merging Parasitics for Block {} : {} Into parent {}",
177                 blk->getConstName(), blk->getParentInst()->getConstName(),
178                 _block->getConstName());
179 
180   // blk->getParent()->getConstName()
181 
182   int netBaseMapId = extSpef::getIntProperty(blk, "_netSpefMapBase");
183   int instBaseMapId = extSpef::getIntProperty(blk, "_instSpefMapBase");
184   _spef->setHierBaseNameMap(instBaseMapId, netBaseMapId);
185 
186   debugPrint(logger_, RCX, "hierspef", 1, "[HEXT:F]",
187              "\n\t_netSpefMapBase= {} _instSpefMapBase= {}", netBaseMapId,
188              instBaseMapId);
189 
190   odb::dbSet<odb::dbCapNode> allcapnodes = blk->getCapNodes();
191   uint blockCapSize = allcapnodes.size();
192 
193   uint* capNodeMap = new uint[2 * blockCapSize + 1];
194 
195   bool foreign = false;
196   uint spefCnt = 0;
197   uint flatCnt = 0;
198   uint gCnt = 0;
199   uint rCnt = 0;
200   uint ccCnt = 0;
201   double resBound = 0.0;
202   uint dbg = 0;
203 
204   odb::dbNet* topDummyNodeNet = _block->findNet("dummy_sub_block_cap_nodes");
205   if (topDummyNodeNet == NULL)
206     topDummyNodeNet = odb::dbNet::create(_block, "dummy_sub_block_cap_nodes");
207 
208   odb::dbSet<odb::dbNet> nets = blk->getNets();
209   odb::dbSet<odb::dbNet>::iterator bitr;
210   for (bitr = nets.begin(); bitr != nets.end(); ++bitr) {
211     odb::dbNet* net = *bitr;
212 
213     if (!net->setIOflag())
214       continue;
215 
216     odb::dbBTerm* bterm = net->get1stBTerm();
217     odb::dbITerm* iterm = bterm->getITerm();
218     odb::dbNet* parentNet = iterm->getNet();
219     if (parentNet == NULL) {
220       logger_->warn(RCX, 408, "Null parent[{}] net : {}", net->getBTermCount(),
221                     net->getConstName());
222       continue;
223     }
224 
225     gCnt += createCapNodes(net, parentNet, capNodeMap, instBaseMapId);
226     rCnt += createRSegs(net, parentNet, capNodeMap);
227     flatCnt++;
228   }
229   markCCsegs(blk, false);
230   for (bitr = nets.begin(); bitr != nets.end(); ++bitr) {
231     odb::dbNet* net = *bitr;
232     if (!net->isIO())
233       continue;
234 
235     odb::dbBTerm* bterm = net->get1stBTerm();
236     odb::dbITerm* iterm = bterm->getITerm();
237     odb::dbNet* parentNet = iterm->getNet();
238     if (parentNet == NULL) {
239       logger_->warn(RCX, 233, "Null parent[{}] net : {}", net->getBTermCount(),
240                     net->getConstName());
241       continue;
242     }
243 
244     ccCnt += createCCsegs(net, parentNet, topDummyNodeNet, capNodeMap,
245                           instBaseMapId);
246   }
247   markCCsegs(blk, false);
248 
249   _spef->setBlock(blk);
250   for (bitr = nets.begin(); bitr != nets.end(); ++bitr) {
251     odb::dbNet* net = *bitr;
252     if (net->isIO())
253       continue;
254 
255     // extMain::printRSegs(net);
256     if (write_spef)
257       spefCnt += _spef->writeHierNet(net, resBound, dbg);
258   }
259   _spef->setBlock(_block);
260   logger_->info(RCX, 235,
261                 "{} internal {} IO nets {} gCaps {} rSegs {} ccCaps : {}",
262                 spefCnt, flatCnt, gCnt, rCnt, ccCnt, blk->getConstName());
263 
264   delete[] capNodeMap;
265   return flatCnt + spefCnt;
266 }
adjustParentNode(odb::dbNet * net,odb::dbITerm * from_child_iterm,uint node_num)267 uint extMain::adjustParentNode(odb::dbNet* net, odb::dbITerm* from_child_iterm,
268                                uint node_num) {
269   odb::dbSet<odb::dbCapNode> capNodes = net->getCapNodes();
270   odb::dbSet<odb::dbCapNode>::iterator cap_node_itr = capNodes.begin();
271   for (; cap_node_itr != capNodes.end(); ++cap_node_itr) {
272     odb::dbCapNode* node = *cap_node_itr;
273     if (!node->isITerm())
274       continue;
275     odb::dbITerm* iterm = node->getITerm();
276     if (iterm != from_child_iterm)
277       continue;
278 
279     node->resetITermFlag();
280     node->setInternalFlag();
281 
282     node->setNode(node_num);
283 
284     return node->getId();
285   }
286   return 0;
287 }
288 
createParentCapNode(odb::dbCapNode * node,odb::dbNet * parentNet,uint nodeNum,uint * capNodeMap,uint baseNum)289 bool extMain::createParentCapNode(odb::dbCapNode* node, odb::dbNet* parentNet,
290                                   uint nodeNum, uint* capNodeMap,
291                                   uint baseNum) {
292   bool foreign = false;
293   char buf[1024];
294 
295   odb::dbCapNode* cap = NULL;
296   if (!node->isBTerm()) {  //
297     cap = odb::dbCapNode::create(parentNet, nodeNum, foreign);
298     capNodeMap[node->getId()] = cap->getId();
299   }
300   if (node->isInternal()) {  //
301     cap->setInternalFlag();
302 
303     debugPrint(logger_, RCX, "hierspef", 1,
304                "[HEXT:C]"
305                "\t\tG intrn {} --> {}",
306                node->getId(), capNodeMap[node->getId()]);
307   } else if (node->isITerm()) {  //
308     odb::dbITerm* iterm = node->getITerm();
309     odb::dbInst* inst = iterm->getInst();
310     uint instId = inst->getId();
311     sprintf(buf, "*%d%s%s", baseNum + instId, _spef->getDelimeter(),
312             iterm->getMTerm()->getConstName());
313 
314     odb::dbStringProperty::create(cap, "_inode", buf);
315     cap->setNode(baseNum + instId);  // so there is some value
316     cap->setNameFlag();
317 
318     debugPrint(logger_, RCX, "hierspef", 1,
319                "[HEXT:C]"
320                "\t\tG ITerm {} --> {} : {}",
321                node->getId(), capNodeMap[node->getId()], buf);
322   } else if (node->isBTerm()) {  //
323 
324     odb::dbBTerm* bterm = node->getBTerm();
325     odb::dbITerm* iterm = bterm->getITerm();
326     uint parentId = adjustParentNode(parentNet, iterm, nodeNum);
327     capNodeMap[node->getId()] = parentId;
328 
329     debugPrint(logger_, RCX, "hierspef", 1,
330                "[HEXT:C]"
331                "\t\tG BTerm {} --> {} : {}",
332                node->getId(), parentId, nodeNum);
333   }
334   return true;
335 }
createTop1stRseg(odb::dbNet * net,odb::dbNet * parentNet)336 void extMain::createTop1stRseg(odb::dbNet* net, odb::dbNet* parentNet) {
337   if (parentNet->getWire() != NULL)
338     return;
339 
340   odb::dbBTerm* bterm = net->get1stBTerm();
341   odb::dbITerm* iterm = bterm->getITerm();
342 
343   odb::dbCapNode* cap =
344       odb::dbCapNode::create(parentNet, 0, /*_foreign*/ false);
345   cap->setNode(iterm->getId());
346   cap->setITermFlag();
347   odb::dbRSeg* rc = odb::dbRSeg::create(parentNet, 0, 0, 0, true);
348   rc->setTargetNode(cap->getId());
349 }
createCapNodes(odb::dbNet * net,odb::dbNet * parentNet,uint * capNodeMap,uint baseNum)350 uint extMain::createCapNodes(odb::dbNet* net, odb::dbNet* parentNet,
351                              uint* capNodeMap, uint baseNum) {
352   createTop1stRseg(net, parentNet);
353 
354   // have to improve for performance
355   uint maxCap = parentNet->maxInternalCapNum() + 1;
356   debugPrint(logger_, RCX, "hierspef", 1,
357              "[HEXT:C]"
358              "\n\tCapNodes: maxCap={} : {} {}",
359              maxCap, net->getConstName(), parentNet->getConstName());
360 
361   uint gCnt = 0;
362   bool foreign = false;
363   char buf[1024];
364   odb::dbSet<odb::dbCapNode> capNodes = net->getCapNodes();
365   odb::dbSet<odb::dbCapNode>::iterator cap_node_itr = capNodes.begin();
366   for (; cap_node_itr != capNodes.end(); ++cap_node_itr) {
367     odb::dbCapNode* node = *cap_node_itr;
368 
369     uint nodeNum = maxCap++;
370 
371     gCnt += createParentCapNode(node, parentNet, nodeNum, capNodeMap, baseNum);
372   }
373   return gCnt;
374 }
printRSegs(odb::dbNet * net,Logger * logger)375 uint extMain::printRSegs(odb::dbNet* net, Logger* logger) {
376   logger->info(RCX, 236, "\t\t\tprintRSegs: {}", net->getConstName());
377   odb::dbSet<odb::dbRSeg> rsegs = net->getRSegs();
378   uint rsize = rsegs.size();
379 
380   uint rCnt = 0;
381   odb::dbSet<odb::dbRSeg>::iterator rseg_itr = rsegs.begin();
382   for (; rseg_itr != rsegs.end(); ++rseg_itr) {
383     odb::dbRSeg* rseg = *rseg_itr;
384 
385     logger->info(RCX, 234, "\t\t\t\t\trsegId: {} -- {} {}", rseg->getId(),
386                  rseg->getSourceNode(), rseg->getTargetNode());
387     rCnt++;
388   }
389   return rCnt;
390 }
createRSegs(odb::dbNet * net,odb::dbNet * parentNet,uint * capNodeMap)391 uint extMain::createRSegs(odb::dbNet* net, odb::dbNet* parentNet,
392                           uint* capNodeMap) {
393   debugPrint(logger_, RCX, "hierspef", 1,
394              "[HEXT:R]"
395              "\n\tRSegs: {} {}",
396              net->getConstName(), parentNet->getConstName());
397 
398   // extMain::printRSegs(parentNet);
399 
400   odb::dbSet<odb::dbRSeg> rsegs = net->getRSegs();
401   uint rsize = rsegs.size();
402 
403   uint rCnt = 0;
404   odb::dbSet<odb::dbRSeg>::iterator rseg_itr = rsegs.begin();
405   for (; rseg_itr != rsegs.end(); ++rseg_itr) {
406     odb::dbRSeg* rseg = *rseg_itr;
407 
408     int x, y;
409     rseg->getCoords(x, y);
410     uint pathDir = rseg->pathLowToHigh() ? 0 : 1;
411     odb::dbRSeg* rc = odb::dbRSeg::create(parentNet, x, y, pathDir, true);
412 
413     uint tgtId = rseg->getTargetNode();
414     uint srcId = rseg->getSourceNode();
415 
416     rc->setSourceNode(capNodeMap[srcId]);
417     rc->setTargetNode(capNodeMap[tgtId]);
418 
419     for (uint corner = 0; corner < _block->getCornerCount(); corner++) {
420       double res = rseg->getResistance(corner);
421       double cap = rseg->getCapacitance(corner);
422 
423       rc->setResistance(res, corner);
424       rc->setCapacitance(cap, corner);
425       debugPrint(logger_, RCX, "hierspef", 1,
426                  "[HEXT:R]"
427                  "\t\tsrc:{}->{} - tgt:{}->{} - {}  {}",
428                  srcId, capNodeMap[srcId], tgtId, capNodeMap[tgtId], res, cap);
429     }
430     rCnt++;
431   }
432   // extMain::printRSegs(parentNet);
433   /*
434   if (rCnt>0) {
435           odb::dbSet<odb::dbRSeg> rSet= parentNet->getRSegs();
436           //rSet.reverse();
437   }
438   */
439   return rCnt;
440 }
adjustChildNode(odb::dbCapNode * childNode,odb::dbNet * parentNet,uint * capNodeMap)441 void extMain::adjustChildNode(odb::dbCapNode* childNode, odb::dbNet* parentNet,
442                               uint* capNodeMap) {
443   char buf[1024];
444   uint parentId = capNodeMap[childNode->getId()];
445   odb::dbCapNode* parentNode = odb::dbCapNode::getCapNode(_block, parentId);
446 
447   if (childNode->isInternal() || childNode->isBTerm()) {  //
448     childNode->resetInternalFlag();
449     childNode->resetBTermFlag();
450 
451     // spefParentNameId == parent netId (just lucky!!)
452     sprintf(buf, "*%d%s%d", parentNet->getId(), _spef->getDelimeter(),
453             parentNode->getNode());
454 
455     odb::dbStringProperty::create(childNode, "_inode", buf);
456 
457     debugPrint(logger_, RCX, "hierspef", 1,
458                "[HEXT:CC]"
459                "\t\tCC intNode {} --> {} : {}",
460                childNode->getId(), parentId, buf);
461   } else if (childNode->isITerm()) {  //
462     childNode->resetITermFlag();
463 
464     odb::dbStringProperty* p =
465         odb::dbStringProperty::find(parentNode, "_inode");
466     odb::dbStringProperty::create(childNode, "_inode", p->getValue().c_str());
467 
468     debugPrint(logger_, RCX, "hierspef", 1,
469                "[HEXT:CC]"
470                "\t\tCC ITermNode {} --> {} : {}",
471                childNode->getId(), parentId, p->getValue().c_str());
472   }
473   childNode->setNameFlag();
474 }
475 
createCCsegs(odb::dbNet * net,odb::dbNet * parentNet,odb::dbNet * topDummyNet,uint * capNodeMap,uint baseNum)476 uint extMain::createCCsegs(odb::dbNet* net, odb::dbNet* parentNet,
477                            odb::dbNet* topDummyNet, uint* capNodeMap,
478                            uint baseNum) {
479   // IO nets
480 
481   // have to improve for performance
482   uint maxCap = parentNet->maxInternalCapNum() + 1;
483 
484   debugPrint(logger_, RCX, "hierspef", 1,
485              "[HEXT:CC]"
486              "\tCCsegs: maxCap[{}] {} {}",
487              maxCap, net->getConstName(), parentNet->getConstName());
488 
489   odb::dbBlock* pblock = parentNet->getBlock();
490   uint ccCnt = 0;
491 
492   odb::dbSet<odb::dbCapNode> nodeSet = net->getCapNodes();
493   odb::dbSet<odb::dbCapNode>::iterator rc_itr;
494   for (rc_itr = nodeSet.begin(); rc_itr != nodeSet.end(); ++rc_itr) {
495     odb::dbCapNode* srcCapNode = *rc_itr;
496 
497     odb::dbSet<odb::dbCCSeg> ccsegs = srcCapNode->getCCSegs();
498     odb::dbSet<odb::dbCCSeg>::iterator ccseg_itr = ccsegs.begin();
499     for (; ccseg_itr != ccsegs.end(); ++ccseg_itr) {
500       odb::dbCCSeg* cc = *ccseg_itr;
501 
502       if (cc->isMarked())
503         continue;
504 
505       odb::dbCapNode* dstCapNode = cc->getTargetCapNode();
506       if (cc->getSourceCapNode() != srcCapNode) {
507         dstCapNode = cc->getSourceCapNode();
508       }
509       if (!dstCapNode->getNet()->isIO()) {
510         uint nodeNum = maxCap++;
511         createParentCapNode(dstCapNode, topDummyNet, nodeNum, capNodeMap,
512                             baseNum);
513         adjustChildNode(srcCapNode, parentNet, capNodeMap);
514       }
515       uint tId = dstCapNode->getId();
516       uint sId = srcCapNode->getId();
517       uint tgtId = capNodeMap[tId];
518       uint srcId = capNodeMap[sId];
519 
520       odb::dbCapNode* map_tgt = odb::dbCapNode::getCapNode(pblock, tgtId);
521       odb::dbCapNode* map_src = odb::dbCapNode::getCapNode(pblock, srcId);
522 
523       odb::dbCCSeg* ccap = odb::dbCCSeg::create(map_src, map_tgt, false);
524 
525       for (uint corner = 0; corner < _block->getCornerCount(); corner++) {
526         double cap = cc->getCapacitance(corner);
527         ccap->setCapacitance(cap, corner);
528 
529         debugPrint(logger_, RCX, "hierspef", 1,
530                    "[HEXT:C]"
531                    "\t\tCC src:{}->{} tgt:{}->{} CC {:g}\n",
532                    sId, srcId, tId, tgtId, cap);
533       }
534       cc->setMark(true);
535     }
536   }
537   return maxCap;
538 }
539 /*
540 uint extMain::adjustCCsegs(odb::dbNet *net, uint baseNum)
541 {
542         //Internal nets
543 
544         // have to improve for performance
545         uint maxCap= parentNet->maxInternalCapNum()+1;
546 
547         debugPrint(logger_, RCX, "hierspef", 1,
548                "[HEXT:F]"
549                 "\tCCsegs: maxCap[{}] {} {}\n", maxCap,
550                 net->getConstName(), parentNet->getConstName());
551 
552         odb::dbBlock *pblock= parentNet->getBlock();
553         uint ccCnt= 0;
554 
555         odb::dbSet<odb::dbCapNode> nodeSet = net->getCapNodes();
556         odb::dbSet<odb::dbCapNode>::iterator rc_itr;
557         for( rc_itr = nodeSet.begin(); rc_itr != nodeSet.end(); ++rc_itr ) {
558                 odb::dbCapNode *srcCapNode = *rc_itr;
559 
560                 odb::dbSet<odb::dbCCSeg> ccsegs= srcCapNode->getCCSegs();
561                 odb::dbSet<odb::dbCCSeg>::iterator ccseg_itr= ccsegs.begin();
562                 for( ; ccseg_itr != ccsegs.end(); ++ccseg_itr ) {
563                         odb::dbCCSeg *cc= *ccseg_itr;
564 
565                         if (cc->isMarked())
566                                 continue;
567 
568                                 adjustChildNode(srcCapNode, parentNet,
569 capNodeMap); cc->setMark(true);
570                 }
571         }
572         return maxCap;
573 }
574 */
writeDnetHier(uint mapId,double * totCap)575 void extSpef::writeDnetHier(uint mapId, double* totCap) {
576   if (_writeNameMap)
577     ATH__fprintf(_outFP, "\n*D_NET *%d ", mapId);
578   // else
579   // ATH__fprintf(_outFP, "\n*D_NET %s ", tinkerSpefName((char
580   // *)_d_net->getConstName()));
581   writeRCvalue(totCap, _cap_unit);
582   ATH__fprintf(_outFP, "\n");
583 }
584 
writeHierNet(odb::dbNet * net,double resBound,uint dbg)585 bool extSpef::writeHierNet(odb::dbNet* net, double resBound, uint dbg) {
586   _block = net->getBlock();
587   _d_net = net;
588   uint netId = net->getId();
589   _cornerBlock = net->getBlock();
590 
591   _cornersPerBlock = _cornerCnt;
592 
593   // if (_cornerBlock && _cornerBlock!=_block)
594   // net= odb::dbNet::getNet(_cornerBlock, netId);
595 
596   uint minNode;
597   uint capNodeCnt = getMinCapNode(net, &minNode);
598   if (capNodeCnt == 0) {
599     logger_->warn(RCX, 237, "No cap nodes net: {}", net->getConstName());
600     return false;
601   }
602   odb::dbSet<odb::dbRSeg> rcSet = net->getRSegs();
603 
604   _cCnt = 1;
605   // must set at calling _symmetricCCcaps= true; //TODO non symmetric case??
606   // must set at calling _preserveCapValues= false // true only for reading in
607   // SPEF
608 
609   double totCap[5];
610   resetCap(totCap);
611   if (_symmetricCCcaps)
612     addCouplingCaps(net, totCap);
613 
614   _firstCapNode = minNode - 1;
615 
616   reinitCapTable(_nodeCapTable, capNodeCnt + 2);
617 
618   if (_singleP)
619     computeCapsAdd2Target(rcSet, totCap);
620   else
621     computeCaps(rcSet, totCap);
622 
623   debugPrint(logger_, RCX, "hierspef", 1,
624              "[HEXT:S]"
625              "\tDNET *{}-{} {:g} {}\n",
626              _childBlockNetBaseMap + netId, netId, totCap[0],
627              net->getConstName());
628 
629   // netId= _childBlockNetBaseMap+netId;
630   writeDnetHier(_childBlockNetBaseMap + netId, totCap);
631 
632   if (_wConn) {
633     writeKeyword("*CONN");
634     writePorts(net);
635     writeITerms(net);
636   }
637   if (_writingNodeCoords == C_STARRC)
638     writeNodeCoords(netId, rcSet);
639 
640   if (_wCap || _wOnlyCCcap)
641     writeKeyword("*CAP");
642 
643   if (_wCap && !_wOnlyCCcap) {
644     writeCapPorts(net);
645     writeCapITerms(net);
646     writeNodeCaps(net, _childBlockNetBaseMap + netId);
647   }
648 
649   if (_wCap || _wOnlyCCcap)
650     writeSrcCouplingCaps(net);
651 
652   if (_symmetricCCcaps && (_wCap || _wOnlyCCcap))
653     writeTgtCouplingCaps(net);
654 
655   if (_wRes) {
656     writeRes(netId, rcSet);
657   }
658   writeKeyword("*END");
659 
660   odb::dbSet<odb::dbCapNode> nodeSet = net->getCapNodes();
661   odb::dbSet<odb::dbCapNode>::iterator rc_itr;
662   for (rc_itr = nodeSet.begin(); rc_itr != nodeSet.end(); ++rc_itr) {
663     odb::dbCapNode* node = *rc_itr;
664     node->setSortIndex(0);
665   }
666   return true;
667 }
setHierBaseNameMap(uint instBase,uint netBase)668 void extSpef::setHierBaseNameMap(uint instBase, uint netBase) {
669   _childBlockNetBaseMap = netBase;
670   _childBlockInstBaseMap = instBase;
671 }
672 
673 }  // namespace rcx
674