Partial management of offgrid fixed segments in Katana.

NOTE: To myself, one more bug uncovered in the Track segments management.
      This is really too complex, must find time to re-think and simplify
      the whole thing.

* New: In Katana::NegociateWidow::createTrackSegment(), detect offgrid
    fixed segments and insert them into tracks directly (as *wide* segment
    of two tracks).
* New: In Katana::TrackSegment::create() factory method, check for offgrid
    fixed segment and use a TrackSegmentWide (of 2 tracks) for them.
* New: In Katana::TrackSegmentWide CTOR, check if they are used in the
    context of an offgrid segment and in that case set the track span
    to two. We *do not* manage yet the case for both *wide* and *offgrid*
    segments.
* Change: In Katana::PowerRails::Rails::doLayout(), do not expand blockage
    rectangles over their real size. Add the guard only for real layers
    segments.
* Bug: In Katana::PreProcess::propagateCagedConstraints(), when looking
    for the first track index, check for out of bound value (npos).
* Bug: In Katana::Track::addOverlapCost(), before using the overlap
    segment indexes, check if we are not in a free hole (get the free
    interval from center).
* Bug: In Katana::Track::expandFreeInterval(), the interval was badly
    computed if it was included inside segments of another (same) net.
This commit is contained in:
Jean-Paul Chaput 2021-02-17 23:57:45 +01:00
parent db0ad6bf07
commit 7bae6d8bad
7 changed files with 82 additions and 65 deletions

View File

