From 7bae6d8bad7e6ba635a8676935256a63c63a1054 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Wed, 17 Feb 2021 23:57:45 +0100 Subject: [PATCH] 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. --- katana/src/NegociateWindow.cpp | 88 ++++++++++++++++++--------------- katana/src/PowerRails.cpp | 8 +-- katana/src/PreProcess.cpp | 2 +- katana/src/RoutingPlane.cpp | 2 +- katana/src/Track.cpp | 36 +++++++------- katana/src/TrackSegment.cpp | 6 ++- katana/src/TrackSegmentWide.cpp | 5 +- 7 files changed, 82 insertions(+), 65 deletions(-) diff --git a/katana/src/NegociateWindow.cpp b/katana/src/NegociateWindow.cpp index 2ec64475..ea09d99c 100644 --- a/katana/src/NegociateWindow.cpp +++ b/katana/src/NegociateWindow.cpp @@ -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 ); } diff --git a/katana/src/PowerRails.cpp b/katana/src/PowerRails.cpp index 8d719ca4..63228ef7 100644 --- a/katana/src/PowerRails.cpp +++ b/katana/src/PowerRails.cpp @@ -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(); + } } } diff --git a/katana/src/PreProcess.cpp b/katana/src/PreProcess.cpp index d0336109..d53e7a98 100644 --- a/katana/src/PreProcess.cpp +++ b/katana/src/PreProcess.cpp @@ -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; diff --git a/katana/src/RoutingPlane.cpp b/katana/src/RoutingPlane.cpp index fd18f9a8..ee4fefaf 100644 --- a/katana/src/RoutingPlane.cpp +++ b/katana/src/RoutingPlane.cpp @@ -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) diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index 2eb93b9e..9ac92725 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -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(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::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); diff --git a/katana/src/TrackSegment.cpp b/katana/src/TrackSegment.cpp index 52a6ba12..1f300d2d 100644 --- a/katana/src/TrackSegment.cpp +++ b/katana/src/TrackSegment.cpp @@ -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(); diff --git a/katana/src/TrackSegmentWide.cpp b/katana/src/TrackSegmentWide.cpp index 80a555b0..473402c9 100644 --- a/katana/src/TrackSegmentWide.cpp +++ b/katana/src/TrackSegmentWide.cpp @@ -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;