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 "ta/FlexTA.h"
30 
31 using namespace std;
32 using namespace fr;
33 
initTracks()34 void FlexTAWorker::initTracks()
35 {
36   trackLocs_.clear();
37   const int numLayers = getDesign()->getTech()->getLayers().size();
38   trackLocs_.resize(numLayers);
39   vector<set<frCoord>> trackCoordSets(numLayers);
40   // uPtr for tp
41   for (int lNum = 0; lNum < (int) numLayers; lNum++) {
42     auto layer = getDesign()->getTech()->getLayer(lNum);
43     if (layer->getType() != frLayerTypeEnum::ROUTING) {
44       continue;
45     }
46     if (layer->getDir() != getDir()) {
47       continue;
48     }
49     for (auto& tp : getDesign()->getTopBlock()->getTrackPatterns(lNum)) {
50       if ((getDir() == frcHorzPrefRoutingDir && tp->isHorizontal() == false)
51           || (getDir() == frcVertPrefRoutingDir
52               && tp->isHorizontal() == true)) {
53         bool isH = (getDir() == frcHorzPrefRoutingDir);
54         frCoord lowCoord
55             = (isH ? getRouteBox().bottom() : getRouteBox().left());
56         frCoord highCoord = (isH ? getRouteBox().top() : getRouteBox().right());
57         int trackNum
58             = (lowCoord - tp->getStartCoord()) / (int) tp->getTrackSpacing();
59         if (trackNum < 0) {
60           trackNum = 0;
61         }
62         if (trackNum * (int) tp->getTrackSpacing() + tp->getStartCoord()
63             < lowCoord) {
64           trackNum++;
65         }
66         for (; trackNum < (int) tp->getNumTracks()
67                && trackNum * (int) tp->getTrackSpacing() + tp->getStartCoord()
68                       < highCoord;
69              trackNum++) {
70           frCoord trackCoord
71               = trackNum * tp->getTrackSpacing() + tp->getStartCoord();
72           trackCoordSets[lNum].insert(trackCoord);
73         }
74       }
75     }
76   }
77   for (int i = 0; i < (int) trackCoordSets.size(); i++) {
78     for (auto coord : trackCoordSets[i]) {
79       trackLocs_[i].push_back(coord);
80     }
81   }
82 }
83 
84 // use prefAp, otherwise return false
initIroute_helper_pin(frGuide * guide,frCoord & maxBegin,frCoord & minEnd,set<frCoord> & downViaCoordSet,set<frCoord> & upViaCoordSet,int & wlen,frCoord & wlen2)85 bool FlexTAWorker::initIroute_helper_pin(frGuide* guide,
86                                          frCoord& maxBegin,
87                                          frCoord& minEnd,
88                                          set<frCoord>& downViaCoordSet,
89                                          set<frCoord>& upViaCoordSet,
90                                          int& wlen,
91                                          frCoord& wlen2)
92 {
93   frPoint bp, ep;
94   guide->getPoints(bp, ep);
95   if (!(bp == ep)) {
96     return false;
97   }
98 
99   auto net = guide->getNet();
100   auto layerNum = guide->getBeginLayerNum();
101   bool isH = (getDir() == frPrefRoutingDirEnum::frcHorzPrefRoutingDir);
102   bool hasDown = false;
103   bool hasUp = false;
104 
105   vector<frGuide*> nbrGuides;
106   auto rq = getRegionQuery();
107   frBox box;
108   box.set(bp, bp);
109   nbrGuides.clear();
110   if (layerNum - 2 >= BOTTOM_ROUTING_LAYER) {
111     rq->queryGuide(box, layerNum - 2, nbrGuides);
112     for (auto& nbrGuide : nbrGuides) {
113       if (nbrGuide->getNet() == net) {
114         hasDown = true;
115         break;
116       }
117     }
118   }
119   nbrGuides.clear();
120   if (layerNum + 2 < (int) design_->getTech()->getLayers().size()) {
121     rq->queryGuide(box, layerNum + 2, nbrGuides);
122     for (auto& nbrGuide : nbrGuides) {
123       if (nbrGuide->getNet() == net) {
124         hasUp = true;
125         break;
126       }
127     }
128   }
129 
130   vector<frBlockObject*> result;
131   box.set(bp, bp);
132   rq->queryGRPin(box, result);
133   frTransform instXform;  // (0,0), frcR0
134   frTransform shiftXform;
135   frTerm* trueTerm = nullptr;
136   for (auto& term : result) {
137     frInst* inst = nullptr;
138     if (term->typeId() == frcInstTerm) {
139       if (static_cast<frInstTerm*>(term)->getNet() != net) {
140         continue;
141       }
142       inst = static_cast<frInstTerm*>(term)->getInst();
143       inst->getTransform(shiftXform);
144       shiftXform.set(frOrient(frcR0));
145       inst->getUpdatedXform(instXform);
146       trueTerm = static_cast<frInstTerm*>(term)->getTerm();
147     } else if (term->typeId() == frcTerm) {
148       if (static_cast<frTerm*>(term)->getNet() != net) {
149         continue;
150       }
151       trueTerm = static_cast<frTerm*>(term);
152     }
153     if (trueTerm) {
154       int pinIdx = 0;
155       int pinAccessIdx = (inst) ? inst->getPinAccessIdx() : -1;
156       for (auto& pin : trueTerm->getPins()) {
157         frAccessPoint* ap = nullptr;
158         if (inst) {
159           ap = (static_cast<frInstTerm*>(term)->getAccessPoints())[pinIdx];
160         }
161         if (!pin->hasPinAccess()) {
162           continue;
163         }
164         if (pinAccessIdx == -1) {
165           continue;
166         }
167         if (ap == nullptr) {
168           continue;
169         }
170         frPoint apBp;
171         ap->getPoint(apBp);
172         auto bNum = ap->getLayerNum();
173         apBp.transform(shiftXform);
174         if (layerNum == bNum && getRouteBox().contains(apBp)) {
175           wlen2 = isH ? apBp.y() : apBp.x();
176           maxBegin = isH ? apBp.x() : apBp.y();
177           minEnd = isH ? apBp.x() : apBp.y();
178           wlen = 0;
179           if (hasDown) {
180             downViaCoordSet.insert(maxBegin);
181           }
182           if (hasUp) {
183             upViaCoordSet.insert(maxBegin);
184           }
185           return true;
186         }
187         pinIdx++;
188       }
189     }
190   }
191 
192   return false;
193 }
194 
initIroute_helper(frGuide * guide,frCoord & maxBegin,frCoord & minEnd,set<frCoord> & downViaCoordSet,set<frCoord> & upViaCoordSet,int & wlen,frCoord & wlen2)195 void FlexTAWorker::initIroute_helper(frGuide* guide,
196                                      frCoord& maxBegin,
197                                      frCoord& minEnd,
198                                      set<frCoord>& downViaCoordSet,
199                                      set<frCoord>& upViaCoordSet,
200                                      int& wlen,
201                                      frCoord& wlen2)
202 {
203   if (!initIroute_helper_pin(guide,
204                              maxBegin,
205                              minEnd,
206                              downViaCoordSet,
207                              upViaCoordSet,
208                              wlen,
209                              wlen2)) {
210     initIroute_helper_generic(
211         guide, maxBegin, minEnd, downViaCoordSet, upViaCoordSet, wlen, wlen2);
212   }
213 }
214 
initIroute_helper_generic_helper(frGuide * guide,frCoord & wlen2)215 void FlexTAWorker::initIroute_helper_generic_helper(frGuide* guide,
216                                                     frCoord& wlen2)
217 {
218   frPoint bp, ep;
219   guide->getPoints(bp, ep);
220   auto net = guide->getNet();
221   bool isH = (getDir() == frPrefRoutingDirEnum::frcHorzPrefRoutingDir);
222 
223   auto rq = getRegionQuery();
224   vector<frBlockObject*> result;
225 
226   frBox box;
227   box.set(bp, bp);
228   rq->queryGRPin(box, result);
229   if (!(ep == bp)) {
230     box.set(ep, ep);
231     rq->queryGRPin(box, result);
232   }
233   frTransform instXform;  // (0,0), frcR0
234   frTransform shiftXform;
235   frTerm* trueTerm = nullptr;
236   for (auto& term : result) {
237     frInst* inst = nullptr;
238     if (term->typeId() == frcInstTerm) {
239       if (static_cast<frInstTerm*>(term)->getNet() != net) {
240         continue;
241       }
242       inst = static_cast<frInstTerm*>(term)->getInst();
243       inst->getTransform(shiftXform);
244       shiftXform.set(frOrient(frcR0));
245       inst->getUpdatedXform(instXform);
246       trueTerm = static_cast<frInstTerm*>(term)->getTerm();
247     } else if (term->typeId() == frcTerm) {
248       if (static_cast<frTerm*>(term)->getNet() != net) {
249         continue;
250       }
251       trueTerm = static_cast<frTerm*>(term);
252     }
253     if (trueTerm) {
254       int pinIdx = 0;
255       int pinAccessIdx = (inst) ? inst->getPinAccessIdx() : -1;
256       for (auto& pin : trueTerm->getPins()) {
257         frAccessPoint* ap = nullptr;
258         if (inst) {
259           ap = (static_cast<frInstTerm*>(term)->getAccessPoints())[pinIdx];
260         }
261         if (!pin->hasPinAccess()) {
262           continue;
263         }
264         if (pinAccessIdx == -1) {
265           continue;
266         }
267         if (ap == nullptr) {
268           continue;
269         }
270         frPoint apBp;
271         ap->getPoint(apBp);
272         apBp.transform(shiftXform);
273         if (getRouteBox().contains(apBp)) {
274           wlen2 = isH ? apBp.y() : apBp.x();
275           return;
276         }
277         pinIdx++;
278       }
279     };  // to do @@@@@
280     wlen2 = 0;
281   }
282 }
283 
initIroute_helper_generic(frGuide * guide,frCoord & minBegin,frCoord & maxEnd,set<frCoord> & downViaCoordSet,set<frCoord> & upViaCoordSet,int & wlen,frCoord & wlen2)284 void FlexTAWorker::initIroute_helper_generic(frGuide* guide,
285                                              frCoord& minBegin,
286                                              frCoord& maxEnd,
287                                              set<frCoord>& downViaCoordSet,
288                                              set<frCoord>& upViaCoordSet,
289                                              int& wlen,
290                                              frCoord& wlen2)
291 {
292   auto net = guide->getNet();
293   auto layerNum = guide->getBeginLayerNum();
294   bool hasMinBegin = false;
295   bool hasMaxEnd = false;
296   minBegin = std::numeric_limits<frCoord>::max();
297   maxEnd = std::numeric_limits<frCoord>::min();
298   wlen = 0;
299   // wlen2       = std::numeric_limits<frCoord>::max();
300   bool isH = (getDir() == frPrefRoutingDirEnum::frcHorzPrefRoutingDir);
301   downViaCoordSet.clear();
302   upViaCoordSet.clear();
303   frPoint nbrBp, nbrEp;
304   frPoint nbrSegBegin, nbrSegEnd;
305 
306   frPoint bp, ep;
307   guide->getPoints(bp, ep);
308   frPoint cp;
309   // layerNum in FlexTAWorker
310   vector<frGuide*> nbrGuides;
311   auto rq = getRegionQuery();
312   frBox box;
313   for (int i = 0; i < 2; i++) {
314     nbrGuides.clear();
315     // check left
316     if (i == 0) {
317       box.set(bp, bp);
318       cp = bp;
319       // check right
320     } else {
321       box.set(ep, ep);
322       cp = ep;
323     }
324     if (layerNum - 2 >= BOTTOM_ROUTING_LAYER) {
325       rq->queryGuide(box, layerNum - 2, nbrGuides);
326     }
327     if (layerNum + 2 < (int) design_->getTech()->getLayers().size()) {
328       rq->queryGuide(box, layerNum + 2, nbrGuides);
329     }
330     for (auto& nbrGuide : nbrGuides) {
331       if (nbrGuide->getNet() == net) {
332         nbrGuide->getPoints(nbrBp, nbrEp);
333         if (!nbrGuide->hasRoutes()) {
334           // via location assumed in center
335           auto psLNum = nbrGuide->getBeginLayerNum();
336           if (psLNum == layerNum - 2) {
337             downViaCoordSet.insert((isH ? nbrBp.x() : nbrBp.y()));
338           } else {
339             upViaCoordSet.insert((isH ? nbrBp.x() : nbrBp.y()));
340           }
341         } else {
342           for (auto& connFig : nbrGuide->getRoutes()) {
343             if (connFig->typeId() == frcPathSeg) {
344               auto obj = static_cast<frPathSeg*>(connFig.get());
345               obj->getPoints(nbrSegBegin, nbrSegEnd);
346               auto psLNum = obj->getLayerNum();
347               if (i == 0) {
348                 minBegin
349                     = min(minBegin, (isH ? nbrSegBegin.x() : nbrSegBegin.y()));
350                 hasMinBegin = true;
351               } else {
352                 maxEnd = max(maxEnd, (isH ? nbrSegBegin.x() : nbrSegBegin.y()));
353                 hasMaxEnd = true;
354               }
355               if (psLNum == layerNum - 2) {
356                 downViaCoordSet.insert(
357                     (isH ? nbrSegBegin.x() : nbrSegBegin.y()));
358               } else {
359                 upViaCoordSet.insert((isH ? nbrSegBegin.x() : nbrSegBegin.y()));
360               }
361             }
362           }
363         }
364         if (cp == nbrEp) {
365           wlen -= 1;
366         }
367         if (cp == nbrBp) {
368           wlen += 1;
369         }
370       }
371     }
372   }
373 
374   if (!hasMinBegin) {
375     minBegin = (isH ? bp.x() : bp.y());
376   }
377   if (!hasMaxEnd) {
378     maxEnd = (isH ? ep.x() : ep.y());
379   }
380   if (minBegin > maxEnd) {
381     swap(minBegin, maxEnd);
382   }
383   if (minBegin == maxEnd) {
384     maxEnd += 1;
385   }
386 
387   // wlen2 purely depends on ap regardless of track
388   initIroute_helper_generic_helper(guide, wlen2);
389 }
390 
initIroute(frGuide * guide)391 void FlexTAWorker::initIroute(frGuide* guide)
392 {
393   auto iroute = make_unique<taPin>();
394   iroute->setGuide(guide);
395   frBox guideBox;
396   guide->getBBox(guideBox);
397   auto layerNum = guide->getBeginLayerNum();
398   bool isExt = !(getRouteBox().contains(guideBox));
399   if (isExt) {
400     // extIroute empty, skip
401     if (guide->getRoutes().empty()) {
402       return;
403     }
404   }
405 
406   frCoord maxBegin, minEnd;
407   set<frCoord> downViaCoordSet, upViaCoordSet;
408   int wlen = 0;
409   frCoord wlen2 = std::numeric_limits<frCoord>::max();
410   initIroute_helper(
411       guide, maxBegin, minEnd, downViaCoordSet, upViaCoordSet, wlen, wlen2);
412 
413   frCoord trackLoc = 0;
414   frPoint segBegin, segEnd;
415   bool isH = (getDir() == frPrefRoutingDirEnum::frcHorzPrefRoutingDir);
416   // set trackIdx
417   if (!isInitTA()) {
418     for (auto& connFig : guide->getRoutes()) {
419       if (connFig->typeId() == frcPathSeg) {
420         auto obj = static_cast<frPathSeg*>(connFig.get());
421         obj->getPoints(segBegin, segEnd);
422         trackLoc = (isH ? segBegin.y() : segBegin.x());
423       }
424     }
425   } else {
426     trackLoc = 0;
427   }
428 
429   unique_ptr<taPinFig> ps = make_unique<taPathSeg>();
430   ps->setNet(guide->getNet());
431   auto rptr = static_cast<taPathSeg*>(ps.get());
432   if (isH) {
433     rptr->setPoints(frPoint(maxBegin, trackLoc), frPoint(minEnd, trackLoc));
434   } else {
435     rptr->setPoints(frPoint(trackLoc, maxBegin), frPoint(trackLoc, minEnd));
436   }
437   rptr->setLayerNum(layerNum);
438   if (guide->getNet() && guide->getNet()->getNondefaultRule()) {
439     frNonDefaultRule* ndr = guide->getNet()->getNondefaultRule();
440     auto style
441         = getDesign()->getTech()->getLayer(layerNum)->getDefaultSegStyle();
442     style.setWidth(
443         max((int) style.getWidth(), ndr->getWidth(layerNum / 2 - 1)));
444     rptr->setStyle(style);
445   } else
446     rptr->setStyle(
447         getDesign()->getTech()->getLayer(layerNum)->getDefaultSegStyle());
448   // owner set when add to taPin
449   iroute->addPinFig(std::move(ps));
450   frViaDef* viaDef;
451   for (auto coord : upViaCoordSet) {
452     if (guide->getNet()->getNondefaultRule()
453         && guide->getNet()->getNondefaultRule()->getPrefVia((layerNum + 2) / 2
454                                                             - 1))
455       viaDef = guide->getNet()->getNondefaultRule()->getPrefVia(
456           (layerNum + 2) / 2 - 1);
457     else
458       viaDef
459           = getDesign()->getTech()->getLayer(layerNum + 1)->getDefaultViaDef();
460     unique_ptr<taPinFig> via = make_unique<taVia>(viaDef);
461     via->setNet(guide->getNet());
462     auto rViaPtr = static_cast<taVia*>(via.get());
463     rViaPtr->setOrigin(isH ? frPoint(coord, trackLoc)
464                            : frPoint(trackLoc, coord));
465     iroute->addPinFig(std::move(via));
466   }
467   for (auto coord : downViaCoordSet) {
468     if (guide->getNet()->getNondefaultRule()
469         && guide->getNet()->getNondefaultRule()->getPrefVia(layerNum / 2 - 1))
470       viaDef
471           = guide->getNet()->getNondefaultRule()->getPrefVia(layerNum / 2 - 1);
472     else
473       viaDef
474           = getDesign()->getTech()->getLayer(layerNum - 1)->getDefaultViaDef();
475     unique_ptr<taPinFig> via = make_unique<taVia>(viaDef);
476     via->setNet(guide->getNet());
477     auto rViaPtr = static_cast<taVia*>(via.get());
478     rViaPtr->setOrigin(isH ? frPoint(coord, trackLoc)
479                            : frPoint(trackLoc, coord));
480     iroute->addPinFig(std::move(via));
481   }
482   iroute->setWlenHelper(wlen);
483   if (wlen2 < std::numeric_limits<frCoord>::max()) {
484     iroute->setWlenHelper2(wlen2);
485   }
486   addIroute(std::move(iroute), isExt);
487 }
488 
initIroutes()489 void FlexTAWorker::initIroutes()
490 {
491   frRegionQuery::Objects<frGuide> result;
492   auto regionQuery = getRegionQuery();
493   for (int lNum = 0; lNum < (int) getDesign()->getTech()->getLayers().size();
494        lNum++) {
495     auto layer = getDesign()->getTech()->getLayer(lNum);
496     if (layer->getType() != frLayerTypeEnum::ROUTING) {
497       continue;
498     }
499     if (layer->getDir() != getDir()) {
500       continue;
501     }
502     result.clear();
503     regionQuery->queryGuide(getExtBox(), lNum, result);
504     // cout <<endl <<"query1:" <<endl;
505     for (auto& [boostb, guide] : result) {
506       frPoint pt1, pt2;
507       guide->getPoints(pt1, pt2);
508       // cout <<endl;
509       initIroute(guide);
510     }
511   }
512 }
513 
initCosts()514 void FlexTAWorker::initCosts()
515 {
516   bool isH = (getDir() == frPrefRoutingDirEnum::frcHorzPrefRoutingDir);
517   frPoint bp, ep;
518   frCoord bc, ec;
519   // init cost
520   if (isInitTA()) {
521     for (auto& iroute : iroutes_) {
522       auto pitch = getDesign()
523                        ->getTech()
524                        ->getLayer(iroute->getGuide()->getBeginLayerNum())
525                        ->getPitch();
526       for (auto& uPinFig : iroute->getFigs()) {
527         if (uPinFig->typeId() == tacPathSeg) {
528           auto obj = static_cast<taPathSeg*>(uPinFig.get());
529           obj->getPoints(bp, ep);
530           bc = isH ? bp.x() : bp.y();
531           ec = isH ? ep.x() : ep.y();
532           iroute->setCost(ec - bc + iroute->hasWlenHelper2() * pitch * 1000);
533         }
534       }
535     }
536   } else {
537     auto& workerRegionQuery = getWorkerRegionQuery();
538     // update worker rq
539     for (auto& iroute : iroutes_) {
540       for (auto& uPinFig : iroute->getFigs()) {
541         workerRegionQuery.add(uPinFig.get());
542         addCost(uPinFig.get());
543       }
544     }
545     for (auto& iroute : extIroutes_) {
546       for (auto& uPinFig : iroute->getFigs()) {
547         workerRegionQuery.add(uPinFig.get());
548         addCost(uPinFig.get());
549       }
550     }
551     // update iroute cost
552     for (auto& iroute : iroutes_) {
553       frUInt4 drcCost = 0;
554       frCoord trackLoc = std::numeric_limits<frCoord>::max();
555       for (auto& uPinFig : iroute->getFigs()) {
556         if (uPinFig->typeId() == tacPathSeg) {
557           static_cast<taPathSeg*>(uPinFig.get())->getPoints(bp, ep);
558           if (isH) {
559             trackLoc = bp.y();
560           } else {
561             trackLoc = bp.x();
562           }
563           break;
564         }
565       }
566       if (trackLoc == std::numeric_limits<frCoord>::max()) {
567         cout << "Error: FlexTAWorker::initCosts does not find trackLoc" << endl;
568         exit(1);
569       }
570       assignIroute_getCost(iroute.get(), trackLoc, drcCost);
571       iroute->setCost(drcCost);
572       totCost_ += drcCost;
573     }
574   }
575 }
576 
sortIroutes()577 void FlexTAWorker::sortIroutes()
578 {
579   // init cost
580   if (isInitTA()) {
581     for (auto& iroute : iroutes_) {
582       addToReassignIroutes(iroute.get());
583     }
584   } else {
585     for (auto& iroute : iroutes_) {
586       if (iroute->getCost()) {
587         addToReassignIroutes(iroute.get());
588       }
589     }
590   }
591 }
592 
initFixedObjs_helper(const frBox & box,frCoord bloatDist,frLayerNum lNum,frNet * net)593 void FlexTAWorker::initFixedObjs_helper(const frBox& box,
594                                         frCoord bloatDist,
595                                         frLayerNum lNum,
596                                         frNet* net)
597 {
598   frBox bloatBox;
599   box.bloat(bloatDist, bloatBox);
600   auto con = getDesign()->getTech()->getLayer(lNum)->getShortConstraint();
601   bool isH = (getDir() == frPrefRoutingDirEnum::frcHorzPrefRoutingDir);
602   int idx1, idx2;
603   // frCoord x1, x2;
604   if (isH) {
605     getTrackIdx(bloatBox.bottom(), bloatBox.top(), lNum, idx1, idx2);
606   } else {
607     getTrackIdx(bloatBox.left(), bloatBox.right(), lNum, idx1, idx2);
608   }
609   auto& trackLocs = getTrackLocs(lNum);
610   auto& workerRegionQuery = getWorkerRegionQuery();
611   for (int i = idx1; i <= idx2; i++) {
612     // new
613     // auto &track = tracks[i];
614     // track.addToCost(net, x1, x2, 0);
615     // track.addToCost(net, x1, x2, 1);
616     // track.addToCost(net, x1, x2, 2);
617     // old
618     auto trackLoc = trackLocs[i];
619     frBox tmpBox;
620     if (isH) {
621       tmpBox.set(bloatBox.left(), trackLoc, bloatBox.right(), trackLoc);
622     } else {
623       tmpBox.set(trackLoc, bloatBox.bottom(), trackLoc, bloatBox.top());
624     }
625     workerRegionQuery.addCost(tmpBox, lNum, net, con);
626   }
627 }
628 
initFixedObjs()629 void FlexTAWorker::initFixedObjs()
630 {
631   frRegionQuery::Objects<frBlockObject> result;
632   frBox box;
633   frCoord width = 0;
634   frCoord bloatDist = 0;
635   for (auto layerNum = getTech()->getBottomLayerNum();
636        layerNum <= getTech()->getTopLayerNum();
637        ++layerNum) {
638     result.clear();
639     if (getTech()->getLayer(layerNum)->getType() != frLayerTypeEnum::ROUTING
640         || getTech()->getLayer(layerNum)->getDir() != getDir()) {
641       continue;
642     }
643     width = getTech()->getLayer(layerNum)->getWidth();
644     getRegionQuery()->query(getExtBox(), layerNum, result);
645     for (auto& [bounds, obj] : result) {
646       bounds.bloat(-1, box);
647       // instterm term
648       if (obj->typeId() == frcTerm || obj->typeId() == frcInstTerm) {
649         bloatDist = TASHAPEBLOATWIDTH * width;
650         frNet* netPtr = nullptr;
651         if (obj->typeId() == frcTerm) {
652           netPtr = static_cast<frTerm*>(obj)->getNet();
653         } else {
654           netPtr = static_cast<frInstTerm*>(obj)->getNet();
655         }
656         initFixedObjs_helper(box, bloatDist, layerNum, netPtr);
657         // snet
658       } else if (obj->typeId() == frcPathSeg || obj->typeId() == frcVia) {
659         bloatDist = initFixedObjs_calcBloatDist(obj, layerNum, bounds);
660         frNet* netPtr = nullptr;
661         if (obj->typeId() == frcPathSeg) {
662           netPtr = static_cast<frPathSeg*>(obj)->getNet();
663         } else {
664           netPtr = static_cast<frVia*>(obj)->getNet();
665         }
666         initFixedObjs_helper(box, bloatDist, layerNum, netPtr);
667         if (DBPROCESSNODE == "GF14_13M_3Mx_2Cx_4Kx_2Hx_2Gx_LB"
668             && getTech()->getLayer(layerNum)->getType()
669                    == frLayerTypeEnum::ROUTING) {
670           // down-via
671           if (layerNum - 2 >= getDesign()->getTech()->getBottomLayerNum()
672               && getTech()->getLayer(layerNum - 2)->getType()
673                      == frLayerTypeEnum::ROUTING) {
674             auto cutLayer = getTech()->getLayer(layerNum - 1);
675             frBox viaBox;
676             auto via = make_unique<frVia>(cutLayer->getDefaultViaDef());
677             via->getLayer2BBox(viaBox);
678             frCoord viaWidth = viaBox.width();
679             // only add for fat via
680             if (viaWidth > width) {
681               bloatDist = initFixedObjs_calcOBSBloatDistVia(
682                   cutLayer->getDefaultViaDef(), layerNum, bounds, false);
683               initFixedObjs_helper(box, bloatDist, layerNum, netPtr);
684             }
685           }
686           // up-via
687           if (layerNum + 2 < (int) design_->getTech()->getLayers().size()
688               && getTech()->getLayer(layerNum + 2)->getType()
689                      == frLayerTypeEnum::ROUTING) {
690             auto cutLayer = getTech()->getLayer(layerNum + 1);
691             frBox viaBox;
692             auto via = make_unique<frVia>(cutLayer->getDefaultViaDef());
693             via->getLayer1BBox(viaBox);
694             frCoord viaWidth = viaBox.width();
695             // only add for fat via
696             if (viaWidth > width) {
697               bloatDist = initFixedObjs_calcOBSBloatDistVia(
698                   cutLayer->getDefaultViaDef(), layerNum, bounds, false);
699               initFixedObjs_helper(box, bloatDist, layerNum, netPtr);
700             }
701           }
702         }
703       } else if (obj->typeId() == frcBlockage
704                  || obj->typeId() == frcInstBlockage) {
705         bloatDist = initFixedObjs_calcBloatDist(obj, layerNum, bounds);
706         initFixedObjs_helper(box, bloatDist, layerNum, nullptr);
707 
708         if (DBPROCESSNODE == "GF14_13M_3Mx_2Cx_4Kx_2Hx_2Gx_LB") {
709           // block track for up-via and down-via for fat MACRO OBS
710           bool isMacro = false;
711           if (obj->typeId() == frcBlockage) {
712             isMacro = true;
713           } else {
714             auto inst = (static_cast<frInstBlockage*>(obj))->getInst();
715             if (inst->getRefBlock()->getMacroClass() == MacroClassEnum::BLOCK
716                 || isPad(inst->getRefBlock()->getMacroClass())
717                 || inst->getRefBlock()->getMacroClass()
718                        == MacroClassEnum::RING) {
719               isMacro = true;
720             }
721           }
722           bool isFatOBS = true;
723           if (bounds.width() <= 2 * width) {
724             isFatOBS = false;
725           }
726           if (isMacro && isFatOBS) {
727             // down-via
728             if (layerNum - 2 >= getDesign()->getTech()->getBottomLayerNum()
729                 && getTech()->getLayer(layerNum - 2)->getType()
730                        == frLayerTypeEnum::ROUTING) {
731               auto cutLayer = getTech()->getLayer(layerNum - 1);
732               bloatDist = initFixedObjs_calcOBSBloatDistVia(
733                   cutLayer->getDefaultViaDef(), layerNum, bounds);
734               initFixedObjs_helper(box, bloatDist, layerNum - 2, nullptr);
735             }
736             // up-via
737             if (layerNum + 2 < (int) design_->getTech()->getLayers().size()
738                 && getTech()->getLayer(layerNum + 2)->getType()
739                        == frLayerTypeEnum::ROUTING) {
740               auto cutLayer = getTech()->getLayer(layerNum + 1);
741               bloatDist = initFixedObjs_calcOBSBloatDistVia(
742                   cutLayer->getDefaultViaDef(), layerNum, bounds);
743               initFixedObjs_helper(box, bloatDist, layerNum + 2, nullptr);
744             }
745           }
746         }
747       } else {
748         cout << "Warning: unsupported type in initFixedObjs" << endl;
749       }
750     }
751   }
752 }
753 
initFixedObjs_calcOBSBloatDistVia(frViaDef * viaDef,const frLayerNum lNum,const frBox & box,bool isOBS)754 frCoord FlexTAWorker::initFixedObjs_calcOBSBloatDistVia(frViaDef* viaDef,
755                                                         const frLayerNum lNum,
756                                                         const frBox& box,
757                                                         bool isOBS)
758 {
759   auto layer = getTech()->getLayer(lNum);
760   frBox viaBox;
761   auto via = make_unique<frVia>(viaDef);
762   if (viaDef->getLayer1Num() == lNum) {
763     via->getLayer1BBox(viaBox);
764   } else {
765     via->getLayer2BBox(viaBox);
766   }
767   frCoord viaWidth = viaBox.width();
768   frCoord viaLength = viaBox.length();
769 
770   frCoord obsWidth = box.width();
771   if (USEMINSPACING_OBS && isOBS) {
772     obsWidth = layer->getWidth();
773   }
774 
775   frCoord bloatDist = 0;
776   auto con = getTech()->getLayer(lNum)->getMinSpacing();
777   if (con) {
778     if (con->typeId() == frConstraintTypeEnum::frcSpacingConstraint) {
779       bloatDist = static_cast<frSpacingConstraint*>(con)->getMinSpacing();
780     } else if (con->typeId()
781                == frConstraintTypeEnum::frcSpacingTablePrlConstraint) {
782       bloatDist = static_cast<frSpacingTablePrlConstraint*>(con)->find(
783           obsWidth, viaWidth /*prl*/);
784     } else if (con->typeId()
785                == frConstraintTypeEnum::frcSpacingTableTwConstraint) {
786       bloatDist = static_cast<frSpacingTableTwConstraint*>(con)->find(
787           obsWidth, viaWidth, viaWidth /*prl*/);
788     }
789   }
790   // at least via enclosure should not short with obs (OBS has issue with
791   // wrongway and PG has issue with prefDir)
792   // TODO: generalize the following
793   if (isOBS) {
794     bloatDist += viaLength / 2;
795   } else {
796     bloatDist += viaWidth / 2;
797   }
798   return bloatDist;
799 }
800 
initFixedObjs_calcBloatDist(frBlockObject * obj,const frLayerNum lNum,const frBox & box)801 frCoord FlexTAWorker::initFixedObjs_calcBloatDist(frBlockObject* obj,
802                                                   const frLayerNum lNum,
803                                                   const frBox& box)
804 {
805   auto layer = getTech()->getLayer(lNum);
806   frCoord width = layer->getWidth();
807   // use width if minSpc does not exist
808   frCoord bloatDist = width;
809   frCoord objWidth = box.width();
810   frCoord prl = (layer->getDir() == frPrefRoutingDirEnum::frcHorzPrefRoutingDir)
811                     ? (box.right() - box.left())
812                     : (box.top() - box.bottom());
813   if (obj->typeId() == frcBlockage || obj->typeId() == frcInstBlockage) {
814     if (USEMINSPACING_OBS) {
815       objWidth = width;
816     }
817   }
818   auto con = getTech()->getLayer(lNum)->getMinSpacing();
819   if (con) {
820     if (con->typeId() == frConstraintTypeEnum::frcSpacingConstraint) {
821       bloatDist = static_cast<frSpacingConstraint*>(con)->getMinSpacing();
822     } else if (con->typeId()
823                == frConstraintTypeEnum::frcSpacingTablePrlConstraint) {
824       bloatDist
825           = static_cast<frSpacingTablePrlConstraint*>(con)->find(objWidth, prl);
826     } else if (con->typeId()
827                == frConstraintTypeEnum::frcSpacingTableTwConstraint) {
828       bloatDist = static_cast<frSpacingTableTwConstraint*>(con)->find(
829           objWidth, width, prl);
830     }
831   }
832   // assuming the wire width is width
833   bloatDist += width / 2;
834   return bloatDist;
835 }
836 
init()837 void FlexTAWorker::init()
838 {
839   rq_.init();
840   initTracks();
841   if (getTAIter() != -1) {
842     initFixedObjs();
843   }
844   initIroutes();
845   if (getTAIter() != -1) {
846     initCosts();
847     sortIroutes();
848   }
849 }
850