// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved // // =================================================================== // // $Id$ // // x-----------------------------------------------------------------x // | | // | C O R I O L I S | // | K i t e - D e t a i l e d R o u t e r | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | // | C++ Module : "./TrackSegment.cpp" | // | *************************************************************** | // | U p d a t e s | // | | // x-----------------------------------------------------------------x #include #include "hurricane/Bug.h" #include "hurricane/Warning.h" #include "hurricane/Net.h" #include "hurricane/Name.h" #include "hurricane/RoutingPad.h" #include "katabatic/AutoContact.h" #include "crlcore/RoutingGauge.h" #include "kite/GCell.h" #include "kite/DataNegociate.h" #include "kite/TrackSegment.h" #include "kite/TrackCost.h" #include "kite/Track.h" #include "kite/Session.h" #include "kite/RoutingEvent.h" #include "kite/NegociateWindow.h" #include "kite/KiteEngine.h" namespace Kite { using namespace std; using Hurricane::inltrace; using Hurricane::ltracein; using Hurricane::ltraceout; using Hurricane::tab; using Hurricane::ForEachIterator; using Hurricane::Bug; using Hurricane::Error; using Hurricane::Net; using Hurricane::Name; using Hurricane::RoutingPad; // ------------------------------------------------------------------- // Class : "TrackSegment". TrackSegment::TrackSegment ( AutoSegment* segment, Track* track ) : TrackElement (track) , _base (segment) , _gcell (NULL) , _created (true) , _lock (true) , _revalidated (false) , _sourceDogLeg (false) , _targetDogLeg (false) , _canRipple (false) , _routed (false) , _area (0) , _data (NULL) , _dogLegLevel (0) , _dogLegOrder (0) { if (segment) { _data = new DataNegociate ( this ); _base->getCanonical ( _sourceU, _targetU ); setArea (); //update (); } } void TrackSegment::_postCreate () { TrackElement::_postCreate (); Session::link ( this ); vector gcells; getGCells ( gcells ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif } TrackSegment::~TrackSegment () { if ( _data ) delete _data; } void TrackSegment::_preDestroy () { ltrace(90) << "TrackSegment::_preDestroy() - " << (void*)this << " [" << (void*)_base << ", " << (void*)(_base?_base->base():NULL) << "]" << endl; Session::unlink ( this ); TrackElement::_preDestroy (); } TrackElement* TrackSegment::create ( AutoSegment* segment, Track* track, bool& created ) { created = false; TrackElement* trackElement = Session::lookup ( segment->base() ); if ( !trackElement ) { TrackSegment* trackSegment = new TrackSegment ( segment, track ); trackSegment->_postCreate (); created = true; trackSegment->invalidate (); ltrace(200) << "TrackSegment::create(): " << trackSegment << endl; trackElement = trackSegment; } return trackElement; } // Formerly Inline Functions. AutoSegment* TrackSegment::base () const { return _base; } bool TrackSegment::isCreated () const { return _created; } bool TrackSegment::isFixed () const { return _base->isFixed(); } bool TrackSegment::isStrap () const { return _base->isCanonicalStrap(); } bool TrackSegment::isSlackenStrap () const { return _base->isSlackenStrap(); } bool TrackSegment::isLocal () const { return _base->isCanonicalLocal(); } bool TrackSegment::isGlobal () const { return !isLocal(); } bool TrackSegment::isLocked () const { return _lock; } bool TrackSegment::isTerminal () const { return _base->isTerminal(); } bool TrackSegment::isRevalidated () const { return _revalidated; } bool TrackSegment::isRouted () const { return _routed; } bool TrackSegment::isSlackened () const { return _base->isSlackened(); } bool TrackSegment::isSlackenDogLeg () const { return isSlackened() and (_dogLegLevel > 0); } bool TrackSegment::hasSourceDogLeg () const { return _sourceDogLeg; } bool TrackSegment::hasTargetDogLeg () const { return _targetDogLeg; } bool TrackSegment::allowOutsideGCell () const { return _base->allowOutsideGCell(); } bool TrackSegment::canGoOutsideGCell () const { return _base->canGoOutsideGCell(); } bool TrackSegment::canRipple () const { return _canRipple; } unsigned long TrackSegment::getId () const { return _base->getId(); } GCell* TrackSegment::getGCell () const { return _gcell; } DbU::Unit TrackSegment::getAxis () const { return _base->getAxis(); } unsigned long TrackSegment::getArea () const { return _area; } unsigned int TrackSegment::getDogLegLevel () const { return _dogLegLevel; } unsigned int TrackSegment::getDogLegOrder () const { return _dogLegOrder; } Interval TrackSegment::getSourceConstraints () const { return _base->getSourceConstraints(); } Interval TrackSegment::getTargetConstraints () const { return _base->getTargetConstraints(); } DataNegociate* TrackSegment::getDataNegociate () const { return _data; } TrackElements TrackSegment::getCollapsedPerpandiculars () { return new TrackElements_CollapsedPerpandicular(this); } void TrackSegment::setAllowOutsideGCell ( bool state ) { _base->setAllowOutsideGCell(state,true); } void TrackSegment::setLock ( bool state ) { _lock = state; } void TrackSegment::setRevalidated ( bool state ) { _revalidated = state; } void TrackSegment::invalidate () { _base->invalidate(); } void TrackSegment::setCanRipple ( bool state ) { _canRipple = state; } void TrackSegment::setSourceDogLeg ( bool state ) { _sourceDogLeg = state; } void TrackSegment::setTargetDogLeg ( bool state ) { _targetDogLeg = state; } TrackElement* TrackSegment::getCanonical ( Interval& i ) { return Session::lookup ( _base->getCanonical(i)->base() ); } bool TrackSegment::canSlacken () const { return (not isSlackened())?(_base->canSlacken(true)):false; } bool TrackSegment::isHorizontal () const { return _base->isHorizontal(); } bool TrackSegment::isVertical () const { return _base->isVertical(); } unsigned int TrackSegment::getDirection () const { return _base->getDirection(); } Net* TrackSegment::getNet () const { return _base->getNet(); } const Layer* TrackSegment::getLayer () const { return _base->getLayer(); } // DbU::Unit TrackSegment::getSourceU () const // { return _base->getSourceU(); } // DbU::Unit TrackSegment::getTargetU () const // { return _base->getTargetU(); } TrackElement* TrackSegment::getNext () const { size_t dummy = _index; return _track->getNext ( dummy, getNet() ); } TrackElement* TrackSegment::getPrevious () const { size_t dummy = _index; return _track->getPrevious ( dummy, getNet() ); } Interval TrackSegment::getFreeInterval ( bool useOrder ) const { if ( !_track ) return Interval(false); size_t begin = _index; size_t end = _index; return _track->expandFreeInterval ( begin, end, Track::Inside, getNet(), useOrder ); } size_t TrackSegment::getGCells ( vector& gcells ) const { vector().swap ( gcells ); GCell* sourceGCell = Session::lookup(base()->getAutoSource()->getGCell()); GCell* targetGCell = Session::lookup(base()->getAutoTarget()->getGCell()); ltrace(148) << "getGCells(): sourceGCell: " << sourceGCell << endl; ltrace(148) << "getGCells(): targetGCell: " << targetGCell << endl; forEach ( AutoSegment*, isegment, base()->getCollapseds() ) { GCell* gcell = Session::lookup(isegment->getAutoSource()->getGCell()); if ( gcell->getIndex() < sourceGCell->getIndex() ) { sourceGCell = gcell; ltrace(148) << "getGCells(): new sourceGCell: " << sourceGCell << endl; } gcell = Session::lookup(isegment->getAutoTarget()->getGCell()); if ( gcell->getIndex() > targetGCell->getIndex() ) { targetGCell = gcell; ltrace(148) << "getGCells(): new targetGCell: " << targetGCell << endl; } } if ( not sourceGCell or not targetGCell ) return 0; if ( not sourceGCell ) { gcells.push_back ( targetGCell ); return 1; } if ( not targetGCell ) { gcells.push_back ( sourceGCell ); return 1; } if ( isHorizontal() ) { gcells.push_back ( sourceGCell ); while ( sourceGCell != targetGCell ) { sourceGCell = sourceGCell->getRight(); if ( not sourceGCell ) break; //cerr << " Pushing: " << sourceGCell << endl; gcells.push_back ( sourceGCell ); } } else { gcells.push_back ( sourceGCell ); while ( sourceGCell != targetGCell ) { sourceGCell = sourceGCell->getUp(); if ( not sourceGCell ) break; gcells.push_back ( sourceGCell ); } } return gcells.size(); } void TrackSegment::setGCell ( GCell* gcell ) { _gcell = gcell; if (_data and not (_data->isBorder() or _data->isRing())) _data->setGCellOrder( (_gcell) ? _gcell->getOrder() : (unsigned int)-1 ); } size_t TrackSegment::getPerpandicularsBound ( set& bounds ) { bounds.clear (); set baseBounds; set::iterator ibase; _base->getPerpandicularsBound ( baseBounds ); for ( ibase = baseBounds.begin() ; ibase != baseBounds.end() ; ibase++ ) { TrackElement* segment = Session::lookup ( *ibase ); if ( segment ) bounds.insert ( segment ); } return bounds.size(); } unsigned int TrackSegment::getOrder () const { if ( _data == NULL ) return numeric_limits::max(); return _data->getGCellOrder (); } void TrackSegment::setDogLegLevel ( unsigned int level ) { if ( level > 15 ) { cerr << Bug("%s has reached maximum dog leg count (15)." ,_getString().c_str()) << endl; level = 15; } _dogLegLevel = level; } void TrackSegment::setDogLegOrder ( unsigned int order ) { ltrace(200) << "setDogLegOrder(): " << order << " " << this << endl; if ( order > 32768 ) { cerr << Bug("%s has reached maximum dog leg order (32768)." ,_getString().c_str()) << endl; order = 32768; } _dogLegOrder = order; } void TrackSegment::dataInvalidate () { if (_data) _data->invalidate(); } void TrackSegment::eventInvalidate () { if ( !_data ) return; RoutingEvent* event = _data->getRoutingEvent(); if ( event ) event->invalidate ( true ); } void TrackSegment::setArea () { //float length = getValue ( getTargetU() - getSourceU() ); //float height = getValue ( getSlack() ); //_area = (unsigned long)( length * height ); _area = _base->getSlack(); } void TrackSegment::setRouted ( bool state ) { _routed = state; } void TrackSegment::setTrack ( Track* track ) { TrackElement::setTrack ( track ); #if ENABLE_STIFFNESS updateGCellsStiffness ( ((track != NULL) ? TrackElement::Routed : TrackElement::UnRouted ) ); #endif } void TrackSegment::detach () { ltrace(200) << "TrackSegment::detach() - " << endl; setTrack ( NULL ); setIndex ( (size_t)-1 ); setLock ( true ); //updateGCellsStiffness ( TrackElement::UnRouted ); } void TrackSegment::revalidate ( bool invalidEvent ) { _created = false; ltrace(148) << "revalidate() - " << this << endl; _base->getCanonical ( _sourceU, _targetU ); _data->update (); if ( invalidEvent ) _data->invalidate ( true, true ); if ( _track ) Session::addSortEvent ( _track ); _revalidated = true; } void TrackSegment::setAxis ( DbU::Unit axis, unsigned int flags ) { _base->setAxis ( axis, flags ); invalidate (); } void TrackSegment::updateGCellsStiffness ( unsigned int flags ) { if ( Session::getKiteEngine()->getState() > Katabatic::StateDriving ) return; vector gcells; getGCells ( gcells ); int count = 0; if ( flags & TrackElement::AddToGCells ) { if ( getTrack() ) { flags |= TrackSegment::Routed; _routed = false; } //cerr << "INC:"; count = +1; } if ( flags & TrackElement::RemoveFromGCells ) { if ( getTrack() ) { flags |= TrackSegment::UnRouted; _routed = true; } //cerr << "DEC:"; count = -1; } if ( count ) { //cerr << count << " SegmentCount() for " << this << endl; for ( size_t i=0 ; iincSegmentCount ( count ); //cerr << "| " << gcells[i] << endl; } } count = 0; if ( not _routed and (flags & TrackElement::Routed ) ) { count = +1; _routed = true; } if ( _routed and (flags & TrackElement::UnRouted) ) { count = -1; _routed = false; } if ( count ) { for ( size_t i=0 ; iincRoutedCount ( count ); //cerr << "Update (" << count << ") " << gcells[i] << " for: " << this << endl; } } } void TrackSegment::swapTrack ( TrackElement* other ) { if ( !other ) return; ltrace(200) << "TrackSegment::swapTrack()" << endl; size_t thisIndex = getIndex (); Track* thisTrack = getTrack (); size_t otherIndex = other->getIndex (); Track* otherTrack = other->getTrack (); if ( _track and otherTrack and (_track != otherTrack) ) { cerr << Error("TrackSegment::swapTrack() - swapping TrackSement from different tracks.") << endl; } // detach (); // other->detach (); // if ( thisTrack ) thisTrack ->insert ( other ); // if ( otherTrack ) otherTrack->insert ( this ); setTrack ( NULL ); other->setTrack ( NULL ); // if ( _track ) updateGCellsStiffness ( TrackElement::UnRouted ); // if ( otherTrack ) other->updateGCellsStiffness ( TrackElement::UnRouted ); //other->setRouted ( thisRouted ); other->setTrack ( thisTrack ); other->setIndex ( thisIndex ); if ( thisTrack ) thisTrack->setSegment ( other, thisIndex ); //setRouted ( otherRouted ); setTrack ( otherTrack ); setIndex ( otherIndex ); if ( _track ) _track->setSegment ( this, _index ); #if defined(CHECK_DATABASE_DISABLED) if ( _track ) _track->_check(); else if ( other->getTrack() ) other->getTrack()->_check(); #endif RoutingEvent* thisEvent = getDataNegociate()->getRoutingEvent(); RoutingEvent* otherEvent = other->getDataNegociate()->getRoutingEvent(); if ( thisEvent ) thisEvent ->setSegment ( other ); if ( otherEvent ) otherEvent->setSegment ( this ); ltrace(200) << "| this: " << this << endl; ltrace(200) << "| other: " << other << endl; } void TrackSegment::reschedule ( unsigned int level ) { ltrace(200) << "TrackSegment::reschedule() - " << this << endl; ltracein(200); ltrace(200) << "GCell: " << _gcell << endl; ltrace(200) << "GCell::order:" << _gcell->getOrder() << " Data::order:" << getOrder() << " Session::order:" << Session::getOrder() << endl; if ( getOrder() == Session::getOrder() ) { if ( not _data or not _data->hasRoutingEvent() ) Session::getNegociateWindow()->addInsertEvent ( this, level ); else { if ( _track != NULL ) Session::addRemoveEvent ( this ); Session::getNegociateWindow()->rescheduleEvent ( _data->getRoutingEvent(), level ); } } else { if ( _data and _data->hasRoutingEvent() ) _data->getRoutingEvent()->setDisabled(); if ( getOrder() > Session::getOrder() ) { if ( _track != NULL ) Session::addRemoveEvent ( this ); } } ltraceout(200); } void TrackSegment::slacken () { if ( not isSlackened() ) { ltrace(200) << "TrackSegment::slacken()" << endl; ltracein(200); // set collapseds; // collapseds.insert ( _base ); // forEach ( AutoSegment*, isegment, _base->getCollapseds() ) { // collapseds.insert ( *isegment ); // } //unsigned int direction = Constant::perpandicular ( getDirection() ); //unsigned int doglegLevel = getDogLegLevel() + 1; //setSlackened ( true ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::RemoveFromGCells ); #endif base()->slacken ( true ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif _postModify (); // const vector& invalidateds = Session::getInvalidateds(); // if ( not invalidateds.empty() ) { // vector segments; // for ( size_t i=0 ; ibase()->isTerminal() or (collapseds.find(segment->base()) != collapseds.end()) ) // // segment->setSlackened ( true ); // if ( segment->isCreated() ) { // //segment->setSlackened ( true ); // if ( segment->getDirection() == direction ) { // ltrace(200) << "Increasing dogleg level to: " << doglegLevel << endl; // segment->setDogLegLevel ( doglegLevel ); // if ( segment->getOrder() > Session::getOrder() ) { // ltrace(200) << "Adding to ring: " << segment << endl; // Session::getNegociateWindow()->addToRing ( segment ); // } // } // } // segment->reschedule ( 0 ); // } // for ( size_t i=0 ; icanPivotUp(reserve); } bool TrackSegment::canMoveUp ( float reserve ) const { // if ( isLocal() /*and (hasSourceDogLeg() or hasTargetDogLeg())*/ ) { // return _base->canPivotUp(); // } return _base->canMoveUp ( true, reserve ); } bool TrackSegment::moveUp () { bool success = false; ltrace(160) << "TrackSegment::moveUp()" << endl; ltracein(200); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::RemoveFromGCells ); #endif success = base()->moveUp ( true ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif const vector& invalidateds = Session::getInvalidateds(); if ( not invalidateds.empty() ) { vector segments; for ( size_t i=0 ; igetTrack() == NULL) // or (segment->getLayer() != segment->getTrack()->getLayer()) ) segment->reschedule ( 0 ); } for ( size_t i=0 ; isetState ( DataNegociate::ConflictSolve1, true ); _data->resetRipupCount (); } ltraceout(200); return success; } bool TrackSegment::moveAside ( bool onLeft ) { bool success = true; ltrace(200) << "TrackSegment::moveAside() - " << (onLeft?"left":"right") << endl; ltracein(200); unsigned int order = _data->getGCellOrder(); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::RemoveFromGCells ); #endif if ( onLeft ) base()->moveULeft (); else base()->moveURight (); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif const vector& invalidateds = Session::getInvalidateds(); if ( not invalidateds.empty() ) { vector segments; for ( size_t i=0 ; ireschedule ( 0 ); } if ( _data->getGCellOrder() < order ) { cinfo << "[INFO] Putting TrackSegment of order " << order << " into GCell " << getGCell() << endl; _data->setGCellOrder ( order ); } for ( size_t i=0 ; igetAutoSource()->getSlaveComponents().getSubSet() ) { dogleg = Session::lookup ( *isegment ); if ( dogleg and (dogleg->getDirection() == direction) ) { ltrace(200) << "Source dogleg: " << dogleg << endl; return dogleg; } } return NULL; } TrackElement* TrackSegment::getTargetDogLeg () { if ( !hasSourceDogLeg() ) return NULL; unsigned int direction = Constant::perpandicular ( getDirection() ); TrackElement* dogleg = NULL; forEach ( Segment*, isegment, base()->getAutoTarget()->getSlaveComponents().getSubSet() ) { dogleg = Session::lookup ( *isegment ); if ( dogleg and (dogleg->getDirection() == direction) ) { ltrace(200) << "Target dogleg: " << dogleg << endl; return dogleg; } } return NULL; } bool TrackSegment::canDogLeg ( Interval interval ) { ltrace(200) << "TrackSegment::canDogLeg(Interval) " << interval << endl; if ( isFixed() ) { ltrace(200) << "Failed: is fixed" << endl; return false; } if ( not isLocal() ) { ltrace(200) << "Failed: is not local" << endl; return false; } if ( getDogLegOrder() < Session::getOrder() ) { ltrace(200) << "No dogleg in current order " << Session::getOrder() << " yet, allowing (previous:" << _dogLegOrder << ")" << endl; setDogLegOrder ( Session::getOrder() ); setSourceDogLeg ( false ); setTargetDogLeg ( false ); } if ( hasSourceDogLeg() or hasTargetDogLeg() or isSlackened() ) { ltrace(200) << "Failed: already has source and/or target dogleg or slackened." << endl; return false; } return _base->canDogLeg(interval); } TrackElement* TrackSegment::makeDogLeg ( Interval interval, bool& leftDogleg ) { ltrace(200) << "TrackSegment::makeDogLeg(Interval)" << endl; bool upLayer = (Session::getRoutingGauge()->getLayerDepth(getLayer()) < 2); GCell* originalGCell = getGCell (); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::RemoveFromGCells ); #endif base()->makeDogLeg ( interval, upLayer, leftDogleg ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif return _postDogLeg ( originalGCell ); } bool TrackSegment::canDogLeg () { ltrace(200) << "TrackSegment::canDogLeg()" << endl; if ( not isLocal() ) { ltrace(200) << "Failed: is not local." << endl; return false; } if ( isFixed() ) { ltrace(200) << "Failed: is fixed." << endl; return false; } if ( isSlackened() ) { ltrace(200) << "Failed: is local & slackened." << endl; return false; } if ( getDogLegOrder() < Session::getOrder() ) { ltrace(200) << "No dogleg in current order " << Session::getOrder() << " yet, allowing (previous:" << _dogLegOrder << ")" << endl; setDogLegOrder ( Session::getOrder() ); setSourceDogLeg ( false ); setTargetDogLeg ( false ); } if ( hasSourceDogLeg() || hasTargetDogLeg() ) return false; return true; } TrackElement* TrackSegment::makeDogLeg () { AutoContact* source = _base->getAutoSource(); AutoContact* target = _base->getAutoTarget(); GCell* gcell = Session::lookup ( _base->getAutoSource()->getGCell() ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::RemoveFromGCells ); #endif TrackElement* dogleg = makeDogLeg ( gcell ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif if ( dogleg ) { if ( source->isTerminal() xor target->isTerminal() ) { if ( target->isTerminal() ) source = target; DbU::Unit axis = (_base->isHorizontal()) ? source->getX() : source->getY(); ltrace(200) << "Setting dogleg axis @" << DbU::getValueString(axis) << endl; dogleg->setAxis ( axis ); } return _postDogLeg(gcell); } return NULL; } bool TrackSegment::canDogLegAt ( GCell* dogLegGCell, bool allowReuse ) { ltrace(200) << "TrackSegment::canDogLegAt(GCell*) " << dogLegGCell << endl; if ( getDogLegOrder() < Session::getOrder() ) { ltrace(200) << "No dogleg in current order " << Session::getOrder() << " yet, allowing (previous:" << _dogLegOrder << ")" << endl; setDogLegOrder ( Session::getOrder() ); setSourceDogLeg ( false ); setTargetDogLeg ( false ); } if ( isFixed() ) { ltrace(200) << "Cannot dogleg a fixed segment." << endl; return false; } if ( isLocal() ) { if ( hasSourceDogLeg() or hasTargetDogLeg() ) { ltrace(200) << "Cannot dogleg again a local segment." << endl; return false; } if ( isSlackened() ) { ltrace(200) << "Cannot dogleg a local slackened segment." << endl; return false; } } // if ( Session::getRoutingGauge()->getLayerDepth(getLayer()) > 3 ) { // ltrace(200) << "Cannot dogleg on the last top layer." << endl; // return false; // } vector gcells; getGCells ( gcells ); ltrace(190) << "Source: " << *gcells.begin () << endl; ltrace(190) << "Target: " << *gcells.rbegin() << endl; bool isGCellInside = false; for ( size_t igcell=0 ; igcellgetUSide(getDirection(),false).intersect(getCanonicalInterval()) ) { // ltrace(200) << "Segment is almost outside the breaking GCell." << endl; // return false; //} break; } if ( not isGCellInside ) { ltrace(200) << "dogleg GCell is outside segment support (go outside GCell active)." << endl; return false; } return true; } TrackElement* TrackSegment::makeDogLeg ( GCell* dogLegGCell ) { ltrace(200) << "TrackSegment::makeDogLeg(GCell*)" << endl; ltrace(200) << "Break in: " << dogLegGCell << endl; bool upLayer = (Session::getRoutingGauge()->getLayerDepth(getLayer()) < 2); GCell* originalGCell = getGCell (); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::RemoveFromGCells ); #endif base()->makeDogLeg ( dogLegGCell->base(), upLayer ); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif return _postDogLeg ( originalGCell ); } TrackElement* TrackSegment::_postDogLeg ( GCell* originalGCell ) { ltracein(200); TrackElement* perpandicular = NULL; const vector& dogLegs = Session::getDogLegs(); if ( not dogLegs.empty() ) { vector segments; for ( size_t i=0 ; ibase() == dogLegs[i])*/ ) // segments[i]->setSlackened (true); segments[i]->setDogLegOrder ( Session::getOrder() ); switch ( i ) { case 0: segments[i]->setTargetDogLeg(); segments[i]->getDataNegociate()->resetRipupCount(); if ( segments[i] != this ) { cerr << Error ( "Incoherency in TrackSegment LUT, lookup of %p gives %p instead of %p (this)" , dogLegs[i], segments[i], this ) << endl; } break; case 1: perpandicular = segments[i]; segments[i]->setSourceDogLeg (); segments[i]->setTargetDogLeg (); segments[i]->setDogLegLevel ( getDogLegLevel()+1 ); break; case 2: segments[i]->setSourceDogLeg (); break; } } ltrace(200) << "Before break: " << originalGCell << endl; ltrace(200) << "After break: " << getGCell() << endl; if ( getGCell() != originalGCell ) swapTrack ( segments[2] ); for ( size_t i=0 ; ireschedule ( ((i==1) ? 0 : 1) ); if ( i == 1 ) { ltrace(200) << "Set canDogleg: dogleg:" << segments[1]->getDataNegociate()->getGCellOrder() << " vs. session:" << Session::getOrder() << endl; if ( segments[1]->getOrder() > Session::getOrder()) { segments[i]->setCanRipple ( true ); ltrace(200) << "Adding to ring: " << segments[i] << endl; Session::getNegociateWindow()->addToRing ( segments[i] ); } } else { if ( segments[i]->getOrder() > Session::getOrder()) { AutoContact* source = segments[i]->base()->getAutoSource(); AutoContact* target = segments[i]->base()->getAutoTarget(); if ( (source and dynamic_cast(source->getAnchor())) or (target and dynamic_cast(target->getAnchor()))) { ltrace(200) << "Adding to ring: " << segments[i] << endl; Session::getNegociateWindow()->addToRing ( segments[i] ); } } } //if ( i == 1 ) { // RoutingEvent* event = segments[i]->getDataNegociate()->getRoutingEvent(); // if ( event ) // event->setCanGoOutsideGCell ( true ); //} } ltrace(200) << "original: " << segments[0] << endl; ltrace(200) << "perpand: " << segments[1] << endl; ltrace(200) << "new paral: " << segments[2] << endl; } ltraceout(200); return perpandicular; } bool TrackSegment::canDesalignate () const { ltrace(200) << "TrackSegment::canDesalignate()" << endl; return _base->canDesalignate(); // Interval baseSpan = _base->getSpanU (); // if ( baseSpan.getVMin() - Session::getExtensionCap() > _sourceCanonical ) return _base->canDesalignate(); // if ( baseSpan.getVMax() + Session::getExtensionCap() < _targetCanonical ) return _base->canDesalignate(); // return false; } void TrackSegment::desalignate () { ltrace(200) << "TrackSegment::desalignate()" << endl; ltracein(200); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::RemoveFromGCells ); #endif _base->desalignate (); #if ENABLE_STIFFNESS updateGCellsStiffness ( TrackElement::AddToGCells ); #endif _postModify (); // const vector& invalidateds = Session::getInvalidateds(); // if ( not invalidateds.empty() ) { // vector segments; // for ( size_t i=0 ; ireschedule ( 0 ); // if ( segments[i]->getDataNegociate()->getGCellOrder() > Session::getOrder() ) { // ltrace(200) << "Adding to ring: " << segments[i] << endl; // Session::getNegociateWindow()->addToRing ( segments[i] ); // } // } // for ( size_t i=0 ; i& invalidateds = Session::getInvalidateds(); vector segments; if ( not invalidateds.empty() ) { for ( size_t i=0 ; iisCreated() and (segment->getDirection() == perpandicularDir) ) { ltrace(200) << "Increasing dogleg level to: " << doglegLevel << endl; segment->setDogLegLevel ( doglegLevel ); } if ( segment->getDataNegociate()->getGCellOrder() == Session::getOrder() ) { if ( segment->getDirection() == parallelDir ) { forEach ( TrackElement*, iperpandicular, segment->getCollapsedPerpandiculars() ) { ltrace(200) << "| pp: " << *iperpandicular << endl; if ( iperpandicular->getDataNegociate()->getGCellOrder() == Session::getOrder() ) { iperpandicular->reschedule ( 0 ); } else if ( iperpandicular->getDataNegociate()->getGCellOrder() > Session::getOrder() ) { ltrace(200) << "Adding to ring: " << *iperpandicular << endl; Session::getNegociateWindow()->addToRing ( *iperpandicular ); } } segment->reschedule ( 0 ); } } else if ( segment->getDataNegociate()->getGCellOrder() > Session::getOrder()) { if ( segment->getDirection() == parallelDir ) { AutoContact* source = segment->base()->getAutoSource(); AutoContact* target = segment->base()->getAutoTarget(); if ( (source and dynamic_cast(source->getAnchor())) or (target and dynamic_cast(target->getAnchor()))) { ltrace(200) << "Adding to ring: " << segment << endl; Session::getNegociateWindow()->addToRing ( segment ); } } } } ltraceout(200); } bool TrackSegment::_check () const { if ( !base() ) return true; bool coherency = true; if ( !base()->isCanonical() ) { cerr << "[CHECK] " << this << " supporting AutoSegment is not canonical." << endl; coherency = false; } DbU::Unit min; DbU::Unit max; base()->getCanonical ( min, max ); if ( getSourceU() != min ) { cerr << "[CHECK] " << this << " has bad source position " << DbU::getValueString(min) << "." << endl; coherency = false; } if ( getTargetU() != max ) { cerr << "[CHECK] " << this << " has bad target position " << DbU::getValueString(max) << "." << endl; coherency = false; } #if ENABLE_STIFFNESS if ( _routed xor (_track != NULL) ) { cerr << "[CHECK] " << this << " incoherency between routed/track flags." << endl; } #endif return coherency; } string TrackSegment::_getTypeName () const { return "TrackSegment"; } string TrackSegment::_getString () const { string s1 = _base->_getString(); string s2 = " [" + DbU::getValueString(_sourceU) + ":" + DbU::getValueString(_targetU) + "]" + " " + DbU::getValueString(_targetU-_sourceU) + " " + getString(_dogLegLevel) + " o:" + getString(_data->getGCellOrder()) + " [" + ((_track) ? getString(_index) : "npos") + "] " + ((isSlackened() ) ? "S" : "-") + ((_track ) ? "T" : "-") + ((_canRipple ) ? "r" : "-") + ((_data->isBorder()) ? "B" : "-") + ((_data->isRing ()) ? "R" : "-") + ((_sourceDogLeg ) ? "s" : "-") + ((_targetDogLeg ) ? "t" : "-"); s1.insert ( s1.size()-1, s2 ); return s1; } Record* TrackSegment::_getRecord () const { Record* record = TrackElement::_getRecord (); record->add ( getSlot ( "_base" , _base ) ); record->add ( getSlot ( "_lock" , _lock ) ); record->add ( getSlot ( "_revalidated", _revalidated ) ); return record; } } // End of Kite namespace.