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).
This commit is contained in:
parent
db8675e501
commit
8f25b97271
|
@ -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 ; i<gcells->size()-1 ; ++i )
|
||||
for ( size_t i=0 ; i<gcells->size()-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<Contact*>( segment->getSource() );
|
||||
|
|
|
@ -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<Contact*>(segment->getSource()) );
|
||||
if (not autoContact or (autoContact->getGCell() != _source)) {
|
||||
autoContact = Session::lookup( dynamic_cast<Contact*>(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<Contact*>(_segments[i]->getSource()) );
|
||||
if (not autoContact or (autoContact->getGCell() != _source)) {
|
||||
autoContact = Session::lookup( dynamic_cast<Contact*>(_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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<DbU::Unit> terminalsX;
|
||||
for ( Component* component : getCell()->getComponentsUnder(gcell->getBoundingBox()) ) {
|
||||
RoutingPad* rp = dynamic_cast<RoutingPad*>( 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue