// -*- 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 : "./Track.cpp" | // | *************************************************************** | // | U p d a t e s | // | | // x-----------------------------------------------------------------x #include #include #include #include #include "hurricane/Warning.h" #include "hurricane/Bug.h" #include "hurricane/Layer.h" #include "hurricane/Net.h" #include "kite/RoutingPlane.h" #include "kite/Track.h" #include "kite/TrackMarker.h" #include "kite/DataNegociate.h" namespace { using namespace std; using namespace CRL; using namespace Kite; struct isDetachedSegment { bool operator() ( const TrackElement* s ) { return !s->getTrack(); }; }; DbU::Unit getPositionByIterator ( const vector& v, size_t i ) { return (*(v.begin()+i))->getSourceU(); } } // End of local namespace. namespace Kite { using std::lower_bound; using std::remove_if; using std::sort; using Hurricane::dbo_ptr; using Hurricane::tab; using Hurricane::inltrace; using Hurricane::ltracein; using Hurricane::ltraceout; using Hurricane::Warning; using Hurricane::Bug; using Hurricane::Layer; using Hurricane::Net; // ------------------------------------------------------------------- // Class : "Track". const size_t Track::NPOS = (size_t)-1; Track::Track ( RoutingPlane* routingPlane, unsigned int index ) : _routingPlane (routingPlane) , _index (index) , _axis (routingPlane->getTrackPosition(index)) , _min (routingPlane->getTrackMin()) , _max (routingPlane->getTrackMax()) , _segments () , _markers () , _segmentsValid(false) , _markersValid (false) { } void Track::_postCreate () { } Track::~Track () { ltrace(90) << "Track::~Track() - " << (void*)this << endl; } void Track::_preDestroy () { ltrace(90) << "Track::_preDestroy() - " << (void*)this << " " << this << endl; ltracein(90); for ( size_t i=0 ; i<_segments.size() ; i++ ) if ( _segments[i] ) _segments[i]->detach(); for ( size_t i=0 ; i<_markers.size() ; i++ ) if ( _markers[i] ) _markers[i]->destroy(); ltraceout(90); } void Track::destroy () { ltrace(90) << "Track::destroy() - " << (void*)this << " " << this << endl; Track::_preDestroy (); delete this; } KiteEngine* Track::getKiteEngine () const { return _routingPlane->getKiteEngine(); } unsigned int Track::getDepth () const { return _routingPlane->getDepth(); } const Layer* Track::getLayer () const { return _routingPlane->getLayer(); } const Layer* Track::getBlockageLayer () const { return _routingPlane->getBlockageLayer(); } TrackElement* Track::getSegment ( size_t index ) const { if ( (index == NPOS) || (index >= getSize()) ) return NULL; return _segments[index]; } TrackElement* Track::getSegment ( DbU::Unit position ) const { unsigned int state; size_t begin; size_t end; getIBounds ( position, begin, end, state ); if ( state & (MinTrackMin|MaxTrackMax) ) return NULL; return getSegment(begin); } TrackElement* Track::getNext ( size_t& index, Net* net, bool useOrder ) const { for ( index++ ; index < _segments.size() ; index++ ) { if ( _segments[index]->getNet() == net ) continue; if ( useOrder and _segments[index]->getDataNegociate() and (_segments[index]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) continue; return _segments[index]; } index = NPOS; return NULL; } TrackElement* Track::getPrevious ( size_t& index, Net* net, bool useOrder ) const { for ( index-- ; index != NPOS ; index-- ) { if ( inltrace(148) ) { cerr << tab << index << ":"; cerr.flush(); cerr << _segments[index] << endl; } if ( _segments[index]->getNet() == net ) continue; if ( useOrder and _segments[index]->getDataNegociate() and (_segments[index]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) continue; return _segments[index]; } index = NPOS; return NULL; } TrackElement* Track::getNextFixed ( size_t& index ) const { TrackElement* nextFixed = getNext ( index, NULL ); for ( ; nextFixed ; nextFixed = getNext(index,NULL) ) { if ( nextFixed->base()->isFixed() ) return nextFixed; } return nextFixed; } void Track::getIBounds ( DbU::Unit position, size_t& begin, size_t& end, unsigned int& state ) const { if ( _segments.empty() ) { state = EmptyTrack; begin = end = 0; return; } if ( position < _min ) { cerr << Warning ( " Position %s inferior to the lower bound of %s. Returning NPOS." , DbU::getValueString(position).c_str() , getString(this).c_str() ) << endl; state = BeforeFirst; begin = end = 0; return; } if ( position > _max ) { cerr << Warning ( " Position %s superior to the upper bound of %s. Returning NPOS." , DbU::getValueString(position).c_str() , getString(this).c_str() ) << endl; state = AfterLast; begin = end = _segments.size() - 1; return; } vector::const_iterator lowerBound = lower_bound ( _segments.begin(), _segments.end(), position, SourceCompare() ); begin = end = lowerBound - _segments.begin(); if ( begin < _segments.size() ) for ( ; (begin > 0) && (_segments[begin-1]->getNet() == _segments[begin]->getNet()) ; --begin ); state = 0; if ( (begin == 0) && (position < _segments[0]->getSourceU()) ) { state = BeforeFirst; } else { if ( begin ) end = begin -= 1; size_t usedBegin = begin; size_t usedEnd = begin; Interval usedInterval = expandUsedInterval ( usedBegin, usedEnd ); if ( position < usedInterval.getVMax() ) state = Inside; else if ( begin+1 == _segments.size() ) state = AfterLast; else state = Outside; } } void Track::getOverlapBounds ( Interval interval, size_t& begin, size_t& end ) const { unsigned int iState; size_t iBegin; size_t iEnd; if ( _segments.empty() || (interval.getVMax() <= _min) || (interval.getVMin() >= _max)) { begin = end = NPOS; return; } getIBounds ( interval.getVMin(), begin, iEnd, iState ); expandUsedInterval ( begin, iEnd ); getIBounds ( interval.getVMax(), iBegin, end, iState ); while ( end < _segments.size() ) { if ( _segments[end++]->getSourceU() >= interval.getVMax() ) break; } } TrackCost Track::getOverlapCost ( Interval interval, Net* net, size_t begin, size_t end ) const { TrackCost cost ( const_cast(this), interval, begin, end ); ltrace(190) << "getOverlapCost() @" << DbU::getValueString(_axis) << " [" << DbU::getValueString(interval.getVMin()) << ":" << DbU::getValueString(interval.getVMax()) << "]" << "<-> [" << begin << ":" << end << "]" << endl; ltracein(148); vector::const_iterator lowerBound = lower_bound ( _markers.begin(), _markers.end(), interval.getVMin(), TrackMarker::Compare() ); size_t mbegin = lowerBound - _markers.begin(); for ( ; (mbegin < _markers.size()) && (_markers[mbegin]->getSourceU() <= interval.getVMax()) ; mbegin++ ) { ltrace(148) << "| @" << DbU::getValueString(_axis) << _markers[mbegin] << endl; if ( _markers[mbegin]->getNet() != net ) { ltrace(148) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl; cost.incTerminals ( _markers[mbegin]->getWeight(this) ); } } if ( begin == NPOS ) { ltrace(148) << " begin == NPOS (after last TrackElement)." << endl; ltraceout(148); return cost; } for ( ; begin < end ; begin++ ) { if ( _segments[begin]->getNet() == net ) { cost.incDeltaShared ( _segments[begin]->getCanonicalInterval().intersection(interval).getSize() ); } ltrace(190) << "| overlap: " << _segments[begin] << endl; _segments[begin]->incOverlapCost ( net, cost ); if ( cost.isInfinite() ) break; } ltraceout(148); return cost; } TrackCost Track::getOverlapCost ( Interval interval, Net* net ) const { size_t begin; size_t end; getOverlapBounds ( interval, begin, end ); return getOverlapCost ( interval, net, begin, end ); } TrackCost Track::getOverlapCost ( TrackElement* segment ) const { return getOverlapCost ( segment->getCanonicalInterval(), segment->getNet() ); } void Track::getTerminalWeight ( Interval interval, Net* net, size_t& count, unsigned int& weight ) const { ltrace(148) << "getTerminalWeight() @" << DbU::getValueString(_axis) << " [" << interval.getVMin() << " " << interval.getVMax() << "]" << endl; ltracein(148); //count = 0; //weight = 0; vector::const_iterator lowerBound = lower_bound ( _markers.begin(), _markers.end(), interval.getVMin(), TrackMarker::Compare() ); size_t mbegin = lowerBound - _markers.begin(); for ( ; (mbegin < _markers.size()) && (_markers[mbegin]->getSourceU() <= interval.getVMax()) ; mbegin++ ) { ltrace(148) << "| @" << DbU::getValueString(_axis) << _markers[mbegin] << endl; if ( _markers[mbegin]->getNet() == net ) { ltrace(200) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl; weight += _markers[mbegin]->getWeight(this); ++count; } } ltraceout(148); } Track* Track::getNext () const { return getRoutingPlane()->getTrackByIndex ( getIndex()+1 ); } Track* Track::getPrevious () const { if ( !getIndex() ) return NULL; return getRoutingPlane()->getTrackByIndex ( getIndex()-1 ); } size_t Track::find ( const TrackElement* segment ) const { if ( !_segments.size() ) return NPOS; vector::const_iterator lowerBound = lower_bound ( _segments.begin() , _segments.end() , segment , SegmentCompare() ); if ( lowerBound != _segments.end() ) { while ( segment->getSourceU() == (*lowerBound)->getSourceU() ) { if ( *lowerBound == segment ) return (size_t)(lowerBound-_segments.begin()); lowerBound++; } } return NPOS; } Interval Track::getFreeInterval ( DbU::Unit position, Net* net ) const { unsigned int state; size_t begin; size_t end; if ( !_segments.size() ) return Interval(_min,_max); getIBounds ( position, begin, end, state ); if ( (state == Inside) && (_segments[begin]->getNet() != net) ) return Interval(); return expandFreeInterval ( begin, end, state, net ); } Interval Track::expandFreeInterval ( size_t& begin, size_t& end, unsigned int state, Net* net, bool useOrder ) const { DbU::Unit minFree = _min; if ( !(state & MinTrackMin) ) { if ( _segments[begin]->getNet() == net ) getPrevious ( begin, net, useOrder ); if ( begin != NPOS ) { size_t usedEnd; minFree = expandUsedInterval ( begin, usedEnd, useOrder ).getVMax(); } } if ( !(state & MaxTrackMax) ) { if ( _segments[end]->getNet() == net ) { getNext ( end, net, useOrder ); if ( end == NPOS ) { end = _segments.size() - 1; setMaximalFlags ( state, MaxTrackMax ); } else { setMaximalFlags ( state, MaxSegmentMin ); } } } return Interval ( minFree, getMaximalPosition(end,state) ); } void Track::forceSort () { _segmentsValid = false; } void Track::insert ( TrackMarker* marker ) { _markers.push_back ( marker ); _markersValid = false; } void Track::insert ( TrackElement* segment ) { ltrace(200) << "Track::insert() " << getLayer()->getName() << " @" << DbU::getValueString(getAxis()) << " " << segment << endl; if ( (getLayer()->getMask() != segment->getLayer()->getMask()) and (getBlockageLayer()->getMask() != segment->getLayer()->getMask()) ) { cerr << Bug("Track::insert(), segment %s has not the right layer." ,getString(segment).c_str()) << endl; } segment->setAxis ( getAxis() ); _segments.push_back ( segment ); _segmentsValid = false; segment->setTrack ( this ); } void Track::setSegment ( TrackElement* segment, size_t index ) { if ( index >= _segments.size() ) return; _segments[index] = segment; } bool Track::_check ( unsigned int& overlaps, const char* message ) const { bool coherency = true; bool holes = false; if ( message ) cerr << " o Checking Track - " << message << endl; ltrace(90) << "[CHECK] " << (void*)this << ":" << this << endl; for ( size_t i=0 ; i<_segments.size() ; i++ ) { if ( _segments[i] ) { if ( i ) { if ( _segments[i-1] == _segments[i] ) { cerr << "[CHECK] incoherency at " << i << " " << _segments[i] << " is duplicated. " << endl; coherency = false; } } if ( !_segments[i]->getTrack() ) { cerr << "[CHECK] incoherency at " << i << " " << _segments[i] << " is detached." << endl; coherency = false; } else { if ( _segments[i]->getTrack() != this ) { cerr << "[CHECK] incoherency at " << i << " " << _segments[i] << " is in track " << _segments[i]->getTrack() << endl; coherency = false; } if ( _segments[i]->getIndex() != i ) { cerr << "[CHECK] incoherency at " << i << " " << _segments[i] << " has bad index " << _segments[i]->getIndex() << endl; coherency = false; } } if ( _segments[i]->getAxis() != getAxis() ) { cerr << "[CHECK] incoherency at " << i << " " << _segments[i] << " is not on Track axis " << DbU::getValueString(getAxis()) << "." << endl; coherency = false; } coherency = coherency && _segments[i]->_check (); } else { cerr << "[CHECK] Hole at position " << i << "." << endl; holes = true; coherency = false; } } if ( !holes ) coherency = coherency && (checkOverlap(overlaps) == 0); return coherency; } DbU::Unit Track::getSourcePosition ( size_t i ) const { if ( i == NPOS) return 0; return _segments[i]->getSourceU(); } DbU::Unit Track::getSourcePosition ( vector::iterator isegment ) const { if ( isegment == _segments.end() ) return 0; return (*isegment)->getSourceU(); } DbU::Unit Track::getMinimalPosition ( size_t index, unsigned int state ) const { Interval canonical; switch ( state & MinMask ) { case MinTrackMin: return _min; case MinSegmentMin: return _segments[index]->getSourceU (); case MinSegmentMax: return _segments[index]->getTargetU (); } cerr << Bug ( " Track::getMinimalPosition(size_t,unsigned int) :" " invalid state value %ud.", state ) << endl; return _min; } DbU::Unit Track::getMaximalPosition ( size_t index, unsigned int state ) const { Interval canonical; switch ( state & MaxMask ) { case MaxTrackMax: return _max; case MaxSegmentMin: return _segments[index ]->getSourceU (); case MaxNextSegmentMin: if ( index+1 >= getSize() ) return _max; return _segments[index+1]->getSourceU (); case MaxSegmentMax: return _segments[index ]->getTargetU (); } cerr << Bug ( " Track::getMaximalPosition(size_t,unsigned int) :" " invalid state value %ud.", state ) << endl; return _min; } Interval Track::expandUsedInterval ( size_t& begin, size_t& end, bool useOrder ) const { if ( begin == NPOS ) return Interval(); size_t seed = begin; Net* owner = _segments[seed]->getNet(); Interval expandInterval; Interval ownerInterval; _segments[seed]->getCanonical ( ownerInterval ); size_t i = seed; while ( --i != NPOS ) { if ( _segments[i]->getNet() != owner ) break; if ( useOrder and _segments[i]->getDataNegociate() and (_segments[i]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) continue; _segments[i]->getCanonical ( expandInterval ); if ( expandInterval.getVMax() >= ownerInterval.getVMin() ) { ownerInterval.merge ( expandInterval ); begin = i; } } end = i = seed; while ( ++i < _segments.size() ) { if ( _segments[i]->getNet() != owner ) break; if ( useOrder and _segments[i]->getDataNegociate() and (_segments[i]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) continue; _segments[i]->getCanonical ( expandInterval ); if ( expandInterval.getVMin() > ownerInterval.getVMax() ) break; if ( expandInterval.getVMax() > ownerInterval.getVMax() ) end = i; ownerInterval.merge ( expandInterval ); } return ownerInterval; } size_t Track::pack () { ltrace(148) << "Track::pack() - " << this << endl; ltracein(148); size_t size = _segments.size(); vector::iterator beginRemove = remove_if ( _segments.begin(), _segments.end(), isDetachedSegment() ); _segments.erase ( beginRemove, _segments.end() ); # if 0 size_t first = 0; size_t last = 0; bool erase = false; while ( last < _segments.size() ) { if ( _segments[last] ) { if ( erase ) { _segments.erase ( _segments.begin()+first, _segments.begin()+last ); erase = false; last = first; } else { first = last; } } else { erase = true; } } if ( erase ) _segments.erase ( _segments.begin()+first, _segments.end() ); # endif ltrace(148) << "After packing " << this << endl; ltraceout(148); return size - _segments.size(); } void Track::sort () { if ( !_segmentsValid ) { std::sort ( _segments.begin(), _segments.end(), SegmentCompare() ); for ( size_t i=0 ; i < _segments.size() ; i++ ) { _segments[i]->setIndex ( i ); } _segmentsValid = true; } if ( !_markersValid ) { std::sort ( _markers.begin(), _markers.end(), TrackMarker::Compare() ); _markersValid = true; } } unsigned int Track::checkOverlap ( unsigned int& overlaps ) const { if ( !_segments.size() ) return 0; size_t j = 0; for ( size_t i=0 ; i<_segments.size()-1 ; i++ ) { if ( _segments[i]->getNet() == _segments[i+1]->getNet() ) { if ( _segments[i]->getSourceU() == _segments[i+1]->getSourceU() ) { if ( _segments[i]->getTargetU() < _segments[i+1]->getTargetU() ) { cerr << Warning(" Invalid sorting length order in %s:\n%s \n%s " ,getString(this).c_str() ,getString(_segments[i ]).c_str() ,getString(_segments[i+1]).c_str()) << endl; } } for ( j=i+1 ; (j<_segments.size()) && (_segments[i]->getNet() == _segments[j]->getNet()) ; j++ ); } else { j = i+1; } if ( (j<_segments.size()) && (_segments[i]->getTargetU() > _segments[j]->getSourceU()) ) { cerr << Warning("Overlap in %s between:\n %s\n %s" ,getString(this).c_str() ,getString(_segments[i]).c_str() ,getString(_segments[j]).c_str()) << endl; overlaps++; } } return overlaps; } string Track::_getString () const { return "<" + _getTypeName() + " " + getString(getLayer()) + " @" + DbU::getValueString(_axis) + " [" + DbU::getValueString(_min) + ":" + DbU::getValueString(_max) + "] [" + getString(_segments.size()) + "/" + getString(_segments.capacity()) + "]>"; } Record* Track::_getRecord () const { Record* record = new Record ( _getString() ); record->add ( getSlot ( "_routingPlane", _routingPlane ) ); record->add ( getSlot ( "_index" , &_index ) ); record->add ( DbU::getValueSlot ( "_axis" , &_axis ) ); record->add ( getSlot ( "_segments" , &_segments ) ); return record; } } // End of Kite namespace.