Use the extention cap in Anabatic to ensure the METAL minimum area.

* New: In AutoSegment::getExtensionCap(), when a routing layer has a
    minimal area defined, compute the minimal wire length (given it's
    width). Then, for segments identified as "MiddleStack" (local
    with turns at each end towards opposite layers), if their length
    is below minimal, return a longer extention cap.
      This may be optimized because with this, the segment extension
    is symmetric on both side while it could be made assymetric.
This commit is contained in:
Jean-Paul Chaput 2021-04-01 08:46:02 +02:00
parent 5311050438
commit 0326d513bd
3 changed files with 44 additions and 8 deletions

View File

@ -418,7 +418,7 @@ namespace Anabatic {
bool AutoSegment::_analogMode = false; bool AutoSegment::_analogMode = false;
bool AutoSegment::_shortNetMode = false; bool AutoSegment::_shortNetMode = false;
bool AutoSegment::_initialized = false; bool AutoSegment::_initialized = false;
vector< array<DbU::Unit*,3> > AutoSegment::_extensionCaps; vector< array<DbU::Unit*,4> > AutoSegment::_extensionCaps;
void AutoSegment::setAnalogMode ( bool state ) { _analogMode = state; } void AutoSegment::setAnalogMode ( bool state ) { _analogMode = state; }
@ -435,6 +435,7 @@ namespace Anabatic {
DbU::Unit* viaToTopCap = new DbU::Unit ( 0 ); DbU::Unit* viaToTopCap = new DbU::Unit ( 0 );
DbU::Unit* viaToBottomCap = new DbU::Unit ( 0 ); DbU::Unit* viaToBottomCap = new DbU::Unit ( 0 );
DbU::Unit* viaToSameCap = new DbU::Unit ( 0 ); DbU::Unit* viaToSameCap = new DbU::Unit ( 0 );
DbU::Unit* minimalLength = new DbU::Unit ( 0 );
bool isVertical = (depth == 0) or (Session::getLayerGauge(depth)->isVertical()); bool isVertical = (depth == 0) or (Session::getLayerGauge(depth)->isVertical());
uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ; uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ;
@ -455,6 +456,12 @@ namespace Anabatic {
*viaToBottomCap = Session::getViaWidth(depth-1)/2 + viaLayer->getTopEnclosure( flags ); *viaToBottomCap = Session::getViaWidth(depth-1)/2 + viaLayer->getTopEnclosure( flags );
} }
const Layer* routingLayer = Session::getRoutingLayer( depth );
double minimalArea = routingLayer->getMinimalArea();
if (minimalArea != 0.0) {
*minimalLength = DbU::fromMicrons( minimalArea / DbU::toMicrons( Session::getWireWidth(depth) ) );
}
//cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl; //cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl;
//cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl; //cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl;
//if (depth > 0) //if (depth > 0)
@ -462,7 +469,10 @@ namespace Anabatic {
//cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl; //cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl;
//cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl; //cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl;
_extensionCaps.push_back( std::array<DbU::Unit*,3>( {{ viaToTopCap, viaToBottomCap, viaToSameCap }} ) ); _extensionCaps.push_back( std::array<DbU::Unit*,4>( {{ viaToTopCap
, viaToBottomCap
, viaToSameCap
, minimalLength }} ) );
} }
} }
@ -739,6 +749,12 @@ namespace Anabatic {
else cap = getViaToSameCap (depth); else cap = getViaToSameCap (depth);
} }
if (not isCreated() and (getMinimalLength(depth) != 0.0) and isMiddleStack()) {
if (getLength() < getMinimalLength(depth)) {
cap = std::max( cap, getMinimalLength(depth)/2 );
}
}
if (getLayer()->isSymbolic() and (cap < getWidth()/2)) cap = getWidth()/2; if (getLayer()->isSymbolic() and (cap < getWidth()/2)) cap = getWidth()/2;
if (not (flags & Flags::LayerCapOnly)) cap += getLayer()->getMinimalSpacing()/2; if (not (flags & Flags::LayerCapOnly)) cap += getLayer()->getMinimalSpacing()/2;
return cap; return cap;
@ -1537,6 +1553,22 @@ namespace Anabatic {
} }
bool AutoSegment::isMiddleStack () const
{
if (isGlobal()) return false;
if (isSpinTopOrBottom()) return false;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
if (not source->isTurn() or not target->isTurn()) return false;
if (source->getPerpandicular(this)->isNonPref()) return false;
if (target->getPerpandicular(this)->isNonPref()) return false;
return true;
}
bool AutoSegment::isReduceCandidate () const bool AutoSegment::isReduceCandidate () const
{ {
if (isGlobal()) return false; if (isGlobal()) return false;

View File

@ -141,6 +141,7 @@ namespace Anabatic {
inline static DbU::Unit getViaToTopCap ( size_t depth ); inline static DbU::Unit getViaToTopCap ( size_t depth );
inline static DbU::Unit getViaToBottomCap ( size_t depth ); inline static DbU::Unit getViaToBottomCap ( size_t depth );
inline static DbU::Unit getViaToSameCap ( size_t depth ); inline static DbU::Unit getViaToSameCap ( size_t depth );
inline static DbU::Unit getMinimalLength ( size_t depth );
static AutoSegment* create ( AutoContact* source static AutoSegment* create ( AutoContact* source
, AutoContact* target , AutoContact* target
, Segment* hurricaneSegment , Segment* hurricaneSegment
@ -221,6 +222,7 @@ namespace Anabatic {
inline bool isUnsetAxis () const; inline bool isUnsetAxis () const;
inline bool isSlackened () const; inline bool isSlackened () const;
inline bool isUserDefined () const; inline bool isUserDefined () const;
bool isMiddleStack () const;
bool isReduceCandidate () const; bool isReduceCandidate () const;
bool isUTurn () const; bool isUTurn () const;
inline bool isAnalog () const; inline bool isAnalog () const;
@ -373,7 +375,7 @@ namespace Anabatic {
static bool _analogMode; static bool _analogMode;
static bool _shortNetMode; static bool _shortNetMode;
static bool _initialized; static bool _initialized;
static vector< array<DbU::Unit*,3> > _extensionCaps; static vector< array<DbU::Unit*,4> > _extensionCaps;
// Internal: Attributes. // Internal: Attributes.
const unsigned long _id; const unsigned long _id;
GCell* _gcell; GCell* _gcell;
@ -467,6 +469,7 @@ namespace Anabatic {
inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; } inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; }
inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; } inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; }
inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; } inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; }
inline DbU::Unit AutoSegment::getMinimalLength ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][3]) : 0; }
inline unsigned long AutoSegment::getId () const { return _id; } inline unsigned long AutoSegment::getId () const { return _id; }
inline Cell* AutoSegment::getCell () const { return base()->getCell(); } inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
inline Net* AutoSegment::getNet () const { return base()->getNet(); } inline Net* AutoSegment::getNet () const { return base()->getNet(); }

