From 8f25b97271c5e4fd333856e51d0686bd5719a140 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Tue, 6 Mar 2018 01:48:44 +0100 Subject: [PATCH] Improve Edge ripup method. Improve two-metal terminal management. * New: In Anabatic::Edge::ripup(), sort edges to ripup by decreasing length so the longest gets riped up first. In two metals mode, ripup all segments *except* those who have terminal contact in the GCell, because they must use it anyway. * Bug: In Anabatic::GCell::getEdgeAt(), the size hint flag was not correctly selected, leading to the use of an edge in the wrong side. So deleted segments where not deleted from their edges, leading to core dump. Don't understand how it can have not shown until now. * New: In KatanaEngine::annotateGlobalGraph(), for two metal gauges, decrease the edge capacity on both north and south side for each terminal in the GCell. As a terminal must be accessed through north or south it blocks the whole vertical track (hence both edges). --- anabatic/src/AnabaticEngine.cpp | 11 +++++- anabatic/src/Edge.cpp | 70 ++++++++++++++++++++++++++++++--- anabatic/src/GCell.cpp | 12 +++++- anabatic/src/Matrix.cpp | 6 ++- anabatic/src/anabatic/Edge.h | 2 + katana/src/Block.cpp | 5 +-- katana/src/KatanaEngine.cpp | 28 +++++++++++++ 7 files changed, 119 insertions(+), 15 deletions(-) diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp index 909a4edc..672b739e 100644 --- a/anabatic/src/AnabaticEngine.cpp +++ b/anabatic/src/AnabaticEngine.cpp @@ -239,14 +239,18 @@ namespace Anabatic { std::swap( gsource, gtarget ); } + cdebug_log(112,0) << "flags:" << side << " axis:" << DbU::getValueString(axis) << endl; + Edge* edge = gsource->getEdgeAt( side, axis ); while ( edge ) { _elements.push_back( Element(edge->getSource(),edge) ); + cdebug_log(112,0) << "| push:" << edge->getSource() << " from " << edge << endl; if (edge->getTarget() == gtarget) break; edge = edge->getTarget()->getEdgeAt( side, axis ); } _elements.push_back( Element(gtarget,NULL) ); + cdebug_log(112,0) << "| push:" << gtarget << " last/target" << endl; cdebug_tabw(112,-1); } @@ -755,8 +759,13 @@ namespace Anabatic { GCellsUnder gcells = getGCellsUnder( segment ); if (not gcells->empty()) { - for ( size_t i=0 ; isize()-1 ; ++i ) + for ( size_t i=0 ; isize()-1 ; ++i ) { + cdebug_log(112,0) << "| " << gcells->gcellAt(i) << endl; + cdebug_log(112,0) << "| " << gcells->edgeAt(i) << endl; gcells->edgeAt(i)->remove( segment ); + } + } else { + cdebug_log(112,0) << "No GCells under segment." << endl; } Contact* source = dynamic_cast( segment->getSource() ); diff --git a/anabatic/src/Edge.cpp b/anabatic/src/Edge.cpp index ddf42500..57f2b48a 100644 --- a/anabatic/src/Edge.cpp +++ b/anabatic/src/Edge.cpp @@ -24,6 +24,30 @@ #include "anabatic/AnabaticEngine.h" +namespace { + + using namespace std; + using namespace Hurricane; + + + class SortSegmentByLength { + public: + inline bool operator() ( const Segment*, const Segment* ); + }; + + + inline bool SortSegmentByLength::operator() ( const Segment* lhs, const Segment* rhs ) + { + DbU::Unit delta = rhs->getLength() - lhs->getLength(); + if (delta > 0) return true; + if (delta < 0) return false; + return (lhs->getId() < rhs->getId()); + } + + +} // Anonymous namespace. + + namespace Anabatic { using std::cerr; @@ -210,8 +234,23 @@ namespace Anabatic { DbU::Unit pitch = 0; if (h) pitch = Session::getGHorizontalPitch(); if (v) pitch = Session::getGVerticalPitch(); + + int deltaOccupancy = 0; - incRealOccupancy( segment->getWidth()/pitch ); // Need to take the wire width into account. + if (not Session::getRoutingGauge()->isTwoMetals()) deltaOccupancy = segment->getWidth()/pitch; + else { + // In channel routing, do not increase edge occupancy on terminals, + // because the capacity has already been decreased in annotedGlobalGraph (Katana). + AutoContact* autoContact = Session::lookup( dynamic_cast(segment->getSource()) ); + if (not autoContact or (autoContact->getGCell() != _source)) { + autoContact = Session::lookup( dynamic_cast(segment->getTarget()) ); + if (not autoContact or (autoContact->getGCell() != _target)) { + deltaOccupancy = segment->getWidth()/pitch; + } + } + } + + incRealOccupancy( deltaOccupancy ); } @@ -219,6 +258,9 @@ namespace Anabatic { { for ( size_t i=0 ; i<_segments.size() ; ++i ) { if (_segments[i] == segment) { + cdebug_log(110,0) << "On " << this << endl; + cdebug_log(110,0) << "| remove:" << segment << endl; + std::swap( _segments[i], _segments[_segments.size()-1] ); _segments.pop_back(); incRealOccupancy( -1 ); // Need to take the wire width into account. @@ -245,13 +287,29 @@ namespace Anabatic { DbU::Unit globalThreshold = Session::getSliceHeight()*3; size_t netCount = 0; + sort( _segments.begin(), _segments.end(), SortSegmentByLength() ); + for ( size_t i=0 ; i<_segments.size() ; ) { - if (_segments[i]->getLength() >= globalThreshold) { - NetData* netData = anabatic->getNetData( _segments[i]->getNet() ); - if (netData->isGlobalRouted()) ++netCount; - anabatic->ripup( _segments[i], Flags::Propagate ); - } else { + if (Session::getRoutingGauge()->isTwoMetals()) { + AutoContact* autoContact = Session::lookup( dynamic_cast(_segments[i]->getSource()) ); + if (not autoContact or (autoContact->getGCell() != _source)) { + autoContact = Session::lookup( dynamic_cast(_segments[i]->getTarget()) ); + if (not autoContact or (autoContact->getGCell() != _target)) { + NetData* netData = anabatic->getNetData( _segments[i]->getNet() ); + if (netData->isGlobalRouted()) ++netCount; + anabatic->ripup( _segments[i], Flags::Propagate ); + continue; + } + } ++i; + } else { + if (_segments[i]->getLength() >= globalThreshold) { + NetData* netData = anabatic->getNetData( _segments[i]->getNet() ); + if (netData->isGlobalRouted()) ++netCount; + anabatic->ripup( _segments[i], Flags::Propagate ); + } else { + ++i; + } } } return netCount; diff --git a/anabatic/src/GCell.cpp b/anabatic/src/GCell.cpp index 231863ea..bdb7b57e 100644 --- a/anabatic/src/GCell.cpp +++ b/anabatic/src/GCell.cpp @@ -506,8 +506,16 @@ namespace Anabatic { { for ( Edge* edge : getEdges(sideHint) ) { GCell* side = edge->getOpposite(this); - if ( (sideHint & (Flags::WestSide |Flags::EastSide )) and (u < side->getYMax()) ) return edge; - if ( (sideHint & (Flags::SouthSide|Flags::NorthSide)) and (u < side->getXMax()) ) return edge; + if ( (sideHint.contains(Flags::WestSide) or sideHint.contains(Flags::EastSide )) + and (u < side->getYMax()) ) { + cdebug_log(112,0) << "H Opposite @" << DbU::getValueString(u) << " is: " << side << endl; + return edge; + } + if ( (sideHint.contains(Flags::SouthSide) or sideHint.contains(Flags::NorthSide)) + and (u < side->getXMax()) ) { + cdebug_log(112,0) << "V Opposite @" << DbU::getValueString(u) << " is: " << side << endl; + return edge; + } } return NULL; } diff --git a/anabatic/src/Matrix.cpp b/anabatic/src/Matrix.cpp index 9f041401..43eda943 100644 --- a/anabatic/src/Matrix.cpp +++ b/anabatic/src/Matrix.cpp @@ -78,8 +78,10 @@ namespace Anabatic { int index = xy2maxIndex(x,y); cdebug_log(110,0) << "Matrix::getUnder() (" - << DbU::getValueString(x) << " " - << DbU::getValueString(y) << ") index:" << index << endl; + << DbU::getValueString(x) << " " + << DbU::getValueString(y) << ") index:" << index + << " " << ((index < 0) ? NULL : _gcells[index]->getUnder(x,y)) << endl; + return (index < 0) ? NULL : _gcells[index]->getUnder(x,y); } diff --git a/anabatic/src/anabatic/Edge.h b/anabatic/src/anabatic/Edge.h index febb46a7..86ec4284 100644 --- a/anabatic/src/anabatic/Edge.h +++ b/anabatic/src/anabatic/Edge.h @@ -60,6 +60,7 @@ namespace Anabatic { inline bool isHorizontal () const; inline bool hasNet ( const Net* ) const; inline unsigned int getCapacity () const; + inline unsigned int getReservedCapacity () const; inline unsigned int getCapacity ( size_t depth ) const; inline unsigned int getRealOccupancy () const; inline unsigned int getEstimateOccupancy () const; @@ -135,6 +136,7 @@ namespace Anabatic { inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); } inline unsigned int Edge::getCapacity () const { return (_capacities) ? _capacities->getCapacity()-_reservedCapacity : 0; } inline unsigned int Edge::getCapacity ( size_t depth ) const { return (_capacities) ? _capacities->getCapacity(depth) : 0; } + inline unsigned int Edge::getReservedCapacity () const { return _reservedCapacity; } inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; } inline unsigned int Edge::getEstimateOccupancy () const { return _estimateOccupancy; } inline float Edge::getHistoricCost () const { return _historicCost; } diff --git a/katana/src/Block.cpp b/katana/src/Block.cpp index a54820aa..5f89a91d 100644 --- a/katana/src/Block.cpp +++ b/katana/src/Block.cpp @@ -170,7 +170,6 @@ namespace Katana { if (inet == nets.end()) { nets.insert( irp.second->getNet() ); } else { - if (southWest->getId() == 2998) DebugSession::close(); southWest = southWest->vcut( irp.second->getX() ); southWest->setType( Anabatic::Flags::StdCellRow ); gcellSplitted = true; @@ -181,7 +180,6 @@ namespace Katana { rps .clear(); nets.clear(); if (not gcellSplitted) { - if (southWest->getId() == 2998) DebugSession::close(); southWest = southWest->getEast(); } } @@ -305,8 +303,7 @@ namespace Katana { Session::close(); _katana->openSession(); - for ( Row* row : _rows ) - row->routingPadsSubBreak(); + for ( Row* row : _rows ) row->routingPadsSubBreak(); if (not sessionReUse) Session::close(); } diff --git a/katana/src/KatanaEngine.cpp b/katana/src/KatanaEngine.cpp index b89ca0d0..cfe6e961 100644 --- a/katana/src/KatanaEngine.cpp +++ b/katana/src/KatanaEngine.cpp @@ -34,6 +34,7 @@ #include "hurricane/Instance.h" #include "hurricane/Vertical.h" #include "hurricane/Horizontal.h" +#include "hurricane/RoutingPad.h" #include "hurricane/viewer/Script.h" #include "crlcore/Measures.h" #include "anabatic/AutoContact.h" @@ -141,6 +142,7 @@ namespace Katana { using Hurricane::Layer; using Hurricane::Horizontal; using Hurricane::Vertical; + using Hurricane::RoutingPad; using Hurricane::NetRoutingState; using Hurricane::NetRoutingExtension; using Hurricane::Cell; @@ -464,6 +466,32 @@ namespace Katana { } } } + + if (Session::getConfiguration()->isTwoMetals()) { + for ( GCell* gcell : getGCells() ) { + if (not gcell->isStdCellRow()) continue; + + set terminalsX; + for ( Component* component : getCell()->getComponentsUnder(gcell->getBoundingBox()) ) { + RoutingPad* rp = dynamic_cast( component ); + if (rp) terminalsX.insert( rp->getX() ); + } + + unsigned int capacity = 0; + if (gcell->getNorthEdge()) { + capacity = gcell->getNorthEdge()->getCapacity(); + if (terminalsX.size() < capacity) capacity = terminalsX.size(); + else --capacity; + gcell->getNorthEdge()->reserveCapacity( capacity ); + } + if (gcell->getSouthEdge()) { + capacity = gcell->getSouthEdge()->getCapacity(); + if (terminalsX.size() < capacity) capacity = terminalsX.size(); + else --capacity; + gcell->getSouthEdge()->reserveCapacity( capacity ); + } + } + } }