coriolis/kite/src/TrackSegment.cpp

1222 lines
38 KiB
C++
Raw Normal View History

// -*- 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 <sstream>
#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<GCell*> 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<GCell*>& gcells ) const
{
vector<GCell*>().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<TrackElement*>& bounds )
{
bounds.clear ();
set<AutoSegment*> baseBounds;
set<AutoSegment*>::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<unsigned int>::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() - <id:" << getId() << ">" << 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<GCell*> 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 ; i<gcells.size() ; ++i ) {
gcells[i]->incSegmentCount ( 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 ; i<gcells.size() ; ++i ) {
gcells[i]->incRoutedCount ( 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<AutoSegment*> 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<AutoSegment*>& invalidateds = Session::getInvalidateds();
// if ( not invalidateds.empty() ) {
// vector<TrackElement*> segments;
// for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
// ltrace(200) << "slacken: " << invalidateds[i] << endl;
// TrackElement* segment = GCell::addTrackSegment(NULL,invalidateds[i],false);
// segments.push_back ( segment );
// //if ( segment->base()->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 ; i<segments.size() ; i++ ) {
// ltrace(200) << "slacken: " << segments[i] << endl;
// }
// }
ltraceout(200);
} else
throw Bug("TrackSegment::slacken(): NULL base or already slackened.");
}
bool TrackSegment::canPivotUp () const
{
return _base->canPivotUp();
}
bool TrackSegment::canMoveUp () const
{
// if ( isLocal() /*and (hasSourceDogLeg() or hasTargetDogLeg())*/ ) {
// return _base->canPivotUp();
// }
return _base->canMoveUp ( true );
}
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<AutoSegment*>& invalidateds = Session::getInvalidateds();
if ( not invalidateds.empty() ) {
vector<TrackElement*> segments;
for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
ltrace(200) << "moved: " << invalidateds[i] << endl;
segments.push_back ( GCell::addTrackSegment(NULL,invalidateds[i],false) );
segments.back()->reschedule ( 0 );
}
for ( size_t i=0 ; i<segments.size() ; i++ ) {
ltrace(200) << "moved: " << segments[i] << endl;
}
if ( _data ) _data->setState ( DataNegociate::ConflictSolve1, true );
}
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<AutoSegment*>& invalidateds = Session::getInvalidateds();
if ( not invalidateds.empty() ) {
vector<TrackElement*> segments;
for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
ltrace(200) << "moved: " << invalidateds[i] << endl;
segments.push_back ( GCell::addTrackSegment(NULL,invalidateds[i],false) );
segments.back()->reschedule ( 0 );
}
if ( _data->getGCellOrder() < order ) {
cinfo << "[INFO] Putting TrackSegment of order " << order
<< " into GCell " << getGCell() << endl;
_data->setGCellOrder ( order );
}
for ( size_t i=0 ; i<segments.size() ; i++ ) {
ltrace(200) << "moved: " << segments[i] << endl;
}
}
ltraceout(200);
return success;
}
TrackElement* TrackSegment::getSourceDogLeg ()
{
if ( !hasSourceDogLeg() ) return NULL;
unsigned int direction = Constant::perpandicular ( getDirection() );
TrackElement* dogleg = NULL;
forEach ( Segment*, isegment, base()->getAutoSource()->getSlaveComponents().getSubSet<Segment*>() ) {
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<Segment*>() ) {
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<GCell*> gcells;
getGCells ( gcells );
ltrace(190) << "Source: " << *gcells.begin () << endl;
ltrace(190) << "Target: " << *gcells.rbegin() << endl;
bool isGCellInside = false;
for ( size_t igcell=0 ; igcell<gcells.size() ; igcell++ ) {
if ( dogLegGCell != gcells[igcell] ) continue;
isGCellInside = true;
if ( igcell == 0 ) {
if ( hasSourceDogLeg() ) {
if ( allowReuse ) return true;
ltrace(200) << "Cannot dogleg again in source GCell." << endl;
return false;
}
}
if ( hasTargetDogLeg() && (igcell == gcells.size()-1) ) {
if ( allowReuse ) return true;
ltrace(200) << "Cannot dogleg again in target GCell." << endl;
return false;
}
//if ( dogLegGCell->getUSide(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<AutoSegment*>& dogLegs = Session::getDogLegs();
if ( not dogLegs.empty() ) {
vector<TrackElement*> segments;
for ( size_t i=0 ; i<dogLegs.size() ; i++ ) {
ltrace(200) << "Looking up: " << dogLegs[i] << endl;
segments.push_back ( GCell::addTrackSegment(NULL,dogLegs[i]) );
//if ( isSlackened() /*&& (segments[i]->base() == 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 ; i<dogLegs.size() ; i++ ) {
segments[i]->reschedule ( ((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<RoutingPad*>(source->getAnchor()))
or (target and dynamic_cast<RoutingPad*>(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<AutoSegment*>& invalidateds = Session::getInvalidateds();
// if ( not invalidateds.empty() ) {
// vector<TrackElement*> segments;
// for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
// ltrace(200) << "desaligned: " << invalidateds[i] << endl;
// segments.push_back ( GCell::addTrackSegment(NULL,invalidateds[i],false) );
// segments[i]->reschedule ( 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<segments.size() ; i++ ) {
// ltrace(200) << "desaligned: " << segments[i] << endl;
// }
// }
ltraceout(200);
}
void TrackSegment::_postModify ()
{
ltrace(200) << "TrackSegment::_postModify()" << endl;
ltracein(200);
unsigned int doglegLevel = getDogLegLevel() + 1;
unsigned int parallelDir = getDirection ();
unsigned int perpandicularDir = Constant::perpandicular ( parallelDir );
const vector<AutoSegment*>& invalidateds = Session::getInvalidateds();
vector<TrackElement*> segments;
if ( not invalidateds.empty() ) {
for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
ltrace(200) << "invalidated: " << invalidateds[i] << endl;
TrackElement* segment = GCell::addTrackSegment(NULL,invalidateds[i],false);
segments.push_back ( segment );
}
}
for ( size_t i=0 ; i<segments.size() ; ++i ) {
TrackElement* segment = segments[i];
ltrace(200) << "Post proccess: " << segment << endl;
if ( segment->isCreated() 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<RoutingPad*>(source->getAnchor()))
or (target and dynamic_cast<RoutingPad*>(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" : "-")
+ ((_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.