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 "dbProperty.h"
34
35 #include "db.h"
36 #include "dbBlock.h"
37 #include "dbChip.h"
38 #include "dbDatabase.h"
39 #include "dbLib.h"
40 #include "dbName.h"
41 #include "dbNameCache.h"
42 #include "dbPropertyItr.h"
43 #include "dbTable.h"
44 #include "dbTable.hpp"
45 #include "dbTech.h"
46
47 namespace odb {
48
49 template class dbTable<_dbProperty>;
50
_dbProperty(_dbDatabase *,const _dbProperty & n)51 _dbProperty::_dbProperty(_dbDatabase*, const _dbProperty& n)
52 : _flags(n._flags), _name(n._name), _next(n._next), _owner(n._owner)
53 {
54 memcpy(&_value, &n._value, sizeof(_value));
55 }
56
_dbProperty(_dbDatabase *)57 _dbProperty::_dbProperty(_dbDatabase*)
58 {
59 _flags._type = DB_STRING_PROP;
60 _flags._spare_bits = 0;
61 _name = 0;
62 _owner = 0;
63 memset(&_value, 0, sizeof(_value));
64 }
65
~_dbProperty()66 _dbProperty::~_dbProperty()
67 {
68 }
69
operator ==(const _dbProperty & rhs) const70 bool _dbProperty::operator==(const _dbProperty& rhs) const
71 {
72 if (_flags._type != rhs._flags._type)
73 return false;
74
75 if (_flags._owner_type != rhs._flags._owner_type)
76 return false;
77
78 if (_name != rhs._name)
79 return false;
80
81 if (_flags._owner_type
82 != dbDatabaseObj) // database owners are never the same...
83 if (_owner != rhs._owner)
84 return false;
85
86 if (_next != rhs._next)
87 return false;
88
89 switch (_flags._type) {
90 case DB_STRING_PROP:
91 if (strcmp(_value._str_val, rhs._value._str_val) != 0)
92 return false;
93
94 break;
95
96 case DB_BOOL_PROP:
97 if (_value._bool_val != rhs._value._bool_val)
98 return false;
99
100 break;
101
102 case DB_INT_PROP:
103 if (_value._int_val != rhs._value._int_val)
104 return false;
105
106 break;
107
108 case DB_DOUBLE_PROP:
109 if (_value._double_val != rhs._value._double_val)
110 return false;
111
112 break;
113 }
114
115 return true;
116 }
117
differences(dbDiff & diff,const char * field,const _dbProperty & rhs) const118 void _dbProperty::differences(dbDiff& diff,
119 const char* field,
120 const _dbProperty& rhs) const
121 {
122 DIFF_BEGIN
123 DIFF_FIELD(_flags._type);
124 DIFF_FIELD(_flags._owner_type);
125 DIFF_FIELD(_name);
126
127 if (_flags._owner_type
128 != dbDatabaseObj) // database owners are never the same...
129 {
130 DIFF_FIELD(_owner);
131 }
132
133 DIFF_FIELD(_next);
134 DIFF_END
135 }
136
out(dbDiff & diff,char side,const char * field) const137 void _dbProperty::out(dbDiff& diff, char side, const char* field) const
138 {
139 DIFF_OUT_BEGIN
140 DIFF_OUT_FIELD(_flags._type);
141 DIFF_OUT_FIELD(_flags._owner_type);
142 DIFF_OUT_FIELD(_name);
143 DIFF_OUT_FIELD(_owner);
144 DIFF_OUT_FIELD(_next);
145 DIFF_END
146 }
147
operator <<(dbOStream & stream,const _dbProperty & prop)148 dbOStream& operator<<(dbOStream& stream, const _dbProperty& prop)
149 {
150 uint* bit_field = (uint*) &prop._flags;
151 stream << *bit_field;
152 stream << prop._name;
153 stream << prop._next;
154 stream << prop._owner;
155
156 switch (prop._flags._type) {
157 case DB_BOOL_PROP:
158 stream << prop._value._bool_val;
159 break;
160
161 case DB_INT_PROP:
162 stream << prop._value._int_val;
163 break;
164
165 case DB_STRING_PROP:
166 stream << prop._value._str_val;
167 break;
168
169 case DB_DOUBLE_PROP:
170 stream << prop._value._double_val;
171 break;
172 }
173
174 return stream;
175 }
176
operator >>(dbIStream & stream,_dbProperty & prop)177 dbIStream& operator>>(dbIStream& stream, _dbProperty& prop)
178 {
179 uint* bit_field = (uint*) &prop._flags;
180 stream >> *bit_field;
181 stream >> prop._name;
182 stream >> prop._next;
183 stream >> prop._owner;
184
185 switch (prop._flags._type) {
186 case DB_BOOL_PROP:
187 stream >> prop._value._bool_val;
188 break;
189
190 case DB_INT_PROP:
191 stream >> prop._value._int_val;
192 break;
193
194 case DB_STRING_PROP:
195 stream >> prop._value._str_val;
196 break;
197
198 case DB_DOUBLE_PROP:
199 stream >> prop._value._double_val;
200 break;
201 }
202
203 return stream;
204 }
205
operator <(const _dbProperty & rhs) const206 bool _dbProperty::operator<(const _dbProperty& rhs) const
207 {
208 return _name < rhs._name;
209 }
210
getItr(dbObject * object)211 dbPropertyItr* _dbProperty::getItr(dbObject* object)
212 {
213 next_object:
214 switch (object->getObjectType()) {
215 case dbDatabaseObj: {
216 _dbDatabase* db = (_dbDatabase*) object;
217 return db->_prop_itr;
218 }
219
220 case dbChipObj: {
221 _dbChip* chip = (_dbChip*) object;
222 return chip->_prop_itr;
223 }
224
225 case dbBlockObj: {
226 _dbBlock* blk = (_dbBlock*) object;
227 return blk->_prop_itr;
228 }
229
230 case dbLibObj: {
231 _dbLib* lib = (_dbLib*) object;
232 return lib->_prop_itr;
233 }
234
235 case dbTechObj: {
236 _dbTech* tech = (_dbTech*) object;
237 return tech->_prop_itr;
238 }
239
240 default:
241 object = object->getImpl()->getOwner();
242 goto next_object;
243 }
244
245 assert(0);
246 return NULL;
247 }
248
getNameCache(dbObject * object)249 _dbNameCache* _dbProperty::getNameCache(dbObject* object)
250 {
251 next_object:
252 switch (object->getObjectType()) {
253 case dbDatabaseObj: {
254 _dbDatabase* db = (_dbDatabase*) object;
255 return db->_name_cache;
256 }
257
258 case dbChipObj: {
259 _dbChip* chip = (_dbChip*) object;
260 return chip->_name_cache;
261 }
262
263 case dbBlockObj: {
264 _dbBlock* blk = (_dbBlock*) object;
265 return blk->_name_cache;
266 }
267
268 case dbLibObj: {
269 _dbLib* lib = (_dbLib*) object;
270 return lib->_name_cache;
271 }
272
273 case dbTechObj: {
274 _dbTech* tech = (_dbTech*) object;
275 return tech->_name_cache;
276 }
277
278 default:
279 object = object->getImpl()->getOwner();
280 goto next_object;
281 }
282
283 assert(0);
284 return NULL;
285 }
286
getPropTable(dbObject * object)287 dbTable<_dbProperty>* _dbProperty::getPropTable(dbObject* object)
288 {
289 next_object:
290 switch (object->getObjectType()) {
291 case dbDatabaseObj: {
292 _dbDatabase* db = (_dbDatabase*) object;
293 return db->_prop_tbl;
294 }
295
296 case dbChipObj: {
297 _dbChip* chip = (_dbChip*) object;
298 return chip->_prop_tbl;
299 }
300
301 case dbBlockObj: {
302 _dbBlock* blk = (_dbBlock*) object;
303 return blk->_prop_tbl;
304 }
305
306 case dbLibObj: {
307 _dbLib* lib = (_dbLib*) object;
308 return lib->_prop_tbl;
309 }
310
311 case dbTechObj: {
312 _dbTech* tech = (_dbTech*) object;
313 return tech->_prop_tbl;
314 }
315
316 default:
317 object = object->getImpl()->getOwner();
318 goto next_object;
319 }
320
321 assert(0);
322 return NULL;
323 }
324
createProperty(dbObject * object_,const char * name,_PropTypeEnum type)325 _dbProperty* _dbProperty::createProperty(dbObject* object_,
326 const char* name,
327 _PropTypeEnum type)
328 {
329 _dbObject* object = (_dbObject*) object_;
330 dbTable<_dbProperty>* propTable = getPropTable(object);
331
332 // Create property
333 _dbProperty* prop = propTable->create();
334 uint oid = object->getOID();
335 prop->_flags._type = type;
336 prop->_flags._owner_type = object->getType();
337 prop->_owner = oid;
338
339 // Get name-id, increment reference count
340 _dbNameCache* cache = getNameCache(object);
341 uint name_id = cache->addName(name);
342 prop->_name = name_id;
343
344 // Link property into owner's prop-list
345 dbObjectTable* table = object->getTable();
346 dbId<_dbProperty> propList = table->getPropList(oid);
347 prop->_next = propList;
348 propList = prop->getImpl()->getOID();
349 table->setPropList(oid, propList);
350 return prop;
351 }
352
353 /////////////////////////////////////////////
354 // property
355 /////////////////////////////////////////////
356
getType()357 dbProperty::Type dbProperty::getType()
358 {
359 _dbProperty* prop = (_dbProperty*) this;
360 return (dbProperty::Type) prop->_flags._type;
361 }
362
getName()363 std::string dbProperty::getName()
364 {
365 _dbProperty* prop = (_dbProperty*) this;
366 _dbNameCache* cache = _dbProperty::getNameCache(this);
367 const char* name = cache->getName(prop->_name);
368 return name;
369 }
370
getPropOwner()371 dbObject* dbProperty::getPropOwner()
372 {
373 _dbProperty* prop = (_dbProperty*) this;
374 dbObjectTable* table = prop->getTable()->getObjectTable(
375 (dbObjectType) prop->_flags._owner_type);
376 return table->getObject(prop->_owner);
377 }
378
find(dbObject * object,const char * name)379 dbProperty* dbProperty::find(dbObject* object, const char* name)
380 {
381 _dbNameCache* cache = _dbProperty::getNameCache(object);
382
383 uint name_id = cache->findName(name);
384
385 if (name_id == 0)
386 return NULL;
387
388 dbSet<dbProperty> props = getProperties(object);
389
390 dbSet<dbProperty>::iterator itr;
391
392 for (itr = props.begin(); itr != props.end(); ++itr) {
393 _dbProperty* p = (_dbProperty*) *itr;
394
395 if (p->_name == name_id)
396 return (dbProperty*) p;
397 }
398
399 return NULL;
400 }
401
find(dbObject * object,const char * name,Type type)402 dbProperty* dbProperty::find(dbObject* object, const char* name, Type type)
403 {
404 _dbNameCache* cache = _dbProperty::getNameCache(object);
405
406 uint name_id = cache->findName(name);
407
408 if (name_id == 0)
409 return NULL;
410
411 dbSet<dbProperty> props = getProperties(object);
412
413 dbSet<dbProperty>::iterator itr;
414
415 for (itr = props.begin(); itr != props.end(); ++itr) {
416 _dbProperty* p = (_dbProperty*) *itr;
417
418 if ((p->_name == name_id) && (p->_flags._type == (_PropTypeEnum) type))
419 return (dbProperty*) p;
420 }
421
422 return NULL;
423 }
424
getProperties(dbObject * object)425 dbSet<dbProperty> dbProperty::getProperties(dbObject* object)
426 {
427 dbSet<dbProperty> props(object, _dbProperty::getItr(object));
428 return props;
429 }
430
destroy(dbProperty * prop_)431 void dbProperty::destroy(dbProperty* prop_)
432 {
433 _dbProperty* prop = (_dbProperty*) prop_;
434
435 // unlink property from owner
436 dbTable<_dbProperty>* propTable = _dbProperty::getPropTable(prop);
437 dbObjectTable* ownerTable = prop->getTable()->getObjectTable(
438 (dbObjectType) prop->_flags._owner_type);
439
440 dbId<_dbProperty> propList = ownerTable->getPropList(prop->_owner);
441 dbId<_dbProperty> cur = propList;
442 uint oid = prop->getOID();
443
444 while (cur) {
445 _dbProperty* p = propTable->getPtr(cur);
446
447 if (cur == oid) {
448 if (cur == propList)
449 ownerTable->setPropList(prop->_owner, p->_next);
450 else
451 p->_next = prop->_next;
452
453 break;
454 }
455
456 cur = p->_next;
457 }
458
459 // Remove reference to name
460 _dbNameCache* cache = _dbProperty::getNameCache(prop);
461 cache->removeName(prop->_name);
462
463 // destroy hier. props.
464 dbProperty::destroyProperties(prop);
465 // destroy the prop
466 propTable->destroy(prop);
467 }
468
destroyProperties(dbObject * obj)469 void dbProperty::destroyProperties(dbObject* obj)
470 {
471 _dbObject* object = obj->getImpl();
472 uint oid = object->getOID();
473 dbObjectTable* objTable = object->getTable();
474 dbId<_dbProperty> cur = objTable->getPropList(oid);
475
476 if (!cur)
477 return;
478
479 _dbNameCache* cache = _dbProperty::getNameCache(obj);
480 dbTable<_dbProperty>* propTable = _dbProperty::getPropTable(obj);
481 while (cur) {
482 _dbProperty* p = propTable->getPtr(cur);
483 cache->removeName(p->_name);
484 cur = p->_next;
485 dbProperty::destroyProperties(p);
486 propTable->destroy(p);
487 }
488
489 objTable->setPropList(oid, cur);
490 }
491
destroy(dbSet<dbProperty>::iterator itr)492 dbSet<dbProperty>::iterator dbProperty::destroy(dbSet<dbProperty>::iterator itr)
493 {
494 dbProperty* p = *itr;
495 dbSet<dbProperty>::iterator n = ++itr;
496 dbProperty::destroy(p);
497 return n;
498 }
499
500 /////////////////////////////////////////////
501 // bool property
502 /////////////////////////////////////////////
503
getValue()504 bool dbBoolProperty::getValue()
505 {
506 _dbProperty* prop = (_dbProperty*) this;
507 return prop->_value._bool_val;
508 }
509
setValue(bool value)510 void dbBoolProperty::setValue(bool value)
511 {
512 _dbProperty* prop = (_dbProperty*) this;
513 prop->_value._bool_val = value;
514 }
515
create(dbObject * object,const char * name,bool value)516 dbBoolProperty* dbBoolProperty::create(dbObject* object,
517 const char* name,
518 bool value)
519 {
520 if (find(object, name))
521 return NULL;
522
523 _dbProperty* prop = _dbProperty::createProperty(object, name, DB_BOOL_PROP);
524 prop->_value._bool_val = value;
525 return (dbBoolProperty*) prop;
526 }
527
find(dbObject * object,const char * name)528 dbBoolProperty* dbBoolProperty::find(dbObject* object, const char* name)
529 {
530 return (dbBoolProperty*) dbProperty::find(
531 object, name, dbProperty::BOOL_PROP);
532 }
533
534 /////////////////////////////////////////////
535 // string property
536 /////////////////////////////////////////////
537
getValue()538 std::string dbStringProperty::getValue()
539 {
540 _dbProperty* prop = (_dbProperty*) this;
541 return prop->_value._str_val;
542 }
543
setValue(const char * value)544 void dbStringProperty::setValue(const char* value)
545 {
546 _dbProperty* prop = (_dbProperty*) this;
547 assert(value);
548
549 if (prop->_value._str_val)
550 free((void*) prop->_value._str_val);
551
552 prop->_value._str_val = strdup(value);
553 ZALLOCATED(prop->_value._str_val);
554 }
555
create(dbObject * object,const char * name,const char * value)556 dbStringProperty* dbStringProperty::create(dbObject* object,
557 const char* name,
558 const char* value)
559 {
560 _dbProperty* prop = (_dbProperty*) find(object, name);
561 if (prop) {
562 std::string val = std::string(prop->_value._str_val) + " " + value;
563 free(prop->_value._str_val);
564 prop->_value._str_val = strdup(val.c_str());
565 ZALLOCATED(prop->_value._str_val);
566 return (dbStringProperty*) prop;
567 }
568
569 prop = _dbProperty::createProperty(object, name, DB_STRING_PROP);
570 prop->_value._str_val = strdup(value);
571 ZALLOCATED(prop->_value._str_val);
572 return (dbStringProperty*) prop;
573 }
574
find(dbObject * object,const char * name)575 dbStringProperty* dbStringProperty::find(dbObject* object, const char* name)
576 {
577 return (dbStringProperty*) dbProperty::find(
578 object, name, dbProperty::STRING_PROP);
579 }
580
581 /////////////////////////////////////////////
582 // int property
583 /////////////////////////////////////////////
584
getValue()585 int dbIntProperty::getValue()
586 {
587 _dbProperty* prop = (_dbProperty*) this;
588 return prop->_value._int_val;
589 }
590
setValue(int value)591 void dbIntProperty::setValue(int value)
592 {
593 _dbProperty* prop = (_dbProperty*) this;
594 prop->_value._int_val = value;
595 }
596
create(dbObject * object,const char * name,int value)597 dbIntProperty* dbIntProperty::create(dbObject* object,
598 const char* name,
599 int value)
600 {
601 if (find(object, name))
602 return NULL;
603
604 _dbProperty* prop = _dbProperty::createProperty(object, name, DB_INT_PROP);
605 prop->_value._int_val = value;
606 return (dbIntProperty*) prop;
607 }
608
find(dbObject * object,const char * name)609 dbIntProperty* dbIntProperty::find(dbObject* object, const char* name)
610 {
611 return (dbIntProperty*) dbProperty::find(object, name, dbProperty::INT_PROP);
612 }
613
614 /////////////////////////////////////////////
615 // double property
616 /////////////////////////////////////////////
617
getValue()618 double dbDoubleProperty::getValue()
619 {
620 _dbProperty* prop = (_dbProperty*) this;
621 return prop->_value._double_val;
622 }
623
setValue(double value)624 void dbDoubleProperty::setValue(double value)
625 {
626 _dbProperty* prop = (_dbProperty*) this;
627 prop->_value._double_val = value;
628 }
629
create(dbObject * object,const char * name,double value)630 dbDoubleProperty* dbDoubleProperty::create(dbObject* object,
631 const char* name,
632 double value)
633 {
634 if (find(object, name))
635 return NULL;
636
637 _dbProperty* prop = _dbProperty::createProperty(object, name, DB_DOUBLE_PROP);
638 prop->_value._double_val = value;
639 return (dbDoubleProperty*) prop;
640 }
641
find(dbObject * object,const char * name)642 dbDoubleProperty* dbDoubleProperty::find(dbObject* object, const char* name)
643 {
644 return (dbDoubleProperty*) dbProperty::find(
645 object, name, dbProperty::DOUBLE_PROP);
646 }
647
writePropValue(dbProperty * prop,FILE * out)648 void dbProperty::writePropValue(dbProperty* prop, FILE* out)
649 {
650 switch (prop->getType()) {
651 case dbProperty::STRING_PROP: {
652 dbStringProperty* p = (dbStringProperty*) prop;
653 std::string v = p->getValue();
654 fprintf(out, "\"%s\" ", v.c_str());
655 break;
656 }
657
658 case dbProperty::INT_PROP: {
659 dbIntProperty* p = (dbIntProperty*) prop;
660 int v = p->getValue();
661 fprintf(out, "%d ", v);
662 break;
663 }
664
665 case dbProperty::DOUBLE_PROP: {
666 dbDoubleProperty* p = (dbDoubleProperty*) prop;
667 double v = p->getValue();
668 fprintf(out, "%G ", v);
669 }
670
671 default:
672 break;
673 }
674 }
675
writeProperties(dbObject * object,FILE * out)676 void dbProperty::writeProperties(dbObject* object, FILE* out)
677 {
678 dbSet<dbProperty> props = dbProperty::getProperties(object);
679 dbSet<dbProperty>::iterator itr;
680
681 for (itr = props.begin(); itr != props.end(); ++itr) {
682 dbProperty* prop = *itr;
683 std::string name = prop->getName();
684 fprintf(out, " PROPERTY %s ", name.c_str());
685 writePropValue(prop, out);
686 fprintf(out, ";\n");
687 }
688 }
689
690 /* Sample Code to access dbTechLayer properties
691 void dbProperty::writeProperties( dbTechLayer * object, FILE *out )
692 {
693 dbSet<dbProperty> props = dbProperty::getProperties(object);
694 dbSet<dbProperty>::iterator itr;
695
696 for( itr = props.begin(); itr != props.end(); ++itr )
697 {
698 dbProperty * prop = *itr;
699 std::string name = prop->getName();
700
701 to get value of a string type:
702 dbStringProperty * p = (dbStringProperty *) prop;
703 std::string v = p->getValue();
704 look function dbProperty::writePropValue on how to retrieve int and
705 double values
706 }
707 }
708 */
709
710 } // namespace odb
711