View File

@ -776,12 +776,13 @@ namespace Etesian {
cmess1 << ::Dots::asUInt( " - Number of instances ", instancesNb ) << endl; cmess1 << ::Dots::asUInt( " - Number of instances ", instancesNb ) << endl;
if (instancesNb) { if (instancesNb) {
float ratio = ((float)registerNb / (float)instancesNb) * 100.0; float ratio = ((float)registerNb / (float)instancesNb) * 100.0;
ostringstream os; ostringstream os1;
os << registerNb << " (" << fixed << setprecision(2) << ratio << "%)"; os1 << registerNb << " (" << fixed << setprecision(2) << ratio << "%)";
cmess1 << ::Dots::asString( " - Registers (DFF) ", os.str() ) << endl; cmess1 << ::Dots::asString( " - Registers (DFF) ", os1.str() ) << endl;
ratio = ((float)_bufferCount / (float)instancesNb) * 100.0; ratio = ((float)_bufferCount / (float)instancesNb) * 100.0;
os << _bufferCount << " (" << fixed << setprecision(2) << ratio << "%)"; ostringstream os2;
cmess1 << ::Dots::asString( " - Buffers ", os.str() ) << endl; os2 << _bufferCount << " (" << fixed << setprecision(2) << ratio << "%)";
cmess1 << ::Dots::asString( " - Buffers ", os2.str() ) << endl;
} }
cout.flush(); cout.flush();