657 lines
18 KiB
C++
657 lines
18 KiB
C++
|
|
// -*- 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 : "./AutoSegments.cpp" |
|
|
// | *************************************************************** |
|
|
// | U p d a t e s |
|
|
// | |
|
|
// x-----------------------------------------------------------------x
|
|
|
|
|
|
#include "hurricane/Error.h"
|
|
#include "katabatic/AutoContact.h"
|
|
#include "katabatic/AutoSegment.h"
|
|
|
|
|
|
namespace Katabatic {
|
|
|
|
|
|
using namespace std;
|
|
using Hurricane::tab;
|
|
using Hurricane::inltrace;
|
|
using Hurricane::ltracein;
|
|
using Hurricane::ltraceout;
|
|
using Hurricane::_TName;
|
|
using Hurricane::Error;
|
|
using Hurricane::ForEachIterator;
|
|
using Hurricane::Hook;
|
|
using Hurricane::Contact;
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Katabatic::AutoSegmentStack".
|
|
|
|
|
|
void AutoSegmentStack::push ( AutoContact* contact, AutoSegment* segment )
|
|
{
|
|
ltrace(80) << "Stacking " << contact << " + " << segment << endl;
|
|
|
|
push_back(make_pair(contact,segment));
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Katabatic::AutoSegments_OnContact".
|
|
|
|
|
|
AutoSegments_OnContact::Locator::Locator ( AutoSegment* master, Contact* contact )
|
|
: AutoSegmentHL()
|
|
, _master(master)
|
|
, _element(NULL)
|
|
{
|
|
_hook = contact->getBodyHook()->getPreviousMasterHook();
|
|
progress ();
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_OnContact::Locator::getClone () const
|
|
{
|
|
return new Locator(*this);
|
|
}
|
|
|
|
|
|
AutoSegment* AutoSegments_OnContact::Locator::getElement () const
|
|
{
|
|
return _element;
|
|
}
|
|
|
|
|
|
bool AutoSegments_OnContact::Locator::isValid () const
|
|
{
|
|
return !_hook;
|
|
}
|
|
|
|
|
|
void AutoSegments_OnContact::Locator::progress ()
|
|
{
|
|
ltrace(80) << "AutoSegments_OnContact::Locator::progress()" << endl;
|
|
|
|
while ( _hook && !_hook->isMaster() ) {
|
|
_hook = _hook->getNextHook();
|
|
_element = NULL;
|
|
|
|
if ( _hook->isMaster() ) { _hook = NULL; break; }
|
|
|
|
Segment* segment = dynamic_cast<Segment*>( _hook->getComponent() );
|
|
if ( segment ) _element = Session::lookup ( segment );
|
|
|
|
if ( !_element || (_element == _master) ) continue;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
string AutoSegments_OnContact::Locator::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_OnContact::Locator")
|
|
+ getString(_element)
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
AutoSegmentHC* AutoSegments_OnContact::getClone () const
|
|
{
|
|
return new AutoSegments_OnContact(*this);
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_OnContact::getLocator () const
|
|
{
|
|
return new Locator(_master,_contact);
|
|
}
|
|
|
|
|
|
string AutoSegments_OnContact::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_OnContact") + " "
|
|
+ getString(_master)
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "AutoSegments_Collapsed".
|
|
|
|
|
|
AutoSegments_Collapsed::Locator::Locator ( AutoSegment* segment, bool withPerpand )
|
|
: AutoSegmentHL()
|
|
, _withPerpand(withPerpand)
|
|
, _master(segment)
|
|
, _stack()
|
|
{
|
|
if ( not _master ) return;
|
|
|
|
AutoContact* contact = segment->getAutoSource();
|
|
if ( contact ) _stack.push ( contact, segment );
|
|
|
|
contact = segment->getAutoTarget();
|
|
if ( contact ) _stack.push ( contact, segment );
|
|
|
|
progress ();
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_Collapsed::Locator::getClone () const
|
|
{
|
|
return new Locator(*this);
|
|
}
|
|
|
|
|
|
bool AutoSegments_Collapsed::Locator::isValid () const
|
|
{
|
|
return !_stack.isEmpty();
|
|
}
|
|
|
|
|
|
void AutoSegments_Collapsed::Locator::progress ()
|
|
{
|
|
ltrace(80) << "AutoSegments_Collapsed::Locator::progress()" << endl;
|
|
|
|
while ( !_stack.isEmpty() ) {
|
|
AutoContact* sourceContact = _stack.getAutoContact ();
|
|
AutoSegment* sourceSegment = _stack.getAutoSegment ();
|
|
|
|
_stack.pop ();
|
|
|
|
forEach ( Component*, component, sourceContact->getSlaveComponents() ) {
|
|
if ( *component == sourceSegment->getSegment() ) continue;
|
|
|
|
Segment* segment = dynamic_cast<Segment*>(*component);
|
|
if ( !segment ) continue;
|
|
|
|
AutoSegment* currentSegment = Session::lookup ( segment );
|
|
if ( !currentSegment ) {
|
|
cerr << Error("Can't lookup <AutoSegment> for %s.",getString(segment).c_str()) << endl;
|
|
continue;
|
|
}
|
|
|
|
unsigned int state = AutoSegment::getPerpandicularState ( sourceContact
|
|
, sourceSegment
|
|
, currentSegment
|
|
, _master
|
|
);
|
|
if ( state & (AutoSegment::PerpandicularIndirect
|
|
|AutoSegment::ParallelOrExpanded
|
|
|AutoSegment::ParallelAndLayerChange ) ) {
|
|
ltrace(98) << "Reject: " << currentSegment << endl;
|
|
continue;
|
|
}
|
|
|
|
AutoContact* targetContact = currentSegment->getOppositeAnchor ( sourceContact );
|
|
if ( targetContact ) _stack.push ( targetContact, currentSegment );
|
|
}
|
|
|
|
if ( _stack.isEmpty() ) break;
|
|
if ( _stack.getAutoSegment() == _master ) continue;
|
|
if ( AutoSegment::areAligneds(_stack.getAutoSegment(),_master) || _withPerpand ) break;
|
|
}
|
|
}
|
|
|
|
|
|
string AutoSegments_Collapsed::Locator::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_Collapsed::Locator")
|
|
+ ">";
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
AutoSegmentHC* AutoSegments_Collapsed::getClone () const
|
|
{
|
|
return new AutoSegments_Collapsed(*this);
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_Collapsed::getLocator () const
|
|
{
|
|
return new Locator(_segment,_withPerpand);
|
|
}
|
|
|
|
|
|
AutoSegment* AutoSegments_Collapsed::Locator::getElement () const
|
|
{
|
|
return _stack.getAutoSegment();
|
|
}
|
|
|
|
|
|
string AutoSegments_Collapsed::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_Collapsed") + " "
|
|
+ getString(_segment)
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "AutoSegments_CollapsedPerpandicular".
|
|
|
|
|
|
AutoSegments_CollapsedPerpandicular::Locator::Locator ( AutoSegment* segment )
|
|
: AutoSegmentHL()
|
|
, _master(segment)
|
|
, _stack()
|
|
, _perpandiculars()
|
|
{
|
|
ltrace(80) << "AutoSegments_CollapsedPerpandicular::Locator::Locator()" << endl;
|
|
ltrace(80) << " " << _master << endl;
|
|
|
|
if ( not _master ) return;
|
|
|
|
AutoContact* contact = segment->getAutoSource();
|
|
if ( contact ) _stack.push ( contact, segment );
|
|
|
|
contact = segment->getAutoTarget();
|
|
if ( contact ) _stack.push ( contact, segment );
|
|
|
|
progress ();
|
|
}
|
|
|
|
|
|
AutoSegment* AutoSegments_CollapsedPerpandicular::Locator::getElement () const
|
|
{
|
|
if ( _perpandiculars.empty() ) return NULL;
|
|
return _perpandiculars.back ();
|
|
}
|
|
|
|
|
|
void AutoSegments_CollapsedPerpandicular::Locator::progress ()
|
|
{
|
|
ltrace(80) << "AutoSegments_CollapsedPerpandicular::Locator::progress()" << endl;
|
|
|
|
if ( !_perpandiculars.empty() ) _perpandiculars.pop_back ();
|
|
if ( !_perpandiculars.empty() ) return;
|
|
|
|
while ( !_stack.isEmpty() ) {
|
|
AutoContact* sourceContact = _stack.getAutoContact ();
|
|
AutoSegment* sourceSegment = _stack.getAutoSegment ();
|
|
|
|
_stack.pop ();
|
|
|
|
forEach ( Component*, component, sourceContact->getSlaveComponents() ) {
|
|
if ( *component == sourceSegment->getSegment() ) continue;
|
|
|
|
Segment* segment = dynamic_cast<Segment*>(*component);
|
|
if ( !segment ) continue;
|
|
|
|
AutoSegment* currentSegment = Session::lookup ( segment );
|
|
if ( !currentSegment ) {
|
|
cerr << Error("Can't lookup <AutoSegment> for %s.",getString(segment).c_str()) << endl;
|
|
continue;
|
|
}
|
|
|
|
ltrace(99) << " Try Perpandicular: " << currentSegment << endl;
|
|
unsigned int state = AutoSegment::getPerpandicularState ( sourceContact
|
|
, sourceSegment
|
|
, currentSegment
|
|
, _master
|
|
);
|
|
|
|
if ( state & AutoSegment::PerpandicularAny ) {
|
|
_perpandiculars.push_back ( currentSegment );
|
|
ltrace(99) << "Stacked Perpandicular: " << currentSegment << endl;
|
|
}
|
|
if ( state & (AutoSegment::PerpandicularIndirect
|
|
|AutoSegment::ParallelOrExpanded
|
|
|AutoSegment::ParallelAndLayerChange ) )
|
|
continue;
|
|
|
|
ltrace(99) << "Stacked Opposite of: " << currentSegment << endl;
|
|
|
|
AutoContact* targetContact = currentSegment->getOppositeAnchor ( sourceContact );
|
|
if ( targetContact ) _stack.push ( targetContact, currentSegment );
|
|
}
|
|
|
|
if ( _stack.isEmpty() ) break;
|
|
if ( _stack.getAutoSegment() == _master ) continue;
|
|
if ( !_perpandiculars.empty() ) break;
|
|
}
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_CollapsedPerpandicular::Locator::getClone () const
|
|
{
|
|
return new Locator(*this);
|
|
}
|
|
|
|
|
|
bool AutoSegments_CollapsedPerpandicular::Locator::isValid () const
|
|
{
|
|
return !_perpandiculars.empty();
|
|
}
|
|
|
|
|
|
AutoSegmentHC* AutoSegments_CollapsedPerpandicular::getClone () const
|
|
{
|
|
return new AutoSegments_CollapsedPerpandicular(*this);
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_CollapsedPerpandicular::getLocator () const
|
|
{
|
|
return new Locator(_segment);
|
|
}
|
|
|
|
|
|
string AutoSegments_CollapsedPerpandicular::Locator::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_CollapsedPerpandicular::Locator")
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
string AutoSegments_CollapsedPerpandicular::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_CollapsedPerpandicular") + " "
|
|
+ getString(_segment)
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "AutoSegments_AnchorOnGCell".
|
|
|
|
|
|
AutoSegments_AnchorOnGCell::Locator::Locator ( GCell* fcell, bool sourceAnchor, unsigned int direction )
|
|
: AutoSegmentHL()
|
|
, _sourceAnchor(sourceAnchor)
|
|
, _direction(direction)
|
|
, _itContact(fcell->getContacts()->begin())
|
|
, _itEnd(fcell->getContacts()->end())
|
|
, _hookLocator(NULL)
|
|
, _element(NULL)
|
|
{
|
|
progress ();
|
|
}
|
|
|
|
|
|
AutoSegments_AnchorOnGCell::Locator::~Locator ()
|
|
{
|
|
if ( _hookLocator ) delete _hookLocator;
|
|
}
|
|
|
|
|
|
AutoSegment* AutoSegments_AnchorOnGCell::Locator::getElement () const
|
|
{
|
|
return _element;
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_AnchorOnGCell::Locator::getClone () const
|
|
{
|
|
return new Locator(*this);
|
|
}
|
|
|
|
|
|
bool AutoSegments_AnchorOnGCell::Locator::isValid () const
|
|
{
|
|
return _element != NULL;
|
|
}
|
|
|
|
|
|
void AutoSegments_AnchorOnGCell::Locator::progress ()
|
|
{
|
|
ltrace(80) << "AutoSegments_AnchorOnGCell::Locator::progress()" << endl;
|
|
ltracein(79);
|
|
|
|
while ( true ) {
|
|
if ( _hookLocator == NULL ) {
|
|
if ( _itContact == _itEnd ) {
|
|
ltrace(79) << "No more AutoContacts" << endl;
|
|
ltraceout(79);
|
|
return;
|
|
}
|
|
|
|
ltrace(79) << *_itContact << endl;
|
|
|
|
_hookLocator = (*_itContact)->getBodyHook()->getSlaveHooks().getLocator();
|
|
_itContact++;
|
|
} else {
|
|
_hookLocator->progress ();
|
|
}
|
|
|
|
while ( _hookLocator->isValid() ) {
|
|
ltrace(79) << _hookLocator->getElement() << endl;
|
|
Hook* hook = dynamic_cast<Segment::SourceHook*>(_hookLocator->getElement());
|
|
if ( hook ) {
|
|
_element = Session::lookup ( static_cast<Segment*>(hook->getComponent()) );
|
|
if ( _element->isHorizontal() ) {
|
|
if ( _direction & Constant::Horizontal ) { ltraceout(79); return; }
|
|
} else
|
|
if ( _direction & Constant::Vertical ) { ltraceout(79); return; }
|
|
}
|
|
_hookLocator->progress();
|
|
}
|
|
_hookLocator = NULL;
|
|
_element = NULL;
|
|
}
|
|
|
|
ltraceout(79);
|
|
}
|
|
|
|
|
|
string AutoSegments_AnchorOnGCell::Locator::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_AnchorOnGCell::Locator")
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
AutoSegmentHC* AutoSegments_AnchorOnGCell::getClone () const
|
|
{
|
|
return new AutoSegments_AnchorOnGCell(*this);
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_AnchorOnGCell::getLocator () const
|
|
{
|
|
return new Locator(_fcell,_sourceAnchor,_direction);
|
|
}
|
|
|
|
|
|
string AutoSegments_AnchorOnGCell::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_AnchorOnGCell") + " "
|
|
+ getString(_fcell)
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Katabatic::AutoSegments_AnchoredBySource".
|
|
|
|
|
|
AutoSegments_AnchoredBySource::Locator::Locator ( AutoContact* sourceAnchor, unsigned int direction )
|
|
: AutoSegmentHL()
|
|
, _direction(direction)
|
|
, _hookLocator(NULL)
|
|
, _element(NULL)
|
|
{
|
|
_contactLocator = sourceAnchor->getCollapseds(_direction).getLocator();
|
|
progress ();
|
|
}
|
|
|
|
|
|
AutoSegments_AnchoredBySource::Locator::~Locator ()
|
|
{
|
|
if ( _hookLocator ) delete _hookLocator;
|
|
if ( _contactLocator ) delete _contactLocator;
|
|
}
|
|
|
|
|
|
AutoSegment* AutoSegments_AnchoredBySource::Locator::getElement () const
|
|
{
|
|
return _element;
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_AnchoredBySource::Locator::getClone () const
|
|
{
|
|
return new Locator(*this);
|
|
}
|
|
|
|
|
|
bool AutoSegments_AnchoredBySource::Locator::isValid () const
|
|
{
|
|
return _element != NULL;
|
|
}
|
|
|
|
|
|
void AutoSegments_AnchoredBySource::Locator::progress ()
|
|
{
|
|
ltrace(80) << "AutoSegments_AnchoredBySource::Locator::progress()" << endl;
|
|
ltracein(79);
|
|
|
|
while ( true ) {
|
|
if ( _hookLocator == NULL ) {
|
|
if ( !_contactLocator->isValid() ) {
|
|
ltrace(79) << "No more AutoContacts" << endl;
|
|
ltraceout(79);
|
|
return;
|
|
}
|
|
|
|
ltrace(79) << _contactLocator->getElement() << endl;
|
|
|
|
_hookLocator = _contactLocator->getElement()->getBodyHook()->getSlaveHooks().getLocator();
|
|
_contactLocator->progress ();
|
|
} else {
|
|
_hookLocator->progress ();
|
|
}
|
|
|
|
while ( _hookLocator->isValid() ) {
|
|
ltrace(79) << _hookLocator->getElement() << endl;
|
|
Hook* hook = dynamic_cast<Segment::SourceHook*>(_hookLocator->getElement());
|
|
if ( hook ) {
|
|
_element = Session::lookup ( static_cast<Segment*>(hook->getComponent()) );
|
|
if ( _element->isHorizontal() ) {
|
|
if ( _direction & Constant::Horizontal ) { ltraceout(79); return; }
|
|
} else
|
|
if ( _direction & Constant::Vertical ) { ltraceout(79); return; }
|
|
}
|
|
_hookLocator->progress();
|
|
}
|
|
_hookLocator = NULL;
|
|
_element = NULL;
|
|
}
|
|
|
|
ltraceout(79);
|
|
}
|
|
|
|
|
|
AutoSegmentHL* AutoSegments_AnchoredBySource::getLocator () const
|
|
{
|
|
return new Locator(_sourceContact,_direction);
|
|
}
|
|
|
|
|
|
AutoSegmentHC* AutoSegments_AnchoredBySource::getClone () const
|
|
{
|
|
return new AutoSegments_AnchoredBySource(*this);
|
|
}
|
|
|
|
|
|
string AutoSegments_AnchoredBySource::Locator::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_AnchoredBySource::Locator")
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
string AutoSegments_AnchoredBySource::_getString () const
|
|
{
|
|
string s = "<" + _TName("AutoSegments_AnchoredBySource") + " "
|
|
+ getString(_sourceContact)
|
|
+ ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "AutoSegments_IsAccountable".
|
|
|
|
|
|
AutoSegmentHF* AutoSegments_IsAccountable::getClone () const
|
|
{
|
|
return new AutoSegments_IsAccountable();
|
|
}
|
|
|
|
|
|
bool AutoSegments_IsAccountable::accept ( AutoSegment* segment ) const
|
|
{
|
|
return segment->isCanonical() && !segment->isCollapsed();
|
|
}
|
|
|
|
|
|
string AutoSegments_IsAccountable::_getString () const
|
|
{
|
|
return "<AutoSegments_IsAccountable>";
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "AutoSegments_InDirection".
|
|
|
|
|
|
AutoSegmentHF* AutoSegments_InDirection::getClone () const
|
|
{
|
|
return new AutoSegments_InDirection(_direction);
|
|
}
|
|
|
|
|
|
bool AutoSegments_InDirection::accept ( AutoSegment* segment ) const
|
|
{
|
|
return ( segment->isHorizontal() && (_direction & Constant::Horizontal) )
|
|
|| ( segment->isVertical () && (_direction & Constant::Vertical ) );
|
|
}
|
|
|
|
|
|
string AutoSegments_InDirection::_getString () const
|
|
{
|
|
return "<AutoSegments_InDirection>";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// x-----------------------------------------------------------------x
|
|
// | Functions Definitions |
|
|
// x-----------------------------------------------------------------x
|
|
|
|
|
|
} // End of Katabatic namespace.
|