// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC 2015-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | B o r a - A n a l o g S l i c i n g T r e e | // | | // | Authors : Eric LAO | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./NodeSets.cpp" | // +-----------------------------------------------------------------+ #include "bora/NodeSets.h" #include "hurricane/Warning.h" #include "hurricane/analog/Device.h" #include "hurricane/analog/TransistorFamily.h" #include "hurricane/analog/LayoutGenerator.h" #include "crlcore/RoutingGauge.h" namespace Bora { using namespace Hurricane; using namespace Analog; NodeSets::NodeSets ( double start, double step, double count ) : _boxSets() , _start ( start ) , _step ( step ) , _count ( count ) { } NodeSets::NodeSets ( const NodeSets* other ) : _boxSets( other->getBoxSets() ) , _start ( other->getStartParameter() ) , _step ( other->getStepParameter() ) , _count ( other->getCountParameter() ) { } NodeSets::~NodeSets () { } NodeSets* NodeSets::create ( Cell* cell , double start , double step , double count , CRL::RoutingGauge* rg ) { NodeSets* nodeset = new NodeSets( start, step, count ); if (not cell) return nodeset; Device* dev = dynamic_cast( cell ); if (dev) { //cdebug_log(536,0) << "createNodeSets for an Analog Device" << endl; TransistorFamily* tf = dynamic_cast(dev); for ( int i = 0; i < count; ++i ) { tf->setNfing( start + i*step ); FormFactorParameter* pff = NULL; if ( (pff = dynamic_cast(tf->getParameter("M"))) != NULL ) pff->setValue( tf->getNfing() ); auto_ptr layoutGenerator ( new LayoutGenerator() ); layoutGenerator->setDevice( dev ); layoutGenerator->drawLayout(); if (rg) { float h2pitch = rg->getHorizontalPitch()*2; float v2pitch = rg->getVerticalPitch ()*2; float h = dev->getAbutmentBox().getHeight(); float w = dev->getAbutmentBox().getWidth(); if (fmod(h,h2pitch) > 1e-06) { cerr << Warning( "NodeSets::create(): The height of device \"%s\" (%s) is not pitched on 2*%s (adjusted)." , getString(dev->getName()).c_str() , DbU::getValueString(dev->getAbutmentBox().getWidth()).c_str() , DbU::getValueString(rg->getHorizontalPitch()*2).c_str() ) << endl; } if (fmod(w,v2pitch) > 1e-06) { cerr << Warning( "NodeSets::create(): The width of device \"%s\" (%s) is not pitched on 2*%s (adjusted)." , getString(dev->getName()).c_str() , DbU::getValueString(dev->getAbutmentBox().getWidth()).c_str() , DbU::getValueString(rg->getVerticalPitch()*2).c_str() ) << endl; } nodeset->push_back( DBoxSet::create( ceil(h/h2pitch)*h2pitch , ceil(w/v2pitch)*v2pitch , start + i*step ) ); } else { nodeset->push_back( DBoxSet::create( dev->getAbutmentBox().getHeight() , dev->getAbutmentBox().getWidth() , start + i*step ) ); } } } else { //cdebug_log(536,0) << "createNodeSets for a Digital Device: " << cell << endl; if (rg) { DbU::Unit h2pitch = rg->getHorizontalPitch()*2; DbU::Unit v2pitch = rg->getVerticalPitch ()*2; DbU::Unit h = cell->getAbutmentBox().getHeight(); DbU::Unit w = cell->getAbutmentBox().getWidth(); if (h % h2pitch) { cerr << Warning( "NodeSets::create(): The height of device \"%s\" (%s) is not pitched on %s*2 (adjusted)." , getString(cell->getName()).c_str() , DbU::getValueString(cell->getAbutmentBox().getHeight()).c_str() , DbU::getValueString(rg->getHorizontalPitch()).c_str() ) << endl; } if (w % v2pitch) { cerr << Warning( "NodeSets::create(): The width of device \"%s\" (%s) is not pitched on %s*2 (adjusted)." , getString(cell->getName()).c_str() , DbU::getValueString(cell->getAbutmentBox().getWidth()).c_str() , DbU::getValueString(rg->getVerticalPitch()).c_str() ) << endl; } nodeset->push_back( DBoxSet::create( ceil(h/h2pitch)*h2pitch , ceil(w/v2pitch)*v2pitch ) ); } else { nodeset->push_back( DBoxSet::create( cell->getAbutmentBox().getHeight() , cell->getAbutmentBox().getWidth() ) ); } } return nodeset; } // NodeSets* NodeSets::create () // { // return new NodeSets(); // } BoxSet* NodeSets::operator[] ( size_t i ) { if (i < _boxSets.size()) return _boxSets[i]; return NULL; } BoxSet* NodeSets::at ( size_t i ) { if (i < _boxSets.size()) return _boxSets[i]; return NULL; } void NodeSets::clear () { if (not _boxSets.empty()) { for ( BoxSet* bs : _boxSets ) bs->destroy(); } _boxSets.clear(); } BoxSet* NodeSets::getPairH ( DbU::Unit height ) const { DbU::Unit w = 0; DbU::Unit hclosest = 0; BoxSet* boxSet = (*_boxSets.begin()); for ( BoxSet* bs : _boxSets ) { if ( (bs->getHeight() > hclosest) and (height >= bs->getHeight()) ) { hclosest = bs->getHeight(); w = bs->getWidth (); boxSet = bs; } } if ( (w == 0) and (hclosest == 0) ) cerr << Warning( "NodeSets::getPairH(): No solution for h=%s has been found." , DbU::getValueString(height).c_str() ) << endl; return boxSet; } BoxSet* NodeSets::getPairHW ( DbU::Unit height, DbU::Unit width ) const { vector::const_iterator it = _boxSets.begin(); DbU::Unit bestH = (*it)->getHeight(); DbU::Unit bestW = (*it)->getWidth(); DbU::Unit currentH = 0; DbU::Unit currentW = 0; BoxSet* boxSet = (*it); while ( it != _boxSets.end() ) { currentH = (*it)->getHeight(); currentW = (*it)->getWidth (); if (currentH <= height) { if (currentH > bestH) { bestH = currentH; bestW = currentW; boxSet = (*it); } else if (currentH == bestH) { if ( (currentW > bestW) and (currentW <= width) ) { bestH = currentH; bestW = currentW; boxSet = (*it); } else if ( (currentW < bestW) and (bestW > width) ) { bestH = currentH; bestW = currentW; boxSet = (*it); } } ++it; } else { it = _boxSets.end(); } } return boxSet; } BoxSet* NodeSets::getPairHW ( unsigned int index ) const { if (index < _boxSets.size()) return _boxSets[index]; return NULL; } size_t NodeSets::findIndex ( DbU::Unit height, DbU::Unit width ) const { for ( size_t i=0 ; i<_boxSets.size() ; ++i ) { if ( (_boxSets[i]->getHeight() == height) and (_boxSets[i]->getWidth () == width ) ) return i; } return NotFound; } BoxSet* NodeSets::find ( DbU::Unit height, DbU::Unit width ) { size_t i = 0; for ( ; i<_boxSets.size() ; ++i ) { if ( (_boxSets[i]->getHeight() == height) and (_boxSets[i]->getWidth () == width ) ) return _boxSets[i]; } return NULL; } BoxSet* NodeSets::find ( BoxSet* boxSet ) { return find( boxSet->getHeight(), boxSet->getWidth() ); } BoxSet* NodeSets::find ( int nfing ) { size_t i = 0; for ( ; i<_boxSets.size() ; ++i ) { if (_boxSets[i]->getNFing() == nfing) return _boxSets[i]; } return NULL; } void NodeSets::print() const { cerr << "Print - NodeSets:" << endl; int index = 0; if (not size()) { cerr << "--- EMPTY ---" << endl; } else { for ( size_t i=0 ; _boxSets.size() ; ++i ) { cerr << "[" << setw(3) << index << "] "; _boxSets[i]->print(); } cerr << endl; } } bool NodeSets::compare ( NodeSets nodeSets2, unsigned int flags ) const { if (_boxSets.size() != nodeSets2.size()) { if (flags & ShowDiff) cerr << "NodeSets::compare() size differs: " << _boxSets.size() << " vs. " << nodeSets2.size() << endl; return false; } bool isSame = true; for ( size_t iset = 0 ; iset<_boxSets.size() ; ++iset ) { if ( (_boxSets[iset]->getHeight() != nodeSets2[iset]->getHeight()) or (_boxSets[iset]->getWidth () != nodeSets2[iset]->getWidth ()) ) { isSame = false; if (flags & ShowDiff) cerr << "NodeSets::compare() Box [" << iset << "] differs " << " (" << DbU::getValueString(_boxSets[iset]->getWidth()) << "," << DbU::getValueString(_boxSets[iset]->getHeight()) << ") vs." << " (" << DbU::getValueString(nodeSets2[iset]->getWidth()) << "," << DbU::getValueString(nodeSets2[iset]->getHeight()) << ")" << endl; } } return isSame; } void NodeSets::push_back ( BoxSet* boxSet ) { if (find(boxSet) == NULL) _boxSets.push_back( boxSet ); else { find( boxSet )->incrementCpt(); boxSet->destroy(); } } void NodeSets::push_back ( vector vect , DbU::Unit height , DbU::Unit width , unsigned int type ) { if (find(height,width) == NULL) { if (type == HorizontalSNode) { _boxSets.push_back( HBoxSet::create( vect, height, width ) ); } else if (type == VerticalSNode) { _boxSets.push_back( VBoxSet::create( vect, height, width ) ); } } else find( height, width )->incrementCpt(); } NodeSets* NodeSets::clone() { NodeSets* nodesets = new NodeSets( _start, _step, _count ); for ( BoxSet* bs : _boxSets ) _boxSets.push_back( bs->clone() ); return nodesets; } } // Bora namespace.