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 "db.h"
34 #include "dbBlock.h"
35 #include "dbNet.h"
36 #include "dbShape.h"
37 #include "dbTable.h"
38 #include "dbWire.h"
39 #include "dbWireCodec.h"
40 #include "dbWireOpcode.h"
41 
42 namespace odb {
43 
44 #define DB_WIRE_DECODE_INVALID_OPCODE 0
45 
46 //////////////////////////////////////////////////////////////////////////////////
47 //
48 // dbWireShapeItr
49 //
50 //////////////////////////////////////////////////////////////////////////////////
dbWireShapeItr()51 dbWireShapeItr::dbWireShapeItr()
52 {
53   _wire = NULL;
54   _block = NULL;
55   _tech = NULL;
56 }
57 
~dbWireShapeItr()58 dbWireShapeItr::~dbWireShapeItr()
59 {
60 }
61 
nextOp(int & value)62 inline unsigned char dbWireShapeItr::nextOp(int& value)
63 {
64   ZASSERT(_idx < (int) _wire->length());
65   value = _wire->_data[_idx];
66   return _wire->_opcodes[_idx++];
67 }
68 
peekOp()69 inline unsigned char dbWireShapeItr::peekOp()
70 {
71   ZASSERT(_idx < (int) _wire->length());
72   return _wire->_opcodes[_idx];
73 }
74 
begin(dbWire * wire)75 void dbWireShapeItr::begin(dbWire* wire)
76 {
77   _wire = (_dbWire*) wire;
78   _block = wire->getBlock();
79   _tech = _block->getDb()->getTech();
80   _idx = 0;
81   _prev_x = 0;
82   _prev_y = 0;
83   _prev_ext = 0;
84   _has_prev_ext = false;
85   _layer = NULL;
86   _via = NULL;
87   _dw = 0;
88   _point_cnt = 0;
89   _has_width = false;
90 }
91 
next(dbShape & shape)92 bool dbWireShapeItr::next(dbShape& shape)
93 {
94   ZASSERT(_wire);
95   int operand;
96 
97 nextOpCode:
98   _shape_id = _idx;
99 
100   if (_idx == (int) _wire->_opcodes.size())
101     return false;
102 
103   unsigned char opcode = nextOp(operand);
104 
105   switch (opcode & WOP_OPCODE_MASK) {
106     case WOP_PATH:
107     case WOP_SHORT:
108     case WOP_VWIRE: {
109       _layer = dbTechLayer::getTechLayer(_tech, operand);
110       _point_cnt = 0;
111       _dw = _layer->getWidth() >> 1;
112       goto nextOpCode;
113     }
114 
115     case WOP_JUNCTION: {
116       WirePoint pnt;
117       getPrevPoint(
118           _tech, _block, _wire->_opcodes, _wire->_data, operand, true, pnt);
119       _layer = pnt._layer;
120       _prev_x = pnt._x;
121       _prev_y = pnt._y;
122       _prev_ext = 0;
123       _has_prev_ext = false;
124       _point_cnt = 0;
125       _dw = _layer->getWidth() >> 1;
126       goto nextOpCode;
127     }
128 
129     case WOP_RULE: {
130       if (opcode & WOP_BLOCK_RULE) {
131         dbTechLayerRule* rule
132             = dbTechLayerRule::getTechLayerRule(_block, operand);
133         _dw = rule->getWidth() >> 1;
134       } else {
135         dbTechLayerRule* rule
136             = dbTechLayerRule::getTechLayerRule(_tech, operand);
137         _dw = rule->getWidth() >> 1;
138       }
139 
140       _has_width = true;
141       goto nextOpCode;
142     }
143 
144     case WOP_X: {
145       int cur_x = operand;
146       int cur_y;
147 
148       if (_point_cnt == 0)
149         opcode = nextOp(cur_y);
150       else
151         cur_y = _prev_y;
152 
153       int cur_ext;
154       bool has_cur_ext;
155 
156       if (opcode & WOP_EXTENSION) {
157         nextOp(cur_ext);
158         has_cur_ext = true;
159       } else {
160         cur_ext = 0;
161         has_cur_ext = false;
162       }
163 
164       if (_point_cnt++ == 0) {
165         _prev_x = cur_x;
166         _prev_y = cur_y;
167         _prev_ext = cur_ext;
168         _has_prev_ext = has_cur_ext;
169         goto nextOpCode;
170       }
171 
172       shape.setSegment(_prev_x,
173                        _prev_y,
174                        _prev_ext,
175                        _has_prev_ext,
176                        cur_x,
177                        cur_y,
178                        cur_ext,
179                        has_cur_ext,
180                        _dw,
181                        _layer);
182       _prev_x = cur_x;
183       _prev_y = cur_y;
184       _prev_ext = cur_ext;
185       _has_prev_ext = has_cur_ext;
186       return true;
187     }
188 
189     case WOP_Y: {
190       ZASSERT(_point_cnt != 0);
191       _point_cnt++;
192       int cur_y = operand;
193       int cur_x = _prev_x;
194       int cur_ext;
195       bool has_cur_ext;
196 
197       if (opcode & WOP_EXTENSION) {
198         nextOp(cur_ext);
199         has_cur_ext = true;
200       } else {
201         cur_ext = 0;
202         has_cur_ext = false;
203       }
204 
205       shape.setSegment(_prev_x,
206                        _prev_y,
207                        _prev_ext,
208                        _has_prev_ext,
209                        cur_x,
210                        cur_y,
211                        cur_ext,
212                        has_cur_ext,
213                        _dw,
214                        _layer);
215       _prev_x = cur_x;
216       _prev_y = cur_y;
217       _prev_ext = cur_ext;
218       _has_prev_ext = has_cur_ext;
219       return true;
220     }
221 
222     case WOP_COLINEAR: {
223       _point_cnt++;
224 
225       // A colinear-point with an extension begins a new path-segment
226       if (opcode & WOP_EXTENSION) {
227         _prev_ext = operand;
228         _has_prev_ext = true;
229         goto nextOpCode;
230       }
231 
232       // A colinear-point following an extension cancels the ext
233       if (_has_prev_ext) {
234         _prev_ext = 0;
235         _has_prev_ext = false;
236         goto nextOpCode;
237       }
238 
239       if (_point_cnt > 1) {
240         shape.setSegment(_prev_x,
241                          _prev_y,
242                          _prev_ext,
243                          _has_prev_ext,
244                          _prev_x,
245                          _prev_y,
246                          0,
247                          false,
248                          _dw,
249                          _layer);
250         _has_prev_ext = false;
251         return true;
252       }
253 
254       _has_prev_ext = false;
255       goto nextOpCode;
256     }
257 
258     case WOP_VIA: {
259       dbVia* via = dbVia::getVia(_block, operand);
260 
261       if (opcode & WOP_VIA_EXIT_TOP)
262         _layer = via->getTopLayer();
263       else
264         _layer = via->getBottomLayer();
265 
266       if (_has_width == false)
267         _dw = _layer->getWidth() >> 1;
268 
269       _prev_ext = 0;
270       _has_prev_ext = false;
271 
272       dbBox* box = via->getBBox();
273 
274       if (box == NULL)
275         goto nextOpCode;
276 
277       Rect b;
278       box->getBox(b);
279       int xmin = b.xMin() + _prev_x;
280       int ymin = b.yMin() + _prev_y;
281       int xmax = b.xMax() + _prev_x;
282       int ymax = b.yMax() + _prev_y;
283       Rect r(xmin, ymin, xmax, ymax);
284       shape.setVia(via, r);
285       return true;
286     }
287 
288     case WOP_TECH_VIA: {
289       dbTechVia* via = dbTechVia::getTechVia(_tech, operand);
290 
291       if (opcode & WOP_VIA_EXIT_TOP)
292         _layer = via->getTopLayer();
293       else
294         _layer = via->getBottomLayer();
295 
296       if (_has_width == false)
297         _dw = _layer->getWidth() >> 1;
298 
299       _prev_ext = 0;
300       _has_prev_ext = false;
301 
302       dbBox* box = via->getBBox();
303 
304       if (box == NULL)
305         goto nextOpCode;
306 
307       Rect b;
308       box->getBox(b);
309       int xmin = b.xMin() + _prev_x;
310       int ymin = b.yMin() + _prev_y;
311       int xmax = b.xMax() + _prev_x;
312       int ymax = b.yMax() + _prev_y;
313       Rect r(xmin, ymin, xmax, ymax);
314       shape.setVia(via, r);
315       return true;
316     }
317 
318     case WOP_RECT: {
319       int deltaX1 = operand;
320       int deltaY1;
321       int deltaX2;
322       int deltaY2;
323       nextOp(deltaY1);
324       nextOp(deltaX2);
325       nextOp(deltaY2);
326       shape.setSegmentFromRect(_prev_x + deltaX1,
327                                _prev_y + deltaY1,
328                                _prev_x + deltaX2,
329                                _prev_y + deltaY2,
330                                _layer);
331       return true;
332     }
333 
334     case WOP_ITERM:
335     case WOP_BTERM:
336     case WOP_OPERAND:
337     case WOP_PROPERTY:
338     case WOP_NOP:
339       goto nextOpCode;
340 
341     default:
342       ZASSERT(DB_WIRE_DECODE_INVALID_OPCODE);
343       goto nextOpCode;
344   }
345 
346   return false;
347 }
348 
getShapeId()349 int dbWireShapeItr::getShapeId()
350 {
351   return _shape_id;
352 }
353 
354 }  // namespace odb
355