1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #include "rcx/extRCap.h"
34 #include "utl/Logger.h"
35 
36 namespace rcx {
37 
38 using utl::RCX;
39 
allocateOverUnderMaps(uint layerCnt)40 uint extMain::allocateOverUnderMaps(uint layerCnt) {
41   uint cnt = layerCnt + 1;
42   _overUnderPlaneLayerMap = new uint* [layerCnt + 1];
43   uint ii;
44   for (ii = 1; ii < layerCnt + 1; ii++) {
45     _overUnderPlaneLayerMap[ii] = new uint[layerCnt + 1];
46     for (uint jj = 1; jj < layerCnt + 1; jj++) {
47       _overUnderPlaneLayerMap[ii][jj] = 0;
48     }
49   }
50   for (ii = 2; ii < layerCnt + 1; ii += 2) {
51     uint mUnder = ii - 1;
52 
53     uint mOver = ii + 1;
54     if (mOver > layerCnt)
55       break;
56 
57     _overUnderPlaneLayerMap[mUnder][mOver] = cnt;
58     cnt++;
59   }
60   for (ii = 3; ii < layerCnt + 1; ii += 2) {
61     uint mUnder = ii - 1;
62 
63     uint mOver = ii + 1;
64     if (mOver > layerCnt)
65       break;
66 
67     _overUnderPlaneLayerMap[mUnder][mOver] = cnt;
68     cnt++;
69   }
70   return cnt;
71 }
initPlanesNew(uint planeCnt,odb::Rect * bb)72 uint extMain::initPlanesNew(uint planeCnt, odb::Rect* bb) {
73   _geomSeq->setSlices(planeCnt);
74 
75   // odb::Rect rectTable[15];
76   // for (uint k= 0; k<15; k++)
77   //	rectTable[k].reset( INT_MAX, INT_MAX, INT_MIN, INT_MIN );
78   // getBboxPerLayer(rectTable);
79 
80   odb::Rect maxRect;
81   _block->getDieArea(maxRect);
82 
83   if (bb != NULL) {
84     maxRect = *bb;
85     logger_->info(RCX, 183, "Init planes area: {} {}  {} {}", maxRect.xMin(),
86                   maxRect.yMin(), maxRect.xMax(), maxRect.yMax());
87   }
88 
89   odb::dbSet<odb::dbTechLayer> layers = _tech->getLayers();
90   odb::dbSet<odb::dbTechLayer>::iterator litr;
91   odb::dbTechLayer* layer;
92   for (litr = layers.begin(); litr != layers.end(); ++litr) {
93     layer = *litr;
94     if (layer->getType() != odb::dbTechLayerType::ROUTING)
95       continue;
96 
97     uint level = layer->getRoutingLevel();
98     uint pp = layer->getPitch();
99     uint minWidth = layer->getWidth();
100 
101     odb::Rect r = maxRect;
102     //_geomSeq->configureSlice(level, pp, pp, r.xMin(), r.yMin(), r.xMax(),
103     // r.yMax());
104 
105     // odb::Rect r= rectTable[level];
106 
107     if (layer->getDirection() == odb::dbTechLayerDir::HORIZONTAL)
108       _geomSeq->configureSlice(level, minWidth, pp, r.xMin(), r.yMin(),
109                                r.xMax(), r.yMax());
110     else
111       _geomSeq->configureSlice(level, pp, minWidth, r.xMin(), r.yMin(),
112                                r.xMax(), r.yMax());
113   }
114   return planeCnt + 1;
115 }
initPlanes(uint dir,uint layerCnt,uint * pitchTable,uint * widthTable,int * ll,int * ur)116 uint extMain::initPlanes(uint dir, uint layerCnt, uint* pitchTable,
117                          uint* widthTable, int* ll, int* ur) {
118   if (_geomSeq != NULL)
119     delete _geomSeq;
120   _geomSeq = new odb::gs;
121 
122   _geomSeq->setSlices(layerCnt);
123 
124   for (uint ii = 1; ii < layerCnt; ii++) {
125     if (dir > 0)  // horizontal
126       _geomSeq->configureSlice(ii, widthTable[ii], pitchTable[ii], ll[0], ll[1],
127                                ur[0], ur[1]);
128     else {
129       if (!_rotatedGs)
130         _geomSeq->configureSlice(ii, pitchTable[ii], widthTable[ii], ll[0],
131                                  ll[1], ur[0], ur[1]);
132       else
133         _geomSeq->configureSlice(ii, widthTable[ii], pitchTable[ii], ll[1],
134                                  ll[0], ur[1], ur[0]);
135     }
136   }
137   return layerCnt;
138 }
initPlanes(uint layerCnt,odb::Rect * bb)139 uint extMain::initPlanes(uint layerCnt, odb::Rect* bb) {
140   if (_geomSeq)
141     delete _geomSeq;
142   _geomSeq = new odb::gs();
143 
144   if (layerCnt == 0)
145     layerCnt = getExtLayerCnt(_tech);
146 
147   //	uint planeCnt= layerCnt+1;
148 
149   _overUnderPlaneLayerMap = NULL;
150 
151 // if (! _diagFlow)
152 // 	planeCnt= allocateOverUnderMaps(layerCnt);
153 
154 #ifdef GS_OLD
155   return initPlanesOld(planeCnt);
156 #else
157   return initPlanesNew(layerCnt, bb);
158 #endif
159 }
makeIntersectPlanes(uint layerCnt)160 uint extMain::makeIntersectPlanes(uint layerCnt) {
161   if (_geomSeq == NULL)
162     return 0;
163   if (_overUnderPlaneLayerMap == NULL)
164     return 0;
165 
166   if (layerCnt == 0) {
167     layerCnt = getExtLayerCnt(_tech);
168   }
169 
170   uint cnt = 0;
171   uint ii;
172   for (ii = 2; ii < layerCnt + 1; ii += 2) {
173     uint mUnder = ii - 1;
174 
175     uint mOver = ii + 1;
176     if (mOver > layerCnt)
177       break;
178 
179     uint planeIndex = _overUnderPlaneLayerMap[mUnder][mOver];
180     _geomSeq->intersect_rows(mUnder, mOver, planeIndex);
181     cnt++;
182   }
183   for (ii = 3; ii < layerCnt + 1; ii += 2) {
184     uint mUnder = ii - 1;
185 
186     uint mOver = ii + 1;
187     if (mOver > layerCnt)
188       break;
189 
190     uint planeIndex = _overUnderPlaneLayerMap[mUnder][mOver];
191     _geomSeq->intersect_rows(mUnder, mOver, planeIndex);
192     cnt++;
193   }
194   return cnt;
195 }
196 
deletePlanes(uint layerCnt)197 void extMain::deletePlanes(uint layerCnt) {
198   if (_overUnderPlaneLayerMap == NULL)
199     return;
200 
201   for (uint ii = 1; ii < layerCnt + 1; ii++) {
202     delete[] _overUnderPlaneLayerMap[ii];
203   }
204   delete[] _overUnderPlaneLayerMap;
205 }
addShapeOnGs(odb::dbShape * s,bool swap_coords)206 uint extMain::addShapeOnGs(odb::dbShape* s, bool swap_coords) {
207   int level = s->getTechLayer()->getRoutingLevel();
208 
209   if (!swap_coords)  // horizontal
210     return _geomSeq->box(s->xMin(), s->yMin(), s->xMax(), s->yMax(), level);
211   else
212     return _geomSeq->box(s->yMin(), s->xMin(), s->yMax(), s->xMax(), level);
213 }
addSBoxOnGs(odb::dbSBox * s,bool swap_coords)214 uint extMain::addSBoxOnGs(odb::dbSBox* s, bool swap_coords) {
215   int level = s->getTechLayer()->getRoutingLevel();
216 
217   if (!swap_coords)  // horizontal
218     return _geomSeq->box(s->xMin(), s->yMin(), s->xMax(), s->yMax(), level);
219   else
220     return _geomSeq->box(s->yMin(), s->xMin(), s->yMax(), s->xMax(), level);
221 }
222 
addPowerGs(int dir,int * ll,int * ur)223 uint extMain::addPowerGs(int dir, int* ll, int* ur) {
224   bool rotatedGs = getRotatedFlag();
225   bool swap_coords = !dir;
226 
227   uint cnt = 0;
228   odb::dbSet<odb::dbNet> bnets = _block->getNets();
229   odb::dbSet<odb::dbNet>::iterator net_itr;
230   odb::dbNet* net;
231   for (net_itr = bnets.begin(); net_itr != bnets.end(); ++net_itr) {
232     net = *net_itr;
233 
234     odb::dbSigType type = net->getSigType();
235     if (type != odb::dbSigType::POWER && type != odb::dbSigType::GROUND)
236       continue;
237     odb::dbSet<odb::dbSWire> swires = net->getSWires();
238     odb::dbSet<odb::dbSWire>::iterator itr;
239     for (itr = swires.begin(); itr != swires.end(); ++itr) {
240       odb::dbSWire* swire = *itr;
241       odb::dbSet<odb::dbSBox> sboxes = swire->getWires();
242       odb::dbSet<odb::dbSBox>::iterator box_itr;
243       for (box_itr = sboxes.begin(); box_itr != sboxes.end(); ++box_itr) {
244         odb::dbSBox* s = *box_itr;
245         if (s->isVia())
246           continue;
247 
248         if (ll == NULL) {
249           if (dir >= 0) {
250             odb::Rect r;
251             s->getBox(r);
252             if (matchDir(dir, r))
253               continue;
254           }
255           int n = 0;
256           if (!rotatedGs)
257             n = _geomSeq->box(s->xMin(), s->yMin(), s->xMax(), s->yMax(),
258                               s->getTechLayer()->getRoutingLevel());
259           else
260             n = addSBoxOnGs(s, swap_coords);
261 
262           if (n == 0)
263             cnt++;
264           continue;
265         }
266         odb::Rect r;
267         s->getBox(r);
268 
269         int bb[2] = {r.xMin(), r.yMin()};
270 
271         if (bb[dir] > ur[dir])
272           continue;
273 
274         if (bb[dir] < ll[dir])
275           continue;
276 
277         _geomSeq->box(r.xMin(), r.yMin(), r.xMax(), r.yMax(),
278                       s->getTechLayer()->getRoutingLevel());
279         cnt++;
280       }
281     }
282   }
283   return cnt;
284 }
getBboxPerLayer(odb::Rect * rectTable)285 void extMain::getBboxPerLayer(odb::Rect* rectTable) {
286   odb::dbSet<odb::dbNet> bnets = _block->getNets();
287   odb::dbSet<odb::dbNet>::iterator net_itr;
288   odb::dbWirePathItr pitr;
289   odb::dbWire* wire;
290   odb::dbWirePath path;
291   odb::dbWirePathShape pshape;
292   odb::dbShape dshape;
293   odb::dbNet* net;
294   for (net_itr = bnets.begin(); net_itr != bnets.end(); ++net_itr) {
295     net = *net_itr;
296 
297     odb::dbSigType type = net->getSigType();
298     if (type != odb::dbSigType::POWER &&
299         type != odb::dbSigType::GROUND) {  // signal
300 
301       wire = net->getWire();
302       if (!wire)
303         continue;
304 
305       for (pitr.begin(wire); pitr.getNextPath(path);) {
306         while (pitr.getNextShape(pshape)) {
307           dshape = pshape.shape;
308           if (dshape.isVia())
309             continue;
310 
311           uint level = dshape.getTechLayer()->getRoutingLevel();
312 
313           odb::Rect r;
314           dshape.getBox(r);
315 
316           rectTable[level].merge(r);
317         }
318       }
319       continue;
320     }
321 
322     odb::dbSet<odb::dbSWire> swires = net->getSWires();
323     odb::dbSet<odb::dbSWire>::iterator itr;
324     for (itr = swires.begin(); itr != swires.end(); ++itr) {
325       odb::dbSWire* swire = *itr;
326       odb::dbSet<odb::dbSBox> sboxes = swire->getWires();
327       odb::dbSet<odb::dbSBox>::iterator box_itr;
328       for (box_itr = sboxes.begin(); box_itr != sboxes.end(); ++box_itr) {
329         odb::dbSBox* s = *box_itr;
330         if (s->isVia())
331           continue;
332 
333         uint level = s->getTechLayer()->getRoutingLevel();
334 
335         odb::Rect r;
336         s->getBox(r);
337 
338         rectTable[level].merge(r);
339       }
340     }
341   }
342 }
addSignalGs(int dir,int * ll,int * ur)343 uint extMain::addSignalGs(int dir, int* ll, int* ur) {
344   bool rotatedGs = getRotatedFlag();
345   bool swap_coords = !dir;
346 
347   uint cnt = 0;
348   odb::dbSet<odb::dbNet> bnets = _block->getNets();
349   odb::dbSet<odb::dbNet>::iterator net_itr;
350   odb::dbNet* net;
351   odb::dbWirePathItr pitr;
352   odb::dbWire* wire;
353   odb::dbWirePath path;
354   odb::dbWirePathShape pshape;
355   odb::dbShape dshape;
356   for (net_itr = bnets.begin(); net_itr != bnets.end(); ++net_itr) {
357     net = *net_itr;
358     odb::dbSigType type = net->getSigType();
359     if (type == odb::dbSigType::POWER || type == odb::dbSigType::GROUND)
360       continue;
361     wire = net->getWire();
362     if (!wire)
363       continue;
364     for (pitr.begin(wire); pitr.getNextPath(path);) {
365       while (pitr.getNextShape(pshape)) {
366         dshape = pshape.shape;
367         if (dshape.isVia())
368           continue;
369         //				uint netId= net->getId();
370 
371         if (ll == NULL) {
372           if (dir >= 0) {
373             odb::Rect r;
374             dshape.getBox(r);
375             if (matchDir(dir, r))
376               continue;
377           }
378           int n = 0;
379           if (!rotatedGs)
380             n = _geomSeq->box(dshape.xMin(), dshape.yMin(), dshape.xMax(),
381                               dshape.yMax(),
382                               dshape.getTechLayer()->getRoutingLevel());
383           else
384             n = addShapeOnGs(&dshape, swap_coords);
385 
386           if (n == 0)
387             cnt++;
388           continue;
389         }
390         odb::Rect r;
391         dshape.getBox(r);
392 
393         int bb[2] = {r.xMin(), r.yMin()};
394 
395         if (bb[dir] >= ur[dir])
396           continue;
397 
398         if (bb[dir] <= ll[dir])
399           continue;
400 
401         _geomSeq->box(r.xMin(), r.yMin(), r.xMax(), r.yMax(),
402                       dshape.getTechLayer()->getRoutingLevel());
403         cnt++;
404       }
405     }
406   }
407   return cnt;
408 }
addObsShapesOnPlanes(odb::dbInst * inst,bool rotatedFlag,bool swap_coords)409 uint extMain::addObsShapesOnPlanes(odb::dbInst* inst, bool rotatedFlag,
410                                    bool swap_coords) {
411   uint cnt = 0;
412 
413   odb::dbInstShapeItr obs_shapes;
414 
415   odb::dbShape s;
416   for (obs_shapes.begin(inst, odb::dbInstShapeItr::OBSTRUCTIONS);
417        obs_shapes.next(s);) {
418     if (s.isVia())
419       continue;
420 
421     uint level = s.getTechLayer()->getRoutingLevel();
422 
423     uint n = 0;
424     if (!rotatedFlag)
425       n = _geomSeq->box(s.xMin(), s.yMin(), s.xMax(), s.yMax(), level);
426     else
427       n = addShapeOnGs(&s, swap_coords);
428   }
429   return cnt;
430 }
addItermShapesOnPlanes(odb::dbInst * inst,bool rotatedFlag,bool swap_coords)431 uint extMain::addItermShapesOnPlanes(odb::dbInst* inst, bool rotatedFlag,
432                                      bool swap_coords) {
433   uint cnt = 0;
434   odb::dbSet<odb::dbITerm> iterms = inst->getITerms();
435   odb::dbSet<odb::dbITerm>::iterator iterm_itr;
436 
437   for (iterm_itr = iterms.begin(); iterm_itr != iterms.end(); ++iterm_itr) {
438     odb::dbITerm* iterm = *iterm_itr;
439 
440     odb::dbShape s;
441     odb::dbITermShapeItr term_shapes;
442     for (term_shapes.begin(iterm); term_shapes.next(s);) {
443       if (s.isVia())
444         continue;
445 
446       uint level = s.getTechLayer()->getRoutingLevel();
447 
448       uint n = 0;
449       if (!rotatedFlag)
450         n = _geomSeq->box(s.xMin(), s.yMin(), s.xMax(), s.yMax(), level);
451       else
452         n = addShapeOnGs(&s, swap_coords);
453 
454       if (n == 0)
455         cnt++;
456     }
457   }
458   return cnt;
459 }
addInstShapesOnPlanes(uint dir,int * ll,int * ur)460 uint extMain::addInstShapesOnPlanes(uint dir, int* ll, int* ur) {
461   bool rotated = getRotatedFlag();
462 
463   uint cnt = 0;
464   odb::dbSet<odb::dbInst> insts = _block->getInsts();
465   odb::dbSet<odb::dbInst>::iterator inst_itr;
466   for (inst_itr = insts.begin(); inst_itr != insts.end(); ++inst_itr) {
467     odb::dbInst* inst = *inst_itr;
468 
469     if (ll == NULL) {
470       cnt += addItermShapesOnPlanes(inst, rotated, !dir);
471       cnt += addObsShapesOnPlanes(inst, rotated, !dir);
472       continue;
473     }
474   }
475   return cnt;
476 }
477 
478 }  // namespace rcx
479