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