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