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