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