420 lines
13 KiB
C++
420 lines
13 KiB
C++
// -*- mode: C++; explicit-buffer-name: "Session.cpp<katabatic>" -*-
|
|
//
|
|
// This file is part of the Coriolis Software.
|
|
// Copyright (c) UPMC 2008-2015, All Rights Reserved
|
|
//
|
|
// +-----------------------------------------------------------------+
|
|
// | C O R I O L I S |
|
|
// | K a t a b a t i c - Routing Toolbox |
|
|
// | |
|
|
// | Author : Jean-Paul CHAPUT |
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./Session.cpp" |
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
#include <cstdlib>
|
|
#include <sstream>
|
|
#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 "katabatic/Session.h"
|
|
#include "katabatic/AutoContact.h"
|
|
#include "katabatic/AutoSegment.h"
|
|
#include "katabatic/AutoSegment.h"
|
|
#include "katabatic/GCellGrid.h"
|
|
#include "katabatic/KatabaticEngine.h"
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
const char* reopenSession =
|
|
"Session::open() :\n\n"
|
|
" Session already open for %s (internal error).";
|
|
|
|
const char* openSessionError =
|
|
"%s :\n\n"
|
|
" Session has not been opened (internal error).";
|
|
|
|
|
|
} // End of local namespace.
|
|
|
|
|
|
|
|
|
|
namespace Katabatic {
|
|
|
|
|
|
using namespace std;
|
|
using Hurricane::tab;
|
|
using Hurricane::ltracein;
|
|
using Hurricane::ltraceout;
|
|
using Hurricane::inltrace;
|
|
using Hurricane::ltracelevel;
|
|
using Hurricane::Error;
|
|
using Hurricane::ForEachIterator;
|
|
using Hurricane::UpdateSession;
|
|
using Hurricane::Horizontal;
|
|
using Hurricane::Vertical;
|
|
using Hurricane::Cell;
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Katabatic::Session".
|
|
|
|
Session* Session::_session = NULL;
|
|
|
|
|
|
Session* Session::get ( const char* message )
|
|
{
|
|
if (not _session and message)
|
|
throw Error( openSessionError, message );
|
|
return _session;
|
|
}
|
|
|
|
|
|
Session::Session ( KatabaticEngine* ktbt )
|
|
: _katabatic (ktbt)
|
|
, _technology (ktbt->getRoutingGauge()->getTechnology())
|
|
, _cellGauge (ktbt->getCellGauge())
|
|
, _routingGauge (ktbt->getRoutingGauge())
|
|
, _autoContacts ()
|
|
, _doglegs ()
|
|
, _segmentInvalidateds()
|
|
, _segmentRevalidateds()
|
|
, _netInvalidateds ()
|
|
, _netRevalidateds ()
|
|
{ }
|
|
|
|
|
|
void Session::_postCreate ()
|
|
{
|
|
UpdateSession::open();
|
|
_session = this;
|
|
}
|
|
|
|
|
|
Session::~Session ()
|
|
{ }
|
|
|
|
|
|
void Session::_preDestroy ()
|
|
{
|
|
if (_katabatic->getState() <= EngineActive) {
|
|
_revalidate ();
|
|
|
|
if (_katabatic->getGCellGrid())
|
|
_katabatic->getGCellGrid()->updateDensity();
|
|
}
|
|
UpdateSession::close();
|
|
}
|
|
|
|
|
|
bool Session::_doDestroyBaseContact () { return _katabatic->doDestroyBaseContact(); }
|
|
bool Session::_doDestroyBaseSegment () { return _katabatic->doDestroyBaseSegment(); }
|
|
bool Session::_doDestroyTool () { return _katabatic->doDestroyTool(); }
|
|
Configuration* Session::_getConfiguration () { return _katabatic->getConfiguration(); }
|
|
|
|
|
|
void Session::_invalidate ( Net* net )
|
|
{
|
|
ltrace(200) << "Session::invalidate(Net*) - " << net << endl;
|
|
_netInvalidateds.insert(net);
|
|
}
|
|
|
|
|
|
void Session::_canonize ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::_canonize()" << endl;
|
|
ltracein(110);
|
|
|
|
if (_segmentInvalidateds.empty()) {
|
|
ltrace(110) << "Invalidated AutoSegment collection <_segmentInvalidateds> is empty." << endl;
|
|
ltraceout(110);
|
|
return;
|
|
}
|
|
|
|
set<Segment*> exploredSegments;
|
|
vector<AutoSegment*> 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()) {
|
|
ltrace(110) << "New chunk from: " << seedSegment << endl;
|
|
aligneds.push_back( seedSegment );
|
|
|
|
bool isWeakGlobal = seedSegment->isGlobal();
|
|
if (not seedSegment->isNotAligned()) {
|
|
forEach ( AutoSegment*, aligned, seedSegment->getAligneds() ) {
|
|
ltrace(110) << "Aligned: " << *aligned << endl;
|
|
aligneds.push_back ( *aligned );
|
|
exploredSegments.insert ( aligned->base() );
|
|
|
|
isWeakGlobal = isWeakGlobal or aligned->isGlobal();
|
|
if (AutoSegment::CompareId()( *aligned, canonical ))
|
|
canonical = *aligned;
|
|
}
|
|
}
|
|
|
|
ltracein(110);
|
|
|
|
canonical->setFlags( SegCanonical );
|
|
ltrace(110) << "Canonical: " << canonical << endl;
|
|
|
|
for ( size_t j=0 ; j<aligneds.size() ; j++ ) {
|
|
if (isWeakGlobal and not aligneds[j]->isGlobal()) aligneds[j]->setFlags ( SegWeakGlobal );
|
|
else aligneds[j]->unsetFlags( 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( SegCanonical );
|
|
ltrace(110) << "Secondary: " << aligneds[j] << endl;
|
|
}
|
|
if (aligneds.empty()) canonical->setFlags( SegNotAligned );
|
|
|
|
ltrace(159) << "Align @" << DbU::toLambda(canonical->getAxis())
|
|
<< " on " << canonical << endl;
|
|
|
|
//canonical->setAxis( canonical->getAxis(), KbRealignate );
|
|
if (canonical->isUnsetAxis()) canonical->toOptimalAxis( KbRealignate|KbPropagate );
|
|
else canonical->setAxis( canonical->getAxis(), KbRealignate|KbPropagate );
|
|
aligneds.clear();
|
|
ltraceout(110);
|
|
}
|
|
}
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
void Session::_revalidateTopology ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::_revalidateTopology()" << endl;
|
|
ltracein(110);
|
|
|
|
set<Net*>::iterator inet = _netInvalidateds.begin();
|
|
|
|
for ( ; inet != _netInvalidateds.end() ; inet++ ) {
|
|
ltrace(110) << "Katabatic::Session::_revalidateTopology(Net*)" << *inet << endl;
|
|
_katabatic->updateNetTopology ( *inet );
|
|
_katabatic->computeNetConstraints( *inet );
|
|
_katabatic->_computeNetOptimals ( *inet );
|
|
_katabatic->_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 );
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
size_t Session::_revalidate ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::revalidate()" << endl;
|
|
ltracein(110);
|
|
|
|
ltrace(110) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
|
|
ltrace(110) << "_autoContacts.size(): " << _autoContacts.size() << endl;
|
|
|
|
size_t count = 0;
|
|
|
|
if (not _netInvalidateds.empty()) _revalidateTopology();
|
|
|
|
ltrace(110) << "AutoContacts Revalidate (after _revalidateTopology())." << endl;
|
|
for ( size_t i=0 ; i < _autoContacts.size() ; i++, count++ )
|
|
_autoContacts[i]->updateGeometry();
|
|
_autoContacts.clear();
|
|
|
|
ltrace(110) << "AutoSegments Revalidate (after AutoContact::updateGeometry())." << endl;
|
|
ltrace(110) << "_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();
|
|
|
|
ltrace(110) << "AutoSegments/AutoContacts queued deletion." << endl;
|
|
unsigned int flags = _katabatic->getFlags( EngineDestroyMask );
|
|
_katabatic->setFlags( EngineDestroyMask );
|
|
set<AutoSegment*>::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();
|
|
}
|
|
_katabatic->setFlags( flags );
|
|
set<AutoSegment*>().swap( _destroyedSegments );
|
|
|
|
ltraceout(110);
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
Session* Session::open ( KatabaticEngine* ktbt )
|
|
{
|
|
ltrace(110) << "Session::open()" << endl;
|
|
|
|
if (_session) {
|
|
if (_session->_katabatic != ktbt)
|
|
throw Error( reopenSession, getString(_session->getKatabatic()).c_str() );
|
|
|
|
return _session;
|
|
}
|
|
|
|
Session* session = new Session ( ktbt );
|
|
session->_postCreate();
|
|
|
|
return session;
|
|
}
|
|
|
|
|
|
void Session::close ()
|
|
{
|
|
ltrace(110) << "Session::close()" << endl;
|
|
ltracein(110);
|
|
|
|
if (not _session) throw Error( openSessionError, "Session::Close()" );
|
|
|
|
_session->_preDestroy();
|
|
|
|
delete _session;
|
|
_session = NULL;
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
unsigned int Session::getDirection ( size_t depth )
|
|
{
|
|
RoutingGauge* rg = get("getDirection()")->_routingGauge;
|
|
switch ( rg->getLayerDirection(depth) ) {
|
|
case Constant::Horizontal: return KbHorizontal;
|
|
case Constant::Vertical: return KbVertical;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
DbU::Unit Session::_getPitch ( size_t depth, unsigned int flags ) const
|
|
{
|
|
if (flags == Configuration::NoFlags) return _routingGauge->getLayerPitch(depth);
|
|
|
|
if (flags & Configuration::PitchAbove) {
|
|
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 & Configuration::PitchBelow) {
|
|
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);
|
|
}
|
|
|
|
|
|
bool Session::isInDemoMode ()
|
|
{ return get("isInDemoMode()")->_katabatic->isInDemoMode(); }
|
|
|
|
|
|
float Session::getSaturateRatio ()
|
|
{ return get("getSaturateRatio()")->_katabatic->getSaturateRatio(); }
|
|
|
|
|
|
size_t Session::getSaturateRp ()
|
|
{ return get("getSaturateRp()")->_katabatic->getSaturateRp(); }
|
|
|
|
|
|
bool Session::doWarnGCellOverload ()
|
|
{ return get("doWarnGCellOverload()")->_katabatic->doWarnOnGCellOverload(); }
|
|
|
|
|
|
void Session::setKatabaticFlags ( unsigned int flags )
|
|
{ get("setKabaticFlags()")->_katabatic->setFlags(flags); }
|
|
|
|
|
|
void Session::link ( AutoContact* autoContact )
|
|
{ return get("link(AutoContact*)")->_katabatic->_link( autoContact ); }
|
|
|
|
|
|
void Session::link ( AutoSegment* autoSegment )
|
|
{ return get("link(AutoSegment*)")->_katabatic->_link( autoSegment ); }
|
|
|
|
|
|
void Session::unlink ( AutoContact* autoContact )
|
|
{ return get("unlink(AutoContact*)")->_katabatic->_unlink( autoContact ); }
|
|
|
|
|
|
void Session::unlink ( AutoSegment* autoSegment )
|
|
{ return get("unlink(AutoSegment*)")->_katabatic->_unlink( autoSegment ); }
|
|
|
|
|
|
AutoContact* Session::lookup ( Contact* contact )
|
|
{ return get("lookup(Contact*)")->_katabatic->_lookup( contact ); }
|
|
|
|
|
|
AutoSegment* Session::lookup ( Segment* segment )
|
|
{ return get("lookup(Segment*)")->_katabatic->_lookup( segment ); }
|
|
|
|
|
|
string Session::_getString () const
|
|
{
|
|
return "<" + _getTypeName() + " "
|
|
+ getString(_katabatic->getCell()->getName())
|
|
+ ">";
|
|
}
|
|
|
|
|
|
Record* Session::_getRecord () const
|
|
{
|
|
Record* record = new Record ( _getString() );
|
|
record->add ( getSlot ( "_katabatic" , _katabatic ) );
|
|
record->add ( getSlot ( "_autoContacts", &_autoContacts ) );
|
|
//record->add ( getSlot ( "_autoSegments", &_autoSegments ) );
|
|
return record;
|
|
}
|
|
|
|
|
|
} // End of Katabatic namespace.
|