440 lines
12 KiB
C++
440 lines
12 KiB
C++
|
|
// -*- 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 a t a b a t i c - Routing Toolbox |
|
|
// | |
|
|
// | Author : Jean-Paul CHAPUT |
|
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./Session.cpp" |
|
|
// | *************************************************************** |
|
|
// | U p d a t e s |
|
|
// | |
|
|
// x-----------------------------------------------------------------x
|
|
|
|
|
|
#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::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())
|
|
, _routingGauge (ktbt->getRoutingGauge())
|
|
, _autoContacts ()
|
|
, _autoSegments ()
|
|
, _revalidateds ()
|
|
, _dogLegs ()
|
|
, _netInvalidateds ()
|
|
, _netRevalidateds ()
|
|
, _invalidateMask (0)
|
|
{ }
|
|
|
|
|
|
void Session::_postCreate ()
|
|
{
|
|
UpdateSession::open ();
|
|
_session = this;
|
|
}
|
|
|
|
|
|
Session::~Session ()
|
|
{ }
|
|
|
|
|
|
size_t Session::_preDestroy ()
|
|
{
|
|
size_t count = 0;
|
|
if ( _katabatic->getState() <= StateActive ) {
|
|
_revalidate ();
|
|
|
|
if ( _katabatic->getGCellGrid() )
|
|
_katabatic->getGCellGrid()->updateDensity ();
|
|
}
|
|
UpdateSession::close();
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
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::_splitContacts ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::_splitContacts()" << endl;
|
|
ltracein(110);
|
|
|
|
for ( size_t i=0; i<_autoContacts.size() ; i++ )
|
|
_autoContacts[i]->split ();
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
void Session::_restoreVCon ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::_restoreVCon()" << endl;
|
|
ltracein(110);
|
|
|
|
for ( size_t i=0; i<_autoContacts.size() ; i++ ) {
|
|
DbU::Unit y = DbU::Max;
|
|
forEach ( Horizontal*, isegment, _autoContacts[i]->getSlaveComponents().getSubSet<Horizontal*>() ) {
|
|
y = isegment->getY();
|
|
}
|
|
_autoContacts[i]->restoreVConnexity ( y, true );
|
|
}
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
void Session::_restoreHCon ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::_restoreHCon()" << endl;
|
|
ltracein(110);
|
|
|
|
for ( size_t i=0; i<_autoContacts.size() ; i++ ) {
|
|
DbU::Unit x = DbU::Max;
|
|
forEach ( Vertical*, isegment, _autoContacts[i]->getSlaveComponents().getSubSet<Vertical*>() ) {
|
|
x = isegment->getX();
|
|
}
|
|
_autoContacts[i]->restoreHConnexity ( x, true );
|
|
}
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
void Session::_canonize ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::_canonize()" << endl;
|
|
ltracein(110);
|
|
|
|
set<Segment*> exploredSegments;
|
|
vector<AutoSegment*> aligneds;
|
|
|
|
sort ( _autoSegments.begin(), _autoSegments.end(), AutoSegment::CompareCanonical() );
|
|
|
|
for ( size_t i=0 ; i<_autoSegments.size() ; i++ ) {
|
|
AutoSegment* seedSegment = _autoSegments[i];
|
|
|
|
if ( exploredSegments.find(seedSegment->getSegment()) == exploredSegments.end() ) {
|
|
ltrace(110) << "New chunk from: " << seedSegment << endl;
|
|
aligneds.push_back ( seedSegment );
|
|
|
|
bool isCanonicalLocal = seedSegment->isLocal();
|
|
forEach ( AutoSegment*, collapsed, seedSegment->getCollapseds() ) {
|
|
ltrace(110) << "Aligned: " << *collapsed << endl;
|
|
aligneds.push_back ( *collapsed );
|
|
exploredSegments.insert ( collapsed->getSegment() );
|
|
|
|
if ( collapsed->isGlobal() ) isCanonicalLocal = false;
|
|
}
|
|
|
|
ltracein(110);
|
|
sort ( aligneds.begin(), aligneds.end(), AutoSegment::CompareCanonical() );
|
|
|
|
if ( aligneds.size() > 1 ) {
|
|
if ( not AutoSegment::CompareCanonical() ( aligneds[0], aligneds[1] ) ) {
|
|
cerr << "Ambiguous canonization: " << aligneds[0]->base() << endl;
|
|
cerr << "Ambiguous canonization: " << aligneds[1]->base() << endl;
|
|
}
|
|
}
|
|
|
|
aligneds[0]->setCanonical ( true );
|
|
aligneds[0]->setCanonicalLocal ( isCanonicalLocal );
|
|
ltrace(110) << "Canonical: " << aligneds[0] << endl;
|
|
|
|
for ( size_t j=1 ; j<aligneds.size() ; j++ ) {
|
|
aligneds[j]->setCanonical ( false );
|
|
ltrace(110) << "Secondary: " << aligneds[j] << endl;
|
|
}
|
|
|
|
ltrace(159) << "Align @" << DbU::getLambda(aligneds[0]->getAxis())
|
|
<< " on " << aligneds[0] << endl;
|
|
|
|
aligneds[0]->setAxis ( aligneds[0]->getAxis(), Realignate );
|
|
aligneds.clear ();
|
|
ltraceout(110);
|
|
}
|
|
}
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
void Session::_revalidateTopology ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::_revalidateTopology()" << endl;
|
|
ltracein(110);
|
|
|
|
set<AutoSegment*> faileds;
|
|
|
|
if ( not _netInvalidateds.empty() ) {
|
|
set<Net*>::iterator inet = _netInvalidateds.begin();
|
|
|
|
if ( _invalidateMask & NetSplitContacts ) {
|
|
_splitContacts ();
|
|
_invalidateMask &= ~NetSplitContacts;
|
|
}
|
|
|
|
if ( _invalidateMask & RestoreVCon ) {
|
|
_restoreVCon ();
|
|
_invalidateMask &= ~RestoreVCon;
|
|
}
|
|
|
|
if ( _invalidateMask & RestoreHCon ) {
|
|
_restoreVCon ();
|
|
_invalidateMask &= ~RestoreHCon;
|
|
}
|
|
|
|
if ( _invalidateMask & NetCanonize ) {
|
|
for ( ; inet != _netInvalidateds.end() ; inet++ ) {
|
|
ltrace(110) << "Katabatic::Session::_revalidateTopology(Net*)" << *inet << endl;
|
|
_katabatic->_computeNetConstraints ( *inet, faileds );
|
|
_katabatic->_computeNetOptimals ( *inet );
|
|
_katabatic->_computeNetTerminals ( *inet );
|
|
}
|
|
_canonize ();
|
|
|
|
for ( size_t i=0 ; i<_autoSegments.size() ; ++i ) {
|
|
if ( _autoSegments[i]->isUnsetAxis()
|
|
and _autoSegments[i]->isCanonical() ) {
|
|
_autoSegments[i]->toOptimalAxis ();
|
|
}
|
|
}
|
|
_invalidateMask &= ~NetCanonize;
|
|
}
|
|
}
|
|
|
|
ltraceout(110);
|
|
}
|
|
|
|
|
|
size_t Session::_revalidate ()
|
|
{
|
|
ltrace(110) << "Katabatic::Session::revalidate()" << endl;
|
|
ltracein(110);
|
|
|
|
size_t count = 0;
|
|
|
|
_revalidateTopology ();
|
|
_netRevalidateds.clear ();
|
|
_netRevalidateds.swap ( _netInvalidateds );
|
|
|
|
ltrace(110) << "AutoContacts Revalidate (after canonize)." << endl;
|
|
for ( size_t i=0 ; i < _autoContacts.size() ; i++, count++ )
|
|
_autoContacts[i]->revalidate ();
|
|
_autoContacts.clear ();
|
|
|
|
ltrace(110) << "AutoSegments Revalidate (after canonize)." << endl;
|
|
for ( size_t i=0 ; i < _autoSegments.size() ; i++, count++ )
|
|
_autoSegments[i]->revalidate ();
|
|
_revalidateds.clear ();
|
|
_autoSegments.swap ( _revalidateds );
|
|
_dogLegs.clear ();
|
|
|
|
ltrace(110) << "AutoSegments/AutoContacts queued deletion." << endl;
|
|
bool destroySegment = _katabatic->setDestroyBaseSegment ( true );
|
|
bool destroyContact = _katabatic->setDestroyBaseContact ( true );
|
|
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->setDestroyBaseSegment ( destroySegment );
|
|
_katabatic->setDestroyBaseContact ( destroyContact );
|
|
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;
|
|
}
|
|
|
|
|
|
size_t Session::close ()
|
|
{
|
|
ltrace(110) << "Session::close()" << endl;
|
|
ltracein(110);
|
|
|
|
if ( !_session ) throw Error ( openSessionError, "Session::Close()" );
|
|
|
|
size_t count = _session->_preDestroy ();
|
|
|
|
delete _session;
|
|
_session = NULL;
|
|
|
|
ltraceout(110);
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
bool Session::getDemoMode ()
|
|
{ return get("getDemoMode()")->_katabatic->getDemoMode(); }
|
|
|
|
|
|
float Session::getSaturateRatio ()
|
|
{ return get("getSaturateRatio()")->_katabatic->getSaturateRatio(); }
|
|
|
|
|
|
bool Session::getWarnGCellOverload ()
|
|
{ return get("getWarnGCellOverload()")->_katabatic->getWarnGCellOverload(); }
|
|
|
|
|
|
void Session::setWarnGCellOverload ( bool state )
|
|
{ get("getWarnGCellOverload()")->_katabatic->setWarnGCellOverload(state); }
|
|
|
|
|
|
DbU::Unit Session::getExtensionCap ()
|
|
{ return getConfiguration()->getExtensionCap(); }
|
|
|
|
|
|
const Layer* Session::getRoutingLayer ( size_t depth )
|
|
{ return getConfiguration()->getRoutingLayer(depth); }
|
|
|
|
|
|
const Layer* Session::getContactLayer ( size_t depth )
|
|
{ return getConfiguration()->getContactLayer(depth); }
|
|
|
|
|
|
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.
|