From 8ce16add53440f617a8ffa84aeb8504a3c28949f Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 13 May 2021 12:20:28 +0200 Subject: [PATCH] Add a "forced halo" to diode clusters. When a long *horizontal* wire connect to a cluster, an antenna effect may be created *before* the METAL3 is deposited, if the cluster's diode is not *directly* connected to the gate through *only* METAL2. So, we add a "forced halo" where the long horizontal connecting wires will be broken by a diode *near* the gate. This problem do not occur for long connecting METAL3, as the diode will be connected by then. Note that we are hard-coding the gauge routing direction in the algorithm. With that modification, only one antenna effect remains in LibreSOC LS180. May be corrected by post-treatement. * New: In Anabatic::DiodeCluster::mergeForcedhalo() add specific secondary areas where diode must be insterted in addition to the one of the RroutingPad cluster. To "isolate" the cluster from long horizontal wires. --- anabatic/src/AntennaProtect.cpp | 124 ++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 46 deletions(-) diff --git a/anabatic/src/AntennaProtect.cpp b/anabatic/src/AntennaProtect.cpp index 4e2c5983..92a6d3ea 100644 --- a/anabatic/src/AntennaProtect.cpp +++ b/anabatic/src/AntennaProtect.cpp @@ -127,7 +127,7 @@ namespace { bool hasGCell ( GCell* ) const; inline Net* getTopNet () const; inline RoutingPad* getRefRp () const; - inline GCellArea& _getArea (); + inline vector& _getAreas (); inline AnabaticEngine* _getAnabatic () const; inline const RoutingPadInfos& getRoutingPads () const; inline RoutingPadInfos& _getRoutingPads () ; @@ -141,18 +141,19 @@ namespace { void merge ( GCell*, uint32_t distance, GCell* back=NULL ); virtual void merge ( RoutingPad* ); virtual void merge ( Segment* ) = 0; + void mergeForcedHalo ( size_t iarea, GCell*, uint32_t distance ); virtual void mergeHalo ( Segment*, uint32_t flags ); virtual void inflateArea (); Instance* _createDiode ( Etesian::Area*, const Box&, DbU::Unit uHint ); Instance* _createDiode ( Etesian::Area*, GCell*, GCell* ); - virtual const vector& createDiode ( Etesian::Area* ); + virtual const vector& createDiodes ( Etesian::Area* ); bool connectDiodes (); private: - AnabaticEngine* _anabatic; - DbU::Unit _WL; - RoutingPadInfos _routingPads; - GCellArea _area; - vector _diodes; + AnabaticEngine* _anabatic; + DbU::Unit _WL; + RoutingPadInfos _routingPads; + vector _areas; + vector _diodes; }; @@ -179,7 +180,7 @@ namespace { : _anabatic(anabatic) , _WL(0) , _routingPads() - , _area() + , _areas(1) , _diodes() { merge( rp ); @@ -190,15 +191,15 @@ namespace { { } - inline AnabaticEngine* DiodeCluster::_getAnabatic () const { return _anabatic; } - inline GCellArea& DiodeCluster::_getArea () { return _area; } - inline Net* DiodeCluster::getTopNet () const { return getRefRp()->getNet(); } - inline DbU::Unit DiodeCluster::getWL () const { return _WL; } - inline DbU::Unit& DiodeCluster::_getWL () { return _WL; } - inline const RoutingPadInfos& DiodeCluster::getRoutingPads () const { return _routingPads; } - inline RoutingPadInfos& DiodeCluster::_getRoutingPads () { return _routingPads; } - inline const vector& DiodeCluster::getDiodes () const { return _diodes; } - inline vector& DiodeCluster::_getDiodes () { return _diodes; } + inline AnabaticEngine* DiodeCluster::_getAnabatic () const { return _anabatic; } + inline vector& DiodeCluster::_getAreas () { return _areas; } + inline Net* DiodeCluster::getTopNet () const { return getRefRp()->getNet(); } + inline DbU::Unit DiodeCluster::getWL () const { return _WL; } + inline DbU::Unit& DiodeCluster::_getWL () { return _WL; } + inline const RoutingPadInfos& DiodeCluster::getRoutingPads () const { return _routingPads; } + inline RoutingPadInfos& DiodeCluster::_getRoutingPads () { return _routingPads; } + inline const vector& DiodeCluster::getDiodes () const { return _diodes; } + inline vector& DiodeCluster::_getDiodes () { return _diodes; } DbU::Unit DiodeCluster::getAntennaMaxWL () const @@ -216,7 +217,7 @@ namespace { inline bool DiodeCluster::hasGCell ( GCell* gcell ) const { if (not gcell) return false; - for ( auto& item : _area ) { + for ( auto& item : _areas[0] ) { if (elemGCell(item) == gcell) return true; } return false; @@ -232,11 +233,14 @@ namespace { void DiodeCluster::showArea () const { - cdebug_log(147,1) << "GCell diode area" << endl; - for ( auto& item : _area ) { - cdebug_log(147,0) << "| d=" << std::get<1>(item) - << " " << std::get<0>(item) - << " back=" << std::get<2>(item) << endl; + cdebug_log(147,1) << "GCell diode areas:" << endl; + for ( size_t i=0 ; i<_areas.size() ; ++i ) { + cdebug_log(147,0) << "GCell diode area [" << i << "]" << endl; + for ( auto& item : _areas[i] ) { + cdebug_log(147,0) << " | d=" << std::get<1>(item) + << " " << std::get<0>(item) + << " back=" << std::get<2>(item) << endl; + } } cdebug_tabw(147,-1); } @@ -269,14 +273,22 @@ namespace { if (not gcell) return; if (hasGCell(gcell)) return; if (back) distance += 20; - _area.insert( make_tuple(gcell,distance,back) ); + _areas[0].insert( make_tuple(gcell,distance,back) ); + } + + + void DiodeCluster::mergeForcedHalo ( size_t iarea, GCell* gcell, uint32_t distance ) + { + if (not gcell) return; + while ( iarea >= _areas.size() ) _areas.push_back( GCellArea() ); + _areas[iarea].insert( make_tuple(gcell,distance,(GCell*)NULL) ); } Box DiodeCluster::getBoundingBox () const { Box bb; - for ( auto& item : _area ) bb.merge( elemGCell(item)->getBoundingBox() ); + for ( auto& item : _areas[0] ) bb.merge( elemGCell(item)->getBoundingBox() ); return bb; } @@ -377,7 +389,7 @@ namespace { } - const vector& DiodeCluster::createDiode ( Etesian::Area* area ) + const vector& DiodeCluster::createDiodes ( Etesian::Area* area ) { if (not needsDiode()) return _diodes; @@ -387,19 +399,24 @@ namespace { showArea(); - cdebug_log(147,1) << "DiodeCluster::createDiode() count=" << diodeCount << endl; + cdebug_log(147,1) << "DiodeCluster::createDiode() count=" << diodeCount + << ", forcedHalo=" << (_areas.size()-1) << endl; Instance* diode = NULL; - for ( auto& item : _area ) { - GCell* gcell = std::get<0>( item ); - GCell* backGCell = std::get<2>( item ); - cdebug_log(147,0) << "| d=" << std::get<1>(item) << " " << gcell << endl; - diode = _createDiode( area, gcell, backGCell ); - if (diode) { - if (_diodes.size() < diodeCount) { - diode = NULL; - continue; + for ( size_t i=0 ; i<_areas.size() ; ++i ) { + if (i) diodeCount = 1; + cdebug_log(147,0) << "Diode for area [" << i << "]" << endl; + for ( auto& item : _areas[i] ) { + GCell* gcell = std::get<0>( item ); + GCell* backGCell = std::get<2>( item ); + cdebug_log(147,0) << "| d=" << std::get<1>(item) << " " << gcell << endl; + diode = _createDiode( area, gcell, backGCell ); + if (diode) { + if (_diodes.size() < diodeCount) { + diode = NULL; + continue; + } + break; } - break; } } cdebug_tabw(147,-1); @@ -496,6 +513,21 @@ namespace { cdebug_log(147,0) << "DiodeRps::mergeHalo(): " << segment << endl; if (not segment) return; + if ( (dynamic_cast(segment)) + and (getWL() + segment->getLength() > getAntennaMaxWL())) { + 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 ); + for ( size_t i=0 ; isize()-1-i); + DiodeCluster::mergeForcedHalo( iarea, gcells->gcellAt(igcell), i ); + } + } + return; + } + GCellsUnder gcells = _getAnabatic()->getGCellsUnder( segment ); if (not gcells->empty()) { size_t count = std::min( gcells->size(), (size_t)10 ); @@ -510,7 +542,7 @@ namespace { void DiodeRps::inflateArea () { vector< tuple > border; - for ( auto& item : _getArea() ) { + for ( auto& item : _getAreas()[0] ) { GCell* current = std::get<0>( item ); if (std::get<2>(item)) continue; @@ -522,7 +554,7 @@ namespace { border.push_back( make_tuple(neighbor,current) ); } - for ( auto& item : _getArea() ) { + for ( auto& item : _getAreas()[0] ) { GCell* current = std::get<0>( item ); if (std::get<2>(item)) continue; @@ -545,10 +577,10 @@ namespace { class DiodeWire : public DiodeCluster { public: - DiodeWire ( AnabaticEngine*, RoutingPad* ); - virtual bool needsDiode () const; - virtual void merge ( Segment* ); - virtual const vector& createDiode ( Etesian::Area* ); + DiodeWire ( AnabaticEngine*, RoutingPad* ); + virtual bool needsDiode () const; + virtual void merge ( Segment* ); + virtual const vector& createDiodes ( Etesian::Area* ); private: set _boxes; set _contacts; @@ -576,7 +608,7 @@ namespace { } - const vector& DiodeWire::createDiode ( Etesian::Area* area ) + const vector& DiodeWire::createDiodes ( Etesian::Area* area ) { cdebug_log(147,1) << "DiodeWire::createDiode() " << endl; DbU::Unit antennaMaxWL = getAntennaMaxWL(); @@ -764,7 +796,7 @@ namespace Anabatic { if (rpsDone.find(rp) != rpsDone.end()) continue; - cdebug_log(147,0) << "New cluster 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 ); @@ -943,7 +975,7 @@ namespace Anabatic { continue; } - const vector& diodes = clusters[i]->createDiode( etesian->getArea() ); + const vector& diodes = clusters[i]->createDiodes( etesian->getArea() ); if (not diodes.empty()) { clusters[i]->connectDiodes(); } else {