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