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