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 
dbInstShapeItr(bool expand_vias)39 dbInstShapeItr::dbInstShapeItr(bool expand_vias)
40 {
41   _state = 0;
42   _inst = NULL;
43   _master = NULL;
44   _mpin = NULL;
45   _type = ALL;
46   _via = NULL;
47   _via_x = 0;
48   _via_y = 0;
49   _expand_vias = expand_vias;
50 }
51 
begin(dbInst * inst,IteratorType type)52 void dbInstShapeItr::begin(dbInst* inst, IteratorType type)
53 {
54   int x, y;
55   _inst = inst;
56   _inst->getOrigin(x, y);
57   _master = _inst->getMaster();
58   _transform = dbTransform(inst->getOrient(), Point(x, y));
59   _type = type;
60   _state = 0;
61 }
62 
begin(dbInst * inst,IteratorType type,const dbTransform & t)63 void dbInstShapeItr::begin(dbInst* inst,
64                            IteratorType type,
65                            const dbTransform& t)
66 {
67   int x, y;
68   _inst = inst;
69   _inst->getOrigin(x, y);
70   _master = _inst->getMaster();
71   _transform = dbTransform(inst->getOrient(), Point(x, y));
72   _transform.concat(t);
73   _type = type;
74   _state = 0;
75 }
76 
getViaBox(dbBox * box,dbShape & shape)77 void dbInstShapeItr::getViaBox(dbBox* box, dbShape& shape)
78 {
79   Rect b;
80   box->getBox(b);
81   int xmin = b.xMin() + _via_x;
82   int ymin = b.yMin() + _via_y;
83   int xmax = b.xMax() + _via_x;
84   int ymax = b.yMax() + _via_y;
85   Rect r(xmin, ymin, xmax, ymax);
86   _transform.apply(r);
87   shape.setViaBox(_via, box->getTechLayer(), r);
88 }
89 
getShape(dbBox * box,dbShape & shape)90 void dbInstShapeItr::getShape(dbBox* box, dbShape& shape)
91 {
92   Rect r;
93   box->getBox(r);
94   _transform.apply(r);
95 
96   dbTechVia* via = box->getTechVia();
97 
98   if (via)
99     shape.setVia(via, r);
100   else
101     shape.setSegment(box->getTechLayer(), r);
102 }
103 
104 #define INIT 0
105 #define MTERM_ITR 1
106 #define MPIN_ITR 2
107 #define MBOX_ITR 3
108 #define OBS_ITR 4
109 #define VIA_BOX_ITR 5
110 #define PINS_DONE 6
111 
next(dbShape & shape)112 bool dbInstShapeItr::next(dbShape& shape)
113 {
114   ZASSERT(_inst);
115 
116 next_state:
117 
118   switch (_state) {
119     case INIT: {
120       if (_type == OBSTRUCTIONS) {
121         _boxes = _master->getObstructions();
122         _box_itr = _boxes.begin();
123         _state = OBS_ITR;
124       } else {
125         _mterms = _master->getMTerms();
126         _mterm_itr = _mterms.begin();
127         _state = MTERM_ITR;
128       }
129 
130       goto next_state;
131     }
132 
133     case MTERM_ITR: {
134       if (_mterm_itr == _mterms.end())
135         _state = PINS_DONE;
136       else {
137         dbMTerm* mterm = *_mterm_itr;
138         ++_mterm_itr;
139         _mpins = mterm->getMPins();
140         _mpin_itr = _mpins.begin();
141         _state = MPIN_ITR;
142       }
143 
144       goto next_state;
145     }
146 
147     case MPIN_ITR: {
148       if (_mpin_itr == _mpins.end())
149         _state = MTERM_ITR;
150       else {
151         _mpin = *_mpin_itr;
152         ++_mpin_itr;
153         _boxes = _mpin->getGeometry();
154         _box_itr = _boxes.begin();
155         _state = MBOX_ITR;
156       }
157 
158       goto next_state;
159     }
160 
161     case MBOX_ITR: {
162       if (_box_itr == _boxes.end())
163         _state = MPIN_ITR;
164       else {
165         dbBox* box = *_box_itr;
166         ++_box_itr;
167 
168         if ((_expand_vias == false) || (box->isVia() == false)) {
169           getShape(box, shape);
170           return true;
171         }
172 
173         else {
174           box->getViaXY(_via_x, _via_y);
175           _via = box->getTechVia();
176           assert(_via);
177           _via_boxes = _via->getBoxes();
178           _via_box_itr = _via_boxes.begin();
179           _prev_state = MBOX_ITR;
180           _state = VIA_BOX_ITR;
181         }
182       }
183 
184       goto next_state;
185     }
186 
187     case OBS_ITR: {
188       if (_box_itr == _boxes.end())
189         return false;
190 
191       else {
192         dbBox* box = *_box_itr;
193         ++_box_itr;
194 
195         if ((_expand_vias == false) || (box->isVia() == false)) {
196           getShape(box, shape);
197           return true;
198         }
199 
200         else {
201           box->getViaXY(_via_x, _via_y);
202           _via = box->getTechVia();
203           assert(_via);
204           _via_boxes = _via->getBoxes();
205           _via_box_itr = _via_boxes.begin();
206           _prev_state = OBS_ITR;
207           _state = VIA_BOX_ITR;
208         }
209       }
210       goto next_state;
211     }
212 
213     case VIA_BOX_ITR: {
214       if (_via_box_itr == _via_boxes.end())
215         _state = _prev_state;
216       else {
217         dbBox* box = *_via_box_itr;
218         ++_via_box_itr;
219         getViaBox(box, shape);
220         return true;
221       }
222 
223       goto next_state;
224     }
225 
226     case PINS_DONE: {
227       if (_type == ALL) {
228         _type = OBSTRUCTIONS;
229         _state = INIT;
230         goto next_state;
231       }
232 
233       return false;
234     }
235   }
236 
237   return false;
238 }
239 
240 }  // namespace odb
241