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 "dbITerm.h"
34 
35 #include "db.h"
36 #include "dbArrayTable.h"
37 #include "dbBTerm.h"
38 #include "dbBlock.h"
39 #include "dbBlockCallBackObj.h"
40 #include "dbChip.h"
41 #include "dbCommon.h"
42 #include "dbDatabase.h"
43 #include "dbDiff.hpp"
44 #include "dbHier.h"
45 #include "dbInst.h"
46 #include "dbInstHdr.h"
47 #include "dbJournal.h"
48 #include "dbLib.h"
49 #include "dbMTerm.h"
50 #include "dbMaster.h"
51 #include "dbNet.h"
52 #include "dbShape.h"
53 #include "dbTable.h"
54 #include "dbTable.hpp"
55 #include "utl/Logger.h"
56 
57 namespace odb {
58 
59 template class dbTable<_dbITerm>;
60 
operator ==(const _dbITerm & rhs) const61 bool _dbITerm::operator==(const _dbITerm& rhs) const
62 {
63   if (_flags._mterm_idx != rhs._flags._mterm_idx)
64     return false;
65 
66   if (_flags._spef != rhs._flags._spef)
67     return false;
68 
69   if (_flags._special != rhs._flags._special)
70     return false;
71 
72   if (_flags._connected != rhs._flags._connected)
73     return false;
74 
75   if (_ext_id != rhs._ext_id)
76     return false;
77 
78   if (_net != rhs._net)
79     return false;
80 
81   if (_inst != rhs._inst)
82     return false;
83 
84   if (_next_net_iterm != rhs._next_net_iterm)
85     return false;
86 
87   if (_prev_net_iterm != rhs._prev_net_iterm)
88     return false;
89 
90   return true;
91 }
92 
operator <(const _dbITerm & rhs) const93 bool _dbITerm::operator<(const _dbITerm& rhs) const
94 {
95   _dbBlock* lhs_blk = (_dbBlock*) getOwner();
96   _dbBlock* rhs_blk = (_dbBlock*) rhs.getOwner();
97 
98   _dbInst* lhs_inst = lhs_blk->_inst_tbl->getPtr(_inst);
99   _dbInst* rhs_inst = rhs_blk->_inst_tbl->getPtr(rhs._inst);
100   int r = strcmp(lhs_inst->_name, rhs_inst->_name);
101 
102   if (r < 0)
103     return true;
104 
105   if (r > 0)
106     return false;
107 
108   _dbMTerm* lhs_mterm = getMTerm();
109   _dbMTerm* rhs_mterm = rhs.getMTerm();
110   return strcmp(lhs_mterm->_name, rhs_mterm->_name) < 0;
111 }
112 
differences(dbDiff & diff,const char * field,const _dbITerm & rhs) const113 void _dbITerm::differences(dbDiff& diff,
114                            const char* field,
115                            const _dbITerm& rhs) const
116 {
117   if (!diff.deepDiff()) {
118     DIFF_BEGIN
119     DIFF_FIELD(_net);
120     DIFF_FIELD(_inst);
121     DIFF_FIELD(_flags._mterm_idx);
122     DIFF_FIELD(_flags._spef);
123     DIFF_FIELD(_flags._special);
124     DIFF_FIELD(_flags._connected);
125     DIFF_FIELD(_ext_id);
126     DIFF_FIELD(_next_net_iterm);
127     DIFF_FIELD(_prev_net_iterm);
128     DIFF_END
129   } else {
130     _dbBlock* lhs_blk = (_dbBlock*) getOwner();
131     _dbBlock* rhs_blk = (_dbBlock*) rhs.getOwner();
132     _dbInst* lhs_inst = lhs_blk->_inst_tbl->getPtr(_inst);
133     _dbInst* rhs_inst = rhs_blk->_inst_tbl->getPtr(rhs._inst);
134     _dbMTerm* lhs_mterm = getMTerm();
135     _dbMTerm* rhs_mterm = rhs.getMTerm();
136     ZASSERT(strcmp(lhs_inst->_name, rhs_inst->_name) == 0);
137     ZASSERT(strcmp(lhs_mterm->_name, rhs_mterm->_name) == 0);
138 
139     diff.begin_object("<> %s (_dbITerm)\n", lhs_mterm->_name);
140 
141     if ((_net != 0) && (rhs._net != 0)) {
142       _dbNet* lhs_net = lhs_blk->_net_tbl->getPtr(_net);
143       _dbNet* rhs_net = rhs_blk->_net_tbl->getPtr(rhs._net);
144       diff.diff("_net", lhs_net->_name, rhs_net->_name);
145     } else if (_net != 0) {
146       _dbNet* lhs_net = lhs_blk->_net_tbl->getPtr(_net);
147       diff.out(dbDiff::LEFT, "_net", lhs_net->_name);
148     } else if (rhs._net != 0) {
149       _dbNet* rhs_net = rhs_blk->_net_tbl->getPtr(rhs._net);
150       diff.out(dbDiff::RIGHT, "_net", rhs_net->_name);
151     }
152 
153     DIFF_FIELD(_flags._spef);
154     DIFF_FIELD(_flags._special);
155     DIFF_FIELD(_flags._connected);
156     DIFF_FIELD(_ext_id);
157     diff.end_object();
158   }
159 }
160 
out(dbDiff & diff,char side,const char * field) const161 void _dbITerm::out(dbDiff& diff, char side, const char* field) const
162 {
163   if (!diff.deepDiff()) {
164     DIFF_OUT_BEGIN
165     DIFF_OUT_FIELD(_net);
166     DIFF_OUT_FIELD(_inst);
167     DIFF_OUT_FIELD(_flags._mterm_idx);
168     DIFF_OUT_FIELD(_flags._spef);
169     DIFF_OUT_FIELD(_flags._special);
170     DIFF_OUT_FIELD(_flags._connected);
171     DIFF_OUT_FIELD(_ext_id);
172     DIFF_OUT_FIELD(_next_net_iterm);
173     DIFF_OUT_FIELD(_prev_net_iterm);
174     DIFF_END
175   } else {
176     _dbMTerm* mterm = getMTerm();
177     diff.begin_object("%c %s (_dbITerm)\n", side, mterm->_name);
178     _dbBlock* blk = (_dbBlock*) getOwner();
179 
180     if (_net != 0) {
181       _dbNet* net = blk->_net_tbl->getPtr(_net);
182       diff.out(side, "_net", net->_name);
183     }
184 
185     DIFF_OUT_FIELD(_flags._spef);
186     DIFF_OUT_FIELD(_flags._special);
187     DIFF_OUT_FIELD(_flags._connected);
188     DIFF_OUT_FIELD(_ext_id);
189     diff.end_object();
190   }
191 }
192 
getMTerm() const193 _dbMTerm* _dbITerm::getMTerm() const
194 {
195   _dbBlock* block = (_dbBlock*) getOwner();
196   _dbInst* inst = block->_inst_tbl->getPtr(_inst);
197   _dbInstHdr* inst_hdr = block->_inst_hdr_tbl->getPtr(inst->_inst_hdr);
198   _dbDatabase* db = getDatabase();
199   _dbLib* lib = db->_lib_tbl->getPtr(inst_hdr->_lib);
200   _dbMaster* master = lib->_master_tbl->getPtr(inst_hdr->_master);
201   dbId<_dbMTerm> mterm = inst_hdr->_mterms[_flags._mterm_idx];
202   return master->_mterm_tbl->getPtr(mterm);
203 }
204 
getInst() const205 _dbInst* _dbITerm::getInst() const
206 {
207   _dbBlock* block = (_dbBlock*) getOwner();
208   _dbInst* inst = block->_inst_tbl->getPtr(_inst);
209   return inst;
210 }
211 
212 ////////////////////////////////////////////////////////////////////
213 //
214 // dbITerm - Methods
215 //
216 ////////////////////////////////////////////////////////////////////
217 
getInst()218 dbInst* dbITerm::getInst()
219 {
220   _dbITerm* iterm = (_dbITerm*) this;
221   _dbBlock* block = (_dbBlock*) iterm->getOwner();
222   _dbInst* inst = block->_inst_tbl->getPtr(iterm->_inst);
223   return (dbInst*) inst;
224 }
225 
getNet()226 dbNet* dbITerm::getNet()
227 {
228   _dbITerm* iterm = (_dbITerm*) this;
229   _dbBlock* block = (_dbBlock*) iterm->getOwner();
230 
231   if (iterm->_net == 0)
232     return NULL;
233 
234   _dbNet* net = block->_net_tbl->getPtr(iterm->_net);
235   return (dbNet*) net;
236 }
237 
getMTerm()238 dbMTerm* dbITerm::getMTerm()
239 {
240   _dbITerm* iterm = (_dbITerm*) this;
241   _dbBlock* block = (_dbBlock*) iterm->getOwner();
242   _dbInst* inst = block->_inst_tbl->getPtr(iterm->_inst);
243   _dbInstHdr* inst_hdr = block->_inst_hdr_tbl->getPtr(inst->_inst_hdr);
244   _dbDatabase* db = iterm->getDatabase();
245   _dbLib* lib = db->_lib_tbl->getPtr(inst_hdr->_lib);
246   _dbMaster* master = lib->_master_tbl->getPtr(inst_hdr->_master);
247   dbId<_dbMTerm> mterm = inst_hdr->_mterms[iterm->_flags._mterm_idx];
248   return (dbMTerm*) master->_mterm_tbl->getPtr(mterm);
249 }
250 
getBTerm()251 dbBTerm* dbITerm::getBTerm()
252 {
253   _dbITerm* iterm = (_dbITerm*) this;
254   _dbBlock* block = (_dbBlock*) iterm->getOwner();
255   _dbInst* inst = block->_inst_tbl->getPtr(iterm->_inst);
256 
257   if (inst->_hierarchy == 0)
258     return NULL;
259 
260   _dbHier* hier = block->_hier_tbl->getPtr(inst->_hierarchy);
261 
262   _dbChip* chip = (_dbChip*) block->getOwner();
263   _dbBlock* child = chip->_block_tbl->getPtr(hier->_child_block);
264   dbId<_dbBTerm> bterm = hier->_child_bterms[iterm->_flags._mterm_idx];
265   return (dbBTerm*) child->_bterm_tbl->getPtr(bterm);
266 }
267 
getBlock()268 dbBlock* dbITerm::getBlock()
269 {
270   return (dbBlock*) getImpl()->getOwner();
271 }
setClocked(bool v)272 void dbITerm::setClocked(bool v)
273 {
274   _dbITerm* iterm = (_dbITerm*) this;
275   iterm->_flags._clocked = v;
276 }
isClocked()277 bool dbITerm::isClocked()
278 {
279   bool masterFlag = getMTerm()->getSigType() == dbSigType::CLOCK ? true : false;
280   _dbITerm* iterm = (_dbITerm*) this;
281   return iterm->_flags._clocked > 0 || masterFlag ? true : false;
282 }
setMark(uint v)283 void dbITerm::setMark(uint v)
284 {
285   _dbITerm* iterm = (_dbITerm*) this;
286   iterm->_flags._mark = v;
287 }
isSetMark()288 bool dbITerm::isSetMark()
289 {
290   _dbITerm* iterm = (_dbITerm*) this;
291   return iterm->_flags._mark > 0 ? true : false;
292 }
293 
isSpecial()294 bool dbITerm::isSpecial()
295 {
296   _dbITerm* iterm = (_dbITerm*) this;
297   return iterm->_flags._special == 1;
298 }
299 
setSpecial()300 void dbITerm::setSpecial()
301 {
302   _dbITerm* iterm = (_dbITerm*) this;
303   //_dbBlock * block = (_dbBlock *) getOwner();
304   // dimitri_fix: need to FIX on FULL_ECO uint prev_flags = flagsToUInt(iterm);
305 #ifdef FULL_ECO
306   uint prev_flags = flagsToUInt(iterm);
307 #endif
308 
309   iterm->_flags._special = 1;
310 
311 #ifdef FULL_ECO
312   if (block->_journal) {
313     debugPrint(getImpl()->getLogger(),
314                utl::ODB,
315                "DB_ECO",
316                1,
317                "ECO: Iterm {}, setSpecial",
318                getId());
319     block->_journal->updateField(
320         this, _dbNet::FLAGS, prev_flags, flagsToUInt(iterm));
321   }
322 #endif
323 }
324 
clearSpecial()325 void dbITerm::clearSpecial()
326 {
327   _dbITerm* iterm = (_dbITerm*) this;
328   //_dbBlock * block = (_dbBlock *) getOwner();
329   // dimitri_fix: need to FIX on FULL_ECO //uint prev_flags =
330   // flagsToUInt(iterm);
331 #ifdef FULL_ECO
332   uint prev_flags = flagsToUInt(iterm);
333 #endif
334 
335   iterm->_flags._special = 0;
336 
337 #ifdef FULL_ECO
338   if (block->_journal) {
339     debugPrint(getImpl()->getLogger(),
340                utl::ODB,
341                "DB_ECO",
342                1,
343                "ECO: Iterm {}, clearSpecial\n",
344                getId());
345     block->_journal->updateField(
346         this, _dbNet::FLAGS, prev_flags, flagsToUInt(iterm));
347   }
348 #endif
349 }
350 
setSpef(uint v)351 void dbITerm::setSpef(uint v)
352 {
353   _dbITerm* iterm = (_dbITerm*) this;
354   //_dbBlock * block = (_dbBlock *) getOwner();
355   // dimitri_fix: need to FIX on FULL_ECO //uint prev_flags =
356   // flagsToUInt(iterm);
357 #ifdef FULL_ECO
358   uint prev_flags = flagsToUInt(iterm);
359 #endif
360 
361   iterm->_flags._spef = v;
362 
363 #ifdef FULL_ECO
364   if (block->_journal) {
365     debugPrint(getImpl()->getLogger(),
366                utl::ODB,
367                "DB_ECO",
368                1,
369                "ECO: Iterm {}, setSpef",
370                getId());
371     block->_journal->updateField(
372         this, _dbNet::FLAGS, prev_flags, flagsToUInt(iterm));
373   }
374 #endif
375 }
376 
isSpef()377 bool dbITerm::isSpef()
378 {
379   _dbITerm* iterm = (_dbITerm*) this;
380   return (iterm->_flags._spef > 0) ? true : false;
381 }
382 
setExtId(uint v)383 void dbITerm::setExtId(uint v)
384 {
385   _dbITerm* iterm = (_dbITerm*) this;
386   iterm->_ext_id = v;
387 }
388 
getExtId()389 uint dbITerm::getExtId()
390 {
391   _dbITerm* iterm = (_dbITerm*) this;
392   return iterm->_ext_id;
393 }
394 
isConnected()395 bool dbITerm::isConnected()
396 {
397   _dbITerm* iterm = (_dbITerm*) this;
398   return iterm->_flags._connected == 1;
399 }
400 
setConnected()401 void dbITerm::setConnected()
402 {
403   _dbITerm* iterm = (_dbITerm*) this;
404   // dimitri_fix: need to FIX on FULL_ECO uint prev_flags = flagsToUInt(iterm);
405 #ifdef FULL_ECO
406   _dbBlock* block = (_dbBlock*) getOwner();
407   uint prev_flags = flagsToUInt(iterm);
408 #endif
409 
410   iterm->_flags._connected = 1;
411 
412 #ifdef FULL_ECO
413   if (block->_journal) {
414     debugPrint(getImpl()->getLogger(),
415                utl::ODB,
416                "DB_ECO",
417                1,
418                "ECO: Iterm {}, setConnected",
419                getId());
420     block->_journal->updateField(
421         this, _dbNet::FLAGS, prev_flags, flagsToUInt(iterm));
422   }
423 #endif
424 }
425 
clearConnected()426 void dbITerm::clearConnected()
427 {
428   _dbITerm* iterm = (_dbITerm*) this;
429   // uint prev_flags = flagsToUInt(iterm);
430 #ifdef FULL_ECO
431   _dbBlock* block = (_dbBlock*) getOwner();
432   uint prev_flags = flagsToUInt(iterm);
433 #endif
434 
435   iterm->_flags._connected = 0;
436 
437 #ifdef FULL_ECO
438   if (block->_journal) {
439     debugPrint(getImpl()->getLogger(),
440                utl::ODB,
441                "DB_ECO",
442                1,
443                "ECO: Iterm {}, clearConnected",
444                getId());
445     block->_journal->updateField(
446         this, _dbNet::FLAGS, prev_flags, flagsToUInt(iterm));
447   }
448 #endif
449 }
450 
connect(dbInst * inst_,dbNet * net_,dbMTerm * mterm_)451 dbITerm* dbITerm::connect(dbInst* inst_, dbNet* net_, dbMTerm* mterm_)
452 {
453   _dbInst* inst = (_dbInst*) inst_;
454   //_dbNet * net = (_dbNet *) net_;
455   _dbMTerm* mterm = (_dbMTerm*) mterm_;
456   _dbBlock* block = (_dbBlock*) inst->getOwner();
457   _dbITerm* iterm = block->_iterm_tbl->getPtr(inst->_iterms[mterm->_order_id]);
458   connect((dbITerm*) iterm, net_);
459   return (dbITerm*) iterm;
460 }
461 
connect(dbITerm * iterm_,dbNet * net_)462 void dbITerm::connect(dbITerm* iterm_, dbNet* net_)
463 {
464   _dbITerm* iterm = (_dbITerm*) iterm_;
465   _dbNet* net = (_dbNet*) net_;
466   _dbBlock* block = (_dbBlock*) iterm->getOwner();
467 
468   // Do Nothing if already connected
469   if (iterm->_net == net->getOID())
470     return;
471   for (auto callback : block->_callbacks)
472     callback->inDbITermPreConnect(iterm_, net_);
473 
474   if (iterm->_net != 0)
475     disconnect(iterm_);
476 
477   if (block->_journal) {
478     debugPrint(iterm->getImpl()->getLogger(),
479                utl::ODB,
480                "DB_ECO",
481                1,
482                "ECO: connect Iterm {} to net {}",
483                iterm_->getId(),
484                net_->getId());
485     block->_journal->beginAction(dbJournal::CONNECT_OBJECT);
486     block->_journal->pushParam(dbITermObj);
487     block->_journal->pushParam(iterm_->getId());
488     block->_journal->pushParam(net_->getId());
489     block->_journal->endAction();
490   }
491 
492   iterm->_net = net->getOID();
493 
494   if (net->_iterms != 0) {
495     _dbITerm* tail = block->_iterm_tbl->getPtr(net->_iterms);
496     iterm->_next_net_iterm = net->_iterms;
497     iterm->_prev_net_iterm = 0;
498     tail->_prev_net_iterm = iterm->getOID();
499   } else {
500     iterm->_next_net_iterm = 0;
501     iterm->_prev_net_iterm = 0;
502   }
503 
504   net->_iterms = iterm->getOID();
505 
506   for (auto callback : block->_callbacks)
507     callback->inDbITermPostConnect(iterm_);
508 }
509 
disconnect(dbITerm * iterm_)510 void dbITerm::disconnect(dbITerm* iterm_)
511 {
512   _dbITerm* iterm = (_dbITerm*) iterm_;
513 
514   if (iterm->_net == 0)
515     return;
516 
517   _dbBlock* block = (_dbBlock*) iterm->getOwner();
518   _dbNet* net = block->_net_tbl->getPtr(iterm->_net);
519   for (auto callback : block->_callbacks)
520     callback->inDbITermPreDisconnect(iterm_);
521   if (block->_journal) {
522     debugPrint(iterm->getImpl()->getLogger(),
523                utl::ODB,
524                "DB_ECO",
525                1,
526                "ECO: disconnect Iterm {}",
527                iterm_->getId());
528     block->_journal->beginAction(dbJournal::DISCONNECT_OBJECT);
529     block->_journal->pushParam(dbITermObj);
530     block->_journal->pushParam(iterm_->getId());
531     block->_journal->endAction();
532   }
533 
534   uint id = iterm->getOID();
535 
536   if (net->_iterms == id) {
537     net->_iterms = iterm->_next_net_iterm;
538 
539     if (net->_iterms != 0) {
540       _dbITerm* t = block->_iterm_tbl->getPtr(net->_iterms);
541       t->_prev_net_iterm = 0;
542     }
543   } else {
544     if (iterm->_next_net_iterm != 0) {
545       _dbITerm* next = block->_iterm_tbl->getPtr(iterm->_next_net_iterm);
546       next->_prev_net_iterm = iterm->_prev_net_iterm;
547     }
548 
549     if (iterm->_prev_net_iterm != 0) {
550       _dbITerm* prev = block->_iterm_tbl->getPtr(iterm->_prev_net_iterm);
551       prev->_next_net_iterm = iterm->_next_net_iterm;
552     }
553   }
554 
555   iterm->_net = 0;
556   for (auto callback : block->_callbacks)
557     callback->inDbITermPostDisconnect(iterm_, (dbNet*) net);
558 }
559 
disconnect(dbSet<dbITerm>::iterator & itr)560 dbSet<dbITerm>::iterator dbITerm::disconnect(dbSet<dbITerm>::iterator& itr)
561 {
562   dbITerm* it = *itr;
563   dbSet<dbITerm>::iterator next = ++itr;
564   disconnect(it);
565   return next;
566 }
567 
getSigType()568 dbSigType dbITerm::getSigType()
569 {
570   _dbMTerm* mterm = (_dbMTerm*) getMTerm();
571   return dbSigType(mterm->_flags._sig_type);
572 }
getIoType()573 dbIoType dbITerm::getIoType()
574 {
575   _dbMTerm* mterm = (_dbMTerm*) getMTerm();
576   return dbIoType(mterm->_flags._io_type);
577 }
isOutputSignal(bool io)578 bool dbITerm::isOutputSignal(bool io)
579 {
580   _dbMTerm* mterm = (_dbMTerm*) getMTerm();
581   dbSigType sType = dbSigType(mterm->_flags._sig_type);
582   dbIoType ioType = dbIoType(mterm->_flags._io_type);
583 
584   if ((sType == dbSigType::GROUND) || (sType == dbSigType::POWER))
585     return false;
586 
587   if (ioType == dbIoType::OUTPUT)
588     return true;
589 
590   if (io && (ioType == dbIoType::INOUT))
591     return true;
592 
593   return false;
594 }
isInputSignal(bool io)595 bool dbITerm::isInputSignal(bool io)
596 {
597   _dbMTerm* mterm = (_dbMTerm*) getMTerm();
598   dbSigType sType = dbSigType(mterm->_flags._sig_type);
599   dbIoType ioType = dbIoType(mterm->_flags._io_type);
600 
601   if ((sType == dbSigType::GROUND) || (sType == dbSigType::POWER))
602     return false;
603 
604   if (ioType == dbIoType::INPUT)
605     return true;
606 
607   if (io && (ioType == dbIoType::INOUT))
608     return true;
609 
610   return false;
611 }
612 
getITerm(dbBlock * block_,uint dbid)613 dbITerm* dbITerm::getITerm(dbBlock* block_, uint dbid)
614 {
615   _dbBlock* block = (_dbBlock*) block_;
616   return (dbITerm*) block->_iterm_tbl->getPtr(dbid);
617 }
618 
getBBox()619 Rect dbITerm::getBBox()
620 {
621   dbMTerm* term = getMTerm();
622   Rect bbox = term->getBBox();
623   odb::dbTransform inst_xfm;
624   getInst()->getTransform(inst_xfm);
625   inst_xfm.apply(bbox);
626   return bbox;
627 }
628 
getAvgXY(int * x,int * y)629 bool dbITerm::getAvgXY(int* x, int* y)
630 {
631   dbMTerm* mterm = getMTerm();
632   int nn = 0;
633   double xx = 0.0;
634   double yy = 0.0;
635   int px;
636   int py;
637   dbInst* inst = getInst();
638   inst->getOrigin(px, py);
639   Point origin = Point(px, py);
640   dbOrientType orient = inst->getOrient();
641   dbTransform transform(orient, origin);
642 
643   dbSet<dbMPin> mpins = mterm->getMPins();
644   dbSet<dbMPin>::iterator mpin_itr;
645   for (mpin_itr = mpins.begin(); mpin_itr != mpins.end(); mpin_itr++) {
646     dbMPin* mpin = *mpin_itr;
647     dbSet<dbBox> boxes = mpin->getGeometry();
648     dbSet<dbBox>::iterator box_itr;
649     for (box_itr = boxes.begin(); box_itr != boxes.end(); box_itr++) {
650       dbBox* box = *box_itr;
651       Rect rect;
652       box->getBox(rect);
653       transform.apply(rect);
654       xx += rect.xMin() + rect.xMax();
655       yy += rect.yMin() + rect.yMax();
656       nn += 2;
657     }
658   }
659   if (!nn) {
660     getImpl()->getLogger()->warn(
661         utl::ODB,
662         34,
663         "Can not find physical location of iterm {}/{}",
664         getInst()->getConstName(),
665         getMTerm()->getConstName());
666     return false;
667   }
668   xx /= nn;
669   yy /= nn;
670   *x = int(xx);
671   *y = int(yy);
672   return true;
673 }
674 
staVertexId()675 uint32_t dbITerm::staVertexId()
676 {
677   _dbITerm* iterm = (_dbITerm*) this;
678   return iterm->_sta_vertex_id;
679 }
680 
staSetVertexId(uint32_t id)681 void dbITerm::staSetVertexId(uint32_t id)
682 {
683   _dbITerm* iterm = (_dbITerm*) this;
684   iterm->_sta_vertex_id = id;
685 }
686 
687 }  // namespace odb
688