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