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:
parent
2f24c05a72
commit
2002282483
|
@ -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.
|
} // Anonymous namespace.
|
||||||
|
|
||||||
|
|
||||||
|
@ -426,14 +453,31 @@ namespace Anabatic {
|
||||||
if (_state == EngineDriving) {
|
if (_state == EngineDriving) {
|
||||||
cdebug_log(145,1) << "Saving AutoContacts/AutoSegments." << endl;
|
cdebug_log(145,1) << "Saving AutoContacts/AutoSegments." << endl;
|
||||||
|
|
||||||
|
vector<NonReducedItem> reduceds;
|
||||||
size_t fixedSegments = 0;
|
size_t fixedSegments = 0;
|
||||||
size_t sameLayerDoglegs = 0;
|
size_t sameLayerDoglegs = 0;
|
||||||
size_t bloatedStraps = 0;
|
size_t bloatedStraps = 0;
|
||||||
for ( auto isegment : _autoSegmentLut ) {
|
for ( auto isegment : _autoSegmentLut ) {
|
||||||
if (isegment.second->isFixed()) ++fixedSegments;
|
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;
|
//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 << " o Driving Hurricane data-base." << endl;
|
||||||
cmess1 << Dots::asSizet(" - Active AutoSegments" ,AutoSegment::getAllocateds()-fixedSegments) << endl;
|
cmess1 << Dots::asSizet(" - Active AutoSegments" ,AutoSegment::getAllocateds()-fixedSegments) << endl;
|
||||||
|
|
|
@ -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".
|
// 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) << "AutoSegment::canReduce():" << this << endl;
|
||||||
cdebug_log(159,0) << " _reduceds:" << _reduceds << endl;
|
cdebug_log(159,0) << " _reduceds:" << _reduceds << endl;
|
||||||
|
@ -1743,7 +1753,8 @@ namespace Anabatic {
|
||||||
if (isGlobal() or isDrag() or isFixed()) return false;
|
if (isGlobal() or isDrag() or isFixed()) return false;
|
||||||
if (not isSpinTopOrBottom()) return false;
|
if (not isSpinTopOrBottom()) return false;
|
||||||
if ((getDepth() == 1) and isSpinBottom()) 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* source = getAutoSource();
|
||||||
AutoContact* target = getAutoTarget();
|
AutoContact* target = getAutoTarget();
|
||||||
|
@ -1773,10 +1784,10 @@ namespace Anabatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AutoSegment::reduce ()
|
bool AutoSegment::reduce ( Flags flags )
|
||||||
{
|
{
|
||||||
if (isReduced()) return false;
|
if (isReduced()) return false;
|
||||||
if (not canReduce()) return false;
|
if (not canReduce(flags)) return false;
|
||||||
cdebug_log(159,0) << "AutoSegment::reduce():" << this << endl;
|
cdebug_log(159,0) << "AutoSegment::reduce():" << this << endl;
|
||||||
|
|
||||||
AutoContact* source = getAutoSource();
|
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
|
bool AutoSegment::mustRaise () const
|
||||||
{
|
{
|
||||||
if (not (_flags & SegIsReduced)) return false;
|
if (not (_flags & SegIsReduced)) return false;
|
||||||
|
@ -2192,8 +2225,9 @@ namespace Anabatic {
|
||||||
DebugSession::open( getNet(), 149, 160 );
|
DebugSession::open( getNet(), 149, 160 );
|
||||||
cdebug_log(159,1) << "AutoSegment::reduceDoglegLayer(): " << this << endl;
|
cdebug_log(159,1) << "AutoSegment::reduceDoglegLayer(): " << this << endl;
|
||||||
|
|
||||||
AutoContact* source = getAutoSource();
|
bool success = false;
|
||||||
AutoContact* target = getAutoTarget();
|
AutoContact* source = getAutoSource();
|
||||||
|
AutoContact* target = getAutoTarget();
|
||||||
|
|
||||||
unsigned int minSourceDepth = Session::getAllowedDepth();
|
unsigned int minSourceDepth = Session::getAllowedDepth();
|
||||||
unsigned int maxSourceDepth = 0;
|
unsigned int maxSourceDepth = 0;
|
||||||
|
@ -2204,9 +2238,11 @@ namespace Anabatic {
|
||||||
unsigned int anchorDepth = Session::getLayerDepth( source->base()->getAnchor()->getLayer() );
|
unsigned int anchorDepth = Session::getLayerDepth( source->base()->getAnchor()->getLayer() );
|
||||||
minSourceDepth = std::min( minSourceDepth, anchorDepth );
|
minSourceDepth = std::min( minSourceDepth, anchorDepth );
|
||||||
maxSourceDepth = std::max( maxSourceDepth, anchorDepth );
|
maxSourceDepth = std::max( maxSourceDepth, anchorDepth );
|
||||||
|
cdebug_log(151,0) << " source:" << source << endl;
|
||||||
} else {
|
} else {
|
||||||
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
|
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
|
||||||
if (perpandicular == this) continue;
|
if (perpandicular == this) continue;
|
||||||
|
cdebug_log(151,0) << " connected:" << perpandicular << endl;
|
||||||
minSourceDepth = std::min( minSourceDepth, perpandicular->getDepth() );
|
minSourceDepth = std::min( minSourceDepth, perpandicular->getDepth() );
|
||||||
maxSourceDepth = std::max( maxSourceDepth, perpandicular->getDepth() );
|
maxSourceDepth = std::max( maxSourceDepth, perpandicular->getDepth() );
|
||||||
}
|
}
|
||||||
|
@ -2215,9 +2251,11 @@ namespace Anabatic {
|
||||||
unsigned int anchorDepth = Session::getLayerDepth( target->base()->getAnchor()->getLayer() );
|
unsigned int anchorDepth = Session::getLayerDepth( target->base()->getAnchor()->getLayer() );
|
||||||
minTargetDepth = std::min( minTargetDepth, anchorDepth );
|
minTargetDepth = std::min( minTargetDepth, anchorDepth );
|
||||||
maxTargetDepth = std::max( maxTargetDepth, anchorDepth );
|
maxTargetDepth = std::max( maxTargetDepth, anchorDepth );
|
||||||
|
cdebug_log(151,0) << " target:" << target << endl;
|
||||||
} else {
|
} else {
|
||||||
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
|
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
|
||||||
if (perpandicular == this) continue;
|
if (perpandicular == this) continue;
|
||||||
|
cdebug_log(151,0) << " connected:" << perpandicular << endl;
|
||||||
minTargetDepth = std::min( minTargetDepth, perpandicular->getDepth() );
|
minTargetDepth = std::min( minTargetDepth, perpandicular->getDepth() );
|
||||||
maxTargetDepth = std::max( maxTargetDepth, perpandicular->getDepth() );
|
maxTargetDepth = std::max( maxTargetDepth, perpandicular->getDepth() );
|
||||||
}
|
}
|
||||||
|
@ -2230,20 +2268,26 @@ namespace Anabatic {
|
||||||
and (minTargetDepth == maxTargetDepth)
|
and (minTargetDepth == maxTargetDepth)
|
||||||
and (minSourceDepth == minTargetDepth) ) {
|
and (minSourceDepth == minTargetDepth) ) {
|
||||||
const Layer* layer = Session::getRoutingLayer(minSourceDepth);
|
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;
|
cdebug_log(159,0) << "Reducing to " << minSourceDepth << " " << layer << endl;
|
||||||
|
|
||||||
source->setLayer( layer );
|
source->setLayer( layer );
|
||||||
target->setLayer( layer );
|
target->setLayer( layer );
|
||||||
setLayer( layer );
|
setLayer( layer );
|
||||||
source->setSizes( side, side );
|
setWidth( hside );
|
||||||
target->setSizes( side, side );
|
source->setSizes( hside, vside );
|
||||||
|
target->setSizes( hside, vside );
|
||||||
|
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdebug_tabw(159,-1);
|
cdebug_tabw(159,-1);
|
||||||
DebugSession::close();
|
DebugSession::close();
|
||||||
return true;
|
return success;
|
||||||
|
|
||||||
|
|
||||||
// if (not source->isTurn() or not target->isTurn()) return true;
|
// if (not source->isTurn() or not target->isTurn()) return true;
|
||||||
|
|
|
@ -124,6 +124,7 @@ namespace Anabatic {
|
||||||
const BaseFlags Flags::LayerCapOnly = (1L << 36);
|
const BaseFlags Flags::LayerCapOnly = (1L << 36);
|
||||||
const BaseFlags Flags::NoMinLength = (1L << 37);
|
const BaseFlags Flags::NoMinLength = (1L << 37);
|
||||||
const BaseFlags Flags::NoSegExt = (1L << 38);
|
const BaseFlags Flags::NoSegExt = (1L << 38);
|
||||||
|
const BaseFlags Flags::NullLength = (1L << 39);
|
||||||
|
|
||||||
|
|
||||||
Flags::~Flags ()
|
Flags::~Flags ()
|
||||||
|
|
|
@ -233,7 +233,7 @@ namespace Anabatic {
|
||||||
inline bool isWide () const;
|
inline bool isWide () const;
|
||||||
inline bool isShortNet () const;
|
inline bool isShortNet () const;
|
||||||
virtual bool _canSlacken () const = 0;
|
virtual bool _canSlacken () const = 0;
|
||||||
bool canReduce () const;
|
bool canReduce ( Flags flags=Flags::WithPerpands ) const;
|
||||||
bool mustRaise () const;
|
bool mustRaise () const;
|
||||||
Flags canDogleg ( Interval );
|
Flags canDogleg ( Interval );
|
||||||
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
|
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
|
||||||
|
@ -290,6 +290,8 @@ namespace Anabatic {
|
||||||
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
|
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
|
||||||
inline AutoSegment* getCanonical ( Interval& i );
|
inline AutoSegment* getCanonical ( Interval& i );
|
||||||
float getMaxUnderDensity ( Flags flags );
|
float getMaxUnderDensity ( Flags flags );
|
||||||
|
inline uint32_t getReduceds () const;
|
||||||
|
uint32_t getNonReduceds ( Flags flags=Flags::WithPerpands ) const;
|
||||||
// Modifiers.
|
// Modifiers.
|
||||||
inline void unsetFlags ( uint64_t );
|
inline void unsetFlags ( uint64_t );
|
||||||
inline void setFlags ( uint64_t );
|
inline void setFlags ( uint64_t );
|
||||||
|
@ -334,7 +336,7 @@ namespace Anabatic {
|
||||||
bool moveDown ( Flags flags=Flags::NoFlags );
|
bool moveDown ( Flags flags=Flags::NoFlags );
|
||||||
bool reduceDoglegLayer ();
|
bool reduceDoglegLayer ();
|
||||||
bool bloatStackedStrap ();
|
bool bloatStackedStrap ();
|
||||||
bool reduce ();
|
bool reduce ( Flags flags=Flags::WithPerpands );
|
||||||
bool raise ();
|
bool raise ();
|
||||||
bool expandToMinLength ( Interval );
|
bool expandToMinLength ( Interval );
|
||||||
bool unexpandToMinLength ();
|
bool unexpandToMinLength ();
|
||||||
|
@ -435,6 +437,9 @@ namespace Anabatic {
|
||||||
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||||
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||||
};
|
};
|
||||||
|
struct CompareByReduceds : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||||
|
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
|
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
|
||||||
typedef std::set<AutoSegment*,CompareId> IdSet;
|
typedef std::set<AutoSegment*,CompareId> IdSet;
|
||||||
|
@ -517,6 +522,7 @@ namespace Anabatic {
|
||||||
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
|
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
|
||||||
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
|
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
|
||||||
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
|
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::isHorizontal () const { return _flags & SegHorizontal; }
|
||||||
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
|
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
|
||||||
|
|
|
@ -105,6 +105,7 @@ namespace Anabatic {
|
||||||
static const BaseFlags LayerCapOnly ;
|
static const BaseFlags LayerCapOnly ;
|
||||||
static const BaseFlags NoMinLength ;
|
static const BaseFlags NoMinLength ;
|
||||||
static const BaseFlags NoSegExt ;
|
static const BaseFlags NoSegExt ;
|
||||||
|
static const BaseFlags NullLength ;
|
||||||
public:
|
public:
|
||||||
inline Flags ( uint64_t flags = NoFlags );
|
inline Flags ( uint64_t flags = NoFlags );
|
||||||
inline Flags ( const Hurricane::BaseFlags& );
|
inline Flags ( const Hurricane::BaseFlags& );
|
||||||
|
|
Loading…
Reference in New Issue