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 "dbRegion.h"
34 
35 #include "db.h"
36 #include "dbBlock.h"
37 #include "dbBlockCallBackObj.h"
38 #include "dbBox.h"
39 #include "dbBoxItr.h"
40 #include "dbDatabase.h"
41 #include "dbInst.h"
42 #include "dbRegion.h"
43 #include "dbRegionInstItr.h"
44 #include "dbRegionItr.h"
45 #include "dbTable.h"
46 #include "dbTable.hpp"
47 
48 namespace odb {
49 
50 template class dbTable<_dbRegion>;
51 
_dbRegion(_dbDatabase *)52 _dbRegion::_dbRegion(_dbDatabase*)
53 {
54   _flags._type = dbRegionType::INCLUSIVE;
55   _flags._invalid = false;
56   _name = NULL;
57 }
58 
_dbRegion(_dbDatabase *,const _dbRegion & r)59 _dbRegion::_dbRegion(_dbDatabase*, const _dbRegion& r)
60     : _flags(r._flags),
61       _name(NULL),
62       _insts(r._insts),
63       _boxes(r._boxes),
64       _parent(r._parent),
65       _children(r._children),
66       _next_child(r._next_child)
67 {
68   if (r._name)
69     _name = strdup(r._name);
70 }
71 
~_dbRegion()72 _dbRegion::~_dbRegion()
73 {
74   if (_name)
75     free((void*) _name);
76 }
77 
operator ==(const _dbRegion & rhs) const78 bool _dbRegion::operator==(const _dbRegion& rhs) const
79 {
80   if (_flags._type != rhs._flags._type)
81     return false;
82 
83   if (_flags._invalid != rhs._flags._invalid)
84     return false;
85 
86   if (_name && rhs._name) {
87     if (strcmp(_name, rhs._name) != 0)
88       return false;
89   } else if (_name || rhs._name)
90     return false;
91 
92   if (_insts != rhs._insts)
93     return false;
94 
95   if (_parent != rhs._parent)
96     return false;
97 
98   if (_children != rhs._children)
99     return false;
100 
101   if (_next_child != rhs._next_child)
102     return false;
103 
104   return true;
105 }
106 
operator <(const _dbRegion & rhs) const107 bool _dbRegion::operator<(const _dbRegion& rhs) const
108 {
109   if (_flags._type < rhs._flags._type)
110     return false;
111 
112   if (_flags._type > rhs._flags._type)
113     return true;
114 
115   if (_flags._invalid < rhs._flags._invalid)
116     return false;
117 
118   if (_flags._invalid > rhs._flags._invalid)
119     return true;
120 
121   if (_insts < rhs._insts)
122     return true;
123 
124   if (_insts > rhs._insts)
125     return false;
126 
127   if (_parent < rhs._parent)
128     return true;
129 
130   if (_parent > rhs._parent)
131     return false;
132 
133   if (_children < rhs._children)
134     return true;
135 
136   if (_children > rhs._children)
137     return false;
138 
139   if (_next_child < rhs._next_child)
140     return true;
141 
142   if (_next_child > rhs._next_child)
143     return false;
144 
145   return _boxes < rhs._boxes;
146 }
147 
differences(dbDiff & diff,const char * field,const _dbRegion & rhs) const148 void _dbRegion::differences(dbDiff& diff,
149                             const char* field,
150                             const _dbRegion& rhs) const
151 {
152   if (diff.deepDiff())
153     return;
154 
155   DIFF_BEGIN
156   DIFF_FIELD(_flags._type);
157   DIFF_FIELD(_flags._invalid);
158   DIFF_FIELD(_name);
159   DIFF_FIELD(_insts);
160   DIFF_FIELD(_boxes);
161   DIFF_FIELD(_parent);
162   DIFF_FIELD(_children);
163   DIFF_FIELD(_next_child);
164   DIFF_END
165 }
166 
out(dbDiff & diff,char side,const char * field) const167 void _dbRegion::out(dbDiff& diff, char side, const char* field) const
168 {
169   if (diff.deepDiff())
170     return;
171 
172   DIFF_OUT_BEGIN
173   DIFF_OUT_FIELD(_flags._type);
174   DIFF_OUT_FIELD(_flags._invalid);
175   DIFF_OUT_FIELD(_name);
176   DIFF_OUT_FIELD(_insts);
177   DIFF_OUT_FIELD(_boxes);
178   DIFF_OUT_FIELD(_parent);
179   DIFF_OUT_FIELD(_children);
180   DIFF_OUT_FIELD(_next_child);
181   DIFF_END
182 }
183 
operator <<(dbOStream & stream,const _dbRegion & r)184 dbOStream& operator<<(dbOStream& stream, const _dbRegion& r)
185 {
186   uint* bit_field = (uint*) &r._flags;
187   stream << *bit_field;
188   stream << r._name;
189   stream << r._insts;
190   stream << r._boxes;
191   stream << r._parent;
192   stream << r._children;
193   stream << r._next_child;
194   return stream;
195 }
196 
operator >>(dbIStream & stream,_dbRegion & r)197 dbIStream& operator>>(dbIStream& stream, _dbRegion& r)
198 {
199   uint* bit_field = (uint*) &r._flags;
200   stream >> *bit_field;
201   stream >> r._name;
202   stream >> r._insts;
203   stream >> r._boxes;
204   stream >> r._parent;
205   stream >> r._children;
206   stream >> r._next_child;
207 
208   return stream;
209 }
210 
getName()211 std::string dbRegion::getName()
212 {
213   _dbRegion* region = (_dbRegion*) this;
214   return region->_name;
215 }
216 
getRegionType()217 dbRegionType dbRegion::getRegionType()
218 {
219   _dbRegion* region = (_dbRegion*) this;
220   dbRegionType t(region->_flags._type);
221   return t;
222 }
223 
setInvalid(bool v)224 void dbRegion::setInvalid(bool v)
225 {
226   _dbRegion* region = (_dbRegion*) this;
227   region->_flags._invalid = v;
228 }
229 
isInvalid()230 bool dbRegion::isInvalid()
231 {
232   _dbRegion* region = (_dbRegion*) this;
233   return region->_flags._invalid == 1;
234 }
235 
setRegionType(dbRegionType type)236 void dbRegion::setRegionType(dbRegionType type)
237 {
238   _dbRegion* region = (_dbRegion*) this;
239   region->_flags._type = type;
240 }
241 
getRegionInsts()242 dbSet<dbInst> dbRegion::getRegionInsts()
243 {
244   _dbRegion* region = (_dbRegion*) this;
245   _dbBlock* block = (_dbBlock*) region->getOwner();
246   return dbSet<dbInst>(region, block->_region_inst_itr);
247 }
248 
getBoundaries()249 dbSet<dbBox> dbRegion::getBoundaries()
250 {
251   _dbRegion* region = (_dbRegion*) this;
252   _dbBlock* block = (_dbBlock*) region->getOwner();
253   return dbSet<dbBox>(region, block->_box_itr);
254 }
255 
addInst(dbInst * inst_)256 void dbRegion::addInst(dbInst* inst_)
257 {
258   _dbRegion* region = (_dbRegion*) this;
259   _dbInst* inst = (_dbInst*) inst_;
260   _dbBlock* block = (_dbBlock*) region->getOwner();
261 
262   if (inst->_region != 0) {
263     dbRegion* r = dbRegion::getRegion((dbBlock*) block, inst->_region);
264     r->removeInst(inst_);
265   }
266 
267   inst->_region = region->getOID();
268 
269   if (region->_insts != 0) {
270     _dbInst* tail = block->_inst_tbl->getPtr(region->_insts);
271     inst->_region_next = region->_insts;
272     inst->_region_prev = 0;
273     tail->_region_prev = inst->getOID();
274   } else {
275     inst->_region_next = 0;
276     inst->_region_prev = 0;
277   }
278 
279   region->_insts = inst->getOID();
280 }
281 
removeInst(dbInst * inst_)282 void dbRegion::removeInst(dbInst* inst_)
283 {
284   _dbRegion* region = (_dbRegion*) this;
285   _dbInst* inst = (_dbInst*) inst_;
286   _dbBlock* block = (_dbBlock*) region->getOwner();
287 
288   uint id = inst->getOID();
289 
290   if (region->_insts == id) {
291     region->_insts = inst->_region_next;
292 
293     if (region->_insts != 0) {
294       _dbInst* t = block->_inst_tbl->getPtr(region->_insts);
295       t->_region_prev = 0;
296     }
297   } else {
298     if (inst->_region_next != 0) {
299       _dbInst* next = block->_inst_tbl->getPtr(inst->_region_next);
300       next->_region_prev = inst->_region_prev;
301     }
302 
303     if (inst->_region_prev != 0) {
304       _dbInst* prev = block->_inst_tbl->getPtr(inst->_region_prev);
305       prev->_region_next = inst->_region_next;
306     }
307   }
308 
309   inst->_region = 0;
310 }
311 
getParent()312 dbRegion* dbRegion::getParent()
313 {
314   _dbRegion* region = (_dbRegion*) this;
315   _dbBlock* block = (_dbBlock*) region->getOwner();
316 
317   if (region->_parent == 0)
318     return NULL;
319 
320   _dbRegion* p = block->_region_tbl->getPtr(region->_parent);
321   return (dbRegion*) p;
322 }
323 
getChildren()324 dbSet<dbRegion> dbRegion::getChildren()
325 {
326   _dbRegion* region = (_dbRegion*) this;
327   _dbBlock* block = (_dbBlock*) region->getOwner();
328 
329   dbSet<dbRegion> children(region, block->_region_itr);
330   return children;
331 }
332 
addChild(dbRegion * child_)333 void dbRegion::addChild(dbRegion* child_)
334 {
335   _dbRegion* child = (_dbRegion*) child_;
336   _dbRegion* parent = (_dbRegion*) this;
337   //_dbBlock * block = (_dbBlock *) getOwner();
338 
339   if (child->_parent || (parent == child))
340     return;
341 
342   child->_parent = parent->getOID();
343   child->_next_child = parent->_children;
344   parent->_children = child->getOID();
345 }
346 
getBlock()347 dbBlock* dbRegion::getBlock()
348 {
349   return (dbBlock*) getImpl()->getOwner();
350 }
351 
create(dbBlock * block_,const char * name)352 dbRegion* dbRegion::create(dbBlock* block_, const char* name)
353 {
354   _dbBlock* block = (_dbBlock*) block_;
355 
356   if (block_->findRegion(name))
357     return NULL;
358 
359   _dbRegion* region = block->_region_tbl->create();
360   region->_name = strdup(name);
361   ZALLOCATED(region->_name);
362   for (auto callback : block->_callbacks)
363     callback->inDbRegionCreate((dbRegion*) region);
364   return (dbRegion*) region;
365 }
366 
create(dbRegion * parent_,const char * name)367 dbRegion* dbRegion::create(dbRegion* parent_, const char* name)
368 {
369   _dbRegion* parent = (_dbRegion*) parent_;
370   _dbBlock* block = (_dbBlock*) parent->getOwner();
371 
372   if (((dbBlock*) block)->findRegion(name))
373     return NULL;
374 
375   _dbRegion* region = block->_region_tbl->create();
376   region->_name = strdup(name);
377   ZALLOCATED(region->_name);
378   region->_parent = parent->getOID();
379   region->_next_child = parent->_children;
380   parent->_children = region->getOID();
381   for (auto callback : block->_callbacks)
382     callback->inDbRegionCreate((dbRegion*) region);
383   return (dbRegion*) region;
384 }
385 
destroy(dbRegion * region_)386 void dbRegion::destroy(dbRegion* region_)
387 {
388   _dbRegion* region = (_dbRegion*) region_;
389   _dbBlock* block = (_dbBlock*) region->getOwner();
390 
391   dbSet<dbRegion> children = region_->getChildren();
392   dbSet<dbRegion>::iterator childItr;
393   for (childItr = children.begin(); childItr != children.end();
394        childItr = children.begin()) {
395     dbRegion* child = *childItr;
396     child->destroy(child);
397   }
398   for (auto callback : block->_callbacks)
399     callback->inDbRegionDestroy((dbRegion*) region);
400 
401   dbSet<dbInst> insts = region_->getRegionInsts();
402   dbSet<dbInst>::iterator iitr;
403 
404   for (iitr = insts.begin(); iitr != insts.end(); iitr = insts.begin()) {
405     dbInst* inst = *iitr;
406     region_->removeInst(inst);
407   }
408 
409   dbSet<dbBox> boxes = region_->getBoundaries();
410   dbSet<dbBox>::iterator bitr;
411 
412   for (bitr = boxes.begin(); bitr != boxes.end();) {
413     dbSet<dbBox>::iterator next = ++bitr;
414     dbBox* box = *bitr;
415     dbProperty::destroyProperties(box);
416     block->_box_tbl->destroy((_dbBox*) box);
417     bitr = next;
418   }
419 
420   if (region->_parent) {
421     _dbRegion* parent = block->_region_tbl->getPtr(region->_parent);
422     _dbRegion* prev = NULL;
423     _dbRegion* cur = block->_region_tbl->getPtr(parent->_children);
424 
425     while (cur) {
426       if (cur == region)
427         break;
428 
429       prev = cur;
430       cur = block->_region_tbl->getPtr(cur->_next_child);
431     }
432 
433     if (prev == NULL)
434       parent->_children = region->_next_child;
435     else
436       prev->_next_child = region->_next_child;
437   }
438 
439   dbProperty::destroyProperties(region);
440   block->_region_tbl->destroy(region);
441 }
442 
destroy(dbSet<dbRegion>::iterator & itr)443 dbSet<dbRegion>::iterator dbRegion::destroy(dbSet<dbRegion>::iterator& itr)
444 {
445   dbRegion* r = *itr;
446   dbSet<dbRegion>::iterator next = ++itr;
447   destroy(r);
448   return next;
449 }
450 
getRegion(dbBlock * block_,uint dbid_)451 dbRegion* dbRegion::getRegion(dbBlock* block_, uint dbid_)
452 {
453   _dbBlock* block = (_dbBlock*) block_;
454   return (dbRegion*) block->_region_tbl->getPtr(dbid_);
455 }
456 
457 }  // namespace odb
458