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 "dbBTerm.h"
34 
35 #include "db.h"
36 #include "dbArrayTable.h"
37 #include "dbBPinItr.h"
38 #include "dbBlock.h"
39 #include "dbBlockCallBackObj.h"
40 #include "dbBox.h"
41 #include "dbBoxItr.h"
42 #include "dbChip.h"
43 #include "dbCommon.h"
44 #include "dbDatabase.h"
45 #include "dbDiff.h"
46 #include "dbDiff.hpp"
47 #include "dbITerm.h"
48 #include "dbJournal.h"
49 #include "dbNet.h"
50 #include "dbShape.h"
51 #include "dbTable.h"
52 #include "dbTable.hpp"
53 #include "dbTransform.h"
54 #include "utl/Logger.h"
55 
56 namespace odb {
57 
58 template class dbTable<_dbBTerm>;
59 
_dbBTerm(_dbDatabase *)60 _dbBTerm::_dbBTerm(_dbDatabase*)
61 {
62   _flags._io_type = dbIoType::INPUT;
63   _flags._sig_type = dbSigType::SIGNAL;
64   _flags._orient = 0;
65   _flags._status = 0;
66   _flags._spef = 0;
67   _flags._special = 0;
68   _flags._mark = 0;
69   _flags._spare_bits = 0;
70   _ext_id = 0;
71   _name = 0;
72   _sta_vertex_id = 0;
73 }
74 
_dbBTerm(_dbDatabase *,const _dbBTerm & b)75 _dbBTerm::_dbBTerm(_dbDatabase*, const _dbBTerm& b)
76     : _flags(b._flags),
77       _ext_id(b._ext_id),
78       _name(NULL),
79       _next_entry(b._next_entry),
80       _net(b._net),
81       _next_bterm(b._next_bterm),
82       _prev_bterm(b._prev_bterm),
83       _parent_block(b._parent_block),
84       _parent_iterm(b._parent_iterm),
85       _bpins(b._bpins),
86       _ground_pin(b._ground_pin),
87       _supply_pin(b._supply_pin),
88       _sta_vertex_id(0)
89 {
90   if (b._name) {
91     _name = strdup(b._name);
92     ZALLOCATED(_name);
93   }
94 }
95 
~_dbBTerm()96 _dbBTerm::~_dbBTerm()
97 {
98   if (_name)
99     free((void*) _name);
100 }
101 
operator <(const _dbBTerm & rhs) const102 bool _dbBTerm::operator<(const _dbBTerm& rhs) const
103 {
104   return strcmp(_name, rhs._name) < 0;
105 }
106 
operator ==(const _dbBTerm & rhs) const107 bool _dbBTerm::operator==(const _dbBTerm& rhs) const
108 {
109   if (_flags._io_type != rhs._flags._io_type)
110     return false;
111 
112   if (_flags._sig_type != rhs._flags._sig_type)
113     return false;
114 
115   if (_flags._spef != rhs._flags._spef)
116     return false;
117 
118   if (_flags._special != rhs._flags._special)
119     return false;
120 
121   if (_ext_id != rhs._ext_id)
122     return false;
123 
124   if (_name && rhs._name) {
125     if (strcmp(_name, rhs._name) != 0)
126       return false;
127   } else if (_name || rhs._name)
128     return false;
129 
130   if (_next_entry != rhs._next_entry)
131     return false;
132 
133   if (_net != rhs._net)
134     return false;
135 
136   if (_next_bterm != rhs._next_bterm)
137     return false;
138 
139   if (_prev_bterm != rhs._prev_bterm)
140     return false;
141 
142   if (_parent_block != rhs._parent_block)
143     return false;
144 
145   if (_parent_iterm != rhs._parent_iterm)
146     return false;
147 
148   if (_bpins != rhs._bpins)
149     return false;
150 
151   if (_ground_pin != rhs._ground_pin)
152     return false;
153 
154   if (_supply_pin != rhs._supply_pin)
155     return false;
156 
157   return true;
158 }
159 
differences(dbDiff & diff,const char * field,const _dbBTerm & rhs) const160 void _dbBTerm::differences(dbDiff& diff,
161                            const char* field,
162                            const _dbBTerm& rhs) const
163 {
164   _dbBlock* lhs_blk = (_dbBlock*) getOwner();
165   _dbBlock* rhs_blk = (_dbBlock*) rhs.getOwner();
166 
167   DIFF_BEGIN
168   DIFF_FIELD(_name);
169   DIFF_FIELD(_flags._io_type);
170   DIFF_FIELD(_flags._sig_type);
171   DIFF_FIELD(_flags._spef);
172   DIFF_FIELD(_flags._special);
173   DIFF_FIELD(_ext_id);
174   DIFF_FIELD_NO_DEEP(_next_entry);
175 
176   if (!diff.deepDiff()) {
177     DIFF_FIELD(_net);
178   } else {
179     _dbNet* lhs_net = lhs_blk->_net_tbl->getPtr(_net);
180     _dbNet* rhs_net = rhs_blk->_net_tbl->getPtr(rhs._net);
181 
182     if (strcmp(lhs_net->_name, rhs_net->_name) != 0) {
183       diff.report("< _net %s\n", lhs_net->_name);
184       diff.report("> _net %s\n", rhs_net->_name);
185     }
186   }
187 
188   DIFF_FIELD_NO_DEEP(_next_bterm);
189   DIFF_FIELD_NO_DEEP(_prev_bterm);
190   DIFF_FIELD_NO_DEEP(_parent_block);
191   DIFF_FIELD_NO_DEEP(_parent_iterm);
192   DIFF_FIELD_NO_DEEP(_bpins);
193   DIFF_FIELD_NO_DEEP(_ground_pin);
194   DIFF_FIELD_NO_DEEP(_supply_pin);
195   DIFF_END
196 }
197 
out(dbDiff & diff,char side,const char * field) const198 void _dbBTerm::out(dbDiff& diff, char side, const char* field) const
199 {
200   _dbBlock* blk = (_dbBlock*) getOwner();
201 
202   DIFF_OUT_BEGIN
203   DIFF_OUT_FIELD(_name);
204   DIFF_OUT_FIELD(_flags._io_type);
205   DIFF_OUT_FIELD(_flags._sig_type);
206   DIFF_OUT_FIELD(_flags._spef);
207   DIFF_OUT_FIELD(_flags._special);
208   DIFF_OUT_FIELD(_ext_id);
209   DIFF_OUT_FIELD_NO_DEEP(_next_entry);
210 
211   if (!diff.deepDiff()) {
212     DIFF_OUT_FIELD(_net);
213   } else {
214     _dbNet* net = blk->_net_tbl->getPtr(_net);
215     diff.report("%c _net %s\n", side, net->_name);
216   }
217 
218   DIFF_OUT_FIELD_NO_DEEP(_next_bterm);
219   DIFF_OUT_FIELD_NO_DEEP(_prev_bterm);
220   DIFF_OUT_FIELD_NO_DEEP(_parent_block);
221   DIFF_OUT_FIELD_NO_DEEP(_parent_iterm);
222   DIFF_OUT_FIELD_NO_DEEP(_bpins);
223   DIFF_OUT_FIELD_NO_DEEP(_ground_pin);
224   DIFF_OUT_FIELD_NO_DEEP(_supply_pin);
225   DIFF_END
226 }
227 
operator <<(dbOStream & stream,const _dbBTerm & bterm)228 dbOStream& operator<<(dbOStream& stream, const _dbBTerm& bterm)
229 {
230   uint* bit_field = (uint*) &bterm._flags;
231   stream << *bit_field;
232   stream << bterm._ext_id;
233   stream << bterm._name;
234   stream << bterm._next_entry;
235   stream << bterm._net;
236   stream << bterm._next_bterm;
237   stream << bterm._prev_bterm;
238   stream << bterm._parent_block;
239   stream << bterm._parent_iterm;
240   stream << bterm._bpins;
241   stream << bterm._ground_pin;
242   stream << bterm._supply_pin;
243   return stream;
244 }
245 
operator >>(dbIStream & stream,_dbBTerm & bterm)246 dbIStream& operator>>(dbIStream& stream, _dbBTerm& bterm)
247 {
248   uint* bit_field = (uint*) &bterm._flags;
249   stream >> *bit_field;
250   stream >> bterm._ext_id;
251   stream >> bterm._name;
252   stream >> bterm._next_entry;
253   stream >> bterm._net;
254   stream >> bterm._next_bterm;
255   stream >> bterm._prev_bterm;
256   stream >> bterm._parent_block;
257   stream >> bterm._parent_iterm;
258   stream >> bterm._bpins;
259   stream >> bterm._ground_pin;
260   stream >> bterm._supply_pin;
261 
262   return stream;
263 }
264 
265 ////////////////////////////////////////////////////////////////////
266 //
267 // dbBTerm - Methods
268 //
269 ////////////////////////////////////////////////////////////////////
270 
getName()271 std::string dbBTerm::getName()
272 {
273   _dbBTerm* bterm = (_dbBTerm*) this;
274   return bterm->_name;
275 }
276 
getConstName()277 const char* dbBTerm::getConstName()
278 {
279   _dbBTerm* bterm = (_dbBTerm*) this;
280   return bterm->_name;
281 }
282 
rename(const char * name)283 bool dbBTerm::rename(const char* name)
284 {
285   _dbBTerm* bterm = (_dbBTerm*) this;
286   _dbBlock* block = (_dbBlock*) getBlock();
287 
288   if (block->_bterm_hash.hasMember(name))
289     return false;
290 
291   block->_bterm_hash.remove(bterm);
292   free((void*) bterm->_name);
293   bterm->_name = strdup(name);
294   ZALLOCATED(bterm->_name);
295   block->_bterm_hash.insert(bterm);
296 
297   return true;
298 }
299 
setSigType(dbSigType type)300 void dbBTerm::setSigType(dbSigType type)
301 {
302   _dbBTerm* bterm = (_dbBTerm*) this;
303   _dbBlock* block = (_dbBlock*) getBlock();
304   uint prev_flags = flagsToUInt(bterm);
305 
306   bterm->_flags._sig_type = type.getValue();
307 
308   if (block->_journal) {
309     debugPrint(getImpl()->getLogger(),
310                utl::ODB,
311                "DB_ECO",
312                1,
313                "ECO: setSigType {}",
314                type.getValue());
315     block->_journal->updateField(
316         this, _dbBTerm::FLAGS, prev_flags, flagsToUInt(bterm));
317   }
318 }
319 
getSigType()320 dbSigType dbBTerm::getSigType()
321 {
322   _dbBTerm* bterm = (_dbBTerm*) this;
323   return dbSigType(bterm->_flags._sig_type);
324 }
325 
setIoType(dbIoType type)326 void dbBTerm::setIoType(dbIoType type)
327 {
328   _dbBTerm* bterm = (_dbBTerm*) this;
329   _dbBlock* block = (_dbBlock*) getBlock();
330   uint prev_flags = flagsToUInt(bterm);
331 
332   bterm->_flags._io_type = type.getValue();
333 
334   if (block->_journal) {
335     debugPrint(getImpl()->getLogger(),
336                utl::ODB,
337                "DB_ECO",
338                1,
339                "ECO: setIoType {}",
340                type.getValue());
341     block->_journal->updateField(
342         this, _dbBTerm::FLAGS, prev_flags, flagsToUInt(bterm));
343   }
344 }
345 
getIoType()346 dbIoType dbBTerm::getIoType()
347 {
348   _dbBTerm* bterm = (_dbBTerm*) this;
349   return dbIoType(bterm->_flags._io_type);
350 }
351 
setSpefMark(uint v)352 void dbBTerm::setSpefMark(uint v)
353 {
354   _dbBTerm* bterm = (_dbBTerm*) this;
355   bterm->_flags._spef = v;
356 }
isSetSpefMark()357 bool dbBTerm::isSetSpefMark()
358 {
359   _dbBTerm* bterm = (_dbBTerm*) this;
360   return bterm->_flags._spef > 0 ? true : false;
361 }
isSpecial() const362 bool dbBTerm::isSpecial() const
363 {
364   _dbBTerm* bterm = (_dbBTerm*) this;
365   return bterm->_flags._special > 0 ? true : false;
366 }
setSpecial()367 void dbBTerm::setSpecial()
368 {
369   _dbBTerm* bterm = (_dbBTerm*) this;
370   bterm->_flags._special = 1;
371 }
setMark(uint v)372 void dbBTerm::setMark(uint v)
373 {
374   _dbBTerm* bterm = (_dbBTerm*) this;
375   bterm->_flags._mark = v;
376 }
isSetMark()377 bool dbBTerm::isSetMark()
378 {
379   _dbBTerm* bterm = (_dbBTerm*) this;
380   return bterm->_flags._mark > 0 ? true : false;
381 }
setExtId(uint v)382 void dbBTerm::setExtId(uint v)
383 {
384   _dbBTerm* bterm = (_dbBTerm*) this;
385   bterm->_ext_id = v;
386 }
getExtId()387 uint dbBTerm::getExtId()
388 {
389   _dbBTerm* bterm = (_dbBTerm*) this;
390   return bterm->_ext_id;
391 }
392 
getNet()393 dbNet* dbBTerm::getNet()
394 {
395   _dbBTerm* bterm = (_dbBTerm*) this;
396   if (bterm->_net) {
397     _dbBlock* block = (_dbBlock*) getBlock();
398     _dbNet* net = block->_net_tbl->getPtr(bterm->_net);
399     return (dbNet*) net;
400   } else
401     return nullptr;
402 }
403 
connect(dbNet * net_)404 void dbBTerm::connect(dbNet* net_)
405 {
406   _dbBTerm* bterm = (_dbBTerm*) this;
407   _dbNet* net = (_dbNet*) net_;
408   _dbBlock* block = (_dbBlock*) net->getOwner();
409 
410   if (block->_journal) {
411     debugPrint(block->getImpl()->getLogger(),
412                utl::ODB,
413                "DB_ECO",
414                1,
415                "ECO: connect Bterm {} to net {}",
416                bterm->getId(),
417                net_->getId());
418     block->_journal->beginAction(dbJournal::CONNECT_OBJECT);
419     block->_journal->pushParam(dbBTermObj);
420     block->_journal->pushParam(bterm->getId());
421     block->_journal->pushParam(net_->getId());
422     block->_journal->endAction();
423   }
424 
425   if (bterm->_net)
426     bterm->disconnectNet(bterm, block);
427   bterm->connectNet(net, block);
428 }
429 
disconnect()430 void dbBTerm::disconnect()
431 {
432   _dbBTerm* bterm = (_dbBTerm*) this;
433   if (bterm->_net) {
434     _dbBlock* block = (_dbBlock*) bterm->getOwner();
435 
436     if (block->_journal) {
437       debugPrint(block->getImpl()->getLogger(),
438                  utl::ODB,
439                  "DB_ECO",
440                  1,
441                  "ECO: disconnect Iterm {}",
442                  bterm->getId());
443       block->_journal->beginAction(dbJournal::DISCONNECT_OBJECT);
444       block->_journal->pushParam(dbBTermObj);
445       block->_journal->pushParam(bterm->getId());
446       block->_journal->endAction();
447     }
448 
449     bterm->disconnectNet(bterm, block);
450   }
451 }
452 
getBPins()453 dbSet<dbBPin> dbBTerm::getBPins()
454 {
455   //_dbBTerm * bterm = (_dbBTerm *) this;
456   _dbBlock* block = (_dbBlock*) getBlock();
457   dbSet<dbBPin> bpins(this, block->_bpin_itr);
458   return bpins;
459 }
460 
getITerm()461 dbITerm* dbBTerm::getITerm()
462 {
463   _dbBTerm* bterm = (_dbBTerm*) this;
464   _dbBlock* block = (_dbBlock*) getBlock();
465 
466   if (bterm->_parent_block == 0)
467     return NULL;
468 
469   _dbChip* chip = (_dbChip*) block->getOwner();
470   _dbBlock* parent = chip->_block_tbl->getPtr(bterm->_parent_block);
471   return (dbITerm*) parent->_iterm_tbl->getPtr(bterm->_parent_iterm);
472 }
473 
getBlock()474 dbBlock* dbBTerm::getBlock()
475 {
476   return (dbBlock*) getImpl()->getOwner();
477 }
478 
getBBox()479 Rect dbBTerm::getBBox()
480 {
481   Rect bbox;
482   bbox.mergeInit();
483   for (dbBPin* pin : getBPins()) {
484     bbox.merge(pin->getBBox());
485   }
486   return bbox;
487 }
488 
getFirstPin(dbShape & shape)489 bool dbBTerm::getFirstPin(dbShape& shape)
490 {
491   dbSet<dbBPin> bpins = getBPins();
492   dbSet<dbBPin>::iterator bpin_itr;
493   for (bpin_itr = bpins.begin(); bpin_itr != bpins.end(); ++bpin_itr) {
494     dbBPin* bpin = *bpin_itr;
495 
496     for (dbBox* box : bpin->getBoxes()) {
497       if (bpin->getPlacementStatus() == dbPlacementStatus::UNPLACED
498           || bpin->getPlacementStatus() == dbPlacementStatus::NONE
499           || box == NULL)
500         continue;
501 
502       if (box->isVia())  // This is not possible...
503         continue;
504 
505       Rect r;
506       box->getBox(r);
507       shape.setSegment(box->getTechLayer(), r);
508       return true;
509     }
510   }
511 
512   return false;
513 }
514 
getFirstPinPlacementStatus()515 dbPlacementStatus dbBTerm::getFirstPinPlacementStatus()
516 {
517   dbSet<dbBPin> bpins = getBPins();
518   auto bpin_itr = bpins.begin();
519   if (bpin_itr != bpins.end()) {
520     dbBPin* bpin = *bpin_itr;
521     return bpin->getPlacementStatus();
522   }
523 
524   return dbPlacementStatus::NONE;
525 }
526 
getFirstPinLocation(int & x,int & y)527 bool dbBTerm::getFirstPinLocation(int& x, int& y)
528 {
529   dbSet<dbBPin> bpins = getBPins();
530   dbSet<dbBPin>::iterator bpin_itr;
531   for (bpin_itr = bpins.begin(); bpin_itr != bpins.end(); ++bpin_itr) {
532     dbBPin* bpin = *bpin_itr;
533 
534     dbSet<dbBox> boxes = bpin->getBoxes();
535     dbSet<dbBox>::iterator boxItr;
536 
537     for (boxItr = boxes.begin(); boxItr != boxes.end(); ++boxItr) {
538       dbBox* box = *boxItr;
539       if (bpin->getPlacementStatus() == dbPlacementStatus::UNPLACED
540           || bpin->getPlacementStatus() == dbPlacementStatus::NONE
541           || box == NULL)
542         continue;
543 
544       if (box->isVia())  // This is not possible...
545         continue;
546 
547       Rect r;
548       box->getBox(r);
549       x = r.xMin() + (int) (r.dx() >> 1U);
550       y = r.yMin() + (int) (r.dy() >> 1U);
551       return true;
552     }
553   }
554 
555   x = 0;
556   y = 0;
557   return false;
558 }
559 
getGroundPin()560 dbBTerm* dbBTerm::getGroundPin()
561 {
562   _dbBTerm* bterm = (_dbBTerm*) this;
563   _dbBlock* block = (_dbBlock*) getBlock();
564 
565   if (bterm->_ground_pin == 0)
566     return NULL;
567 
568   _dbBTerm* ground = block->_bterm_tbl->getPtr(bterm->_ground_pin);
569   return (dbBTerm*) ground;
570 }
571 
setGroundPin(dbBTerm * pin)572 void dbBTerm::setGroundPin(dbBTerm* pin)
573 {
574   _dbBTerm* bterm = (_dbBTerm*) this;
575   bterm->_ground_pin = pin->getImpl()->getOID();
576 }
577 
getSupplyPin()578 dbBTerm* dbBTerm::getSupplyPin()
579 {
580   _dbBTerm* bterm = (_dbBTerm*) this;
581   _dbBlock* block = (_dbBlock*) getBlock();
582 
583   if (bterm->_supply_pin == 0)
584     return NULL;
585 
586   _dbBTerm* supply = block->_bterm_tbl->getPtr(bterm->_supply_pin);
587   return (dbBTerm*) supply;
588 }
589 
setSupplyPin(dbBTerm * pin)590 void dbBTerm::setSupplyPin(dbBTerm* pin)
591 {
592   _dbBTerm* bterm = (_dbBTerm*) this;
593   bterm->_supply_pin = pin->getImpl()->getOID();
594 }
595 
create(dbNet * net_,const char * name)596 dbBTerm* dbBTerm::create(dbNet* net_, const char* name)
597 {
598   _dbNet* net = (_dbNet*) net_;
599   _dbBlock* block = (_dbBlock*) net->getOwner();
600 
601   if (block->_bterm_hash.hasMember(name))
602     return NULL;
603 
604   if (block->_journal) {
605     debugPrint(block->getImpl()->getLogger(),
606                utl::ODB,
607                "DB_ECO",
608                1,
609                "ECO: dbBTerm:create");
610     block->_journal->beginAction(dbJournal::CREATE_OBJECT);
611     block->_journal->pushParam(dbBTermObj);
612     block->_journal->pushParam(net->getId());
613     block->_journal->pushParam(name);
614     block->_journal->endAction();
615   }
616 
617   _dbBTerm* bterm = block->_bterm_tbl->create();
618   bterm->_name = strdup(name);
619   ZALLOCATED(bterm->_name);
620   block->_bterm_hash.insert(bterm);
621   for (auto callback : block->_callbacks)
622     callback->inDbBTermCreate((dbBTerm*) bterm);
623   bterm->connectNet(net, block);
624 
625   return (dbBTerm*) bterm;
626 }
627 
connectNet(_dbNet * net,_dbBlock * block)628 void _dbBTerm::connectNet(_dbNet* net, _dbBlock* block)
629 {
630   for (auto callback : block->_callbacks)
631     callback->inDbBTermPreConnect((dbBTerm*) this, (dbNet*) net);
632   _net = net->getOID();
633   if (net->_bterms != 0) {
634     _dbBTerm* tail = block->_bterm_tbl->getPtr(net->_bterms);
635     _next_bterm = net->_bterms;
636     tail->_prev_bterm = getOID();
637   } else
638     _next_bterm = 0;
639   _prev_bterm = 0;
640   net->_bterms = getOID();
641   for (auto callback : block->_callbacks)
642     callback->inDbBTermPostConnect((dbBTerm*) this);
643 }
644 
destroy(dbBTerm * bterm_)645 void dbBTerm::destroy(dbBTerm* bterm_)
646 {
647   _dbBTerm* bterm = (_dbBTerm*) bterm_;
648   _dbBlock* block = (_dbBlock*) bterm->getOwner();
649 
650   // delete bpins
651   dbSet<dbBPin> bpins = bterm_->getBPins();
652   dbSet<dbBPin>::iterator itr;
653 
654   for (itr = bpins.begin(); itr != bpins.end();) {
655     itr = dbBPin::destroy(itr);
656   }
657   if (bterm->_net)
658     bterm->disconnectNet(bterm, block);
659   for (auto callback : block->_callbacks)
660     callback->inDbBTermDestroy(bterm_);
661   // remove from hash-table
662 
663   if (block->_journal) {
664     debugPrint(block->getImpl()->getLogger(),
665                utl::ODB,
666                "DB_ECO",
667                1,
668                "ECO: dbBTerm:destroy");
669     block->_journal->beginAction(dbJournal::DELETE_OBJECT);
670     block->_journal->pushParam(dbBTermObj);
671     block->_journal->pushParam(bterm_->getId());
672     block->_journal->endAction();
673   }
674 
675   block->_bterm_hash.remove(bterm);
676   dbProperty::destroyProperties(bterm);
677   block->_bterm_tbl->destroy(bterm);
678 }
679 
disconnectNet(_dbBTerm * bterm,_dbBlock * block)680 void _dbBTerm::disconnectNet(_dbBTerm* bterm, _dbBlock* block)
681 {
682   // unlink bterm from the net
683   for (auto callback : block->_callbacks)
684     callback->inDbBTermPreDisconnect((dbBTerm*) this);
685   _dbNet* net = block->_net_tbl->getPtr(bterm->_net);
686   uint id = bterm->getOID();
687 
688   if (net->_bterms == id) {
689     net->_bterms = bterm->_next_bterm;
690 
691     if (net->_bterms != 0) {
692       _dbBTerm* t = block->_bterm_tbl->getPtr(net->_bterms);
693       t->_prev_bterm = 0;
694     }
695   } else {
696     if (bterm->_next_bterm != 0) {
697       _dbBTerm* next = block->_bterm_tbl->getPtr(bterm->_next_bterm);
698       next->_prev_bterm = bterm->_prev_bterm;
699     }
700 
701     if (bterm->_prev_bterm != 0) {
702       _dbBTerm* prev = block->_bterm_tbl->getPtr(bterm->_prev_bterm);
703       prev->_next_bterm = bterm->_next_bterm;
704     }
705   }
706   _net = 0;
707   for (auto callback : block->_callbacks)
708     callback->inDbBTermPostDisConnect((dbBTerm*) this, (dbNet*) net);
709 }
710 
destroy(dbSet<dbBTerm>::iterator & itr)711 dbSet<dbBTerm>::iterator dbBTerm::destroy(dbSet<dbBTerm>::iterator& itr)
712 {
713   dbBTerm* bt = *itr;
714   dbSet<dbBTerm>::iterator next = ++itr;
715   destroy(bt);
716   return next;
717 }
718 
getBTerm(dbBlock * block_,uint dbid_)719 dbBTerm* dbBTerm::getBTerm(dbBlock* block_, uint dbid_)
720 {
721   _dbBlock* block = (_dbBlock*) block_;
722   return (dbBTerm*) block->_bterm_tbl->getPtr(dbid_);
723 }
724 
staVertexId()725 uint32_t dbBTerm::staVertexId()
726 {
727   _dbBTerm* iterm = (_dbBTerm*) this;
728   return iterm->_sta_vertex_id;
729 }
730 
staSetVertexId(uint32_t id)731 void dbBTerm::staSetVertexId(uint32_t id)
732 {
733   _dbBTerm* iterm = (_dbBTerm*) this;
734   iterm->_sta_vertex_id = id;
735 }
736 
737 }  // namespace odb
738