// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC 2021-2021, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | E t e s i a n - A n a l y t i c P l a c e r | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | // | C++ Module : "./FlattenPower.cpp" | // +-----------------------------------------------------------------+ #include #include #include "hurricane/configuration/Configuration.h" #include "hurricane/DebugSession.h" #include "hurricane/UpdateSession.h" #include "hurricane/Error.h" #include "hurricane/Warning.h" #include "hurricane/DataBase.h" #include "hurricane/Technology.h" #include "hurricane/BasicLayer.h" #include "hurricane/RegularLayer.h" #include "hurricane/Pad.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/Rectilinear.h" #include "hurricane/RoutingPad.h" #include "hurricane/NetExternalComponents.h" #include "hurricane/NetRoutingProperty.h" #include "hurricane/Instance.h" #include "hurricane/Plug.h" #include "hurricane/Path.h" #include "hurricane/Query.h" #include "crlcore/AllianceFramework.h" #include "crlcore/RoutingGauge.h" #include "etesian/EtesianEngine.h" namespace { using namespace std; using namespace Hurricane; using CRL::AllianceFramework; using CRL::RoutingGauge; using CRL::RoutingLayerGauge; // ------------------------------------------------------------------- // Local Functions. void destroyRing ( Net* net ) { for( RoutingPad* rp : net->getRoutingPads() ) { bool allMasters = true; vector ring; for( Hook* hook : rp->getBodyHook()->getHooks() ) { if (not hook->isMaster()) { allMasters = false; break; } ring.push_back( hook ); } if (allMasters) { for ( auto hook : ring ) { hook->_setNextHook( hook ); } } } } // ------------------------------------------------------------------- // Class : "::GlobalNetTable". class GlobalNetTable { public: GlobalNetTable ( Cell* ); inline Cell* getTopCell () const; Net* getRootNet ( const Net*, Path ) const; inline Net* getVdd () const; inline Net* getVss () const; inline Net* getBlockage () const; inline void setBlockage ( Net* ); private: bool guessGlobalNet ( const Name&, Net* ); private: uint32_t _flags; Name _vddCoreName; Name _vssCoreName; Net* _vdd; Net* _vss; Net* _blockage; Cell* _topCell; }; inline Cell* GlobalNetTable::getTopCell () const { return _topCell; } inline Net* GlobalNetTable::getVdd () const { return _vdd; } inline Net* GlobalNetTable::getVss () const { return _vss; } inline Net* GlobalNetTable::getBlockage () const { return _blockage; } inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; } GlobalNetTable::GlobalNetTable ( Cell* topCell ) : _flags (0) , _vddCoreName() , _vssCoreName() , _vdd (NULL) , _vss (NULL) , _blockage (NULL) , _topCell (topCell) { if (_topCell == NULL) return; cmess1 << " o Looking for powers/grounds & clocks." << endl; for( Net* net : _topCell->getNets() ) { Net::Type netType = net->getType(); if (NetRoutingExtension::isManualDetailRoute(net)) continue; if (NetRoutingExtension::isManualGlobalRoute(net)) continue; if (netType == Net::Type::POWER) { if (_vddCoreName.isEmpty()) { _vddCoreName = net->getName(); _vdd = net; } else { cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n" " (will consider only <%s>)" , getString(net ->getName()).c_str() , getString(_vdd->getName()).c_str() ) << endl; } } if (netType == Net::Type::GROUND) { if (_vssCoreName.isEmpty()) { _vssCoreName = net->getName(); _vss = net; } else { cerr << Error("Second power ground net <%s> net at top block level will be ignored.\n" " (will consider only <%s>)" , getString(net ->getName()).c_str() , getString(_vss->getName()).c_str() ) << endl; } } } if (_vdd == NULL) cerr << Error("Missing POWER net at top block level." ) << endl; else destroyRing( _vdd ); if (_vss == NULL) cerr << Error("Missing GROUND net at top block level." ) << endl; else destroyRing( _vss ); } bool GlobalNetTable::guessGlobalNet ( const Name& name, Net* net ) { if (name == _vddCoreName) { cmess1 << " - Using <" << net->getName() << "> as core (internal:vdd) power net." << endl; _vdd = net; return true; } if (name == _vssCoreName) { cmess1 << " - Using <" << net->getName() << "> as core (internal:vss) ground net." << endl; _vss = net; return true; } return false; } Net* GlobalNetTable::getRootNet ( const Net* net, Path path ) const { cdebug_log(159,0) << " getRootNet:" << path << ":" << net << endl; if (net == _blockage) return _blockage; if (net->getType() == Net::Type::POWER ) return _vdd; if (net->getType() == Net::Type::GROUND) return _vss; return NULL; } class Rails; class Plane; // ------------------------------------------------------------------- // Class : "::Rail". class Rail { public: Rail ( Rails*, DbU::Unit axis, DbU::Unit width ); inline DbU::Unit getAxis () const; inline DbU::Unit getWidth () const; inline Rails* getRails () const; inline uint32_t getDirection () const; inline RoutingLayerGauge* getLayerGauge () const; inline Net* getNet () const; inline const Layer* getLayer () const; void merge ( DbU::Unit source, DbU::Unit target ); void doLayout ( const Layer* ); string _getString () const; private: Rails* _rails; DbU::Unit _axis; DbU::Unit _width; list _chunks; }; void Rail::merge ( DbU::Unit source, DbU::Unit target ) { Interval chunkToMerge ( source, target ); cdebug_log(159,0) << " Rail::merge() " << ((getDirection()==Constant::Horizontal) ? "Horizontal" : "Vertical") << " " << chunkToMerge << endl; cdebug_log(159,0) << " | " << _getString() << endl; list::iterator imerge = _chunks.end(); list::iterator ichunk = _chunks.begin(); while ( ichunk != _chunks.end() ) { if (imerge == _chunks.end()) { if (chunkToMerge.getVMax() < (*ichunk).getVMin()) { cdebug_log(159,0) << " | Insert before " << *ichunk << endl; imerge = _chunks.insert( ichunk, chunkToMerge ); break; } if (chunkToMerge.intersect(*ichunk)) { cdebug_log(159,0) << " | Merge with " << *ichunk << endl; imerge = ichunk; (*imerge).merge( chunkToMerge ); } } else { if (chunkToMerge.getVMax() >= (*ichunk).getVMin()) { (*imerge).merge( *ichunk ); cdebug_log(159,0) << " | Absorb (erase) " << *ichunk << endl; ichunk = _chunks.erase( ichunk ); continue; } else break; } ++ichunk; } if (imerge == _chunks.end()) { _chunks.insert( ichunk, chunkToMerge ); cdebug_log(159,0) << " | Insert at end " << DbU::getValueString(_axis) << " " << chunkToMerge << endl; cdebug_log(159,0) << " | " << _getString() << endl; } } void Rail::doLayout ( const Layer* layer ) { cdebug_log(159,0) << "Doing layout of rail: " << " " << layer->getName() << " " << ((getDirection()==Constant::Horizontal) ? "Horizontal" : "Vertical") << " @" << DbU::getValueString(_axis) << endl; cdebug_log(159,0) << _getString() << endl; Net* net = getNet(); RoutingLayerGauge* rg = getLayerGauge(); Segment* segment = NULL; DbU::Unit extension = layer->getExtentionCap(); cdebug_log(159,0) << " (pitch:" << DbU::getValueString(rg->getPitch()) << " , ww/2:" << DbU::getValueString(rg->getHalfWireWidth()) << ")" << endl; // if ( type == Constant::PinOnly ) { // cdebug_log(159,0) << " Layer is PinOnly." << endl; // return; // } if ( getDirection() == Constant::Horizontal ) { list::iterator ichunk = _chunks.begin(); list::iterator ichunknext = ichunk; ++ichunknext; for ( ; ichunk != _chunks.end() ; ++ichunk, ++ichunknext ) { if (ichunknext != _chunks.end()) { if ((*ichunk).intersect(*ichunknext)) cerr << Error( "Overlaping consecutive chunks in %s %s Rail @%s:\n" " %s" , getString(layer->getName()).c_str() , ((getDirection()==Constant::Horizontal) ? "Horizontal" : "Vertical") , DbU::getValueString(_axis).c_str() , _getString().c_str() ) << endl; } cdebug_log(159,0) << " chunk: [" << DbU::getValueString((*ichunk).getVMin()) << ":" << DbU::getValueString((*ichunk).getVMax()) << "]" << endl; segment = Horizontal::create ( net , layer , _axis , _width , (*ichunk).getVMin()+extension , (*ichunk).getVMax()-extension ); if ( segment and net->isExternal() ) NetExternalComponents::setExternal ( segment ); } } else { list::iterator ichunk = _chunks.begin(); for ( ; ichunk != _chunks.end() ; ichunk++ ) { cdebug_log(159,0) << " chunk: [" << DbU::getValueString((*ichunk).getVMin()) << ":" << DbU::getValueString((*ichunk).getVMax()) << "]" << endl; segment = Vertical::create ( net , layer , _axis , _width , (*ichunk).getVMin()+extension , (*ichunk).getVMax()-extension ); if ( segment and net->isExternal() ) NetExternalComponents::setExternal ( segment ); } } } string Rail::_getString () const { ostringstream os; os << "::const_iterator ichunk = _chunks.begin(); for ( ; ichunk != _chunks.end() ; ++ichunk ) { if (ichunk != _chunks.begin()) os << " "; os << "[" << DbU::getValueString((*ichunk).getVMin()) << " " << DbU::getValueString((*ichunk).getVMax()) << "]"; } os << ">"; return os.str(); } // ------------------------------------------------------------------- // Class : "::RailCompare" & "::RailMatch". class RailCompare { public: bool operator() ( const Rail* lhs, const Rail* rhs ); }; inline bool RailCompare::operator() ( const Rail* lhs, const Rail* rhs ) { if ( lhs->getAxis () < rhs->getAxis () ) return true; if ( lhs->getWidth() < rhs->getWidth() ) return true; return false; } class RailMatch : public unary_function { public: inline RailMatch ( DbU::Unit axis, DbU::Unit width ); inline bool operator() ( const Rail* ); private: DbU::Unit _axis; DbU::Unit _width; }; inline RailMatch::RailMatch ( DbU::Unit axis, DbU::Unit width ) : _axis(axis) , _width(width) { } inline bool RailMatch::operator() ( const Rail* rail ) { return (rail->getAxis() == _axis) and (rail->getWidth() == _width); } // ------------------------------------------------------------------- // Class : "::Rails". class Rails { public: Rails ( Plane*, uint32_t direction, Net* ); ~Rails (); inline Plane* getPlane (); inline uint32_t getDirection () const; inline RoutingLayerGauge* getLayerGauge () const; inline Net* getNet () const; void merge ( const Box& ); void doLayout ( const Layer* ); private: Plane* _plane; uint32_t _direction; Net* _net; vector _rails; }; // Delayed "::Rail" functions. Rail::Rail ( Rails* rails, DbU::Unit axis, DbU::Unit width ) : _rails (rails) , _axis (axis) , _width (width) , _chunks() { cdebug_log(159,0) << " new Rail " << " @" << DbU::getValueString(axis) << " " << getLayer()->getName() << " " << getRails()->getNet() << " " << ((getDirection()==Constant::Horizontal) ? "Horizontal" : "Vertical")<< endl; } inline DbU::Unit Rail::getAxis () const { return _axis; } inline DbU::Unit Rail::getWidth () const { return _width; } inline Rails* Rail::getRails () const { return _rails; } inline uint32_t Rail::getDirection () const { return _rails->getDirection(); } inline RoutingLayerGauge* Rail::getLayerGauge () const { return _rails->getLayerGauge(); } inline Net* Rail::getNet () const { return _rails->getNet(); } // Delayed "::Rail" functions. Rails::Rails ( Plane* plane, uint32_t direction , Net* net ) : _plane (plane) , _direction (direction) , _net (net) , _rails () { cdebug_log(159,0) << " new Rails @" << " " << getLayerGauge()->getLayer()->getName() << " " << net << " " << ((getDirection()==Constant::Horizontal) ? "Horizontal": "Vertical") << endl; } Rails::~Rails () { while ( not _rails.empty() ) { delete (*_rails.begin()); _rails.erase ( _rails.begin() ); } } inline Plane* Rails::getPlane () { return _plane; } inline uint32_t Rails::getDirection () const { return _direction; } inline Net* Rails::getNet () const { return _net; } void Rails::merge ( const Box& bb ) { DbU::Unit axis; DbU::Unit width; DbU::Unit sourceU; DbU::Unit targetU; if (getDirection() == Constant::Horizontal) { axis = bb.getYCenter(); width = bb.getHeight(); sourceU = bb.getXMin(); targetU = bb.getXMax(); } else { axis = bb.getXCenter(); width = bb.getWidth(); sourceU = bb.getYMin(); targetU = bb.getYMax(); } vector::iterator irail = find_if ( _rails.begin(), _rails.end(), RailMatch(axis,width) ); Rail* rail = NULL; if ( irail == _rails.end() ) { rail = new Rail(this,axis,width); _rails.push_back ( rail ); stable_sort ( _rails.begin(), _rails.end(), RailCompare() ); } else { rail = *irail; } rail->merge ( sourceU, targetU ); } void Rails::doLayout ( const Layer* layer ) { cdebug_log(159,0) << "Doing layout of rails: " << layer->getName() << " " << ((_direction==Constant::Horizontal) ? "Horizontal" : "Vertical") << " " << _net->getName() << endl; for ( size_t irail=0 ; irail<_rails.size() ; irail++ ) _rails[irail]->doLayout ( layer ); } // ------------------------------------------------------------------- // Class : "::Plane". class Plane { public: typedef map RailsMap; public: Plane ( const Layer*, RoutingLayerGauge* ); ~Plane (); inline const Layer* getLayer () const; inline uint32_t getDirection () const; inline RoutingLayerGauge* getLayerGauge () const; inline uint32_t getPowerDirection () const; void merge ( const Box&, Net* ); void doLayout (); private: const Layer* _layer; RoutingLayerGauge* _layerGauge; RailsMap _horizontalRails; RailsMap _verticalRails; uint32_t _powerDirection; }; // Delayed ::Rails function. inline const Layer* Rail::getLayer () const { return _rails->getPlane()->getLayer(); } inline RoutingLayerGauge* Rails::getLayerGauge () const { return _plane->getLayerGauge(); } // Delayed ::Rails function. Plane::Plane ( const Layer* layer, RoutingLayerGauge* layerGauge ) : _layer (layer) , _layerGauge (layerGauge) , _horizontalRails() , _verticalRails () , _powerDirection (layerGauge->getDirection()) { cdebug_log(159,0) << "New Plane " << _layer->getName() << " " << _layerGauge << endl; // Hard-coded SxLib gauge. if (_layerGauge->getDepth() == 0) _powerDirection = Constant::Horizontal; } Plane::~Plane () { RailsMap::iterator irail = _horizontalRails.begin(); for ( ; irail != _horizontalRails.end() ; ++irail ) { delete (*irail).second; } irail = _verticalRails.begin(); for ( ; irail != _verticalRails.end() ; ++irail ) { delete (*irail).second; } } inline const Layer* Plane::getLayer () const { return _layer; } inline RoutingLayerGauge* Plane::getLayerGauge () const { return _layerGauge; } inline uint32_t Plane::getDirection () const { return _layerGauge->getDirection(); } inline uint32_t Plane::getPowerDirection () const { return _powerDirection; } void Plane::merge ( const Box& bb, Net* net ) { Rails* rails = NULL; cdebug_log(159,0) << " Plane::merge() " << net->getName() << " " << bb << endl; uint32_t direction = getDirection(); if ( (net->getType() == Net::Type::POWER) or (net->getType() == Net::Type::GROUND) ) direction = getPowerDirection(); if (direction == Constant::Horizontal) { RailsMap::iterator irails = _horizontalRails.find(net); if ( irails == _horizontalRails.end() ) { rails = new Rails( this, Constant::Horizontal, net ); _horizontalRails.insert ( make_pair(net,rails) ); } else rails = (*irails).second; rails->merge ( bb ); } else { RailsMap::iterator irails = _verticalRails.find(net); if ( irails == _verticalRails.end() ) { rails = new Rails( this, Constant::Vertical, net ); _verticalRails.insert ( make_pair(net,rails) ); } else rails = (*irails).second; cdebug_log(159,0) << " Vertical Merging" << endl; rails->merge ( bb ); } } void Plane::doLayout () { cdebug_log(159,0) << "Doing layout of plane: " << _layer->getName() << endl; RailsMap::iterator irails = _horizontalRails.begin(); for ( ; irails != _horizontalRails.end() ; ++irails ) { (*irails).second->doLayout(_layer); } irails = _verticalRails.begin(); for ( ; irails != _verticalRails.end() ; ++irails ) { (*irails).second->doLayout(_layer); } } // ------------------------------------------------------------------- // Class : "::PowerRailsPlanes". class PowerRailsPlanes { public: typedef map PlanesMap; public: PowerRailsPlanes ( Cell*, RoutingGauge* ); ~PowerRailsPlanes (); inline Net* getRootNet ( Net*, Path ); bool hasPlane ( const BasicLayer* ); inline void setBlockageNet ( Net* ); bool setActivePlane ( const BasicLayer* ); inline Plane* getActivePlane () const; inline Plane* getActiveBlockagePlane () const; void merge ( const Box&, Net* ); void doLayout (); private: Cell* _topCell; GlobalNetTable _globalNets; PlanesMap _planes; Plane* _activePlane; Plane* _activeBlockagePlane; }; PowerRailsPlanes::PowerRailsPlanes ( Cell* topCell, RoutingGauge* rg ) : _topCell (topCell) , _globalNets (topCell) , _planes () , _activePlane (NULL) , _activeBlockagePlane(NULL) { for ( RoutingLayerGauge* lg : rg->getLayerGauges() ) { cdebug_log(159,0) << "Gauge: [" << lg->getDepth() << "] " << lg << endl; const BasicLayer* basicLayer = dynamic_cast( lg->getLayer() ); if (not basicLayer) basicLayer = dynamic_cast( lg->getLayer() )->getBasicLayer(); _planes.insert( make_pair(basicLayer,new Plane(lg->getLayer(),lg)) ); //if (lg->getType() == Constant::PinOnly) continue; const BasicLayer* blockageLayer = dynamic_cast( lg->getBlockageLayer() ); if (not blockageLayer) continue; _planes.insert( make_pair(blockageLayer,new Plane(blockageLayer,lg)) ); } } PowerRailsPlanes::~PowerRailsPlanes () { while ( not _planes.empty() ) { delete _planes.begin()->second; _planes.erase ( _planes.begin() ); } } inline Net* PowerRailsPlanes::getRootNet ( Net* net, Path path ) { return _globalNets.getRootNet(net,path); } bool PowerRailsPlanes::hasPlane ( const BasicLayer* layer ) { return (_planes.find(layer) != _planes.end()); } inline void PowerRailsPlanes::setBlockageNet ( Net* blockageNet ) { _globalNets.setBlockage( blockageNet ); } bool PowerRailsPlanes::setActivePlane ( const BasicLayer* layer ) { PlanesMap::iterator iplane = _planes.find(layer); if (iplane == _planes.end()) return false; _activePlane = iplane->second; _activeBlockagePlane = NULL; if (layer->getMaterial() != BasicLayer::Material::blockage) { BasicLayer* blockageLayer = layer->getBlockageLayer(); PlanesMap::iterator ibplane = _planes.find(blockageLayer); if (ibplane != _planes.end()) _activeBlockagePlane = ibplane->second; } return true; } inline Plane* PowerRailsPlanes::getActivePlane () const { return _activePlane; } inline Plane* PowerRailsPlanes::getActiveBlockagePlane () const { return _activeBlockagePlane; } void PowerRailsPlanes::merge ( const Box& bb, Net* net ) { if (not _activePlane) return; Net* topGlobalNet = _globalNets.getRootNet( net, Path() ); if (topGlobalNet == NULL) { cdebug_log(159,0) << "Not a global net: " << net << endl; return; } if ( (topGlobalNet == _globalNets.getBlockage()) and (_activeBlockagePlane != NULL) ) _activeBlockagePlane->merge( bb, topGlobalNet ); else _activePlane->merge( bb, topGlobalNet ); } void PowerRailsPlanes::doLayout () { PlanesMap::iterator iplane = _planes.begin(); for ( ; iplane != _planes.end() ; iplane++ ) iplane->second->doLayout (); } // ------------------------------------------------------------------- // Class : "::QueryPowerRails". class QueryPowerRails : public Query { public: QueryPowerRails ( Cell*, RoutingGauge* ); virtual bool hasGoCallback () const; virtual void setBasicLayer ( const BasicLayer* ); virtual bool hasBasicLayer ( const BasicLayer* ); inline Net* getBlockageNet () const; virtual void goCallback ( Go* ); virtual void rubberCallback ( Rubber* ); virtual void extensionGoCallback ( Go* ); virtual void masterCellCallback (); void addToPowerRail ( const Go* go , const BasicLayer* basicLayer , const Box& area , const Transformation& transformation ); virtual void doQuery (); inline void doLayout (); inline uint32_t getGoMatchCount () const; private: AllianceFramework* _framework; Cell* _topCell; Net* _blockageNet; RoutingGauge* _routingGauge; PowerRailsPlanes _powerRailsPlanes; bool _isBlockagePlane; uint32_t _goMatchCount; }; QueryPowerRails::QueryPowerRails ( Cell* topCell, RoutingGauge* rg ) : Query () , _framework (AllianceFramework::get()) , _topCell (topCell) , _blockageNet (topCell->getNet("blockagenet")) , _routingGauge (rg) , _powerRailsPlanes(topCell,rg) , _isBlockagePlane (false) , _goMatchCount (0) { setCell ( topCell ); setArea ( topCell->getAbutmentBox() ); setBasicLayer ( NULL ); setFilter ( Query::DoTerminalCells|Query::DoComponents ); if (not _blockageNet) { _blockageNet = Net::create( topCell, "blockagenet" ); _blockageNet->setType( Net::Type::BLOCKAGE ); } _powerRailsPlanes.setBlockageNet( _blockageNet ); cmess1 << " o Building power rails." << endl; } inline uint32_t QueryPowerRails::getGoMatchCount () const { return _goMatchCount; } inline Net* QueryPowerRails::getBlockageNet () const { return _blockageNet; } inline void QueryPowerRails::doLayout () { return _powerRailsPlanes.doLayout(); } bool QueryPowerRails::hasBasicLayer ( const BasicLayer* basicLayer ) { return _powerRailsPlanes.hasPlane ( basicLayer ); } void QueryPowerRails::setBasicLayer ( const BasicLayer* basicLayer ) { _isBlockagePlane = (basicLayer) and (basicLayer->getMaterial() == BasicLayer::Material::blockage); _powerRailsPlanes.setActivePlane ( basicLayer ); Query::setBasicLayer ( basicLayer ); } void QueryPowerRails::doQuery () { Plane* activePlane = _powerRailsPlanes.getActivePlane(); if (not activePlane) return; cmess1 << " - PowerRails in " << activePlane->getLayer()->getName() << " ..." << endl; Query::doQuery(); } void QueryPowerRails::masterCellCallback () { } bool QueryPowerRails::hasGoCallback () const { return true; } void QueryPowerRails::goCallback ( Go* go ) { //ltrace(80) << "QueryPowerRails::goCallback() " << go->getId() << ":" << go // << " " << getPath().getName() << endl; addToPowerRail ( go, getBasicLayer(), getArea(), getTransformation() ); } void QueryPowerRails::addToPowerRail ( const Go* go , const BasicLayer* basicLayer , const Box& area , const Transformation& transformation ) { cdebug_log(159,0) << "addToPowerRail: go=" << go << endl; const Component* component = dynamic_cast( go ); if (component) { if ( _framework->isPad(getMasterCell()) and ( (_routingGauge->getLayerDepth(component->getLayer()) < 2) or (component->getLayer()->getBasicLayers().getFirst()->getMaterial() != BasicLayer::Material::blockage) ) ) return; Net* rootNet = _blockageNet; if (not _isBlockagePlane) { rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath()); if (not NetExternalComponents::isExternal(component)) return; } if (not rootNet) { cdebug_log(159,0) << " rootNet is NULL, not taken into account." << endl; return; } cdebug_log(159,0) << " rootNet " << rootNet << " " << go->getCell() << " (" << go->getCell()->isTerminal() << ")" << endl; const Segment* segment = dynamic_cast( component ); if (segment) { _goMatchCount++; cdebug_log(159,0) << " Merging PowerRail element: " << segment << endl; Box bb = segment->getBoundingBox( basicLayer ); transformation.applyOn( bb ); _powerRailsPlanes.merge( bb, rootNet ); } else { const Contact* contact = dynamic_cast( component ); if (contact) { _goMatchCount++; Box bb = contact->getBoundingBox( basicLayer ); transformation.applyOn( bb ); cdebug_log(159,0) << " Merging PowerRail element: " << contact << " bb:" << bb << " " << basicLayer << endl; _powerRailsPlanes.merge( bb, rootNet ); } else { const Pad* pad = dynamic_cast( component ); if (pad) { _goMatchCount++; Box bb = pad->getBoundingBox( basicLayer ); transformation.applyOn( bb ); cdebug_log(159,0) << " Merging PowerRail element: " << pad << " bb:" << bb << " " << basicLayer << endl; _powerRailsPlanes.merge( bb, rootNet ); } else { const Rectilinear* rectilinear = dynamic_cast( component ); if (rectilinear and (rectilinear->getPoints().size() == 5)) { _goMatchCount++; Box bb = rectilinear->getBoundingBox( basicLayer ); transformation.applyOn( bb ); cdebug_log(159,0) << " Merging PowerRail element: " << rectilinear << " bb:" << bb << " " << basicLayer << endl; _powerRailsPlanes.merge( bb, rootNet ); } } } } } } void QueryPowerRails::rubberCallback ( Rubber* ) { } void QueryPowerRails::extensionGoCallback ( Go* ) { } } // anonymous namespace. namespace Etesian { using Hurricane::UpdateSession; using Hurricane::DataBase; using Hurricane::Technology; using Hurricane::BasicLayer; void EtesianEngine::flattenPower () { string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString(); RoutingGauge* rg = AllianceFramework::get()->getRoutingGauge( gaugeName ); if (not rg) throw Error( "EtesianEngine::falttenPower(): No routing gauge named \"%s\"", gaugeName.c_str() ); //DebugSession::open( 150, 160 ); UpdateSession::open(); Technology* technology = DataBase::getDB()->getTechnology(); QueryPowerRails query ( getCell(), rg ); query.setStopCellFlags( Cell::Flags::AbstractedSupply ); for ( BasicLayer* layer : technology->getBasicLayers() ) { if ( (layer->getMaterial() != BasicLayer::Material::metal) and (layer->getMaterial() != BasicLayer::Material::blockage) ) continue; if (not query.hasBasicLayer(layer)) continue; query.setBasicLayer( layer ); query.doQuery (); } query.doLayout(); cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl; getCell()->setFlags( Cell::Flags::AbstractedSupply ); UpdateSession::close(); //DebugSession::close(); } } // Etesian namespace.