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 "dbObstruction.h"
34
35 #include "db.h"
36 #include "dbBlock.h"
37 #include "dbBlockCallBackObj.h"
38 #include "dbBox.h"
39 #include "dbDatabase.h"
40 #include "dbDiff.hpp"
41 #include "dbInst.h"
42 #include "dbSet.h"
43 #include "dbTable.h"
44 #include "dbTable.hpp"
45 #include "dbTechLayer.h"
46
47 namespace odb {
48
49 template class dbTable<_dbObstruction>;
50
_dbObstruction(_dbDatabase *,const _dbObstruction & o)51 _dbObstruction::_dbObstruction(_dbDatabase*, const _dbObstruction& o)
52 : _flags(o._flags),
53 _inst(o._inst),
54 _bbox(o._bbox),
55 _min_spacing(o._min_spacing),
56 _effective_width(o._effective_width)
57 {
58 }
59
_dbObstruction(_dbDatabase *)60 _dbObstruction::_dbObstruction(_dbDatabase*)
61 {
62 _flags._slot_obs = 0;
63 _flags._fill_obs = 0;
64 _flags._pushed_down = 0;
65 _flags._has_min_spacing = 0;
66 _flags._has_effective_width = 0;
67 _flags._spare_bits = 0;
68 _min_spacing = 0;
69 _effective_width = 0;
70 }
71
~_dbObstruction()72 _dbObstruction::~_dbObstruction()
73 {
74 }
75
operator <<(dbOStream & stream,const _dbObstruction & obs)76 dbOStream& operator<<(dbOStream& stream, const _dbObstruction& obs)
77 {
78 uint* bit_field = (uint*) &obs._flags;
79 stream << *bit_field;
80 stream << obs._inst;
81 stream << obs._bbox;
82 stream << obs._min_spacing;
83 stream << obs._effective_width;
84 return stream;
85 }
86
operator >>(dbIStream & stream,_dbObstruction & obs)87 dbIStream& operator>>(dbIStream& stream, _dbObstruction& obs)
88 {
89 uint* bit_field = (uint*) &obs._flags;
90 stream >> *bit_field;
91 stream >> obs._inst;
92 stream >> obs._bbox;
93 stream >> obs._min_spacing;
94 stream >> obs._effective_width;
95
96 return stream;
97 }
98
operator ==(const _dbObstruction & rhs) const99 bool _dbObstruction::operator==(const _dbObstruction& rhs) const
100 {
101 if (_flags._slot_obs != rhs._flags._slot_obs)
102 return false;
103
104 if (_flags._fill_obs != rhs._flags._fill_obs)
105 return false;
106
107 if (_flags._pushed_down != rhs._flags._pushed_down)
108 return false;
109
110 if (_flags._has_min_spacing != rhs._flags._has_min_spacing)
111 return false;
112
113 if (_flags._has_effective_width != rhs._flags._has_effective_width)
114 return false;
115
116 if (_inst != rhs._inst)
117 return false;
118
119 if (_bbox != rhs._bbox)
120 return false;
121
122 return true;
123 }
124
differences(dbDiff & diff,const char * field,const _dbObstruction & rhs) const125 void _dbObstruction::differences(dbDiff& diff,
126 const char* field,
127 const _dbObstruction& rhs) const
128 {
129 _dbBlock* lhs_blk = (_dbBlock*) getOwner();
130 _dbBlock* rhs_blk = (_dbBlock*) rhs.getOwner();
131
132 DIFF_BEGIN
133 DIFF_FIELD(_flags._slot_obs);
134 DIFF_FIELD(_flags._fill_obs);
135 DIFF_FIELD(_flags._pushed_down);
136 DIFF_FIELD(_flags._has_min_spacing);
137 DIFF_FIELD(_flags._has_effective_width);
138 DIFF_FIELD(_min_spacing);
139 DIFF_FIELD(_effective_width);
140
141 if (!diff.deepDiff()) {
142 DIFF_FIELD(_inst);
143 } else {
144 if (_inst && rhs._inst) {
145 _dbBlock* lhs_blk = (_dbBlock*) getOwner();
146 _dbBlock* rhs_blk = (_dbBlock*) rhs.getOwner();
147 _dbInst* lhs_inst = lhs_blk->_inst_tbl->getPtr(_inst);
148 _dbInst* rhs_inst = rhs_blk->_inst_tbl->getPtr(rhs._inst);
149 diff.diff("_inst", lhs_inst->_name, rhs_inst->_name);
150 } else if (_inst) {
151 _dbBlock* lhs_blk = (_dbBlock*) getOwner();
152 _dbInst* lhs_inst = lhs_blk->_inst_tbl->getPtr(_inst);
153 diff.out(dbDiff::LEFT, "_inst", lhs_inst->_name);
154 } else if (rhs._inst) {
155 _dbBlock* rhs_blk = (_dbBlock*) rhs.getOwner();
156 _dbInst* rhs_inst = rhs_blk->_inst_tbl->getPtr(rhs._inst);
157 diff.out(dbDiff::RIGHT, "_inst", rhs_inst->_name);
158 }
159 }
160
161 DIFF_OBJECT(_bbox, lhs_blk->_box_tbl, rhs_blk->_box_tbl);
162 DIFF_END
163 }
164
out(dbDiff & diff,char side,const char * field) const165 void _dbObstruction::out(dbDiff& diff, char side, const char* field) const
166 {
167 _dbBlock* blk = (_dbBlock*) getOwner();
168
169 DIFF_OUT_BEGIN
170 DIFF_OUT_FIELD(_flags._slot_obs);
171 DIFF_OUT_FIELD(_flags._fill_obs);
172 DIFF_OUT_FIELD(_flags._pushed_down);
173 DIFF_OUT_FIELD(_flags._has_min_spacing);
174 DIFF_OUT_FIELD(_flags._has_effective_width);
175 DIFF_OUT_FIELD(_min_spacing);
176 DIFF_OUT_FIELD(_effective_width);
177
178 if (!diff.deepDiff()) {
179 DIFF_OUT_FIELD(_inst);
180 } else {
181 if (_inst) {
182 _dbBlock* blk = (_dbBlock*) getOwner();
183 _dbInst* inst = blk->_inst_tbl->getPtr(_inst);
184 diff.out(side, "_inst", inst->_name);
185 } else {
186 diff.out(side, "_inst", "(NULL)");
187 }
188 }
189
190 DIFF_OUT_OBJECT(_bbox, blk->_box_tbl);
191 DIFF_END
192 }
193
operator <(const _dbObstruction & rhs) const194 bool _dbObstruction::operator<(const _dbObstruction& rhs) const
195 {
196 _dbBlock* lhs_block = (_dbBlock*) getOwner();
197 _dbBlock* rhs_block = (_dbBlock*) rhs.getOwner();
198 _dbBox* lhs_box = lhs_block->_box_tbl->getPtr(_bbox);
199 _dbBox* rhs_box = rhs_block->_box_tbl->getPtr(rhs._bbox);
200
201 if (*lhs_box < *rhs_box)
202 return true;
203
204 if (lhs_box->equal(*rhs_box)) {
205 if (_inst && rhs._inst) {
206 _dbBlock* lhs_blk = (_dbBlock*) getOwner();
207 _dbBlock* rhs_blk = (_dbBlock*) rhs.getOwner();
208 _dbInst* lhs_inst = lhs_blk->_inst_tbl->getPtr(_inst);
209 _dbInst* rhs_inst = rhs_blk->_inst_tbl->getPtr(rhs._inst);
210 int r = strcmp(lhs_inst->_name, rhs_inst->_name);
211
212 if (r < 0)
213 return true;
214
215 if (r > 0)
216 return false;
217 } else if (_inst) {
218 return false;
219 } else if (rhs._inst) {
220 return true;
221 }
222
223 if (_flags._slot_obs < rhs._flags._slot_obs)
224 return true;
225
226 if (_flags._slot_obs > rhs._flags._slot_obs)
227 return false;
228
229 if (_flags._fill_obs < rhs._flags._fill_obs)
230 return true;
231
232 if (_flags._fill_obs > rhs._flags._fill_obs)
233 return false;
234
235 if (_flags._pushed_down < rhs._flags._pushed_down)
236 return true;
237
238 if (_flags._pushed_down > rhs._flags._pushed_down)
239 return false;
240
241 if (_flags._has_min_spacing < rhs._flags._has_min_spacing)
242 return true;
243
244 if (_flags._has_min_spacing > rhs._flags._has_min_spacing)
245 return false;
246
247 if (_flags._has_effective_width < rhs._flags._has_effective_width)
248 return true;
249
250 if (_flags._has_effective_width > rhs._flags._has_effective_width)
251 return false;
252
253 if (_min_spacing < rhs._min_spacing)
254 return true;
255
256 if (_min_spacing > rhs._min_spacing)
257 return false;
258
259 if (_effective_width < rhs._effective_width)
260 return true;
261
262 if (_effective_width > rhs._effective_width)
263 return false;
264 }
265
266 return false;
267 }
268
269 ////////////////////////////////////////////////////////////////////
270 //
271 // dbObstruction - Methods
272 //
273 ////////////////////////////////////////////////////////////////////
274
getBBox()275 dbBox* dbObstruction::getBBox()
276 {
277 _dbObstruction* obs = (_dbObstruction*) this;
278 _dbBlock* block = (_dbBlock*) obs->getOwner();
279 return (dbBox*) block->_box_tbl->getPtr(obs->_bbox);
280 }
281
getInstance()282 dbInst* dbObstruction::getInstance()
283 {
284 _dbObstruction* obs = (_dbObstruction*) this;
285
286 if (obs->_inst == 0)
287 return NULL;
288
289 _dbBlock* block = (_dbBlock*) obs->getOwner();
290 return (dbInst*) block->_inst_tbl->getPtr(obs->_inst);
291 }
292
setSlotObstruction()293 void dbObstruction::setSlotObstruction()
294 {
295 _dbObstruction* obs = (_dbObstruction*) this;
296 obs->_flags._slot_obs = 1;
297 }
298
isSlotObstruction()299 bool dbObstruction::isSlotObstruction()
300 {
301 _dbObstruction* obs = (_dbObstruction*) this;
302 return obs->_flags._slot_obs == 1;
303 }
304
setFillObstruction()305 void dbObstruction::setFillObstruction()
306 {
307 _dbObstruction* obs = (_dbObstruction*) this;
308 obs->_flags._fill_obs = 1;
309 }
310
isFillObstruction()311 bool dbObstruction::isFillObstruction()
312 {
313 _dbObstruction* obs = (_dbObstruction*) this;
314 return obs->_flags._fill_obs == 1;
315 }
316
setPushedDown()317 void dbObstruction::setPushedDown()
318 {
319 _dbObstruction* obs = (_dbObstruction*) this;
320 obs->_flags._pushed_down = 1;
321 }
322
isPushedDown()323 bool dbObstruction::isPushedDown()
324 {
325 _dbObstruction* obs = (_dbObstruction*) this;
326 return obs->_flags._pushed_down == 1;
327 }
328
hasEffectiveWidth()329 bool dbObstruction::hasEffectiveWidth()
330 {
331 _dbObstruction* obs = (_dbObstruction*) this;
332 return obs->_flags._has_effective_width == 1U;
333 }
334
setEffectiveWidth(int w)335 void dbObstruction::setEffectiveWidth(int w)
336 {
337 _dbObstruction* obs = (_dbObstruction*) this;
338 obs->_flags._has_effective_width = 1U;
339 obs->_effective_width = w;
340 }
341
getEffectiveWidth()342 int dbObstruction::getEffectiveWidth()
343 {
344 _dbObstruction* obs = (_dbObstruction*) this;
345 return obs->_effective_width;
346 }
347
hasMinSpacing()348 bool dbObstruction::hasMinSpacing()
349 {
350 _dbObstruction* obs = (_dbObstruction*) this;
351 return obs->_flags._has_min_spacing == 1U;
352 }
353
setMinSpacing(int w)354 void dbObstruction::setMinSpacing(int w)
355 {
356 _dbObstruction* obs = (_dbObstruction*) this;
357 obs->_flags._has_min_spacing = 1U;
358 obs->_min_spacing = w;
359 }
360
getMinSpacing()361 int dbObstruction::getMinSpacing()
362 {
363 _dbObstruction* obs = (_dbObstruction*) this;
364 return obs->_min_spacing;
365 }
366
getBlock()367 dbBlock* dbObstruction::getBlock()
368 {
369 return (dbBlock*) getImpl()->getOwner();
370 }
371
create(dbBlock * block_,dbTechLayer * layer_,int x1,int y1,int x2,int y2,dbInst * inst_)372 dbObstruction* dbObstruction::create(dbBlock* block_,
373 dbTechLayer* layer_,
374 int x1,
375 int y1,
376 int x2,
377 int y2,
378 dbInst* inst_)
379 {
380 _dbBlock* block = (_dbBlock*) block_;
381 _dbTechLayer* layer = (_dbTechLayer*) layer_;
382 _dbInst* inst = (_dbInst*) inst_;
383
384 _dbObstruction* obs = block->_obstruction_tbl->create();
385
386 if (inst)
387 obs->_inst = inst->getOID();
388
389 _dbBox* box = block->_box_tbl->create();
390 box->_shape._rect.init(x1, y1, x2, y2);
391 box->_flags._owner_type = dbBoxOwner::OBSTRUCTION;
392 box->_owner = obs->getOID();
393 box->_flags._layer_id = layer->getOID();
394 obs->_bbox = box->getOID();
395
396 // Update bounding box of block
397 block->add_rect(box->_shape._rect);
398 for (auto callback : block->_callbacks)
399 callback->inDbObstructionCreate((dbObstruction*) obs);
400 return (dbObstruction*) obs;
401 }
402
destroy(dbObstruction * obstruction)403 void dbObstruction::destroy(dbObstruction* obstruction)
404 {
405 _dbObstruction* obs = (_dbObstruction*) obstruction;
406 _dbBlock* block = (_dbBlock*) obs->getOwner();
407 for (auto callback : block->_callbacks)
408 callback->inDbObstructionDestroy(obstruction);
409 dbProperty::destroyProperties(obs);
410 block->_obstruction_tbl->destroy(obs);
411 }
412
getObstruction(dbBlock * block_,uint dbid_)413 dbObstruction* dbObstruction::getObstruction(dbBlock* block_, uint dbid_)
414 {
415 _dbBlock* block = (_dbBlock*) block_;
416 return (dbObstruction*) block->_obstruction_tbl->getPtr(dbid_);
417 }
418
419 } // namespace odb
420