@ -321,45 +321,53 @@ namespace Katana {
DebugSession::open( autoSegment->getNet(), 159, 160 );
cdebug_log(159,1) << "NegociateWindow::createTrackSegment() - " << autoSegment << endl;
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(autoSegment->getLayer());
Track* refTrack = plane->getTrackByPosition( autoSegment->getAxis() );
Track* insTrack = NULL;
size_t trackSpan = 1;
// Special case: fixed AutoSegments must not interfere with blockages.
// Ugly: uses of getExtensionCap().
if (autoSegment->isFixed()) {
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(autoSegment->getLayer());
Track* track = plane->getTrackByPosition( autoSegment->getAxis() );
size_t begin;
size_t end;
Interval fixedSpan;
Interval blockageSpan;
autoSegment->getCanonical( fixedSpan );
fixedSpan.inflate( Session::getExtensionCap(autoSegment->getLayer())-1 );
if (refTrack->getAxis() != autoSegment->getAxis()) {
trackSpan = 2;
refTrack = plane->getTrackByPosition( autoSegment->getAxis(), Constant::Inferior );
insTrack = refTrack;
}
track->getOverlapBounds( fixedSpan, begin, end );
for ( ; (begin < end) ; begin++ ) {
Track* track = refTrack;
for ( size_t ispan=0 ; track and (ispan < trackSpan) ; ++ispan, track=track->getNextTrack() ) {
autoSegment->getCanonical( fixedSpan );
fixedSpan.inflate( Session::getExtensionCap(autoSegment->getLayer())-1 );
TrackElement* other = track->getSegment(begin);
cdebug_log(159,0) << "| overlap: " << other << endl;
track->getOverlapBounds( fixedSpan, begin, end );
for ( ; (begin < end) ; begin++ ) {
TrackElement* other = track->getSegment(begin);
cdebug_log(159,0) << "| overlap: " << other << endl;
if (not other->isBlockage()) continue;
if (not other->isBlockage()) continue;
other->getCanonical( blockageSpan );
blockageSpan.inflate( Session::getExtensionCap(autoSegment->getLayer()) );
other->getCanonical( blockageSpan );
blockageSpan.inflate( Session::getExtensionCap(autoSegment->getLayer()) );
cdebug_log(159,0) << " fixed:" << fixedSpan << " vs. blockage:" << blockageSpan << endl;
cdebug_log(159,0) << " fixed:" << fixedSpan << " vs. blockage:" << blockageSpan << endl;
if (not fixedSpan.intersect(blockageSpan)) continue;
if (not fixedSpan.intersect(blockageSpan)) continue;
// Overlap between fixed & blockage.
cdebug_log(159,0) << "* Blockage overlap: " << autoSegment << endl;
//Session::destroyRequest( autoSegment );
cerr << Warning( "Overlap between fixed %s and blockage at %s."
, getString(autoSegment).c_str()
, getString(blockageSpan).c_str() ) << endl;
cdebug_tabw(159,-1);
DebugSession::close();
return NULL;
// Overlap between fixed & blockage.
cdebug_log(159,0) << "* Blockage overlap: " << autoSegment << endl;
//Session::destroyRequest( autoSegment );
cerr << Warning( "Overlap between fixed %s and blockage at %s."
, getString(autoSegment).c_str()
, getString(blockageSpan).c_str() ) << endl;
cdebug_tabw(159,-1);
DebugSession::close();
return NULL;
}
}
}
@ -367,7 +375,7 @@ namespace Katana {
autoSegment = autoSegment->getCanonical( span );
bool created;
TrackElement* trackSegment = TrackSegment::create( autoSegment, NULL, created );
TrackElement* trackSegment = TrackSegment::create( autoSegment, insTrack, created );
if (not (flags & Flags::LoadingStage))
cdebug_log(159,0) << "* lookup: " << autoSegment << endl;
@ -383,38 +391,38 @@ namespace Katana {
return trackSegment;
}
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(autoSegment->getLayer());
Track* track = plane->getTrackByPosition ( autoSegment->getAxis() );
Interval uside = autoSegment->getAutoSource()->getGCell()->getSide( perpandicularTo(autoSegment->getDirection()) );
Interval constraints;
Interval uside = autoSegment->getAutoSource()->getGCell()->getSide( perpandicularTo(autoSegment->getDirection()) );
Interval constraints;
autoSegment->getConstraints( constraints );
cdebug_log(159,0) << "* Constraints " << constraints << endl;
uside.intersection( constraints );
cdebug_log(159,0) << "* Constraints+U-side " << constraints << endl;
cdebug_log(159,0) << "* Nearest " << track << endl;
cdebug_log(159,0) << "* Nearest " << refTrack << endl;
if (not track)
if (not refTrack)
throw Error( "NegociateWindow::createTrackSegment(): No track near axis of %s."
, getString(autoSegment).c_str() );
if (track->getAxis() > uside.getVMax()) track = track->getPreviousTrack();
if (track->getAxis() < uside.getVMin()) track = track->getNextTrack();
if (not track)
if (not insTrack) {
insTrack = refTrack;
if (refTrack->getAxis() > uside.getVMax()) insTrack = refTrack->getPreviousTrack();
if (refTrack->getAxis() < uside.getVMin()) insTrack = refTrack->getNextTrack();
}
if (not insTrack)
throw Error( "NegociateWindow::createTrackSegment(): No track near axis of %s (after adjust)."
, getString(autoSegment).c_str() );
cdebug_log(159,0) << "* GCell U-side " << uside << endl;
cdebug_log(159,0) << "* " << plane << endl;
cdebug_log(159,0) << "* " << track << endl;
cdebug_log(159,0) << "* " << insTrack << endl;
trackSegment->setAxis( track->getAxis(), AutoSegment::SegAxisSet );
if (trackSpan == 1)
trackSegment->setAxis( insTrack->getAxis(), AutoSegment::SegAxisSet );
trackSegment->invalidate();
if (trackSegment->isFixed()) {
Session::addInsertEvent( trackSegment, track, track->getAxis() );
if (trackSegment->isFixed() and not trackSegment->getTrack()) {
Session::addInsertEvent( trackSegment, insTrack, refTrack->getAxis() );
} else {
_segments.push_back( trackSegment );
}

View File

@ -518,9 +518,11 @@ namespace {
DbU::Unit axisMin = 0;
DbU::Unit axisMax = 0;
if (AllianceFramework::get()->getCellGauge()->getName() == Name("FlexLib")) {
if (_width >= DbU::fromPhysical( 10.0, DbU::UnitPower::Micro )) {
delta = 2 * plane->getLayerGauge()->getPitch();
if (not layer->isBlockage()) {
if (AllianceFramework::get()->getCellGauge()->getName() == Name("FlexLib")) {
if (_width >= DbU::fromPhysical( 10.0, DbU::UnitPower::Micro )) {
delta = 2 * plane->getLayerGauge()->getPitch();
}
}
}

View File

@ -142,7 +142,7 @@ namespace {
// Computing constraints from fixed only TrackElements (caging).
TrackElement* parallel;
size_t i = track->find( segment );
while ( i > 0 ) {
while ( (i != Track::npos) and (i > 0) ) {
parallel = track->getSegment( --i );
if (not parallel) continue;
if (parallel->getTargetU() < uside.getVMin()) break;

View File

@ -50,7 +50,7 @@ namespace Katana {
RoutingPlane::RoutingPlane ( KatanaEngine* katana, size_t depth )
: _katana (katana)
: _katana (katana)
, _layerGauge(katana->getConfiguration()->getLayerGauge(depth))
, _depth (depth)
, _flags (0)

View File

@ -54,7 +54,7 @@ namespace {
: segment->base()->getAutoTarget() ;
if (contact->getLayer() != layer) return false;
if (not contact->isTurn()) return false;
AutoSegment* pp = contact->getPerpandicular( segment->base() );
//AutoSegment* pp = contact->getPerpandicular( segment->base() );
return contact->getPerpandicular(segment->base())->getLength();
}
@ -368,11 +368,13 @@ namespace Katana {
TrackCost& Track::addOverlapCost ( TrackCost& cost ) const
{
size_t begin = Track::npos;
size_t end = Track::npos;
const Interval& interval = cost.getInterval();
size_t begin = Track::npos;
size_t end = Track::npos;
const Interval& interval = cost.getInterval();
Interval freeInterval = getFreeInterval( interval.getCenter(), cost.getNet() );
getOverlapBounds( cost.getInterval(), begin, end );
if (not freeInterval.contains(interval))
getOverlapBounds( cost.getInterval(), begin, end );
cost.setTrack( const_cast<Track*>(this), begin, end );
cdebug_log(155,1) << "addOverlapCost() @" << DbU::getValueString(_axis)
@ -380,6 +382,9 @@ namespace Katana {
<< ":" << DbU::getValueString(interval.getVMax())
<< "] <-> [" << begin << ":" << end << "]"
<< endl;
cdebug_log(155,0) << "freeInterval [" << DbU::getValueString(freeInterval.getVMin())
<< ":" << DbU::getValueString(freeInterval.getVMax()) << "]"
<< endl;
vector<TrackMarker*>::const_iterator lowerBound
= lower_bound( _markers.begin(), _markers.end(), interval.getVMin(), TrackMarker::Compare() );
@ -407,7 +412,8 @@ namespace Katana {
for ( ; begin < end ; begin++ ) {
Interval overlap = interval.getIntersection( _segments[begin]->getCanonicalInterval() );
cdebug_log(155,0) << "overlap:" << overlap << " size:" << overlap.getSize() << endl;
cdebug_log(155,0) << "overlap:" << overlap
<< " size:" << DbU::getValueString(overlap.getSize()) << endl;
if (overlap.getSize() == 0) continue;
if (_segments[begin]->getNet() == cost.getNet()) {
@ -523,19 +529,15 @@ namespace Katana {
} else {
cdebug_log(155,0) << "| same net, end:" << end << " (after last)" << endl;
}
if (end == npos) {
end = _segments.size() - 1;
setMaximalFlags( state, EndIsTrackMax );
} else {
setMaximalFlags( state, EndIsSegmentMin );
}
} else {
state = EndIsTrackMax;
cdebug_log(155,0) << "| already after last" << endl;
}
if (end == npos) {
end = _segments.size() - 1;
setMaximalFlags( state, EndIsTrackMax );
} else {
setMaximalFlags( state, EndIsSegmentMin );
}
cdebug_log(155,0) << "end:" << end << " state:" << state << endl;
cdebug_log(155,0) << "end:" << _segments[end] << endl;
}
cdebug_tabw(155,-1);

View File

@ -147,10 +147,12 @@ namespace Katana {
cerr << Error( "TrackSegment::create(): Must not set track when creating a non-preferred element.\n"
" (on %s)", getString(segment).c_str() ) << endl;
} else {
if (segment->base()->getWidth() <= defaultWireWidth)
if (segment->isFixed() and track and (segment->getAxis() != track->getAxis()))
trackElement = new TrackSegmentWide( segment, track );
else if (segment->base()->getWidth() <= defaultWireWidth)
trackElement = new TrackSegmentRegular( segment, track );
else
trackElement = new TrackSegmentWide ( segment, track );
trackElement = new TrackSegmentWide( segment, track );
}
trackElement->_postCreate();

View File

@ -62,8 +62,11 @@ namespace Katana {
if (not _trackSpan) {
DbU::Unit mWidth = std::max( Session::getWireWidth(getLayer()), Session::getViaWidth(getLayer()) );
if (segment->getWidth() < mWidth) {
if (segment->getWidth() <= mWidth) {
_trackSpan = 1;
if (track and (track->getAxis() != segment->getAxis())) {
_trackSpan = 2;
}
} else {
DbU::Unit pitch = Session::getPitch(segment->getLayer());
DbU::Unit width = segment->getWidth() - mWidth;