// -*- C++ -*- // // This file is part of the Chams Software. // Copyright (c) UPMC 2012-2016, All Rights Reserved // // +-----------------------------------------------------------------+ // | C H A M S | // | H o r u s - S l i c i n g T r e e | // | | // | Authors : Eric LAO | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./hurricaneAMS/layout/SlicingNode.cpp" | // +-----------------------------------------------------------------+ #include "hurricane/Warning.h" #include "hurricane/Breakpoint.h" #include "hurricane/NetExternalComponents.h" #include "hurricaneAMS/analogic/AnalogCellExtension.h" #include "hurricaneAMS/layout/SlicingNode.h" #include "anabatic/AnabaticEngine.h" #include "hurricane/DeepNet.h" #include "hurricane/Property.h" #include "crlcore/AllianceFramework.h" #include "crlcore/RoutingGauge.h" #include "crlcore/RoutingLayerGauge.h" using namespace std; using Hurricane::Warning; using Hurricane::Breakpoint; using Hurricane::Error; using Hurricane::NetRoutingState; using Hurricane::NetRoutingExtension; using Hurricane::NetExternalComponents; using Hurricane::Net; using Hurricane::Cell; using Hurricane::DeepNet; // -----------------------------------------------------------------------------------------------// // Class : BoxSet // -----------------------------------------------------------------------------------------------// BoxSet::BoxSet( DbU::Unit height, DbU::Unit width ): _height( height ) , _width ( width ) , _cpt ( 1 ){} BoxSet::BoxSet( BoxSet* boxSet ) { if ( boxSet != NULL ){ _height = boxSet->getHeight(); _width = boxSet->getWidth(); _cpt = boxSet->getCpt(); } else { _height = 0; _width = 0; _cpt = 1; } } BoxSet::~BoxSet(){} void BoxSet::print() const { cerr << "area: " << setprecision(4) << this->getOccupationArea() ; cerr << "%, \t cpt: " << this->getCpt(); if ((this->getWidth() == 0) && (this->getHeight() == 0)) cerr << ", \t ratio (W/H):inf"; else cerr << ", \t ratio (W/H):" << setprecision(2) << this->getWidth()/this->getHeight(); cerr << ", \t ratio (W*H):" << setprecision(4) << DbU::getPhysical(this->getWidth(),DbU::Micro) * DbU::getPhysical(this->getHeight(),DbU::Micro) << "um²"; if (this->getType() == DeviceSNode){ cerr << ", \t Nfing: " << this->getNFing(); } cerr << ", \t H: " << setprecision(4) << DbU::getPhysical(this->getHeight(),DbU::Micro) << "um" ; cerr << ", W: " << DbU::getPhysical(this->getWidth(),DbU::Micro)<< "um"; cerr << endl; } const vector& BoxSet::getSet() const { cerr << "Error(vector< BoxSet*> getSet () const): DBoxSet and RHVBoxSet do not have vector of BoxSets." << endl; static const vector boxSet = vector (); return boxSet; } int BoxSet::getNFing() const { cerr << "Error(int BoxSet::getNFing() const): Only DBoxSet has fingers." << endl; return 0; } void BoxSet::destroy() { delete(this); } // -----------------------------------------------------------------------------------------------// // Class : HVBoxSet // -----------------------------------------------------------------------------------------------// HVBoxSet::HVBoxSet( vector dimensionSet, DbU::Unit height, DbU::Unit width ): BoxSet ( height, width ) ,_dimensionSet ( dimensionSet ){} HVBoxSet::HVBoxSet( HVBoxSet* boxSet ): BoxSet ( boxSet ) , _dimensionSet ( boxSet->getSet() ){} HVBoxSet::~HVBoxSet(){} double HVBoxSet::getDevicesArea() const { double area = 0; for (vector::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){ area += (*it)->getDevicesArea(); } return area; } // -----------------------------------------------------------------------------------------------// // Class : HBoxSet // -----------------------------------------------------------------------------------------------// int HBoxSet::_count = 0; int HBoxSet::_countAll = 0; HBoxSet::HBoxSet( vector< BoxSet*> dimensionSet, DbU::Unit height, DbU::Unit width ): HVBoxSet( dimensionSet, height, width ) { if ( (_height == 0) && (_width == 0) ){ calculateHeight(); calculateWidth(); } } HBoxSet::HBoxSet( HBoxSet* boxSet ): HVBoxSet( boxSet ){} HBoxSet::~HBoxSet(){} HBoxSet* HBoxSet::create( vector< BoxSet*> dimensionSet, DbU::Unit height, DbU::Unit width ) { _count++; _countAll++; return new HBoxSet( dimensionSet, height, width ); } HBoxSet* HBoxSet::clone() { return HBoxSet::create( getSet(), getHeight(), getWidth() ); } void HBoxSet::calculateHeight() { DbU::Unit currentH = 0; for (vector::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){ currentH += (*it)->getHeight(); } _height = currentH; } void HBoxSet::calculateWidth() { DbU::Unit currentW = 0; for (vector::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){ if (currentW < (*it)->getWidth()){ currentW = (*it)->getWidth(); } } _width = currentW; } void HBoxSet::destroy() { _count--; BoxSet::destroy(); } // -----------------------------------------------------------------------------------------------// // Class : VBoxSet // -----------------------------------------------------------------------------------------------// int VBoxSet::_count = 0; int VBoxSet::_countAll = 0; VBoxSet::VBoxSet( vector dimensionSet, DbU::Unit height, DbU::Unit width ): HVBoxSet( dimensionSet, height, width ) { if ( (_height == 0) && (_width == 0) ){ calculateHeight(); calculateWidth (); } } VBoxSet::VBoxSet( VBoxSet* boxSet ): HVBoxSet( boxSet ){} VBoxSet::~VBoxSet(){} VBoxSet* VBoxSet::create( vector dimensionSet, DbU::Unit height, DbU::Unit width ) { _count++; _countAll++; return new VBoxSet( dimensionSet, height, width ); } VBoxSet* VBoxSet::clone() { return VBoxSet::create( getSet(), getHeight(), getWidth() ); } void VBoxSet::calculateHeight() { DbU::Unit currentH = 0; for (vector::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){ if (currentH < (*it)->getHeight()){ currentH = (*it)->getHeight(); } } _height = currentH; } void VBoxSet::calculateWidth() { DbU::Unit currentW = 0; for (vector::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){ currentW += (*it)->getWidth(); } _width = currentW; } void VBoxSet::destroy() { _count--; BoxSet::destroy(); } // -----------------------------------------------------------------------------------------------// // Class : DBoxSet // -----------------------------------------------------------------------------------------------// int DBoxSet::_count = 0; int DBoxSet::_countAll = 0; DBoxSet::DBoxSet( DbU::Unit height, DbU::Unit width, int nfing ): BoxSet( height, width ), _nfing(nfing){} DBoxSet::DBoxSet( DBoxSet* boxSet ): BoxSet( boxSet ), _nfing(boxSet->getNFing()){} DBoxSet::~DBoxSet(){} DBoxSet* DBoxSet::create( DbU::Unit height, DbU::Unit width, int nfing ) { _count++; _countAll++; return new DBoxSet( height, width, nfing ); } DBoxSet* DBoxSet::clone() { return DBoxSet::create( getHeight(), getWidth(), getNFing() ); } void DBoxSet::destroy() { _count--; BoxSet::destroy(); } // -----------------------------------------------------------------------------------------------// // Class : RHVBoxSet // -----------------------------------------------------------------------------------------------// int RHVBoxSet::_count = 0; int RHVBoxSet::_countAll = 0; RHVBoxSet::RHVBoxSet( DbU::Unit height, DbU::Unit width ): BoxSet( height, width ) { _width = width; _height = height; } RHVBoxSet::RHVBoxSet( RHVBoxSet* boxSet ): BoxSet( boxSet ){} RHVBoxSet::~RHVBoxSet(){} void RHVBoxSet::destroy() { _count--; delete(this); } void RHVBoxSet::print() const { cerr << "area: " << setprecision(4) << this->getOccupationArea() ; cerr << "%, \t cpt: " << this->getCpt(); // if ( (_width == 0)&&(_height == 0) ) cerr << ", \t ratio (W/H):inf"; // else cerr << ", \t ratio (W/H):" << _width/_height; // cerr << ", \t ratio (W*H):" << setprecision(4) << DbU::getPhysical(_width,DbU::Micro) * DbU::getPhysical(_height,DbU::Micro) << "um²"; // if (this->getType() == DeviceSNode){ cerr << ", \t Nfing: " << this->getNFing(); } cerr << ", \t H: " << setprecision(4) << DbU::getPhysical(_height,DbU::Micro) << "um" ; cerr << ", W: " << DbU::getPhysical(_width,DbU::Micro)<< "um"; cerr << endl; } // -----------------------------------------------------------------------------------------------// // Class : RHBoxSet // -----------------------------------------------------------------------------------------------// RHBoxSet::RHBoxSet( DbU::Unit height ): RHVBoxSet( height, 0 ){} RHBoxSet::RHBoxSet( RHBoxSet* boxSet ): RHVBoxSet( boxSet ){} RHBoxSet::~RHBoxSet(){} RHBoxSet* RHBoxSet::create( DbU::Unit height ) { _count++; _countAll++; return new RHBoxSet ( height ); } RHBoxSet* RHBoxSet::clone() { return RHBoxSet::create( getHeight() ); } // -----------------------------------------------------------------------------------------------// // Class : RVBoxSet // -----------------------------------------------------------------------------------------------// RVBoxSet::RVBoxSet( DbU::Unit width ): RHVBoxSet( 0, width ){} RVBoxSet::RVBoxSet( RVBoxSet* boxSet ): RHVBoxSet( boxSet ){} RVBoxSet::~RVBoxSet(){} RVBoxSet* RVBoxSet::create( DbU::Unit width ) { _count++; _countAll++; return new RVBoxSet( width ); } RVBoxSet* RVBoxSet::clone() { return RVBoxSet::create( getWidth() ); } // -----------------------------------------------------------------------------------------------// // Class : NodeSets // -----------------------------------------------------------------------------------------------// NodeSets::NodeSets( double start, double step, double count ) { _nodeSets = std::vector(); _nodeSets.clear(); _start = start; _step = step; _count = count; } NodeSets::NodeSets( const NodeSets* other ) { _nodeSets = other->getNodeSets(); _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); 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 < _nodeSets.size()) return _nodeSets[i]; return NULL; } BoxSet* NodeSets::at ( size_t i ) { if (i < _nodeSets.size()) return _nodeSets[i]; return NULL; } void NodeSets::clear() { if ( _nodeSets.empty() != true ){ for (vector::iterator it = _nodeSets.begin(); it != _nodeSets.end(); it++){ (*it)->destroy(); } _nodeSets.clear(); } } BoxSet* NodeSets::getPairH( DbU::Unit height ) const { DbU::Unit w = 0; DbU::Unit hclosest = 0; BoxSet* boxSet = (*_nodeSets.begin()); for (vector::const_iterator itHW = _nodeSets.begin(); itHW != _nodeSets.end(); itHW++){ if ( ((*itHW)->getHeight() > hclosest) && (height >= (*itHW)->getHeight()) ){ hclosest = (*itHW)->getHeight(); w = (*itHW)->getWidth(); boxSet = (*itHW); } } if ( (w == 0) && (hclosest == 0) ) { cerr << "Error(pair NodeSets::getPairH( DbU::Unit height ) const): No solution for h = " << height << " has been found." << endl; } return boxSet; } BoxSet* NodeSets::getPairHW( DbU::Unit height, DbU::Unit width ) const { vector::const_iterator it = _nodeSets.begin(); DbU::Unit bestH = (*it)->getHeight(); DbU::Unit bestW = (*it)->getWidth(); DbU::Unit currentH = 0; DbU::Unit currentW = 0; BoxSet* boxSet = (*it); while (it != _nodeSets.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) && (currentW <= width) ){ bestH = currentH; bestW = currentW; boxSet = (*it); } else if ( (currentW < bestW) && (bestW > width) ){ bestH = currentH; bestW = currentW; boxSet = (*it); } } it++; } else { it = _nodeSets.end(); } } return boxSet; } BoxSet* NodeSets::getPairHW( unsigned int index ) const { BoxSet* bs = NULL; if ( index < _nodeSets.size() ){ bs = _nodeSets[index]; } return bs; } int NodeSets::findIndex( DbU::Unit height, DbU::Unit width ) const { bool end = false; int indextbd = 0; int index = 0; vector::const_iterator it = _nodeSets.begin(); while(end == false){ if ( ((*it)->getHeight() == height) && ((*it)->getWidth() == width) ){ indextbd = index; end = true; } index++; it++; if (it == _nodeSets.end()){ end = true; } } return indextbd; } vector::iterator NodeSets::find( DbU::Unit height, DbU::Unit width ) { vector::iterator it = _nodeSets.begin(); vector::iterator itFind = _nodeSets.end(); if (_nodeSets.empty() != true){ while(it != _nodeSets.end()){ if ( ((*it)->getHeight() == height) && ((*it)->getWidth() == width) ){ itFind = it; it = _nodeSets.end(); } else { it++; } if ( it == _nodeSets.end() ){ it = _nodeSets.end(); } } } else { it = _nodeSets.end(); } return itFind; } vector::iterator NodeSets::find( BoxSet* boxSet ) { vector::iterator it = _nodeSets.begin(); vector::iterator itFind = _nodeSets.end(); if ( (_nodeSets.empty() != true) && (boxSet != NULL) ){ while(it != _nodeSets.end()){ if ( ((*it)->getHeight() == boxSet->getHeight()) && ((*it)->getWidth() == boxSet->getWidth()) ){ itFind = it; it = _nodeSets.end(); } else { it++; } } } else { it = _nodeSets.end(); } return itFind; } vector::iterator NodeSets::find( int nfing ) { vector::iterator it = _nodeSets.begin(); vector::iterator itFind = _nodeSets.end(); if ( (_nodeSets.empty() != true) ){ while(it != _nodeSets.end()){ if ( (*it)->getNFing() == nfing ){ itFind = it; it = _nodeSets.end(); } else { it++; } } } else { it = _nodeSets.end(); } return itFind; } void NodeSets::print() const { cerr << "Print - NodeSets:" << endl; int index = 0; if ( this->size() == 0){ cerr << "--- EMPTY ---" << endl; } else { for (vector::const_iterator itPrint = _nodeSets.begin(); itPrint != _nodeSets.end(); itPrint++) { cerr << index << ": \t"; (*itPrint)->print(); index++; } cerr << endl; } } bool NodeSets::compare ( NodeSets nodeSets2, unsigned int flags ) const { if (_nodeSets.size() != nodeSets2.size()) { if (flags & ShowDiff) cerr << "NodeSets::compare() size differs: " << _nodeSets.size() << " vs. " << nodeSets2.size() << endl; return false; } bool isSame = true; for ( size_t iset = 0 ; iset<_nodeSets.size() ; ++iset ) { if ( (_nodeSets[iset]->getHeight() != nodeSets2[iset]->getHeight()) or (_nodeSets[iset]->getWidth () != nodeSets2[iset]->getWidth ()) ) { isSame = false; if (flags & ShowDiff) cerr << "NodeSets::compare() Box [" << iset << "] differs " << " (" << DbU::getValueString(_nodeSets[iset]->getWidth()) << "," << DbU::getValueString(_nodeSets[iset]->getHeight()) << ") vs." << " (" << DbU::getValueString(nodeSets2[iset]->getWidth()) << "," << DbU::getValueString(nodeSets2[iset]->getHeight()) << ")" << endl; } } return isSame; } void NodeSets::push_back( BoxSet* boxSet ) { if( this->find(boxSet) == _nodeSets.end() ){ _nodeSets.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( this->find(height, width) == _nodeSets.end() ){ if (type == HorizontalSNode){ _nodeSets.push_back(HBoxSet::create(vect, height, width)); } else if (type == VerticalSNode){ _nodeSets.push_back(VBoxSet::create(vect, height, width)); } } else { (*find(height, width))->incrementCpt(); } } NodeSets* NodeSets::clone() { NodeSets* nodesets = new NodeSets( _start, _step, _count ); for (vector::iterator it = _nodeSets.begin(); it != _nodeSets.end(); it++) { nodesets->push_back((*it)->clone()); } return nodesets; } // -----------------------------------------------------------------------------------------------// // Class : SlicingNode // -----------------------------------------------------------------------------------------------// CRL::RoutingGauge* SlicingNode::_rg = NULL; Cell* SlicingNode::_cell = NULL; Katana::KatanaEngine* SlicingNode::_katana = NULL; vector SlicingNode::_railSegments = vector(); SlicingNode::SlicingNode( unsigned int type , NodeSets* nodeSets , unsigned int alignment , BoxSet* boxSet ):_nodeSets(nodeSets) ,_x(0), _y(0) { _flags = 0; _parent = NULL; _master = NULL; _gcell = NULL; _nodeSets = nodeSets; _x = 0; _y = 0; this->setType(type); this->setAlignment(alignment); if ( boxSet != NULL ){ this->setBoxSet(boxSet); this->setPreset(Preset); this->setSet(Set); } } SlicingNode::~SlicingNode(){} bool SlicingNode::isSameSize( BoxSet* boxSet ) const { bool same = false; if ( (_boxSet != NULL)&&(boxSet != NULL) ){ if ((_boxSet->getHeight() == boxSet->getHeight()) && (_boxSet->getWidth() == boxSet->getWidth())){ same = true; } } return same; } bool SlicingNode::isSameSize( DbU::Unit height, DbU::Unit width ) const { bool same = false; if ( _boxSet != NULL ){ if ( (_boxSet->getHeight() == height) && (_boxSet->getWidth() == width) ){ same = true; } } return same; } bool SlicingNode::isEmpty() const { return _nodeSets->empty(); } DbU::Unit SlicingNode::getHeight () const { if (_boxSet != NULL){ return _boxSet->getHeight(); } else { return 0; } } DbU::Unit SlicingNode::getWidth () const { if (_boxSet != NULL){ return _boxSet->getWidth(); } else { return 0; } } DbU::Unit SlicingNode::getRootHeight () const { if (_parent){ SlicingNode* p = _parent; while(p->getParent()){ p = p->getParent(); } return p->getHeight(); } else { return getHeight(); } } DbU::Unit SlicingNode::getRootWidth () const { if (_parent){ SlicingNode* p = _parent; while(p->getParent()){ p = p->getParent(); } return p->getWidth(); } else { return getWidth(); } } DbU::Unit SlicingNode::getRootX () const { if (_parent){ SlicingNode* p = _parent; while(p->getParent()){ p = p->getParent(); } return p->getX(); } else { return getX(); } } DbU::Unit SlicingNode::getRootY () const { if (_parent){ SlicingNode* p = _parent; while(p->getParent()){ p = p->getParent(); } return p->getY(); } else { return getY(); } } SlicingNode* SlicingNode::getRoot() { SlicingNode* parent = this; if (_parent != NULL){ parent = _parent->getRoot(); } return parent; } int SlicingNode::getCpt() { if (_boxSet != NULL){ return _boxSet->getCpt(); } else { return 0; } } double SlicingNode::getRatio() { if (_boxSet != NULL){ return _boxSet->getRatio(); } else { return 0; } } double SlicingNode::getArea() { if (_boxSet != NULL){ return _boxSet->getArea(); } else { return 0; } } DbU::Unit SlicingNode::getVPitch () { if (_rg) return _rg->getVerticalPitch(); cerr << Error( "DbU::Unit getVPitch(): RoutingGauge has not been defined." ) << endl; return 0; } DbU::Unit SlicingNode::getHPitch () { if (_rg) return _rg->getHorizontalPitch(); cerr << Error( "DbU::Unit getHPitch(): RoutingGauge has not been defined." ) << endl; return 0; } void SlicingNode::setBoxSet( BoxSet* boxSet ) { if ( (!this->isPreset()) ){ if (_nodeSets->find(boxSet) != _nodeSets->end()){ this->setSet(Set); _boxSet = boxSet; } else { cerr << "Error(void SlicingNode::setBoxSet( BoxSet* boxSet )): Boxset not found."; } } } void SlicingNode::setBoxSet( DbU::Unit height, DbU::Unit width ) { if (!this->isPreset()){ if (_nodeSets->find(height, width) != _nodeSets->end()){ this->setSet(Set); _boxSet = (*_nodeSets->find(height, width)); } else { cerr << "Error(void SlicingNode::setBoxSet( BoxSet* boxSet )): Boxset not found."; } } } void SlicingNode::setBoxSet( size_t index ) { if (index > (_nodeSets->size()-1)){ cerr << "Error(void SlicingNode::setBoxSet( int index )): Out of bound index." << endl; } else { this->_setBoxSet((*(_nodeSets->begin() + index))); } } void SlicingNode::_setBoxSet( BoxSet* boxSet ) { if (isPreset()) return; setSet( Set ); _boxSet = boxSet; } void SlicingNode::setX ( DbU::Unit x ) { float pitch = _rg->getVerticalPitch(); if (fmod(x,pitch) > 1e-06) { cerr << Warning( "SlicingNode::setX(): On %s, X position %s is not pitched on %s (will be adjusted)." , getString(this).c_str() , DbU::getValueString(x ).c_str() , DbU::getValueString(pitch).c_str() ) << endl; } _x = x; } void SlicingNode::setY ( DbU::Unit y ) { float pitch = _rg->getHorizontalPitch(); if (fmod(y,pitch) > 1e-06) { cerr << Warning( "SlicingNode::setY(): On %s, Y position %s is not pitched on %s (will be adjusted)." , getString(this).c_str() , DbU::getValueString(y ).c_str() , DbU::getValueString(pitch).c_str() ) << endl; } _y = y; } void SlicingNode::clearParentsNodeSets() { if ( _parent != NULL ){ _parent->clearParentsNodeSets(); } if (getMaster() == NULL) _nodeSets->clear(); } void SlicingNode::resetSlicingTree() { // -----------------------------------------------------------------------------------------------// // Notes: Reset a slicing tree means: // - Empty NodeSets of every parent // - Unset every nodes that are not preset // - Unplace every nodes // -----------------------------------------------------------------------------------------------// clearParentsNodeSets(); getRoot()->_resetSlicingTree(); } void SlicingNode::_resetSlicingTree() { _x = 0; _y = 0; setPlaced(false); if (!this->isPreset()){ _boxSet = NULL; setSet(false); } } void SlicingNode::print() const { printParent(); if ( this->isPreset() ){ cerr << "Preset : True" << endl; } else { cerr << "Preset : False " << endl; } if ( this->isSet() ) { cerr << "Set : True" << endl; } else { cerr << "Set : False " << endl; } if ( this->isPlaced() ){ cerr << "Placed : True" << endl; } else { cerr << "Placed : False " << endl; } if ( this->getMaster()){ cerr << "Master : "; this->getMaster()->printLine(); } unsigned int type = getType(); if ( type == HorizontalSNode ){ cerr << "Type : HorizontalSNode"<< endl; } else if ( type == VerticalSNode ){ cerr << "Type : VerticalSNode" << endl; } else if ( type == DeviceSNode ){ cerr << "Type : DeviceSNode" << endl; } else if ( type == RoutingSNode ){ cerr << "Type : RoutingSNode" << endl; } else { cerr << "Type : UnknownType" << endl; } cerr << "Height : " << DbU::getPhysical(getHeight(),DbU::Micro) << endl; cerr << "Width : " << DbU::getPhysical(getWidth(),DbU::Micro) << endl; cerr << "X : " << DbU::getPhysical(_x,DbU::Micro) << endl; cerr << "Y : " << DbU::getPhysical(_y,DbU::Micro) << endl; if (isRoutingEstimated()) cerr << "REstimated : True" << endl; else cerr << "REstimated : False" << endl; //_nodeSets->print(); cerr << "GCell : " << _gcell << endl; if (!((getType() == HorizontalSNode)||(getType() == VerticalSNode))){ cerr << "GCell : " << _gcell << endl; if(_gcell){ cerr << "Edges : " << endl; vector ne = _gcell->getNorthEdges(); vector se = _gcell->getSouthEdges(); vector ee = _gcell->getEastEdges(); vector we = _gcell->getWestEdges(); cerr << "--- North : " << endl; for (vector::const_iterator itn = ne.begin(); itn != ne.end(); itn++){ cerr << (*itn)->getOpposite(_gcell) << endl; } cerr << "--- South : " << endl; for (vector::const_iterator its = se.begin(); its != se.end(); its++){ cerr << (*its)->getOpposite(_gcell) << endl; } cerr << "--- East : " << endl; for (vector::const_iterator ite = ee.begin(); ite != ee.end(); ite++){ cerr << (*ite)->getOpposite(_gcell) << endl; } cerr << "--- West : " << endl; for (vector::const_iterator itw = we.begin(); itw != we.end(); itw++){ cerr << (*itw)->getOpposite(_gcell) << endl; } } } cerr << endl; } void SlicingNode::printLine() const { unsigned int type = getType(); if (_master) { cerr << " [MASTER]: "; _master->printLine(); } if ( type == HorizontalSNode ){ cerr << "Type : HorizontalSNode"; } else if ( type == VerticalSNode ){ cerr << "Type : VerticalSNode" ; } else if ( type == DeviceSNode ){ cerr << "Type : DeviceSNode" ; } else if ( type == RoutingSNode ){ cerr << "Type : RoutingSNode" ; } else { cerr << "Type : UnknownType" ; } cerr << ", X: " << DbU::getPhysical(getX(),DbU::Micro); cerr << ", Y: " << DbU::getPhysical(getY(),DbU::Micro); cerr << ", W: " << setprecision(4) << DbU::getPhysical(getWidth() ,DbU::Micro); cerr << ", H: " << setprecision(4) << DbU::getPhysical(getHeight(),DbU::Micro) << endl; } void SlicingNode::printParent() const { if (_parent != NULL){ unsigned int type = _parent->getType(); if ( type == HorizontalSNode ){ cerr << "Parent : Type: HorizontalSNode" ; } else if ( type == VerticalSNode ){ cerr << "Parent : Type: VerticalSNode" ; } else { cerr << "Parent : Type: UnknownType"; } cerr << ", H: " << setprecision(4) << DbU::getPhysical(_parent->getHeight(),DbU::Micro); cerr << ", W: " << setprecision(4) << DbU::getPhysical(_parent->getWidth(),DbU::Micro); cerr << ", X: " << DbU::getPhysical(_parent->getX(),DbU::Micro); cerr << ", Y: " << DbU::getPhysical(_parent->getY(),DbU::Micro) << endl; } else { cerr << "Parent : IsROOT " << endl; } } string SlicingNode::_getString () const { ostringstream os; os << "<" << _getTypeName(); if (getGCell()) os << " id:" << getGCell()->getId(); os << " " << (void*)this << ">"; return os.str(); } string SlicingNode::_getTypeName () const { return "SlicingNode"; } void SlicingNode::printBoxSet() const { if (_boxSet != NULL){ _boxSet->print(); } } void SlicingNode::place( DbU::Unit x, DbU::Unit y ) { cdebug_log(536,1) << "SlicingNode::place(DbU::Unit x, DbU::Unit y)" << endl; if (isSet()) { _x = x; _y = y; setPlaced( Placed ); DbU::Unit hpitch = _rg->getHorizontalPitch(); DbU::Unit vpitch = _rg->getVerticalPitch(); if (_x % vpitch) cerr << Warning( "SlicingNode::place(): On %s, _x is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(_x).c_str() , DbU::getValueString(vpitch).c_str() ) << endl; if (_y % hpitch) cerr << Warning( "SlicingNode::place(): On %s, _y is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(_y).c_str() , DbU::getValueString(hpitch).c_str() ) << endl; } else cerr << Error( "SlicingNode::place(DbU::Unit x, DbU::Unit y): Device has not been set." ) << endl; cdebug_tabw(536,-1); } void SlicingNode::replace( DbU::Unit x, DbU::Unit y ) { cdebug_log(536,1) << "SlicingNode::replace(DbU::Unit x, DbU::Unit y)" << endl; if (isSet()) { _x = x; _y = y; setPlaced( Placed ); } else cerr << Error( "SlicingNode::replace(DbU::Unit x, DbU::Unit y): Device has not been set." ) << endl; cdebug_tabw(536,-1); } void SlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace ) { cdebug_log(536,1) << "SlicingNode::place(DbU::Unit x, DbU::Unit y)" << endl; SlicingNode::place(x,y); cdebug_tabw(536,-1); } void SlicingNode::setGlobalSize( DbU::Unit height, DbU::Unit width ) { cmess2 << " o Selecting box set (" << DbU::getValueString(height) << "," << DbU::getValueString(width) << ")" << endl; this->setBoxSet( height, width ); } void SlicingNode::setGlobalSize( size_t index ) { cmess2 << " o Selecting box set at index " << index << endl; this->setBoxSet( index ); } void SlicingNode::_setGlobalSize ( BoxSet* boxSet ) { cdebug_log(535,1) << "SlicingNode::_setGlobalSize( BoxSet* boxSet ) " << endl; _setBoxSet( boxSet ); cdebug_log(535,-1); } void SlicingNode::preDestroy() { if ( _parent != NULL ){ _parent->removeNode(this); }/* else { if (_railCell) _railCell->destroy(); }*/ if (this->getMaster() == NULL) _nodeSets->clear(); } void SlicingNode::destroy() { SlicingNode::preDestroy(); delete(this); } void SlicingNode::preRecursiveDestroy() { SlicingNode::preDestroy(); } void SlicingNode::recursiveDestroy() { SlicingNode::preRecursiveDestroy(); delete(this); } list SlicingNode::getLeaves() const { return list(); } bool SlicingNode::checkInitialPlacement( int& cpt ) const { // -----------------------------------------------------------------------------------------------// // Notes:: Initial placement criteria is having at least 2 devices placed at (x, y) = (0, 0) // -----------------------------------------------------------------------------------------------// bool initialPlacement = false; if ( cpt < 2 ){ initialPlacement = true; } return initialPlacement; } void SlicingNode::updateCellAbutmentBox() { Point pmin = Point(getX(), getY()); Point pmax = Point(getX()+getWidth(), getY()+getHeight()); Box box = Box(pmin, pmax); _cell->setAbutmentBox(box); } void SlicingNode::setGCell( Anabatic::GCell* gcell ) { _gcell = gcell; cdebug_log(535,0) << "SlicingNode::setGCell() " << _gcell << endl; } // Error Methods DbU::Unit SlicingNode::getToleranceRatioH() const { cerr << "Error(DbU::Unit SlicingNode::getToleranceH()): Device and Routing do not have tolerance parameters." << endl; return 0; } DbU::Unit SlicingNode::getToleranceRatioW() const { cerr << "Error(DbU::Unit SlicingNode::getToleranceW()): Device and Routing do not have tolerance parameters." << endl; return 0; } void SlicingNode::setToleranceRatioH( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::setToleranceH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::setToleranceRatioW( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::setToleranceW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } DbU::Unit SlicingNode::getToleranceBandH() const { cerr << "Error(DbU::Unit SlicingNode::getToleranceBandH()): Device and Routing do not have tolerance parameters." << endl; return 0; } DbU::Unit SlicingNode::getToleranceBandW() const { cerr << "Error(DbU::Unit SlicingNode::getToleranceBandW()): Device and Routing do not have tolerance parameters." << endl; return 0; } void SlicingNode::setToleranceBandH( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::setToleranceBandH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::setToleranceBandW( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::setToleranceBandW(DbU::Unit tolerance)): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::recursiveSetToleranceRatioH( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::recursiveSetToleranceRatioH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::recursiveSetToleranceRatioW( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::recursiveSetToleranceRatioW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::recursiveSetToleranceBandH( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::recursiveSetToleranceBandH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::recursiveSetToleranceBandW( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::recursiveSetToleranceBandW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::_recursiveSetToleranceRatioH( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::_recursiveSetToleranceRatioH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::_recursiveSetToleranceRatioW( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::_recursiveSetToleranceRatioW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::_recursiveSetToleranceBandH( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::_recursiveSetToleranceBandH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::_recursiveSetToleranceBandW( DbU::Unit tolerance ) { cerr << "Error(void SlicingNode::_recursiveSetToleranceBandW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::setTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw ) { cerr << "Error(void SlicingNode::setTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw ) { cerr << "Error(void SlicingNode::recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )): Device and Routing do not have tolerance parameters." << endl; } void SlicingNode::_recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw ) { cerr << "Error(void SlicingNode::_recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )): Device and Routing do not have tolerance parameters." << endl; } bool SlicingNode::hasEmptyChildrenNodeSets() const { cerr << "Error(bool SlicingNode::hasEmptyChildrenNodeSets()): Device and routing do not have child." << endl; return true; } const vector& SlicingNode::getChildren() const { cerr << "Error(vector SlicingNode::getChildren()): Device and Routing do not have child." << endl; static vector dummyVectorSlicingNode; return dummyVectorSlicingNode; } SlicingNode* SlicingNode::getChild( int index ) const { cerr << "Error(SlicingNode* SlicingNode::getChild(int index)): Device and Routing do not have child." << endl; return NULL; } int SlicingNode::getChildIndex( SlicingNode* node ) const { cerr << "Error(int SlicingNode::getChildIndex( SlicingNode* node )): Device and Routing do not have child." << endl; return 0; } size_t SlicingNode::getNbChild() const { cerr << "Error(int SlicingNode::getNbChild()): Device and Routing do not have child." << endl; return 0; } void SlicingNode::createChild( unsigned int type, unsigned int alignment ) { cerr << "Error(void createChild( SlicingType type, Alignment alignment = UnknownAlignment)): Device and Routing do not have child." << endl; } void SlicingNode::createChild( NodeSets* nodeSets , unsigned int alignment , Instance* instance , BoxSet* boxSet ) { cerr << "Error(void createChild( NodeSets* nodeSets, Alignment alignment, Instance* instance, BoxSet* boxset )): Device and Routing do not have child." << endl; } void SlicingNode::createChild( int childIndex, int copyIndex, unsigned int tr ) { std::cerr << "Error(createChild( int childIndex, int copyIndex, unsigned int tr )): Device and Routing do not have child." << endl; } void SlicingNode::createRouting( DbU::Unit space ) { std::cerr << "Error(void createChild( DbU::Unit space )): Device and Routing do not have child." << endl; } void SlicingNode::insertNode( SlicingNode* node, int index ) { cerr << "Error(void SlicingNode::insertNode( SlicingNode* node, int index )): Device and Routing do not have child." << endl; } void SlicingNode::push_back( SlicingNode* node, bool reset ) { cerr << "Error(void SlicingNode::push_back( SlicingNode* node, bool reset )): Device and Routing do not have child." << endl; } void SlicingNode::push_front( SlicingNode* node ) { cerr << "Error(void SlicingNode::push_front( SlicingNode* node )): Device and Routing do not have child." << endl; } void SlicingNode::removeNode( SlicingNode* node ) { cerr << "Error(void SlicingNode::removeNode( SlicingNode* node )): Device and Routing do not have child." << endl; } void SlicingNode::removeAllNodes() { cerr << "Error(void SlicingNode::removeAllNodes()): Device and Routing do not have child." << endl; } list > SlicingNode::getSymmetries() const { cerr << "Error(list > SlicingNode::getSymmetries() const) : Device and Routing do not have symmetries." << endl; return list >(); } void SlicingNode::setSymmetries( list > sym ) { cerr << "Error(void SlicingNode::setSymmetries( list > sym )) : Device and Routing do not have symmetries." << endl; } bool SlicingNode::isSymmetry( int index, std::pair& symmetry ) { cerr << "Error(bool SlicingNode::isSymmetry( int index, std::pair& symmetry )) : Device and Routing do not have symmetries." << endl; return false; } bool SlicingNode::isSymmetry( int index ) { cerr << "Error(bool SlicingNode::isSymmetry( int index )) : Device and Routing do not have symmetries." << endl; return false; } void SlicingNode::addSymmetry( int childIndex, int copyIndex, bool reset ) { cerr << "Error(void SlicingNode::addSymmetry( int childIndex, int copyIndex, bool reset )) : Device and Routing do not have symmetries." << endl; } void SlicingNode::removeSymmetry( int index ) { cerr << "Error(void SlicingNode::removeSymmetry( int index )) : Device and Routing do not have symmetries." << endl; } void SlicingNode::normalizeSymmetries() { cerr << "Error(void SlicingNode::normalizeSymmetries() const) : Device and Routing do not have symmetries." << endl; } void SlicingNode::printChildren() const { cerr << "Error(void SlicingNode::printChildren() const): Device and Routing do not have child." << endl; } void SlicingNode::printChildrenLine() const { cerr << "Error(void SlicingNode::printChildrenLine() const): Device and Routing do not have child." << endl; } double SlicingNode::getOccupationArea() const { cerr << "Error(double SlicingNode::getOccupationArea() const) : Occupied Area is not relevant for Routing and Devices." << endl; return 100; } void SlicingNode::setNFing( int nfing ) { cerr << "Error(void SlicingNode::setNFing( int nfing )): Only DlicingNode have NFing parameter." << endl; } int SlicingNode::getNFing() const { cerr << "Error(int SlicingNode::getNFing() const): Only DSlicingNode have NFing parameter." << endl; return 0; } double SlicingNode::getStartParameter() const { cerr << "Error(int SlicingNode::getStartParameter() const): Only DSlicingNode have Start parameter." << endl; return 0; } double SlicingNode::getStepParameter() const { cerr << "Error(int SlicingNode::getStepParameter() const): Only DSlicingNode have Step parameter." << endl; return 0; } double SlicingNode::getCountParameter() const { cerr << "Error(int SlicingNode::getCountParameter() const): Only DSlicingNode have Count parameter." << endl; return 0; } Instance* SlicingNode::getInstance() const { cerr << "Error(Instance* getInstance() const): Only DSlicingNode have an Instance." << endl; return NULL; } void SlicingNode::setInstance( Instance* instance ) { cerr << "Error(Instance* setInstance( Instance* instance ) const): Only DSlicingNode have an Instance." << endl; } void SlicingNode::setCell( Cell* cell ) { if (_parent == NULL){ if (checkCellInstances(cell)){ _cell = cell; AnalogCellExtension::setSlicingTree( cell, this ); } } else { cerr << "Error(void SlicingNode::setCell( Cell* cell )): SlicingTree's root only can set the Slicing tree's cell." << endl; } } void SlicingNode::setKatana( Katana::KatanaEngine* katana ) { _katana = katana; } bool SlicingNode::checkCellInstances( Cell* cell ) { return true; } SlicingNode* SlicingNode::findInstance( Instance* instance ) { return NULL; } SlicingNode* SlicingNode::findSlicingNode( Anabatic::GCell* gcell ) { return NULL; } void SlicingNode::createSlicingRouting() { cerr << "Error(void SlicingNode::createSlicingRouting()): Used for HVSlicingNode only." << endl; } void SlicingNode::resetSlicingRouting() { cerr << "Error(void SlicingNode::resetSlicingRouting()): Used for HVSlicingNode only." << endl; } void SlicingNode::destroySlicingRouting() { cerr << "Error(void SlicingNode::destroySlicingRouting()): Used for HVSlicingNode only." << endl; } int SlicingNode::getRoutingIndex ( SlicingNode* node ) const { cerr << "Error(int SlicingNode::getRoutingIndex ( SlicingNode* node ) const ): Routing index is used for Horizontal/Vertical nodes." << endl; return 0; } SlicingNode* SlicingNode::getSlicingRouting ( int index ) const { cerr << "Error(SlicingNode* SlicingNode::getSlicingRouting ( int index ) const): Used for Horizontal/Vertical Slicing node only." << endl; return NULL; } SlicingNode* SlicingNode::findHorizontalParent () const { if (_parent) { SlicingNode* node = _parent; while(node){ if (node->getType() == HorizontalSNode){ break; } else { node = node->getParent(); } } return node; } else { return NULL; } } SlicingNode* SlicingNode::findVerticalParent () const { if (_parent) { SlicingNode* node = _parent; while(node){ if (node->getType() == VerticalSNode){ break; } else { node = node->getParent(); } } return node; } else { return NULL; } } int SlicingNode::getIndexInHorizontalParent() const { if (_parent) { if (this->getParent()->getType() == HorizontalSNode){ int i = 0; vector::const_iterator it = this->getParent()->getChildren().begin(); while (it != this->getParent()->getChildren().end()){ if ( ((*it)->getType() == this->getType() ) && ((*it)->getHeight() == this->getHeight()) && ((*it)->getWidth () == this->getWidth ()) && ((*it)->getX() == this->getX() ) && ((*it)->getY() == this->getY() ) ) { it = this->getParent()->getChildren().end(); } else { i++; it++; } } return i; } else { bool found = false; SlicingNode* node = this->getParent(); while((node->getParent() != NULL) && (found == false)){ if (node->getParent()->getType() == HorizontalSNode){ found = true; } else { node = node->getParent(); } } if (found){ return node->getParent()->getChildIndex(node); } else { return -1; } } } else { return -1; } } int SlicingNode::getIndexInVerticalParent() const { if (_parent) { if (this->getParent()->getType() == VerticalSNode){ int i = 0; vector::const_iterator it = this->getParent()->getChildren().begin(); while (it != this->getParent()->getChildren().end()){ if ( ((*it)->getType() == this->getType() ) && ((*it)->getHeight() == this->getHeight()) && ((*it)->getWidth () == this->getWidth ()) && ((*it)->getX() == this->getX() ) && ((*it)->getY() == this->getY() ) ) { it = this->getParent()->getChildren().end(); } else { i++; it++; } } return i; } else { bool found = false; SlicingNode* node = this->getParent(); while((node->getParent() != NULL) && (found == false)){ if (node->getParent()->getType() == VerticalSNode){ found = true; } else { node = node->getParent(); } } if (found){ return node->getParent()->getChildIndex(node); } else { return -1; } } } else { return -1; } } void SlicingNode::createRoutingPads () { cdebug_log(536,1) << "SlicingNode::createRoutingPads()" << endl; if (not _cell) { cdebug_tabw(536,-1); return; } //_cell->flattenNets( Cell::Flags::StayOnPlugs ); _cell->flattenNets(); #if THIS_IS_DISABLED for ( Net* net : _cell->getNets() ) { cdebug_log(536,0) << "Net: " << net << endl; if ( net->getPlugs().getSize() > 1 ) { cdebug_log(530,1) << "Not a rail supply and has " << net->getPlugs().getSize() << " plugs" << endl; vector plugs; for ( Plug* plug : net->getPlugs() ) { cdebug_log(530,0) << "| " << plug << endl; if (dynamic_cast(plug->getMasterNet()->getCell())){ cdebug_log(530,0) << "| Device: " << plug << endl; plugs.push_back( plug ); } else if (isRailSegments(plug)){ cdebug_log(530,0) << "| PR: " << plug << endl; plugs.push_back( plug ); } else { if (not plug->getNet()->isSupply()) plugs.push_back( plug ); } } for ( Plug* plug : plugs ) { cdebug_log(536,0) << "Building RoutingPad for " << plug << endl; RoutingPad* rp = RoutingPad::create( net, Occurrence(plug) ); cdebug_log(536,0) << "+ " << rp << ", instance: " << plug->getInstance()->getTransformation() << endl; cdebug_log(536,0) << "+ instance ab: " << plug->getInstance()->getMasterCell()->getAbutmentBox() << endl; // Select the Component with the highest layer. Net* masterNet = static_cast( rp->getOccurrence().getEntity() )->getMasterNet(); Horizontal* hbest = NULL; Vertical* vbest = NULL; for ( Component* c : masterNet->getComponents() ) { //cdebug_log(530,0) << "| " << c << endl; Horizontal* h = dynamic_cast(c); Vertical* v = dynamic_cast(c); if (h) { if (not hbest) hbest = h; else { if (h->getLayer()->above(hbest->getLayer())){ hbest = h; } else if (h->getLayer() == hbest->getLayer()){ if ( hbest->getBoundingBox().getWidth() * hbest->getBoundingBox().getHeight() < h->getBoundingBox().getWidth() * h->getBoundingBox().getHeight() ) { hbest = h; } } } } else if (v) { if (not vbest) vbest = v; else { if (v->getLayer()->above(vbest->getLayer())){ vbest = v; } else if (v->getLayer() == vbest->getLayer()){ if ( vbest->getBoundingBox().getWidth() * vbest->getBoundingBox().getHeight() < v->getBoundingBox().getWidth() * v->getBoundingBox().getHeight() ) { vbest = v; } } } } } if (hbest) { cdebug_log(536,0) << "* " << hbest << endl; rp->setExternalComponent(hbest); } else if (vbest) { cdebug_log(536,0) << "* " << vbest << endl; rp->setExternalComponent(vbest); } } RoutingPad* previousRp = NULL; for ( RoutingPad* rp : net->getRoutingPads() ) { if ( previousRp and ( not rp ->getBodyHook()->isAttached() or not previousRp->getBodyHook()->isAttached()) ) { rp->getBodyHook()->attach( previousRp->getBodyHook() ); } previousRp = rp; } cdebug_tabw(530,-1); } } #endif cdebug_tabw(536,-1); } void SlicingNode::clearRoutingPads() { vector nets; for ( Net* net : _cell->getNets() ) { DeepNet* n = dynamic_cast(net); if (n) nets.push_back(n); } for ( DeepNet* net : nets ){ net->destroy(); } for ( Net* net : _cell->getNets() ) { vector rps; for ( RoutingPad* rp : net->getRoutingPads() ) rps.push_back( rp ); for ( RoutingPad* rp : rps ) rp->destroy(); } } void SlicingNode::restrictDevices() { if (_gcell){ Anabatic::Vertex* vertex = _gcell->getObserver< Anabatic::Vertex>( Anabatic::GCell::Observable::Vertex); vertex->clearRestriction(); } } void SlicingNode::setVertexRestriction ( Net* net, Katana::KatanaEngine* kanata ){} void SlicingNode::estimateChannelsSize () { setRoutingEstimated (RoutingEstimated); } void SlicingNode::expandRoutingChannel () { setRoutingEstimated (RoutingEstimated); } void SlicingNode::_expandRoutingChannel () { setRoutingEstimated (RoutingEstimated); } void SlicingNode::expandRoutingChannel ( DbU::Unit height, DbU::Unit width ) { setRoutingEstimated (RoutingEstimated); } void SlicingNode::clearGlobalRouting() { vector c = vector(); c.clear(); vector s = vector(); int hcpt = 0; int vcpt = 0; int ccpt = 0; for(Net* net: _cell->getNets()){ for(Component* component: net->getComponents()){ if (SlicingNode::isRailSegments(dynamic_cast (component)) == false){ Hurricane::Horizontal* h = dynamic_cast(component); Hurricane::Vertical* v = dynamic_cast (component); Hurricane::Contact* cc = dynamic_cast (component); if (h) s.push_back(component); if (v) s.push_back(component); if (cc) c.push_back(component); if (h) hcpt++; if (v) vcpt++; if (cc) ccpt++; } } } for (vector::iterator it = s.begin(); it != s.end(); it++){ (*it)->destroy(); } for (vector::iterator it = c.begin(); it != c.end(); it++){ (*it)->destroy(); } this->clearGCells(); } void SlicingNode::clearGCells() { _gcell = NULL; } void SlicingNode::updateGCellPosition() { if (_gcell) { _gcell->setSouthWestCorner( getX(), getY() ); } cdebug_log(535,0) << "SlicingNode::updateGCellPosition(): " << _gcell << endl; } void SlicingNode::updateGContacts() { if (_gcell) { _gcell->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); } cdebug_log(535,0) << "SlicingNode::updateGContacts(): " << _gcell << endl; } /*<<<<<<< HEAD*/ void SlicingNode::updateMatrixGCellPosition() { cerr << "Error(void SlicingNode::updateMatrixGCellPosition()): Only used by DSlicingNode" << endl; } void SlicingNode::updateMatrixGContacts() { cerr << "Error(void SlicingNode::updateMatrixGContacts()): Only used by DSlicingNode" << endl; } /*void SlicingNode::updateMatrixGContactsPosition() { cerr << "Error(void SlicingNode::updateMatrixGContactsPosition()): Only used by DSlicingNode" << endl; } void SlicingNode::updateGContactsPosition() { if (_gcell)_gcell->updateContactsPosition(); } ======= >>>>>>> ad94201dbefd0e6f98b1e28a032a3b2a6d57390d*/ int SlicingNode::getNbDevices() { return 1; } bool SlicingNode::containAxis( DbU::Unit axis, unsigned int symmetryType ) { if (symmetryType == HSymmetry){ return ( (axis > getX()) && (axis < getX()+getWidth())); } else if (symmetryType == VSymmetry){ return ( (axis > getY()) && (axis < getY()+getHeight())); } else return false; } bool SlicingNode::checkSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) const { cerr << "Error(bool checkSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) const): Only used by HVSlicingNode" << endl; return false; } void SlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) { cerr << "Error(void addSymmetryNet ( unsigned int type, Net* net1, Net* net2 )): Only used by HVSlicingNode" << endl; } void SlicingNode::updateNetConstraints () { cerr << "Error(void SlicingNode::updateNetConstraints ()): Only used by HVSlicingNode" << endl; } void SlicingNode::updateSymNetAxis() { cerr << "Error(void SlicingNode::updateSymNetAxis ()): Only used by HVSlicingNode" << endl; } void SlicingNode::setRoutingGauge ( CRL::RoutingGauge* rg ) { _rg = rg; } void SlicingNode::addRailSegments( Hurricane::Segment* s ) { _railSegments.push_back(s); } bool SlicingNode::isRailSegments ( Hurricane::Segment* s ) { bool is = false; for (Segment* seg : _railSegments){ if ( s == seg ) { is = true; break; } } return is; } bool SlicingNode::isRailSegments ( Hurricane::Plug* p ) { Instance* i = p->getInstance(); Net* net = NULL; int t = 0; for (Net* n : i->getMasterCell()->getNets()) { net = n; t++; } if (t != 1) return false; Component* component = NULL; t = 0; for (Component* c : net->getComponents()){ component = c; t++; } if (t != 1) return false; Horizontal* h = dynamic_cast(component); Vertical* v = dynamic_cast (component); if (h) return isRailSegments(h); else if (v) return isRailSegments(v); else return false; } void SlicingNode::flattenDigitalNets () { cerr << "Error(void SlicingNode::flattenDigitalNets ()): Only used by HVSlicingNode" << endl; } void SlicingNode::updateWireOccupation ( Anabatic::VertexSet ) { cerr << "Error(void SlicingNode::updateWireOccupation ( Anabatic::VertexSet )): Only used by HVSlicingNode" << endl; } void SlicingNode::addWireOccupation ( DbU::Unit min, DbU::Unit max ) { cerr << "Error(void SlicingNode::addWireOccupation ( DbU::Unit min, DbU::Unit max )): Only used by HVSlicingNode and RHVSlicingNode" << endl; } void SlicingNode::resetWireOccupation () { cerr << "Error(void SlicingNode::resetWireOccupation()): Only used by HVSlicingNode and RHVSlicingNode" << endl; } int SlicingNode::getMaxWireOccupation () { cerr << "Error(int SlicingNode::getMaxWireOccupation()): Only used by HVSlicingNode and RHVSlicingNode" << endl; return 0; } // -----------------------------------------------------------------------------------------------// // Class : HVSlicingNode // -----------------------------------------------------------------------------------------------// HVSlicingNode::HVSlicingNode( unsigned int type, unsigned int alignment ): SlicingNode( type, NodeSets::create(), alignment, NULL ) { _toleranceRatioH = 0; _toleranceRatioW = 0; _toleranceBandH = 0; _toleranceBandW = 0; _children = vector(); _symmetries = list >(); _slicingRouting = vector(); _netsymmetries = vector >(); } HVSlicingNode::~HVSlicingNode(){} void HVSlicingNode::setToleranceRatioH ( DbU::Unit tolerance ) { _toleranceRatioH = tolerance; getRoot()->_resetSlicingTree(); } void HVSlicingNode::setToleranceRatioW ( DbU::Unit tolerance ) { _toleranceRatioW = tolerance; getRoot()->_resetSlicingTree(); } void HVSlicingNode::setToleranceBandH ( DbU::Unit tolerance ) { _toleranceBandH = tolerance; resetSlicingTree(); } void HVSlicingNode::setToleranceBandW ( DbU::Unit tolerance ) { _toleranceBandW = tolerance; resetSlicingTree(); } void HVSlicingNode::recursiveSetToleranceRatioH( DbU::Unit tolerance ) { _recursiveSetToleranceRatioH(tolerance); getRoot()->_resetSlicingTree(); } void HVSlicingNode::recursiveSetToleranceRatioW( DbU::Unit tolerance ) { _recursiveSetToleranceRatioW(tolerance); getRoot()->_resetSlicingTree(); } void HVSlicingNode::recursiveSetToleranceBandH( DbU::Unit tolerance ) { resetSlicingTree(); _recursiveSetToleranceBandH(tolerance); } void HVSlicingNode::recursiveSetToleranceBandW( DbU::Unit tolerance ) { resetSlicingTree(); _recursiveSetToleranceBandW(tolerance); } void HVSlicingNode::_recursiveSetToleranceRatioH( DbU::Unit tolerance ) { for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) ) { (*it)->recursiveSetToleranceRatioH(tolerance); } } _toleranceRatioH = tolerance; } void HVSlicingNode::_recursiveSetToleranceRatioW( DbU::Unit tolerance ) { for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) ) { (*it)->recursiveSetToleranceRatioW(tolerance); } } _toleranceRatioW = tolerance; } void HVSlicingNode::_recursiveSetToleranceBandH( DbU::Unit tolerance ) { for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) ) { (*it)->recursiveSetToleranceBandH(tolerance); } } _toleranceBandH = tolerance; } void HVSlicingNode::_recursiveSetToleranceBandW( DbU::Unit tolerance ) { for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) ) { (*it)->recursiveSetToleranceBandW(tolerance); } } _toleranceBandW = tolerance; } void HVSlicingNode::setTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw ) { resetSlicingTree(); _toleranceRatioH = trh; _toleranceRatioW = trw; _toleranceBandH = tbh; _toleranceBandW = tbw; } void HVSlicingNode::recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw ) { resetSlicingTree(); _recursiveSetTolerances( trh, trw, tbh, tbw ); } void HVSlicingNode::_recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw ) { _recursiveSetToleranceRatioH(trh); _recursiveSetToleranceRatioW(trw); _recursiveSetToleranceBandH(tbh); _recursiveSetToleranceBandW(tbw); } bool HVSlicingNode::hasEmptyChildrenNodeSets() const { bool flag = false; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ NodeSets* node = (*it)->getNodeSets(); if ( (node->empty() != true) && (!(*it)->isRouting()) ) { if (node->empty() == true) {flag = true;} } } return flag; } int HVSlicingNode::getChildIndex( SlicingNode* node ) const { int i = 0; vector::const_iterator it = _children.begin(); while (it != _children.end()){ if ( ((*it)->getType() == node->getType() ) && ((*it)->getHeight() == node->getHeight()) && ((*it)->getWidth () == node->getWidth ()) && ((*it)->getX() == node->getX() ) && ((*it)->getY() == node->getY() ) ) { it = _children.end(); } else { i++; it++; } } return i; } void HVSlicingNode::createChild( unsigned int type, unsigned int alignment ) { if (type == HorizontalSNode) { HSlicingNode* hsn = HSlicingNode::create(alignment); hsn->setTolerances( getToleranceRatioH() , getToleranceRatioW() , getToleranceBandH() , getToleranceBandW() ); push_back(hsn); resetSlicingTree(); } else if (type == VerticalSNode) { VSlicingNode* vsn = VSlicingNode::create(alignment); vsn->setTolerances( getToleranceRatioH() , getToleranceRatioW() , getToleranceBandH() , getToleranceBandW() ); push_back(vsn); resetSlicingTree(); } else { cerr << " Error(void HVSlicingNode::createChild(SlicingType type, Alignment alignment)): Unknown type." << endl; } } void HVSlicingNode::createChild( NodeSets* nodeSets , unsigned int alignment , Instance* instance , BoxSet* boxSet ) { DSlicingNode* node = DSlicingNode::create( nodeSets, alignment, instance, boxSet ); node->setParent(this); this->push_back(node); resetSlicingTree(); } void HVSlicingNode::createChild( int childIndex, int copyIndex, unsigned int tr ) { if (childIndex != copyIndex){ SlicingNode* node = this->getChild(childIndex)->clone(tr); this->insertNode( node, copyIndex ); _symmetries.push_back( pair(min(childIndex, copyIndex), max(childIndex, copyIndex)) ); resetSlicingTree(); normalizeSymmetries(); } else { cerr << "Error(void HVSlicingNode::createChild( int childIndex, int copyIndex, unsigned int tr )): Indexes cannot be the same." << endl; } } void HVSlicingNode::insertNode( SlicingNode* node, int index ) { vector::iterator it = _children.begin(); for (int i = 0; i < index; i++){ if (it != _children.end()){ it++; } } _children.insert(it,node); node->setParent(this); resetSlicingTree(); } void HVSlicingNode::push_back( SlicingNode* node, bool reset ) { node->setParent(this); _children.push_back(node); if (reset) { resetSlicingTree(); } } void HVSlicingNode::push_front( SlicingNode* node ) { node->setParent(this); _children.insert(_children.begin(), node); resetSlicingTree(); } void HVSlicingNode::removeNode( SlicingNode* node ) { int index = 0; bool found = false; vector::iterator it = _children.begin(); //(*it)->printLine(); while( it != _children.end() ){ if ((*it) == node) { _children.erase(it); found = true; it = _children.end(); } else { it++; index++; } } if (found == true){ removeSymmetry(index); resetSlicingTree(); node->removeParent(); node->setX(0); node->setY(0); node->setPlaced(false); } /*else { cerr << "Didn't found" << endl; }*/ } bool HVSlicingNode::isSymmetry( int index, pair& symmetry ) { bool symmetryFound = false; if (_symmetries.empty() != true){ for (list >::const_iterator it2 = _symmetries.begin(); it2 != _symmetries.end(); it2++){ if ((*it2).second == index){ symmetry = pair((*it2).first,(*it2).second); symmetryFound = true; } } } return symmetryFound; } bool HVSlicingNode::isSymmetry( int index ) { bool symmetryFound = false; if (_symmetries.empty() != true){ for (list >::const_iterator it2 = _symmetries.begin(); it2 != _symmetries.end(); it2++){ if ((*it2).second == index){ symmetryFound = true; } } } return symmetryFound; } void HVSlicingNode::addSymmetry( int childIndex, int copyIndex, bool reset ) { if (childIndex >= (int)getChildren().size()) { cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Child index out of range:%d (> %d), symmetry is ignored." , childIndex, getChildren().size() ) << endl; return; } if (copyIndex >= (int)getChildren().size()) { cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Copy index out of range:%d (> %d), symmetry is ignored." , copyIndex, getChildren().size() ) << endl; return; } if (childIndex == copyIndex) { cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Indexes cannot be identical (%d), symmetry is ignored." , childIndex ) << endl; return; } unsigned int symmetryType = 0; if (this->getType() == HorizontalSNode) symmetryType = HSymmetry; if (this->getType() == VerticalSNode ) symmetryType = VSymmetry; if (not getChild(childIndex)->isSymmetric(getChild(copyIndex), symmetryType, ShowDiff)) { cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored." , childIndex, copyIndex ) << endl; return; } _symmetries.push_back( pair(min(childIndex, copyIndex), max(childIndex, copyIndex)) ); if (reset) resetSlicingTree(); unsigned int flag = 0; if (this->getType() == HorizontalSNode) flag = HSymmetry; if (this->getType() == VerticalSNode ) flag = VSymmetry; getChild(copyIndex)->setSymmetryFlag(flag); getChild(copyIndex)->setMaster(getChild(childIndex)); normalizeSymmetries(); } void HVSlicingNode::removeSymmetry( int index ) { bool first = true; int erasedFirst = 0; int erasedSecond = 0; bool isReference = true; for ( list >::iterator it = _symmetries.begin(); it != _symmetries.end(); it++ ){ if ((((*it).first == index) || ((*it).second == index) ) && (first == true)){ list >::iterator itToerase = it; it++; resetSlicingTree(); first = false; if ((*it).first == index){ erasedFirst = (*itToerase).first; erasedSecond = (*itToerase).second; } else { isReference = false; } _symmetries.erase(itToerase); it--; } else { if ( (first == false) && (isReference) ){ if ((*it).first == erasedFirst){ (*it).first = erasedSecond; } } if ((*it).first > index) { (*it).first--; } if ((*it).second > index) { (*it).second--; } } } } void HVSlicingNode::normalizeSymmetries() { // -----------------------------------------------------------------------------------------------// // Notes : Symmetries must be described in a specific way, in case it is not, this method correct it. // Examples: // WRONG: Symmetries [< 1, 2 >, < 2, 3 >, < 3, 4 >]; RIGHT: [< 1, 2 >, < 1, 3 >, < 1, 4 >]; // WRONG: Symmetries [< 3, 4 >, < 5, 6 >, < 1, 2 >]; RIGHT: [< 1, 2 >, < 3, 4 >, < 5, 6 >]; // WRONG: Symmetries [< 1, 2 >, < 1, 2 >, < 3, 4 >]; RIGHT: [< 1, 2 >, < 3, 4 >]; // -----------------------------------------------------------------------------------------------// list > adjustedSymmetries = list >(); for (list >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++){ if ((*it).first > (*it).second ){ adjustedSymmetries.push_back(pair((*it).second,(*it).first)); } else { adjustedSymmetries.push_back(pair((*it).first,(*it).second)); } } adjustedSymmetries.sort(); bool next = false; list >::iterator it2 = adjustedSymmetries.begin(); it2++; for (list >::iterator it = adjustedSymmetries.begin(); it != adjustedSymmetries.end(); it++){ it2 = it; it2++; while(next != true){ if ( (*it).second == (*it2).first ){ (*it2).first = (*it).first; } if ( (*it).second < (*it2).first ){ next = true; } it2++; if ( it2 == adjustedSymmetries.end() ) { next = true; } } next = false; } _symmetries = adjustedSymmetries; } void HVSlicingNode::_resetSlicingTree() { _x = 0; _y = 0; setPlaced(false); if (!this->isPreset()){ _boxSet = NULL; setSet(false); for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ (*it)->_resetSlicingTree(); } } } void HVSlicingNode::print() const { SlicingNode::print(); if (_symmetries.empty() == false){ cerr << "Symmetries: " << endl; for (list >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++) { cerr << "Children: " << (*it).first << " and " << (*it).second << endl; } cerr << endl; } else { cerr << "Symmetries: None" << endl; } if (_slicingRouting.empty() == false){ cerr<< "Slicing Routing: " << endl; int index = 0; for (vector::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ cerr << "---------------- " << setprecision(4) << index << " -----------------" << endl; cerr << "Print - Slicing Routing: "; cerr << "X: " << DbU::getPhysical((*it)->getX(), DbU::Micro); cerr << ", Y: " << DbU::getPhysical((*it)->getY(), DbU::Micro); cerr << ", \t height: " << DbU::getPhysical((*it)->getHeight(), DbU::Micro); cerr << ", width: " << DbU::getPhysical((*it)->getWidth(), DbU::Micro) << endl; cerr << "GCell: " << (*it)->getGCell() << endl; if((*it)->getGCell()){ cerr << "GCell : " << (*it)->getGCell() << endl; cerr << "Edges : " << endl; vector ne = (*it)->getGCell()->getNorthEdges(); vector se = (*it)->getGCell()->getSouthEdges(); vector ee = (*it)->getGCell()->getEastEdges(); vector we = (*it)->getGCell()->getWestEdges(); cerr << "--- North : " << ne.empty() << endl; for (vector::const_iterator itn = ne.begin(); itn != ne.end(); itn++){ cerr << (*itn)->getOpposite((*it)->getGCell()) << endl; } cerr << "--- South : " << se.empty()<< endl; for (vector::const_iterator its = se.begin(); its != se.end(); its++){ cerr << (*its)->getOpposite((*it)->getGCell()) << endl; } cerr << "--- East : " << ee.empty()<< endl; for (vector::const_iterator ite = ee.begin(); ite != ee.end(); ite++){ cerr << (*ite)->getOpposite((*it)->getGCell()) << endl; } cerr << "--- West : "<< we.empty() << endl; for (vector::const_iterator itw = we.begin(); itw != we.end(); itw++){ cerr << (*itw)->getOpposite((*it)->getGCell()) << endl; } } cerr << "------------------------------------" << endl; index++; } } else { cerr<< "Slicing Routing: empty" << endl; } cerr << endl; } void HVSlicingNode::printChildren() const { int count = 0; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->isDevice()) || ((*it)->isRouting()) ){ cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl; (*it)->print(); } else { cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl; (*it)->print(); (*it)->printChildren(); } count++; } } void HVSlicingNode::printLine() const { SlicingNode::printLine(); if (_symmetries.empty() == false){ cerr << "Symmetries: " << endl; for (list >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++) { cerr << "Children: " << (*it).first << " and " << (*it).second << endl; } cerr << endl; } /*int index = 0; cerr << "Print - Slicing Routing: " << endl; for (vector::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ cerr << "Index: " << index; cerr << ", X: " << DbU::getPhysical((*it)->getX(), DbU::Micro); cerr << ", Y: " << DbU::getPhysical((*it)->getY(), DbU::Micro); cerr << ", \t height: " << DbU::getPhysical((*it)->getHeight(), DbU::Micro); cerr << ", width: " << DbU::getPhysical((*it)->getWidth(), DbU::Micro); if ((*it)->getMaster()){ cerr << ", MASTER: "; (*it)->getMaster()->printLine(); } else { cerr << endl; } index++; }*/ } void HVSlicingNode::printChildrenLine() const { int count = 0; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->isDevice()) || ((*it)->isRouting()) ){ cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl; (*it)->printLine(); } else { cerr << endl; cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl; (*it)->printLine(); (*it)->printChildrenLine(); } count++; } } bool HVSlicingNode::recursiveCheckPreset() const { bool isPreset = this->isPreset(); if (isPreset){ for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ isPreset = (*it)->recursiveCheckPreset(); } } return isPreset; } bool HVSlicingNode::recursiveCheckSet() const { bool isSet = this->isSet(); if (isSet){ for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ isSet = (*it)->recursiveCheckSet(); } } return isSet; } bool HVSlicingNode::recursiveCheckPlaced() const { bool isPlaced = this->isPlaced(); if (isPlaced){ for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ isPlaced = (*it)->recursiveCheckPlaced(); } } return isPlaced; } int HVSlicingNode::getLeafNumber() const { int cpt = 0; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++) { cpt += (*it)->getLeafNumber(); } return cpt; } double HVSlicingNode::getDevicesArea() const { double area = 0; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ area += (*it)->getDevicesArea(); } return area; } double HVSlicingNode::getOccupationArea() const { double estimation = 0; if(recursiveCheckPlaced()) { estimation = getDevicesArea()/(getHeight() * getWidth())*100; } else { cerr << "Error(double HVSlicingNode::getSpaceEstimation()): SlicingNodes dimensions need to be set first before being estimated." << endl; } return estimation; } void HVSlicingNode::setGlobalSize( DbU::Unit height, DbU::Unit width ) { if ( (_nodeSets->empty() != true) ){ vector::const_iterator it = _nodeSets->begin(); DbU::Unit bestH = 0; DbU::Unit bestW = 0; DbU::Unit currentH = 0; DbU::Unit currentW = 0; BoxSet* boxSet = (*_nodeSets->begin()); while (it != _nodeSets->end()){ currentH = (*it)->getHeight(); currentW = (*it)->getWidth(); if ( (currentH <= height) && (currentW <= width) ){ if ( ((height-currentH) <= _toleranceRatioH) && ((height-bestH) <= _toleranceRatioH) ) { if (currentW > bestW){ bestH = currentH; bestW = currentW; boxSet = (*it); } } else if (currentH > bestH) { bestH = currentH; bestW = currentW; boxSet = (*it); } } it++; } this->_setGlobalSize(boxSet); } else { cerr << "Error(void HVSlicingNode::setGlobalSize( DbU::Unit height, DbU::Unit width )): NodeSets empty. UpdateGlobalSize needs to be used first or with higher tolerances." << endl; } } void HVSlicingNode::setGlobalSize( size_t index ) { if ( _nodeSets->empty() != true ){ if (index > (_nodeSets->size()-1)){ cerr << "Error(void HVSlicingNode::setGlobalSize( size_t index )): Out of bound index." << endl; } else { this->_setGlobalSize((*(_nodeSets->begin() + index))); } } else { cerr << "Error(void HVSlicingNode::setGlobalSize( int index )): NodeSets empty. UpdateGlobalSize needs to be used first or with higher tolerances." << endl; } } void HVSlicingNode::_setGlobalSize ( BoxSet* boxSet ) { //cerr << "void HVSlicingNode::_setGlobalSize ( BoxSet* boxSet ) " << endl; if ( (!this->isPreset()) ){ if (this->getMaster() == NULL) { this->_setBoxSet(boxSet); } else { this->_setBoxSet(_master->getBoxSet()); } if ( ((getType() == HorizontalSNode) && (isHSymmetry())) || ((getType() == VerticalSNode ) && (isVSymmetry())) ){ vector::const_iterator itBoxSet = boxSet->getSet().begin(); for (vector::reverse_iterator it = _children.rbegin(); it != _children.rend(); ++it){ (*it)->_setGlobalSize((*itBoxSet)); itBoxSet++; } } else { vector::const_iterator itBoxSet = boxSet->getSet().begin(); for (vector::iterator it = _children.begin(); it != _children.end(); it++){ (*it)->_setGlobalSize((*itBoxSet)); itBoxSet++; } } } } void HVSlicingNode::preDestroy() { SlicingNode::preDestroy(); for (vector::iterator it = _children.begin(); it != _children.end(); it++){ (*it)->removeParent(); } } void HVSlicingNode::destroy() { HVSlicingNode::preDestroy(); delete(this); } void HVSlicingNode::preRecursiveDestroy() { SlicingNode::preRecursiveDestroy(); for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->getType() == HorizontalSNode) || ((*it)->getType() == VerticalSNode) ){ (*it)->removeParent(); (*it)->recursiveDestroy(); } else { (*it)->removeParent(); (*it)->destroy(); } } } void HVSlicingNode::recursiveDestroy() { HVSlicingNode::preRecursiveDestroy(); delete(this); } void printList( list liste ) { for ( list::const_iterator it = liste.begin(); it != liste.end(); it++ ){ (*it)->print(); } } list HVSlicingNode::getLeaves () const { list leaves = list(); for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->getType() == DeviceSNode) || ((*it)->getType() == RoutingSNode) ){ leaves.push_back((*it)); } else { leaves.splice(leaves.end(), (*it)->getLeaves()); } } return leaves; } bool HVSlicingNode::checkInitialPlacement( int& cpt ) const { // -----------------------------------------------------------------------------------------------// // Notes:: Initial placement criteria is having at least 2 devices placed at (x, y) = (0, 0) // -----------------------------------------------------------------------------------------------// bool initialPlacement = false; if (cpt < 2){ initialPlacement = true; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if (cpt < 2){ initialPlacement = (*it)->checkInitialPlacement(cpt); } } } return initialPlacement; } bool HVSlicingNode::isSame( SlicingNode* node, unsigned int flags ) const { if ( ( getType() == node->getType() ) and ( getNbChild() == node->getNbChild() ) and ( getToleranceBandH() == node->getToleranceBandH() ) and ( getToleranceBandW() == node->getToleranceBandW() ) ) { bool isSame = true; for ( size_t ichild = 0 ; isSame and (ichild < getNbChild()) ; ++ichild ) { isSame = getChild(ichild)->isSame( node->getChild(ichild) ); } if (not isSame and (flags & ShowDiff)) cerr << "HVSlicingNode::isSame() " << this << " and " << node << " differs (childs)." << endl; return isSame; } else { if (flags & ShowDiff) cerr << "HVSlicingNode::isSame() " << this << " and " << node << " differs." << endl; return false; } } /*bool HVSlicingNode::checkCellInstances ( Cell* cell ) { if (cell) { bool found = true; for ( Instance* instance : cell->getInstances() ) { if (not findInstance(instance)) { found = false; cerr << Warning( "HVSlicingNode::checkCellInstances() Instance \"%s\" is missing from the SlicingTree. " , getString(instance->getName()).c_str() ) << endl; } } return found; } return false; }*/ bool HVSlicingNode::checkCellInstances ( Cell* cell ) { if (cell) { bool found = true; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if (not (*it)->checkCellInstances(cell)) found = false; } return found; } else { cerr << "HVSlicingNode::checkCellInstances() Cell is NULL. " << endl; return false; } } SlicingNode* HVSlicingNode::findInstance( Instance* instance ) { SlicingNode* node = NULL; for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if( ((*it)->getType() == HorizontalSNode) || ((*it)->getType() == VerticalSNode) ){ SlicingNode* inode = (*it)->findInstance(instance); if (inode != NULL){ node = inode; } } else if ((*it)->getType() == DeviceSNode){ if ( (*it)->getInstance() == instance ){ node = (*it); } } } return node; } SlicingNode* HVSlicingNode::findSlicingNode( Anabatic::GCell* gcell ) { SlicingNode* node = NULL; for (vector::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); ++it){ if ( (*it)->getGCell() == gcell ){ node = (*it); break; } } if (node == NULL){ for (vector::const_iterator it = _children.begin(); it != _children.end(); ++it){ if( ((*it)->getType() == HorizontalSNode) || ((*it)->getType() == VerticalSNode) ){ SlicingNode* inode = (*it)->findSlicingNode(gcell); if (inode != NULL){ node = inode; } } else if ((*it)->getType() == DeviceSNode){ if ( (*it)->getGCell() == gcell ){ node = (*it); break; } } } } return node; } void HVSlicingNode::resetSlicingRouting() { for (vector::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ (*it)->resetSize(); } for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode) ){ (*it)->resetSlicingRouting(); } } this->setRoutingEstimated(0); } void HVSlicingNode::destroySlicingRouting() { for (vector::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ (*it)->destroy(); } _slicingRouting.clear(); for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode) ){ (*it)->destroySlicingRouting(); } } this->setRoutingEstimated(0); } int HVSlicingNode::getRoutingIndex( SlicingNode* node ) const { int i = 0; vector::const_iterator it = _slicingRouting.begin(); while (it != _slicingRouting.end()){ if ( ((*it)->getHeight() == node->getHeight()) && ((*it)->getWidth () == node->getWidth ()) && ((*it)->getX() == node->getX() ) && ((*it)->getY() == node->getY() ) ) { it = _slicingRouting.end(); } else { i++; it++; } } return i; } SlicingNode* HVSlicingNode::getSlicingRouting( int index ) const { return (*(_slicingRouting.begin()+index)); } void HVSlicingNode::restrictDevices() { for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ (*it)->restrictDevices(); } for (std::vector::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ (*it)->restrictDevices(); } } void HVSlicingNode::setVertexRestriction( Net* net, Katana::KatanaEngine* katana ) { cdebug_log(536,1) << "HVSlicingNode::setVertexRestriction(Net*,KatanaEngine*)" << endl; this->restrictDevices(); vector rps; for ( RoutingPad* rp : net->getRoutingPads() ) rps.push_back( rp ); for ( RoutingPad* rp : rps ) { Box rpBb = rp->getBoundingBox(); Point center = rpBb.getCenter(); Anabatic::GCell* gcell = katana->getGCellUnder( center ); if (not gcell) { cerr << Error( "Dijkstra::load(): %s of %s is not under any GCell.\n" " It will be ignored ans the routing will be incomplete." , getString(rp ).c_str() , getString(net).c_str() ) << endl; continue; } Anabatic::Vertex* vertex = gcell->getObserver(Anabatic::GCell::Observable::Vertex); // Analog Restrictions Plug* plug = dynamic_cast(rp->getPlugOccurrence().getEntity()); Cell* cell = plug->getInstance()->getMasterCell(); Device* device = dynamic_cast(cell); if (device){ cdebug_log(536,0) << "Underlying device: " << device << endl; unsigned int rule = device->getRestrictions2(plug->getMasterNet()); vertex->clearRestriction(); cdebug_log(536,0) << "Restrictions rule: " << rule << endl; if (rule & WestBlocked ) vertex->setWRestricted(); if (rule & EastBlocked ) vertex->setERestricted(); if (rule & SouthBlocked) vertex->setSRestricted(); if (rule & NorthBlocked) vertex->setNRestricted(); cdebug_log(536,0) << "Applied restrictions: " << vertex << endl; } else { vertex->clearRestriction(); } } cdebug_tabw(536,-1); } void HVSlicingNode::estimateChannelsSize() { for (std::vector::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ (*it)->estimateChannelsSize(); } for (vector::iterator it = _children.begin(); it != _children.end(); it++){ (*it)->estimateChannelsSize(); } } void HVSlicingNode::expandRoutingChannel() { estimateChannelsSize(); _expandRoutingChannel(); } void HVSlicingNode::_expandRoutingChannel() { for ( RHVSlicingNode* node : _slicingRouting ) node->_expandRoutingChannel(); for ( SlicingNode* node : _children ) { if (node->getType() != RoutingSNode) node->_expandRoutingChannel(); } setRoutingEstimated(RoutingEstimated); if (_parent == NULL) { for ( SlicingNode* node : _children ) node->adjustBorderChannels(); } } void HVSlicingNode::expandRoutingChannel( DbU::Unit height, DbU::Unit width ) { for ( RHVSlicingNode* node : _slicingRouting ) node->expandRoutingChannel( height, width ); for ( SlicingNode* node : _children ) { if (node->getType() != RoutingSNode) node->expandRoutingChannel( height, width ); } setRoutingEstimated( RoutingEstimated ); if (_parent == NULL) for ( SlicingNode* node : _children ) node->adjustBorderChannels(); } bool HVSlicingNode::isRoutingEstimated() const { //cerr << "bool HVSlicingNode::isRoutingEstimated() const" << endl; bool estimated = true; if (_slicingRouting.empty()){ estimated = false; } else { for (std::vector::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ estimated &= (*it)->isRoutingEstimated(); } } for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->getType() == HorizontalSNode ) || ((*it)->getType() == VerticalSNode) ){ estimated &= (*it)->isRoutingEstimated(); } } return estimated; } void HVSlicingNode::updateGCellPosition() { cdebug_log(535,1) << "HVSlicingNode::updateGCellPosition()" << endl; for ( SlicingNode* node : _slicingRouting ) node->updateGCellPosition(); for ( SlicingNode* node : _children ) node->updateGCellPosition(); cdebug_tabw(535,-1); } void HVSlicingNode::updateGContacts() { cdebug_log(535,1) << "HVSlicingNode::updateGContacts()" << endl; for ( SlicingNode* node : _slicingRouting ) node->updateGContacts(); for ( SlicingNode* node : _children ) node->updateGContacts(); cdebug_tabw(535,-1); } void HVSlicingNode::clearGCells() { for (std::vector::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ (*it)->clearGCells(); } for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ (*it)->clearGCells(); } _gcell = NULL; } int HVSlicingNode::getNbDevices () { int nb = 0; for ( SlicingNode* node : _children ){ nb += node->getNbDevices(); } return nb; } string HVSlicingNode::_getString () const { string s = Super::_getString(); s.insert( s.size()-1, " childs:" + getString(_children.size()) ); return s; } string HVSlicingNode::_getTypeName () const { return "HVSlicingNode"; } void HVSlicingNode::setSymmetryFlag( unsigned int flag ) { SlicingNode::setSymmetryFlag(flag); for (std::vector::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){ (*it)->setSymmetryFlag(flag); } for (vector::const_iterator it = _children.begin(); it != _children.end(); it++){ (*it)->setSymmetryFlag(flag); } } void HVSlicingNode::setMaster ( SlicingNode* master ) { _master = master; int index = 0; if ( ((getType() == HorizontalSNode) && (isHSymmetry())) || ((getType() == VerticalSNode ) && (isVSymmetry())) ){ for (vector::reverse_iterator it = _children.rbegin(); it != _children.rend(); it++) { (*it)->setMaster(master->getChild(index)); index++; } } else { for (vector::iterator it = _children.begin(); it != _children.end(); it++) { (*it)->setMaster(master->getChild(index)); index++; } } } bool HVSlicingNode::isSymmetric( SlicingNode* node, unsigned int symmetryType, unsigned int flags ) const { if ( ( getType() == node->getType() ) and ( getNbChild() == node->getNbChild() ) and ( getToleranceBandH() == node->getToleranceBandH() ) and ( getToleranceBandW() == node->getToleranceBandW() ) ) { bool isSame = true; if ( ((getType() == HorizontalSNode) && (symmetryType == HSymmetry)) || ((getType() == VerticalSNode ) && (symmetryType == VSymmetry)) ){ int i = 0; for ( int ichild = (int) getNbChild()-1 ; isSame and (ichild > -1) ; --ichild ) { isSame = getChild(i)->isSymmetric( node->getChild(ichild), symmetryType ); i++; } } else { for ( int ichild = 0 ; isSame and (ichild < (int) getNbChild()) ; ++ichild ) { isSame = getChild(ichild)->isSymmetric( node->getChild(ichild), symmetryType ); } } if (not isSame and (flags & ShowDiff)) cerr << "HVSlicingNode::isSame() " << this << " and " << node << " differs (childs)." << endl; return isSame; } else { if (flags & ShowDiff) cerr << "HVSlicingNode::isSame() " << this << " and " << node << " differs." << endl; return false; } } bool HVSlicingNode::checkSymmetryNet( unsigned int type, Net* net1, Net* net2 ) const { //cerr << "bool HVSlicingNode::checkSymmetryNet( unsigned int type, Net* net1, Net* net2 ) const" << endl; bool b = false; for ( vector >::const_iterator it = _netsymmetries.begin(); it != _netsymmetries.end(); ++it) { if (get<1>((*it)) == net1){ if (get<2>((*it)) == net2){ if (get<0>((*it)) == type) { b = true; break; } } } } return b; } void HVSlicingNode::addSymmetryNet( unsigned int type, Net* net1, Net* net2 ) { //cerr << "void HVSlicingNode::addSymmetryNet( unsigned int type, Net* net1, Net* net2 )" << endl; if (!checkSymmetryNet(type, net1, net2)){ unsigned int ftype = type; if (type == 1) ftype = NetRoutingState::Vertical; else if (type == 2) ftype = NetRoutingState::Horizontal; _netsymmetries.push_back(make_tuple(ftype, net1, net2)); } else { cerr << "Warning(void HVSlicingNode::addSymmetryNet( unsigned int type, Net* net1, Net* net2 )): Net symmetry already set." << endl; } } void HVSlicingNode::updateNetConstraints() { //cerr << "void void HVSlicingNode::updateNetConstraints()" << endl; if (_cell != NULL){ for ( vector >::const_iterator it = _netsymmetries.begin(); it != _netsymmetries.end(); ++it) { if (get<2>((*it))){ Net* masterNet = get<1>((*it)); if (not masterNet) cerr << "void HVSlicingNode::updateNetConstraints() Net \"%s\" not found." << endl; NetRoutingState* masterState = NetRoutingExtension::get( masterNet ); if (not masterState) masterState = NetRoutingExtension::create( masterNet ); //cerr << "type: " << get<0>((*it)) << endl; //cerr << "net1: " << get<1>((*it)) << endl; //cerr << "net2: " << get<2>((*it)) << endl; masterState->setFlags ( NetRoutingState::AutomaticGlobalRoute | NetRoutingState::Symmetric | NetRoutingState::SymmetricMaster | get<0>((*it)) ); /*if (get<0>((*it)) == NetRoutingState::Vertical ) masterState->setSymAxis( getX() + getWidth ()/2 ); else if (get<0>((*it)) == NetRoutingState::Horizontal) masterState->setSymAxis( getY() + getHeight()/2 ); else cerr << "void HVSlicingNode::updateNetConstraints(): Wrong axis for Net \"%s\"." << endl;*/ Net* slaveNet = get<2>((*it)); if (not slaveNet) cerr << "void HVSlicingNode::updateNetConstraints() Net \"%s\" not found." << endl; NetRoutingState* slaveState = NetRoutingExtension::get( slaveNet ); if (not slaveState) slaveState = NetRoutingExtension::create( slaveNet ); slaveState ->setFlags ( NetRoutingState::AutomaticGlobalRoute | NetRoutingState::Symmetric | get<0>((*it)) ); /*if (get<0>((*it)) == NetRoutingState::Vertical ) slaveState->setSymAxis( getX() + getWidth ()/2 ); else if (get<0>((*it)) == NetRoutingState::Horizontal) slaveState->setSymAxis( getY() + getHeight()/2 ); else cerr << "void HVSlicingNode::updateNetConstraints(): Wrong axis for Net \"%s\"." << endl;*/ slaveState ->setSymNet ( masterNet ); masterState->setSymNet ( slaveNet ); //cerr << "masterState: " << masterState << endl; //cerr << "slaveState : " << slaveState << endl; } else { Net* net = get<1>((*it)); if (not net) cerr << "void HVSlicingNode::updateNetConstraints() Net \"%s\" not found." << endl; NetRoutingState* state = NetRoutingExtension::get( net ); if (not state) state = NetRoutingExtension::create( net ); state->setFlags ( NetRoutingState::AutomaticGlobalRoute | NetRoutingState::Symmetric | get<0>((*it)) ); //cerr << "state: " << state << endl; /*if (get<0>((*it)) == NetRoutingState::Vertical ) state->setSymAxis( getX() + getWidth ()/2 ); else if (get<0>((*it)) == NetRoutingState::Horizontal) state->setSymAxis( getY() + getHeight()/2 ); else cerr << "void HVSlicingNode::updateNetConstraints(): Wrong axis for Net \"%s\"." << endl;*/ } } for (vector::iterator it = _children.begin(); it != _children.end(); ++it){ if (((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode)) (*it)->updateNetConstraints(); } } else { cerr << "Error(void HVSlicingNode::updateNetConstraints()): Cell undefined." << endl; } } void HVSlicingNode::updateSymNetAxis() { //cerr << "void HVSlicingNode::updateSymNetAxis()" << endl; if (_cell != NULL){ for ( const tuple triplet : _netsymmetries ) { SlicingNode* n1 = getChild(_symmetries.front().first); SlicingNode* n2 = getChild(_symmetries.front().second); DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2; DbU::Unit yCenter = (n1->getY() + n2->getY() + n2->getHeight())/2; if (get<2>(triplet)){ Net* masterNet = get<1>(triplet); if (not masterNet) cerr << "void HVSlicingNode::updateSymNetAxis() Net \"%s\" not found." << endl; NetRoutingState* masterState = NetRoutingExtension::get( masterNet ); if (not masterState) cerr << "void HVSlicingNode::updateSymNetAxis(): UpdateNetConstraint need to be used first." << endl; if (get<0>(triplet) == NetRoutingState::Vertical ) masterState->setSymAxis( xCenter );//getXCenter() ); else if (get<0>(triplet) == NetRoutingState::Horizontal) masterState->setSymAxis( yCenter );//getYCenter() ); else cerr << "void HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." << endl; Net* slaveNet = get<2>(triplet); if (not slaveNet) cerr << "void HVSlicingNode::updateSymNetAxis() Net \"%s\" not found." << endl; NetRoutingState* slaveState = NetRoutingExtension::get( slaveNet ); if (not slaveState) cerr << "void HVSlicingNode::updateSymNetAxis(): updateSymNetAxis need to be used first." << endl; if (get<0>(triplet) == NetRoutingState::Vertical ) slaveState->setSymAxis( xCenter );//getXCenter() ); else if (get<0>(triplet) == NetRoutingState::Horizontal) slaveState->setSymAxis( yCenter );//getYCenter() ); else cerr << "void HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." << endl; //cerr << "Master net: " << masterNet << ", state: " << masterState << ", axis: " << DbU::getValueString(masterState->getSymAxis())<< endl; //cerr << "Slave net: " << slaveNet << ", state: " << slaveState << ", axis: " << DbU::getValueString(slaveState->getSymAxis())<< endl; } else { /* if ( getType() == HorizontalSNode ) { if ( !checkSelfSymH (get<1>(triplet)) ) { cerr << Error( "SlicingNode::HVSlicingNode::updateSymNetAxis(): Net %s is not self symmetric.", getString(get<1>(triplet)).c_str() ) << endl; } } else if ( getType() == VerticalSNode ) { if ( !checkSelfSymV (get<1>(triplet)) ) { cerr << Error( "SlicingNode::HVSlicingNode::updateSymNetAxis(): Net %s is not self symmetric.", getString(get<1>(triplet)).c_str() ) << endl; } } */ Net* net = get<1>(triplet); if (not net) cerr << "void HVSlicingNode::updateSymNetAxis() Net not found." << endl; NetRoutingState* state = NetRoutingExtension::get( net ); if (not state) cerr << "void HVSlicingNode::updateSymNetAxis(): UpdateNetConstraint need to be used first." << endl; if (get<0>(triplet) == NetRoutingState::Vertical ){ //cerr << "case Vertical" << endl ; state->setSymAxis( xCenter );//getXCenter() ); } else if (get<0>(triplet) == NetRoutingState::Horizontal) { //cerr << "case Horizontal" << endl ; state->setSymAxis( yCenter );//getYCenter() ); } else cerr << "void HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." << endl; //cerr << "Master Only net: " << net << ", state: " << state << ", axis: " << DbU::getValueString(state->getSymAxis())<< endl; } } for ( SlicingNode* child : _children ) { if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) child->updateSymNetAxis(); } } else { cerr << "Error(void HVSlicingNode::updateSymNetAxis()): Cell undefined." << endl; } } void HVSlicingNode::flattenDigitalNets () { if (_cell != NULL){ for (vector::iterator it = _children.begin(); it != _children.end(); ++it){ if (((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode)){ (*it)->flattenDigitalNets(); } else if ((*it)->getType() == DeviceSNode){ if ( ((*it)->getGCell() != NULL) && ((*it)->getInstance() != NULL) ){ if ( (*it)->getGCell()->isMatrix() ) { //cerr << "FLATTEN NETS: " << (*it)->getInstance() << endl; _cell->flattenNets( (*it)->getInstance(), Cell::Flags::BuildRings|Cell::Flags::WarnOnUnplacedInstances ); } } } } } else { cerr << "Error(void HVSlicingNode::flattenDigitalNets()): Cell not found." << endl; } } void HVSlicingNode::updateWireOccupation ( Anabatic::VertexSet sources ) { //cerr << "void HVSlicingNode::updateWireOccupation ( Anabatic::VertexSet sources )" << endl; if (_parent == NULL){ //Anabatic::Vertex* ivertex = NULL; for ( Anabatic::Vertex* ivertex : sources ) { Anabatic::GCell* igcell = ivertex->getGCell(); SlicingNode* snode = findSlicingNode(igcell); if (snode){ if((snode->getType() == RoutingSNode)&& ivertex->hasAData()){ //cerr << "ivertex:" << ivertex << ", min:" << DbU::getPhysical(ivertex->getIMin(), DbU::Micro) << ", max:" << DbU::getPhysical(ivertex->getIMax(), DbU::Micro) << endl; snode->addWireOccupation( ivertex->getIMin() , ivertex->getIMax() ); } } } } //cerr << "" << endl; } void HVSlicingNode::resetWireOccupation () { for (std::vector::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); ++it){ (*it)->resetWireOccupation(); } for (vector::iterator it = _children.begin(); it != _children.end(); ++it){ if ((*it)->getType() != DeviceSNode) (*it)->resetWireOccupation(); } } // -----------------------------------------------------------------------------------------------// // Class : HSlicingNode // -----------------------------------------------------------------------------------------------// int HSlicingNode::_count = 0; int HSlicingNode::_countAll = 0; HSlicingNode::HSlicingNode( unsigned int type, unsigned int alignment ): HVSlicingNode( type, alignment ){} HSlicingNode::~HSlicingNode(){} HSlicingNode* HSlicingNode::create( unsigned int alignment ) { _count++; _countAll++; return new HSlicingNode( HorizontalSNode, alignment ); } void HSlicingNode::createRouting( DbU::Unit space ) { this->push_back(RHSlicingNode::create( space )); resetSlicingTree(); } void HSlicingNode::print() const { cerr << "- Print from Slicing Node - " << endl; cerr << "SlicingType: Horizontal Node" << endl; if (this->isAlignLeft ()){ cerr << "Alignment : Left" << endl; } else if (this->isAlignCenter()){ cerr << "Alignment : Middle" << endl; } else if (this->isAlignRight ()){ cerr << "Alignment : Right" << endl; } else { cerr << "Alignment : Unknown" << endl; } cerr << "Tolerances : RatioH: " << DbU::getPhysical(_toleranceRatioH,DbU::Micro) << ", RatioW: " << DbU::getPhysical(_toleranceRatioW,DbU::Micro) << ", BandH: " << DbU::getPhysical(_toleranceBandH,DbU::Micro) << ", BandW: " << DbU::getPhysical(_toleranceBandW,DbU::Micro) << endl; HVSlicingNode::print(); } HSlicingNode* HSlicingNode::clone( unsigned int tr ) { HSlicingNode* node = HSlicingNode::create( this->getAlignment() ); node->setTolerances( getToleranceRatioH() , getToleranceRatioW() , getToleranceBandH() , getToleranceBandW() ); node->setBoxSet ( getBoxSet() ); node->setNodeSets ( _nodeSets->clone() ); node->setPreset ( this->getPreset() ); node->setSet ( this->getSet() ); node->setPlaced ( this->getPlaced() ); node->setSymmetries( this->getSymmetries() ); for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if (tr == MY){ node->push_front((*it)->clone(tr)); } else { node->push_back ((*it)->clone(tr)); } } return node; } void HSlicingNode::place( DbU::Unit x, DbU::Unit y ) { if( recursiveCheckSet() ){ if (!_slicingRouting.empty()) { this->destroySlicingRouting(); this->resetSlicingRouting(); } this->_place(x,y); if (_slicingRouting.empty()) { this->createSlicingRouting(); } this->updateCellAbutmentBox(); } else { cerr << "Error(void HSlicingNode::place( DbU::Unit x, DbU::Unit y )): The SlicingTree is not completely set." << endl; } } void HSlicingNode::replace( DbU::Unit x, DbU::Unit y ) { // WARNING: This will change GCell edges. if (recursiveCheckSet()) { _place( x, y, true ); updateCellAbutmentBox(); updateGCellPosition(); updateGContacts(); } else { cerr << Error( "void HSlicingNode::replace(DbU::Unit,DbU::Unit)): The SlicingTree is not completely set." ) << endl; } } void HSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace ) { cdebug_log(536,1) << "void HSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )" << endl; vector::iterator itspace = _slicingRouting.begin(); DbU::Unit xref = x; DbU::Unit yref = y; if (isRoutingEstimated()){ (*itspace)->_place(xref, yref, replace); yref += (*itspace)->getHeight(); itspace++; } for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->isHorizontal()) || ((*it)->isVertical()) ){ if ( (*it)->isAlignLeft() ){ (*it)->setX(xref); (*it)->setY(yref); } else if ( (*it)->isAlignCenter() ){ (*it)->setX(xref + (this->getWidth()/2) - ((*it)->getWidth()/2)); (*it)->setY(yref); } else if ( (*it)->isAlignRight() ){ (*it)->setX(xref + this->getWidth() - (*it)->getWidth()); (*it)->setY(yref); } } if ( (*it)->isAlignLeft() ) { (*it)->_place(xref , yref, replace); } else if ( (*it)->isAlignCenter() ) { (*it)->_place(xref + (this->getWidth()/2) - ((*it)->getWidth()/2), yref, replace); } else if ( (*it)->isAlignRight() ) { (*it)->_place(xref + this->getWidth() - (*it)->getWidth() , yref, replace); } else if ( (*it)->isRouting() ) { (*it)->_place(xref , yref, replace); } else { cerr << "Error(_place( DbU::Unit x, DbU::Unit y )): Unknown Alignment in SlicingTree." << endl ; (*it)->print(); } xref = x; yref += (*it)->getHeight(); if (isRoutingEstimated()){ (*itspace)->_place(xref, yref, replace); yref += (*itspace)->getHeight(); itspace++; } } setPlaced(Placed); cdebug_tabw(536,-1); } void HSlicingNode::updateGlobalSize() { cdebug_log(535,1) << "HSlicingNode::updateGlobalsize()" << endl; for (vector::iterator it = _children.begin(); it != _children.end(); it++) { (*it)->updateGlobalSize(); } if (this->getMaster() == NULL) { if (this->getNbChild() == 1){ _nodeSets->clear(); NodeSets* node = _children[0]->getNodeSets(); for(vector::const_iterator it2 = node->begin(); it2 != node->end(); it2++){ vector vect = vector(); vect.push_back((*it2)); DbU::Unit height = (*it2)->getHeight(); DbU::Unit width = (*it2)->getWidth(); _nodeSets->push_back(vect, height, width, HorizontalSNode); } } else if ( (this->hasEmptyChildrenNodeSets() != true) && (_nodeSets->empty() == true) ){ HSetState state = HSetState(this); while( !state.end() ){ state.next(); } _nodeSets = state.getNodeSets(); } if (_nodeSets->empty()){ cerr << "Error(void HSlicingNode::updateGlobalSize()): No solution has been found. Try to set larger tolerances." << endl; } } else { _nodeSets = _master->getNodeSets(); } cdebug_tabw(535,-1); } void HSlicingNode::preDestroy() { _count--; HVSlicingNode::preDestroy(); } void HSlicingNode::destroy() { HSlicingNode::preDestroy(); delete(this); } void HSlicingNode::preRecursiveDestroy() { _count--; HVSlicingNode::preRecursiveDestroy(); } void HSlicingNode::recursiveDestroy() { HSlicingNode::preRecursiveDestroy(); delete(this); } OpenChams::SlicingNode* HSlicingNode::toOpenChams() { OpenChams::SlicingNode* hnode = OpenChams::HSlicingNode::create(); if ( isAlignLeft() ){ hnode->setAlignment( "AlignLeft" ); } else if ( isAlignRight() ){ hnode->setAlignment( "AlignRight" ); } else if ( isAlignCenter() ){ hnode->setAlignment( "AlignCenter" ); } else if ( isAlignTop() ){ hnode->setAlignment( "AlignTop" ); } else if ( isAlignBottom() ){ hnode->setAlignment( "AlignBottom" ); } else { hnode->setAlignment( "UnknownAlignment"); } hnode->setToleranceRatioH(_toleranceRatioH); hnode->setToleranceRatioW(_toleranceRatioW); hnode->setToleranceBandH(_toleranceBandH); hnode->setToleranceBandW(_toleranceBandW); if (!_symmetries.empty()){ for (list >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++){ hnode->addSymmetry((*it).first, (*it).second); } } for (vector::iterator it2 = _children.begin(); it2 != _children.end(); it2++){ hnode->push_back( (*it2)->toOpenChams() ); } return hnode; } void HSlicingNode::createSlicingRouting() // Needs to be change in case of not alternative H/V { if (_boxSet){ int numberChildren = getNbChild(); vector::iterator it1 = _children.begin(); DbU::Unit x = this->getX(); DbU::Unit y = this->getY(); DbU::Unit heightValue = 0; if ( _parent ){ if ( _parent->getType() == VerticalSNode ){ if ( (this->getAlignment() == AlignBottom) || (this->getAlignment() == AlignTop) ){ heightValue = _parent->getHeight() - this->getHeight(); } else if ( this->getAlignment() == AlignCenter ){ heightValue = (_parent->getHeight() - this->getHeight())/2; } } } DbU::Unit hpitch = _rg->getHorizontalPitch(); if (heightValue % hpitch) cerr << Warning( "HSlicingNode::createSlicingRouting(): On %s, height is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(heightValue).c_str() , DbU::getValueString(hpitch).c_str() ) << endl; for (int i = 0; i < numberChildren+1; ++i){ RHSlicingNode* rnode = NULL; if ( i == 0 ){ if ( (this->getAlignment() == AlignTop) || (this->getAlignment() == AlignCenter) ){ rnode = RHSlicingNode::create( heightValue ); } else { rnode = RHSlicingNode::create(); } } else if ( i == numberChildren ){ if ( (this->getAlignment() == AlignBottom) || (this->getAlignment() == AlignCenter) ){ rnode = RHSlicingNode::create( heightValue ); } else { rnode = RHSlicingNode::create(); } } else { rnode = RHSlicingNode::create(); } rnode->setParent(this); if (i == 0){ if ( this->getAlignment() == AlignBottom ){ rnode->place(x, y); } else if ( (this->getAlignment() == AlignCenter) || (this->getAlignment() == AlignTop)) { rnode->place(x, y-heightValue); } } else { rnode->place(x, y); } if (_master){ rnode->setMaster(_master->getSlicingRouting(i)); } _slicingRouting.push_back(rnode); if (i < numberChildren){ y += (*it1)->getHeight(); it1++; } } if (_master){ if (isHSymmetry()){ for (size_t i = 0; i < _slicingRouting.size(); i++){ getSlicingRouting(i)->setMaster(_master->getSlicingRouting(_slicingRouting.size()-1-i)); } } else { for (size_t i = 0; i < _slicingRouting.size(); i++){ getSlicingRouting(i)->setMaster(_master->getSlicingRouting(i)); } } } else if ((_symmetries.empty() == false)&&(isAlignCenter())){ for (size_t i = 0; i < (_slicingRouting.size()/2); i++){ getSlicingRouting(_slicingRouting.size()-1-i)->setMaster(getSlicingRouting(i)); } } for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->isHorizontal()) || ((*it)->isVertical()) ){ (*it)->createSlicingRouting(); } } this->setRoutingCreated(RoutingCreated); } else { cerr << "Error(void HSlicingNode::createSlicingRouting()): SlicingTree needs to be placed first." << endl; } } DbU::Unit HSlicingNode::getHeight () const { DbU::Unit hpitch = _rg->getHorizontalPitch(); DbU::Unit height = 0; if (isRoutingEstimated()){ for ( SlicingNode* node : _children ) height += node->getHeight(); for ( RHVSlicingNode* node : _slicingRouting ) height += node->getHeight(); } else { if (_boxSet != NULL) height = _boxSet->getHeight(); } if (height % hpitch) cerr << Warning( "HSlicingNode::getHeight(): On %s, height is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(height).c_str() , DbU::getValueString(hpitch).c_str() ) << endl; return height; } DbU::Unit HSlicingNode::getWidth () const { //cdebug_log(536,0) << "DbU::Unit HSlicingNode::getWidth () const " << endl; DbU::Unit vpitch = _rg->getVerticalPitch(); DbU::Unit width = 0; if (isRoutingEstimated()) { SlicingNode* m = NULL; for ( SlicingNode* node : _children ) { if ( (node->getType() != RoutingSNode) and (node->getWidth() > width) ) { width = node->getWidth(); m = node; } } if (m->isDevice()) width += vpitch*2; } else { //cdebug_log(536,0) << "case is routing not estimated" << endl; if (_boxSet != NULL) width = _boxSet->getWidth(); } if (width % vpitch) cerr << Warning( "HSlicingNode::getWidth(): On %s, width is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(width).c_str() , DbU::getValueString(vpitch).c_str() ) << endl; return width; } void HSlicingNode::setGCell ( Anabatic::GCell* gcell ) { Anabatic::GCell* prevGCell = gcell; Anabatic::GCell* nextGCell = NULL; vector::const_iterator itc = _children.begin(); vector::const_iterator its = _slicingRouting.begin(); cdebug_log(535,1) << "HSlicingNode::setGCell(Anabatic::GCell*), start Y: "<< (*its)->getY() << ", GCell:" << gcell << endl; int index = 0; DbU::Unit y = (*its)->getY(); while ( not ((itc == _children.end()) and (its+1 == _slicingRouting.end())) ) { if (index%2 == 0) { y += (*its)->getHeight(); nextGCell = prevGCell->hcut( y ); (*its)->setGCell( prevGCell ); its++; } else { y += (*itc)->getHeight(); nextGCell = prevGCell->hcut( y ); (*itc)->setGCell( prevGCell ); itc++; } prevGCell = nextGCell; index++; } (*its)->setGCell( prevGCell ); cdebug_tabw(535,-1); } void HSlicingNode::adjustBorderChannels () { if (_parent){ if (_parent->getHeight() > getHeight()){ DbU::Unit space = _parent->getHeight() - getHeight(); if ( this->getAlignment() == AlignTop ){ RHVSlicingNode* ch = (*_slicingRouting.begin()); ch->setHeight(ch->getHeight()+space); } else if ( this->getAlignment() == AlignCenter ){ RHVSlicingNode* chf = (*_slicingRouting.begin()); RHVSlicingNode* chl = (*(_slicingRouting.end()-1)); chf->setHeight(chf->getHeight()+space/2); chl->setHeight(chl->getHeight()+space/2); } else if ( this->getAlignment() == AlignBottom ){ RHVSlicingNode* ch = (*(_slicingRouting.end()-1)); ch->setHeight(ch->getHeight()+space); } } } for (vector::iterator it = _children.begin(); it != _children.end(); it++){ (*it)->adjustBorderChannels(); } } string HSlicingNode::_getString () const { string s = Super::_getString(); return s; } string HSlicingNode::_getTypeName () const { return "HSlicingNode"; } // -----------------------------------------------------------------------------------------------// // Class : VSlicingNode // -----------------------------------------------------------------------------------------------// int VSlicingNode::_count = 0; int VSlicingNode::_countAll = 0; VSlicingNode::VSlicingNode( unsigned int type, unsigned int alignment ): HVSlicingNode( type, alignment ){} VSlicingNode::~VSlicingNode(){} VSlicingNode* VSlicingNode::create( unsigned int alignment ) { _count++; _countAll++; return new VSlicingNode( VerticalSNode, alignment ); } void VSlicingNode::createRouting( DbU::Unit space ) { this->push_back(RVSlicingNode::create( space )); resetSlicingTree(); } void VSlicingNode::print() const { cerr << "- Print from Slicing Node - " << endl; cerr << "SlicingType: Vertical Node" << endl; if (this->isAlignBottom()){ cerr << "Alignment : Bottom" << endl; } else if (this->isAlignCenter()){ cerr << "Alignment : Middle" << endl; } else if (this->isAlignTop ()){ cerr << "Alignment : Top" << endl; } else { cerr << "Alignment : Unknown" << endl; } cerr << "Tolerances : RatioH: " << DbU::getPhysical(_toleranceRatioH,DbU::Micro) << ", RatioW: " << DbU::getPhysical(_toleranceRatioW,DbU::Micro) << ", BandH: " << DbU::getPhysical(_toleranceBandH,DbU::Micro) << ", BandW: " << DbU::getPhysical(_toleranceBandW,DbU::Micro) << endl; HVSlicingNode::print(); } VSlicingNode* VSlicingNode::clone( unsigned int tr ) { VSlicingNode* node = VSlicingNode::create( this->getAlignment() ); node->setTolerances( getToleranceRatioH() , getToleranceRatioW() , getToleranceBandH() , getToleranceBandW() ); node->setBoxSet ( getBoxSet() ); node->setNodeSets ( _nodeSets->clone() ); node->setPreset ( this->getPreset() ); node->setSet ( this->getSet() ); node->setPlaced ( this->getPlaced() ); node->setSymmetries( this->getSymmetries() ); for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if (tr == MX){ node->push_front((*it)->clone(tr)); } else { node->push_back ((*it)->clone(tr)); } } return node; } void VSlicingNode::place( DbU::Unit x, DbU::Unit y ) { if (recursiveCheckSet()){ if (!_slicingRouting.empty()) { this->destroySlicingRouting(); this->resetSlicingRouting(); } this->_place(x,y); if (_slicingRouting.empty()) { this->createSlicingRouting(); } this->updateCellAbutmentBox(); } else { cerr << "Error(void VSlicingNode::place( DbU::Unit x, DbU::Unit y )): The SlicingTree is not completely set." << endl; } } void VSlicingNode::replace( DbU::Unit x, DbU::Unit y ) { // WARNING: This will change GCell edges. if (recursiveCheckSet()) { _place( x, y, true ); updateCellAbutmentBox(); updateGCellPosition(); updateGContacts(); } else { cerr << Error( "HVlicingNode::place(DbU::Unit,DbU::Unit)): The SlicingTree is not completely set." ) << endl; } } void VSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace ) { cdebug_log(536,1) << "void VSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )" << endl; //printLine(); vector::iterator itspace = _slicingRouting.begin(); DbU::Unit xref = x; DbU::Unit yref = y; if (isRoutingEstimated()){ (*itspace)->_place(xref, yref, replace); xref += (*itspace)->getWidth(); itspace++; } for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( ( (*it)->isHorizontal()) || ((*it)->isVertical()) ){ if ( (*it)->isAlignBottom() ){ (*it)->setX(xref); (*it)->setY(yref); } else if ( (*it)->isAlignCenter() ){ (*it)->setX(xref); (*it)->setY(yref + (this->getHeight()/2) - ((*it)->getHeight()/2)); } else if ( (*it)->isAlignTop() ){ (*it)->setX(xref); (*it)->setY(yref + this->getHeight() - (*it)->getHeight()); } } if ( (*it)->isAlignBottom() ) { (*it)->_place(xref, yref , replace); } else if ( (*it)->isAlignCenter() ) { (*it)->_place(xref, yref + (this->getHeight()/2) - ((*it)->getHeight()/2), replace); } else if ( (*it)->isAlignTop() ) { (*it)->_place(xref, yref + this->getHeight() - (*it)->getHeight() , replace); } else if ( (*it)->isRouting() ) { (*it)->_place(xref, yref , replace); } else { cerr << " Error(void place( DbU::Unit x, DbU::Unit y )): Unknown Alignment in SlicingTree." << endl ; (*it)->print(); } xref += (*it)->getWidth(); yref = y; if (isRoutingEstimated()){ (*itspace)->_place(xref, yref, replace); xref += (*itspace)->getWidth(); itspace++; } } setPlaced(Placed); cdebug_tabw(536,-1); } void VSlicingNode::updateGlobalSize() { cdebug_log(535,1) << "HSlicingNode::updateGlobalsize()" << endl; for (vector::iterator it = _children.begin(); it != _children.end(); it++) { (*it)->updateGlobalSize(); } if (this->getMaster() == NULL) { if (this->getNbChild() == 1){ _nodeSets->clear(); NodeSets* node = _children[0]->getNodeSets(); for(vector::const_iterator it2 = node->begin(); it2 != node->end(); it2++){ vector vect = vector(); vect.push_back((*it2)); DbU::Unit height = (*it2)->getHeight(); DbU::Unit width = (*it2)->getWidth(); _nodeSets->push_back(vect, height, width, VerticalSNode); } } else if ( (this->hasEmptyChildrenNodeSets() != true) && (_nodeSets->empty() == true) ){ VSetState state = VSetState(this); while( !state.end() ){ state.next(); } _nodeSets = state.getNodeSets(); } if (_nodeSets->empty()) { cerr << "Error(void VSlicingNode::updateGlobalSize()): No solution has been found. Try to set larger tolerances." << endl; } } else { _nodeSets = _master->getNodeSets(); } cdebug_tabw(535,-1); } void VSlicingNode::preDestroy() { _count--; HVSlicingNode::preDestroy(); } void VSlicingNode::destroy() { VSlicingNode::preDestroy(); delete(this); } void VSlicingNode::preRecursiveDestroy() { _count--; HVSlicingNode::preRecursiveDestroy(); } void VSlicingNode::recursiveDestroy() { VSlicingNode::preRecursiveDestroy(); delete(this); } OpenChams::SlicingNode* VSlicingNode::toOpenChams() { OpenChams::SlicingNode* vnode = OpenChams::VSlicingNode::create(); if ( isAlignLeft() ){ vnode->setAlignment( "AlignLeft" ); } else if ( isAlignRight() ){ vnode->setAlignment( "AlignRight" ); } else if ( isAlignCenter() ){ vnode->setAlignment( "AlignCenter" ); } else if ( isAlignTop() ){ vnode->setAlignment( "AlignTop" ); } else if ( isAlignBottom() ){ vnode->setAlignment( "AlignBottom" ); } else { vnode->setAlignment( "UnknownAlignment"); } vnode->setToleranceRatioH(_toleranceRatioH); vnode->setToleranceRatioW(_toleranceRatioW); vnode->setToleranceBandH(_toleranceBandH); vnode->setToleranceBandW(_toleranceBandW); if (!_symmetries.empty()){ for (list >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++){ vnode->addSymmetry((*it).first, (*it).second); } } for (vector::iterator it2 = _children.begin(); it2 != _children.end(); it2++){ vnode->push_back( (*it2)->toOpenChams() ); } return vnode; } void VSlicingNode::createSlicingRouting() // Needs to be change in case of not alternative H/V { if ( isPlaced() ){ int numberChildren = getNbChild(); vector::iterator it1 = _children.begin(); DbU::Unit x = this->getX(); DbU::Unit y = this->getY(); DbU::Unit widthValue = 0; if (_parent){ if ( _parent->getType() == HorizontalSNode ){ if ( (this->getAlignment() == AlignLeft) || (this->getAlignment() == AlignRight) ){ widthValue = _parent->getWidth() - this->getWidth(); } else if ( this->getAlignment() == AlignCenter ){ widthValue = (_parent->getWidth() - this->getWidth())/2; } } } DbU::Unit vpitch = _rg->getVerticalPitch(); if (widthValue % vpitch) cerr << Warning( "VSlicingNode::createSlicingRouting(): On %s, width is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(widthValue).c_str() , DbU::getValueString(vpitch).c_str() ) << endl; for (int i = 0; i < numberChildren+1; ++i){ RVSlicingNode* rnode = NULL; if ( i == 0 ){ if ( (this->getAlignment() == AlignRight) || (this->getAlignment() == AlignCenter) ){ rnode = RVSlicingNode::create( widthValue ); } else { rnode = RVSlicingNode::create(); } } else if ( i == numberChildren ){ if ( (this->getAlignment() == AlignLeft) || (this->getAlignment() == AlignCenter) ){ rnode = RVSlicingNode::create( widthValue ); } else { rnode = RVSlicingNode::create(); } } else { rnode = RVSlicingNode::create(); } rnode->setParent(this); if (i == 0){ if ( this->getAlignment() == AlignLeft ){ rnode->place(x, y); } else if ( (this->getAlignment() == AlignCenter) || (this->getAlignment() == AlignRight)) { rnode->place(x-widthValue, y); } } else { rnode->place(x, y); } _slicingRouting.push_back(rnode); if (i < numberChildren){ x += (*it1)->getWidth(); it1++; } } if (_master){ if (isVSymmetry()){ for (size_t i = 0; i < _slicingRouting.size(); i++){ getSlicingRouting(i)->setMaster(_master->getSlicingRouting(_slicingRouting.size()-1-i)); } } else { for (size_t i = 0; i < _slicingRouting.size(); i++){ getSlicingRouting(i)->setMaster(_master->getSlicingRouting(i)); } } } else if ((_symmetries.empty() == false)&&(isAlignCenter())){ for (size_t i = 0; i < (_slicingRouting.size()/2); i++){ getSlicingRouting(_slicingRouting.size()-1-i)->setMaster(getSlicingRouting(i)); } } for (vector::iterator it = _children.begin(); it != _children.end(); it++){ if ( ((*it)->isHorizontal()) || ((*it)->isVertical()) ){ (*it)->createSlicingRouting(); } } this->setRoutingCreated(RoutingCreated); } } DbU::Unit VSlicingNode::getWidth () const { DbU::Unit vpitch = _rg->getVerticalPitch(); DbU::Unit width = 0; if (isRoutingEstimated()){ for ( SlicingNode* node : _children ) width += node->getWidth(); for ( RHVSlicingNode* node : _slicingRouting ) width += node->getWidth(); } else { if (_boxSet != NULL) width = _boxSet->getWidth(); } if (width % vpitch) cerr << Warning( "VSlicingNode::getWidth(): On %s, width is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(width).c_str() , DbU::getValueString(vpitch).c_str() ) << endl; return width; } DbU::Unit VSlicingNode::getHeight () const { DbU::Unit hpitch = _rg->getHorizontalPitch(); DbU::Unit height = 0; if (isRoutingEstimated()) { SlicingNode* m = NULL; for ( SlicingNode* node : _children ) { if (node->getType() != RoutingSNode) { if (node->getHeight() > height) { height = node->getHeight(); m = node; } } } if (m->isDevice()) height += hpitch*2; } else { if (_boxSet != NULL) height = _boxSet->getHeight(); } if (height % hpitch) cerr << Warning( "VSlicingNode::getHeight(): On %s, height is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(height).c_str() , DbU::getValueString(hpitch).c_str() ) << endl; return height; } void VSlicingNode::setGCell ( Anabatic::GCell* gcell ) { cdebug_log(535,1) << "VSlicingNode::setGCell(Anabatic::GCell*) " << gcell << endl; Anabatic::GCell* prevGCell = gcell; Anabatic::GCell* nextGCell = NULL; vector::const_iterator itc = _children.begin(); vector::const_iterator its = _slicingRouting.begin(); int index = 0; DbU::Unit x = (*its)->getX(); while ( not ((itc == _children.end()) and (its+1 == _slicingRouting.end())) ) { if (index%2 == 0) { x += (*its)->getWidth(); nextGCell = prevGCell->vcut( x ); (*its)->setGCell( prevGCell ); its++; } else { x += (*itc)->getWidth(); nextGCell = prevGCell->vcut( x ); (*itc)->setGCell( prevGCell ); itc++; } prevGCell = nextGCell; index++; } (*its)->setGCell( prevGCell ); cdebug_tabw(535,-1); } void VSlicingNode::adjustBorderChannels () { if (_parent){ DbU::Unit space = _parent->getWidth() - getWidth(); if ( this->getAlignment() == AlignRight ){ RHVSlicingNode* ch = (*_slicingRouting.begin()); ch->setWidth(ch->getWidth()+space); } else if ( this->getAlignment() == AlignCenter ){ RHVSlicingNode* chf = (*_slicingRouting.begin()); RHVSlicingNode* chl = (*(_slicingRouting.end()-1)); chf->setWidth(chf->getWidth()+space/2); chl->setWidth(chl->getWidth()+space/2); } else if ( this->getAlignment() == AlignLeft ){ RHVSlicingNode* ch = (*(_slicingRouting.end()-1)); ch->setWidth(ch->getWidth()+space); } } for (vector::iterator it = _children.begin(); it != _children.end(); it++){ (*it)->adjustBorderChannels(); } } string VSlicingNode::_getString () const { string s = Super::_getString(); return s; } string VSlicingNode::_getTypeName () const { return "VSlicingNode"; } // -----------------------------------------------------------------------------------------------// // Class : DSlicingNode // -----------------------------------------------------------------------------------------------// int DSlicingNode::_count = 0; int DSlicingNode::_countAll = 0; DSlicingNode::DSlicingNode( unsigned int type , NodeSets* nodeSets , unsigned int alignment , Instance* instance , BoxSet* boxSet ): SlicingNode( type, nodeSets, alignment, boxSet ) , _instance(instance) {} DSlicingNode::~DSlicingNode(){} DSlicingNode* DSlicingNode::create( NodeSets* nodeSets , unsigned int alignment , Instance* instance , BoxSet* boxSet ) { _count++; _countAll++; return new DSlicingNode( DeviceSNode, nodeSets, alignment, instance, boxSet ); } void DSlicingNode::print() const { cerr << "- Print from Slicing Node - " << endl; cerr << "SlicingType: Device Node" << endl; if (this->isAlignLeft ()){ cerr << "Alignment : Left" << endl; } else if (this->isAlignCenter()){ cerr << "Alignment : Middle" << endl; } else if (this->isAlignRight ()){ cerr << "Alignment : Right" << endl; } else if (this->isAlignTop ()){ cerr << "Alignment : Top" << endl; } else if (this->isAlignBottom()){ cerr << "Alignment : Bottom" << endl; } else { cerr << "Alignment : Unknown" << endl; } cerr << "NFingers : " << getNFing() << endl; if (_instance != NULL){ cerr << "Instance : " << _instance << endl; } else { cerr << "Instance : None" << endl; } SlicingNode::print(); } DSlicingNode* DSlicingNode::clone( unsigned int tr ) { DSlicingNode* node = DSlicingNode::create( _nodeSets->clone() , this->getAlignment() , this->getInstance() , this->getBoxSet() ); node->setPreset(this->getPreset()); node->setSet (this->getSet() ); node->setPlaced(this->getPlaced()); return node; } void DSlicingNode::setNFing( int nfing ) { if (_nodeSets->find(nfing) != _nodeSets->end()){ _boxSet = (*_nodeSets->find(nfing)); } else { _boxSet = (*_nodeSets->begin()); } } int DSlicingNode::getNFing() const { if (_boxSet != NULL) { return _boxSet->getNFing(); } else { return 1; } } double DSlicingNode::getStartParameter() const { return _nodeSets->getStartParameter(); } double DSlicingNode::getStepParameter() const { return _nodeSets->getStepParameter(); } double DSlicingNode::getCountParameter() const { return _nodeSets->getCountParameter(); } void DSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace ) { cdebug_log(536,1) << "void DSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )" << endl; if (replace){ SlicingNode::place(x,y); if (_instance != NULL){ Cell* model = _instance->getMasterCell(); _instance->setTransformation(Transformation( _x - model->getAbutmentBox().getXMin(), _y - model->getAbutmentBox().getYMin())); _instance->setPlacementStatus(Instance::PlacementStatus::PLACED); } } else { if (isSet()){ SlicingNode::place(x,y); if (_instance != NULL){ Cell* model = _instance->getMasterCell(); Device* dev = dynamic_cast(model); if (dev) { TransistorFamily* tf = dynamic_cast(dev); if (tf) { tf->setNfing( this->getNFing() ); FormFactorParameter* pff = NULL; if ( (pff = dynamic_cast(tf->getParameter("M"))) != NULL ) { pff->setValue( tf->getNfing() ); } shared_ptr layoutGenerator ( new LayoutGenerator() ); layoutGenerator->setDevice(dev); layoutGenerator->drawLayout(); } } _instance->setTransformation(Transformation( _x - model->getAbutmentBox().getXMin(), _y - model->getAbutmentBox().getYMin())); _instance->setPlacementStatus(Instance::PlacementStatus::PLACED); } } } cdebug_tabw(536,-1); } void DSlicingNode::place( DbU::Unit x, DbU::Unit y ) { DSlicingNode::_place(x, y); } void DSlicingNode::preDestroy() { _count--; SlicingNode::preDestroy(); } void DSlicingNode::destroy() { DSlicingNode::preDestroy(); delete(this); } void DSlicingNode::preRecursiveDestroy() { _count--; SlicingNode::preRecursiveDestroy(); } void DSlicingNode::recursiveDestroy() { DSlicingNode::preRecursiveDestroy(); delete(this); } OpenChams::SlicingNode* DSlicingNode::toOpenChams() { OpenChams::SlicingNode* dnode = OpenChams::DSlicingNode::create(_instance->getName()._getString()); if ( isAlignLeft() ){ dnode->setAlignment("AlignLeft" ); } else if ( isAlignRight() ){ dnode->setAlignment("AlignRight" ); } else if ( isAlignCenter() ){ dnode->setAlignment("AlignCenter" ); } else if ( isAlignTop() ){ dnode->setAlignment("AlignTop" ); } else if ( isAlignBottom() ){ dnode->setAlignment("AlignBottom" ); } else { dnode->setAlignment("UnknownAlignment"); } string strue = "true"; string sfalse = "false"; if( isPreset() ){ dnode->setPreset( strue ); } else { dnode->setPreset( sfalse ); } dnode->setX ( _x ); dnode->setY ( _y ); dnode->setNFing ( getNFing() ); dnode->setStart ( getStartParameter() ); dnode->setStep ( getStepParameter() ); dnode->setCount ( getCountParameter() ); return dnode; } bool DSlicingNode::checkInitialPlacement ( int& cpt ) const { // -----------------------------------------------------------------------------------------------// // Notes:: Initial placement criteria is having at least 2 devices placed at (x, y) = (0, 0) // -----------------------------------------------------------------------------------------------// bool initialPlacement = false; if ( cpt < 2 ){ if ( (_x == 0) && (_y == 0) ){ cpt++; if ( cpt < 2 ) { initialPlacement = true; } } else { initialPlacement = true; } } return initialPlacement; } void DSlicingNode::setGCell( Anabatic::GCell* gcell ) { cdebug_log(535,0) << "DSlicingNode::setGCell(Anabatic::GCell*) " << gcell << endl; if (getParent() != NULL) { if (getParent()->getType() == HorizontalSNode) { if (getAlignment() == AlignLeft) { Anabatic::GCell* rightc = gcell->vcut( getX() + getWidth() ); _gcell = gcell; rightc->setType( Anabatic::Flags::StrutGCell ); } else if (getAlignment() == AlignCenter) { _gcell = gcell->vcut( getX() ); Anabatic::GCell* rightc = _gcell->vcut( this->getX() + this->getWidth() ); gcell->setType ( Anabatic::Flags::StrutGCell ); rightc->setType( Anabatic::Flags::StrutGCell ); } else if (getAlignment() == AlignRight ){ _gcell = gcell->vcut( getX() ); gcell->setType( Anabatic::Flags::StrutGCell ); } } else if (getParent()->getType() == VerticalSNode) { if (getAlignment() == AlignBottom){ Anabatic::GCell* topc = gcell->hcut(this->getY()+this->getHeight()); _gcell = gcell; topc->setType( Anabatic::Flags::StrutGCell ); } else if (getAlignment() == AlignCenter) { _gcell = gcell->hcut( getY() ); Anabatic::GCell* topc = _gcell->hcut( getY() + getHeight() ); gcell->setType( Anabatic::Flags::StrutGCell ); topc->setType ( Anabatic::Flags::StrutGCell ); } else if (getAlignment() == AlignTop) { _gcell = gcell->hcut( this->getY() ); gcell->setType( Anabatic::Flags::StrutGCell ); } } else { _gcell = gcell; } } else { _gcell = gcell; } if (_gcell) { if (dynamic_cast(_instance->getMasterCell())){ _gcell->setType( Anabatic::Flags::DeviceGCell ); } else { _gcell->setType( Anabatic::Flags::MatrixGCell ); if( (_gcell->getWidth() > Anabatic::Session::getSliceHeight()) and(_gcell->getHeight() > Anabatic::Session::getSliceHeight()) ) { _gcell->doGrid(); } } } cdebug_log(535,0) << "> Device:" << _instance << endl; cdebug_log(535,0) << "> GCell: " << _gcell << endl; } bool DSlicingNode::isSame ( SlicingNode* node, unsigned int flags ) const { bool isSame = _nodeSets->compare( node->getNodeSets(), flags ); if (not isSame and (flags & ShowDiff)) cerr << "DSlicingNode::isSame() Check " << this << " vs. " << node << endl; return isSame; } bool DSlicingNode::isSymmetric( SlicingNode* node, unsigned int symmetryType, unsigned int flags ) const { bool isSame = _nodeSets->compare( node->getNodeSets(), flags ); if (not isSame and (flags & ShowDiff)) cerr << "[WARNING] DSlicingNode::isSymmetric(): Different nodesets Check " << this << " vs. " << node << endl; if (_instance != NULL){ Cell* model1 = _instance->getMasterCell(); Cell* model2 = node->getInstance()->getMasterCell(); Device* dev1 = dynamic_cast(model1); Device* dev2 = dynamic_cast(model2); if ((dev1 != NULL) && (dev2 !=NULL)){ CommonSourcePair* csp1 = dynamic_cast(model1); DifferentialPair* dp1 = dynamic_cast(model1); Transistor* ts1 = dynamic_cast(model1); CommonSourcePair* csp2 = dynamic_cast(model2); DifferentialPair* dp2 = dynamic_cast(model2); Transistor* ts2 = dynamic_cast(model2); if ((csp1 != NULL) && (csp2 != NULL)) isSame = csp1->isSame(csp2); else if ((dp1 != NULL) && (dp2 != NULL)) isSame = dp1->isSame(dp2); else if ((ts1 != NULL) && (ts2 != NULL)) isSame = ts1->isSame(ts2); else isSame = false; } if (not(isSame)) cerr << "[WARNING] DSlicingNode::isSymmetric(): Different devices. Check " << this << " vs. " << node << endl; } return isSame; } void DSlicingNode::updateMatrixGCellPosition() { DbU::Unit tx = getX()-_gcell->getXMin(); DbU::Unit ty = getY()-_gcell->getYMin(); Anabatic::GCell* ygcell = _gcell; Anabatic::GCell* xgcell = ygcell; while (ygcell){ while(xgcell){ xgcell->setSouthWestCorner( xgcell->getXMin()+tx, xgcell->getYMin()+ty ); if (xgcell->getEast()->isMatrix()) xgcell = xgcell->getEast(); else xgcell = NULL; } if (ygcell->getNorth()->isMatrix()) ygcell = ygcell->getNorth(); else ygcell = NULL; xgcell = ygcell; } } void DSlicingNode::updateMatrixGContacts() { Anabatic::GCell* ygcell = _gcell; Anabatic::GCell* xgcell = ygcell; while (ygcell){ while(xgcell){ xgcell->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); if (xgcell->getEast()->isMatrix()) xgcell = xgcell->getEast(); else xgcell = NULL; } if (ygcell->getNorth()->isMatrix()) ygcell = ygcell->getNorth(); else ygcell = NULL; xgcell = ygcell; } } void DSlicingNode::updateGCellPosition() { cdebug_log(535,0) << "DSlicingNode::updateGCellPosition() " << _gcell << endl; if (_gcell) { if (_parent) { if (_parent->getType() == HorizontalSNode) { DbU::Unit hpitch = _rg->getHorizontalPitch(); if (getAlignment() == AlignLeft) { _gcell->getEastNMatrix()->setSouthWestCorner( getX()+getWidth(), getY() ); _gcell->getEastNMatrix()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/hpitch) , floor(getHeight()/hpitch) ); } else if (getAlignment() == AlignCenter) { _gcell->getWest()->setSouthWestCorner( _parent->getX(), getY() ); _gcell->getWest()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/(2*hpitch)) , floor(getHeight()/(2*hpitch)) ); _gcell->getEastNMatrix()->setSouthWestCorner( getX()+getWidth(), getY() ); _gcell->getEastNMatrix()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/(2*hpitch)) , floor(getHeight()/(2*hpitch)) ); } else if (getAlignment() == AlignRight) { _gcell->getWest()->setSouthWestCorner( _parent->getX(), getY() ); _gcell->getWest()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/hpitch) , floor(getHeight()/hpitch) ); } } else if (_parent->getType() == VerticalSNode) { DbU::Unit vpitch = _rg->getVerticalPitch(); if (getAlignment() == AlignBottom) { _gcell->getNorthNMatrix()->setSouthWestCorner( getX(), getY()+getHeight() ); _gcell->getNorthNMatrix()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/vpitch) , floor(getWidth()/vpitch) ); } else if (getAlignment() == AlignCenter) { _gcell->getSouth()->setSouthWestCorner( getX(), _parent->getY() ); _gcell->getSouth()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/(2*vpitch)) , floor(getWidth()/(2*vpitch)) ); _gcell->getNorthNMatrix()->setSouthWestCorner( getX(), getY()+getHeight() ); _gcell->getNorthNMatrix()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/(2*vpitch)) , floor(getWidth()/(2*vpitch)) ); } else if (getAlignment() == AlignTop) { _gcell->getSouth()->setSouthWestCorner( getX(), _parent->getY() ); _gcell->getSouth()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/vpitch) , floor(getWidth()/vpitch) ); } } } if (_gcell->isMatrix()) this->updateMatrixGCellPosition(); else _gcell->setSouthWestCorner( getX(), getY() ); cdebug_log(535,0) << "| Updated:" << _gcell << endl; } } void DSlicingNode::updateGContacts() { cdebug_log(535,0) << "DSlicingNode::updateGContacts() " << _gcell << endl; if (_gcell) { if (_parent) { if (_parent->getType() == HorizontalSNode) { if (getAlignment() == AlignLeft) { _gcell->getEastNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); } else if (getAlignment() == AlignCenter) { _gcell->getWest()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); _gcell->getEastNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); } else if (getAlignment() == AlignRight) { _gcell->getWest()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); } } else if (_parent->getType() == VerticalSNode) { if (getAlignment() == AlignBottom) { _gcell->getNorthNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); } else if (getAlignment() == AlignCenter) { _gcell->getSouth()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); _gcell->getNorthNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); } else if (getAlignment() == AlignTop) { _gcell->getSouth()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); } } } if (_gcell->isMatrix()) this->updateMatrixGContacts(); else _gcell->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal ); cdebug_log(535,0) << "| Updated:" << _gcell << endl; } } void DSlicingNode::restrictDevices() { if (_gcell){ Anabatic::Vertex* vertex = _gcell->getObserver< Anabatic::Vertex>( Anabatic::GCell::Observable::Vertex); vertex->setRestricted(); if (!vertex->hasValidStamp()){ if ((_gcell->getWidth() > _gcell->getHeight())||(_gcell->getWidth() == _gcell->getHeight())) { vertex->unsetFlags(Anabatic::Vertex::iVertical); vertex->setFlags(Anabatic::Vertex::iHorizontal); } else { vertex->unsetFlags(Anabatic::Vertex::iHorizontal); vertex->setFlags(Anabatic::Vertex::iVertical ); } } } } void DSlicingNode::printLine() const { cerr << "Instance: " << _instance << ", " ; SlicingNode::printLine(); } string DSlicingNode::_getString () const { string s = Super::_getString(); s.insert( s.size()-1, " "+getString(_instance->getName())); return s; } string DSlicingNode::_getTypeName () const { return "DSlicingNode"; } bool DSlicingNode::isAnalog () const { if (_instance){ Cell* model = _instance->getMasterCell(); Device* dev = dynamic_cast(model); if (dev) return true; else return false; } else return false; } bool DSlicingNode::isDigital () const { return (not (isAnalog())); } bool DSlicingNode::checkCellInstances ( Cell* cell ){ if (_instance){ if (cell->getInstance(_instance->getName())) return true; else return false; } else return false; } // -----------------------------------------------------------------------------------------------// // Class : RHVSlicingNode // -----------------------------------------------------------------------------------------------// int RHVSlicingNode::_count = 0; int RHVSlicingNode::_countAll = 0; RHVSlicingNode::RHVSlicingNode(): SlicingNode( RoutingSNode, NodeSets::create(), UnknownAlignment, NULL ) , _railInstance(NULL) { this->setPreset(Preset); this->setSet (Set ); this->setOverCell(OverCell); _wireOccupation = ChannelRouting::create(); } RHVSlicingNode::~RHVSlicingNode(){} void RHVSlicingNode::print() const { cerr << "- Print from Slicing Node - " << endl; if (_railInstance) cerr << "RailInstace: " << _railInstance << endl; SlicingNode::print(); } void RHVSlicingNode::_setGlobalSize ( DbU::Unit height, DbU::Unit width ){} void RHVSlicingNode::preDestroy() { _count--; SlicingNode::preDestroy(); if(_wireOccupation) _wireOccupation->destroy(); } void RHVSlicingNode::destroy() { RHVSlicingNode::preDestroy(); delete(this); } void RHVSlicingNode::preRecursiveDestroy() { _count--; SlicingNode::preRecursiveDestroy(); } void RHVSlicingNode::recursiveDestroy() { RHVSlicingNode::preRecursiveDestroy(); delete(this); } void RHVSlicingNode::resetSize() { _boxSet->setHeight( _minHeight ); _boxSet->setWidth ( _minWidth ); } bool RHVSlicingNode::isSame( SlicingNode* node, unsigned int flags ) const { return ( (this->getHeight() == node->getHeight())&& (this->getWidth() == node->getWidth()) ); } bool RHVSlicingNode::isSymmetric( SlicingNode* node, unsigned int symmetryType, unsigned int flags ) const { return ( (this->getHeight() == node->getHeight())&& (this->getWidth() == node->getWidth()) ); } void RHVSlicingNode::setRailInstance(Hurricane::Instance* i) { _railInstance = i; } void RHVSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace ) { SlicingNode::_place(x,y,replace); if (_railInstance){ Net* net = NULL; int t = 0; for (Net* n : _railInstance->getMasterCell()->getNets()) { net = n; t++; } if (t != 1) cerr << "Error(void RHVSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )): Several Nets in Rail Instance Cell." << endl; Component* component = NULL; t = 0; for (Component* c : net->getComponents()){ component = c; t++; } if (t != 1) cerr << "Error(void RHVSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )): Several Components in Rail Instance Cell." << endl; Horizontal* h = dynamic_cast(component); Vertical* v = dynamic_cast (component); UpdateSession::open(); if (h){ h->setDxSource(0); h->setDxTarget(getRootWidth()); _railInstance->getMasterCell()->setAbutmentBox(Box( 0, 0, getRootWidth(), getHeight() )); _railInstance->setTransformation(Transformation( _cell->getAbutmentBox().getXMin(), getY() ) ); } else if (v){ v->setDySource(0); v->setDyTarget(getRootHeight()); _railInstance->getMasterCell()->setAbutmentBox(Box( 0, 0, getWidth(), getRootHeight() )); _railInstance->setTransformation(Transformation( getX(), _cell->getAbutmentBox().getYMin() ) ); } else { cerr << "Error(void RHVSlicingNode::_place( DbU::Unit x = 0, DbU::Unit y = 0, bool replace = false )): Unknown segment type." << endl; } _railInstance->setPlacementStatus(Instance::PlacementStatus::PLACED); UpdateSession::close(); } } void RHVSlicingNode::addWireOccupation( DbU::Unit min, DbU::Unit max ) { //cerr << "addWireOccupation min:" << DbU::getPhysical(min, DbU::Micro) << ", max:" << DbU::getPhysical(max, DbU::Micro) << ", MaxCount: " << _wireOccupation->getMaxCount() << endl; if (_wireOccupation) { if (min == max){/* RHSlicingNode* h = dynamic_cast(this); RVSlicingNode* v = dynamic_cast(this); if (h) { _wireOccupation->insertChannel(getX(), getX()+getWidth()); } else if (v) { _wireOccupation->insertChannel(getY(), getY()+getHeight()); }*/ } else { _wireOccupation->insertChannel(min, max); } } //cerr << "NewMaxCount:" << _wireOccupation->getMaxCount() << endl; //_wireOccupation->print(); //printLine(); } void RHVSlicingNode::resetWireOccupation() { if (_wireOccupation) _wireOccupation->reset(); } int RHVSlicingNode::getMaxWireOccupation() { if (_wireOccupation) return _wireOccupation->getMaxCount()+1; else return 0; } // Error Message Methods unsigned int RHVSlicingNode::getAlignment() const { cerr << " Error(unsigned int getAlignment () const): Routing does not have centering type." << endl; return UnknownAlignment; } NodeSets* RHVSlicingNode::getNodeSets() const { cerr << " Error(NodeSets* getNodeSets() const): Routing does not have different dimensions." << endl; return NULL; } BoxSet* RHVSlicingNode::getPairH( DbU::Unit height ) const { cerr << " Error(BoxSet* getPairH ( DbU::Unit height ) const): Routing does not have different dimensions." << endl; return _boxSet; } BoxSet* RHVSlicingNode::getPairHW( DbU::Unit height, DbU::Unit width ) const { cerr << " Error(BoxSet* RHVSlicingNode::getPairHW( DbU::Unit height, DbU::Unit width ) const): Routing does not have different dimensions." << endl; return _boxSet; } void RHVSlicingNode::setPairH( DbU::Unit height ) { cerr << " Error(void setPairH ( DbU::Unit height )): Routing does not have different dimensions." << endl; } void RHVSlicingNode::setPairHW( DbU::Unit height, DbU::Unit width ) { cerr << " Error(void setPairHW ( DbU::Unit height, DbU::Unit width )): Routing does not have different dimensions." << endl; } // -----------------------------------------------------------------------------------------------// // Class : RHSlicingNode // -----------------------------------------------------------------------------------------------// RHSlicingNode::RHSlicingNode( DbU::Unit height ): RHVSlicingNode() { RHBoxSet* node = RHBoxSet::create(height); _nodeSets->push_back(node); _boxSet = node; _minHeight = height; if (_parent != NULL){ _minWidth = _parent->getWidth(); } else { _minWidth = 0; } DbU::Unit hpitch = _rg->getHorizontalPitch(); if (height % hpitch) cerr << Warning( "RHSlicingNode::RHSlicingNode(): On %s, height is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(height).c_str() , DbU::getValueString(hpitch).c_str() ) << endl; } RHSlicingNode::RHSlicingNode( Hurricane::Instance* i ): RHVSlicingNode() { RHBoxSet* node = RHBoxSet::create(i->getMasterCell()->getAbutmentBox().getHeight()); _nodeSets->push_back(node); _boxSet = node; _minHeight = i->getMasterCell()->getAbutmentBox().getHeight(); setRailInstance(i); if (_parent != NULL){ _minWidth = _parent->getWidth(); } else { _minWidth = 0; } } RHSlicingNode::~RHSlicingNode(){}; RHSlicingNode* RHSlicingNode::create( DbU::Unit height ) { _count++; _countAll++; return new RHSlicingNode(height); } RHSlicingNode* RHSlicingNode::create( Hurricane::Net* net,Hurricane::Layer* layer, int npitch, string cname, string iname ) { //cerr << "RHSlicingNode::Create (Layer and co)" << endl; Cell* cell = Hurricane::Cell::create(Hurricane::DataBase::getDB()->getRootLibrary(), cname); Net* subnet = Hurricane::Net::create(cell, net->getName()); DbU::Unit height = CRL::AllianceFramework::get()->getRoutingGauge()->getHorizontalPitch()* npitch; subnet->setExternal(true); Hurricane::Horizontal* h = Hurricane::Horizontal::create( subnet, layer, height/2, height ); NetExternalComponents::setExternal( h ); Hurricane::Instance* instance = Hurricane::Instance::create(_cell, iname, cell); instance->getPlug(subnet)->setNet(net); cell->setAbutmentBox(Box(0, 0, 0, height)); SlicingNode::addRailSegments(h); return new RHSlicingNode(instance); } RHSlicingNode* RHSlicingNode::clone( unsigned int tr ) { RHSlicingNode* node = RHSlicingNode::create(this->getHeight()); return node; } DbU::Unit RHSlicingNode::getWidth () const { //cerr << "DbU::Unit RHSlicingNode::getWidth () const" << endl; if ( (_parent) ){ return _parent->getWidth(); } else { return 0; } } void RHSlicingNode::setHeight( DbU::Unit height ) { _boxSet->setHeight( height ); DbU::Unit hpitch = _rg->getHorizontalPitch(); if (height % hpitch) cerr << Warning( "RHSlicingNode::getHeight(): On %s, height is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(height).c_str() , DbU::getValueString(hpitch).c_str() ) << endl; } OpenChams::SlicingNode* RHSlicingNode::toOpenChams() { OpenChams::SlicingNode* rnode = OpenChams::RSlicingNode::create(this->getHeight()); return rnode; } void RHSlicingNode:: estimateChannelsSize() { if (getRailInstance() == NULL){ if (_gcell){ /*ChannelRouting* c = ChannelRouting::create(); for ( Contact* contact : _gcell->getGContacts() ) { DbU::Unit xmin = contact->getX(); DbU::Unit xmax = contact->getX(); NetRoutingState* state = NetRoutingExtension::get( contact->getNet() ); DbU::Unit wpitch = 1; if (state) wpitch = state->getWPitch(); for ( Component* comp: contact->getSlaveComponents() ){ Vertical* v = dynamic_cast(comp); Horizontal* h = dynamic_cast(comp); if (v){ if (xmin > v->getX()) xmin = v->getX(); if (xmax < v->getX()) xmax = v->getX(); if (xmin < getX()) xmin = getX(); if (xmax > getX()+getWidth()) xmax = getX()+getWidth(); } else if (h){ xmin = getX(); xmax = getX()+getWidth(); } } c->insertChannel(xmin, xmax, wpitch); }*/ /*if (_rg){ DbU::Unit hpitch = _rg->getHorizontalPitch(); if ( c->getMaxCount() > 0 ){ int occupancyH = c->getMaxCount()+1; //+1 for having enough space if (occupancyH%2 != 0) occupancyH++; this->updateMasterSize( occupancyH*hpitch ); } else this->updateMasterSize( 2*hpitch ); this->setRoutingEstimated(RoutingEstimated); } else { cerr << "Error(void RHSlicingNode::estimateChannelsSize()): Technology missing." << endl; }*/ if (_rg){ DbU::Unit hpitch = _rg->getHorizontalPitch(); if ( getMaxWireOccupation()> 0 ){ int occupancyH = getMaxWireOccupation (); //+1 for having enough space if (occupancyH%2 != 0) occupancyH++; this->updateMasterSize( occupancyH*hpitch ); } else this->updateMasterSize( 2*hpitch ); this->setRoutingEstimated(RoutingEstimated); } else { cerr << "Error(void RHSlicingNode::estimateChannelsSize()): Technology missing." << endl; } } } } void RHSlicingNode::_expandRoutingChannel () { SlicingNode* master = this; while ( master->getMaster() != NULL ) master = master->getMaster(); // cerr << "RHSlicingNode::_expandRoutingChannel() " << this // << " to " << DbU::getValueString( master->getHeight() ) << endl; setHeight( master->getHeight() ); setRoutingEstimated( RoutingEstimated ); } void RHSlicingNode::expandRoutingChannel ( DbU::Unit height, DbU::Unit width ) { // cerr << "RHSlicingNode::expandRoutingChannel(DbU::Unit h, DbU::Unit w) " << this // << " to " << DbU::getValueString( height ) << endl; setHeight( height ); setRoutingEstimated( RoutingEstimated ); } void RHSlicingNode::updateMasterSize( DbU::Unit size ) { SlicingNode* master = this; while(master->getMaster() != NULL) master = master->getMaster(); if (master->getHeight() < size) master->setHeight(size); } void RHSlicingNode::setGCell( Anabatic::GCell* gcell ) { _gcell = gcell; if (_gcell) { if (_railInstance) _gcell->setType( Anabatic::Flags::HRailGCell ); else _gcell->setType( Anabatic::Flags::HChannelGCell ); } cdebug_log(535,0) << "RHSlicingNode::setGCell() " << _gcell << endl; } // Error Methods void RHSlicingNode::setWidth( DbU::Unit width ) { cerr << "Error(void RHSlicingNode::setWidth( DbU::Unit width )): Routing does not have width." << endl; } string RHSlicingNode::_getTypeName () const { return "RHSlicingNode"; } // -----------------------------------------------------------------------------------------------// // Class : RVSlicingNode // -----------------------------------------------------------------------------------------------// RVSlicingNode::RVSlicingNode( DbU::Unit width ): RHVSlicingNode() { RVBoxSet* node = RVBoxSet::create(width); _nodeSets->push_back(node); _boxSet = node; _minWidth = width; if (_parent != NULL){ _minHeight = _parent->getHeight(); } else { _minHeight = 0; } DbU::Unit vpitch = _rg->getVerticalPitch(); if (width % vpitch) cerr << Warning( "RVSlicingNode::RVSlicingNode(): On %s, width is not pitched (%s, pitch:%s)." , getString(this).c_str() , DbU::getValueString(width).c_str() , DbU::getValueString(vpitch).c_str() ) << endl; } RVSlicingNode::RVSlicingNode( Hurricane::Instance* i ): RHVSlicingNode() { RVBoxSet* node = RVBoxSet::create(i->getMasterCell()->getAbutmentBox().getWidth()); _nodeSets->push_back(node); _boxSet = node; _minHeight = i->getMasterCell()->getAbutmentBox().getWidth(); setRailInstance(i); if (_parent != NULL){ _minWidth = _parent->getWidth(); } else { _minWidth = 0; } } RVSlicingNode::~RVSlicingNode(){}; RVSlicingNode* RVSlicingNode::create( DbU::Unit width ) { _count++; _countAll++; return new RVSlicingNode(width); } RVSlicingNode* RVSlicingNode::create( Hurricane::Net* net, Hurricane::Layer* layer, int npitch, string cname, string iname ) { //cerr << "RVSlicingNode::Create (Layer and co)" << endl; Cell* cell = Hurricane::Cell::create(Hurricane::DataBase::getDB()->getRootLibrary(), cname); Net* subnet = Hurricane::Net::create(cell, net->getName()); DbU::Unit width = CRL::AllianceFramework::get()->getRoutingGauge()->getVerticalPitch()* npitch; subnet->setExternal(true); Hurricane::Vertical* v = Hurricane::Vertical::create( subnet, layer, width/2, width ); NetExternalComponents::setExternal( v ); Hurricane::Instance* instance = Hurricane::Instance::create(_cell, iname, cell); instance->getPlug(subnet)->setNet(net); cell->setAbutmentBox(Box(0, 0, width, 0)); SlicingNode::addRailSegments(v); return new RVSlicingNode(instance); } RVSlicingNode* RVSlicingNode::clone( unsigned int tr ) { RVSlicingNode* node = RVSlicingNode::create(this->getWidth()); return node; } DbU::Unit RVSlicingNode::getHeight () const { //cerr << "DbU::Unit RVSlicingNode::getHeight () const" << endl; if ( (_parent) ){ return _parent->getHeight(); } else { return 0; } } void RVSlicingNode::setWidth( DbU::Unit width ) { _boxSet->setWidth( width ); } OpenChams::SlicingNode* RVSlicingNode::toOpenChams() { OpenChams::SlicingNode* rnode = OpenChams::RSlicingNode::create(this->getWidth()); return rnode; } void RVSlicingNode::estimateChannelsSize() { if (getRailInstance() == NULL){ if (_gcell){ /*ChannelRouting* c = ChannelRouting::create(); for ( Contact* contact : _gcell->getGContacts() ) { DbU::Unit ymin = contact->getY(); DbU::Unit ymax = contact->getY(); NetRoutingState* state = NetRoutingExtension::get( contact->getNet() ); DbU::Unit wpitch = 1; if (state) wpitch = state->getWPitch(); for ( Component* comp: contact->getSlaveComponents() ){ Vertical* v = dynamic_cast(comp); Horizontal* h = dynamic_cast(comp); if (h){ if (ymin > h->getY()) ymin = h->getY(); if (ymax < h->getY()) ymax = h->getY(); if (ymin < getY()) ymin = getY(); if (ymax > getY()+getHeight()) ymax = getY()+getHeight(); } else if (v){ ymin = getY(); ymax = getY()+getHeight(); } } c->insertChannel(ymin, ymax, wpitch); } if (_rg){ DbU::Unit vpitch = _rg->getVerticalPitch(); if ( c->getMaxCount() > 0 ){ int occupancyV = c->getMaxCount()+1; //+1 for having enough space if (occupancyV%2 != 0) occupancyV++; this->updateMasterSize(occupancyV*vpitch); //this->setWidth(occupancyV*vpitch); } else this->updateMasterSize(2*vpitch); this->setRoutingEstimated(RoutingEstimated); } else { cerr << "Error(void RHSlicingNode::estimateChannelsSize ()): Technology missing." << endl; }*/ if (_rg){ DbU::Unit vpitch = _rg->getVerticalPitch(); if ( getMaxWireOccupation() > 0 ){ int occupancyV = getMaxWireOccupation(); //+1 for having enough space if (occupancyV%2 != 0) occupancyV++; this->updateMasterSize(occupancyV*vpitch); //this->setWidth(occupancyV*vpitch); } else this->updateMasterSize(2*vpitch); this->setRoutingEstimated(RoutingEstimated); } else { cerr << "Error(void RHSlicingNode::estimateChannelsSize ()): Technology missing." << endl; } } } } void RVSlicingNode::_expandRoutingChannel () { SlicingNode* master = this; while(master->getMaster() != NULL) master = master->getMaster(); this->setWidth(master->getWidth()); this->setRoutingEstimated(RoutingEstimated); } void RVSlicingNode::expandRoutingChannel( DbU::Unit height, DbU::Unit width ) { this->setWidth(width); this->setRoutingEstimated(RoutingEstimated); } void RVSlicingNode::setGCell( Anabatic::GCell* gcell ) { _gcell = gcell; if (_gcell) { if (_railInstance) _gcell->setType( Anabatic::Flags::VRailGCell ); else _gcell->setType( Anabatic::Flags::VChannelGCell ); } cdebug_log(535,0) << "RVSlicingNode::setGCell() " << _gcell << endl; } void RVSlicingNode::updateMasterSize( DbU::Unit size ) { SlicingNode* master = this; while(master->getMaster() != NULL) master = master->getMaster(); if (master->getWidth() < size) master->setWidth(size); } // Error Methods void RVSlicingNode::setHeight( DbU::Unit height ) { cerr << "Error(void RVSlicingNode::setHeight( DbU::Unit height )): Routing does not have height." << endl; } string RVSlicingNode::_getTypeName () const { return "RVSlicingNode"; } // -----------------------------------------------------------------------------------------------// // Class : HVSetState // -----------------------------------------------------------------------------------------------// HVSetState::HVSetState( HVSlicingNode* node ): _HVSnode( node ) { _currentSet = vector (); _nextSet = vector (); _nodeSets = NodeSets::create(); _counter = 1; initSet(); initModulos(); } HVSetState::~HVSetState(){} NodeSets* HVSetState::getNodeSets() { _nodeSets->sort(); return _nodeSets; } void HVSetState::print() { int index = 0; cerr << "currentSet:" << endl; vector::iterator it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); cerr << index << ": H = " << node->at((*it2))->getHeight() << ", W = " << node->at((*it2))->getWidth() << endl; it2++; index++; } cerr << "counter = " << _counter << endl; cerr << "end counter = " << _modulos.back()<< endl; cerr << "modulos:" << endl; index = 0; for (vector::iterator it = _modulos.begin(); it != _modulos.end(); it++) { cerr << index << ": modulo = " << (*it) << endl; index++; } _nodeSets->print(); } void HVSetState::initSet() { _nextSet.clear(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ if ( (*it)->isPreset() ) { _nextSet.push_back((*it)->getNodeSets()->findIndex((*it)->getHeight(), (*it)->getWidth())); } else { _nextSet.push_back(0); } } _currentSet = _nextSet; } void HVSetState::initModulos() { // -----------------------------------------------------------------------------------------------// // Notes: Considering a horizontal/vertical node with X children and each children has N possibilities: // child 0: N0 possibilities, // child 1: N1 possibilities, // . // . // . // child X: NX possibilities. // If a child is preset then, it only has 1 possibility and N = 1. So we have: // number of possibilities to be studied = N0 * N1 * ... * NX. // Children are seen like a and modulos are used to know when a child needs to choose its next possibility. // It starts like this: // - child 0 goes through its N0 possibilities // - when child 0 was at its last possibility, it goes back to its first one and child 1 pick its second possibility. // - and we keep going . . . // -----------------------------------------------------------------------------------------------// int modulo = 1; int index = 0; _modulos.clear(); _modulos.push_back(1); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ if ( it != _HVSnode->getChildren().begin() ) { _modulos.push_back(modulo); } if ( (!isSymmetry(index)) && (!(*it)->isPreset()) ){ modulo *= (*it)->getNodeSets()->size(); } index++; } _modulos.push_back(modulo); } void HVSetState::next() { // -----------------------------------------------------------------------------------------------// // Notes: Set the next combination. See notes above. // -----------------------------------------------------------------------------------------------// int index = 0; pair symmetry = pair(); vector::iterator itpair = _nextSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ if ( this->isSymmetry(index, symmetry) ) { (*itpair) = _nextSet[symmetry.first]; } else { if ( (((_counter-1)%_modulos[index]) == _modulos[index]-1) && (!(*it)->isPreset()) ) { if ( (*itpair)+1 != (*it)->getNodeSets()->size() ) { (*itpair)++ ; } else { (*itpair) = 0; } } } index++; itpair++; } _counter += 1; _currentSet = _nextSet; } // -----------------------------------------------------------------------------------------------// // Class : HSetState // -----------------------------------------------------------------------------------------------// HSetState::HSetState( HSlicingNode* node ):HVSetState(node) {} HSetState::~HSetState(){} pair HSetState::getCurrentWs() { // -----------------------------------------------------------------------------------------------// // Notes: Calculate the min and max width of the current combination // Routing nodes need to be taken into account to not calculate a wrong width. // -----------------------------------------------------------------------------------------------// DbU::Unit wmin = 0; DbU::Unit wmax = 0; if (!_currentSet.empty()) { vector< size_t >::const_iterator it2 = _currentSet.begin(); vector::const_iterator it = _HVSnode->getChildren().begin(); while( (wmin == 0) && (it != _HVSnode->getChildren().end()) ){ NodeSets* node = (*it)->getNodeSets(); if ( node->at((*it2))->getWidth() != 0 ) { wmin = node->at((*it2))->getWidth(); } it++; it2++; } it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); if ( (node->at((*it2))->getWidth() < wmin)&&(node->at((*it2))->getWidth() != 0) ) { wmin = node->at((*it2))->getWidth(); } if (node->at((*it2))->getWidth() > wmax) { wmax = node->at((*it2))->getWidth(); } it2++; } } return pair (wmin, wmax); } DbU::Unit HSetState::getCurrentH() { // -----------------------------------------------------------------------------------------------// // Notes: Calculate the height of the current combination // Routing nodes need to be taken into account to not calculate a wrong height. // -----------------------------------------------------------------------------------------------// DbU::Unit currentH = 0; vector< size_t >::const_iterator it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); currentH += node->at((*it2))->getHeight(); it2++; } return currentH; } DbU::Unit HSetState::getCurrentW() { // -----------------------------------------------------------------------------------------------// // Notes: Calculate the width of the current combination // Routing nodes need to be taken into account to not calculate a wrong width. // -----------------------------------------------------------------------------------------------// DbU::Unit currentW = 0; vector< size_t >::const_iterator it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); if (node->at((*it2))->getWidth() > currentW) { currentW = node->at((*it2))->getWidth(); } it2++; } return currentW; } void HSetState::print() { HVSetState::print(); cerr << "currentH = " << getCurrentH() << endl; cerr << "currentW = " << getCurrentW() << endl; cerr << endl; } void HSetState::next() { push_back(); HVSetState::next(); } void HSetState::push_back() { // -----------------------------------------------------------------------------------------------// // Notes: Check if conditions on tolerance are filled. // If yes, add the current set to the NodeSets // -----------------------------------------------------------------------------------------------// pair paireWidths = getCurrentWs(); DbU::Unit width = paireWidths.second; DbU::Unit wmin = paireWidths.first; DbU::Unit height = 0; if ( width - wmin <= _HVSnode->getToleranceBandW() ){ vector vect = vector(); vector::iterator it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); vect.push_back(node->at((*it2))); height += node->at((*it2))->getHeight(); it2++; } _nodeSets->push_back(vect, height, width, HorizontalSNode); // create the BoxSet of the current accepted set } } // -----------------------------------------------------------------------------------------------// // Class : VSetState // -----------------------------------------------------------------------------------------------// VSetState::VSetState( VSlicingNode* node ):HVSetState(node) {} VSetState::~VSetState(){} pair VSetState::getCurrentHs () { // -----------------------------------------------------------------------------------------------// // Notes: Same as HSetState but for Vertical Node. See notes above. // -----------------------------------------------------------------------------------------------// DbU::Unit hmin = 0; DbU::Unit hmax = 0; if (!_currentSet.empty()) { vector::const_iterator it2 = _currentSet.begin(); vector::const_iterator it = _HVSnode->getChildren().begin(); while( (hmin == 0) && (it != _HVSnode->getChildren().end()) ){ NodeSets* node = (*it)->getNodeSets(); if ( node->at((*it2))->getHeight() != 0 ) { hmin = node->at((*it2))->getHeight(); } it++; it2++; } it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); if ( (node->at((*it2))->getHeight() < hmin)&&(node->at((*it2))->getHeight() != 0) ) { hmin = node->at((*it2))->getHeight(); } if (node->at((*it2))->getHeight() > hmax) { hmax = node->at((*it2))->getHeight(); } it2++; } } return pair (hmin, hmax); } DbU::Unit VSetState::getCurrentH() { // -----------------------------------------------------------------------------------------------// // Notes: Same as HSetState but for Vertical Node. See notes above. // -----------------------------------------------------------------------------------------------// DbU::Unit currentH = 0; vector< size_t >::const_iterator it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); if (node->at((*it2))->getHeight() > currentH) { currentH = node->at((*it2))->getHeight(); } it2++; } return currentH; } DbU::Unit VSetState::getCurrentW() { // -----------------------------------------------------------------------------------------------// // Notes: Same as HSetState but for Vertical Node. See notes above. // -----------------------------------------------------------------------------------------------// DbU::Unit currentW = 0; vector< size_t >::const_iterator it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); currentW += node->at((*it2))->getWidth(); it2++; } return currentW; } void VSetState::print() { HVSetState::print(); cerr << "currentH = " << getCurrentH() << endl; cerr << "currentW = " << getCurrentW() << endl; cerr << endl; } void VSetState::next() { push_back(); HVSetState::next(); } void VSetState::push_back() { // -----------------------------------------------------------------------------------------------// // Notes: Same as HSetState but for Vertical Node. See notes above. // -----------------------------------------------------------------------------------------------// pair paireHeights = getCurrentHs(); DbU::Unit height = paireHeights.second; DbU::Unit hmin = paireHeights.first; DbU::Unit width = 0; if (height - hmin <= _HVSnode->getToleranceBandH()){ vector vect = vector(); vector::iterator it2 = _currentSet.begin(); for (vector::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){ NodeSets* node = (*it)->getNodeSets(); vect.push_back(node->at((*it2))); width += node->at((*it2))->getWidth(); it2++; } _nodeSets->push_back(vect, height, width, VerticalSNode); } } // -----------------------------------------------------------------------------------------------// // Class : ChannelRouting // -----------------------------------------------------------------------------------------------// ChannelRouting::ChannelRouting(){} ChannelRouting::~ChannelRouting(){} ChannelRouting* ChannelRouting::create() { return new ChannelRouting(); } void ChannelRouting::destroy() { delete this; } void ChannelRouting::reset() { _limits.clear(); _counts.clear(); } int ChannelRouting::getMaxCount() const { int count = 0; for (vector::const_iterator it = _counts.begin(); it != _counts.end(); it++){ count = max( (*it), count ); } return count; } void pvectF(vector vec) { for (vector::const_iterator it = vec.begin(); it != vec.end(); it++){ cerr << (*it) << " - "; } cerr << endl; } void pvectI(vector vec) { for (vector::const_iterator it = vec.begin(); it != vec.end(); it++){ cerr << (*it) << " - "; } cerr << endl; } void ChannelRouting::insertChannel( DbU::Unit xy1, DbU::Unit xy2, unsigned int w ) { for (unsigned int i = 0; i < w; ++i){ insertChannel(xy1, xy2); } } void ChannelRouting::insertChannel( DbU::Unit xy1, DbU::Unit xy2 ) { DbU::Unit min = xy1; DbU::Unit max = xy2; ; if (_limits.empty()){ _limits.push_back(min); _limits.push_back(max); _counts.push_back(1); } else { if (max < _limits.front()){ _limits.insert(_limits.begin(), max); _limits.insert(_limits.begin(), min); _counts.insert(_counts.begin(), 0); _counts.insert(_counts.begin(), 1); } else if (min > _limits.back ()){ _limits.push_back(min); _limits.push_back(max); _counts.push_back(0); _counts.push_back(1); } else { int index = 0; vector::iterator itL = _limits.begin(); vector::iterator itC = _counts.begin(); if (min < (*itL)){ _limits.insert(itL, min); _counts.insert(itC, 1 ); } else { while( ((*itL) < min) && (itL != _limits.end()) ){ itL++; index++; if (itC != _counts.end()) itC++; } if ((*itL) != min){ _limits.insert(itL, min); _counts.insert(itC, *(itC-1) ); itL = _limits.begin()+index; itC = _counts.begin()+index; } itL = _limits.begin()+index; itC = _counts.begin()+index; while( ((*itL) < max) && (itL != _limits.end()) ){ itL++; index++; if (itC != _counts.end()) { (*itC) += 1; itC++; } } if ( itL != _limits.end() ){ if ((*(itL)) > max){ _limits.insert(itL, max); _counts.insert(itC, *(itC-1)-1 ); } } else { if ((*(itL-1)) != max){ _limits.push_back(max); _counts.push_back(1); } } } } } } void ChannelRouting::print() const { cerr << "limits: "; for (vector::const_iterator it = _limits.begin(); it != _limits.end(); it++){ cerr << DbU::getPhysical((*it), DbU::Micro) << " - "; } cerr << endl; cerr << "count: "; for (vector::const_iterator it = _counts.begin(); it != _counts.end(); it++){ cerr << (*it) << " - "; } cerr << endl; }