// -*- mode: C++; explicit-buffer-name: "Session.cpp" -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC 2008-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | A n a b a t i c - Routing Toolbox | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./Session.cpp" | // +-----------------------------------------------------------------+ #include #include #include "hurricane/Error.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/Cell.h" #include "hurricane/UpdateSession.h" #include "crlcore/RoutingGauge.h" #include "crlcore/RoutingLayerGauge.h" #include "anabatic/Configuration.h" #include "anabatic/Session.h" #include "anabatic/AutoContact.h" #include "anabatic/AutoSegment.h" #include "anabatic/AnabaticEngine.h" namespace { const char* reopenSession = "Anabatic::Session::_open(): Session already open for %s (internal error)."; const char* openSessionError = "%s: Session has not been opened (internal error)."; } // End of local namespace. namespace Anabatic { using namespace std; using Hurricane::tab; using Hurricane::Error; using Hurricane::ForEachIterator; using Hurricane::UpdateSession; using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::Cell; using CRL::RoutingLayerGauge; // ------------------------------------------------------------------- // Class : "Anabatic::Session". Session* Session::_session = NULL; Session* Session::get ( const char* message ) { if (not _session and message) throw Error( openSessionError, message ); return _session; } Session::Session ( AnabaticEngine* anbt ) : _anabatic (anbt) , _technology (anbt->getConfiguration()->getRoutingGauge()->getTechnology()) , _cellGauge (anbt->getConfiguration()->getCellGauge()) , _routingGauge (anbt->getConfiguration()->getRoutingGauge()) , _autoContacts () , _doglegs () , _segmentInvalidateds() , _segmentRevalidateds() , _netInvalidateds () , _netRevalidateds () { } void Session::_postCreate () { UpdateSession::open(); _session = this; } Session::~Session () { } void Session::_preDestroy () { if (_anabatic->getState() <= EngineActive) { _revalidate (); _anabatic->updateDensity(); } UpdateSession::close(); } bool Session::_doDestroyBaseContact () { return _anabatic->doDestroyBaseContact(); } bool Session::_doDestroyBaseSegment () { return _anabatic->doDestroyBaseSegment(); } bool Session::_doDestroyTool () { return _anabatic->doDestroyTool(); } Configuration* Session::_getConfiguration () { return _anabatic->getConfiguration(); } void Session::_invalidate ( Net* net ) { cdebug_log(149,0) << "Session::invalidate(Net*) - " << net << endl; _netInvalidateds.insert(net); } void Session::_canonize () { cdebug_log(145,1) << "Anabatic::Session::_canonize()" << endl; if (_segmentInvalidateds.empty()) { cdebug_log(145,0) << "Invalidated AutoSegment collection <_segmentInvalidateds> is empty." << endl; cdebug_tabw(145,-1); return; } set exploredSegments; vector aligneds; // Should no longer be necessary to ensure determinism. //sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end(), AutoSegment::CompareId() ); for ( size_t i=0 ; i<_segmentInvalidateds.size() ; i++ ) { AutoSegment* seedSegment = _segmentInvalidateds[i]; AutoSegment* canonical = seedSegment; if (exploredSegments.find(seedSegment->base()) == exploredSegments.end()) { cdebug_log(145,0) << "New chunk from: " << seedSegment << endl; aligneds.push_back( seedSegment ); bool isWeakGlobal = seedSegment->isGlobal(); if (not seedSegment->isNotAligned()) { forEach ( AutoSegment*, aligned, seedSegment->getAligneds() ) { cdebug_log(145,0) << "Aligned: " << *aligned << endl; aligneds.push_back ( *aligned ); exploredSegments.insert ( aligned->base() ); isWeakGlobal = isWeakGlobal or aligned->isGlobal(); if (AutoSegment::CompareId()( *aligned, canonical )) canonical = *aligned; } } cdebug_tabw(145,1); canonical->setFlags( AutoSegment::SegCanonical ); cdebug_log(145,0) << "Canonical: " << canonical << endl; for ( size_t j=0 ; jisGlobal()) aligneds[j]->setFlags ( AutoSegment::SegWeakGlobal ); else aligneds[j]->unsetFlags( AutoSegment::SegWeakGlobal ); if (aligneds[j] == canonical) continue; if (aligneds[j]->isCanonical()) { cerr << Error("Session::_canonize(): On %s\n" " Segment is no longer the canonical one, this must not happens." ,getString(aligneds[j]).c_str()) << endl; } aligneds[j]->unsetFlags( AutoSegment::SegCanonical ); cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl; } if (aligneds.empty()) canonical->setFlags( AutoSegment::SegNotAligned ); cdebug_log(149,0) << "Align on canonical:" << canonical << endl; //canonical->setAxis( canonical->getAxis(), Flags::Realignate ); if (canonical->isUnsetAxis() and not canonical->isFixed()) canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate ); else canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate ); aligneds.clear(); cdebug_tabw(145,-1); } } cdebug_tabw(145,-1); } void Session::_revalidateTopology () { cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl; set::iterator inet = _netInvalidateds.begin(); for ( ; inet != _netInvalidateds.end() ; inet++ ) { cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << *inet << endl; _anabatic->updateNetTopology ( *inet ); _anabatic->computeNetConstraints( *inet ); _anabatic->_computeNetOptimals ( *inet ); _anabatic->_computeNetTerminals ( *inet ); } _canonize (); for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) { if (_segmentInvalidateds[i]->isCanonical()) { if (_segmentInvalidateds[i]->isUnsetAxis()) _segmentInvalidateds[i]->toOptimalAxis(); else _segmentInvalidateds[i]->toConstraintAxis(); } } _netRevalidateds.clear(); _netRevalidateds.swap( _netInvalidateds ); cdebug_tabw(145,-1); } size_t Session::_revalidate () { cdebug_log(145,1) << "Anabatic::Session::revalidate()" << endl; cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl; cdebug_log(145,0) << "_autoContacts.size(): " << _autoContacts.size() << endl; size_t count = 0; if (not _netInvalidateds.empty()) _revalidateTopology(); cdebug_log(145,0) << "AutoContacts Revalidate (after _revalidateTopology())." << endl; for ( size_t i=0 ; i < _autoContacts.size() ; i++, count++ ) _autoContacts[i]->updateGeometry(); _autoContacts.clear(); cdebug_log(145,0) << "AutoSegments Revalidate (after AutoContact::updateGeometry())." << endl; cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl; _segmentRevalidateds.clear(); for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) { _segmentInvalidateds[i]->revalidate(); if ( not _destroyedSegments.empty() and (_destroyedSegments.find(_segmentInvalidateds[i]) != _destroyedSegments.end()) ) continue; _segmentRevalidateds.push_back( _segmentInvalidateds[i] ); } _segmentInvalidateds.clear(); cdebug_log(145,0) << "AutoSegments/AutoContacts queued deletion." << endl; Flags flags = _anabatic->flags() & Flags::DestroyMask; _anabatic->flags() = Flags::DestroyMask; set::iterator isegment = _destroyedSegments.begin(); for ( ; isegment != _destroyedSegments.end() ; isegment++ ) { AutoContact* source = (*isegment)->getAutoSource(); AutoContact* target = (*isegment)->getAutoTarget(); (*isegment)->destroy(); if (source and source->canDestroy(true)) source->destroy(); if (target and target->canDestroy(true)) target->destroy(); } _anabatic->flags() = flags; set().swap( _destroyedSegments ); cdebug_tabw(145,-1); return count; } Session* Session::_open ( AnabaticEngine* anbt ) { cdebug_log(145,0) << "Anabatic::Session::_open()" << endl; if (_session) { if (_session->_anabatic != anbt) throw Error( reopenSession, getString(_session->getAnabatic()).c_str() ); return _session; } Session* session = new Session ( anbt ); session->_postCreate(); return session; } void Session::close () { cdebug_log(145,1) << "Session::close()" << endl; if (not _session) throw Error( openSessionError, "Session::Close()" ); _session->_preDestroy(); delete _session; _session = NULL; cdebug_tabw(145,-1); } Flags Session::getDirection ( size_t depth ) { RoutingGauge* rg = get("getDirection()")->_routingGauge; switch ( rg->getLayerDirection(depth) ) { case Constant::Horizontal: return Flags::Horizontal; case Constant::Vertical: return Flags::Vertical; } return Flags::NoFlags; } DbU::Unit Session::_getPitch ( size_t depth, Flags flags ) const { if (flags == Flags::NoFlags) return _routingGauge->getLayerPitch(depth); if (flags & Flags::AboveLayer) { if (depth < getAllowedDepth()) return _routingGauge->getLayerPitch( depth + 1 ); else { if ( (depth > 0) and (_routingGauge->getLayerType(depth-1) != Constant::PinOnly) ) return _routingGauge->getLayerPitch( depth - 1 ); } } if (flags & Flags::BelowLayer) { if ( (depth > 0) and (_routingGauge->getLayerType(depth-1) != Constant::PinOnly) ) return _routingGauge->getLayerPitch( depth - 1 ); else { if (depth < getAllowedDepth()) return _routingGauge->getLayerPitch( depth + 1 ); } } // Should issue at least a warning here. return _routingGauge->getLayerPitch(depth); } Point Session::_getNearestGridPoint ( Point p, Box constraint ) { Box ab = _anabatic->getCell()->getAbutmentBox(); RoutingLayerGauge* lg = _routingGauge->getVerticalGauge(); DbU::Unit x = lg->getTrackPosition( ab.getXMin() , lg->getTrackIndex( ab.getXMin() , ab.getXMax() , p.getX() , Constant::Nearest ) ); if (x < constraint.getXMin()) x += lg->getPitch(); if (x > constraint.getXMax()) x -= lg->getPitch(); lg = _routingGauge->getHorizontalGauge(); DbU::Unit y = lg->getTrackPosition( ab.getYMin() , lg->getTrackIndex( ab.getYMin() , ab.getYMax() , p.getY() , Constant::Nearest ) ); if (y < constraint.getYMin()) y += lg->getPitch(); if (y > constraint.getYMax()) y -= lg->getPitch(); return Point(x,y); } bool Session::isInDemoMode () { return get("isInDemoMode()")->_anabatic->isInDemoMode(); } float Session::getSaturateRatio () { return get("getSaturateRatio()")->_anabatic->getSaturateRatio(); } size_t Session::getSaturateRp () { return get("getSaturateRp()")->_anabatic->getSaturateRp(); } bool Session::doWarnGCellOverload () { return get("doWarnGCellOverload()")->_anabatic->doWarnOnGCellOverload(); } void Session::setAnabaticFlags ( Flags flags ) { get("setKabaticFlags()")->_anabatic->flags() = flags; } void Session::link ( AutoContact* autoContact ) { return get("link(AutoContact*)")->_anabatic->_link( autoContact ); } void Session::link ( AutoSegment* autoSegment ) { return get("link(AutoSegment*)")->_anabatic->_link( autoSegment ); } void Session::unlink ( AutoContact* autoContact ) { return get("unlink(AutoContact*)")->_anabatic->_unlink( autoContact ); } void Session::unlink ( AutoSegment* autoSegment ) { return get("unlink(AutoSegment*)")->_anabatic->_unlink( autoSegment ); } AutoContact* Session::lookup ( Contact* contact ) { return get("lookup(Contact*)")->_anabatic->_lookup( contact ); } AutoSegment* Session::lookup ( Segment* segment ) { return get("lookup(Segment*)")->_anabatic->_lookup( segment ); } string Session::_getString () const { return "<" + _getTypeName() + " " + getString(_anabatic->getCell()->getName()) + ">"; } Record* Session::_getRecord () const { Record* record = new Record ( _getString() ); record->add ( getSlot ( "_anabatic" , _anabatic ) ); record->add ( getSlot ( "_autoContacts", &_autoContacts ) ); //record->add ( getSlot ( "_autoSegments", &_autoSegments ) ); return record; } } // End of Anabatic namespace.