More accurate antenna management in Anabatic.

* New: In Anabatic::DiodeWire, use "antennaDiodeMaxWL" to compute the number
    of diodes to insert in a wire only cluster. Use boxes instead of segments
    to define the area as segments can be splitted by the diodes inserteds
    at the DiodeRps stage.
* New: In DiodeWire::createDiodes(), specific diode insertion method.
    Try to instert first in long horizontal wires.
This commit is contained in:
Jean-Paul Chaput 2021-05-22 15:14:32 +02:00
parent dbdef9901f
commit d4c3cf7dbb
6 changed files with 159 additions and 115 deletions

View File

@ -108,6 +108,10 @@ namespace {
typedef set<GCellInfosItem,CompareGCellInfos> GCellArea;
inline DbU::Unit getBoxLength ( const Box& bb )
{ return (bb.getWidth() > bb.getHeight()) ? bb.getWidth() : bb.getHeight(); }
// -----------------------------------------------------------------
// Class : "::DiodeCluster".
@ -122,7 +126,8 @@ namespace {
public:
DiodeCluster ( AnabaticEngine*, RoutingPad* );
virtual ~DiodeCluster ();
DbU::Unit getAntennaMaxWL () const;
DbU::Unit getAntennaGateMaxWL () const;
DbU::Unit getAntennaDiodeMaxWL () const;
inline bool hasRp ( RoutingPad* ) const;
bool hasGCell ( GCell* ) const;
inline Net* getTopNet () const;
@ -202,11 +207,19 @@ namespace {
inline vector<Instance*>& DiodeCluster::_getDiodes () { return _diodes; }
DbU::Unit DiodeCluster::getAntennaMaxWL () const
DbU::Unit DiodeCluster::getAntennaGateMaxWL () const
{
EtesianEngine* etesian = static_cast<EtesianEngine*>
( ToolEngine::get( _getAnabatic()->getCell(), EtesianEngine::staticGetName() ));
return etesian->getAntennaMaxWL();
return etesian->getAntennaGateMaxWL();
}
DbU::Unit DiodeCluster::getAntennaDiodeMaxWL () const
{
EtesianEngine* etesian = static_cast<EtesianEngine*>
( ToolEngine::get( _getAnabatic()->getCell(), EtesianEngine::staticGetName() ));
return etesian->getAntennaDiodeMaxWL();
}
@ -393,13 +406,13 @@ namespace {
{
if (not needsDiode()) return _diodes;
DbU::Unit antennaMaxWL = getAntennaMaxWL();
size_t diodeCount = getWL() / antennaMaxWL;
DbU::Unit antennaDiodeMaxWL = getAntennaDiodeMaxWL();
size_t diodeCount = getWL() / antennaDiodeMaxWL;
if (not diodeCount) diodeCount = 1;
showArea();
cdebug_log(147,1) << "DiodeCluster::createDiode() count=" << diodeCount
cdebug_log(147,1) << "DiodeCluster::createDiodes() count=" << diodeCount
<< ", forcedHalo=" << (_areas.size()-1) << endl;
Instance* diode = NULL;
for ( size_t i=0 ; i<_areas.size() ; ++i ) {
@ -514,12 +527,12 @@ namespace {
if (not segment) return;
if ( (dynamic_cast<Horizontal*>(segment))
and (getWL() + segment->getLength() > getAntennaMaxWL())) {
and (getWL() + segment->getLength() > getAntennaGateMaxWL())) {
cdebug_log(147,0) << " Put in forced halo." << segment << endl;
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( segment );
if (not gcells->empty()) {
size_t iarea = _getAreas().size();
size_t count = std::min( gcells->size(), (size_t)10 );
size_t count = std::min( gcells->size(), (size_t)50 );
for ( size_t i=0 ; i<count ; ++i ) {
size_t igcell = (flags & IsSegSource) ? i : (gcells->size()-1-i);
DiodeCluster::mergeForcedHalo( iarea, gcells->gcellAt(igcell), i );
@ -595,7 +608,7 @@ namespace {
bool DiodeWire::needsDiode () const
{ return getWL() > getAntennaMaxWL(); }
{ return getWL() >= getAntennaDiodeMaxWL(); }
void DiodeWire::merge ( Segment* segment )
@ -610,33 +623,36 @@ namespace {
const vector<Instance*>& DiodeWire::createDiodes ( Etesian::Area* area )
{
cdebug_log(147,1) << "DiodeWire::createDiode() " << endl;
DbU::Unit antennaMaxWL = getAntennaMaxWL();
cdebug_log(147,1) << "DiodeWire::createDiodes() " << endl;
DbU::Unit antennaDiodeMaxWL = getAntennaDiodeMaxWL();
size_t diodeCount = getWL() / antennaMaxWL;
size_t diodeCount = getWL() / antennaDiodeMaxWL;
if (not diodeCount) return _getDiodes();
for ( const Box& bb : _boxes ) {
bool bbH = (bb.getWidth() >= bb.getHeight());
DbU::Unit bbLength = (bbH) ? bb.getWidth() : bb.getHeight();
size_t segDiodeCount = bbLength / antennaMaxWL;
size_t segDiodeCount = bbLength / antennaDiodeMaxWL;
if (not segDiodeCount) ++segDiodeCount;
cdebug_log(147,0) << "diodes=" << segDiodeCount << " " << bb << endl;
if (bbLength < antennaMaxWL/4) continue;
bool isH = (bb.getWidth() >= bb.getHeight());
cdebug_log(147,0) << "diodes=" << segDiodeCount << " " << bb
<< " isH=" << isH
<< " length:" << DbU::getValueString(getBoxLength(bb)) << endl;
//if (bbLength < antennaDiodeMaxWL/4) continue;
if (bbH) {
DbU::Unit uHint = bb.getXMin();
DbU::Unit uMax = bb.getXMax();
while ( uHint < uMax ) {
_createDiode( area, bb, uHint );
uHint += antennaMaxWL;
uHint += antennaDiodeMaxWL;
}
if (_getDiodes().size() >= diodeCount) break;
} else {
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( Point(bb.getXCenter(),bb.getYMin())
, Point(bb.getXCenter(),bb.getYMax()) );
if (gcells->size()) {
size_t gcellPeriod = antennaMaxWL / gcells->gcellAt(0)->getHeight();
size_t gcellPeriod = antennaDiodeMaxWL / gcells->gcellAt(0)->getHeight();
for ( size_t i=0 ; i<gcells->size() ; ++i ) {
Instance* diode = _createDiode( area, gcells->gcellAt(i), NULL );
if (diode) {
@ -786,7 +802,7 @@ namespace Anabatic {
EtesianEngine* etesian = static_cast<EtesianEngine*>
( ToolEngine::get( getCell(), EtesianEngine::staticGetName() ));
DbU::Unit antennaMaxWL = etesian->getAntennaMaxWL();
DbU::Unit antennaGateMaxWL = etesian->getAntennaGateMaxWL();
vector<DiodeCluster*> clusters;
set<RoutingPad*,DBo::CompareById> rpsDone;
@ -796,7 +812,7 @@ namespace Anabatic {
if (rpsDone.find(rp) != rpsDone.end()) continue;
cdebug_log(147,0) << "New cluster [" << clusters.size() << "] from " << rp << endl;
cdebug_log(147,0) << "New Cluster [" << clusters.size() << "] from " << rp << endl;
DiodeCluster* cluster = new DiodeRps ( this, rp );
clusters.push_back( cluster );
rpsDone.insert( rp );
@ -814,7 +830,7 @@ namespace Anabatic {
cdebug_log(147,0) << "| PROCESS [" << stackTop << "] " << fromSegment << endl;
if (fromSegment) {
if (fromSegment->getLength() > antennaMaxWL/2) {
if (fromSegment->getLength() > antennaGateMaxWL/2) {
cdebug_log(147,0) << "| Long connecting wire, skipping" << endl;
++stackTop;
continue;
@ -832,7 +848,7 @@ namespace Anabatic {
cdebug_log(147,0) << "| wl=" << DbU::getValueString(cluster->getWL())
<< " + " << DbU::getValueString(branchWL) << endl;
if (cluster->getWL() + branchWL > antennaMaxWL) {
if (cluster->getWL() + branchWL > antennaGateMaxWL) {
cdebug_log(147,0) << "| Cluster above maximul WL, skipping" << endl;
++stackTop;
continue;
@ -919,7 +935,8 @@ namespace Anabatic {
for ( Segment* segment : net->getSegments() ) {
if (clusterSegments.find(segment) != clusterSegments.end()) continue;
cdebug_log(147,0) << "New wiring cluster from " << segment << endl;
cdebug_log(147,0) << "New Cluster [" << clusters.size()
<< "] wiring from " << segment << endl;
DiodeWire* cluster = new DiodeWire( this, clusters[0]->getRefRp() );
cluster->merge( segment );
clusters.push_back( cluster );
@ -940,6 +957,15 @@ namespace Anabatic {
Hook* toHook = std::get<0>( hooksStack[stackTop] );
Segment* fromSegment = std::get<1>( hooksStack[stackTop] );
bool hasRp = false;
for ( Hook* hook : toHook->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
hasRp = true;
break;
}
}
if (not hasRp) {
for ( Hook* hook : toHook->getHooks() ) {
Segment* segment = dynamic_cast<Segment*>( hook->getComponent() );
if (segment) {
@ -955,6 +981,7 @@ namespace Anabatic {
}
}
}
}
++stackTop;
}
@ -1015,7 +1042,7 @@ namespace Anabatic {
}
EtesianEngine* etesian = static_cast<EtesianEngine*>
( ToolEngine::get( getCell(), EtesianEngine::staticGetName() ));
DbU::Unit segmentMaxWL = etesian->getAntennaMaxWL() / 2;
DbU::Unit segmentMaxWL = etesian->getAntennaDiodeMaxWL() / 2;
if (not etesian->getDiodeCell()) {
cerr << Warning( "AnabaticEngine::antennaProtect(): No diode cell found, skipped." ) << endl;
@ -1033,8 +1060,9 @@ namespace Anabatic {
if (net->isClock ()) continue;
antennaProtect( net, failed, total );
}
cmess2 << Dots::asString ( " - Antenna maximum WL" , DbU::getValueString(etesian->getAntennaMaxWL()) ) << endl;
cmess2 << Dots::asString ( " - Segment maximum WL" , DbU::getValueString(segmentMaxWL) ) << endl;
cmess2 << Dots::asString ( " - Antenna gate maximum WL" , DbU::getValueString(etesian->getAntennaGateMaxWL()) ) << endl;
cmess2 << Dots::asString ( " - Antenna diode maximum WL" , DbU::getValueString(etesian->getAntennaDiodeMaxWL()) ) << endl;
cmess2 << Dots::asString ( " - Antenna segment maximum WL", DbU::getValueString(segmentMaxWL) ) << endl;
cmess2 << Dots::asInt ( " - Total needed diodes", total ) << endl;
cmess2 << Dots::asInt ( " - Failed to allocate" , failed ) << endl;
cmess2 << Dots::asPercentage( " - Success ratio" , (float)(total-failed)/(float)total ) << endl;

View File

@ -91,7 +91,8 @@ namespace Anabatic {
, _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble())
, _globalIterations (Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt())
, _diodeName (Cfg::getParamString("etesian.diodeName" , "dio_x0")->asString() )
, _antennaMaxWL (Cfg::getParamInt ("etesian.antennaMaxWL" , 0 )->asInt())
, _antennaGateMaxWL (Cfg::getParamInt ("etesian.antennaGateMaxWL" , 0 )->asInt())
, _antennaDiodeMaxWL(Cfg::getParamInt ("etesian.antennaDiodeMaxWL", 0 )->asInt())
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -159,6 +160,14 @@ namespace Anabatic {
}
}
}
if (_antennaGateMaxWL and not _antennaDiodeMaxWL) {
_antennaDiodeMaxWL = _antennaGateMaxWL;
cerr << Warning( "Anabatic::Configuration(): \"etesian.antennaGateMaxWL\" is defined but not \"etesian.antennaDiodeMaxWL\".\n"
" Setting both to %s"
, DbU::getValueString(_antennaGateMaxWL).c_str()
) << endl;
}
}
@ -183,7 +192,8 @@ namespace Anabatic {
, _edgeHScaling (other._edgeHScaling)
, _globalIterations (other._globalIterations)
, _diodeName (other._diodeName)
, _antennaMaxWL (other._antennaMaxWL)
, _antennaGateMaxWL (other._antennaGateMaxWL)
, _antennaDiodeMaxWL(other._antennaDiodeMaxWL)
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -592,7 +602,8 @@ namespace Anabatic {
record->add( getSlot( "_edgeHInc" , _edgeHInc ) );
record->add( getSlot( "_edgeHScaling" , _edgeHScaling ) );
record->add( getSlot( "_globalIterations", _globalIterations ) );
record->add( DbU::getValueSlot( "_antennaMaxWL", &_antennaMaxWL ) );
record->add( DbU::getValueSlot( "_antennaGateMaxWL" , &_antennaGateMaxWL ) );
record->add( DbU::getValueSlot( "_antennaDiodeMaxWL", &_antennaDiodeMaxWL ) );
return record;
}

View File

@ -1459,8 +1459,8 @@ namespace Anabatic {
}
DbU::Unit Dijkstra::getAntennaMaxWL () const
{ return _anabatic->getAntennaMaxWL(); }
DbU::Unit Dijkstra::getAntennaGateMaxWL () const
{ return _anabatic->getAntennaGateMaxWL(); }
Point Dijkstra::_getPonderedPoint() const
@ -2330,7 +2330,7 @@ namespace Anabatic {
}
}
if (gWL > getAntennaMaxWL()) {
if (gWL > getAntennaGateMaxWL()) {
cdebug_log(113,0) << "| \"" << _net->getName() << "\" may have antenna effect, "
<< DbU::getValueString(gWL)
<< endl;

View File

@ -248,7 +248,8 @@ namespace Anabatic {
inline bool doDestroyBaseContact () const;
inline bool doDestroyBaseSegment () const;
inline bool doDestroyTool () const;
inline DbU::Unit getAntennaMaxWL () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
inline DbU::Unit getGlobalThreshold () const;
inline float getSaturateRatio () const;
inline size_t getSaturateRp () const;
@ -376,7 +377,8 @@ namespace Anabatic {
inline bool AnabaticEngine::doWarnOnGCellOverload () const { return _flags & Flags::WarnOnGCellOverload; }
inline bool AnabaticEngine::isInDemoMode () const { return _flags & Flags::DemoMode; }
inline bool AnabaticEngine::isChip () const { return _chipTools.isChip(); }
inline DbU::Unit AnabaticEngine::getAntennaMaxWL () const { return getConfiguration()->getAntennaMaxWL(); }
inline DbU::Unit AnabaticEngine::getAntennaGateMaxWL () const { return getConfiguration()->getAntennaGateMaxWL(); }
inline DbU::Unit AnabaticEngine::getAntennaDiodeMaxWL () const { return getConfiguration()->getAntennaDiodeMaxWL(); }
inline DbU::Unit AnabaticEngine::getGlobalThreshold () const { return _configuration->getGlobalThreshold(); }
inline float AnabaticEngine::getSaturateRatio () const { return _configuration->getSaturateRatio(); }
inline size_t AnabaticEngine::getSaturateRp () const { return _configuration->getSaturateRp(); }

View File

@ -116,7 +116,8 @@ namespace Anabatic {
float getSaturateRatio () const;
size_t getSaturateRp () const;
inline std::string getDiodeName () const;
inline DbU::Unit getAntennaMaxWL () const;
inline DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getAntennaDiodeMaxWL () const;
DbU::Unit getGlobalThreshold () const;
void setAllowedDepth ( size_t );
void setSaturateRatio ( float );
@ -160,7 +161,8 @@ namespace Anabatic {
float _edgeHScaling;
int _globalIterations;
std::string _diodeName;
DbU::Unit _antennaMaxWL;
DbU::Unit _antennaGateMaxWL;
DbU::Unit _antennaDiodeMaxWL;
private:
Configuration& operator= ( const Configuration& ) = delete;
void _setTopRoutingLayer ( Name name );
@ -189,7 +191,8 @@ namespace Anabatic {
inline DbU::Unit Configuration::getDContactWidth () const { return getWireWidth ( getDContactDepth() ); }
inline DbU::Unit Configuration::getDContactPitch () const { return getPitch ( getDContactDepth(), Flags::NoFlags ); }
inline std::string Configuration::getDiodeName () const { return _diodeName; }
inline DbU::Unit Configuration::getAntennaMaxWL () const { return _antennaMaxWL; }
inline DbU::Unit Configuration::getAntennaGateMaxWL () const { return _antennaGateMaxWL; }
inline DbU::Unit Configuration::getAntennaDiodeMaxWL () const { return _antennaDiodeMaxWL; }
} // Anabatic namespace.

View File

@ -522,7 +522,7 @@ namespace Anabatic {
inline bool isSourceVertex ( Vertex* ) const;
inline Net* getNet () const;
inline bool isTargetVertex ( Vertex* ) const;
DbU::Unit getAntennaMaxWL () const;
DbU::Unit getAntennaGateMaxWL () const;
inline DbU::Unit getSearchAreaHalo () const;
template<typename DistanceT>
inline DistanceT* setDistance ( DistanceT );