coriolis/katabatic/src/KatabaticEngine.cpp

914 lines
27 KiB
C++
Raw Normal View History

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2008, 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 : "./KatabaticEngine.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <iostream>
#include <fstream>
#include "hurricane/DebugSession.h"
#include "hurricane/Bug.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/Layer.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Cell.h"
#include "crlcore/Utilities.h"
#include "crlcore/AllianceFramework.h"
#include "katabatic/Session.h"
#include "katabatic/AutoContact.h"
#include "katabatic/AutoSegment.h"
#include "katabatic/GCell.h"
#include "katabatic/GCellGrid.h"
#include "katabatic/KatabaticEngine.h"
namespace {
using namespace Hurricane;
struct NetCompareByName {
inline bool operator() ( const Net* lhs, const Net* rhs ) const;
};
inline bool NetCompareByName::operator() ( const Net* lhs, const Net* rhs ) const
{
return lhs->getName() < rhs->getName();
}
bool isTopAndBottomConnected ( Segment* segment, set<const Layer*>& layers )
{
ltrace(88) << "* Potential Null Length: " << segment << endl;
ltracein(88);
Contact* source = dynamic_cast<Contact*>(segment->getSource());
Contact* target = dynamic_cast<Contact*>(segment->getTarget());
layers.clear ();
if ( source ) {
forEach ( Hook*, ihook, source->getBodyHook()->getSlaveHooks() ) {
ltrace(88) << "* Slave: " << (*ihook)->getComponent() << endl;
if ( (*ihook)->getComponent() == segment ) continue;
layers.insert ( (*ihook)->getComponent()->getLayer() );
}
}
if ( target ) {
forEach ( Hook*, ihook, target->getBodyHook()->getSlaveHooks() ) {
ltrace(88) << "* Slave: " << (*ihook)->getComponent() << endl;
if ( (*ihook)->getComponent() == segment ) continue;
layers.insert ( (*ihook)->getComponent()->getLayer() );
}
}
size_t supplemental = (layers.find(segment->getLayer()) == layers.end()) ? 1 : 0;
if ( source->getAnchor() || target->getAnchor() ) supplemental++;
#if 0
bool bottomConnect = false;
bool topConnect = false;
if ( source ) {
if ( segment->getLayer() != source->getLayer() ) {
if ( source->getLayer()->getTop() == segment->getLayer() ) {
bottomConnect = true;
ltrace(88) << "Source bottom connected: " << source << endl;
} else {
topConnect = true;
ltrace(88) << "Source top connected: " << source << endl;
}
}
forEach ( Hook*, ihook, source->getBodyHook()->getSlaveHooks() ) {
ltrace(88) << "* Slave: " << (*ihook)->getComponent() << endl;
if ( (*ihook)->getComponent() == segment ) continue;
if ( (*ihook)->getComponent()->getLayer() == segment->getLayer() ) {
if ( bottomConnect ) topConnect = true;
else bottomConnect = true;
break;
}
}
}
if ( target ) {
if ( segment->getLayer() != target->getLayer() ) {
if ( target->getLayer()->getTop() == segment->getLayer() ) {
bottomConnect = true;
ltrace(88) << "Target bottom connected: " << target << endl;
} else {
topConnect = true;
ltrace(88) << "Target top connected: " << target << endl;
}
}
forEach ( Hook*, ihook, target->getBodyHook()->getSlaveHooks() ) {
ltrace(88) << "* Slave: " << (*ihook)->getComponent() << endl;
if ( (*ihook)->getComponent() == segment ) continue;
if ( (*ihook)->getComponent()->getLayer() == segment->getLayer() ) {
if ( bottomConnect ) topConnect = true;
else bottomConnect = true;
break;
}
}
}
#endif
ltraceout(88);
//return topConnect && bottomConnect;
return layers.size()+supplemental > 2;
}
} // End of anonymous namespace.
namespace Katabatic {
using namespace std;
using Hurricane::tab;
using Hurricane::ltracein;
using Hurricane::ltraceout;
using Hurricane::inltrace;
using Hurricane::DebugSession;
using Hurricane::ForEachIterator;
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::Warning;
using Hurricane::DataBase;
using Hurricane::Technology;
using Hurricane::Layer;
using Hurricane::BasicLayer;
using Hurricane::NetExternalComponents;
using CRL::AllianceFramework;
// -------------------------------------------------------------------
// Global Variables.
const char* missingKTBT =
"%s :\n\n"
" Cell %s do not have any Katabatic (or not yet created).\n";
const char* badMethod =
"%s :\n\n"
" No method id %ud (Cell %s).\n";
const char* lookupFailed =
"Katabatic::Extension::getDatas(Segment*) :\n\n"
" Cannot find AutoSegment associated to %s (internal error).\n";
// -------------------------------------------------------------------
// Class : "Katabatic::KatabaticEngine".
Name KatabaticEngine::_toolName = "Katabatic";
KatabaticEngine* KatabaticEngine::get ( const Cell* cell )
{
return static_cast<KatabaticEngine*>(ToolEngine::get(cell,staticGetName()));
}
const Name& KatabaticEngine::staticGetName ()
{
return _toolName;
}
const Name& KatabaticEngine::getName () const
{
return _toolName;
}
KatabaticEngine::KatabaticEngine ( const RoutingGauge* gauge, Cell* cell )
: ToolEngine (cell)
, _timer ()
, _state (StateCreation)
, _destroyBaseContact(true)
, _destroyBaseSegment(false)
, _demoMode (false)
, _warnGCellOverload (false)
, _configuration (gauge)
, _gcellGrid (NULL)
, _routingNets ()
{ }
void KatabaticEngine::_postCreate ()
{
ToolEngine::_postCreate ();
}
void KatabaticEngine::createDetailedGrid ()
{
_gcellGrid = GCellGrid::create ( this );
Session::revalidate ();
}
KatabaticEngine* KatabaticEngine::create ( const RoutingGauge* gauge, Cell* cell )
{
ltrace(90) << "KatabaticEngine::create() - " << cell << endl;
KatabaticEngine* katabatic = new KatabaticEngine ( gauge, cell );
katabatic->_postCreate ();
return katabatic;
}
KatabaticEngine::~KatabaticEngine ()
{ }
void KatabaticEngine::_preDestroy ()
{
ltrace(90) << "Katabatic::_preDestroy ()" << endl;
ltracein(90);
if ( getState() < Katabatic::StateGutted )
setState ( Katabatic::StatePreDestroying );
_gutKatabatic ();
_state = StateGutted;
ltrace(89) << "About to delete base class ToolEngine." << endl;
ToolEngine::_preDestroy ();
ltrace(89) << "Exiting Katabatic::_preDestroy()." << endl;
ltraceout(90);
cmess2 << " - GCells := " << GCell::getAllocateds() << endl;
cmess2 << " - AutoContacts := " << AutoContact::getAllocateds() << endl;
cmess2 << " - AutoSegments := " << AutoSegment::getAllocateds() << endl;
cmess2 << " - SegmentEnds := " << AutoContact::getSegmentEndAllocateds() << endl;
}
void KatabaticEngine::_gutKatabatic ()
{
Session::open ( this );
_destroyBaseContact = false;
_destroyBaseSegment = false;
if ( _state == StateDriving ) {
ltracein(90);
ltrace(90) << "Saving AutoContacts/AutoSegments." << endl;
cmess1 << " o Driving Hurricane data-base." << endl;
cmess1 << " - AutoSegments := " << AutoSegment::getAllocateds() << endl;
cmess1 << " - AutoContacts := " << AutoContact::getAllocateds() << endl;
forEach ( Net*, inet, _cell->getNets() )
_saveNet ( *inet );
//_autoContactLut.clear ();
ltraceout(90);
}
if ( _state < StateGutted ) {
ltrace(90) << "Gutting Katabatic." << endl;
_state = StateGutted;
_destroyBaseContact = true;
_destroyAutoSegments ();
_destroyAutoContacts ();
if ( _gcellGrid ) {
_gcellGrid->destroy ();
_gcellGrid = NULL;
}
}
Session::close ();
}
AutoSegment* KatabaticEngine::_lookup ( Segment* segment ) const
{
AutoSegmentLut::const_iterator it = _autoSegmentLut.find ( segment );
if ( it == _autoSegmentLut.end() ) return NULL;
return (*it).second;
}
void KatabaticEngine::_link ( AutoSegment* autoSegment )
{
if ( _state > StateActive ) return;
_autoSegmentLut [ autoSegment->getSegment() ] = autoSegment;
}
void KatabaticEngine::_unlink ( AutoSegment* autoSegment )
{
if ( _state > StateDriving ) return;
AutoSegmentLut::iterator it = _autoSegmentLut.find ( autoSegment->getSegment() );
if ( it != _autoSegmentLut.end() )
_autoSegmentLut.erase ( it );
}
AutoContact* KatabaticEngine::_lookup ( Contact* contact ) const
{
AutoContactLut::const_iterator it = _autoContactLut.find ( contact );
if ( it == _autoContactLut.end() ) {
return NULL;
}
return (*it).second;
}
void KatabaticEngine::_link ( AutoContact* autoContact )
{
if ( _state > StateActive ) return;
_autoContactLut [ autoContact->base() ] = autoContact;
}
void KatabaticEngine::_unlink ( AutoContact* autoContact )
{
if ( _state > StateActive ) return;
AutoContactLut::iterator it = _autoContactLut.find ( autoContact->getContact() );
if ( it != _autoContactLut.end() )
_autoContactLut.erase ( it );
}
void KatabaticEngine::xmlWriteGCellGrid ( const string& fileName )
{
ofstream file ( fileName.c_str() );
xmlWriteGCellGrid ( file );
file.close ();
}
void KatabaticEngine::xmlWriteGCellGrid ( ostream& o )
{
if ( _gcellGrid )
_gcellGrid->_xmlWrite ( o );
else
cerr << Error("Cannot dump GCellGrid: not allocated yet.") << endl;
}
void KatabaticEngine::startMeasures ()
{
_timer.resetIncrease ();
_timer.start ();
}
void KatabaticEngine::stopMeasures ()
{
_timer.stop ();
}
void KatabaticEngine::printMeasures () const
{
cmess1 << " - Done in " << Timer::getStringTime(_timer.getCombTime())
<< " [+" << Timer::getStringMemory(_timer.getIncrease()) << "]." << endl;
cmess1 << " (raw measurements : " << _timer.getCombTime()
<< "s [+" << (_timer.getIncrease()>>10) << "Ko/"
<< (_timer.getMemorySize()>>10) << "Ko])" << endl;
}
bool KatabaticEngine::_check ( const char* message ) const
{
bool coherency = true;
if ( message )
cerr << " o checking Katabatic DB (" << message << ")." << endl;
AutoSegmentLut::const_iterator it = _autoSegmentLut.begin ();
AutoSegmentLut::const_iterator end = _autoSegmentLut.end ();
for ( ; it != end ; it++ )
coherency = coherency && it->second->_check();
vector<GCell*>::const_iterator itGCell = _gcellGrid->getGCellVector()->begin();
vector<GCell*>::const_iterator endGCell = _gcellGrid->getGCellVector()->end();
for ( ; itGCell != endGCell ; itGCell++ ) {
vector<AutoContact*>::const_iterator itAutoContact = (*itGCell)->getContacts()->begin();
vector<AutoContact*>::const_iterator endAutoContact = (*itGCell)->getContacts()->end();
for ( ; itAutoContact != endAutoContact ; itAutoContact++ ) {
(*itAutoContact)->checkTopology ();
}
}
if ( message )
cerr << " - completed." << endl;
return coherency;
}
void KatabaticEngine::refresh ( bool openSession )
{
if ( _gcellGrid ) _gcellGrid->updateContacts ( openSession );
}
void KatabaticEngine::_destroyAutoSegments ()
{
ltrace(90) << "Katabatic::_destroyAutoSegments ()" << endl;
size_t expandeds = 0;
AutoSegmentLut::iterator it = _autoSegmentLut.begin ();
AutoSegmentLut::iterator end = _autoSegmentLut.end ();
for ( ; it != end ; it++ ) {
if ( !it->second->isCollapsed() ) expandeds++;
it->second->destroy ();
}
if ( _state == StateDriving )
cerr << " - Expandeds := " << expandeds << endl;
_autoSegmentLut.clear ();
}
void KatabaticEngine::_destroyAutoContacts ()
{
ltrace(90) << "Katabatic::_destroyAutoContacts ()" << endl;
AutoContactLut::iterator it = _autoContactLut.begin ();
AutoContactLut::iterator end = _autoContactLut.end ();
for ( ; it != end ; it++ )
it->second->destroy ();
_autoContactLut.clear ();
}
Configuration* KatabaticEngine::getConfiguration ()
{ return &_configuration; }
void KatabaticEngine::loadGlobalRouting ( unsigned int method, vector<Net*>& nets )
{
if ( _state < StateGlobalLoaded )
throw Error ("KatabaticEngine::loadGlobalRouting() : global routing not present yet.");
if ( _state > StateGlobalLoaded )
throw Error ("KatabaticEngine::loadGlobalRouting() : global routing already loaded.");
AllianceFramework* af = AllianceFramework::get ();
if ( nets.empty() ) {
forEach ( Net*, net, _cell->getNets() ) {
if ( net->getType() == Net::Type::POWER ) continue;
if ( net->getType() == Net::Type::GROUND ) continue;
if ( net->getType() == Net::Type::CLOCK ) continue;
if ( af->isOBSTACLE(net->getName()) ) continue;
_routingNets.push_back ( *net );
}
} else {
vector<Net*>::iterator it = nets.begin();
for ( ; it != nets.end() ; it++ ) {
if ( ( (*it)->getType() == Net::Type::POWER )
|| ( (*it)->getType() == Net::Type::GROUND )
|| ( (*it)->getType() == Net::Type::CLOCK )
|| ( af->isOBSTACLE((*it)->getName()) ) ) {
cerr << Warning("%s is not a routable net, removed from set.",getString(*it).c_str()) << endl;
} else
_routingNets.push_back ( *it );
}
}
switch ( method ) {
case LoadGrByNet: _loadGrByNet(); break;
case LoadGrByGCell:
default:
throw Error ( badMethod
, "Katabatic::loadGlobalRouting()"
, method
, getString(_cell).c_str()
);
}
_state = StateActive;
}
void KatabaticEngine::finalizeLayout ()
{
ltrace(90) << "Katabatic::finalizeLayout()" << endl;
if ( _state > StateDriving ) return;
_state = StateDriving;
startMeasures ();
_gutKatabatic ();
stopMeasures ();
printMeasures ();
_state = StateGutted;
}
void KatabaticEngine::_alignate ( Net* net )
{
DebugSession::open ( net, 99 );
ltrace(100) << "Katabatic::_alignate ( " << net << " )" << endl;
ltracein(99);
//cmess2 << " - " << getString(net) << endl;
set<Segment*> exploredSegments;
vector<AutoSegment*> unexploreds;
vector<AutoSegment*> aligneds;
forEach ( Component*, icomponent, net->getComponents() ) {
Segment* segment = dynamic_cast<Segment*>(*icomponent);
if ( segment ) {
AutoSegment* seedSegment = Session::lookup ( segment );
if ( seedSegment ) unexploreds.push_back ( seedSegment );
}
}
sort ( unexploreds.begin(), unexploreds.end(), AutoSegment::CompareCanonical() );
for ( size_t i=0 ; i<unexploreds.size() ; i++ ) {
AutoSegment* seedSegment = unexploreds[i];
if ( exploredSegments.find(seedSegment->getSegment()) == exploredSegments.end() ) {
ltrace(99) << "New chunk from: " << seedSegment << endl;
aligneds.push_back ( seedSegment );
forEach ( AutoSegment*, collapsed, seedSegment->getCollapseds() ) {
ltrace(99) << "Aligned: " << *collapsed << endl;
aligneds.push_back ( *collapsed );
exploredSegments.insert ( collapsed->getSegment() );
}
ltracein(99);
sort ( aligneds.begin(), aligneds.end(), AutoSegment::CompareCanonical() );
ltrace(99) << "Seed: " << (void*)aligneds[0]->base() << " " << aligneds[0] << endl;
for ( size_t j=1 ; j<aligneds.size() ; j++ ) {
ltrace(99) << "Secondary: " << (void*)(aligneds[j]->base()) << " " << aligneds[j] << endl;
}
ltrace(159) << "Align on " << aligneds[0]
<< " " << DbU::getLambda(aligneds[0]->getAxis()) << endl;
aligneds[0]->setAxis ( aligneds[0]->getAxis(), Realignate|AxisSet );
aligneds.clear ();
ltraceout(99);
}
}
ltraceout(99);
DebugSession::close ();
}
void KatabaticEngine::_canonize ( Net* net )
{
DebugSession::open ( net, 99 );
ltrace(100) << "Katabatic::_canonize ( " << net << " )" << endl;
ltracein(99);
//cmess2 << " - " << getString(net) << endl;
set<Segment*> exploredSegments;
vector<AutoSegment*> unexploreds;
vector<AutoSegment*> aligneds;
forEach ( Component*, icomponent, net->getComponents() ) {
Segment* segment = dynamic_cast<Segment*>(*icomponent);
if ( segment ) {
AutoSegment* seedSegment = Session::lookup ( segment );
if ( seedSegment )
unexploreds.push_back ( seedSegment );
}
}
sort ( unexploreds.begin(), unexploreds.end(), AutoSegment::CompareCanonical() );
for ( size_t i=0 ; i<unexploreds.size() ; i++ ) {
AutoSegment* seedSegment = unexploreds[i];
if ( exploredSegments.find(seedSegment->getSegment()) == exploredSegments.end() ) {
ltrace(99) << "New chunk from: " << (void*)seedSegment->base() << ":" << seedSegment << endl;
aligneds.push_back ( seedSegment );
bool isCanonicalLocal = seedSegment->isLocal();
forEach ( AutoSegment*, collapsed, seedSegment->getCollapseds() ) {
ltrace(99) << "Aligned: " << (void*)collapsed->base() << ":" << *collapsed << endl;
aligneds.push_back ( *collapsed );
exploredSegments.insert ( collapsed->getSegment() );
if ( collapsed->isGlobal() ) isCanonicalLocal = false;
}
ltracein(99);
sort ( aligneds.begin(), aligneds.end(), AutoSegment::CompareCanonical() );
aligneds[0]->setCanonical ( true );
aligneds[0]->setCanonicalLocal ( isCanonicalLocal );
ltrace(99) << "Canonical: " << (void*)aligneds[0]->base() << ":" << aligneds[0] << endl;
for ( size_t j=1 ; j<aligneds.size() ; j++ ) {
aligneds[j]->setCanonical ( false );
ltrace(99) << "Secondary: " << (void*)(aligneds[j]->base()) << ":" << aligneds[j] << endl;
}
ltrace(159) << "Align on " << aligneds[0]
<< " " << DbU::getLambda(aligneds[0]->getAxis()) << endl;
aligneds[0]->setAxis ( aligneds[0]->getAxis(), Realignate|AxisSet );
aligneds.clear ();
ltraceout(99);
}
}
ltraceout(99);
DebugSession::close ();
}
void KatabaticEngine::_computeNetTerminals ( Net* net )
{
DebugSession::open ( net, 88 );
ltrace(100) << "Katabatic::_computeNetTerminals ( " << net << " )" << endl;
ltracein(99);
vector<AutoSegment*> segments;
forEach ( Segment*, segment, net->getSegments() ) {
AutoSegment* autoSegment = Session::lookup ( *segment );
if ( !autoSegment ) continue;
if ( autoSegment->isInvalidated() ) autoSegment->_computeTerminal();
}
ltraceout(99);
DebugSession::close ();
}
void KatabaticEngine::_saveNet ( Net* net )
{
DebugSession::open ( net, 88 );
ltrace(90) << "Katabatic::_saveNet() " << net << endl;
ltracein(90);
vector<AutoContact*> autoContacts;
forEach ( Contact*, icontact, net->getContacts() ) {
AutoContact* autoContact = Session::lookup ( *icontact );
if ( autoContact )
autoContacts.push_back ( autoContact );
}
ltrace(90) << "Breaking/Deleting AutoContacts." << endl;
vector<AutoContact*>::iterator it = autoContacts.begin();
for ( ; it != autoContacts.end() ; it++ ) {
ltrace(90) << "Examining " << (void*)*it << " " << (*it) << endl;
ltracein(90);
ltrace(90) << "In " << (void*)((*it)->getGCell()) << " - "
<< (*it)->getGCell() << endl;
(*it)->breakUp ();
// AutoContacts are destroyed through the tool.
//(*it)->destroy ();
ltraceout(90);
}
ltrace(90) << "Deleting zero-length segments." << endl;
vector<Segment*> nullSegments;
set<const Layer*> connectedLayers;
forEach ( Segment*, segment, net->getSegments() ) {
if ( segment->getLength() ) {
if ( net->isExternal() ) {
NetExternalComponents::setExternal ( *segment );
}
continue;
}
if ( not isTopAndBottomConnected(*segment,connectedLayers) ) {
nullSegments.push_back ( *segment );
ltrace(90) << "* Null Length: " << *segment << endl;
}
}
setDestroyBaseSegment ( true );
for ( size_t i = 0 ; i < nullSegments.size() ; i++ ) {
Contact* source = dynamic_cast<Contact*>(nullSegments[i]->getSource());
Contact* target = dynamic_cast<Contact*>(nullSegments[i]->getTarget());
if ( source->getAnchor() ) {
if ( target->getAnchor() ) {
continue;
//cerr << Bug("Both source & target are anchored while deleting zero-length segment:\n"
// " %s.",getString(nullSegments[i]).c_str()) << endl;
} else
swap ( source, target );
}
ltrace(90) << "Deleting: " << nullSegments[i] << endl;
if ( isTopAndBottomConnected(nullSegments[i],connectedLayers) ) {
ltrace(90) << "Deletion cancelled, no longer top or bottom connected." << endl;
continue;
}
ltrace(90) << "* Source: " << (void*)source << " " << source << endl;
ltrace(90) << "* Target: " << (void*)target << " " << target << endl;
const Layer* layer = DataBase::getDB()->getTechnology()
->getViaBetween ( *connectedLayers.begin(), *connectedLayers.rbegin() );
ltrace(90) << *connectedLayers.begin() << " + " << *connectedLayers.rbegin() << endl;
ltrace(90) << "* Shrink layer: " << layer << endl;
if ( !layer ) {
cerr << Error("NULL contact layer while deleting %s."
,getString(nullSegments[i]).c_str()) << endl;
continue;
}
Session::lookup ( nullSegments[i] )->destroy ();
vector<Hook*> slaveHooks;
Hook* masterHook = source->getBodyHook()->getPreviousMasterHook();
while ( masterHook->getNextHook() != source->getBodyHook() ) {
slaveHooks.push_back ( masterHook->getNextHook() );
ltrace(90) << "* detach: "
<< (void*)masterHook->getNextHook()->getComponent()
<< " " << masterHook->getNextHook()->getComponent() << endl;
masterHook->getNextHook()->detach ();
}
source->destroy ();
masterHook = target->getBodyHook ();
for ( size_t j=0 ; j < slaveHooks.size() ; j++ ) {
slaveHooks[j]->attach ( masterHook );
}
ltrace(90) << (void*)target << " " << target << " setLayer: " << layer << endl;
target->setLayer ( layer );
}
setDestroyBaseSegment ( false );
ltraceout(90);
DebugSession::close ();
}
void KatabaticEngine::_check ( Net* net ) const
{
ltrace(200) << "Checking " << net << endl;
ltracein(200);
forEach ( Segment*, isegment, net->getComponents().getSubSet<Segment*>() ) {
AutoSegment* autoSegment = _lookup ( *isegment );
ltrace(200) << autoSegment << endl;
if ( autoSegment ) {
AutoContact* autoContact = autoSegment->getAutoSource();
ltrace(200) << autoContact << endl;
if ( autoContact ) autoContact->checkTopology ();
autoContact = autoSegment->getAutoTarget();
ltrace(200) << autoContact << endl;
if ( autoContact ) autoContact->checkTopology ();
}
}
ltraceout(200);
}
void KatabaticEngine::_print ( Net* net ) const
{
cerr << "Order: Components of " << net << endl;
vector<AutoSegment*> segments;
forEach ( Segment*, isegment, net->getComponents().getSubSet<Segment*>() ) {
AutoSegment* autoSegment = _lookup ( *isegment );
if ( autoSegment )
segments.push_back ( autoSegment );
}
sort ( segments.begin(), segments.end(), AutoSegment::CompareCanonical() );
Interval constraints;
for ( size_t i=0 ; i<segments.size() ; i++ ) {
segments[i]->getConstraints ( constraints );
cerr << "Order: " << i
<< " " << segments[i]->isCanonical()
<< " " << segments[i]->isCollapsed()
<< " " << setw(6) << DbU::getValueString(segments[i]->getSourceU())
<< " " << setw(6) << DbU::getValueString(segments[i]->getLength())
<< " " << segments[i]->isGlobal()
<< " " << segments[i]->isTerminal()
<< " " << segments[i]->isHorizontal()
<< " " << setw(6) << DbU::getValueString(segments[i]->getAxis())
<< " " << segments[i]->isFixed()
<< " [" << DbU::getValueString(constraints.getVMin())
<< ":" << DbU::getValueString(constraints.getVMax())
<< "] " << segments[i]
<< endl;
}
}
void KatabaticEngine::_print () const
{
#if defined(CHECK_DETERMINISM)
cerr << "Order: Nets components." << endl;
#endif
vector<Net*> nets;
forEach ( Net*, inet, getCell()->getNets() ) {
nets.push_back ( *inet );
}
sort ( nets.begin(), nets.end(), NetCompareByName() );
#if defined(CHECK_DETERMINISM)
for ( size_t i=0 ; i<nets.size() ; i++ )
_print ( nets[i] );
#endif
}
string KatabaticEngine::_getTypeName () const
{
return "Katabatic";
}
string KatabaticEngine::_getString () const
{
ostringstream os;
os << "<" << "Katabatic " << _cell->getName () << " " << _configuration.getRoutingGauge()->getName() << ">";
return ( os.str() );
}
Record* KatabaticEngine::_getRecord () const
{
Record* record = ToolEngine::_getRecord ();
record->add ( getSlot ( "_demoMode" , _demoMode ) );
record->add ( getSlot ( "_state" , _state ) );
record->add ( getSlot ( "_configuration" , &_configuration ) );
record->add ( getSlot ( "_gcellGrid" , _gcellGrid ) );
record->add ( getSlot ( "_routingNets" , &_routingNets ) );
record->add ( getSlot ( "_autoContactLut" , &_autoContactLut ) );
record->add ( getSlot ( "_autoSegmentLut" , &_autoSegmentLut ) );
return ( record );
}
} // End of Katabatic namespace.