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 "ZException.h"
34 #include "db.h"
35 #include "dbShape.h"
36
37 namespace odb {
38
isFiltered(unsigned filter,unsigned mask)39 inline bool isFiltered(unsigned filter, unsigned mask)
40 {
41 return (filter & mask) == mask;
42 }
43
dbHierInstShapeItr(dbShapeItrCallback * callback)44 dbHierInstShapeItr::dbHierInstShapeItr(dbShapeItrCallback* callback)
45 {
46 _callback = callback;
47 assert(callback);
48 }
49
iterate(dbInst * inst,unsigned filter)50 void dbHierInstShapeItr::iterate(dbInst* inst, unsigned filter)
51 {
52 _transforms.clear();
53 _transforms.push_back(dbTransform());
54 iterate_inst(inst, filter, 0);
55 }
56
push_transform(dbTransform t)57 void dbHierInstShapeItr::push_transform(dbTransform t)
58 {
59 dbTransform top = _transforms.back();
60 top.concat(t);
61 _transforms.push_back(top);
62 }
63
iterate_leaf(dbInst * inst,unsigned filter,int level)64 bool dbHierInstShapeItr::iterate_leaf(dbInst* inst, unsigned filter, int level)
65 {
66 if (isFiltered(filter, INST_OBS | INST_VIA | INST_PIN))
67 return true;
68
69 _callback->beginInst(inst, level);
70
71 int x, y;
72 inst->getOrigin(x, y);
73 push_transform(dbTransform(inst->getOrient(), Point(x, y)));
74 dbMaster* master = inst->getMaster();
75
76 if (!isFiltered(filter, INST_OBS | INST_VIA)) {
77 _callback->beginObstructions(master);
78 dbSet<dbBox> boxes = master->getObstructions();
79 dbSet<dbBox>::iterator itr;
80 bool filter_via = isFiltered(filter, INST_VIA);
81 bool filter_obs = isFiltered(filter, INST_OBS);
82
83 dbShape s;
84
85 for (itr = boxes.begin(); itr != boxes.end(); ++itr) {
86 dbBox* box = *itr;
87
88 if (box->isVia()) {
89 if (!filter_via) {
90 getShape(box, s);
91
92 if (!_callback->nextBoxShape(box, s)) {
93 _transforms.pop_back();
94 _callback->endObstructions();
95 _callback->endInst();
96 return false;
97 }
98 }
99
100 } else {
101 if (!filter_obs) {
102 getShape(box, s);
103
104 if (!_callback->nextBoxShape(box, s)) {
105 _transforms.pop_back();
106 _callback->endObstructions();
107 _callback->endInst();
108 return false;
109 }
110 }
111 }
112 }
113
114 _callback->endObstructions();
115 }
116
117 if (!isFiltered(filter, INST_PIN)) {
118 dbSet<dbMTerm> mterms = master->getMTerms();
119 dbSet<dbMTerm>::iterator mitr;
120 dbShape s;
121
122 for (mitr = mterms.begin(); mitr != mterms.end(); ++mitr) {
123 dbMTerm* mterm = *mitr;
124 _callback->beginMTerm(mterm);
125
126 dbSet<dbMPin> mpins = mterm->getMPins();
127 dbSet<dbMPin>::iterator pitr;
128
129 for (pitr = mpins.begin(); pitr != mpins.end(); ++pitr) {
130 dbMPin* pin = *pitr;
131 _callback->beginMPin(pin);
132
133 dbSet<dbBox> geoms = pin->getGeometry();
134 dbSet<dbBox>::iterator gitr;
135
136 for (gitr = geoms.begin(); gitr != geoms.end(); ++gitr) {
137 dbBox* box = *gitr;
138 getShape(box, s);
139
140 if (!_callback->nextBoxShape(box, s)) {
141 _transforms.pop_back();
142 _callback->endMPin();
143 _callback->endMTerm();
144 _callback->endInst();
145 return false;
146 }
147 }
148
149 _callback->endMPin();
150 }
151
152 _callback->endMTerm();
153 }
154 }
155
156 _transforms.pop_back();
157 _callback->endInst();
158 return true;
159 }
160
iterate_inst(dbInst * inst,unsigned filter,int level)161 bool dbHierInstShapeItr::iterate_inst(dbInst* inst, unsigned filter, int level)
162 {
163 if (!inst->isHierarchical())
164 return iterate_leaf(inst, filter, level);
165
166 _callback->beginInst(inst, level);
167
168 int x, y;
169 inst->getOrigin(x, y);
170 push_transform(dbTransform(inst->getOrient(), Point(x, y)));
171 dbBlock* child = inst->getChild();
172 dbShape shape;
173
174 if (!isFiltered(filter, BLOCK_PIN)) {
175 dbSet<dbBTerm> bterms = child->getBTerms();
176 dbSet<dbBTerm>::iterator bitr;
177
178 for (bitr = bterms.begin(); bitr != bterms.end(); ++bitr) {
179 dbBTerm* bterm = *bitr;
180 dbSet<dbBPin> bpins = bterm->getBPins();
181 dbSet<dbBPin>::iterator pitr;
182
183 for (pitr = bpins.begin(); pitr != bpins.end(); ++pitr) {
184 dbBPin* pin = *pitr;
185 _callback->beginBPin(pin);
186
187 for (dbBox* box : pin->getBoxes()) {
188 getShape(box, shape);
189 if (!_callback->nextBoxShape(box, shape)) {
190 _transforms.pop_back();
191 _callback->endBPin();
192 _callback->endInst();
193 return false;
194 }
195 }
196
197 _callback->endBPin();
198 }
199 }
200 }
201
202 if (!isFiltered(filter, BLOCK_OBS)) {
203 dbSet<dbObstruction> obstructions = child->getObstructions();
204 dbSet<dbObstruction>::iterator oitr;
205
206 for (oitr = obstructions.begin(); oitr != obstructions.end(); ++oitr) {
207 dbObstruction* obs = *oitr;
208 dbBox* box = obs->getBBox();
209 getShape(box, shape);
210 _callback->beginObstruction(obs);
211
212 if (!_callback->nextBoxShape(box, shape)) {
213 _transforms.pop_back();
214 _callback->endObstruction();
215 _callback->endInst();
216 return false;
217 }
218
219 _callback->endObstruction();
220 }
221 }
222
223 dbSet<dbInst> insts = child->getInsts();
224 dbSet<dbInst>::iterator iitr;
225
226 for (iitr = insts.begin(); iitr != insts.end(); ++iitr) {
227 dbInst* inst = *iitr;
228
229 if (!iterate_inst(inst, filter, ++level)) {
230 _transforms.pop_back();
231 return false;
232 }
233 }
234
235 dbSet<dbNet> nets = child->getNets();
236 dbSet<dbNet>::iterator nitr;
237
238 for (nitr = nets.begin(); nitr != nets.end(); ++nitr) {
239 dbNet* net = *nitr;
240
241 _callback->beginNet(net);
242
243 bool draw_segments;
244 bool draw_vias;
245
246 if (!drawNet(filter, net, draw_vias, draw_segments))
247 continue;
248
249 if (!isFiltered(filter, NET_SWIRE)) {
250 if (!iterate_swires(filter, net, draw_vias, draw_segments)) {
251 _transforms.pop_back();
252 _callback->endNet();
253 _callback->endInst();
254 return false;
255 }
256 }
257
258 if (!isFiltered(filter, NET_WIRE)) {
259 if (!iterate_wire(filter, net, draw_vias, draw_segments)) {
260 _transforms.pop_back();
261 _callback->endNet();
262 _callback->endInst();
263 return false;
264 }
265 }
266
267 _callback->endNet();
268 }
269
270 _transforms.pop_back();
271 _callback->endInst();
272 return true;
273 }
274
drawNet(unsigned filter,dbNet * net,bool & draw_via,bool & draw_segment)275 bool dbHierInstShapeItr::drawNet(unsigned filter,
276 dbNet* net,
277 bool& draw_via,
278 bool& draw_segment)
279 {
280 dbSigType type = net->getSigType();
281 draw_via = false;
282 draw_segment = false;
283
284 switch (type) {
285 case dbSigType::SCAN:
286 case dbSigType::ANALOG:
287 case dbSigType::TIEOFF:
288 case dbSigType::SIGNAL: {
289 if (isFiltered(filter, SIGNAL_WIRE | SIGNAL_VIA))
290 return false;
291
292 if (!isFiltered(filter, SIGNAL_WIRE))
293 draw_segment = true;
294
295 if (!isFiltered(filter, SIGNAL_VIA))
296 draw_via = true;
297
298 return true;
299 }
300
301 case dbSigType::POWER:
302 case dbSigType::GROUND: {
303 if (isFiltered(filter, POWER_WIRE | POWER_VIA))
304 return false;
305
306 if (!isFiltered(filter, POWER_WIRE))
307 draw_segment = true;
308
309 if (!isFiltered(filter, POWER_VIA))
310 draw_via = true;
311
312 return true;
313 }
314
315 case dbSigType::CLOCK: {
316 if (isFiltered(filter, CLOCK_WIRE | CLOCK_VIA))
317 return false;
318
319 if (!isFiltered(filter, CLOCK_WIRE))
320 draw_segment = true;
321
322 if (!isFiltered(filter, CLOCK_VIA))
323 draw_via = true;
324
325 return true;
326 }
327
328 case dbSigType::RESET: {
329 if (isFiltered(filter, RESET_WIRE | RESET_VIA))
330 return false;
331
332 if (!isFiltered(filter, RESET_WIRE))
333 draw_segment = true;
334
335 if (!isFiltered(filter, RESET_VIA))
336 draw_via = true;
337
338 return true;
339 }
340 }
341
342 draw_via = true;
343 draw_segment = true;
344 return true;
345 }
346
iterate_swires(unsigned filter,dbNet * net,bool draw_vias,bool draw_segments)347 bool dbHierInstShapeItr::iterate_swires(unsigned filter,
348 dbNet* net,
349 bool draw_vias,
350 bool draw_segments)
351 {
352 dbSet<dbSWire> swires = net->getSWires();
353 dbSet<dbSWire>::iterator itr;
354
355 for (itr = swires.begin(); itr != swires.end(); ++itr) {
356 dbSWire* swire = *itr;
357
358 if (!iterate_swire(filter, swire, draw_vias, draw_segments))
359 return false;
360 }
361
362 return true;
363 }
364
iterate_swire(unsigned filter,dbSWire * swire,bool draw_vias,bool draw_segments)365 bool dbHierInstShapeItr::iterate_swire(unsigned filter,
366 dbSWire* swire,
367 bool draw_vias,
368 bool draw_segments)
369 {
370 _callback->beginSWire(swire);
371
372 if (isFiltered(filter, NET_SBOX)) {
373 _callback->endSWire();
374 return true;
375 }
376
377 dbSet<dbSBox> boxes = swire->getWires();
378 dbSet<dbSBox>::iterator itr;
379 dbShape shape;
380
381 for (itr = boxes.begin(); itr != boxes.end(); ++itr) {
382 dbBox* box = *itr;
383
384 if (box->isVia()) {
385 if (draw_vias == true) {
386 getShape(box, shape);
387
388 if (!_callback->nextBoxShape(box, shape)) {
389 _callback->endSWire();
390 return false;
391 }
392 }
393 } else {
394 if (draw_segments == true) {
395 getShape(box, shape);
396
397 if (!_callback->nextBoxShape(box, shape)) {
398 _callback->endSWire();
399 return false;
400 }
401 }
402 }
403 }
404
405 _callback->endSWire();
406 return true;
407 }
408
iterate_wire(unsigned filter,dbNet * net,bool draw_vias,bool draw_segments)409 bool dbHierInstShapeItr::iterate_wire(unsigned filter,
410 dbNet* net,
411 bool draw_vias,
412 bool draw_segments)
413 {
414 dbWire* wire = net->getWire();
415
416 if (wire == NULL)
417 return true;
418
419 _callback->beginWire(wire);
420
421 if (isFiltered(filter, NET_WIRE_SHAPE)) {
422 _callback->endWire();
423 return true;
424 }
425
426 dbShape shape;
427 dbWireShapeItr itr;
428
429 for (itr.begin(wire); itr.next(shape);) {
430 if (shape.isVia()) {
431 if (draw_vias == true) {
432 transform(shape);
433
434 if (!_callback->nextWireShape(wire, itr.getShapeId(), shape)) {
435 _callback->endWire();
436 return false;
437 }
438 }
439 } else {
440 if (draw_segments == true) {
441 transform(shape);
442
443 if (!_callback->nextWireShape(wire, itr.getShapeId(), shape)) {
444 _callback->endWire();
445 return false;
446 }
447 }
448 }
449 }
450
451 _callback->endWire();
452 return true;
453 }
454
transform(dbShape & shape)455 void dbHierInstShapeItr::transform(dbShape& shape)
456 {
457 dbTransform& t = _transforms.back();
458 t.apply(shape._rect);
459 }
460
getShape(dbBox * box,dbShape & shape)461 void dbHierInstShapeItr::getShape(dbBox* box, dbShape& shape)
462 {
463 Rect r;
464 box->getBox(r);
465 dbTransform& t = _transforms.back();
466 t.apply(r);
467
468 if (!box->isVia()) {
469 shape.setSegment(box->getTechLayer(), r);
470 } else {
471 dbTechVia* tech_via = box->getTechVia();
472
473 if (tech_via)
474 shape.setVia(tech_via, r);
475 else {
476 dbVia* via = box->getBlockVia();
477 assert(via);
478 shape.setVia(via, r);
479 }
480 }
481 }
482
483 } // namespace odb
484