From 97d5a1f583a5943f3a45368cc29bf2f0caa6bb81 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Wed, 21 Feb 2018 17:03:43 +0100 Subject: [PATCH] Bad computation of optimal position for analog segments. * Bug: In Anabatic::AutoSegment::computeOptimal(), the "side stack" computing the intersection of all the sides of the GCell that the segment is going through was implicitly supposing that the resulting intersection wasn't empty. But for analog segment, we compute the position of all the segments linked though simple doglegs, and as dogleg occurs there can be a sufficient shift so the intersections of all the sides became empty. Now the "side stack" can manage configuration when instead of having an intersection we have a "hole" in the GCell side span (only one hole is supported at the moment). When a hole is present, the optimal position is the center of the hole. Should be refined so that the position is computed according to the longest GCell that we go through. * Change: In Katana::SegmentFsm::_slackenGlobal(), when slackening a global from a ananlog net, allow to make a dog leg once instead of immediately moving up. The break point is the center of the segment. * Change: In Katana::Manipulator::Makedogleg(DbU::Unit) if the break position is over a device, choose the left of right GCell. --- anabatic/src/AutoSegment.cpp | 78 +++++++++++++++++++++++++----------- katana/src/Manipulator.cpp | 6 +++ katana/src/SegmentFsm.cpp | 10 ++++- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/anabatic/src/AutoSegment.cpp b/anabatic/src/AutoSegment.cpp index ec0c2d42..88f2a113 100644 --- a/anabatic/src/AutoSegment.cpp +++ b/anabatic/src/AutoSegment.cpp @@ -239,16 +239,20 @@ namespace { class SideStack { public: - SideStack ( Flags direction, DbU::Unit pitch ); - const Interval& getSideAt ( DbU::Unit ) const; - inline const Interval& getGSide () const; - inline DbU::Unit getGSideMin () const; - inline DbU::Unit getGSideMax () const; - void addGCell ( const GCell* ); - inline void restrictGSide ( const Interval& ); - void show () const; + SideStack ( Flags direction, DbU::Unit pitch ); + inline bool isHoled () const; + const Interval& getSideAt ( DbU::Unit ) const; + inline const Interval& getGSide () const; + inline DbU::Unit getGSideMin () const; + inline DbU::Unit getGSideMax () const; + inline DbU::Unit getGSideCenter () const; + void addGCell ( const GCell* ); + inline bool intersect ( const Interval& ) const; + inline void restrictGSide ( const Interval& ); + void show () const; private: Flags _direction; + bool _holed; DbU::Unit _pitch; Interval _full; Interval _gside; @@ -258,6 +262,7 @@ namespace { SideStack::SideStack ( Flags direction, DbU::Unit pitch ) : _direction( (direction & Flags::Horizontal) ? Flags::Vertical : Flags::Horizontal ) + , _holed (false) , _pitch (pitch) , _full (false) , _gside (false) @@ -265,10 +270,13 @@ namespace { { } - inline const Interval& SideStack::getGSide () const { return _gside; } - inline DbU::Unit SideStack::getGSideMin () const { return _gside.getVMin(); } - inline DbU::Unit SideStack::getGSideMax () const { return _gside.getVMax(); } - inline void SideStack::restrictGSide ( const Interval& restrict ) { _gside.intersection( restrict ); } + inline bool SideStack::isHoled () const { return _holed; } + inline const Interval& SideStack::getGSide () const { return _gside; } + inline DbU::Unit SideStack::getGSideMin () const { return _gside.getVMin(); } + inline DbU::Unit SideStack::getGSideMax () const { return _gside.getVMax(); } + inline DbU::Unit SideStack::getGSideCenter () const { return _gside.getVMax(); } + inline bool SideStack::intersect ( const Interval& side ) const { return _gside.intersect(side); } + inline void SideStack::restrictGSide ( const Interval& restrict ) { if (not _holed) _gside.intersection(restrict); } const Interval& SideStack::getSideAt ( DbU::Unit position ) const @@ -290,7 +298,20 @@ namespace { DbU::Unit position = (_direction & Flags::Vertical) ? gcell->getBoundingBox().getXMin() : gcell->getBoundingBox().getYMin(); - _gside.intersection( side ); + if (not _holed and intersect(side)) _gside.intersection( side ); + else { + if (not _holed) { + _holed = true; + if (side.getVMin() > _gside.getVMax()) _gside = Interval( _gside.getVMax(), side.getVMin() ); + else _gside = Interval( side.getVMax(), _gside.getVMin() ); + } else { + if (not intersect(side)) { + if (side.getVMax() < _gside.getVMin()) _gside.merge( side.getVMax() ); + else _gside.merge( side.getVMin() ); + } + } + } + _sides.insert( make_pair(position,side) ); } @@ -1176,15 +1197,20 @@ namespace Anabatic { cdebug_log(145,0) << "Using pitch for L/T shrink:" << DbU::getValueString(getPitch()) << endl; for ( AutoSegment* aligned : aligneds ) { + cdebug_log(145,0) << "@ " << aligned << endl; + aligned->getGCells( gcells ); for ( GCell* gcell : gcells ) { sideStack.addGCell( gcell ); cdebug_log(145,0) << "| gcellSide:" << sideStack.getGSide() << " (from " << gcell << ")" << endl; } - if (aligned->isStrongTerminal()) { + if (aligned->isStrongTerminal() and not sideStack.isHoled()) { + cdebug_log(145,0) << "> Is strong terminal, restrict." << aligned << endl; + Interval terminalConstraints; aligned->getConstraints( terminalConstraints ); sideStack.restrictGSide( terminalConstraints ); + cdebug_log(145,0) << "| " << terminalConstraints.intersection(sideStack.getGSide()) << endl; cdebug_log(145,0) << "| gcellSide:" << sideStack.getGSide() << " (from " << aligned << ")" << endl; } } @@ -1274,20 +1300,24 @@ namespace Anabatic { cdebug_tabw(145,-1); } - if (attractors.getAttractorsCount()) { - optimalMin = attractors.getLowerMedian(); - optimalMax = attractors.getUpperMedian(); + if (sideStack.isHoled()) { + optimalMin = optimalMax = sideStack.getGSideCenter(); } else { - cdebug_log(145,0) << "No attractors, reverting to GCell bounding box" << endl; + if (attractors.getAttractorsCount()) { + optimalMin = attractors.getLowerMedian(); + optimalMax = attractors.getUpperMedian(); + } else { + cdebug_log(145,0) << "No attractors, reverting to GCell bounding box" << endl; + + optimalMin = 0; + optimalMax = (isHorizontal()) ? _gcell->getBoundingBox().getYMax() + : _gcell->getBoundingBox().getXMax(); + } - optimalMin = 0; - optimalMax = (isHorizontal()) ? _gcell->getBoundingBox().getYMax() - : _gcell->getBoundingBox().getXMax(); + setInBound( sideStack.getGSideMin(), sideStack.getGSideMax(), optimalMin ); + setInBound( sideStack.getGSideMin(), sideStack.getGSideMax(), optimalMax ); } - setInBound( sideStack.getGSideMin(), sideStack.getGSideMax(), optimalMin ); - setInBound( sideStack.getGSideMin(), sideStack.getGSideMax(), optimalMax ); - cdebug_log(145,0) << "optimalMin: " << DbU::getValueString(optimalMin) << endl; cdebug_log(145,0) << "optimalMax: " << DbU::getValueString(optimalMax) << endl; } diff --git a/katana/src/Manipulator.cpp b/katana/src/Manipulator.cpp index 5a612033..41f57da1 100644 --- a/katana/src/Manipulator.cpp +++ b/katana/src/Manipulator.cpp @@ -1263,6 +1263,12 @@ namespace Katana { break; } if (igcell == gcells.size()) return false; + if (gcells[igcell]->isDevice()) { + if (igcell > 0) --igcell; + else if (igcell < gcells.size()-1) ++igcell; + else return false; + } + if (not _segment->canDogleg(gcells[igcell])) return false; TrackElement* dogleg = NULL; diff --git a/katana/src/SegmentFsm.cpp b/katana/src/SegmentFsm.cpp index 4d609406..2b1baa7d 100644 --- a/katana/src/SegmentFsm.cpp +++ b/katana/src/SegmentFsm.cpp @@ -1286,13 +1286,19 @@ namespace Katana { case DataNegociate::RipupPerpandiculars: case DataNegociate::Minimize: case DataNegociate::Dogleg: - cdebug_log(159,0) << "Global, SegmentFsm: RipupPerpandiculars." << endl; + if (NetRoutingExtension::isAnalog(segment->getNet())) { + cdebug_log(159,0) << "Global, SegmentFsm / Analogic: Try to dogleg once." << endl; + success = manipulator.makeDogleg( segment->getCanonicalInterval().getCenter() ); + if (success) break; + } else { + cdebug_log(159,0) << "Global, SegmentFsm: RipupPerpandiculars." << endl; + } nextState = DataNegociate::Slacken; break; case DataNegociate::Slacken: cdebug_log(159,0) << "Global, SegmentFsm: Slacken " << ((manipulator.getEvent()) - ? manipulator.getEvent()->getConstraints() : "(not event yet)") << endl; + ? manipulator.getEvent()->getConstraints() : "(no event yet)") << endl; if ( manipulator.getEvent() and manipulator.getEvent()->getConstraints().isPonctual() and segment->canMoveUp(1.0,Flags::CheckLowUpDensity|Flags::AllowTerminal) ) {