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 "dbMTerm.h"
34 
35 #include "db.h"
36 #include "dbDatabase.h"
37 #include "dbLib.h"
38 #include "dbMPinItr.h"
39 #include "dbMaster.h"
40 #include "dbTable.h"
41 #include "dbTable.hpp"
42 #include "dbTargetItr.h"
43 #include "dbTechLayerAntennaRule.h"
44 #include "lefout.h"
45 
46 namespace odb {
47 
48 template class dbTable<_dbMTerm>;
49 
operator ==(const _dbMTerm & rhs) const50 bool _dbMTerm::operator==(const _dbMTerm& rhs) const
51 {
52   if (_flags._io_type != rhs._flags._io_type)
53     return false;
54 
55   if (_flags._sig_type != rhs._flags._sig_type)
56     return false;
57 
58   if (_order_id != rhs._order_id)
59     return false;
60 
61   if (_name && rhs._name) {
62     if (strcmp(_name, rhs._name) != 0)
63       return false;
64   } else if (_name || rhs._name)
65     return false;
66 
67   if (_next_entry != rhs._next_entry)
68     return false;
69 
70   if (_next_mterm != rhs._next_mterm)
71     return false;
72 
73   if (_pins != rhs._pins)
74     return false;
75 
76   if (_targets != rhs._targets)
77     return false;
78 
79   if (_oxide1 != rhs._oxide1)
80     return false;
81 
82   if (_oxide2 != rhs._oxide2)
83     return false;
84 
85   if (_par_met_area != rhs._par_met_area)
86     return false;
87 
88   if (_par_met_sidearea != rhs._par_met_sidearea)
89     return false;
90 
91   if (_par_cut_area != rhs._par_cut_area)
92     return false;
93 
94   if (_diffarea != rhs._diffarea)
95     return false;
96 
97   return true;
98 }
99 
differences(dbDiff & diff,const char * field,const _dbMTerm & rhs) const100 void _dbMTerm::differences(dbDiff& diff,
101                            const char* field,
102                            const _dbMTerm& rhs) const
103 {
104   DIFF_BEGIN
105   DIFF_FIELD(_flags._io_type);
106   DIFF_FIELD(_flags._sig_type);
107   DIFF_FIELD(_order_id);
108   DIFF_FIELD(_name);
109   DIFF_FIELD(_next_entry);
110   DIFF_FIELD(_next_mterm);
111   DIFF_FIELD(_pins);
112   DIFF_FIELD(_targets);
113   DIFF_FIELD(_oxide1);
114   DIFF_FIELD(_oxide2);
115   DIFF_VECTOR_PTR(_par_met_area);
116   DIFF_VECTOR_PTR(_par_met_sidearea);
117   DIFF_VECTOR_PTR(_par_cut_area);
118   DIFF_VECTOR_PTR(_diffarea);
119   DIFF_END
120 }
121 
out(dbDiff & diff,char side,const char * field) const122 void _dbMTerm::out(dbDiff& diff, char side, const char* field) const
123 {
124   DIFF_OUT_BEGIN
125   DIFF_OUT_FIELD(_flags._io_type);
126   DIFF_OUT_FIELD(_flags._sig_type);
127   DIFF_OUT_FIELD(_order_id);
128   DIFF_OUT_FIELD(_name);
129   DIFF_OUT_FIELD(_next_entry);
130   DIFF_OUT_FIELD(_next_mterm);
131   DIFF_OUT_FIELD(_pins);
132   DIFF_OUT_FIELD(_targets);
133   DIFF_OUT_FIELD(_oxide1);
134   DIFF_OUT_FIELD(_oxide2);
135   DIFF_OUT_VECTOR_PTR(_par_met_area);
136   DIFF_OUT_VECTOR_PTR(_par_met_sidearea);
137   DIFF_OUT_VECTOR_PTR(_par_cut_area);
138   DIFF_OUT_VECTOR_PTR(_diffarea);
139   DIFF_END
140 }
141 
142 ////////////////////////////////////////////////////////////////////
143 //
144 // _dbMTerm - Methods
145 //
146 ////////////////////////////////////////////////////////////////////
147 
_dbMTerm(_dbDatabase *,const _dbMTerm & m)148 _dbMTerm::_dbMTerm(_dbDatabase*, const _dbMTerm& m)
149     : _flags(m._flags),
150       _order_id(m._order_id),
151       _name(NULL),
152       _next_entry(m._next_entry),
153       _next_mterm(m._next_mterm),
154       _pins(m._pins),
155       _targets(m._targets),
156       _oxide1(m._oxide1),
157       _oxide2(m._oxide2),
158       _sta_port(m._sta_port)
159 {
160   if (m._name) {
161     _name = strdup(m._name);
162     ZALLOCATED(_name);
163   }
164 
165   dbVector<_dbTechAntennaAreaElement*>::const_iterator itr;
166 
167   for (itr = m._par_met_area.begin(); itr != m._par_met_area.end(); ++itr) {
168     _dbTechAntennaAreaElement* e = new _dbTechAntennaAreaElement(*(*itr));
169     ZALLOCATED(e);
170     _par_met_area.push_back(e);
171   }
172 
173   for (itr = m._par_met_sidearea.begin(); itr != m._par_met_sidearea.end();
174        ++itr) {
175     _dbTechAntennaAreaElement* e = new _dbTechAntennaAreaElement(*(*itr));
176     ZALLOCATED(e);
177     _par_met_sidearea.push_back(e);
178   }
179 
180   for (itr = m._par_cut_area.begin(); itr != m._par_cut_area.end(); ++itr) {
181     _dbTechAntennaAreaElement* e = new _dbTechAntennaAreaElement(*(*itr));
182     ZALLOCATED(e);
183     _par_cut_area.push_back(e);
184   }
185 
186   for (itr = m._diffarea.begin(); itr != m._diffarea.end(); ++itr) {
187     _dbTechAntennaAreaElement* e = new _dbTechAntennaAreaElement(*(*itr));
188     ZALLOCATED(e);
189     _diffarea.push_back(e);
190   }
191 }
192 /*
193 inline _dbMTerm::~_dbMTerm()
194 {
195     if ( _name )
196         free( (void *) _name );
197 
198     dbVector<_dbTechAntennaAreaElement *>::iterator  antitr;
199     for (antitr = _par_met_area.begin(); antitr != _par_met_area.end();
200 antitr++) delete *antitr; _par_met_area.clear();
201 
202     for (antitr = _par_met_sidearea.begin(); antitr != _par_met_sidearea.end();
203 antitr++) delete *antitr; _par_met_sidearea.clear();
204 
205     for (antitr = _par_cut_area.begin(); antitr != _par_cut_area.end();
206 antitr++) delete *antitr; _par_cut_area.clear();
207 
208     for (antitr = _diffarea.begin(); antitr != _diffarea.end(); antitr++)
209       delete *antitr;
210     _diffarea.clear();
211 }
212 */
operator <<(dbOStream & stream,const _dbMTerm & mterm)213 dbOStream& operator<<(dbOStream& stream, const _dbMTerm& mterm)
214 {
215   uint* bit_field = (uint*) &mterm._flags;
216   stream << *bit_field;
217   stream << mterm._order_id;
218   stream << mterm._name;
219   stream << mterm._next_entry;
220   stream << mterm._next_mterm;
221   stream << mterm._pins;
222   stream << mterm._targets;
223   stream << mterm._oxide1;
224   stream << mterm._oxide2;
225   stream << mterm._par_met_area;
226   stream << mterm._par_met_sidearea;
227   stream << mterm._par_cut_area;
228   stream << mterm._diffarea;
229   return stream;
230 }
231 
operator >>(dbIStream & stream,_dbMTerm & mterm)232 dbIStream& operator>>(dbIStream& stream, _dbMTerm& mterm)
233 {
234   uint* bit_field = (uint*) &mterm._flags;
235   stream >> *bit_field;
236   stream >> mterm._order_id;
237   stream >> mterm._name;
238   stream >> mterm._next_entry;
239   stream >> mterm._next_mterm;
240   stream >> mterm._pins;
241   stream >> mterm._targets;
242   stream >> mterm._oxide1;
243   stream >> mterm._oxide2;
244   stream >> mterm._par_met_area;
245   stream >> mterm._par_met_sidearea;
246   stream >> mterm._par_cut_area;
247   stream >> mterm._diffarea;
248   return stream;
249 }
250 
251 ////////////////////////////////////////////////////////////////////
252 //
253 // dbMTerm - Methods
254 //
255 ////////////////////////////////////////////////////////////////////
256 
getName()257 std::string dbMTerm::getName()
258 {
259   _dbMTerm* mterm = (_dbMTerm*) this;
260   return mterm->_name;
261 }
262 
getName(dbInst * inst,char * ttname)263 char* dbMTerm::getName(dbInst* inst, char* ttname)
264 {
265   dbBlock* block = (dbBlock*) inst->getImpl()->getOwner();
266   dbMaster* master = inst->getMaster();
267   return (getName(block, master, ttname));
268 }
269 
getName(dbBlock * block,dbMaster * master,char * ttname)270 char* dbMTerm::getName(dbBlock* block, dbMaster* master, char* ttname)
271 {
272   char* mtname = (char*) getConstName();
273   char blk_left_bus_del, blk_right_bus_del, lib_left_bus_del, lib_right_bus_del;
274   uint ii = 0;
275   block->getBusDelimeters(blk_left_bus_del, blk_right_bus_del);
276   if (blk_left_bus_del == '\0' || blk_right_bus_del == '\0')
277     return mtname;
278   master->getLib()->getBusDelimeters(lib_left_bus_del, lib_right_bus_del);
279 
280   if (lib_left_bus_del != blk_left_bus_del
281       || lib_right_bus_del != blk_right_bus_del) {
282     while (mtname[ii] != '\0') {
283       if (mtname[ii] == lib_left_bus_del)
284         ttname[ii] = blk_left_bus_del;
285       else if (mtname[ii] == lib_right_bus_del)
286         ttname[ii] = blk_right_bus_del;
287       else
288         ttname[ii] = mtname[ii];
289       ii++;
290     }
291     ttname[ii] = '\0';
292     return ttname;
293   }
294   return mtname;
295 }
296 
getConstName()297 const char* dbMTerm::getConstName()
298 {
299   _dbMTerm* mterm = (_dbMTerm*) this;
300   return mterm->_name;
301 }
302 
getSigType()303 dbSigType dbMTerm::getSigType()
304 {
305   _dbMTerm* mterm = (_dbMTerm*) this;
306   return dbSigType(mterm->_flags._sig_type);
307 }
308 
getIoType()309 dbIoType dbMTerm::getIoType()
310 {
311   _dbMTerm* mterm = (_dbMTerm*) this;
312   return dbIoType(mterm->_flags._io_type);
313 }
314 
setMark(uint v)315 void dbMTerm::setMark(uint v)
316 {
317   _dbMTerm* mterm = (_dbMTerm*) this;
318   mterm->_flags._mark = v;
319 }
isSetMark()320 bool dbMTerm::isSetMark()
321 {
322   _dbMTerm* mterm = (_dbMTerm*) this;
323   return mterm->_flags._mark > 0 ? true : false;
324 }
325 
getMaster()326 dbMaster* dbMTerm::getMaster()
327 {
328   return (dbMaster*) getImpl()->getOwner();
329 }
330 
getMPins()331 dbSet<dbMPin> dbMTerm::getMPins()
332 {
333   _dbMTerm* mterm = (_dbMTerm*) this;
334   _dbMaster* master = (_dbMaster*) mterm->getOwner();
335   return dbSet<dbMPin>(mterm, master->_mpin_itr);
336 }
337 
getBBox()338 Rect dbMTerm::getBBox()
339 {
340   Rect bbox;
341   bbox.mergeInit();
342   for (dbMPin* pin : getMPins()) {
343     bbox.merge(pin->getBBox());
344   }
345   return bbox;
346 }
347 
getTargets()348 dbSet<dbTarget> dbMTerm::getTargets()
349 {
350   _dbMTerm* mterm = (_dbMTerm*) this;
351   _dbMaster* master = (_dbMaster*) mterm->getOwner();
352   return dbSet<dbTarget>(mterm, master->_target_itr);
353 }
354 
staPort()355 void* dbMTerm::staPort()
356 {
357   _dbMTerm* mterm = (_dbMTerm*) this;
358   return mterm->_sta_port;
359 }
360 
staSetPort(void * port)361 void dbMTerm::staSetPort(void* port)
362 {
363   _dbMTerm* mterm = (_dbMTerm*) this;
364   mterm->_sta_port = port;
365 }
366 
getIndex()367 int dbMTerm::getIndex()
368 {
369   _dbMTerm* mterm = (_dbMTerm*) this;
370   return mterm->_order_id;
371 }
372 
373 //
374 // Add entries for antenna info elements that are not model specific
375 //
addPartialMetalAreaEntry(double inval,dbTechLayer * refly)376 void dbMTerm::addPartialMetalAreaEntry(double inval, dbTechLayer* refly)
377 {
378   _dbMTerm* mterm = (_dbMTerm*) this;
379   _dbTechAntennaAreaElement::create(mterm->_par_met_area, inval, refly);
380 }
381 
addPartialMetalSideAreaEntry(double inval,dbTechLayer * refly)382 void dbMTerm::addPartialMetalSideAreaEntry(double inval, dbTechLayer* refly)
383 {
384   _dbMTerm* mterm = (_dbMTerm*) this;
385   _dbTechAntennaAreaElement::create(mterm->_par_met_sidearea, inval, refly);
386 }
387 
addPartialCutAreaEntry(double inval,dbTechLayer * refly)388 void dbMTerm::addPartialCutAreaEntry(double inval, dbTechLayer* refly)
389 {
390   _dbMTerm* mterm = (_dbMTerm*) this;
391   _dbTechAntennaAreaElement::create(mterm->_par_cut_area, inval, refly);
392 }
393 
addDiffAreaEntry(double inval,dbTechLayer * refly)394 void dbMTerm::addDiffAreaEntry(double inval, dbTechLayer* refly)
395 {
396   _dbMTerm* mterm = (_dbMTerm*) this;
397   _dbTechAntennaAreaElement::create(mterm->_diffarea, inval, refly);
398 }
399 
createDefaultAntennaModel()400 dbTechAntennaPinModel* dbMTerm::createDefaultAntennaModel()
401 {
402   _dbMTerm* mterm = (_dbMTerm*) this;
403   _dbTechAntennaPinModel* m
404       = (_dbTechAntennaPinModel*) getDefaultAntennaModel();
405 
406   // Reinitialize the object to its default state...
407   if (m != NULL) {
408     m->~_dbTechAntennaPinModel();
409     new (m) _dbTechAntennaPinModel(mterm->getDatabase());
410     m->_mterm = getImpl()->getOID();
411   } else {
412     _dbMaster* master = (_dbMaster*) mterm->getOwner();
413     m = master->_antenna_pin_model_tbl->create();
414     mterm->_oxide1 = m->getOID();
415     m->_mterm = getImpl()->getOID();
416   }
417 
418   return (dbTechAntennaPinModel*) m;
419 }
420 
createOxide2AntennaModel()421 dbTechAntennaPinModel* dbMTerm::createOxide2AntennaModel()
422 {
423   _dbMTerm* mterm = (_dbMTerm*) this;
424   _dbTechAntennaPinModel* m = (_dbTechAntennaPinModel*) getOxide2AntennaModel();
425 
426   // Reinitialize the object to its default state...
427   if (m != NULL) {
428     m->~_dbTechAntennaPinModel();
429     new (m) _dbTechAntennaPinModel(mterm->getDatabase());
430     m->_mterm = getImpl()->getOID();
431   } else {
432     _dbMaster* master = (_dbMaster*) mterm->getOwner();
433     m = master->_antenna_pin_model_tbl->create();
434     mterm->_oxide2 = m->getOID();
435     m->_mterm = getImpl()->getOID();
436   }
437 
438   return (dbTechAntennaPinModel*) m;
439 }
440 
hasDefaultAntennaModel() const441 bool dbMTerm::hasDefaultAntennaModel() const
442 {
443   _dbMTerm* mterm = (_dbMTerm*) this;
444   return (mterm->_oxide1 != 0);
445 }
446 
hasOxide2AntennaModel() const447 bool dbMTerm::hasOxide2AntennaModel() const
448 {
449   _dbMTerm* mterm = (_dbMTerm*) this;
450   return (mterm->_oxide2 != 0);
451 }
452 
getDefaultAntennaModel() const453 dbTechAntennaPinModel* dbMTerm::getDefaultAntennaModel() const
454 {
455   _dbMTerm* mterm = (_dbMTerm*) this;
456 
457   if (mterm->_oxide1 == 0)
458     return NULL;
459 
460   _dbMaster* master = (_dbMaster*) mterm->getOwner();
461   return (dbTechAntennaPinModel*) master->_antenna_pin_model_tbl->getPtr(
462       mterm->_oxide1);
463 }
464 
getOxide2AntennaModel() const465 dbTechAntennaPinModel* dbMTerm::getOxide2AntennaModel() const
466 {
467   _dbMTerm* mterm = (_dbMTerm*) this;
468 
469   if (mterm->_oxide2 == 0)
470     return NULL;
471 
472   _dbMaster* master = (_dbMaster*) mterm->getOwner();
473   return (dbTechAntennaPinModel*) master->_antenna_pin_model_tbl->getPtr(
474       mterm->_oxide2);
475 }
476 
getDiffArea(std::vector<std::pair<double,dbTechLayer * >> & data)477 void dbMTerm::getDiffArea(std::vector<std::pair<double, dbTechLayer*>>& data)
478 {
479   _dbMTerm* mterm = (_dbMTerm*) this;
480   _dbTechAntennaPinModel::getAntennaValues(
481       mterm->getDatabase(), mterm->_diffarea, data);
482 }
483 
writeAntennaLef(lefout & writer) const484 void dbMTerm::writeAntennaLef(lefout& writer) const
485 {
486   _dbMTerm* mterm = (_dbMTerm*) this;
487 
488   dbVector<_dbTechAntennaAreaElement*>::iterator ant_iter;
489 
490   dbMaster* tpmtr = (dbMaster*) mterm->getOwner();
491   dbLib* tplib = (dbLib*) tpmtr->getImpl()->getOwner();
492   dbTech* tech = tplib->getTech();
493 
494   for (ant_iter = mterm->_par_met_area.begin();
495        ant_iter != mterm->_par_met_area.end();
496        ant_iter++)
497     (*ant_iter)->writeLef("ANTENNAPARTIALMETALAREA", tech, writer);
498 
499   for (ant_iter = mterm->_par_met_sidearea.begin();
500        ant_iter != mterm->_par_met_sidearea.end();
501        ant_iter++)
502     (*ant_iter)->writeLef("ANTENNAPARTIALMETALSIDEAREA", tech, writer);
503 
504   for (ant_iter = mterm->_par_cut_area.begin();
505        ant_iter != mterm->_par_cut_area.end();
506        ant_iter++)
507     (*ant_iter)->writeLef("ANTENNAPARTIALCUTAREA", tech, writer);
508 
509   for (ant_iter = mterm->_diffarea.begin(); ant_iter != mterm->_diffarea.end();
510        ant_iter++)
511     (*ant_iter)->writeLef("ANTENNADIFFAREA", tech, writer);
512 
513   if (hasDefaultAntennaModel())
514     getDefaultAntennaModel()->writeLef(tech, writer);
515 
516   if (hasOxide2AntennaModel()) {
517     fprintf(writer.out(), "        ANTENNAMODEL OXIDE2 ;\n");
518     getOxide2AntennaModel()->writeLef(tech, writer);
519   }
520 }
521 
create(dbMaster * master_,const char * name_,dbIoType io_type_,dbSigType sig_type_)522 dbMTerm* dbMTerm::create(dbMaster* master_,
523                          const char* name_,
524                          dbIoType io_type_,
525                          dbSigType sig_type_)
526 {
527   _dbMaster* master = (_dbMaster*) master_;
528 
529   if (master->_flags._frozen || master->_mterm_hash.hasMember(name_))
530     return NULL;
531 
532   _dbMTerm* mterm = master->_mterm_tbl->create();
533   mterm->_name = strdup(name_);
534   ZALLOCATED(mterm->_name);
535   mterm->_flags._io_type = io_type_;
536   mterm->_flags._sig_type = sig_type_;
537   if (sig_type_ == dbSigType::CLOCK)
538     master_->setSequential(1);
539   master->_mterm_hash.insert(mterm);
540   master->_mterm_cnt++;
541   return (dbMTerm*) mterm;
542 }
543 
getMTerm(dbMaster * master_,uint dbid_)544 dbMTerm* dbMTerm::getMTerm(dbMaster* master_, uint dbid_)
545 {
546   _dbMaster* master = (_dbMaster*) master_;
547   return (dbMTerm*) master->_mterm_tbl->getPtr(dbid_);
548 }
549 
550 }  // namespace odb
551