1 /* Authors: Lutong Wang and Bangqi Xu */
2 /*
3  * Copyright (c) 2019, The Regents of the University of California
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *     * Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above copyright
11  *       notice, this list of conditions and the following disclaimer in the
12  *       documentation and/or other materials provided with the distribution.
13  *     * Neither the name of the University nor the
14  *       names of its contributors may be used to endorse or promote products
15  *       derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <omp.h>
30 
31 #include "dr/FlexDR.h"
32 #include "frProfileTask.h"
33 #include "io/io.h"
34 
35 using namespace std;
36 using namespace fr;
37 
38 string netToDebug = "";
39 // copied from FlexDRWorker::initNets_searchRepair_pin2epMap_helper
checkConnectivity_pin2epMap_helper(const frNet * net,const frPoint & bp,frLayerNum lNum,map<frBlockObject *,set<pair<frPoint,frLayerNum>>,frBlockObjectComp> & pin2epMap,bool isPathSeg)40 void FlexDR::checkConnectivity_pin2epMap_helper(
41     const frNet* net,
42     const frPoint& bp,
43     frLayerNum lNum,
44     map<frBlockObject*, set<pair<frPoint, frLayerNum>>, frBlockObjectComp>&
45         pin2epMap,
46     bool isPathSeg)
47 {
48   bool enableOutput = false;
49   // bool enableOutput = true;
50   auto regionQuery = getRegionQuery();
51   frRegionQuery::Objects<frBlockObject> result;
52   // result.clear();
53   //  In PA we may have used NearbyGrid which puts a via outside the pin
54   //  but still overlapping.  So we expand bp to a min-width square when
55   //  searching for the pin shape.
56   auto half_min_width = getTech()->getLayer(lNum)->getMinWidth() / 2;
57   frBox query_box(bp.x() - half_min_width,
58                   bp.y() - half_min_width,
59                   bp.x() + half_min_width,
60                   bp.y() + half_min_width);
61   regionQuery->query(query_box, lNum, result);
62   for (auto& [bx, rqObj] : result) {
63     if (isPathSeg && !bx.contains(bp))
64       continue;
65     if (rqObj->typeId() == frcInstTerm) {
66       auto instTerm = static_cast<frInstTerm*>(rqObj);
67       if (instTerm->getNet() == net) {
68           if (!isPathSeg && !bx.contains(bp) &&
69               !instTerm->hasAccessPoint(bp.x(), bp.y(), lNum))
70               continue;
71         if (enableOutput) {
72           cout << "    found " << instTerm->getName() << "\n";
73         }
74         pin2epMap[rqObj].insert(make_pair(bp, lNum));
75       }
76     } else if (rqObj->typeId() == frcTerm) {
77       if (!isPathSeg && !bx.contains(bp))
78             continue;
79       auto term = static_cast<frTerm*>(rqObj);
80       if (term->getNet() == net) {
81         if (enableOutput) {
82           cout << "    found PIN/" << term->getName() << endl;
83         }
84         pin2epMap[rqObj].insert(make_pair(bp, lNum));
85       }
86     }
87   }
88 }
89 
checkConnectivity_pin2epMap(const frNet * net,const vector<frConnFig * > & netDRObjs,map<frBlockObject *,set<pair<frPoint,frLayerNum>>,frBlockObjectComp> & pin2epMap)90 void FlexDR::checkConnectivity_pin2epMap(
91     const frNet* net,
92     const vector<frConnFig*>& netDRObjs,
93     map<frBlockObject*, set<pair<frPoint, frLayerNum>>, frBlockObjectComp>&
94         pin2epMap)
95 {
96   bool enableOutput = net->getName() == netToDebug;
97   // bool enableOutput = true;
98   if (enableOutput)
99     cout << "pin2epMap\n\n";
100   frPoint bp, ep;
101   set<pair<frPoint, frLayerNum>>
102       extEndPoints;  // to avoid delooping fake planar ep in pin
103   for (auto& connFig : netDRObjs) {
104     if (connFig->typeId() == frcPathSeg) {
105       auto obj = static_cast<frPathSeg*>(connFig);
106       obj->getPoints(bp, ep);
107       frSegStyle style;
108       obj->getStyle(style);
109       auto lNum = obj->getLayerNum();
110       if (enableOutput) {
111         cout << *obj << " layer " << getTech()->getLayer(lNum)->getName()
112              << endl;
113         cout << "  query bp" << endl;
114       }
115       if (style.getBeginStyle() == frEndStyle(frcTruncateEndStyle)) {
116         checkConnectivity_pin2epMap_helper(net, bp, lNum, pin2epMap, true);
117       }
118       if (enableOutput) {
119         cout << "  query ep" << endl;
120       }
121       if (style.getEndStyle() == frEndStyle(frcTruncateEndStyle)) {
122         checkConnectivity_pin2epMap_helper(net, ep, lNum, pin2epMap, true);
123       }
124     }
125   }
126   for (auto& connFig : netDRObjs) {
127     if (connFig->typeId() == frcVia) {
128       auto obj = static_cast<frVia*>(connFig);
129       obj->getOrigin(bp);
130       auto l1Num = obj->getViaDef()->getLayer1Num();
131       auto l2Num = obj->getViaDef()->getLayer2Num();
132       if (enableOutput) {
133         cout << *obj;
134       }
135       if (enableOutput) {
136         cout << "  query pt l1" << endl;
137       }
138       if (obj->isBottomConnected())
139         checkConnectivity_pin2epMap_helper(net, bp, l1Num, pin2epMap, false);
140       if (enableOutput) {
141         cout << "  query pt l2" << endl;
142       }
143       if (obj->isTopConnected())
144         checkConnectivity_pin2epMap_helper(net, bp, l2Num, pin2epMap, false);
145       //} else if (connFig->typeId() == frcPatchWire) {
146       //  ;
147     }
148   }
149 }
150 
checkConnectivity_initDRObjs(const frNet * net,vector<frConnFig * > & netDRObjs)151 void FlexDR::checkConnectivity_initDRObjs(const frNet* net,
152                                           vector<frConnFig*>& netDRObjs)
153 {
154   bool enableOutput = false;
155   // bool enableOutput = true;
156   if (enableOutput)
157     cout << "initDRObjs\n\n";
158   for (auto& uPtr : net->getShapes()) {
159     auto connFig = uPtr.get();
160     if (connFig->typeId() == frcPathSeg) {
161       netDRObjs.push_back(connFig);
162       if (enableOutput) {
163         auto obj = static_cast<frPathSeg*>(connFig);
164         frPoint bp, ep;
165         auto lNum = obj->getLayerNum();
166         obj->getPoints(bp, ep);
167         cout << *obj << " layer " << getTech()->getLayer(lNum)->getName()
168              << endl;
169       }
170     } else {
171       cout << "Error: checkConnectivity_initDRObjs unsupported type" << endl;
172     }
173   }
174   for (auto& uPtr : net->getVias()) {
175     auto connFig = uPtr.get();
176     if (connFig->typeId() == frcVia) {
177       netDRObjs.push_back(connFig);
178       if (enableOutput) {
179         auto obj = static_cast<frVia*>(connFig);
180         frPoint bp;
181         obj->getOrigin(bp);
182         cout << *obj << " layer " << obj->getViaDef()->getName() << endl;
183       }
184     } else {
185       cout << "Error: checkConnectivity_initDRObjs unsupported type" << endl;
186     }
187   }
188 }
189 
checkConnectivity_nodeMap_routeObjEnd(const frNet * net,const vector<frConnFig * > & netRouteObjs,map<pair<frPoint,frLayerNum>,set<int>> & nodeMap)190 void FlexDR::checkConnectivity_nodeMap_routeObjEnd(
191     const frNet* net,
192     const vector<frConnFig*>& netRouteObjs,
193     map<pair<frPoint, frLayerNum>, set<int>>& nodeMap)
194 {
195   bool enableOutput = false;
196   frPoint bp, ep;
197   for (int i = 0; i < (int) netRouteObjs.size(); i++) {
198     auto& connFig = netRouteObjs[i];
199     if (connFig->typeId() == frcPathSeg) {
200       auto obj = static_cast<frPathSeg*>(connFig);
201       obj->getPoints(bp, ep);
202       auto lNum = obj->getLayerNum();
203       nodeMap[make_pair(bp, lNum)].insert(i);
204       nodeMap[make_pair(ep, lNum)].insert(i);
205       if (enableOutput) {
206         cout << "node idx = " << i << ", (" << bp.x() / 2000.0 << ", "
207              << bp.y() / 2000.0 << ") (" << ep.x() / 2000.0 << ", "
208              << ep.y() / 2000.0 << ") " << getTech()->getLayer(lNum)->getName()
209              << endl;
210       }
211     } else if (connFig->typeId() == frcVia) {
212       auto obj = static_cast<frVia*>(connFig);
213       obj->getOrigin(bp);
214       auto l1Num = obj->getViaDef()->getLayer1Num();
215       auto l2Num = obj->getViaDef()->getLayer2Num();
216       nodeMap[make_pair(bp, l1Num)].insert(i);
217       nodeMap[make_pair(bp, l2Num)].insert(i);
218       if (enableOutput) {
219         cout << "node idx = " << i << ", (" << bp.x() / 2000.0 << ", "
220              << bp.y() / 2000.0 << ") " << getTech()->getLayer(l1Num)->getName()
221              << " --> " << getTech()->getLayer(l2Num)->getName() << endl;
222       }
223     } else {
224       cout << "Error: checkConnectivity_nodeMap_routeObjEnd unsupported type"
225            << endl;
226     }
227   }
228 }
229 
checkConnectivity_nodeMap_routeObjSplit_helper(const frPoint & crossPt,frCoord trackCoord,frCoord splitCoord,frLayerNum lNum,const vector<map<frCoord,map<frCoord,pair<frCoord,int>>>> & mergeHelper,map<pair<frPoint,frLayerNum>,set<int>> & nodeMap)230 void FlexDR::checkConnectivity_nodeMap_routeObjSplit_helper(
231     const frPoint& crossPt,
232     frCoord trackCoord,
233     frCoord splitCoord,
234     frLayerNum lNum,
235     const vector<map<frCoord, map<frCoord, pair<frCoord, int>>>>& mergeHelper,
236     map<pair<frPoint, frLayerNum>, set<int>>& nodeMap)
237 {
238   auto it1 = mergeHelper[lNum].find(trackCoord);
239   if (it1 != mergeHelper[lNum].end()) {
240     auto& mp = it1->second;  // map<ep, pair<bp, objIdx>>
241     auto it2 = mp.lower_bound(splitCoord);
242     if (it2 != mp.end()) {
243       auto& endP = it2->first;
244       auto& [beginP, objIdx] = it2->second;
245       if (endP > splitCoord && beginP < splitCoord) {
246         nodeMap[make_pair(crossPt, lNum)].insert(objIdx);
247       }
248     }
249   }
250 }
251 
checkConnectivity_nodeMap_routeObjSplit(const frNet * net,const vector<frConnFig * > & netRouteObjs,map<pair<frPoint,frLayerNum>,set<int>> & nodeMap)252 void FlexDR::checkConnectivity_nodeMap_routeObjSplit(
253     const frNet* net,
254     const vector<frConnFig*>& netRouteObjs,
255     map<pair<frPoint, frLayerNum>, set<int>>& nodeMap)
256 {
257   frPoint bp, ep;
258   // vector<map<track, map<ep, pair<bp, objIdx>>>> interval_map
259   vector<map<frCoord, map<frCoord, pair<frCoord, int>>>> horzMergeHelper(
260       getTech()->getLayers().size());
261   vector<map<frCoord, map<frCoord, pair<frCoord, int>>>> vertMergeHelper(
262       getTech()->getLayers().size());
263   for (int i = 0; i < (int) netRouteObjs.size(); i++) {
264     auto& connFig = netRouteObjs[i];
265     if (connFig->typeId() == frcPathSeg) {
266       auto obj = static_cast<frPathSeg*>(connFig);
267       obj->getPoints(bp, ep);
268       auto lNum = obj->getLayerNum();
269       // vert seg
270       if (bp.x() == ep.x()) {
271         vertMergeHelper[lNum][bp.x()][ep.y()] = make_pair(bp.y(), i);
272         // horz seg
273       } else {
274         horzMergeHelper[lNum][bp.y()][ep.x()] = make_pair(bp.x(), i);
275       }
276     }
277   }
278   for (int i = 0; i < (int) netRouteObjs.size(); i++) {
279     auto& connFig = netRouteObjs[i];
280     // ep on pathseg
281     if (connFig->typeId() == frcPathSeg) {
282       auto obj = static_cast<frPathSeg*>(connFig);
283       obj->getPoints(bp, ep);
284       auto lNum = obj->getLayerNum();
285       // vert seg, find horz crossing seg
286       if (bp.x() == ep.x()) {
287         // find whether there is horz track at bp
288         auto crossPt = bp;
289         auto trackCoord = bp.y();
290         auto splitCoord = bp.x();
291         checkConnectivity_nodeMap_routeObjSplit_helper(
292             crossPt, trackCoord, splitCoord, lNum, horzMergeHelper, nodeMap);
293         // find whether there is horz track at ep
294         crossPt = ep;
295         trackCoord = ep.y();
296         splitCoord = ep.x();
297         checkConnectivity_nodeMap_routeObjSplit_helper(
298             crossPt, trackCoord, splitCoord, lNum, horzMergeHelper, nodeMap);
299         // horz seg
300       } else {
301         // find whether there is vert track at bp
302         auto crossPt = bp;
303         auto trackCoord = bp.x();
304         auto splitCoord = bp.y();
305         checkConnectivity_nodeMap_routeObjSplit_helper(
306             crossPt, trackCoord, splitCoord, lNum, vertMergeHelper, nodeMap);
307         // find whether there is vert track at ep
308         crossPt = ep;
309         trackCoord = ep.x();
310         splitCoord = ep.y();
311         checkConnectivity_nodeMap_routeObjSplit_helper(
312             crossPt, trackCoord, splitCoord, lNum, vertMergeHelper, nodeMap);
313       }
314     } else if (connFig->typeId() == frcVia) {
315       auto obj = static_cast<frVia*>(connFig);
316       obj->getOrigin(bp);
317       auto lNum = obj->getViaDef()->getLayer1Num();
318       // find whether there is horz track at bp on layer1
319       auto crossPt = bp;
320       auto trackCoord = bp.y();
321       auto splitCoord = bp.x();
322       checkConnectivity_nodeMap_routeObjSplit_helper(
323           crossPt, trackCoord, splitCoord, lNum, horzMergeHelper, nodeMap);
324       // find whether there is vert track at bp on layer1
325       crossPt = bp;
326       trackCoord = bp.x();
327       splitCoord = bp.y();
328       checkConnectivity_nodeMap_routeObjSplit_helper(
329           crossPt, trackCoord, splitCoord, lNum, vertMergeHelper, nodeMap);
330 
331       lNum = obj->getViaDef()->getLayer2Num();
332       // find whether there is horz track at bp on layer2
333       crossPt = bp;
334       trackCoord = bp.y();
335       splitCoord = bp.x();
336       checkConnectivity_nodeMap_routeObjSplit_helper(
337           crossPt, trackCoord, splitCoord, lNum, horzMergeHelper, nodeMap);
338       // find whether there is vert track at bp on layer2
339       crossPt = bp;
340       trackCoord = bp.x();
341       splitCoord = bp.y();
342       checkConnectivity_nodeMap_routeObjSplit_helper(
343           crossPt, trackCoord, splitCoord, lNum, vertMergeHelper, nodeMap);
344     }
345   }
346 }
347 
checkConnectivity_nodeMap_pin(const vector<frConnFig * > & netRouteObjs,vector<frBlockObject * > & netPins,const map<frBlockObject *,set<pair<frPoint,frLayerNum>>,frBlockObjectComp> & pin2epMap,map<pair<frPoint,frLayerNum>,set<int>> & nodeMap)348 void FlexDR::checkConnectivity_nodeMap_pin(
349     const vector<frConnFig*>& netRouteObjs,
350     vector<frBlockObject*>& netPins,
351     const map<frBlockObject*,
352               set<pair<frPoint, frLayerNum>>,
353               frBlockObjectComp>& pin2epMap,
354     map<pair<frPoint, frLayerNum>, set<int>>& nodeMap)
355 {
356   bool enableOutput = false;
357   int currCnt = (int) netRouteObjs.size();
358   for (auto& [obj, locS] : pin2epMap) {
359     netPins.push_back(obj);
360     for (auto& pr : locS) {
361       nodeMap[pr].insert(currCnt);
362       if (enableOutput) {
363         cout << "pin idx = " << currCnt << ", (" << pr.first.x() << ", "
364              << pr.first.y() << ") "
365              << getTech()->getLayer(pr.second)->getName() << endl;
366       }
367     }
368     ++currCnt;
369   }
370 }
371 
checkConnectivity_nodeMap(const frNet * net,const vector<frConnFig * > & netRouteObjs,vector<frBlockObject * > & netPins,const map<frBlockObject *,set<pair<frPoint,frLayerNum>>,frBlockObjectComp> & pin2epMap,map<pair<frPoint,frLayerNum>,set<int>> & nodeMap)372 void FlexDR::checkConnectivity_nodeMap(
373     const frNet* net,
374     const vector<frConnFig*>& netRouteObjs,
375     vector<frBlockObject*>& netPins,
376     const map<frBlockObject*,
377               set<pair<frPoint, frLayerNum>>,
378               frBlockObjectComp>& pin2epMap,
379     map<pair<frPoint, frLayerNum>, set<int>>& nodeMap)
380 {
381   bool enableOutput = false;
382   // bool enableOutput = true;
383   checkConnectivity_nodeMap_routeObjEnd(net, netRouteObjs, nodeMap);
384   checkConnectivity_nodeMap_routeObjSplit(net, netRouteObjs, nodeMap);
385   checkConnectivity_nodeMap_pin(netRouteObjs, netPins, pin2epMap, nodeMap);
386   if (enableOutput) {
387     int idx = 0;
388     for (auto connFig : netRouteObjs) {
389       if (connFig->typeId() == frcPathSeg) {
390         auto obj = static_cast<frPathSeg*>(connFig);
391         frPoint bp, ep;
392         auto lNum = obj->getLayerNum();
393         obj->getPoints(bp, ep);
394         cout << "#" << idx << *obj << getTech()->getLayer(lNum)->getName()
395              << endl;
396       } else if (connFig->typeId() == frcVia) {
397         auto obj = static_cast<frVia*>(connFig);
398         frPoint bp;
399         obj->getOrigin(bp);
400         cout << "#" << idx << *obj << obj->getViaDef()->getName() << endl;
401       } else {
402         cout << "Error: checkConnectivity_nodeMap unsupported type" << endl;
403       }
404       idx++;
405     }
406     for (auto obj : netPins) {
407       if (obj->typeId() == frcInstTerm) {
408         auto instTerm = static_cast<frInstTerm*>(obj);
409         cout << "#" << idx << " " << instTerm->getName() << "\n";
410       } else if (obj->typeId() == frcTerm) {
411         auto term = static_cast<frTerm*>(obj);
412         cout << "#" << idx << " PIN/" << term->getName() << endl;
413       }
414       idx++;
415     }
416   }
417 }
418 
checkConnectivity_astar(frNet * net,vector<bool> & adjVisited,vector<int> & adjPrevIdx,const map<pair<frPoint,frLayerNum>,set<int>> & nodeMap,const vector<frConnFig * > & netDRObjs,const int & nNetRouteObjs,const int & nNetObjs)419 bool FlexDR::checkConnectivity_astar(
420     frNet* net,
421     vector<bool>& adjVisited,
422     vector<int>& adjPrevIdx,
423     const map<pair<frPoint, frLayerNum>, set<int>>& nodeMap,
424         const vector<frConnFig*>& netDRObjs,
425     const int& nNetRouteObjs,
426     const int& nNetObjs)
427 {
428   // bool enableOutput = true;
429   bool enableOutput = net->getName() == netToDebug;
430   // a star search
431   if (enableOutput)
432     cout << "checkConnectivity_astar\n\n";
433   // node index, node visited
434   vector<vector<int>> adjVec(nNetObjs, vector<int>());
435   vector<bool> onPathIdx(nNetObjs, false);
436   adjVisited.clear();
437   adjPrevIdx.clear();
438   adjVisited.resize(nNetObjs, false);
439   adjPrevIdx.resize(nNetObjs, -1);
440   for (auto& [pr, idxS] : nodeMap) {
441     // auto &[pt, lNum] = pr;
442     for (auto it1 = idxS.begin(); it1 != idxS.end(); it1++) {
443       auto it2 = it1;
444       it2++;
445       auto idx1 = *it1;
446       for (; it2 != idxS.end(); it2++) {
447         auto idx2 = *it2;
448         adjVec[idx1].push_back(idx2);
449         adjVec[idx2].push_back(idx1);
450         if (enableOutput)
451           cout << "add edge #" << idx1 << " -- #" << idx2 << endl;
452         //  one pin, one gcell
453       }
454     }
455   }
456 
457   struct wf
458   {
459     int nodeIdx;
460     int prevIdx;
461     int cost;
462     bool operator<(const wf& b) const
463     {
464       if (cost == b.cost) {
465         return nodeIdx > b.nodeIdx;
466       } else {
467         return cost > b.cost;
468       }
469     }
470   };
471   for (int findNode = nNetRouteObjs; findNode < nNetObjs - 1; findNode++) {
472     // adjVisited = onPathIdx;
473     // cout <<"finished " <<findNode <<" nodes" <<endl;
474     priority_queue<wf> pq;
475     if (enableOutput) {
476       // cout <<"visit";
477     }
478     if (findNode == nNetRouteObjs) {
479       // push only first pin into pq
480       pq.push({nNetRouteObjs, -1, 0});
481     } else {
482       // push every visited node into pq
483       for (int i = 0; i < nNetObjs; i++) {
484         // if (adjVisited[i]) {
485         if (onPathIdx[i]) {
486           // penalize feedthrough in normal mode
487           if (i >= nNetRouteObjs) {
488             pq.push({i, adjPrevIdx[i], 5});
489           } else {
490             pq.push({i, adjPrevIdx[i], 0});
491           }
492         }
493       }
494     }
495     int lastNodeIdx = -1;
496     while (!pq.empty()) {
497       auto wfront = pq.top();
498       pq.pop();
499       if (!onPathIdx[wfront.nodeIdx] && adjVisited[wfront.nodeIdx]) {
500         continue;
501       }
502       if (wfront.nodeIdx > nNetRouteObjs && wfront.nodeIdx < nNetObjs
503           && adjVisited[wfront.nodeIdx] == false) {
504         adjVisited[wfront.nodeIdx] = true;
505         adjPrevIdx[wfront.nodeIdx] = wfront.prevIdx;
506         if (enableOutput) {
507           cout << "visit pin " << wfront.nodeIdx << " (" << wfront.cost << ","
508                << wfront.prevIdx << ")"
509                << " exit" << endl;
510         }
511         lastNodeIdx = wfront.nodeIdx;
512         break;
513       }
514       adjVisited[wfront.nodeIdx] = true;
515       adjPrevIdx[wfront.nodeIdx] = wfront.prevIdx;
516       if (enableOutput) {
517           cout << "visit ";
518           if (wfront.nodeIdx < (int)netDRObjs.size())
519              cout << *netDRObjs[wfront.nodeIdx];
520           cout << "idx " << wfront.nodeIdx << " (" << wfront.cost << ","
521              << wfront.prevIdx << ")" << endl;
522       }
523       // visit other nodes
524       for (auto nbrIdx : adjVec[wfront.nodeIdx]) {
525         if (!adjVisited[nbrIdx]) {
526           pq.push({nbrIdx, wfront.nodeIdx, wfront.cost + 1});
527           if (enableOutput) {
528             cout << "push " << nbrIdx << endl;
529           }
530         }
531       }
532     }
533     // trace back path
534     if (enableOutput) {
535       cout << "trace back id";
536     }
537     while ((lastNodeIdx != -1) && (!onPathIdx[lastNodeIdx])) {
538       onPathIdx[lastNodeIdx] = true;
539       if (enableOutput) {
540         cout << " " << lastNodeIdx << " (" << adjPrevIdx[lastNodeIdx] << ")";
541       }
542       lastNodeIdx = adjPrevIdx[lastNodeIdx];
543     }
544     if (enableOutput) {
545       cout << endl;
546     }
547     adjVisited = onPathIdx;
548   }
549   if (enableOutput) {
550     cout << "stat: " << net->getName()
551          << " #guide/#pin/#unused = " << nNetRouteObjs << "/"
552          << nNetObjs - nNetRouteObjs << "/"
553          << nNetObjs - count(adjVisited.begin(), adjVisited.end(), true)
554          << endl;
555   }
556   int pinVisited
557       = count(adjVisited.begin() + nNetRouteObjs, adjVisited.end(), true);
558   // true error when allowing feedthrough
559   if (pinVisited != nNetObjs - nNetRouteObjs) {
560     cout << "Error: " << net->getName() << " "
561          << nNetObjs - nNetRouteObjs - pinVisited
562          << " pin not visited #guides = " << nNetRouteObjs << endl;
563     if (enableOutput) {
564       for (int i = nNetRouteObjs; i < nNetObjs; i++) {
565         if (!adjVisited[i]) {
566           cout << "  pin id = " << i << endl;
567         }
568       }
569     }
570   }
571   if (pinVisited == nNetObjs - nNetRouteObjs) {
572     return true;
573   } else {
574     return false;
575   }
576 }
577 
checkConnectivity_final(frNet * net,vector<frConnFig * > & netRouteObjs,vector<frBlockObject * > & netPins,const vector<bool> & adjVisited,int gCnt,int nCnt,map<pair<frPoint,frLayerNum>,set<int>> & nodeMap)578 void FlexDR::checkConnectivity_final(
579     frNet* net,
580     vector<frConnFig*>& netRouteObjs,
581     vector<frBlockObject*>& netPins,
582     const vector<bool>& adjVisited,
583     int gCnt,
584     int nCnt,
585     map<pair<frPoint, frLayerNum>, set<int>>& nodeMap)
586 {
587   // bool enableOutput = true;
588   bool enableOutput = net->getName() == netToDebug;
589 
590   auto regionQuery = getRegionQuery();
591 
592   // from obj to pt
593   map<int, set<pair<frPoint, frLayerNum>>> reverseNodeMap;
594   for (auto& [pr, idxS] : nodeMap) {
595     for (auto& idx : idxS) {
596       reverseNodeMap[idx].insert(pr);
597     }
598   }
599 
600   // nodeMap delete redundant objs
601   for (int i = 0; i < (int) adjVisited.size(); i++) {
602     if (adjVisited[i]) {
603       continue;
604     }
605     for (auto& pr : reverseNodeMap[i]) {
606       nodeMap[pr].erase(i);
607     }
608     if (i < gCnt) {
609       if (netRouteObjs[i]->typeId() == frcPathSeg) {
610         auto victimPathSeg = static_cast<frPathSeg*>(netRouteObjs[i]);
611         // negative rule
612         frBox bbox;
613         victimPathSeg->getBBox(bbox);
614         checkConnectivity_addMarker(net, victimPathSeg->getLayerNum(), bbox);
615 
616         if (enableOutput) {
617           cout << "net " << net->getName() << " deleting pathseg " <<
618                   *static_cast<frPathSeg*>(netRouteObjs[i]) << endl;
619         }
620         regionQuery->removeDRObj(static_cast<frShape*>(netRouteObjs[i]));
621         net->removeShape(static_cast<frShape*>(netRouteObjs[i]));
622       } else if (netRouteObjs[i]->typeId() == frcVia) {
623         auto victimVia = static_cast<frVia*>(netRouteObjs[i]);
624         // negative rule
625         frBox bbox;
626         victimVia->getLayer1BBox(bbox);
627         checkConnectivity_addMarker(
628             net, victimVia->getViaDef()->getLayer1Num(), bbox);
629 
630         frVia* via = static_cast<frVia*>(netRouteObjs[i]);
631         if (enableOutput) {
632           cout << "net " << net->getName() << " deleting via " << *via << endl;
633         }
634         regionQuery->removeDRObj(via);
635         net->removeVia(via);
636         //} else if (netRouteObjs[i]->typeId() == frcPatchWire) {
637         //  regionQuery->removeDRObj(static_cast<frPatchWire*>(netRouteObjs[i]));
638         //  net->removePatchWire(static_cast<frPatchWire*>(netRouteObjs[i]));
639         //  if (enableOutput) {
640         //    cout <<"net " <<net->getName() <<" deleting pwire" <<endl;
641         //  }
642       } else {
643         cout << "Error: checkConnectivity_final unsupporterd type" << endl;
644         exit(1);
645       }
646       netRouteObjs[i] = nullptr;
647     } else {
648       cout << "Error: checkConnectivity_final i >= gCnt" << endl;
649       exit(1);
650     }
651   }
652 
653   // rebuild reverseNodeMap
654   reverseNodeMap.clear();
655   for (auto& [pr, idxS] : nodeMap) {
656     if (idxS.size() == 1) {
657       continue;
658     }
659     for (auto& idx : idxS) {
660       reverseNodeMap[idx].insert(pr);
661     }
662   }
663 
664   // must use map because split has to start from right
665   map<pair<frPoint, frLayerNum>, int> psSplits;
666   for (auto& [pr, idxS] : nodeMap) {
667     bool hasPin = false;
668     for (auto idx : idxS) {
669       // skip for non-pin idx
670       if (idx >= gCnt) {
671         hasPin = true;
672         break;
673       }
674     }
675 
676     if (!hasPin) {
677       continue;
678     }
679 
680     bool hasPinEP = false;
681     int psIdx = -1;
682     for (auto idx : idxS) {
683       if (idx >= gCnt) {
684         continue;
685       }
686       if (netRouteObjs[idx]->typeId() == frcPathSeg) {
687         auto ps = static_cast<frPathSeg*>(netRouteObjs[idx]);
688         frPoint bp, ep;
689         ps->getPoints(bp, ep);
690         if (bp == pr.first || ep == pr.first) {
691           hasPinEP = true;
692           break;
693         } else {
694           psIdx = idx;
695         }
696       } else if (netRouteObjs[idx]->typeId() == frcVia) {
697         hasPinEP = true;
698         break;
699       }
700     }
701 
702     // need to split for pin feedthrough for connectivity
703     // psIdx might be -1 because empty nodeMap
704     //   1. two segments of a corner deleted, corner does not exist anymore
705     //   2. to a feedthrough pin, if the feedthrough is in a loop, one end does
706     //   not exist anymore
707     if (!hasPinEP && psIdx != -1) {
708       psSplits[pr] = psIdx;
709     }
710   }
711 
712   vector<frPathSeg*> addedPS;
713   for (auto it = psSplits.rbegin(); it != psSplits.rend(); it++) {
714     auto& [pr, idx1] = *it;
715     int idx2 = nCnt + addedPS.size();
716     auto& [splitPt, lNum] = pr;
717     frPoint bp1, ep1;
718     auto ps1 = static_cast<frPathSeg*>(netRouteObjs[idx1]);
719     ps1->getPoints(bp1, ep1);
720     bool isHorz = (bp1.y() == ep1.y());
721     set<pair<frPoint, frLayerNum>> newPr1;
722     set<pair<frPoint, frLayerNum>> newPr2;
723     for (auto& [prPt, prLNum] : reverseNodeMap[idx1]) {
724       if (isHorz) {
725         if (prPt.x() <= splitPt.x()) {
726           newPr1.insert(make_pair(prPt, prLNum));
727         } else {
728           nodeMap[make_pair(prPt, prLNum)].erase(idx1);
729         }
730         if (prPt.x() >= splitPt.x()) {
731           newPr2.insert(make_pair(prPt, prLNum));
732           nodeMap[make_pair(prPt, prLNum)].insert(idx2);
733         }
734       } else {
735         if (prPt.y() <= splitPt.y()) {
736           newPr1.insert(make_pair(prPt, prLNum));
737         } else {
738           nodeMap[make_pair(prPt, prLNum)].erase(idx1);
739         }
740         if (prPt.y() >= splitPt.y()) {
741           newPr2.insert(make_pair(prPt, prLNum));
742           nodeMap[make_pair(prPt, prLNum)].insert(idx2);
743         }
744       }
745     }
746 
747     reverseNodeMap[idx1].clear();
748     reverseNodeMap[idx1] = newPr1;
749     reverseNodeMap[idx2] = newPr2;
750 
751     auto uPs2 = make_unique<frPathSeg>(*ps1);
752     auto ps2 = uPs2.get();
753     addedPS.push_back(ps2);
754     unique_ptr<frShape> uShape(std::move(uPs2));
755     net->addShape(std::move(uShape));
756     // manipulate ps1
757     regionQuery->removeDRObj(ps1);
758     frSegStyle ps1Style;
759     ps1->getStyle(ps1Style);
760     ps1Style.setEndStyle(frEndStyle(frcTruncateEndStyle), 0);
761     ps1->setStyle(ps1Style);
762     ps1->setPoints(bp1, splitPt);
763     regionQuery->addDRObj(ps1);
764 
765     // manipulate ps2
766     frSegStyle ps2Style;
767     ps2->getStyle(ps2Style);
768     ps2Style.setBeginStyle(frEndStyle(frcTruncateEndStyle), 0);
769     ps2->setStyle(ps2Style);
770     ps2->setPoints(splitPt, ep1);
771     regionQuery->addDRObj(ps2);
772   }
773 
774   for (auto& [idx, ptS] : reverseNodeMap) {
775     frPathSeg* ps = nullptr;
776     if (idx < gCnt) {
777       if (netRouteObjs[idx]->typeId() == frcPathSeg) {
778         ps = static_cast<frPathSeg*>(netRouteObjs[idx]);
779       }
780     } else if (idx >= nCnt) {
781       ps = addedPS[idx - nCnt];
782     }
783     if (!ps) {
784       continue;
785     }
786 
787     frPoint bp, ep;
788     ps->getPoints(bp, ep);
789     auto [minPr, maxPr] = minmax_element(ptS.begin(), ptS.end());
790     auto& minPt = minPr->first;
791     auto& maxPt = maxPr->first;
792     // shrink segment
793     if (bp < minPt || maxPt < ep) {
794       // negative rule
795       frBox bbox;
796       ps->getBBox(bbox);
797       checkConnectivity_addMarker(net, ps->getLayerNum(), bbox);
798 
799       regionQuery->removeDRObj(ps);
800       ps->setPoints(minPt, maxPt);
801       regionQuery->addDRObj(ps);
802       if (enableOutput) {
803         cout << "net " << net->getName() << " shrinking pathseg" << endl;
804       }
805     }
806   }
807 
808   // delete redundant pwires
809   set<pair<frPoint, frLayerNum>> validPoints;
810   frPoint bp, ep;
811   frLayerNum lNum;
812   for (auto& connFig : net->getShapes()) {
813     if (connFig->typeId() == frcPathSeg) {
814       auto obj = static_cast<frPathSeg*>(connFig.get());
815       obj->getPoints(bp, ep);
816       lNum = obj->getLayerNum();
817       validPoints.insert(make_pair(bp, lNum));
818       validPoints.insert(make_pair(ep, lNum));
819     } else {
820       cout << "Error: checkConnectivity_final unsupporterd type" << endl;
821       exit(1);
822     }
823   }
824   for (auto& connFig : net->getVias()) {
825     if (connFig->typeId() == frcVia) {
826       auto obj = static_cast<frVia*>(connFig.get());
827       obj->getOrigin(bp);
828       lNum = obj->getViaDef()->getLayer1Num();
829       validPoints.insert(make_pair(bp, lNum));
830       lNum = obj->getViaDef()->getLayer2Num();
831       validPoints.insert(make_pair(bp, lNum));
832     } else {
833       cout << "Error: checkConnectivity_final unsupporterd type" << endl;
834       exit(1);
835     }
836   }
837   for (auto it = net->getPatchWires().begin();
838        it != net->getPatchWires().end();) {
839     auto obj = static_cast<frPatchWire*>(it->get());
840     it++;
841     obj->getOrigin(bp);
842     lNum = obj->getLayerNum();
843     if (validPoints.find(make_pair(bp, lNum)) == validPoints.end()) {
844       // negative rule
845       frBox bbox;
846       obj->getBBox(bbox);
847       checkConnectivity_addMarker(net, obj->getLayerNum(), bbox);
848 
849       regionQuery->removeDRObj(obj);
850       net->removePatchWire(obj);
851       if (enableOutput) {
852         cout << "net " << net->getName() << " deleting pwire" << endl;
853       }
854     }
855   }
856 }
857 
checkConnectivity_merge1(const frNet * net,const vector<frConnFig * > & netRouteObjs,vector<map<frCoord,vector<int>>> & horzPathSegs,vector<map<frCoord,vector<int>>> & vertPathSegs)858 void FlexDR::checkConnectivity_merge1(
859     const frNet* net,
860     const vector<frConnFig*>& netRouteObjs,
861     vector<map<frCoord, vector<int>>>& horzPathSegs,
862     vector<map<frCoord, vector<int>>>& vertPathSegs)
863 {
864   // bool enableOutput = false;
865   frPoint bp, ep;
866   if (netRouteObjs.empty()) {
867     return;
868   }
869 
870   for (int i = 0; i < (int) netRouteObjs.size(); i++) {
871     auto& connFig = netRouteObjs[i];
872     if (connFig->typeId() == frcPathSeg) {
873       auto obj = static_cast<frPathSeg*>(connFig);
874       obj->getPoints(bp, ep);
875       auto lNum = obj->getLayerNum();
876       // vert
877       if (bp.x() == ep.x()) {
878         vertPathSegs[lNum][bp.x()].push_back(i);
879       } else if (bp.y() == ep.y()) {
880         horzPathSegs[lNum][bp.y()].push_back(i);
881       } else {
882         cout << "Error: non-orthogonal wires in checkConnectivity_merge\n";
883       }
884       // vert
885     } else if (connFig->typeId() == frcVia) {
886       ;
887     } else if (connFig->typeId() == frcPatchWire) {
888       ;
889     } else {
890       cout << "Warning: unsupporterd obj type in checkConnectivity_merge"
891            << endl;
892     }
893   }
894 }
895 
checkConnectivity_merge2(frNet * net,const vector<frConnFig * > & netRouteObjs,const vector<map<frCoord,vector<int>>> & horzPathSegs,const vector<map<frCoord,vector<int>>> & vertPathSegs,vector<vector<vector<int>>> & horzVictims,vector<vector<vector<int>>> & vertVictims,vector<vector<vector<pair<frCoord,frCoord>>>> & horzNewSegSpans,vector<vector<vector<pair<frCoord,frCoord>>>> & vertNewSegSpans)896 void FlexDR::checkConnectivity_merge2(
897     frNet* net,
898     const vector<frConnFig*>& netRouteObjs,
899     const vector<map<frCoord, vector<int>>>& horzPathSegs,
900     const vector<map<frCoord, vector<int>>>& vertPathSegs,
901     vector<vector<vector<int>>>& horzVictims,
902     vector<vector<vector<int>>>& vertVictims,
903     vector<vector<vector<pair<frCoord, frCoord>>>>& horzNewSegSpans,
904     vector<vector<vector<pair<frCoord, frCoord>>>>& vertNewSegSpans)
905 {
906   for (auto lNum = 0; lNum < (int) horzPathSegs.size(); lNum++) {
907     auto& track2Segs = horzPathSegs[lNum];
908     horzVictims[lNum].resize(track2Segs.size());
909     horzNewSegSpans[lNum].resize(track2Segs.size());
910     int i = 0;
911     for (auto& [trackCoord, indices] : track2Segs) {
912       auto& victims = horzVictims[lNum][i];
913       auto& newSegSpans = horzNewSegSpans[lNum][i];
914       checkConnectivity_merge_perform(
915           netRouteObjs, indices, victims, newSegSpans, true /*isHorz*/);
916       i++;
917     }
918   }
919 
920   for (auto lNum = 0; lNum < (int) vertPathSegs.size(); lNum++) {
921     auto& track2Segs = vertPathSegs[lNum];
922     vertVictims[lNum].resize(track2Segs.size());
923     vertNewSegSpans[lNum].resize(track2Segs.size());
924     int i = 0;
925     for (auto& [trackCoord, indices] : track2Segs) {
926       auto& victims = vertVictims[lNum][i];
927       auto& newSegSpans = vertNewSegSpans[lNum][i];
928       checkConnectivity_merge_perform(
929           netRouteObjs, indices, victims, newSegSpans, false /*isHorz*/);
930       i++;
931     }
932   }
933 }
934 
checkConnectivity_merge3(frNet * net,vector<frConnFig * > & netRouteObjs,const vector<map<frCoord,vector<int>>> & horzPathSegs,const vector<map<frCoord,vector<int>>> & vertPathSegs,const vector<vector<vector<int>>> & horzVictims,const vector<vector<vector<int>>> & vertVictims,const vector<vector<vector<pair<frCoord,frCoord>>>> & horzNewSegSpans,const vector<vector<vector<pair<frCoord,frCoord>>>> & vertNewSegSpans)935 void FlexDR::checkConnectivity_merge3(
936     frNet* net,
937     vector<frConnFig*>& netRouteObjs,
938     const vector<map<frCoord, vector<int>>>& horzPathSegs,
939     const vector<map<frCoord, vector<int>>>& vertPathSegs,
940     const vector<vector<vector<int>>>& horzVictims,
941     const vector<vector<vector<int>>>& vertVictims,
942     const vector<vector<vector<pair<frCoord, frCoord>>>>& horzNewSegSpans,
943     const vector<vector<vector<pair<frCoord, frCoord>>>>& vertNewSegSpans)
944 {
945   for (auto lNum = 0; lNum < (int) horzPathSegs.size(); lNum++) {
946     auto& track2Segs = horzPathSegs[lNum];
947     int i = 0;
948     for (auto& [trackCoord, indices] : track2Segs) {
949       auto& victims = horzVictims[lNum][i];
950       auto& newSegSpans = horzNewSegSpans[lNum][i];
951       checkConnectivity_merge_commit(net,
952                                      netRouteObjs,
953                                      victims,
954                                      lNum,
955                                      trackCoord,
956                                      newSegSpans,
957                                      true /*isHorz*/);
958       i++;
959     }
960   }
961 
962   for (auto lNum = 0; lNum < (int) vertPathSegs.size(); lNum++) {
963     auto& track2Segs = vertPathSegs[lNum];
964     int i = 0;
965     for (auto& [trackCoord, indices] : track2Segs) {
966       auto& victims = vertVictims[lNum][i];
967       auto& newSegSpans = vertNewSegSpans[lNum][i];
968       checkConnectivity_merge_commit(net,
969                                      netRouteObjs,
970                                      victims,
971                                      lNum,
972                                      trackCoord,
973                                      newSegSpans,
974                                      false /*isHorz*/);
975       i++;
976     }
977   }
978 }
979 
checkConnectivity_merge_perform(const vector<frConnFig * > & netRouteObjs,const vector<int> & indices,vector<int> & victims,vector<pair<frCoord,frCoord>> & newSegSpans,bool isHorz)980 void FlexDR::checkConnectivity_merge_perform(
981     const vector<frConnFig*>& netRouteObjs,
982     const vector<int>& indices,
983     vector<int>& victims,
984     vector<pair<frCoord, frCoord>>& newSegSpans,
985     bool isHorz)
986 {
987   vector<pair<pair<frCoord, frCoord>, int>> segSpans;
988   frPoint bp, ep;
989   for (auto& idx : indices) {
990     auto obj = static_cast<frPathSeg*>(netRouteObjs[idx]);
991     obj->getPoints(bp, ep);
992     if (isHorz) {
993       segSpans.push_back(make_pair(make_pair(bp.x(), ep.x()), idx));
994       if (bp.x() >= ep.x()) {
995         cout << "Error: bp >= ep\n";
996       }
997     } else {
998       segSpans.push_back(make_pair(make_pair(bp.y(), ep.y()), idx));
999       if (bp.y() >= ep.y()) {
1000         cout << "Error: bp >= ep\n";
1001       }
1002     }
1003   }
1004   sort(segSpans.begin(), segSpans.end());
1005 
1006   // get victim segments and merged segments
1007   checkConnectivity_merge_perform_helper(segSpans, victims, newSegSpans);
1008 }
1009 
checkConnectivity_merge_perform_helper(const vector<pair<pair<frCoord,frCoord>,int>> & segSpans,vector<int> & victims,vector<pair<frCoord,frCoord>> & newSegSpans)1010 void FlexDR::checkConnectivity_merge_perform_helper(
1011     const vector<pair<pair<frCoord, frCoord>, int>>& segSpans,
1012     vector<int>& victims,
1013     vector<pair<frCoord, frCoord>>& newSegSpans)
1014 {
1015   // bool enableOutput = true;
1016   map<int, int> victimIdx2SegSpanIdx;
1017   int ovlpCnt = 0;
1018   frCoord currStart = INT_MAX, currEnd = INT_MIN;
1019   vector<int> localVictims;
1020   for (auto& segSpan : segSpans) {
1021     if (segSpan.first.first >= currEnd) {
1022       ovlpCnt++;
1023       if (ovlpCnt >= 2) {
1024         // commit prev merged segs
1025         newSegSpans.push_back(make_pair(currStart, currEnd));
1026         // commit victims in merged segs
1027         victims.insert(victims.end(), localVictims.begin(), localVictims.end());
1028         // if (enableOutput) {
1029         //   cout << "intervals ";
1030         //   for (auto &victimIdx: localVictims) {
1031         //     auto &intv = segSpans[victimIdx2SegSpanIdx[victimIdx]].first;
1032         //     cout << "[" << intv.first << "," << intv.second << "] ";
1033         //   }
1034         //   cout << "merged to [" << currStart << "," << currEnd << "]\n";
1035         // }
1036       }
1037       // cleanup
1038       localVictims.clear();
1039       ovlpCnt = 0;
1040       // update local variables
1041       currStart = segSpan.first.first;
1042       currEnd = segSpan.first.second;
1043       localVictims.push_back(segSpan.second);
1044     } else {
1045       ovlpCnt++;
1046       // update local variables
1047       currEnd = max(currEnd, segSpan.first.second);
1048       localVictims.push_back(segSpan.second);
1049     }
1050   }
1051   if (ovlpCnt >= 1) {
1052     newSegSpans.push_back(make_pair(currStart, currEnd));
1053     victims.insert(victims.end(), localVictims.begin(), localVictims.end());
1054   }
1055 }
1056 
checkConnectivity_merge_commit(frNet * net,vector<frConnFig * > & netRouteObjs,const vector<int> & victims,frLayerNum lNum,frCoord trackCoord,const vector<pair<frCoord,frCoord>> & newSegSpans,bool isHorz)1057 void FlexDR::checkConnectivity_merge_commit(
1058     frNet* net,
1059     vector<frConnFig*>& netRouteObjs,
1060     const vector<int>& victims,
1061     frLayerNum lNum,
1062     frCoord trackCoord,
1063     const vector<pair<frCoord, frCoord>>& newSegSpans,
1064     bool isHorz)
1065 {
1066   if (victims.empty()) {
1067     return;
1068   }
1069   auto regionQuery = getRegionQuery();
1070   // add segments from overlapped segments
1071   int cnt = 0;
1072   frPathSeg *last, *curr;
1073   for (auto& newSegSpan : newSegSpans) {
1074     auto victimPathSeg = static_cast<frPathSeg*>(netRouteObjs[victims[cnt]]);
1075     regionQuery->removeDRObj(static_cast<frShape*>(victimPathSeg));
1076 
1077     frPoint bp, ep;
1078     if (isHorz) {
1079       bp.set(newSegSpan.first, trackCoord);
1080       ep.set(newSegSpan.second, trackCoord);
1081     } else {
1082       bp.set(trackCoord, newSegSpan.first);
1083       ep.set(trackCoord, newSegSpan.second);
1084     }
1085     victimPathSeg->setPoints(bp, ep);
1086     cnt++;
1087     last = nullptr;
1088     for (; cnt < (int) victims.size(); cnt++) {
1089       curr = static_cast<frPathSeg*>(netRouteObjs[victims[cnt]]);
1090       if (curr->high() <= newSegSpan.second) {
1091         last = curr;
1092         regionQuery->removeDRObj(
1093             static_cast<frShape*>(netRouteObjs[victims[cnt]]));
1094         net->removeShape(static_cast<frShape*>(netRouteObjs[victims[cnt]]));
1095         netRouteObjs[victims[cnt]] = nullptr;
1096       } else
1097         break;
1098     }
1099     if (last) {
1100       victimPathSeg->setEndStyle(last->getEndStyle(), last->getEndExt());
1101     }
1102     regionQuery->addDRObj(victimPathSeg);
1103   }
1104 }
1105 
checkConnectivity_addMarker(frNet * net,frLayerNum lNum,const frBox & bbox)1106 void FlexDR::checkConnectivity_addMarker(frNet* net,
1107                                          frLayerNum lNum,
1108                                          const frBox& bbox)
1109 {
1110   auto regionQuery = getRegionQuery();
1111   auto marker = make_unique<frMarker>();
1112   marker->setBBox(bbox);
1113   marker->setLayerNum(lNum);
1114   marker->setConstraint(
1115       getDesign()->getTech()->getLayer(lNum)->getRecheckConstraint());
1116   marker->addSrc(net);
1117   marker->addVictim(net, make_tuple(lNum, bbox, false));
1118   marker->addAggressor(net, make_tuple(lNum, bbox, false));
1119   regionQuery->addMarker(marker.get());
1120   getDesign()->getTopBlock()->addMarker(std::move(marker));
1121 }
1122 
1123 // feedthrough and loop check
checkConnectivity(int iter)1124 void FlexDR::checkConnectivity(int iter)
1125 {
1126   ProfileTask profile("DR:checkConnectivity");
1127   bool isWrong = false;
1128 
1129   int batchSize = 131072;
1130   vector<vector<frNet*>> batches(1);
1131   for (auto& uPtr : getDesign()->getTopBlock()->getNets()) {
1132     auto net = uPtr.get();
1133     if (!net->isModified()) {
1134       continue;
1135     } else {
1136       net->setModified(false);
1137       if ((int) batches.back().size() < batchSize) {
1138         batches.back().push_back(net);
1139       } else {
1140         batches.push_back(vector<frNet*>());
1141         batches.back().push_back(net);
1142       }
1143     }
1144   }
1145   if (batches.size() && batches[0].empty()) {
1146     batches.clear();
1147   }
1148 
1149   // omp_set_num_threads(MAX_THREADS);
1150   omp_set_num_threads(1);
1151   for (auto& batch : batches) {
1152     // only for init batch vectors, prefix t = temporary
1153     vector<map<frCoord, vector<int>>> tHorzPathSegs(
1154         getTech()->getLayers().size());
1155     vector<map<frCoord, vector<int>>> tVertPathSegs(
1156         getTech()->getLayers().size());
1157     vector<vector<vector<int>>> tHorzVictims(getTech()->getLayers().size());
1158     vector<vector<vector<int>>> tVertVictims(getTech()->getLayers().size());
1159     vector<vector<vector<pair<frCoord, frCoord>>>> tHorzNewSegSpans(
1160         getTech()->getLayers().size());
1161     vector<vector<vector<pair<frCoord, frCoord>>>> tVertNewSegSpans(
1162         getTech()->getLayers().size());
1163 
1164     // prefix a = all batch
1165     // net->figs
1166     vector<vector<frConnFig*>> aNetDRObjs(batchSize);
1167     // net->layer->track->indices of DRObj
1168     vector<vector<map<frCoord, vector<int>>>> aHorzPathSegs(batchSize,
1169                                                             tHorzPathSegs);
1170     vector<vector<map<frCoord, vector<int>>>> aVertPathSegs(batchSize,
1171                                                             tVertPathSegs);
1172     // net->lnum->trackIdx->objIdxs
1173     vector<vector<vector<vector<int>>>> aHorzVictims(batchSize, tHorzVictims);
1174     vector<vector<vector<vector<int>>>> aVertVictims(batchSize, tVertVictims);
1175     // net->lnum->trackIdx->seg_start_end_pairs
1176     vector<vector<vector<vector<pair<frCoord, frCoord>>>>> aHorzNewSegSpans(
1177         batchSize, tHorzNewSegSpans);
1178     vector<vector<vector<vector<pair<frCoord, frCoord>>>>> aVertNewSegSpans(
1179         batchSize, tVertNewSegSpans);
1180     // net->term/instTerm->pt_layer
1181     vector<
1182         map<frBlockObject*, set<pair<frPoint, frLayerNum>>, frBlockObjectComp>>
1183         aPin2epMap(batchSize);
1184     vector<vector<frBlockObject*>> aNetPins(batchSize);
1185     vector<map<pair<frPoint, frLayerNum>, set<int>>> aNodeMap(batchSize);
1186     vector<vector<bool>> aAdjVisited(batchSize);
1187     vector<vector<int>> aAdjPrevIdx(batchSize);
1188     vector<bool> status(batchSize, false);
1189 
1190 // parallel
1191 #pragma omp parallel for schedule(static)
1192     for (int i = 0; i < (int) batch.size(); i++) {
1193       auto& net = batch[i];
1194       auto& initNetDRObjs = aNetDRObjs[i];
1195       auto& horzPathSegs = aHorzPathSegs[i];
1196       auto& vertPathSegs = aVertPathSegs[i];
1197       auto& horzVictims = aHorzVictims[i];
1198       auto& vertVictims = aVertVictims[i];
1199       auto& horzNewSegSpans = aHorzNewSegSpans[i];
1200       auto& vertNewSegSpans = aVertNewSegSpans[i];
1201 
1202       checkConnectivity_initDRObjs(net, initNetDRObjs);
1203       checkConnectivity_merge1(net, initNetDRObjs, horzPathSegs, vertPathSegs);
1204       checkConnectivity_merge2(net,
1205                                initNetDRObjs,
1206                                horzPathSegs,
1207                                vertPathSegs,
1208                                horzVictims,
1209                                vertVictims,
1210                                horzNewSegSpans,
1211                                vertNewSegSpans);
1212     }
1213 
1214     // sequential
1215     for (int i = 0; i < (int) batch.size(); i++) {
1216       auto& net = batch[i];
1217       auto& initNetDRObjs = aNetDRObjs[i];
1218       auto& horzPathSegs = aHorzPathSegs[i];
1219       auto& vertPathSegs = aVertPathSegs[i];
1220       auto& horzVictims = aHorzVictims[i];
1221       auto& vertVictims = aVertVictims[i];
1222       auto& horzNewSegSpans = aHorzNewSegSpans[i];
1223       auto& vertNewSegSpans = aVertNewSegSpans[i];
1224       checkConnectivity_merge3(net,
1225                                initNetDRObjs,
1226                                horzPathSegs,
1227                                vertPathSegs,
1228                                horzVictims,
1229                                vertVictims,
1230                                horzNewSegSpans,
1231                                vertNewSegSpans);
1232     }
1233 
1234 // parallel
1235 #pragma omp parallel for schedule(static)
1236     for (int i = 0; i < (int) batch.size(); i++) {
1237       auto& net = batch[i];
1238       auto& netDRObjs = aNetDRObjs[i];
1239       auto& pin2epMap = aPin2epMap[i];
1240       auto& netPins = aNetPins[i];
1241       auto& nodeMap = aNodeMap[i];
1242       auto& adjVisited = aAdjVisited[i];
1243       auto& adjPrevIdx = aAdjPrevIdx[i];
1244       netDRObjs.clear();
1245       checkConnectivity_initDRObjs(net, netDRObjs);
1246       checkConnectivity_pin2epMap(net, netDRObjs, pin2epMap);
1247       checkConnectivity_nodeMap(net, netDRObjs, netPins, pin2epMap, nodeMap);
1248 
1249       int nNetRouteObjs = (int) netDRObjs.size();
1250       int nNetObjs = (int) netDRObjs.size() + (int) netPins.size();
1251       status[i] = checkConnectivity_astar(
1252           net, adjVisited, adjPrevIdx, nodeMap, netDRObjs, nNetRouteObjs, nNetObjs);
1253     }
1254 
1255     // sequential
1256     for (int i = 0; i < (int) batch.size(); i++) {
1257       auto& net = batch[i];
1258       auto& netDRObjs = aNetDRObjs[i];
1259       auto& netPins = aNetPins[i];
1260       auto& nodeMap = aNodeMap[i];
1261       auto& adjVisited = aAdjVisited[i];
1262 
1263       int gCnt = (int) netDRObjs.size();
1264       int nCnt = (int) netDRObjs.size() + (int) netPins.size();
1265 
1266       if (!status[i]) {
1267         cout << "Error: checkConnectivity break, net " << net->getName() << endl
1268              << "Objs not visited:\n";
1269         for (int idx = 0; idx < (int)adjVisited.size(); idx++) {
1270           if (!adjVisited[idx]) {
1271             if (idx < (int)netDRObjs.size())
1272               cout << *(netDRObjs[idx]) << "\n";
1273             else
1274               cout << *(netPins[idx - netDRObjs.size()]) << "\n";
1275           }
1276         }
1277         isWrong = true;
1278       } else {
1279         // get lock
1280         // delete / shrink netRouteObjs,
1281         checkConnectivity_final(
1282             net, netDRObjs, netPins, adjVisited, gCnt, nCnt, nodeMap);
1283         // release lock
1284       }
1285     }
1286   }
1287 
1288   if (isWrong) {
1289     if (graphics_) {
1290       graphics_->debugWholeDesign();
1291     }
1292     auto writer = io::Writer(getDesign(), logger_);
1293     writer.updateDb(db_);
1294     logger_->error(utl::DRT, 206, "checkConnectivity error");
1295   }
1296 }
1297