From 81fffb9d0a47732d9b63c44c0ffc1e173f99e033 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sat, 10 Apr 2021 19:51:19 +0200 Subject: [PATCH] Add a new Track finishing stage: close short gaps of same nets wires. * New: In Track::repair(), short gaps between segments of the same nets where occuring and being not detected. This was causing DRC minimal distance violations. Now, fuse the segments when they are too close. Done by extenting the duSource of the rightmost one to the leftlost one. Create ancillary class GapSet to manage the gaps of the various segment of the same net. --- katana/src/KatanaEngine.cpp | 15 ++-- katana/src/Track.cpp | 135 ++++++++++++++++++++++++++++++- katana/src/TrackFixedSegment.cpp | 4 +- katana/src/katana/Track.h | 1 + 4 files changed, 144 insertions(+), 11 deletions(-) diff --git a/katana/src/KatanaEngine.cpp b/katana/src/KatanaEngine.cpp index 0867f3a1..e8766df4 100644 --- a/katana/src/KatanaEngine.cpp +++ b/katana/src/KatanaEngine.cpp @@ -844,13 +844,14 @@ namespace Katana { cdebug_tabw(155,1); - // openSession(); - // for ( RoutingPlane* plane : _routingPlanes ) { - // for ( Track* track : plane->getTracks() ) { - // track->expandMinArea(); - // } - // } - // Session::close(); + openSession(); + for ( RoutingPlane* plane : _routingPlanes ) { + for ( Track* track : plane->getTracks() ) { + //track->expandMinArea(); + track->repair(); + } + } + Session::close(); setState( Anabatic::EngineDriving ); _gutKatana(); diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index 7df026df..46a7cf72 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -38,6 +38,95 @@ namespace { using namespace Katana; + class GapSet { + public: + GapSet ( const Track* ); + inline size_t size () const; + inline const vector< pair >& + spans () const; + inline DbU::Unit sourceU ( size_t ) const; + inline DbU::Unit targetU ( size_t ) const; + void merge ( size_t ); + inline void clear (); + private: + const Track* _track; + DbU::Unit _halfSpacing; + vector< pair > _spans; + }; + + + GapSet::GapSet ( const Track* track ) + : _track(track) + , _halfSpacing(_track->getLayer()->getMinimalSpacing()/2) + , _spans() + { } + + inline size_t GapSet::size () const { return _spans.size(); } + inline const vector< pair >& GapSet::spans () const { return _spans; } + inline void GapSet::clear () + { + // cerr << "GapSet::clear()" << endl; + // for ( size_t i=0 ; i < _spans.size() ; ++i ) { + // cerr << " " << i << "=[" << DbU::getValueString(sourceU(i)) + // << " " << DbU::getValueString(targetU(i)) << "] " ; + // } + // cerr << endl; + _spans.clear(); + } + + inline DbU::Unit GapSet::sourceU ( size_t i ) const + { + // if (_track->getSegment( _spans[i].first)->isNonPref()) { + // cerr << " Non-pref sourceU: " << DbU::getValueString(_track->getSegment( _spans[i].first )->getSourceU()) << endl; + // cerr << " " << _track->getSegment( _spans[i].first ) << endl; + // } + return (i<_spans.size()) ? _track->getSegment( _spans[i].first )->getSourceU()+_halfSpacing : 0; + } + + inline DbU::Unit GapSet::targetU ( size_t i ) const + { + // if (_track->getSegment( _spans[i].second)->isNonPref()) { + // cerr << " Non-pref targetU: " << DbU::getValueString(_track->getSegment( _spans[i].second )->getTargetU()) << endl; + // cerr << " " << _track->getSegment( _spans[i].second ) << endl; + // } + return (i<_spans.size()) ? _track->getSegment( _spans[i].second )->getTargetU()-_halfSpacing : 0; + } + + + void GapSet::merge ( size_t i ) + { + // cerr << "GapSet::merge() " << _track->getSegment( i ) << endl; + if (_spans.empty()) { + _spans.push_back( make_pair(i,i) ); + return; + } + + size_t ispan = 0; + TrackElement* element = _track->getSegment( i ); + DbU::Unit segSourceU = element->getSourceU()+_halfSpacing; + DbU::Unit segTargetU = element->getTargetU()-_halfSpacing; + for ( ; ispan<_spans.size() ; ++ispan ) { + if (targetU(ispan) >= segSourceU) { + if (targetU(ispan) >= segTargetU) + return; + _spans[ispan].second = i; + break; + } + } + if (ispan == _spans.size()) { + _spans.push_back( make_pair(i,i) ); + return; + } + while ( ispan+1 < _spans.size() ) { + if (targetU(ispan) >= sourceU(ispan+1)) { + _spans[ispan].second = std::max( targetU(ispan), targetU(ispan+1) ); + _spans.erase( _spans.begin()+ispan+1 ); + } + } + } + + + struct isDetachedSegment { bool operator() ( const TrackElement* s ) { return not s->getTrack(); }; }; @@ -847,6 +936,48 @@ namespace Katana { } + uint32_t Track::repair () const + { + if (_segments.empty()) return 0; + DbU::Unit minSpacing = getLayer()->getMinimalSpacing(); + + uint32_t gaps = 0; + GapSet gapset ( this ); + for ( size_t i=0 ; i<_segments.size()-1 ; i++ ) { + gapset.merge( i ); + if ( (_segments[i]->getNet() != _segments[i+1]->getNet()) + or _segments[i]->getLayer()->isBlockage() ) { + if (gapset.size() > 1) { + // cerr << "potential gap around " << _segments[i] << endl; + for ( size_t j=0 ; j+1 < gapset.size() ; ++j ) { + // cerr << j << "=[" << DbU::getValueString(gapset.sourceU(j)) + // << " " << DbU::getValueString(gapset.targetU(j)) << "], " + // << j+1 << "=[" << DbU::getValueString(gapset.sourceU(j+1)) + // << " " << DbU::getValueString(gapset.targetU(j+1)) << "]" << endl; + DbU::Unit spacing = gapset.sourceU(j+1) - gapset.targetU(j); + // cerr << "| spacing=" << DbU::getValueString(spacing) << endl; + if (spacing < minSpacing) { + AutoSegment* first = _segments[j+1]->base(); + for ( AutoSegment* segment : _segments[j]->base()->getAligneds() ) { + if (segment->getSourcePosition() < first->getSourcePosition()) + first = segment; + } + first->setDuSource( first->getDuSource() - spacing ); + ++gaps; + cerr << Warning( " Track::repair(): Closing same net gap in %s near:\n %s" + , getString(this).c_str() + , getString(_segments[i-1]).c_str() ) << endl; + } + } + } + gapset.clear(); + } + } + + return gaps; + } + + uint32_t Track::checkOverlap ( uint32_t& overlaps ) const { if ( !_segments.size() ) return 0; @@ -873,8 +1004,8 @@ namespace Katana { j = i+1; } - if ( (j<_segments.size()) - && (_segments[i]->getTargetU() > _segments[j]->getSourceU()) ) { + if ( (j<_segments.size()) + and (_segments[i]->getTargetU() > _segments[j]->getSourceU()) ) { cerr << Error("Overlap in %s between:\n %s\n %s\n TargetU:%s SourceU:%s" ,getString(this).c_str() ,getString(_segments[i]).c_str() diff --git a/katana/src/TrackFixedSegment.cpp b/katana/src/TrackFixedSegment.cpp index 199e7e2f..721b5819 100644 --- a/katana/src/TrackFixedSegment.cpp +++ b/katana/src/TrackFixedSegment.cpp @@ -68,8 +68,8 @@ namespace Katana { if (track) { uint32_t depth = track->getDepth(); - Technology* technology = DataBase::getDB()->getTechnology(); - const Layer* layer1 = track->getLayer()->getBlockageLayer(); + //Technology* technology = DataBase::getDB()->getTechnology(); + //const Layer* layer1 = track->getLayer()->getBlockageLayer(); //RegularLayer* layer2 = dynamic_cast(technology->getLayer(layer1->getMask())); //if (layer2) { //cerr << track->getLayer() << " minSpace:" << DbU::getValueString(track->getLayer()->getMinimalSpacing()) << endl; diff --git a/katana/src/katana/Track.h b/katana/src/katana/Track.h index 8a59de55..5d4139c7 100644 --- a/katana/src/katana/Track.h +++ b/katana/src/katana/Track.h @@ -97,6 +97,7 @@ namespace Katana { TrackCost& addOverlapCost ( TrackCost& ) const; void getTerminalWeight ( Interval, Net*, size_t& count, uint32_t& weight ) const; DbU::Unit getSourcePosition ( size_t index ) const; + uint32_t repair () const; bool check ( uint32_t& overlaps, const char* message=NULL ) const; uint32_t checkOverlap ( uint32_t& overlaps ) const; uint32_t checkMinArea () const;