2010-03-09 09:24:55 -06:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
Corrections in how to access pads terminals in Katabatic/Kite.
* Change: In Katabatic, in GCellTopology::doRp_AccessPad(), if the supporting
RoutingPad is big (more than two pitch), do not put the access
contact in the center but on the edge. This is to avoid cut violations
between the VIAs and the matrix of VIAs that may be generated under the
RoutingPad itself.
* Change: In Kite, in TrackSegment destructor, if the legnth of the wire,
without extensions is less than one picth, enlarge it so it encompass
it's source & target VIAs (to avoid notches).
* Bug: In Kite, in Track destructor, the TrackElements where detacheds,
but not deleted, causing a memory link.
2016-03-02 10:15:58 -06:00
|
|
|
// Copyright (c) UPMC 2008-2016, All Rights Reserved
|
2010-03-09 09:24:55 -06:00
|
|
|
//
|
2013-12-03 18:59:29 -06:00
|
|
|
// +-----------------------------------------------------------------+
|
2010-03-09 09:24:55 -06:00
|
|
|
// | 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" |
|
2013-12-03 18:59:29 -06:00
|
|
|
// +-----------------------------------------------------------------+
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <sstream>
|
|
|
|
#include <memory>
|
|
|
|
#include <algorithm>
|
|
|
|
#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"
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace CRL;
|
|
|
|
using namespace Kite;
|
|
|
|
|
|
|
|
|
|
|
|
struct isDetachedSegment {
|
2013-12-03 18:59:29 -06:00
|
|
|
bool operator() ( const TrackElement* s ) { return not s->getTrack(); };
|
2010-03-09 09:24:55 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-12-09 16:49:46 -06:00
|
|
|
// DbU::Unit getPositionByIterator ( const vector<TrackElement*>& v, size_t i )
|
|
|
|
// { return (*(v.begin()+i))->getSourceU(); }
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
} // Anonymous namespace.
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
|
|
|
namespace Kite {
|
|
|
|
|
|
|
|
using std::lower_bound;
|
|
|
|
using std::remove_if;
|
|
|
|
using std::sort;
|
|
|
|
using Hurricane::dbo_ptr;
|
|
|
|
using Hurricane::tab;
|
|
|
|
using Hurricane::Warning;
|
|
|
|
using Hurricane::Bug;
|
|
|
|
using Hurricane::Layer;
|
|
|
|
using Hurricane::Net;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Track".
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
const size_t Track::npos = (size_t)-1;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
|
|
|
Track::Track ( RoutingPlane* routingPlane, unsigned int index )
|
|
|
|
: _routingPlane (routingPlane)
|
|
|
|
, _index (index)
|
|
|
|
, _axis (routingPlane->getTrackPosition(index))
|
|
|
|
, _min (routingPlane->getTrackMin())
|
|
|
|
, _max (routingPlane->getTrackMax())
|
|
|
|
, _segments ()
|
|
|
|
, _markers ()
|
* ./kite:
- New: In RoutingEvent, while routing a full chip, transient full blockages
may happens due to the initial position of some perpandiculars on theirs
optimal positions. Check for it and perform a "ripupPerpandicular" with
the perpandiculars re-routed first (on normal operation, this is the
reverse).
- Change: In NegociateWindow::NegociateOverlapCost(), do not account terminals
if the layer is *above* METAL3 as it is unlikely that it's truly directly
connected to a terminal (true at least for our designs).
- Change: In RoutingEvent::State, add a "fullBlocked" flag to perform the
full blockage direction while building the state object.
- Change: In RoutingEvent::cacheAxisHint(), when the TrackSegment has parent,
uses the parent current axis position and not it's axis hint.
- Change: In Manipulator::insertInTrack(), when the overlapped segment is a
Local and is completly enclosed (shrinkLeft & shrinkRight), no longer
rip it up but force a shrink left/right instead.
- Bug: In RoutingEvent, the event sorting function was sorting in the *wrong*
order! The less prioritary first! With the correct sort, we won an
additionnal 30% in speed (total: 69%). From the "reference" time we have
a 3.2 speed-up. And we can successfully process denser designs...
2011-01-09 12:08:57 -06:00
|
|
|
, _localAssigned(false)
|
2010-03-09 09:24:55 -06:00
|
|
|
, _segmentsValid(false)
|
|
|
|
, _markersValid (false)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
void Track::_postCreate ()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
Track::~Track ()
|
2016-05-17 16:00:06 -05:00
|
|
|
{ cdebug.log(155) << "Track::~Track() - " << (void*)this << endl; }
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
|
|
|
void Track::_preDestroy ()
|
|
|
|
{
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(155,1) << "Track::_preDestroy() - " << (void*)this << " " << this << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_segments.size() ; i++ )
|
Corrections in how to access pads terminals in Katabatic/Kite.
* Change: In Katabatic, in GCellTopology::doRp_AccessPad(), if the supporting
RoutingPad is big (more than two pitch), do not put the access
contact in the center but on the edge. This is to avoid cut violations
between the VIAs and the matrix of VIAs that may be generated under the
RoutingPad itself.
* Change: In Kite, in TrackSegment destructor, if the legnth of the wire,
without extensions is less than one picth, enlarge it so it encompass
it's source & target VIAs (to avoid notches).
* Bug: In Kite, in Track destructor, the TrackElements where detacheds,
but not deleted, causing a memory link.
2016-03-02 10:15:58 -06:00
|
|
|
if (_segments[i]) { _segments[i]->detach(); _segments[i]->destroy(); }
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_markers.size() ; i++ )
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_markers[i]) _markers[i]->destroy();
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.tabw(155,-1);
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Track::destroy ()
|
|
|
|
{
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(155) << "Track::destroy() - " << (void*)this << " " << this << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
Track::_preDestroy();
|
2010-03-09 09:24:55 -06:00
|
|
|
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(); }
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
Track* Track::getNextTrack () const
|
|
|
|
{ return getRoutingPlane()->getTrackByIndex( getIndex()+1 ); }
|
|
|
|
|
|
|
|
|
|
|
|
Track* Track::getPreviousTrack () const
|
|
|
|
{
|
|
|
|
if (not getIndex()) return NULL;
|
|
|
|
return getRoutingPlane()->getTrackByIndex( getIndex()-1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:55 -06:00
|
|
|
TrackElement* Track::getSegment ( size_t index ) const
|
|
|
|
{
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( (index == npos) or (index >= getSize()) ) return NULL;
|
2010-03-09 09:24:55 -06:00
|
|
|
return _segments[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TrackElement* Track::getSegment ( DbU::Unit position ) const
|
|
|
|
{
|
|
|
|
unsigned int state;
|
|
|
|
size_t begin;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
getBeginIndex( position, begin, state );
|
|
|
|
if (state & (BeginIsTrackMin|EndIsTrackMax)) return NULL;
|
2010-03-09 09:24:55 -06:00
|
|
|
return getSegment(begin);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-12 15:42:57 -06:00
|
|
|
TrackElement* Track::getNext ( size_t& index, Net* net ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
|
|
|
for ( index++ ; index < _segments.size() ; index++ ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[index]->getNet() == net) continue;
|
2010-03-09 09:24:55 -06:00
|
|
|
return _segments[index];
|
|
|
|
}
|
2013-12-03 18:59:29 -06:00
|
|
|
index = npos;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-12 15:42:57 -06:00
|
|
|
TrackElement* Track::getPrevious ( size_t& index, Net* net ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
2013-12-03 18:59:29 -06:00
|
|
|
for ( index-- ; index != npos ; index-- ) {
|
2016-05-17 16:00:06 -05:00
|
|
|
if (cdebug.enabled()) {
|
2010-03-09 09:24:55 -06:00
|
|
|
cerr << tab << index << ":"; cerr.flush();
|
|
|
|
cerr << _segments[index] << endl;
|
|
|
|
}
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[index]->getNet() == net) continue;
|
2010-03-09 09:24:55 -06:00
|
|
|
return _segments[index];
|
|
|
|
}
|
2013-12-03 18:59:29 -06:00
|
|
|
index = npos;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
void Track::getBeginIndex ( DbU::Unit position, size_t& begin, unsigned int& state ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments.empty()) {
|
2010-03-09 09:24:55 -06:00
|
|
|
state = EmptyTrack;
|
2013-12-03 18:59:29 -06:00
|
|
|
begin = 0;
|
2010-03-09 09:24:55 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
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 = BeforeFirstElement;
|
|
|
|
begin = 0;
|
2010-03-09 09:24:55 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
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 = AfterLastElement;
|
|
|
|
begin = _segments.size()-1;
|
2010-03-09 09:24:55 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<TrackElement*>::const_iterator lowerBound
|
2013-12-03 18:59:29 -06:00
|
|
|
= lower_bound( _segments.begin(), _segments.end(), position, SourceCompare() );
|
|
|
|
begin = lowerBound - _segments.begin();
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
// This is suspicious.
|
|
|
|
// I guess this has been written for the case of overlapping segments from the same
|
|
|
|
// net, we find the first one of the overlapped sets. But what if they are not overlapping
|
|
|
|
// but still from the same net?
|
2016-04-13 11:42:55 -05:00
|
|
|
size_t sameNetDelta = 0;
|
|
|
|
if (begin < _segments.size()) {
|
|
|
|
for ( ; (begin > 0) and (_segments[begin-1]->getNet() == _segments[begin]->getNet())
|
|
|
|
; --begin, ++sameNetDelta );
|
|
|
|
}
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
state = 0;
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( (begin == 0) and (position < _segments[0]->getSourceU()) ) {
|
|
|
|
state = BeforeFirstElement;
|
2010-03-09 09:24:55 -06:00
|
|
|
} else {
|
2016-04-13 11:42:55 -05:00
|
|
|
if (begin and not sameNetDelta) begin -= 1;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
size_t usedBegin = begin;
|
2013-12-03 18:59:29 -06:00
|
|
|
Interval usedInterval = getOccupiedInterval( usedBegin );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (position < usedInterval.getVMax())
|
|
|
|
state = InsideElement;
|
2010-03-09 09:24:55 -06:00
|
|
|
else
|
2013-12-03 18:59:29 -06:00
|
|
|
if (begin+1 == _segments.size())
|
|
|
|
state = AfterLastElement;
|
2010-03-09 09:24:55 -06:00
|
|
|
else
|
2013-12-03 18:59:29 -06:00
|
|
|
state = OutsideElement;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Track::getOverlapBounds ( Interval interval, size_t& begin, size_t& end ) const
|
|
|
|
{
|
|
|
|
unsigned int iState;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( _segments.empty()
|
|
|
|
or (interval.getVMax() <= _min)
|
|
|
|
or (interval.getVMin() >= _max)) {
|
|
|
|
begin = end = npos;
|
2010-03-09 09:24:55 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
getBeginIndex ( interval.getVMin(), begin, iState );
|
|
|
|
getOccupiedInterval( begin );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
getBeginIndex( interval.getVMax(), end, iState );
|
2016-04-13 11:42:55 -05:00
|
|
|
for ( ; end < _segments.size() ; ++end ) {
|
|
|
|
if (_segments[end]->getSourceU() >= interval.getVMax()) break;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
2016-04-13 11:42:55 -05:00
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "Track::getOverlapBounds(): begin:" << begin << " end:" << end << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
* ./kite:
- New: In NegociateWindow/RoutingEvent, adds a more comprehensive stage
"Repair". Perform in three stage: first try to place with a relaxed
constraint (one GCell on each side). Second try to minimize the faulty
segment. Third perform another "repack perpandicular" but this time
the faulty segment is re-inserted *before* any of it's perpandiculars.
- New: In RoutingEvent::cacheAxisHint(), when a segment has a parent, that
is comes for a "moveUp()", uses the parent axis hint as it's own.
- New: In State::slackenTopology(), in the global FSM, adds a special
operation when reaching MaximumSlack: forceOverLocals(), try to insert
the global on track containing only local segments. Should tend to
concentrate locals on a small set of shared tracks. Most useful on the
highest layers.
- New: In State::slackenTopology(), in the "MoveUp" state, try to find the
more appropriate segment to move up (Manipulator::desaturate()).
Effectively move up the longest segment fully enclosing the one we are
processing.
- New: In State::slackenTopology(), add a check for fully blocked segments
in the local segment FSM. Calls State::solveFullBlocked().
- New: In KiteEngine::createGlobalGraph(), decrease the vertical capacity
of one track inside the core. Helps smooth the vertical density.
- Change: In Manipulator::insertInTrack(), when a track is freed for a
to be inserted changes the priorities so that the segment is immediatly
inserted. Parallels ripeds and theirs perpandiculars are replaced
only *after*. This is the opposite of the previous behavior.
- Change: In NegociateWindow::NegociateOverlapCost(), account the costs
of terminals only for deep depth layers (M1, M2 & M3).
- Change: In RoutingEvent::insertInTrack(), expand the excluded interval
by a half-pitch (2.5l) instead of one lambda.
- Change: In State::State(), do not uses DiscardGlobal if the ripup count
exceed 5. Case of the "Strap" segments that can be ripped a lot
before changing state.
- Change: In State::_processNegociate(), no longer lock into position
(fixed) the local terminal segments as a last resort.
- Change: In RoutingEvent::_processNegociate(), no longer ripup perpandiculars
when a segment is inserted in a free space. Reduce the number of
events whithout degrading the routing quality.
- Change: In State::conflictSolve1_v1b(), if getLongestConflict() is nul,
ignore the track, the conflict must occurs on another track.
- Change: In TrackCost, add a flag support. First uses, a flags to prevent
a local of the topmost layer to ripup a global which is in moveUp
state.
- Bug: In State::solveFullBlockage(), after have been freed, reset the
segment state to "moveUp".
- Bug: In manipulator::minimize(), the axisHint was miscalculated if the
punctual span was empty.
2011-01-25 11:16:50 -06:00
|
|
|
TrackCost Track::getOverlapCost ( Interval interval
|
|
|
|
, Net* net
|
|
|
|
, size_t begin
|
|
|
|
, size_t end
|
|
|
|
, unsigned int flags ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
* ./kite:
- New: In NegociateWindow/RoutingEvent, adds a more comprehensive stage
"Repair". Perform in three stage: first try to place with a relaxed
constraint (one GCell on each side). Second try to minimize the faulty
segment. Third perform another "repack perpandicular" but this time
the faulty segment is re-inserted *before* any of it's perpandiculars.
- New: In RoutingEvent::cacheAxisHint(), when a segment has a parent, that
is comes for a "moveUp()", uses the parent axis hint as it's own.
- New: In State::slackenTopology(), in the global FSM, adds a special
operation when reaching MaximumSlack: forceOverLocals(), try to insert
the global on track containing only local segments. Should tend to
concentrate locals on a small set of shared tracks. Most useful on the
highest layers.
- New: In State::slackenTopology(), in the "MoveUp" state, try to find the
more appropriate segment to move up (Manipulator::desaturate()).
Effectively move up the longest segment fully enclosing the one we are
processing.
- New: In State::slackenTopology(), add a check for fully blocked segments
in the local segment FSM. Calls State::solveFullBlocked().
- New: In KiteEngine::createGlobalGraph(), decrease the vertical capacity
of one track inside the core. Helps smooth the vertical density.
- Change: In Manipulator::insertInTrack(), when a track is freed for a
to be inserted changes the priorities so that the segment is immediatly
inserted. Parallels ripeds and theirs perpandiculars are replaced
only *after*. This is the opposite of the previous behavior.
- Change: In NegociateWindow::NegociateOverlapCost(), account the costs
of terminals only for deep depth layers (M1, M2 & M3).
- Change: In RoutingEvent::insertInTrack(), expand the excluded interval
by a half-pitch (2.5l) instead of one lambda.
- Change: In State::State(), do not uses DiscardGlobal if the ripup count
exceed 5. Case of the "Strap" segments that can be ripped a lot
before changing state.
- Change: In State::_processNegociate(), no longer lock into position
(fixed) the local terminal segments as a last resort.
- Change: In RoutingEvent::_processNegociate(), no longer ripup perpandiculars
when a segment is inserted in a free space. Reduce the number of
events whithout degrading the routing quality.
- Change: In State::conflictSolve1_v1b(), if getLongestConflict() is nul,
ignore the track, the conflict must occurs on another track.
- Change: In TrackCost, add a flag support. First uses, a flags to prevent
a local of the topmost layer to ripup a global which is in moveUp
state.
- Bug: In State::solveFullBlockage(), after have been freed, reset the
segment state to "moveUp".
- Bug: In manipulator::minimize(), the axisHint was miscalculated if the
punctual span was empty.
2011-01-25 11:16:50 -06:00
|
|
|
TrackCost cost ( const_cast<Track*>(this), interval, begin, end, net, flags );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159,1) << "getOverlapCost() @" << DbU::getValueString(_axis)
|
|
|
|
<< " [" << DbU::getValueString(interval.getVMin())
|
|
|
|
<< ":" << DbU::getValueString(interval.getVMax())
|
|
|
|
<< "] <-> [" << begin << ":" << end << "]"
|
|
|
|
<< endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
vector<TrackMarker*>::const_iterator lowerBound
|
2013-12-03 18:59:29 -06:00
|
|
|
= lower_bound( _markers.begin(), _markers.end(), interval.getVMin(), TrackMarker::Compare() );
|
2010-03-09 09:24:55 -06:00
|
|
|
size_t mbegin = lowerBound - _markers.begin();
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
for ( ; (mbegin < _markers.size())
|
|
|
|
and (_markers[mbegin]->getSourceU() <= interval.getVMax()) ; mbegin++ ) {
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "| @" << DbU::getValueString(_axis) << _markers[mbegin] << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
if ( _markers[mbegin]->getNet() != net ) {
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
cost.incTerminals( _markers[mbegin]->getWeight(this) );
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (begin == npos) {
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << " begin == npos (after last TrackElement)." << endl;
|
|
|
|
cdebug.tabw(159,-1);
|
2010-03-09 09:24:55 -06:00
|
|
|
return cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; begin < end ; begin++ ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
Interval overlap = interval.getIntersection( _segments[begin]->getCanonicalInterval() );
|
|
|
|
if ( _segments[begin]->getNet() == net ) {
|
|
|
|
cost.incDeltaShared ( overlap.getSize() );
|
|
|
|
}
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "| overlap: " << _segments[begin] << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
_segments[begin]->incOverlapCost( net, cost );
|
|
|
|
if (cost.isInfinite()) break;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.tabw(159,-1);
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
* ./kite:
- New: In NegociateWindow/RoutingEvent, adds a more comprehensive stage
"Repair". Perform in three stage: first try to place with a relaxed
constraint (one GCell on each side). Second try to minimize the faulty
segment. Third perform another "repack perpandicular" but this time
the faulty segment is re-inserted *before* any of it's perpandiculars.
- New: In RoutingEvent::cacheAxisHint(), when a segment has a parent, that
is comes for a "moveUp()", uses the parent axis hint as it's own.
- New: In State::slackenTopology(), in the global FSM, adds a special
operation when reaching MaximumSlack: forceOverLocals(), try to insert
the global on track containing only local segments. Should tend to
concentrate locals on a small set of shared tracks. Most useful on the
highest layers.
- New: In State::slackenTopology(), in the "MoveUp" state, try to find the
more appropriate segment to move up (Manipulator::desaturate()).
Effectively move up the longest segment fully enclosing the one we are
processing.
- New: In State::slackenTopology(), add a check for fully blocked segments
in the local segment FSM. Calls State::solveFullBlocked().
- New: In KiteEngine::createGlobalGraph(), decrease the vertical capacity
of one track inside the core. Helps smooth the vertical density.
- Change: In Manipulator::insertInTrack(), when a track is freed for a
to be inserted changes the priorities so that the segment is immediatly
inserted. Parallels ripeds and theirs perpandiculars are replaced
only *after*. This is the opposite of the previous behavior.
- Change: In NegociateWindow::NegociateOverlapCost(), account the costs
of terminals only for deep depth layers (M1, M2 & M3).
- Change: In RoutingEvent::insertInTrack(), expand the excluded interval
by a half-pitch (2.5l) instead of one lambda.
- Change: In State::State(), do not uses DiscardGlobal if the ripup count
exceed 5. Case of the "Strap" segments that can be ripped a lot
before changing state.
- Change: In State::_processNegociate(), no longer lock into position
(fixed) the local terminal segments as a last resort.
- Change: In RoutingEvent::_processNegociate(), no longer ripup perpandiculars
when a segment is inserted in a free space. Reduce the number of
events whithout degrading the routing quality.
- Change: In State::conflictSolve1_v1b(), if getLongestConflict() is nul,
ignore the track, the conflict must occurs on another track.
- Change: In TrackCost, add a flag support. First uses, a flags to prevent
a local of the topmost layer to ripup a global which is in moveUp
state.
- Bug: In State::solveFullBlockage(), after have been freed, reset the
segment state to "moveUp".
- Bug: In manipulator::minimize(), the axisHint was miscalculated if the
punctual span was empty.
2011-01-25 11:16:50 -06:00
|
|
|
TrackCost Track::getOverlapCost ( Interval interval, Net* net, unsigned int flags ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
|
|
|
size_t begin;
|
|
|
|
size_t end;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
getOverlapBounds( interval, begin, end );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
return getOverlapCost( interval, net, begin, end, flags );
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
* ./kite:
- New: In NegociateWindow/RoutingEvent, adds a more comprehensive stage
"Repair". Perform in three stage: first try to place with a relaxed
constraint (one GCell on each side). Second try to minimize the faulty
segment. Third perform another "repack perpandicular" but this time
the faulty segment is re-inserted *before* any of it's perpandiculars.
- New: In RoutingEvent::cacheAxisHint(), when a segment has a parent, that
is comes for a "moveUp()", uses the parent axis hint as it's own.
- New: In State::slackenTopology(), in the global FSM, adds a special
operation when reaching MaximumSlack: forceOverLocals(), try to insert
the global on track containing only local segments. Should tend to
concentrate locals on a small set of shared tracks. Most useful on the
highest layers.
- New: In State::slackenTopology(), in the "MoveUp" state, try to find the
more appropriate segment to move up (Manipulator::desaturate()).
Effectively move up the longest segment fully enclosing the one we are
processing.
- New: In State::slackenTopology(), add a check for fully blocked segments
in the local segment FSM. Calls State::solveFullBlocked().
- New: In KiteEngine::createGlobalGraph(), decrease the vertical capacity
of one track inside the core. Helps smooth the vertical density.
- Change: In Manipulator::insertInTrack(), when a track is freed for a
to be inserted changes the priorities so that the segment is immediatly
inserted. Parallels ripeds and theirs perpandiculars are replaced
only *after*. This is the opposite of the previous behavior.
- Change: In NegociateWindow::NegociateOverlapCost(), account the costs
of terminals only for deep depth layers (M1, M2 & M3).
- Change: In RoutingEvent::insertInTrack(), expand the excluded interval
by a half-pitch (2.5l) instead of one lambda.
- Change: In State::State(), do not uses DiscardGlobal if the ripup count
exceed 5. Case of the "Strap" segments that can be ripped a lot
before changing state.
- Change: In State::_processNegociate(), no longer lock into position
(fixed) the local terminal segments as a last resort.
- Change: In RoutingEvent::_processNegociate(), no longer ripup perpandiculars
when a segment is inserted in a free space. Reduce the number of
events whithout degrading the routing quality.
- Change: In State::conflictSolve1_v1b(), if getLongestConflict() is nul,
ignore the track, the conflict must occurs on another track.
- Change: In TrackCost, add a flag support. First uses, a flags to prevent
a local of the topmost layer to ripup a global which is in moveUp
state.
- Bug: In State::solveFullBlockage(), after have been freed, reset the
segment state to "moveUp".
- Bug: In manipulator::minimize(), the axisHint was miscalculated if the
punctual span was empty.
2011-01-25 11:16:50 -06:00
|
|
|
TrackCost Track::getOverlapCost ( TrackElement* segment, unsigned int flags ) const
|
2013-12-03 18:59:29 -06:00
|
|
|
{ return getOverlapCost ( segment->getCanonicalInterval(), segment->getNet(), flags ); }
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
|
|
|
void Track::getTerminalWeight ( Interval interval, Net* net, size_t& count, unsigned int& weight ) const
|
|
|
|
{
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159,1) << "getTerminalWeight() @" << DbU::getValueString(_axis)
|
|
|
|
<< " [" << interval.getVMin() << " " << interval.getVMax() << "]" << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
//count = 0;
|
|
|
|
//weight = 0;
|
|
|
|
|
|
|
|
vector<TrackMarker*>::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++ ) {
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "| @" << DbU::getValueString(_axis) << _markers[mbegin] << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
if ( _markers[mbegin]->getNet() == net ) {
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
weight += _markers[mbegin]->getWeight(this);
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
}
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.tabw(159,-1);
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t Track::find ( const TrackElement* segment ) const
|
|
|
|
{
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments.empty()) return npos;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
vector<TrackElement*>::const_iterator lowerBound
|
2013-12-03 18:59:29 -06:00
|
|
|
= lower_bound( _segments.begin()
|
|
|
|
, _segments.end()
|
|
|
|
, segment
|
|
|
|
, SegmentCompare()
|
|
|
|
);
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (lowerBound != _segments.end()) {
|
2010-03-09 09:24:55 -06:00
|
|
|
while ( segment->getSourceU() == (*lowerBound)->getSourceU() ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
if (*lowerBound == segment) return (size_t)(lowerBound-_segments.begin());
|
2010-03-09 09:24:55 -06:00
|
|
|
lowerBound++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
return npos;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Interval Track::getFreeInterval ( DbU::Unit position, Net* net ) const
|
|
|
|
{
|
|
|
|
unsigned int state;
|
|
|
|
size_t begin;
|
|
|
|
size_t end;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments.empty()) return Interval(_min,_max);
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
getBeginIndex( position, begin, state );
|
|
|
|
if ( (state == InsideElement) and (_segments[begin]->getNet() != net) )
|
2010-03-09 09:24:55 -06:00
|
|
|
return Interval();
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
end = begin;
|
|
|
|
return expandFreeInterval( begin, end, state, net );
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-12 15:42:57 -06:00
|
|
|
Interval Track::expandFreeInterval ( size_t& begin, size_t& end, unsigned int state, Net* net ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
|
|
|
DbU::Unit minFree = _min;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (not (state & BeginIsTrackMin) ) {
|
|
|
|
if (_segments[begin]->getNet() == net)
|
|
|
|
getPrevious( begin, net );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (begin != npos) {
|
|
|
|
minFree = getOccupiedInterval(begin).getVMax();
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (not (state & EndIsTrackMax) ) {
|
|
|
|
if (_segments[end]->getNet() == net) {
|
|
|
|
getNext( end, net );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (end == npos) {
|
2010-03-09 09:24:55 -06:00
|
|
|
end = _segments.size() - 1;
|
2013-12-03 18:59:29 -06:00
|
|
|
setMaximalFlags( state, EndIsTrackMax );
|
2010-03-09 09:24:55 -06:00
|
|
|
} else {
|
2013-12-03 18:59:29 -06:00
|
|
|
setMaximalFlags( state, EndIsSegmentMin );
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
return Interval( minFree, getMaximalPosition(end,state) );
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
void Track::invalidate ()
|
|
|
|
{ _segmentsValid = false; }
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
|
|
|
void Track::insert ( TrackMarker* marker )
|
|
|
|
{
|
|
|
|
_markers.push_back ( marker );
|
|
|
|
_markersValid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Track::insert ( TrackElement* segment )
|
|
|
|
{
|
2016-05-17 16:00:06 -05:00
|
|
|
// cdebug.log(9000) << "Deter| Track::insert() " << getLayer()->getName()
|
2014-07-06 17:42:38 -05:00
|
|
|
// << " @" << DbU::getValueString(getAxis()) << " " << segment << endl;
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "Track::insert() " << getLayer()->getName()
|
2010-03-09 09:24:55 -06:00
|
|
|
<< " @" << 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
bool Track::check ( unsigned int& overlaps, const char* message ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
|
|
|
bool coherency = true;
|
|
|
|
bool holes = false;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (message) cerr << " o Checking Track - " << message << endl;
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(155) << (void*)this << ":" << this << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_segments.size() ; i++ ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[i]) {
|
|
|
|
if (i) {
|
|
|
|
if (_segments[i-1] == _segments[i]) {
|
2010-03-09 09:24:55 -06:00
|
|
|
cerr << "[CHECK] incoherency at " << i << " "
|
|
|
|
<< _segments[i] << " is duplicated. " << endl;
|
|
|
|
coherency = false;
|
|
|
|
}
|
|
|
|
}
|
2013-12-03 18:59:29 -06:00
|
|
|
if (not _segments[i]->getTrack()) {
|
2010-03-09 09:24:55 -06:00
|
|
|
cerr << "[CHECK] incoherency at " << i << " "
|
|
|
|
<< _segments[i] << " is detached." << endl;
|
|
|
|
coherency = false;
|
|
|
|
} else {
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[i]->getTrack() != this) {
|
2010-03-09 09:24:55 -06:00
|
|
|
cerr << "[CHECK] incoherency at " << i << " "
|
|
|
|
<< _segments[i] << " is in track "
|
|
|
|
<< _segments[i]->getTrack() << endl;
|
|
|
|
coherency = false;
|
|
|
|
}
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[i]->getIndex() != i) {
|
2010-03-09 09:24:55 -06:00
|
|
|
cerr << "[CHECK] incoherency at " << i << " "
|
|
|
|
<< _segments[i] << " has bad index "
|
|
|
|
<< _segments[i]->getIndex() << endl;
|
|
|
|
coherency = false;
|
|
|
|
}
|
|
|
|
}
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[i]->getAxis() != getAxis()) {
|
2010-03-09 09:24:55 -06:00
|
|
|
cerr << "[CHECK] incoherency at " << i << " "
|
|
|
|
<< _segments[i] << " is not on Track axis "
|
|
|
|
<< DbU::getValueString(getAxis()) << "." << endl;
|
|
|
|
coherency = false;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
coherency = _segments[i]->_check() and coherency;
|
2010-03-09 09:24:55 -06:00
|
|
|
} else {
|
|
|
|
cerr << "[CHECK] Hole at position " << i << "." << endl;
|
|
|
|
holes = true;
|
|
|
|
coherency = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (not holes)
|
* ./Kite:
- New: In BuildPowerRails, special processing for the power ring segments.
The "diagonal" of vias at each corner is causing a misbehavior of the
routing algorithm (due to fully saturated GCells in one direction).
As a temporary fix, extend the segments so they form a "square corner".
(problem arise on "d_in_i(22)").
- New: In RoutingEvent::_processNegociate, disable the "isForcedToHint()"
feature. No noticeable loss of quality or speed.
- New: In TrackElement/TrackSegment, wraps the AutoSegment parent's mechanism.
Allows to gets the DataNegociate of either the segment or it's parent.
- New: State::solveFullBlockages(), dedicated method to solves the case when
all the allowed tracks of a segment are blocked, tries to moves up
local segments and to break-up global ones.
- New: RoutingEventLoop, a more sophisticated way to detect looping.
Maintain a dynamic histogram of the last N (default 10) segments routeds,
with the count of how many times they have occurred. If that count
exeed 40, we *may* be facing a loop.
- Change: In State::conflictSolve1, implement new policy. The global segments
no more can be broken by local ones. The idea behind is that breaking
a global on the request of a local will only produce more cluttering
in the GCell. Globals must be keep straigth pass through, especially
inside near-saturated GCells. Globals breaking however can occurs at
another global's request.
- Change: In TrackCost, implement the new policy about locals segments that
cannot break globals segments. The sorting class now accept flags to
modulate the sorting function. Two options avalaibles: IgnoreAxisWeigth
(to uses for strap segments) and DiscardGlobals (to uses with locals).
- Change: In TrackCost, the "distance to fixed" have now an upper bound of
50 lambdas (no need to be greater because it means it's outside the
begin & en GCells). Take account not only of fixed segment, but also
of placed segments which makes bound.
- Bug: In Track::_check(), while calling each individual TrackSegment check,
uses it as the *first* argument of the "or", otherwise it may not be
called.
- Bug: In ProtectRoutingPad, loop over segment Collections while modificating
it was producing non-deterministic results. The fact that a collection
must be not modificated while beeing iterated is becoming a more and more
painful problem.
2010-12-30 12:42:17 -06:00
|
|
|
coherency = (checkOverlap(overlaps) == 0) and coherency;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return coherency;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit Track::getSourcePosition ( size_t i ) const
|
|
|
|
{
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( i == npos) return 0;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return _segments[i]->getSourceU();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit Track::getSourcePosition ( vector<TrackElement*>::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;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
switch ( state & BeginMask ) {
|
|
|
|
case BeginIsTrackMin: return _min;
|
|
|
|
case BeginIsSegmentMin: return _segments[index]->getSourceU ();
|
|
|
|
case BeginIsSegmentMax: return _segments[index]->getTargetU ();
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
cerr << Bug( " Track::getMinimalPosition(size_t,unsigned int) :"
|
|
|
|
" invalid state value %ud.", state ) << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return _min;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit Track::getMaximalPosition ( size_t index, unsigned int state ) const
|
|
|
|
{
|
|
|
|
Interval canonical;
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
switch ( state & EndMask ) {
|
|
|
|
case EndIsTrackMax: return _max;
|
|
|
|
case EndIsSegmentMin: return _segments[index ]->getSourceU ();
|
|
|
|
case EndIsNextSegmentMin: if (index+1 >= getSize()) return _max;
|
|
|
|
return _segments[index+1]->getSourceU ();
|
|
|
|
case EndIsSegmentMax: return _segments[index ]->getTargetU ();
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
cerr << Bug( " Track::getMaximalPosition(size_t,unsigned int) :"
|
|
|
|
" invalid state value %ud.", state ) << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return _min;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
Interval Track::getOccupiedInterval ( size_t& begin ) const
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
2013-12-03 18:59:29 -06:00
|
|
|
if (begin == npos) return Interval();
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
size_t seed = begin;
|
|
|
|
Net* owner = _segments[seed]->getNet();
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
Interval segmentInterval;
|
|
|
|
Interval mergedInterval;
|
|
|
|
_segments[seed]->getCanonical( mergedInterval );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
size_t i = seed;
|
2013-12-03 18:59:29 -06:00
|
|
|
while ( --i != npos ) {
|
|
|
|
if (_segments[i]->getNet() != owner) break;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
_segments[i]->getCanonical ( segmentInterval );
|
|
|
|
if (segmentInterval.getVMax() >= mergedInterval.getVMin()) {
|
|
|
|
mergedInterval.merge( segmentInterval );
|
2010-03-09 09:24:55 -06:00
|
|
|
begin = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
i = seed;
|
2010-03-09 09:24:55 -06:00
|
|
|
while ( ++i < _segments.size() ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[i]->getNet() != owner) break;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
_segments[i]->getCanonical( segmentInterval );
|
|
|
|
if (segmentInterval.getVMin() > mergedInterval.getVMax()) break;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
mergedInterval.merge( segmentInterval );
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
return mergedInterval;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
size_t Track::doRemoval ()
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159,1) << "Track::doRemoval() - " << this << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
size_t size = _segments.size();
|
|
|
|
|
|
|
|
vector<TrackElement*>::iterator beginRemove
|
2013-12-03 18:59:29 -06:00
|
|
|
= remove_if( _segments.begin(), _segments.end(), isDetachedSegment() );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
_segments.erase( beginRemove, _segments.end() );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "After doRemoval " << this << endl;
|
|
|
|
cdebug.tabw(159,-1);
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return size - _segments.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
void Track::doReorder ()
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
2016-05-17 16:00:06 -05:00
|
|
|
cdebug.log(159) << "Track::doReorder() " << this << endl;
|
2014-10-03 09:04:12 -05:00
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (not _segmentsValid ) {
|
2010-03-09 09:24:55 -06:00
|
|
|
std::sort ( _segments.begin(), _segments.end(), SegmentCompare() );
|
|
|
|
for ( size_t i=0 ; i < _segments.size() ; i++ ) {
|
|
|
|
_segments[i]->setIndex ( i );
|
|
|
|
}
|
|
|
|
_segmentsValid = true;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
if (not _markersValid ) {
|
2010-03-09 09:24:55 -06:00
|
|
|
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++ ) {
|
2014-10-03 09:04:12 -05:00
|
|
|
if (not _segments[i]->isBlockage() and (_segments[i]->getLayer() != getLayer()) ) {
|
|
|
|
cerr << Error( " Track vs. Segment Layer discrepency:\n %s\n %s "
|
|
|
|
, getString(this).c_str()
|
|
|
|
, getString(_segments[i]).c_str() ) << endl;
|
|
|
|
}
|
|
|
|
|
2010-03-09 09:24:55 -06:00
|
|
|
if ( _segments[i]->getNet() == _segments[i+1]->getNet() ) {
|
|
|
|
if ( _segments[i]->getSourceU() == _segments[i+1]->getSourceU() ) {
|
|
|
|
if ( _segments[i]->getTargetU() < _segments[i+1]->getTargetU() ) {
|
2014-10-03 09:04:12 -05:00
|
|
|
cerr << Error(" Invalid sorting length order in %s:\n %s\n %s "
|
2013-12-03 18:59:29 -06:00
|
|
|
,getString(this).c_str()
|
|
|
|
,getString(_segments[i ]).c_str()
|
|
|
|
,getString(_segments[i+1]).c_str()) << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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()) ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
cerr << Error("Overlap in %s between:\n %s\n %s"
|
|
|
|
,getString(this).c_str()
|
|
|
|
,getString(_segments[i]).c_str()
|
|
|
|
,getString(_segments[j]).c_str()) << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
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() );
|
2013-12-03 18:59:29 -06:00
|
|
|
record->add ( getSlot ( "_routingPlane", _routingPlane ) );
|
|
|
|
record->add ( getSlot ( "_index" , &_index ) );
|
2010-03-09 09:24:55 -06:00
|
|
|
record->add ( DbU::getValueSlot ( "_axis" , &_axis ) );
|
2013-12-03 18:59:29 -06:00
|
|
|
record->add ( getSlot ( "_segments" , &_segments ) );
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
return record;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
} // Kite namespace.
|