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.
This commit is contained in:
Jean-Paul Chaput 2018-02-21 17:03:43 +01:00
parent 793dbb26b2
commit 97d5a1f583
3 changed files with 68 additions and 26 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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) ) {