2010-03-09 09:24:55 -06:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
2015-03-17 10:42:12 -05:00
|
|
|
// Copyright (c) UPMC 2008-2015, 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::inltrace;
|
|
|
|
using Hurricane::ltracein;
|
|
|
|
using Hurricane::ltraceout;
|
|
|
|
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 ()
|
2013-12-03 18:59:29 -06:00
|
|
|
{ ltrace(90) << "Track::~Track() - " << (void*)this << endl; }
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
|
|
|
|
void Track::_preDestroy ()
|
|
|
|
{
|
|
|
|
ltrace(90) << "Track::_preDestroy() - " << (void*)this << " " << this << endl;
|
|
|
|
ltracein(90);
|
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_segments.size() ; i++ )
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[i]) _segments[i]->detach();
|
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
|
|
|
|
|
|
|
ltraceout(90);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Track::destroy ()
|
|
|
|
{
|
|
|
|
ltrace(90) << "Track::destroy() - " << (void*)this << " " << this << endl;
|
|
|
|
|
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-- ) {
|
|
|
|
if (inltrace(148)) {
|
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?
|
|
|
|
if (begin < _segments.size())
|
|
|
|
for ( ; (begin > 0) and (_segments[begin-1]->getNet() == _segments[begin]->getNet()) ; --begin );
|
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 {
|
2013-12-03 18:59:29 -06:00
|
|
|
if (begin) 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 );
|
2010-03-09 09:24:55 -06:00
|
|
|
while ( end < _segments.size() ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
if (_segments[end++]->getSourceU() >= interval.getVMax()) break;
|
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
|
|
|
|
* ./kite:
- New: In BuilPowerRails & BuildBlockage, specific support for chip-level
design. The Alliance "top chip" design hierarchical structure is
hard-coded. Top level POWER/GROUND/CLOCK nets must always have the
<vsse>, <vdde>, <ck>, <vssi>, <vddi>, <ckc>, <cki> names.
Specific method to get trans-hierarchical root nets, espcially in
case of global ones (POWER/GROUND). Clock is *not* global.
Some correction in the manner obscured tracks are computeds.
- New: ProtectRoutingPad module that perform a more clean work for protecting
unused RoutingPad.
- Bug: In BuildPowerRails, uses stable_sort<> instead of sort<>, which
causes unexplained core dumps (seems to try to perform a comparison
using the "end" pseudo element). Already occured in Knik, no explanation
other than a STL bug.
- Change: Slight changes in the weights to move up. Now needs a full empty
track instead of a half one.
2010-11-16 08:00:03 -06:00
|
|
|
ltrace(190) << "getOverlapCost() @" << DbU::getValueString(_axis)
|
|
|
|
<< " [" << DbU::getValueString(interval.getVMin())
|
* ./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
|
|
|
<< ":" << DbU::getValueString(interval.getVMax())
|
|
|
|
<< "] <-> [" << begin << ":" << end << "]"
|
* ./kite:
- New: In BuilPowerRails & BuildBlockage, specific support for chip-level
design. The Alliance "top chip" design hierarchical structure is
hard-coded. Top level POWER/GROUND/CLOCK nets must always have the
<vsse>, <vdde>, <ck>, <vssi>, <vddi>, <ckc>, <cki> names.
Specific method to get trans-hierarchical root nets, espcially in
case of global ones (POWER/GROUND). Clock is *not* global.
Some correction in the manner obscured tracks are computeds.
- New: ProtectRoutingPad module that perform a more clean work for protecting
unused RoutingPad.
- Bug: In BuildPowerRails, uses stable_sort<> instead of sort<>, which
causes unexplained core dumps (seems to try to perform a comparison
using the "end" pseudo element). Already occured in Knik, no explanation
other than a STL bug.
- Change: Slight changes in the weights to move up. Now needs a full empty
track instead of a half one.
2010-11-16 08:00:03 -06:00
|
|
|
<< endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
|
|
|
|
ltracein(148);
|
|
|
|
|
|
|
|
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++ ) {
|
2010-03-09 09:24:55 -06:00
|
|
|
ltrace(148) << "| @" << DbU::getValueString(_axis) << _markers[mbegin] << endl;
|
|
|
|
if ( _markers[mbegin]->getNet() != net ) {
|
|
|
|
ltrace(148) << "* 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) {
|
|
|
|
ltrace(148) << " begin == npos (after last TrackElement)." << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
ltraceout(148);
|
|
|
|
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() );
|
|
|
|
}
|
|
|
|
ltrace(190) << "| overlap: " << _segments[begin] << endl;
|
|
|
|
_segments[begin]->incOverlapCost( net, cost );
|
|
|
|
if (cost.isInfinite()) break;
|
2010-03-09 09:24:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
ltraceout(148);
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
|
|
|
ltrace(148) << "getTerminalWeight() @" << DbU::getValueString(_axis)
|
|
|
|
<< " [" << interval.getVMin() << " " << interval.getVMax() << "]" << endl;
|
|
|
|
ltracein(148);
|
|
|
|
|
|
|
|
//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++ ) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
2014-07-06 17:42:38 -05:00
|
|
|
// ltrace(500) << "Deter| Track::insert() " << getLayer()->getName()
|
|
|
|
// << " @" << DbU::getValueString(getAxis()) << " " << segment << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
ltrace(90) << (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
|
|
|
{
|
2013-12-03 18:59:29 -06:00
|
|
|
ltrace(148) << "Track::doRemoval() - " << this << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
ltracein(148);
|
|
|
|
|
|
|
|
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
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
ltrace(148) << "After doRemoval " << this << endl;
|
2010-03-09 09:24:55 -06:00
|
|
|
ltraceout(148);
|
|
|
|
|
|
|
|
return size - _segments.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:59:29 -06:00
|
|
|
void Track::doReorder ()
|
2010-03-09 09:24:55 -06:00
|
|
|
{
|
2014-10-03 09:04:12 -05:00
|
|
|
ltrace(200) << "Track::doReorder() " << this << endl;
|
|
|
|
|
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.
|