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.
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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& );
|
||||
|
|
Loading…
Reference in New Issue