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 #pragma once
34
35 #include "ZException.h"
36 #include "dbObject.h"
37 #include "dbSet.h"
38 #include "dbTransform.h"
39 #include "dbWireCodec.h"
40 #include "geom.h"
41 #include "odb.h"
42 namespace utl {
43 class Logger;
44 }
45 namespace odb {
46
47 class _dbWire;
48 class dbBox;
49 class dbNet;
50 class dbMPin;
51 class dbBPin;
52 class dbObstruction;
53 class dbMTerm;
54 class dbMaster;
55 class dbInst;
56 class dbTechNonDefaultRule;
57 class dbTechLayer;
58 class dbWire;
59 class dbSWire;
60 class dbObstruction;
61
62 ///////////////////////////////////////////////////////////////////////////////
63 ///
64 /// dbShape
65 ///
66 ///////////////////////////////////////////////////////////////////////////////
67 class dbShape
68 {
69 friend class dbHierInstShapeItr;
70
71 public:
72 enum Type
73 {
74 VIA,
75 TECH_VIA,
76 SEGMENT,
77 TECH_VIA_BOX,
78 VIA_BOX
79 };
80
81 private:
82 Type _type;
83 Rect _rect;
84 dbTechLayer* _layer;
85 dbObject* _via;
86
87 public:
dbShape()88 dbShape() : _type(SEGMENT), _layer(NULL), _via(NULL) {}
89
dbShape(dbVia * via,const Rect & r)90 dbShape(dbVia* via, const Rect& r)
91 : _type(VIA), _rect(r), _layer(NULL), _via((dbObject*) via)
92 {
93 }
94
dbShape(dbTechVia * via,const Rect & r)95 dbShape(dbTechVia* via, const Rect& r)
96 : _type(TECH_VIA), _rect(r), _layer(NULL), _via((dbObject*) via)
97 {
98 }
99
dbShape(dbTechLayer * layer,const Rect & r)100 dbShape(dbTechLayer* layer, const Rect& r)
101 : _type(SEGMENT), _rect(r), _layer(layer), _via(NULL)
102 {
103 }
104
dbShape(dbTechVia * via,dbTechLayer * layer,const Rect & r)105 dbShape(dbTechVia* via, dbTechLayer* layer, const Rect& r)
106 : _type(TECH_VIA_BOX), _rect(r), _layer(layer), _via((dbObject*) via)
107 {
108 }
109
dbShape(dbVia * via,dbTechLayer * layer,const Rect & r)110 dbShape(dbVia* via, dbTechLayer* layer, const Rect& r)
111 : _type(VIA_BOX), _rect(r), _layer(layer), _via((dbObject*) via)
112 {
113 }
114
115 void setSegment(int prev_x,
116 int prev_y,
117 int prev_ext,
118 bool has_prev_ext,
119 int cur_x,
120 int cur_y,
121 int cur_ext,
122 bool has_cur_ext,
123 int dw,
124 dbTechLayer* layer);
125
126 void setSegmentFromRect(int x1, int y1, int x2, int y2, dbTechLayer* layer);
127
setVia(dbVia * via,const Rect & r)128 void setVia(dbVia* via, const Rect& r)
129 {
130 _type = VIA;
131 _rect = r;
132 _layer = NULL;
133 _via = (dbObject*) via;
134 }
135
setVia(dbTechVia * via,const Rect & r)136 void setVia(dbTechVia* via, const Rect& r)
137 {
138 _type = TECH_VIA;
139 _rect = r;
140 _layer = NULL;
141 _via = (dbObject*) via;
142 }
143
setSegment(dbTechLayer * layer,const Rect & r)144 void setSegment(dbTechLayer* layer, const Rect& r)
145 {
146 _type = SEGMENT;
147 _rect = r;
148 _layer = layer;
149 _via = NULL;
150 }
151
setViaBox(dbTechVia * via,dbTechLayer * layer,const Rect & r)152 void setViaBox(dbTechVia* via, dbTechLayer* layer, const Rect& r)
153 {
154 _type = TECH_VIA_BOX;
155 _rect = r;
156 _layer = layer;
157 _via = (dbObject*) via;
158 }
159
setViaBox(dbVia * via,dbTechLayer * layer,const Rect & r)160 void setViaBox(dbVia* via, dbTechLayer* layer, const Rect& r)
161 {
162 _type = VIA_BOX;
163 _rect = r;
164 _layer = layer;
165 _via = (dbObject*) via;
166 }
167
168 bool operator==(const dbShape& s)
169 {
170 return (_type == s._type) && (_rect == s._rect) && (_via == s._via)
171 && (_layer == s._layer);
172 }
173
174 bool operator!=(const dbShape& s) { return !operator==(s); }
175
176 bool operator<(const dbShape& rhs);
177
178 ///
179 /// Get the lower coordinate.
180 ///
181 int xMin() const;
182
183 ///
184 /// Get the lower y coordinate.
185 ///
186 int yMin() const;
187
188 ///
189 /// Get the high x coordinate.
190 ///
191 int xMax() const;
192
193 ///
194 /// Get the high y coordinate.
195 ///
196 int yMax() const;
197
198 ///
199 /// Get the placed coordinate of this via
200 ///
201 void getViaXY(int& x, int& y) const;
202
203 ///
204 /// Returns true if this object is a via
205 ///
206 bool isVia() const;
207
208 ///
209 /// Returns true if this object is a via box
210 ///
211 bool isViaBox() const;
212
213 ///
214 /// Returns the type this shape represents..
215 ///
216 Type getType() const;
217
218 ///
219 /// Get tech-via of this TECH_VIA.
220 /// Returns NULL if this shape does not represent a tech-via
221 ///
222 dbTechVia* getTechVia() const;
223
224 ///
225 /// Get via of this VIA.
226 /// Returns NULL if this shape does not represent a via
227 ///
228 dbVia* getVia() const;
229
230 ///
231 /// Get layer of this SEGMENT.
232 /// Returns NULL if this shape does not represent a segment
233 ///
234 dbTechLayer* getTechLayer() const;
235
236 ///
237 /// Get the box bounding points.
238 ///
239 void getBox(Rect& rect) const;
240
241 ///
242 /// Get the width (xMax-xMin) of the box.
243 ///
244 uint getDX() const;
245
246 ///
247 /// Get the height (yMax-yMin) of the box.
248 ///
249 uint getDY() const;
250
251 //
252 // Dump contents into logger
253 //
254 void dump(utl::Logger* logger, const char* group, int level) const;
255
256 //
257 // Get the via-boxes of this via-shape.
258 //
259 // WARNING: This method only works for shapes generated from a dbWire.
260 //
261 static void getViaBoxes(const dbShape& via, std::vector<dbShape>& boxes);
262 };
263
264 ///
265 /// dbWireShapeItr - Iterate the shapes of a dbWire.
266 ///
267 /// RECT in the dbWire are treats as segments for convenience
268 ///
269 class dbWireShapeItr
270 {
271 public:
272 _dbWire* _wire;
273 dbTech* _tech;
274 dbBlock* _block;
275 int _idx;
276 int _prev_x;
277 int _prev_y;
278 int _prev_ext;
279 bool _has_prev_ext;
280 dbTechLayer* _layer;
281 dbObject* _via;
282 int _dw;
283 int _point_cnt;
284 int _shape_id;
285 bool _has_width;
286
287 unsigned char nextOp(int& value);
288 unsigned char peekOp();
289
290 public:
291 dbWireShapeItr();
292 ~dbWireShapeItr();
293
294 void begin(dbWire* wire);
295 bool next(dbShape& shape);
296 int getShapeId();
297 };
298
299 ///////////////////////////////////////////////////////////////////////////////
300 ///
301 /// dbWirePathItr - Iterate the paths of a dbWire.
302 ///
303 ///////////////////////////////////////////////////////////////////////////////
304 struct dbWirePath
305 {
306 int junction_id; // junction id of this point
307 Point point; // starting point of path
308 dbTechLayer* layer; // starting layer of path
309 dbBTerm* bterm; // dbBTerm connected at this point, otherwise NULL
310 dbITerm* iterm; // dbITerm connected at this point, otherwise NULL
311 bool is_branch; // true if this path is a branch from the current tree
312 bool is_short; // true if this path is a virtual short to a previous junction
313 int short_junction; // junction id of the virtual short.
314 dbTechNonDefaultRule* rule; // nondefaultrule for this path
315 void dump(utl::Logger* logger, const char* group, int level) const;
316 };
317
318 struct dbWirePathShape
319 {
320 int junction_id; // junction id of this point
321 Point point; // starting point of path
322 dbTechLayer* layer; // layer of shape, or exit layer of via
323 dbBTerm* bterm; // dbBTerm connected at this point, otherwise NULL
324 dbITerm* iterm; // dbITerm connected at this point, otherwise NULL
325 dbShape shape; // shape at this point
326
327 void dump(utl::Logger* logger, const char* group, int level) const;
328 };
329
330 class dbWirePathItr
331 {
332 dbWireDecoder _decoder;
333 dbWireDecoder::OpCode _opcode;
334 int _prev_x;
335 int _prev_y;
336 int _prev_ext;
337 bool _has_prev_ext;
338 dbWire* _wire;
339 int _dw;
340 dbTechNonDefaultRule* _rule;
341
342 void getTerms(dbWirePathShape& s);
343
344 public:
345 dbWirePathItr();
346 ~dbWirePathItr();
347
348 void begin(dbWire* wire);
349 bool getNextPath(dbWirePath& path);
350 bool getNextShape(dbWirePathShape& shape);
351 };
352
353 ///////////////////////////////////////////////////////////////////////////////
354 ///
355 /// dbInstShapeItr
356 ///
357 ///////////////////////////////////////////////////////////////////////////////
358 class dbInstShapeItr
359 {
360 public:
361 enum IteratorType
362 {
363 ALL,
364 PINS,
365 OBSTRUCTIONS
366 };
367
368 private:
369 dbSet<dbBox> _boxes;
370 dbSet<dbMPin> _mpins;
371 dbSet<dbMTerm> _mterms;
372 dbSet<dbBox>::iterator _box_itr;
373 dbSet<dbMTerm>::iterator _mterm_itr;
374 dbSet<dbMPin>::iterator _mpin_itr;
375 int _state;
376 dbInst* _inst;
377 dbMaster* _master;
378 dbMPin* _mpin;
379 dbTransform _transform;
380 IteratorType _type;
381 dbTechVia* _via;
382 dbSet<dbBox> _via_boxes;
383 dbSet<dbBox>::iterator _via_box_itr;
384 int _via_x;
385 int _via_y;
386 bool _expand_vias;
387 int _prev_state;
388
389 void getShape(dbBox* box, dbShape& shape);
390 void getViaBox(dbBox* box, dbShape& shape);
391
392 public:
393 dbInstShapeItr(bool expand_vias = false);
394 void begin(dbInst* inst, IteratorType type);
395 void begin(dbInst* inst, IteratorType type, const dbTransform& t);
396 bool next(dbShape& shape);
397 };
398
399 ///////////////////////////////////////////////////////////////////////////////
400 ///
401 /// dbITermShapeItr
402 ///
403 ///////////////////////////////////////////////////////////////////////////////
404 class dbITermShapeItr
405 {
406 private:
407 dbSet<dbBox> _boxes;
408 dbSet<dbMPin> _mpins;
409 dbMTerm* _mterm;
410 dbSet<dbBox>::iterator _box_itr;
411 dbSet<dbMPin>::iterator _mpin_itr;
412 int _state;
413 dbITerm* _iterm;
414 dbMPin* _mpin;
415 dbTransform _transform;
416 dbTechVia* _via;
417 dbSet<dbBox> _via_boxes;
418 dbSet<dbBox>::iterator _via_box_itr;
419 int _via_x;
420 int _via_y;
421 bool _expand_vias;
422
423 void getShape(dbBox* box, dbShape& shape);
424 void getViaBox(dbBox* box, dbShape& shape);
425
426 public:
427 dbITermShapeItr(bool expand_vias = false);
428 void begin(dbITerm* iterm);
429 bool next(dbShape& shape);
430 };
431
432 class dbShapeItrCallback
433 {
434 public:
435 // Overide the following methods of interest...
beginInst(dbInst *,int)436 virtual void beginInst(dbInst*, int) {}
endInst()437 virtual void endInst() {}
438
beginObstruction(dbObstruction *)439 virtual void beginObstruction(dbObstruction*) {}
endObstruction()440 virtual void endObstruction() {}
441
beginBPin(dbBPin *)442 virtual void beginBPin(dbBPin*) {}
endBPin()443 virtual void endBPin() {}
444
beginNet(dbNet *)445 virtual void beginNet(dbNet*) {}
endNet()446 virtual void endNet() {}
447
beginWire(dbWire *)448 virtual void beginWire(dbWire*) {}
endWire()449 virtual void endWire() {}
450
beginSWire(dbSWire *)451 virtual void beginSWire(dbSWire*) {}
endSWire()452 virtual void endSWire() {}
453
beginObstructions(dbMaster *)454 virtual void beginObstructions(dbMaster*) {}
endObstructions()455 virtual void endObstructions() {}
456
beginMTerm(dbMTerm *)457 virtual void beginMTerm(dbMTerm*) {}
endMTerm()458 virtual void endMTerm() {}
459
beginMPin(dbMPin *)460 virtual void beginMPin(dbMPin*) {}
endMPin()461 virtual void endMPin() {}
462
463 // Called for all shapes except dbWire shapes.
nextBoxShape(dbBox *,dbShape &)464 virtual bool nextBoxShape(dbBox*, dbShape&) { return true; }
465
466 // Called only for dbWireShapes.
nextWireShape(dbWire *,int,dbShape &)467 virtual bool nextWireShape(dbWire*, int, dbShape&) { return true; }
468 };
469
470 class dbHierInstShapeItr
471 {
472 public:
473 enum Filter
474 {
475 NONE = 0,
476 BLOCK_PIN = 0x00001,
477 BLOCK_OBS = 0x00002,
478 INST_OBS = 0x00004,
479 INST_PIN = 0x00008,
480 INST_VIA = 0x00010,
481 SIGNAL_WIRE = 0x00020,
482 SIGNAL_VIA = 0x00040,
483 POWER_WIRE = 0x00080,
484 POWER_VIA = 0x00100,
485 CLOCK_WIRE = 0x00200,
486 CLOCK_VIA = 0x00400,
487 RESET_WIRE = 0x00800,
488 RESET_VIA = 0x01000,
489 NET_WIRE = 0x02000,
490 NET_SWIRE = 0x04000,
491 NET_WIRE_SHAPE = 0x08000,
492 NET_SBOX = 0x10000
493 };
494
495 private:
496 std::vector<dbTransform> _transforms;
497 dbShapeItrCallback* _callback;
498
499 bool drawNet(unsigned filter, dbNet* net, bool& draw_via, bool& draw_segment);
500 void getShape(dbBox* box, dbShape& shape);
501 void getViaBox(dbBox* box, dbShape& shape);
502 void push_transform(Point origin, dbTransform& transform);
503 void pop_transform();
504 bool iterate_inst(dbInst* inst, unsigned filter, int level);
505 bool iterate_swires(unsigned filter,
506 dbNet* net,
507 bool draw_vias,
508 bool draw_segments);
509 bool iterate_swire(unsigned filter,
510 dbSWire* swire,
511 bool draw_vias,
512 bool draw_segments);
513 bool iterate_wire(unsigned filter,
514 dbNet* net,
515 bool draw_vias,
516 bool draw_segments);
517 bool iterate_leaf(dbInst* inst, unsigned filter, int level);
518 void push_transform(dbTransform t);
519 void transform(dbShape& shape);
520
521 public:
522 dbHierInstShapeItr(dbShapeItrCallback* callback);
523
524 // filter = { PINS | OBSTRUCTIONS | ... }
525 void iterate(dbInst* inst, unsigned filter = NONE);
526 };
527
528 /////////////////////////////////////////////////////////////////////////////////////////////
529 // inline functions
530 /////////////////////////////////////////////////////////////////////////////////////////////
531
xMin()532 inline int dbShape::xMin() const
533 {
534 return _rect.xMin();
535 }
yMin()536 inline int dbShape::yMin() const
537 {
538 return _rect.yMin();
539 }
xMax()540 inline int dbShape::xMax() const
541 {
542 return _rect.xMax();
543 }
yMax()544 inline int dbShape::yMax() const
545 {
546 return _rect.yMax();
547 }
isVia()548 inline bool dbShape::isVia() const
549 {
550 return (_type == VIA) || (_type == TECH_VIA);
551 }
isViaBox()552 inline bool dbShape::isViaBox() const
553 {
554 return (_type == VIA_BOX) || (_type == TECH_VIA_BOX);
555 }
556
getType()557 inline dbShape::Type dbShape::getType() const
558 {
559 return _type;
560 }
561
getTechVia()562 inline dbTechVia* dbShape::getTechVia() const
563 {
564 if ((_type != TECH_VIA) && (_type != TECH_VIA_BOX))
565 return NULL;
566
567 return (dbTechVia*) _via;
568 }
569
getVia()570 inline dbVia* dbShape::getVia() const
571 {
572 if ((_type != VIA) && (_type != VIA_BOX))
573 return NULL;
574
575 return (dbVia*) _via;
576 }
577
getTechLayer()578 inline dbTechLayer* dbShape::getTechLayer() const
579 {
580 return (dbTechLayer*) _layer;
581 }
582
getBox(Rect & rect)583 inline void dbShape::getBox(Rect& rect) const
584 {
585 rect = _rect;
586 }
getDX()587 inline uint dbShape::getDX() const
588 {
589 return _rect.dx();
590 }
getDY()591 inline uint dbShape::getDY() const
592 {
593 return _rect.dy();
594 }
595
setSegment(int prev_x,int prev_y,int prev_ext,bool has_prev_ext,int cur_x,int cur_y,int cur_ext,bool has_cur_ext,int dw,dbTechLayer * layer)596 inline void dbShape::setSegment(int prev_x,
597 int prev_y,
598 int prev_ext,
599 bool has_prev_ext,
600 int cur_x,
601 int cur_y,
602 int cur_ext,
603 bool has_cur_ext,
604 int dw,
605 dbTechLayer* layer)
606 {
607 int x1, x2, y1, y2;
608 if (cur_x == prev_x) // vert. path
609 {
610 x1 = cur_x - dw;
611 x2 = cur_x + dw;
612
613 if (cur_y > prev_y) {
614 if (has_prev_ext)
615 y1 = prev_y - prev_ext;
616 else
617 y1 = prev_y - dw;
618
619 if (has_cur_ext)
620 y2 = cur_y + cur_ext;
621 else
622 y2 = cur_y + dw;
623 } else if (cur_y < prev_y) {
624 if (has_cur_ext)
625 y1 = cur_y - cur_ext;
626 else
627 y1 = cur_y - dw;
628
629 if (has_prev_ext)
630 y2 = prev_y + prev_ext;
631 else
632 y2 = prev_y + dw;
633 } else {
634 y1 = cur_y - dw;
635 y2 = cur_y + dw;
636 }
637 } else if (cur_y == prev_y) // horiz. path
638 {
639 y1 = cur_y - dw;
640 y2 = cur_y + dw;
641
642 if (cur_x > prev_x) {
643 if (has_prev_ext)
644 x1 = prev_x - prev_ext;
645 else
646 x1 = prev_x - dw;
647
648 if (has_cur_ext)
649 x2 = cur_x + cur_ext;
650 else
651 x2 = cur_x + dw;
652 } else if (cur_x < prev_x) {
653 if (has_cur_ext)
654 x1 = cur_x - cur_ext;
655 else
656 x1 = cur_x - dw;
657
658 if (has_prev_ext)
659 x2 = prev_x + prev_ext;
660 else
661 x2 = prev_x + dw;
662 } else {
663 x1 = cur_x - dw;
664 x2 = cur_x + dw;
665 }
666
667 } else {
668 x1 = 0;
669 y1 = 0;
670 x2 = 0;
671 y2 = 0;
672 assert(0); // illegal: non-orthogonal-path
673 }
674
675 _type = dbShape::SEGMENT;
676 _rect.reset(x1, y1, x2, y2);
677 _layer = layer;
678 _via = NULL;
679 }
680
setSegmentFromRect(int x1,int y1,int x2,int y2,dbTechLayer * layer)681 inline void dbShape::setSegmentFromRect(int x1,
682 int y1,
683 int x2,
684 int y2,
685 dbTechLayer* layer)
686 {
687 _type = dbShape::SEGMENT;
688 _rect.reset(x1, y1, x2, y2);
689 _layer = layer;
690 _via = nullptr;
691 }
692
693 //
694 // Print utilities declared here
695 //
696 void dumpWirePaths4Net(dbNet* innet, const char* group, int level);
697
698 } // namespace odb
699