Add a zero-length segment compaction stage in Anabatic DTOR.

* New: In AnabaticEngine::_gutAnabatic(), perform progessive compaction
    of segment of null length.
      CAUTION: Reduced segments *may* not be null length segments.
               They are "less or equal" than one perpandicular pitch and
	       can have their layer put into the perpandicular one.
                 They non-null one *must* be excluded for the compaction.
      Null segments are compacted starting from the one connecteds to
   non-null length segments. This is to avoid the compaction starting
   in the middle of a whole set of zero-segments that will block further
   compaction.
     This behavior was causing "zero-length" segment on orphaned layers
   that were causing minumal area DRC errors.
* Change: AutoSegment::canReduce() is modified so it now takes a flag
    argument to tell it to look for collapisble zero-length segments.
* New: AutoSegment::getNonReduceds(): returns the number of non-zero
    length segments connecteds to the current one.
* Change: In AutoSegment::reduceDoglegLayer(), use the perpandicular
    width of the routing layer instead of the regular (parallel) one.
      This was causing DRC errors.
This commit is contained in:
Jean-Paul Chaput 2021-04-12 23:50:25 +02:00
parent 2f24c05a72
commit 2002282483
5 changed files with 109 additions and 13 deletions

View File

@ -122,6 +122,33 @@ namespace {
}
class NonReducedItem {
public:
inline NonReducedItem ( AutoSegment* segment=NULL, uint32_t nonReduceds=0 );
inline AutoSegment* segment () const;
inline uint32_t nonReduceds () const;
private:
AutoSegment* _segment;
uint32_t _nonReduceds;
};
inline NonReducedItem::NonReducedItem ( AutoSegment* segment, uint32_t nonReduceds )
: _segment (segment)
, _nonReduceds(nonReduceds)
{ }
inline AutoSegment* NonReducedItem::segment () const { return _segment; }
inline uint32_t NonReducedItem::nonReduceds () const { return _nonReduceds; }
bool operator< ( const NonReducedItem& lhs, const NonReducedItem& rhs )
{
int32_t deltaReduceds = (int32_t)lhs.nonReduceds() - (int32_t)rhs.nonReduceds();
if (deltaReduceds > 0) return true; // Most connected first.
if (deltaReduceds < 0) return false;
return lhs.segment()->getId() < rhs.segment()->getId(); // Smallest Id first.
}
} // Anonymous namespace.
@ -426,14 +453,31 @@ namespace Anabatic {
if (_state == EngineDriving) {
cdebug_log(145,1) << "Saving AutoContacts/AutoSegments." << endl;
vector<NonReducedItem> reduceds;
size_t fixedSegments = 0;
size_t sameLayerDoglegs = 0;
size_t bloatedStraps = 0;
for ( auto isegment : _autoSegmentLut ) {
if (isegment.second->isFixed()) ++fixedSegments;
if (isegment.second->reduceDoglegLayer()) ++sameLayerDoglegs;
if (isegment.second->canReduce( Flags::NullLength )) {
//cerr << "push_back() " << (void*)isegment.second << ":" << isegment.second << endl;
reduceds.push_back( NonReducedItem( isegment.second
, isegment.second->getNonReduceds( Flags::NoFlags ) ));
} else {
if (isegment.second->reduceDoglegLayer()) ++sameLayerDoglegs;
}
//if (isegment.second->bloatStackedStrap()) ++bloatedStraps;
}
sort( reduceds.begin(), reduceds.end() );
// for ( size_t i=0 ; i<reduceds.size() ; ++i ) {
// cerr << "| " << setw(3) << i
// << " " << reduceds[i].nonReduceds()
// << " " << reduceds[i].segment() << endl;
// }
for ( auto& item : reduceds ) {
item.segment()->reduce( Flags::NoFlags );
if (item.segment()->reduceDoglegLayer()) ++sameLayerDoglegs;
}
cmess1 << " o Driving Hurricane data-base." << endl;
cmess1 << Dots::asSizet(" - Active AutoSegments" ,AutoSegment::getAllocateds()-fixedSegments) << endl;

View File

@ -425,6 +425,16 @@ namespace Anabatic {
}
bool AutoSegment::CompareByReduceds::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const
{
uint32_t deltaReduceds = lhs->getReduceds() - rhs->getReduceds();
if (deltaReduceds < 0) return true; // Smallest source first.
if (deltaReduceds > 0) return false;
return lhs->getId() < rhs->getId(); // Smallest Id first.
}
// -------------------------------------------------------------------
// Class : "Anabatic::AutoSegment".
@ -1735,7 +1745,7 @@ namespace Anabatic {
}
bool AutoSegment::canReduce () const
bool AutoSegment::canReduce ( Flags flags ) const
{
cdebug_log(159,0) << "AutoSegment::canReduce():" << this << endl;
cdebug_log(159,0) << " _reduceds:" << _reduceds << endl;
@ -1743,7 +1753,8 @@ namespace Anabatic {
if (isGlobal() or isDrag() or isFixed()) return false;
if (not isSpinTopOrBottom()) return false;
if ((getDepth() == 1) and isSpinBottom()) return false;
if (_reduceds) return false;
if ((flags & Flags::WithPerpands) and _reduceds) return false;
if ((flags & Flags::NullLength) and (getAnchoredLength() > 0)) return false;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
@ -1773,10 +1784,10 @@ namespace Anabatic {
}
bool AutoSegment::reduce ()
bool AutoSegment::reduce ( Flags flags )
{
if (isReduced()) return false;
if (not canReduce()) return false;
if (not canReduce(flags)) return false;
cdebug_log(159,0) << "AutoSegment::reduce():" << this << endl;
AutoContact* source = getAutoSource();
@ -1796,6 +1807,28 @@ namespace Anabatic {
}
uint32_t AutoSegment::getNonReduceds ( Flags flags ) const
{
if (not canReduce(flags)) return false;
cdebug_log(159,0) << "AutoSegment::getNonReduceds():" << this << endl;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
uint32_t nonReduceds = 0;
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
if (perpandicular == this) continue;
if (perpandicular->getAnchoredLength()) ++nonReduceds;
}
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
if (perpandicular == this) continue;
if (perpandicular->getAnchoredLength()) ++nonReduceds;
}
return nonReduceds;
}
bool AutoSegment::mustRaise () const
{
if (not (_flags & SegIsReduced)) return false;
@ -2192,8 +2225,9 @@ namespace Anabatic {
DebugSession::open( getNet(), 149, 160 );
cdebug_log(159,1) << "AutoSegment::reduceDoglegLayer(): " << this << endl;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
bool success = false;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
unsigned int minSourceDepth = Session::getAllowedDepth();
unsigned int maxSourceDepth = 0;
@ -2204,9 +2238,11 @@ namespace Anabatic {
unsigned int anchorDepth = Session::getLayerDepth( source->base()->getAnchor()->getLayer() );
minSourceDepth = std::min( minSourceDepth, anchorDepth );
maxSourceDepth = std::max( maxSourceDepth, anchorDepth );
cdebug_log(151,0) << " source:" << source << endl;
} else {
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
if (perpandicular == this) continue;
cdebug_log(151,0) << " connected:" << perpandicular << endl;
minSourceDepth = std::min( minSourceDepth, perpandicular->getDepth() );
maxSourceDepth = std::max( maxSourceDepth, perpandicular->getDepth() );
}
@ -2215,9 +2251,11 @@ namespace Anabatic {
unsigned int anchorDepth = Session::getLayerDepth( target->base()->getAnchor()->getLayer() );
minTargetDepth = std::min( minTargetDepth, anchorDepth );
maxTargetDepth = std::max( maxTargetDepth, anchorDepth );
cdebug_log(151,0) << " target:" << target << endl;
} else {
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
if (perpandicular == this) continue;
cdebug_log(151,0) << " connected:" << perpandicular << endl;
minTargetDepth = std::min( minTargetDepth, perpandicular->getDepth() );
maxTargetDepth = std::max( maxTargetDepth, perpandicular->getDepth() );
}
@ -2230,20 +2268,26 @@ namespace Anabatic {
and (minTargetDepth == maxTargetDepth)
and (minSourceDepth == minTargetDepth) ) {
const Layer* layer = Session::getRoutingLayer(minSourceDepth);
DbU::Unit side = Session::getWireWidth (minSourceDepth);
DbU::Unit vside = Session::getWireWidth (minSourceDepth);
DbU::Unit hside = Session::getPWireWidth (minSourceDepth);
if (Session::getDirection(minSourceDepth) & Flags::Vertical)
std::swap( hside, vside );
cdebug_log(159,0) << "Reducing to " << minSourceDepth << " " << layer << endl;
source->setLayer( layer );
target->setLayer( layer );
setLayer( layer );
source->setSizes( side, side );
target->setSizes( side, side );
setWidth( hside );
source->setSizes( hside, vside );
target->setSizes( hside, vside );
success = true;
}
cdebug_tabw(159,-1);
DebugSession::close();
return true;
return success;
// if (not source->isTurn() or not target->isTurn()) return true;

View File

@ -124,6 +124,7 @@ namespace Anabatic {
const BaseFlags Flags::LayerCapOnly = (1L << 36);
const BaseFlags Flags::NoMinLength = (1L << 37);
const BaseFlags Flags::NoSegExt = (1L << 38);
const BaseFlags Flags::NullLength = (1L << 39);
Flags::~Flags ()

View File

@ -233,7 +233,7 @@ namespace Anabatic {
inline bool isWide () const;
inline bool isShortNet () const;
virtual bool _canSlacken () const = 0;
bool canReduce () const;
bool canReduce ( Flags flags=Flags::WithPerpands ) const;
bool mustRaise () const;
Flags canDogleg ( Interval );
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
@ -290,6 +290,8 @@ namespace Anabatic {
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
inline AutoSegment* getCanonical ( Interval& i );
float getMaxUnderDensity ( Flags flags );
inline uint32_t getReduceds () const;
uint32_t getNonReduceds ( Flags flags=Flags::WithPerpands ) const;
// Modifiers.
inline void unsetFlags ( uint64_t );
inline void setFlags ( uint64_t );
@ -334,7 +336,7 @@ namespace Anabatic {
bool moveDown ( Flags flags=Flags::NoFlags );
bool reduceDoglegLayer ();
bool bloatStackedStrap ();
bool reduce ();
bool reduce ( Flags flags=Flags::WithPerpands );
bool raise ();
bool expandToMinLength ( Interval );
bool unexpandToMinLength ();
@ -435,6 +437,9 @@ namespace Anabatic {
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
struct CompareByReduceds : public binary_function<AutoSegment*,AutoSegment*,bool> {
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
};
public:
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
typedef std::set<AutoSegment*,CompareId> IdSet;
@ -517,6 +522,7 @@ namespace Anabatic {
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
inline uint32_t AutoSegment::getReduceds () const { return _reduceds; }
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }

View File

@ -105,6 +105,7 @@ namespace Anabatic {
static const BaseFlags LayerCapOnly ;
static const BaseFlags NoMinLength ;
static const BaseFlags NoSegExt ;
static const BaseFlags NullLength ;
public:
inline Flags ( uint64_t flags = NoFlags );
inline Flags ( const Hurricane::BaseFlags& );