// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved // // =================================================================== // // $Id$ // // x-----------------------------------------------------------------x // | | // | C O R I O L I S | // | K i t e - D e t a i l e d R o u t e r | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | // | C++ Module : "./BuildPowerRails.cpp" | // | *************************************************************** | // | U p d a t e s | // | | // x-----------------------------------------------------------------x #include #include #include "hurricane/DataBase.h" #include "hurricane/Technology.h" #include "hurricane/BasicLayer.h" #include "hurricane/RegularLayer.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/NetExternalComponents.h" #include "hurricane/Query.h" #include "kite/RoutingPlane.h" #include "kite/TrackFixedSegment.h" #include "kite/Track.h" #include "kite/KiteEngine.h" namespace { using namespace std; using Hurricane::tab; using Hurricane::inltrace; using Hurricane::ForEachIterator; using Hurricane::DbU; using Hurricane::Box; using Hurricane::Interval; using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::NetExternalComponents; using Hurricane::Query; using Hurricane::Go; using Hurricane::Rubber; using Hurricane::Layer; using Hurricane::BasicLayer; using Hurricane::RegularLayer; using Hurricane::Transformation; using Hurricane::Technology; using Hurricane::DataBase; using namespace Kite; // ------------------------------------------------------------------- // Class : "::PowerRailsPlanes". class PowerRailsPlanes { private: class Rails; class Plane; 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 RoutingPlane* getRoutingPlane () const; inline Constant::Direction getDirection () const; inline Net::Type getType () const; void merge ( DbU::Unit source, DbU::Unit target ); void doLayout ( const Layer*, Net* ); private: Rails* _rails; DbU::Unit _axis; DbU::Unit _width; list _chunks; }; private: class RailCompare { public: bool operator() ( const Rail* lhs, const Rail* rhs ); }; 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; }; private: class Rails { public: Rails ( Plane*, Constant::Direction, Net::Type ); ~Rails (); inline Plane* getPlane (); inline RoutingPlane* getRoutingPlane (); inline Constant::Direction getDirection () const; inline Net::Type getType () const; void merge ( Point& source, Point& target, DbU::Unit width ); void doLayout ( const Layer*, Net* ); private: Plane* _plane; Constant::Direction _direction; Net::Type _type; vector _rails; }; private: class Plane { public: Plane ( const RegularLayer*, RoutingPlane* ); ~Plane (); inline RoutingPlane* getRoutingPlane (); void merge ( Point& source, Point& target, DbU::Unit width, Net::Type ); void doLayout ( Net* powerNet, Net* groundNet ); private: const RegularLayer* _layer; RoutingPlane* _routingPlane; Rails _railsPowerHorizontal; Rails _railsPowerVertical; Rails _railsGroundHorizontal; Rails _railsGroundVertical; }; public: PowerRailsPlanes ( KiteEngine* ); ~PowerRailsPlanes (); bool hasPlane ( const BasicLayer* ); bool setActivePlane ( const BasicLayer* ); inline Plane* getActivePlane () const; void merge ( Point& source, Point& target, DbU::Unit width, Net::Type ); void doLayout (); private: KiteEngine* _kite; map _planes; Plane* _activePlane; }; PowerRailsPlanes::Rail::Rail ( Rails* rails, DbU::Unit axis, DbU::Unit width ) : _rails (rails) , _axis (axis) , _width (width) , _chunks() { cinfo << " New rail @" << DbU::getValueString(axis) << " " << getRoutingPlane()->getLayer()->getName() << " " << getRails()->getType() << endl; } inline DbU::Unit PowerRailsPlanes::Rail::getAxis () const { return _axis; } inline DbU::Unit PowerRailsPlanes::Rail::getWidth () const { return _width; } inline PowerRailsPlanes::Rails* PowerRailsPlanes::Rail::getRails () const { return _rails; } inline RoutingPlane* PowerRailsPlanes::Rail::getRoutingPlane () const { return _rails->getRoutingPlane(); } inline Constant::Direction PowerRailsPlanes::Rail::getDirection () const { return _rails->getDirection(); } inline Net::Type PowerRailsPlanes::Rail::getType () const { return _rails->getType(); } void PowerRailsPlanes::Rail::merge ( DbU::Unit source, DbU::Unit target ) { Interval chunkMerge ( source, target ); list::iterator imerge = _chunks.end(); list::iterator ichunk = _chunks.begin(); while ( ichunk != _chunks.end() ) { if ( chunkMerge.getVMax() < (*ichunk).getVMin() ) break; if ( chunkMerge.intersect(*ichunk) ) { if ( imerge == _chunks.end() ) { imerge = ichunk; (*imerge).merge ( chunkMerge ); } else { (*imerge).merge ( *ichunk ); ichunk = _chunks.erase ( ichunk ); continue; } } ichunk++; } if ( imerge == _chunks.end() ) { _chunks.insert ( ichunk, chunkMerge ); ltrace(190) << "| Add on " << DbU::getValueString(_axis) << " " << chunkMerge << endl; } } void PowerRailsPlanes::Rail::doLayout ( const Layer* layer, Net* net ) { cinfo << "Doing layout of rail: " << layer->getName() << " @" << DbU::getValueString(_axis) << endl; RoutingPlane* plane = getRoutingPlane(); Segment* segment = NULL; DbU::Unit delta = plane->getLayerGauge()->getPitch() - plane->getLayerGauge()->getHalfWireWidth() - 1; unsigned int type = plane->getLayerGauge()->getType(); if ( getDirection() == Constant::Horizontal ) { list::iterator ichunk = _chunks.begin(); for ( ; ichunk != _chunks.end() ; ichunk++ ) { segment = Horizontal::create ( net, layer, _axis, _width, (*ichunk).getVMin(), (*ichunk).getVMax() ); if ( segment ) NetExternalComponents::setExternal ( segment ); if ( type == Constant::PinOnly ) continue; DbU::Unit axisMin = _axis - _width/2 - delta; DbU::Unit axisMax = _axis + _width/2 + delta; Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) { TrackFixedSegment::create ( track, segment ); } } } else { list::iterator ichunk = _chunks.begin(); for ( ; ichunk != _chunks.end() ; ichunk++ ) { segment = Vertical::create ( net, layer, _axis, _width, (*ichunk).getVMin(), (*ichunk).getVMax() ); if ( segment ) NetExternalComponents::setExternal ( segment ); if ( type == Constant::PinOnly ) continue; DbU::Unit axisMin = _axis - _width/2 - delta; DbU::Unit axisMax = _axis + _width/2 + delta; Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) { TrackFixedSegment::create ( track, segment ); } } } } inline bool PowerRailsPlanes::RailCompare::operator() ( const Rail* lhs, const Rail* rhs ) { if ( lhs->getAxis () < rhs->getAxis () ) return true; if ( lhs->getWidth() < rhs->getWidth() ) return true; return false; } inline PowerRailsPlanes::RailMatch::RailMatch ( DbU::Unit axis, DbU::Unit width ) : _axis(axis) , _width(width) { } inline bool PowerRailsPlanes::RailMatch::operator() ( const Rail* rail ) { return (rail->getAxis() == _axis) and (rail->getWidth() == _width); } PowerRailsPlanes::Rails::Rails ( PowerRailsPlanes::Plane* plane, Constant::Direction direction, Net::Type type ) : _plane (plane) , _direction(direction) , _type (type) { } PowerRailsPlanes::Rails::~Rails () { while ( not _rails.empty() ) { delete (*_rails.begin()); _rails.erase ( _rails.begin() ); } } inline PowerRailsPlanes::Plane* PowerRailsPlanes::Rails::getPlane () { return _plane; } inline RoutingPlane* PowerRailsPlanes::Rails::getRoutingPlane () { return getPlane()->getRoutingPlane(); } inline Constant::Direction PowerRailsPlanes::Rails::getDirection () const { return _direction; } inline Net::Type PowerRailsPlanes::Rails::getType () const { return _type; } void PowerRailsPlanes::Rails::merge ( Point& source, Point& target, DbU::Unit width ) { DbU::Unit axis = (_direction == Constant::Horizontal) ? source.getY() : source.getX(); 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 ); sort ( _rails.begin(), _rails.end(), RailCompare() ); } else { rail = *irail; } if ( _direction == Constant::Horizontal ) rail->merge ( source.getX(), target.getX() ); else rail->merge ( source.getY(), target.getY() ); } void PowerRailsPlanes::Rails::doLayout ( const Layer* layer, Net* net ) { cinfo << "Doing layout of plane: " << layer->getName() << " " << net->getName() << endl; for ( size_t irail=0 ; irail<_rails.size() ; irail++ ) _rails[irail]->doLayout ( layer, net ); } PowerRailsPlanes::Plane::Plane ( const RegularLayer* layer, RoutingPlane* routingPlane ) : _layer (layer) , _routingPlane (routingPlane) , _railsPowerHorizontal (this,Constant::Horizontal,Net::Type::POWER) , _railsPowerVertical (this,Constant::Vertical ,Net::Type::POWER) , _railsGroundHorizontal(this,Constant::Horizontal,Net::Type::GROUND) , _railsGroundVertical (this,Constant::Vertical ,Net::Type::GROUND) { cinfo << "New Plane " << _layer->getName() << " " << _routingPlane << endl; } PowerRailsPlanes::Plane::~Plane () { } inline RoutingPlane* PowerRailsPlanes::Plane::getRoutingPlane () { return _routingPlane; } void PowerRailsPlanes::Plane::merge ( Point& source, Point& target, DbU::Unit width, Net::Type type ) { if ( source.getY() == target.getY() ) { switch ( type ) { case Net::Type::POWER: _railsPowerHorizontal .merge(source,target,width); break; case Net::Type::GROUND: _railsGroundHorizontal.merge(source,target,width); break; default: break; } } else { switch ( type ) { case Net::Type::POWER: _railsPowerVertical .merge(source,target,width); break; case Net::Type::GROUND: _railsGroundVertical.merge(source,target,width); break; default: break; } } } void PowerRailsPlanes::Plane::doLayout ( Net* powerNet, Net* groundNet ) { _railsPowerHorizontal .doLayout ( _layer, powerNet ); _railsPowerVertical .doLayout ( _layer, powerNet ); _railsGroundHorizontal.doLayout ( _layer, groundNet ); _railsGroundVertical .doLayout ( _layer, groundNet ); } PowerRailsPlanes::PowerRailsPlanes ( KiteEngine* kite ) : _kite (kite) , _planes () , _activePlane(NULL) { Technology* technology = DataBase::getDB()->getTechnology(); RoutingGauge* rg = _kite->getConfiguration()->getRoutingGauge(); forEach ( Layer*, iLayer, technology->getLayers() ) { RegularLayer* regular = dynamic_cast(*iLayer); if ( not regular or (regular->getBasicLayer()->getMaterial() != BasicLayer::Material::metal) ) continue; RoutingLayerGauge* lg = rg->getLayerGauge(regular); if ( not lg ) continue; cinfo << "Gauge: [" << lg->getDepth() << "] " << lg << endl; RoutingPlane* rp = _kite->getRoutingPlaneByIndex(lg->getDepth()); cinfo << "Plane:" << rp << endl; _planes.insert ( make_pair(regular->getBasicLayer(),new Plane(regular,rp)) ); } } PowerRailsPlanes::~PowerRailsPlanes () { while ( not _planes.empty() ) { delete _planes.begin()->second; _planes.erase ( _planes.begin() ); } } bool PowerRailsPlanes::hasPlane ( const BasicLayer* layer ) { return (_planes.find(layer) != _planes.end()); } bool PowerRailsPlanes::setActivePlane ( const BasicLayer* layer ) { map::iterator iplane = _planes.find(layer); if ( iplane == _planes.end() ) return false; _activePlane = iplane->second; return true; } inline PowerRailsPlanes::Plane* PowerRailsPlanes::getActivePlane () const { return _activePlane; } void PowerRailsPlanes::merge ( Point& source, Point& target, DbU::Unit width, Net::Type type ) { if ( not _activePlane ) return; _activePlane->merge ( source, target, width, type ); } void PowerRailsPlanes::doLayout () { Net* powerNet = NULL; Net* groundNet = NULL; forEach ( Net*, inet, _kite->getCell()->getNets() ) { if ( not powerNet and (inet->getType() == Net::Type::POWER)) powerNet = *inet; if ( not groundNet and (inet->getType() == Net::Type::GROUND)) groundNet = *inet; if ( powerNet and groundNet ) break; } cinfo << "Doing power/ground layout " << powerNet->getName() << "/" << groundNet->getName() << endl; map::iterator iplane = _planes.begin(); for ( ; iplane != _planes.end() ; iplane++ ) iplane->second->doLayout ( powerNet, groundNet ); } // ------------------------------------------------------------------- // Class : "::QueryPowerRails". class QueryPowerRails : public Query { public: QueryPowerRails ( KiteEngine* ); virtual bool hasGoCallback () const; virtual void setBasicLayer ( const BasicLayer* ); 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 unsigned int getGoMatchCount () const; private: KiteEngine* _kite; PowerRailsPlanes _powerRailsPlanes; unsigned int _goMatchCount; }; QueryPowerRails::QueryPowerRails ( KiteEngine* kite ) : Query () , _kite (kite) , _powerRailsPlanes(kite) , _goMatchCount (0) { setCell ( kite->getCell() ); setArea ( kite->getCell()->getBoundingBox() ); setBasicLayer ( NULL ); setFilter ( Query::DoTerminalCells|Query::DoComponents ); } inline unsigned int QueryPowerRails::getGoMatchCount () const { return _goMatchCount; } inline void QueryPowerRails::doLayout () { return _powerRailsPlanes.doLayout(); } void QueryPowerRails::setBasicLayer ( const BasicLayer* basicLayer ) { _powerRailsPlanes.setActivePlane ( basicLayer ); Query::setBasicLayer ( basicLayer ); } void QueryPowerRails::doQuery () { if ( not _powerRailsPlanes.getActivePlane() ) return; Query::doQuery (); } void QueryPowerRails::masterCellCallback () { } bool QueryPowerRails::hasGoCallback () const { return true; } void QueryPowerRails::goCallback ( Go* go ) { addToPowerRail ( go, getBasicLayer(), getArea(), getTransformation() ); } void QueryPowerRails::addToPowerRail ( const Go* go , const BasicLayer* basicLayer , const Box& area , const Transformation& transformation ) { const Component* component = dynamic_cast(go); if ( component ) { Net::Type netType = component->getNet()->getType(); if ( (netType != Net::Type::POWER) and (netType != Net::Type::GROUND) ) return; const Segment* segment = dynamic_cast(component); if ( not segment ) return; _goMatchCount++; cinfo << " Merging PowerRail element: " << segment << endl; Point source = segment->getSourcePosition(); Point target = segment->getTargetPosition(); transformation.applyOn ( source ); transformation.applyOn ( target ); _powerRailsPlanes.merge ( source, target, segment->getWidth(), netType ); } } void QueryPowerRails::rubberCallback ( Rubber* ) { } void QueryPowerRails::extensionGoCallback ( Go* ) { } } // End of anonymous namespace. namespace Kite { using Hurricane::DataBase; using Hurricane::Technology; using Hurricane::BasicLayer; using Hurricane::ForEachIterator; void KiteEngine::buildPowerRails () { cmess1 << " o Building power rails." << endl; QueryPowerRails query ( this ); Technology* technology = DataBase::getDB()->getTechnology(); forEach ( BasicLayer*, iLayer, technology->getBasicLayers() ) { if ( iLayer->getMaterial() != BasicLayer::Material::metal ) continue; if ( _configuration->isGMetal(*iLayer) ) continue; cmess1 << " - PowerRails in " << iLayer->getName() << " ..." << endl; query.setBasicLayer ( *iLayer ); query.doQuery (); } query.doLayout (); cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl; Session::revalidate (); } } // End of Kite namespace.