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::_shortNetMode = 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; }
@ -435,6 +435,7 @@ namespace Anabatic {
DbU::Unit* viaToTopCap = new DbU::Unit ( 0 );
DbU::Unit* viaToBottomCap = 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());
uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ;
@ -455,6 +456,12 @@ namespace Anabatic {
*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 << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl;
//if (depth > 0)
@ -462,7 +469,10 @@ namespace Anabatic {
//cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << 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);
}
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 (not (flags & Flags::LayerCapOnly)) cap += getLayer()->getMinimalSpacing()/2;
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
{
if (isGlobal()) return false;

View File

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

View File

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