// -*- 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 : "./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( _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(*component); if ( !segment ) continue; AutoSegment* currentSegment = Session::lookup ( segment ); if ( !currentSegment ) { cerr << Error("Can't lookup 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(*component); if ( !segment ) continue; AutoSegment* currentSegment = Session::lookup ( segment ); if ( !currentSegment ) { cerr << Error("Can't lookup 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(_hookLocator->getElement()); if ( hook ) { _element = Session::lookup ( static_cast(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(_hookLocator->getElement()); if ( hook ) { _element = Session::lookup ( static_cast(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 ""; } // ------------------------------------------------------------------- // 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 ""; } // x-----------------------------------------------------------------x // | Functions Definitions | // x-----------------------------------------------------------------x } // End of Katabatic namespace.