From abf58190ebe680b407c40cf1f76f089e3608218e Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 26 Jun 2016 14:32:32 +0200 Subject: [PATCH] Anabatic transient commit 10. Ripup & reroute support in Dijsktra. * New: In Anabatic: - In AnabaticEngine, keep track of overflowed edges. - In AnabaticEngine, getNetsFromedge() to lookup all nets going through an Edge. - In Configuration, read the Kite "reserved local" parameter to decrease the Edge capacity (it's a guessing of the cost of the local routing). - In Edge, add an attribute to know if there is an associated segment of the current net (set by Dijkstra::_traceback()). Transparently manage the overflowed edges. - In GCell_Edges, correct a filtering bug when not all sides are selecteds. - New GCell::getEdgeTo() to find the edge between two adjacent GCells. - New GCell::unrefContact() to automatically removes global contacts no longer used by any global segments (used during the ripup step). - In Dijkstra::load(), now able to "reload" and already partially or completly routed net (look for Contact of "gcontact" layer and their attached segments). - In Dijkstra, keep the last net loaded until the next one is. Put the cleanup operations in an isolated function "_cleanup()". - In Dijkstra::_selectFirstsource() and run(), load first source component made of multiple vertexes. - In Dijkstra::_trackback(), link the Net segments to the Edges. - New Dijkstra::ripup(), Dijkstra::_propagateRipup() to perform the ripup of one edge of a Net (must be loaded in Dijkstra first). Dijkstra::_tagConnecteds() setup the connexId of a set of Vertexes - that are connecteds through edges *with* segments. - In GraphicAnabaticengine & GlobalRoute.cpp, embryo of a global routing tool with ripup & reroute. --- anabatic/src/AnabaticEngine.cpp | 40 +++ anabatic/src/CMakeLists.txt | 1 + anabatic/src/Configuration.cpp | 10 + anabatic/src/Dijkstra.cpp | 332 +++++++++++++++--- anabatic/src/Edge.cpp | 26 ++ anabatic/src/Edges.cpp | 37 +- anabatic/src/GCell.cpp | 52 ++- anabatic/src/GlobalRoute.cpp | 195 ++++++++++ anabatic/src/GraphicAnabaticEngine.cpp | 46 ++- anabatic/src/anabatic/AnabaticEngine.h | 21 ++ anabatic/src/anabatic/Configuration.h | 6 + anabatic/src/anabatic/Dijkstra.h | 17 +- anabatic/src/anabatic/Edge.h | 38 +- anabatic/src/anabatic/GCell.h | 183 +++++----- anabatic/src/anabatic/GraphicAnabaticEngine.h | 1 + 15 files changed, 837 insertions(+), 168 deletions(-) create mode 100644 anabatic/src/GlobalRoute.cpp diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp index 400614bb..b36f1238 100644 --- a/anabatic/src/AnabaticEngine.cpp +++ b/anabatic/src/AnabaticEngine.cpp @@ -18,6 +18,8 @@ #include #include "hurricane/Error.h" #include "hurricane/RegularLayer.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" #include "hurricane/Cell.h" #include "hurricane/UpdateSession.h" #include "crlcore/RoutingGauge.h" @@ -33,6 +35,9 @@ namespace Anabatic { using std::ostringstream; using Hurricane::Error; using Hurricane::RegularLayer; + using Hurricane::Component; + using Hurricane::Horizontal; + using Hurricane::Vertical; using Hurricane::Cell; using Hurricane::UpdateSession; using CRL::RoutingGauge; @@ -63,6 +68,7 @@ namespace Anabatic { , _configuration (new ConfigurationConcrete()) , _matrix () , _gcells () + , _ovEdges () , _viewer (NULL) , _flags (Flags::NoFlags) , _stamp (-1) @@ -114,6 +120,7 @@ namespace Anabatic { for ( GCell* gcell : _gcells ) gcell->_destroyEdges(); for ( GCell* gcell : _gcells ) gcell->destroy(); _gcells.clear(); + _ovEdges.clear(); } @@ -164,6 +171,39 @@ namespace Anabatic { } + size_t AnabaticEngine::getNetsFromEdge ( const Edge* edge, NetSet& nets ) + { + size_t count = 0; + GCell* source = edge->getSource(); + GCell* target = edge->getTarget(); + const vector& contacts = source->getGContacts(); + + for ( Contact* contact : contacts ) { + for ( Component* component : contact->getSlaveComponents() ) { + if (edge->isHorizontal()) { + Horizontal* horizontal = dynamic_cast( component ); + if (horizontal + and (horizontal->getSource() == contact) + and (target->hasGContact(dynamic_cast(horizontal->getTarget())))) { + nets.insert( horizontal->getNet() ); + ++count; + } + } + if (edge->isVertical()) { + Vertical* vertical = dynamic_cast( component ); + if (vertical + and (vertical->getSource() == contact) + and (target->hasGContact(dynamic_cast(vertical->getTarget())))) { + nets.insert( vertical->getNet() ); + ++count; + } + } + } + } + return count; + } + + void AnabaticEngine::startMeasures () { _timer.resetIncrease(); diff --git a/anabatic/src/CMakeLists.txt b/anabatic/src/CMakeLists.txt index e666a39a..e7c0a20f 100644 --- a/anabatic/src/CMakeLists.txt +++ b/anabatic/src/CMakeLists.txt @@ -32,6 +32,7 @@ endif ( CHECK_DETERMINISM ) Edges.cpp GCell.cpp AnabaticEngine.cpp + GlobalRoute.cpp GraphicAnabaticEngine.cpp Dijkstra.cpp ) diff --git a/anabatic/src/Configuration.cpp b/anabatic/src/Configuration.cpp index f2fef557..cc2d61dc 100644 --- a/anabatic/src/Configuration.cpp +++ b/anabatic/src/Configuration.cpp @@ -75,6 +75,8 @@ namespace Anabatic { , _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt())) , _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH", 9.0)->asDouble()) , _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK",-10.0)->asDouble()) + , _hEdgeLocal (Cfg::getParamInt("kite.hTracksReservedLocal",0)->asInt()) + , _vEdgeLocal (Cfg::getParamInt("kite.vTracksReservedLocal",0)->asInt()) { if (cg == NULL) cg = AllianceFramework::get()->getCellGauge(); if (rg == NULL) rg = AllianceFramework::get()->getRoutingGauge(); @@ -288,6 +290,14 @@ namespace Anabatic { { return _edgeWidth; } + size_t ConfigurationConcrete::getHEdgeLocal () const + { return _hEdgeLocal; } + + + size_t ConfigurationConcrete::getVEdgeLocal () const + { return _vEdgeLocal; } + + float ConfigurationConcrete::getEdgeCostH () const { return _edgeCostH; } diff --git a/anabatic/src/Dijkstra.cpp b/anabatic/src/Dijkstra.cpp index 4141cb11..5c43d07d 100644 --- a/anabatic/src/Dijkstra.cpp +++ b/anabatic/src/Dijkstra.cpp @@ -35,6 +35,7 @@ namespace Anabatic { using Hurricane::ForEachIterator; using Hurricane::Error; using Hurricane::Component; + using Hurricane::Segment; using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::RoutingPad; @@ -63,7 +64,7 @@ namespace Anabatic { string s = "getXMin()) + "," + DbU::getValueString(_gcell->getYMin()) + ")" - + " connexId:" + getString(_connexId) + + " connexId:" + ((_connexId >= 0) ? getString(_connexId) : "None") + " d:" + ((_distance == unreached) ? "unreached" : DbU::getValueString(_distance) ) + "+" + getString(_branchId) + " stamp:" + (hasValidStamp() ? "valid" : "outdated") @@ -143,27 +144,45 @@ namespace Anabatic { void Dijkstra::load ( Net* net ) { - _net = net; + _cleanup(); + + const Layer* gcontactLayer = _anabatic->getConfiguration()->getGContactLayer(); + + _net = net; + _stamp = _anabatic->incStamp(); DebugSession::open( _net, 112, 120 ); cdebug_log(112,1) << "Dijkstra::load() " << _net << endl; - _sources.clear(); - _targets.clear(); - _searchArea.makeEmpty(); - _stamp = _anabatic->incStamp(); + vector< std::pair > components; + for ( Component* component : _net->getComponents() ) { + RoutingPad* rp = dynamic_cast( component ); + if (rp) { components.push_back( make_pair(rp,true) ); continue; } - vector rps; - for ( RoutingPad* rp : _net->getRoutingPads() ) rps.push_back( rp ); - for ( RoutingPad* rp : rps ) { - Box rpBb = rp->getBoundingBox(); - Point center = rpBb.getCenter(); - GCell* gcell = _anabatic->getGCellUnder( center ); + Contact* gcontact = dynamic_cast( component ); + if (gcontact and (gcontact->getLayer() == gcontactLayer)) + components.push_back( make_pair(gcontact,false) ); + } + + for ( auto element : components ) { + RoutingPad* rp = NULL; + Contact* gcontact = NULL; + Point center; + + if (element.second) { + rp = static_cast( element.first ); + center = rp->getBoundingBox().getCenter(); + } else { + gcontact = static_cast( element.first ); + center = gcontact->getCenter(); + } + + GCell* gcell = _anabatic->getGCellUnder( center ); if (not gcell) { cerr << Error( "Dijkstra::load(): %s of %s is not under any GCell.\n" - " It will be ignored ans the routing will be incomplete." - , getString(rp ).c_str() + " It will be ignored so the routing may be incomplete." + , getString(element.first).c_str() , getString(_net).c_str() ) << endl; continue; @@ -175,22 +194,76 @@ namespace Anabatic { if (vertex->getConnexId() < 0) { vertex->setDistance( Vertex::unreached ); vertex->setStamp ( _stamp ); - vertex->setConnexId( _targets.size() ); + vertex->setConnexId( _connectedsId ); vertex->setBranchId( 0 ); vertex->setFrom ( NULL ); _targets.insert( vertex ); cdebug_log(112,0) << "Add Vertex: " << vertex << endl; } - Contact* gcontact = vertex->getGContact( _net ); - rp->getBodyHook()->detach(); - rp->getBodyHook()->attach( gcontact->getBodyHook() ); + if (gcontact) { + for ( Component* slave : gcontact->getSlaveComponents() ) { + Flags sideHint = Flags::NoFlags; + GCell* oppositeGCell = NULL; + + Segment* segment = dynamic_cast(slave); + if (segment) { + cdebug_log(112,0) << "| " << segment << endl; + if (segment->getSource() == gcontact) { + oppositeGCell = _anabatic->getGCellUnder( segment->getTarget()->getCenter() ); + sideHint = Flags::EastSide; + } else + if (segment->getTarget() == gcontact) { + cdebug_log(112,0) << " Connected by target, skipped." << endl; + continue; + } + } else { + segment = dynamic_cast(slave); + if (segment) { + cdebug_log(112,0) << "| " << segment << endl; + if (segment->getSource() == gcontact) { + oppositeGCell = _anabatic->getGCellUnder( segment->getTarget()->getCenter() ); + sideHint = Flags::NorthSide; + } else + if (segment->getTarget() == gcontact) { + cdebug_log(112,0) << " Connected by target, skipped." << endl; + continue; + } + } + } + + Edge* edge = gcell->getEdgeTo( oppositeGCell, sideHint ); + if (edge) { + cdebug_log(112,0) << "+ Associated to edge." << endl; + edge->setSegment( segment ); + } else + cerr << Error( "Dijkstra::load(): Cannot bind segment to any edge:\n" + " %s\n" + " source:%s\n" + " target:%s" + , getString(segment).c_str() + , getString(gcell).c_str() + , getString(oppositeGCell).c_str() + ) << endl; + } + } + + if (rp) { + Contact* vcontact = vertex->getGContact( _net ); + rp->getBodyHook()->detach(); + rp->getBodyHook()->attach( vcontact->getBodyHook() ); + } + } + + for ( Vertex* vertex : _targets ) { + if (vertex->getConnexId() != 0) continue; + _tagConnecteds( vertex, ++_connectedsId ); } cdebug_log(112,0) << "Search area: " << _searchArea << endl; cdebug_tabw(112,-1); DebugSession::close(); - } + } void Dijkstra::_selectFirstSource () @@ -240,13 +313,35 @@ namespace Anabatic { } } - _targets.erase ( firstSource ); - _sources.insert( firstSource ); + for ( auto ivertex = _targets.begin() ; ivertex != _targets.end() ; ) { + auto inext = ivertex; inext++; + + if ((*ivertex)->getConnexId() == firstSource->getConnexId()) { + _sources.insert( *ivertex ); + _targets.erase ( ivertex ); + } + + ivertex = inext; + } cdebug_log(112,0) << "Dijkstra::_selectFirstSource() " << *_sources.begin() << endl; } + void Dijkstra::_cleanup () + { + for ( Vertex* vertex : _sources ) if (vertex->getFrom()) vertex->getFrom()->setSegment( NULL ); + for ( Vertex* vertex : _targets ) if (vertex->getFrom()) vertex->getFrom()->setSegment( NULL ); + + //_checkEdges(); + + _sources.clear(); + _targets.clear(); + _searchArea.makeEmpty(); + _connectedsId = 0; + } + + bool Dijkstra::_propagate ( Flags enabledSides ) { cdebug_log(112,1) << "Dijkstra::_propagate() " << _net << endl; @@ -301,6 +396,7 @@ namespace Anabatic { // We did reach another target (different ). // Tag back the path, with a higher . _traceback( current ); + cdebug_tabw(112,-1); return true; } @@ -345,21 +441,23 @@ namespace Anabatic { Contact* sourceContact = source->getGContact( _net ); Contact* targetContact = target->getGContact( _net ); + Segment* segment = NULL; if (from->isHorizontal()) { - Horizontal::create( sourceContact - , targetContact - , _anabatic->getConfiguration()->getGHorizontalLayer() - , from->getAxis() - , DbU::fromLambda(2.0) - ); + segment = Horizontal::create( sourceContact + , targetContact + , _anabatic->getConfiguration()->getGHorizontalLayer() + , from->getAxis() + , DbU::fromLambda(2.0) + ); } else { - Vertical::create( sourceContact - , targetContact - , _anabatic->getConfiguration()->getGVerticalLayer() - , from->getAxis() - , DbU::fromLambda(2.0) - ); + segment = Vertical::create( sourceContact + , targetContact + , _anabatic->getConfiguration()->getGVerticalLayer() + , from->getAxis() + , DbU::fromLambda(2.0) + ); } + from->setSegment( segment ); } cdebug_tabw(112,-1); @@ -388,15 +486,16 @@ namespace Anabatic { enabledEdges = Flags::EastSide | Flags::SouthSide; } - Vertex* source = *_sources.begin(); _queue.clear(); - _queue.push( source ); - _connectedsId = source->getConnexId(); - source->setDistance( 0.0 ); + _connectedsId = (*_sources.begin())->getConnexId(); + for ( Vertex* source : _sources ) { + _queue.push( source ); + source->setDistance( 0.0 ); + cdebug_log(112,0) << "Push source: (size:" << _queue.size() << ") " + << source + << " _connectedsId:" << _connectedsId << endl; + } - cdebug_log(112,0) << "Push source: (size:" << _queue.size() << ") " - << source - << " _connectedsId:" << _connectedsId << endl; while ( not _targets.empty() and _propagate(enabledEdges) ); @@ -407,4 +506,157 @@ namespace Anabatic { } + void Dijkstra::ripup ( Edge* edge ) + { + DebugSession::open( _net, 112, 120 ); + + cdebug_log(112,1) << "Dijkstra::ripup(): " << edge << endl; + + GCell* gsource = edge->getSource(); + GCell* gtarget = edge->getTarget(); + Vertex* vsource = gsource->getObserver(GCell::Observable::Vertex); + Vertex* vtarget = gtarget->getObserver(GCell::Observable::Vertex); + + if ( (not isSourceVertex(vsource) and not isTargetVertex(vsource)) + or (not isSourceVertex(vtarget) and not isTargetVertex(vtarget)) ) { + cerr << Error( "Dijkstra::ripup(): %s do *not* belong to %s (ignored)." + , getString(edge).c_str() + , getString(_net).c_str() + ) << endl; + cdebug_tabw(112,-1); + DebugSession::close(); + return; + } + + edge->destroySegment(); + // for ( Contact* contact : gsource->getGContacts() ) { + // if (contact->getNet() != _net) continue; + + // for ( Component* component : contact->getSlaveComponents() ) { + // Segment* segment = dynamic_cast( component ); + // if (segment and (gtarget->hasGContact(dynamic_cast(segment->getTarget())))) { + // segment->destroy(); + // break; + // } + // } + + // break; + // } + + edge->incRealOccupancy( -1 ); + _propagateRipup( vsource ); + vtarget = _propagateRipup( vtarget ); + _tagConnecteds( vtarget, ++_connectedsId ); + + cdebug_tabw(112,-1); + DebugSession::close(); + } + + + Vertex* Dijkstra::_propagateRipup ( Vertex* end ) + { + cdebug_log(112,1) << "Dijkstra::_propagateRipup() from:" << end << endl; + + while ( end ) { + cdebug_log(112,0) << "| " << end << endl; + + Contact* gcontact = end->getGCell()->getGContact( _net ); + if (not gcontact) { + cdebug_log(112,0) << "Exiting on missing GContact." << endl; + cdebug_tabw(112,-1); + return end; + } + + Edge* eneighbor = NULL; + for ( Edge* edge : end->getGCell()->getEdges() ) { + if (edge->getSegment()) { + if (not eneighbor) eneighbor = edge; + else { + eneighbor = NULL; + break; + } + } + } + + for ( Component* component : gcontact->getSlaveComponents() ) { + if (dynamic_cast(component)) { + eneighbor = NULL; + break; + } + } + + if (not eneighbor) { + cdebug_log(112,0) << "Normal exit (fork or RoutingPad)." << endl; + cdebug_tabw(112,-1); + return end; + } + + cdebug_log(112,0) << "+ " << eneighbor << endl; + eneighbor->incRealOccupancy( -1 ); + eneighbor->destroySegment(); + eneighbor->setSegment( NULL ); + + end->setConnexId( -1 ); + end->setDistance( Vertex::unreached ); + end = eneighbor->getOpposite(end->getGCell())->getObserver(GCell::Observable::Vertex);; + } + + cdebug_log(112,0) << "Exiting on nothing left." << endl; + cdebug_tabw(112,-1); + return NULL; + } + + + void Dijkstra::_tagConnecteds ( Vertex* source, int connexId ) + { + cdebug_log(112,1) << "Dijkstra::_tagConnecteds()" << endl; + + source->setConnexId( connexId ); + + VertexSet stack; + stack.insert( source ); + + while ( not stack.empty() ) { + source = *stack.begin(); + stack.erase( source ); + + cdebug_log(112,0) << "| source:" << source << " stack.size():" << stack.size() << endl; + + for ( Edge* edge : source->getGCell()->getEdges() ) { + if (not edge->getSegment()) { + cdebug_log(112,0) << " Not connected:" << edge << endl; + continue; + } + + GCell* gneighbor = edge->getOpposite(source->getGCell()); + Vertex* vneighbor = gneighbor->getObserver(GCell::Observable::Vertex); + + if (not vneighbor->hasValidStamp()) continue; + if (vneighbor->getConnexId() == connexId) continue; + + vneighbor->setConnexId( connexId ); + stack.insert( vneighbor ); + } + } + + cdebug_tabw(112,-1); + } + + + void Dijkstra::_checkEdges () const + { + cdebug_log(112,1) << "Dijkstra::_checkEdges()" << endl; + + for ( Vertex* vertex : _vertexes ) { + for ( Edge* edge : vertex->getGCell()->getEdges(Flags::EastSide|Flags::NorthSide) ) { + if (edge->getSegment()) { + cdebug_log(112,0) << "Not reset:" << edge << edge->getSegment() << endl; + } + } + } + + cdebug_tabw(112,-1); + } + + } // Anabatic namespace. diff --git a/anabatic/src/Edge.cpp b/anabatic/src/Edge.cpp index 068bee37..114c89c7 100644 --- a/anabatic/src/Edge.cpp +++ b/anabatic/src/Edge.cpp @@ -16,6 +16,7 @@ #include #include "hurricane/Error.h" +#include "hurricane/Segment.h" #include "anabatic/Edge.h" #include "anabatic/GCell.h" #include "anabatic/AnabaticEngine.h" @@ -41,6 +42,7 @@ namespace Anabatic { , _source (source) , _target (target) , _axis (0) + , _segment (NULL) { } @@ -170,6 +172,30 @@ namespace Anabatic { } + void Edge::incRealOccupancy ( int delta ) + { + unsigned int occupancy = 0; + if ((int)_realOccupancy + delta > 0) occupancy = _realOccupancy + delta; + if ((_realOccupancy <= _capacity) and (occupancy > _capacity)) getAnabatic()->addOv ( this ); + if ((_realOccupancy > _capacity) and (occupancy <= _capacity)) getAnabatic()->removeOv( this ); + _realOccupancy = occupancy; + } + + + void Edge::destroySegment () + { + if (not _segment) return; + + Contact* csource = dynamic_cast( _segment->getSource() ); + Contact* ctarget = dynamic_cast( _segment->getTarget() ); + + _segment->destroy(); + _segment = NULL; + if (csource) getSource()->unrefContact( csource ); + if (ctarget) getTarget()->unrefContact( ctarget ); + } + + void Edge::_setSource ( GCell* source ) { if (source == _target) diff --git a/anabatic/src/Edges.cpp b/anabatic/src/Edges.cpp index 588f7d0f..33845ebe 100644 --- a/anabatic/src/Edges.cpp +++ b/anabatic/src/Edges.cpp @@ -46,7 +46,7 @@ namespace Anabatic { Edge* GCell_Edges::Locator::getElement () const - { + { if (_stateFlags.contains(Flags::EastSide )) return _gcell->getEastEdges ()[_iedge]; if (_stateFlags.contains(Flags::NorthSide)) return _gcell->getNorthEdges()[_iedge]; if (_stateFlags.contains(Flags::WestSide )) return _gcell->getWestEdges ()[_iedge]; @@ -61,40 +61,45 @@ namespace Anabatic { void GCell_Edges::Locator::progress () { - // cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl; - // cdebug_log(110,0) << " East:" << _gcell->getEastEdges().size() - // << " North:" << _gcell->getNorthEdges().size() - // << " West:" << _gcell->getWestEdges().size() - // << " South:" << _gcell->getSouthEdges().size() << endl; - // cdebug_log(110,0) << this << endl; + cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl; + cdebug_log(110,0) << " _filterFlags:" << _filterFlags << endl; + cdebug_log(110,0) << " East:" << _gcell->getEastEdges().size() + << " North:" << _gcell->getNorthEdges().size() + << " West:" << _gcell->getWestEdges().size() + << " South:" << _gcell->getSouthEdges().size() << endl; + cdebug_log(110,0) << this << endl; ++_iedge; while (_stateFlags) { - if ((_stateFlags & _filterFlags).contains(Flags::EastSide)) { - if (_iedge < _gcell->getEastEdges().size()) break; + if (_stateFlags.contains(Flags::EastSide)) { + if ( (_iedge < _gcell->getEastEdges().size()) + and _filterFlags.contains(Flags::EastSide)) break; // cdebug_log(110,0) << "Switching to North side." << endl; _stateFlags = Flags::NorthSide; _iedge = 0; // cdebug_log(110,0) << this << endl; continue; } - if ((_stateFlags & _filterFlags).contains(Flags::NorthSide)) { - if (_iedge < _gcell->getNorthEdges().size()) break; + if (_stateFlags.contains(Flags::NorthSide)) { + if ( (_iedge < _gcell->getNorthEdges().size()) + and _filterFlags.contains(Flags::NorthSide)) break; // cdebug_log(110,0) << "Switching to West side." << endl; _stateFlags = Flags::WestSide; _iedge = 0; // cdebug_log(110,0) << this << endl; continue; } - if ((_stateFlags & _filterFlags).contains(Flags::WestSide)) { - if (_iedge < _gcell->getWestEdges().size()) break; + if (_stateFlags.contains(Flags::WestSide)) { + if ( (_iedge < _gcell->getWestEdges().size()) + and _filterFlags.contains(Flags::WestSide)) break; // cdebug_log(110,0) << "Switching to South side." << endl; _stateFlags = Flags::SouthSide; _iedge = 0; continue; } - if ((_stateFlags & _filterFlags).contains(Flags::SouthSide)) { - if (_iedge < _gcell->getSouthEdges().size()) break; + if (_stateFlags.contains(Flags::SouthSide)) { + if ( (_iedge < _gcell->getSouthEdges().size()) + and _filterFlags.contains(Flags::SouthSide)) break; // cdebug_log(110,0) << "All edges done." << endl; _stateFlags = 0; _iedge = 0; @@ -102,7 +107,7 @@ namespace Anabatic { } } - //cdebug_log(110,0) << "GCell_Edges::Locator::progress() [to] " << _stateFlags << " iedge:" << _iedge << endl; + cdebug_log(110,0) << "GCell_Edges::Locator::progress() [to] " << _stateFlags << " iedge:" << _iedge << endl; } diff --git a/anabatic/src/GCell.cpp b/anabatic/src/GCell.cpp index 0314f5af..fe1a625b 100644 --- a/anabatic/src/GCell.cpp +++ b/anabatic/src/GCell.cpp @@ -164,6 +164,24 @@ namespace Anabatic { } + bool GCell::hasGContact ( const Contact* owned ) const + { + for ( Contact* contact : _contacts ) { + if (contact == owned) return true; + } + return false; + } + + + Edge* GCell::getEdgeTo ( GCell* neighbor, Flags sideHint ) const + { + for ( Edge* edge : getEdges(sideHint) ) { + if (edge->getOpposite(this) == neighbor) return edge; + } + return NULL; + } + + GCell* GCell::getWest ( DbU::Unit y ) const { for ( Edge* edge : _westEdges ) { @@ -372,7 +390,9 @@ namespace Anabatic { bool GCell::doGrid () { - DbU::Unit side = getAnabatic()->getConfiguration()->getSliceHeight(); + const vector& gcells = getAnabatic()->getGCells(); + size_t ibegin = gcells.size(); + DbU::Unit side = getAnabatic()->getConfiguration()->getSliceHeight(); Interval hspan = getSide( Flags::Horizontal ); Interval vspan = getSide( Flags::Vertical ); @@ -414,6 +434,15 @@ namespace Anabatic { column = column->vcut( xcut ); } + size_t hLocal = - getAnabatic()->getConfiguration()->getHEdgeLocal(); + size_t vLocal = - getAnabatic()->getConfiguration()->getVEdgeLocal(); + for ( ; ibegin < gcells.size() ; ++ibegin ) { + for ( Edge* edge : gcells[ibegin]->getEdges(Flags::NorthSide|Flags::EastSide) ) { + if (edge->isHorizontal()) edge->incCapacity( hLocal ); + else edge->incCapacity( vLocal ); + } + } + //UpdateSession::close(); return true; @@ -549,11 +578,32 @@ namespace Anabatic { , DbU::fromLambda(2.0) , DbU::fromLambda(2.0) ); + _contacts.push_back( contact ); cdebug_log(111,0) << "GCell::getGContact(): " << contact << endl; return contact; } + bool GCell::unrefContact ( Contact* unref ) + { + if (_contacts.empty()) return false; + + for ( size_t i=0 ; i< _contacts.size() ; ++i ) { + if (_contacts[i] == unref) { + if (_contacts[i]->getSlaveComponents().getLocator()->isValid()) return false; + + std::swap( _contacts[i], _contacts[_contacts.size()-1] ); + _contacts[ _contacts.size()-1 ]->destroy(); + _contacts.pop_back(); + + return true; + } + } + + return false; + } + + const Name& GCell::getName () const { return _extensionName; } diff --git a/anabatic/src/GlobalRoute.cpp b/anabatic/src/GlobalRoute.cpp new file mode 100644 index 00000000..28087a7e --- /dev/null +++ b/anabatic/src/GlobalRoute.cpp @@ -0,0 +1,195 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2016-2016, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Global Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./GlobalRoute.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include "hurricane/Error.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/Cell.h" +#include "hurricane/UpdateSession.h" +#include "hurricane/DebugSession.h" +#include "crlcore/RoutingGauge.h" +#include "anabatic/GCell.h" +#include "anabatic/Dijkstra.h" +#include "anabatic/AnabaticEngine.h" + + +namespace { + + using std::cerr; + using std::endl; + using std::setw; + using std::left; + using std::right; + using Hurricane::DbU; + using Anabatic::Edge; + using Anabatic::Vertex; + + + class DigitalDistance { + public: + inline DigitalDistance ( float h, float k ); + DbU::Unit operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const; + private: + // For an explanation of h & k parameters, see: + // "KNIK, routeur global pour la plateforme Coriolis", p. 52. + float _h; + float _k; + }; + + + inline DigitalDistance::DigitalDistance ( float h, float k ) : _h(h), _k(k) { } + + + DbU::Unit DigitalDistance::operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const + { + if (edge->getCapacity() <= 0) return Vertex::unreached; + + float congestion = (float)edge->getRealOccupancy() / (float)edge->getCapacity(); + float congestionCost = 1.0 + _h / (1.0 + std::exp(_k * (congestion - 1.0))); + + float distance = (float)source->getDistance() + congestionCost * (float)edge->getDistance(); + + // Edge* sourceFrom = source->getFrom(); + // if (sourceFrom) { + // distance += ((sourceFrom->isHorizontal() xor edge->isHorizontal()) ? 3.0 : 0.0) * (float)Edge::unity; + // } + cdebug_log(112,0) << "cong:" << congestion + << " ccost:" << congestionCost + << " digitalDistance:" << DbU::getValueString((DbU::Unit)distance) << endl; + + return (DbU::Unit)distance; + } + + +} // Anonymous namespace. + + +namespace Anabatic { + + using std::cerr; + using std::cout; + using std::endl; + using std::setw; + using std::ostringstream; + using Hurricane::Error; + using Hurricane::RegularLayer; + using Hurricane::Component; + using Hurricane::Horizontal; + using Hurricane::Vertical; + using Hurricane::Cell; + using Hurricane::UpdateSession; + using Hurricane::DebugSession; + using CRL::RoutingGauge; + using CRL::RoutingLayerGauge; + + +// ------------------------------------------------------------------- +// Class : "Anabatic::AnabaticEngine". +// +// Methods dedicateds to complete global routing. + + + void AnabaticEngine::globalRoute () + { + Cell* cell = getCell(); + + cell->flattenNets( Cell::Flags::BuildRings ); + cell->createRoutingPadRings( Cell::Flags::BuildRings ); + + //DebugSession::addToTrace( cell->getNet("alu_out(3)") ); + //DebugSession::addToTrace( cell->getNet("imuxe.not_i(1)") ); + //DebugSession::addToTrace( cell->getNet("r(0)") ); + //DebugSession::addToTrace( cell->getNet("a_from_pads(0)") ); + //DebugSession::addToTrace( cell->getNet("ialu.not_aux104") ); + //DebugSession::addToTrace( cell->getNet("mips_r3000_1m_dp_shift32_rshift_se_muxoutput(126)") ); + + startMeasures(); + + UpdateSession::open(); + if (getGCells().size() == 1) { + cmess1 << " o Building regular grid..." << endl; + getSouthWestGCell()->doGrid(); + } else { + cmess1 << " o Reusing existing grid." << endl; + } + cmess1 << Dots::asInt(" - GCells" ,getGCells().size()) << endl; + UpdateSession::close(); + + stopMeasures(); + printMeasures( "Anabatic Grid" ); + startMeasures(); + + cmess1 << " o Running global routing..." << endl; + + NetSet netsToRoute; + for ( Net* net : cell->getNets() ) { + if (net->isSupply() or net->isClock()) continue; + netsToRoute.insert( net ); + } + + UpdateSession::open(); + Dijkstra* dijkstra = new Dijkstra ( this ); + dijkstra->setDistance( DigitalDistance( getConfiguration()->getEdgeCostH() + , getConfiguration()->getEdgeCostK() ) ); + + size_t iteration = 0; + while ( not netsToRoute.empty() and (iteration < 5) ) { + cmess2 << " [" << setw(3) << iteration << "] nets:" + << left << setw(6) << netsToRoute.size() << right; + + for ( Net* net : netsToRoute ) { + dijkstra->load( net ); + dijkstra->run(); + } + + netsToRoute.clear(); + const vector& ovEdges = getOvEdges(); + cmess2 << " ovEdges:" << ovEdges.size(); + + while ( not ovEdges.empty() ) { + Edge* ovEdge = ovEdges[0]; + NetSet netsToUnroute; + getNetsFromEdge( ovEdge, netsToUnroute ); + + for ( Net* net : netsToUnroute ) { + dijkstra->load( net ); + dijkstra->ripup( ovEdge ); + netsToRoute.insert( net ); + } + } + + cmess2 << " ripup:" << netsToRoute.size(); + + stopMeasures(); + cmess2 << " " << setw(10) << Timer::getStringTime (_timer.getCombTime()) + << " " << setw( 6) << Timer::getStringMemory(_timer.getIncrease()) << endl; + startMeasures(); + + ++iteration; + } + + stopMeasures(); + printMeasures( "Dijkstra" ); + + delete dijkstra; + UpdateSession::close(); + } + + +} // Anabatic namespace. diff --git a/anabatic/src/GraphicAnabaticEngine.cpp b/anabatic/src/GraphicAnabaticEngine.cpp index 3708e777..48165030 100644 --- a/anabatic/src/GraphicAnabaticEngine.cpp +++ b/anabatic/src/GraphicAnabaticEngine.cpp @@ -200,8 +200,9 @@ namespace Anabatic { //DebugSession::addToTrace( cell->getNet("alu_out(3)") ); //DebugSession::addToTrace( cell->getNet("imuxe.not_i(1)") ); - DebugSession::addToTrace( cell->getNet("r(0)") ); - DebugSession::addToTrace( cell->getNet("ialu.not_aux104") ); + //DebugSession::addToTrace( cell->getNet("r(0)") ); + //DebugSession::addToTrace( cell->getNet("ialu.not_aux104") ); + DebugSession::addToTrace( cell->getNet("mips_r3000_1m_dp_shift32_rshift_se_muxoutput(159)") ); engine->startMeasures(); @@ -226,11 +227,33 @@ namespace Anabatic { dijkstra->load( net ); dijkstra->run(); } - delete dijkstra; UpdateSession::close(); engine->stopMeasures(); engine->printMeasures( "Dijkstra" ); + + const vector& ovEdges = engine->getOvEdges(); + if (not ovEdges.empty()) { + size_t count = 0; + + cmess1 << " - " << ovEdges.size() << " overloaded edges." << endl; + cmess1 << " " << ovEdges[0] << endl; + NetSet nets; + engine->getNetsFromEdge( ovEdges[0], nets ); + for ( Net* net : nets ) { + cmess1 << " [" << setw(2) << count++ << "] " << net << endl; + } + + UpdateSession::open(); + Net* net = *nets.begin(); + dijkstra->load( net ); + dijkstra->ripup( ovEdges[0] ); + UpdateSession::close(); + } + + UpdateSession::open(); + delete dijkstra; + UpdateSession::close(); } @@ -401,22 +424,35 @@ namespace Anabatic { } + void GraphicAnabaticEngine::_globalRoute () + { + AnabaticEngine* engine = getForFramework( CreateEngine ); + engine->globalRoute(); + } + + void GraphicAnabaticEngine::addToMenu ( CellViewer* viewer ) { assert( _viewer == NULL ); _viewer = viewer; - if (_viewer->hasMenuAction("placeAndRoute.anabatic")) { + if (_viewer->hasMenuAction("placeAndRoute.anabatic.globalRoute")) { cerr << Warning( "GraphicAnabaticEngine::addToMenu() - Anabatic engine already hooked in." ) << endl; return; } - _viewer->addToMenu( "placeAndRoute.anabatic" + _viewer->addMenu ( "placeAndRoute.anabatic", "Anabatic" ); + _viewer->addToMenu( "placeAndRoute.anabatic.runTest" , "Anabatic - &Test Run" , "Perform a test run of Anabatic on the design" , std::bind(&GraphicAnabaticEngine::_runTest,this) ); + _viewer->addToMenu( "placeAndRoute.anabatic.globalRoute" + , "Anabatic - &Global Route" + , "Global Route" + , std::bind(&GraphicAnabaticEngine::_globalRoute,this) + ); } diff --git a/anabatic/src/anabatic/AnabaticEngine.h b/anabatic/src/anabatic/AnabaticEngine.h index 19971218..01d12638 100644 --- a/anabatic/src/anabatic/AnabaticEngine.h +++ b/anabatic/src/anabatic/AnabaticEngine.h @@ -19,10 +19,12 @@ #include #include +#include #include "hurricane/Timer.h" namespace Hurricane { class Name; + class Net; class Cell; class Instance; class CellViewer; @@ -47,6 +49,9 @@ namespace Anabatic { using CRL::ToolEngine; + typedef std::set NetSet; + + class AnabaticEngine : public ToolEngine { public: typedef ToolEngine Super; @@ -60,13 +65,19 @@ namespace Anabatic { inline void setViewer ( CellViewer* ); inline const Matrix* getMatrix () const; inline const vector& getGCells () const; + inline const vector& getOvEdges () const; inline GCell* getSouthWestGCell () const; inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const; inline GCell* getGCellUnder ( Point ) const; int getCapacity ( Interval, Flags ) const; + size_t getNetsFromEdge ( const Edge*, NetSet& ); + inline void addOv ( Edge* ); + inline void removeOv ( Edge* ); // Dijkstra related functions. inline int getStamp () const; inline int incStamp (); + // Global routing related functions. + void globalRoute (); // Misc. functions. inline const Flags& flags () const; inline Flags& flags (); @@ -97,6 +108,7 @@ namespace Anabatic { Configuration* _configuration; Matrix _matrix; vector _gcells; + vector _ovEdges; CellViewer* _viewer; Flags _flags; int _stamp; @@ -107,6 +119,7 @@ namespace Anabatic { inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; } inline const Matrix* AnabaticEngine::getMatrix () const { return &_matrix; } inline const vector& AnabaticEngine::getGCells () const { return _gcells; } + inline const vector& AnabaticEngine::getOvEdges () const { return _ovEdges; } inline GCell* AnabaticEngine::getSouthWestGCell () const { return _gcells[0]; } inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); } inline GCell* AnabaticEngine::getGCellUnder ( Point p ) const { return _matrix.getUnder(p); } @@ -134,6 +147,14 @@ namespace Anabatic { inline int AnabaticEngine::getStamp () const { return _stamp; } inline int AnabaticEngine::incStamp () { return ++_stamp; } + inline void AnabaticEngine::addOv ( Edge* edge ) { _ovEdges.push_back(edge); } + + inline void AnabaticEngine::removeOv ( Edge* edge ) + { + for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge ) + if (*iedge == edge) { _ovEdges.erase(iedge); break; } + } + } // Anabatic namespace. diff --git a/anabatic/src/anabatic/Configuration.h b/anabatic/src/anabatic/Configuration.h index 0dad59fd..d122d310 100644 --- a/anabatic/src/anabatic/Configuration.h +++ b/anabatic/src/anabatic/Configuration.h @@ -88,6 +88,8 @@ namespace Anabatic { virtual DbU::Unit getEdgeWidth () const = 0; virtual float getEdgeCostH () const = 0; virtual float getEdgeCostK () const = 0; + virtual size_t getHEdgeLocal () const = 0; + virtual size_t getVEdgeLocal () const = 0; virtual void print ( Cell* ) const = 0; virtual Record* _getRecord () const = 0; virtual string _getString () const = 0; @@ -143,6 +145,8 @@ namespace Anabatic { virtual DbU::Unit getEdgeWidth () const; virtual float getEdgeCostH () const; virtual float getEdgeCostK () const; + virtual size_t getHEdgeLocal () const; + virtual size_t getVEdgeLocal () const; virtual void print ( Cell* ) const; virtual Record* _getRecord () const; virtual string _getString () const; @@ -160,6 +164,8 @@ namespace Anabatic { DbU::Unit _edgeWidth; float _edgeCostH; float _edgeCostK; + size_t _hEdgeLocal; + size_t _vEdgeLocal; private: ConfigurationConcrete ( const ConfigurationConcrete& ); ConfigurationConcrete& operator= ( const ConfigurationConcrete& ); diff --git a/anabatic/src/anabatic/Dijkstra.h b/anabatic/src/anabatic/Dijkstra.h index 18e8a6e8..dbd56f60 100644 --- a/anabatic/src/anabatic/Dijkstra.h +++ b/anabatic/src/anabatic/Dijkstra.h @@ -44,7 +44,7 @@ namespace Anabatic { public: class CompareById { public: - inline bool operator() ( const Vertex* lhs, const Vertex* rhs ); + inline bool operator() ( const Vertex* lhs, const Vertex* rhs ) const; }; public: static DbU::Unit unreached; @@ -125,7 +125,7 @@ namespace Anabatic { inline Vertex* Vertex::getPredecessor () const { return (hasValidStamp() and _from) ? _from->getOpposite(_gcell)->getObserver(GCell::Observable::Vertex) : NULL; } - inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) + inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) const { return lhs->getId() < rhs->getId(); } @@ -224,16 +224,23 @@ namespace Anabatic { ~Dijkstra (); public: inline bool isBipoint () const; + inline bool isSourceVertex ( Vertex* ) const; + inline bool isTargetVertex ( Vertex* ) const; inline void setDistance ( distance_t ); void load ( Net* ); void run ( Mode mode=Mode::Standart ); + void ripup ( Edge* ); private: Dijkstra ( const Dijkstra& ); Dijkstra& operator= ( const Dijkstra& ); static DbU::Unit _distance ( const Vertex*, const Vertex*, const Edge* ); + void _cleanup (); bool _propagate ( Flags enabledSides ); void _traceback ( Vertex* ); void _selectFirstSource (); + Vertex* _propagateRipup ( Vertex* ); + void _tagConnecteds ( Vertex*, int connexId ); + void _checkEdges () const; private: AnabaticEngine* _anabatic; vector _vertexes; @@ -252,8 +259,10 @@ namespace Anabatic { inline Dijkstra::Mode::Mode ( unsigned int flags ) : BaseFlags(flags) { } inline Dijkstra::Mode::Mode ( BaseFlags base ) : BaseFlags(base) { } - inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); } - inline void Dijkstra::setDistance ( distance_t cb ) { _distanceCb = cb; } + inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); } + inline bool Dijkstra::isSourceVertex ( Vertex* v ) const { return (_sources.find(v) != _sources.end()); } + inline bool Dijkstra::isTargetVertex ( Vertex* v ) const { return (_targets.find(v) != _targets.end()); } + inline void Dijkstra::setDistance ( distance_t cb ) { _distanceCb = cb; } } // Anabatic namespace. diff --git a/anabatic/src/anabatic/Edge.h b/anabatic/src/anabatic/Edge.h index aa2a4db4..887ccf47 100644 --- a/anabatic/src/anabatic/Edge.h +++ b/anabatic/src/anabatic/Edge.h @@ -22,10 +22,14 @@ #include "hurricane/Interval.h" #include "hurricane/Box.h" #include "hurricane/ExtensionGo.h" +namespace Hurricane { + class Segment; +} #include "anabatic/Constants.h" #include "anabatic/Edges.h" + namespace Anabatic { using std::string; @@ -34,6 +38,7 @@ namespace Anabatic { using Hurricane::DbU; using Hurricane::Interval; using Hurricane::Box; + using Hurricane::Segment; using Hurricane::Cell; using Hurricane::ExtensionGo; @@ -63,7 +68,11 @@ namespace Anabatic { inline DbU::Unit getAxis () const; DbU::Unit getAxisMin () const; Interval getSide () const; - inline void incRealOccupancy ( unsigned int ); + inline Segment* getSegment () const; + inline void incCapacity ( int ); + void incRealOccupancy ( int ); + inline void setSegment ( Segment* ); + void destroySegment (); inline const Flags& flags () const; inline Flags& flags (); inline void invalidate (); @@ -80,17 +89,17 @@ namespace Anabatic { virtual Box getBoundingBox () const; public: // Inspector support. - virtual string _getTypeName () const; - virtual string _getString () const; - virtual Record* _getRecord () const; - protected: - Edge ( GCell* source, GCell* target, Flags flags ); - virtual ~Edge (); - virtual void _postCreate (); - virtual void _preDestroy (); - private: - Edge ( const Edge& ); - Edge& operator= ( const Edge& ); + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + protected: + Edge ( GCell* source, GCell* target, Flags flags ); + virtual ~Edge (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + Edge ( const Edge& ); + Edge& operator= ( const Edge& ); private: static Name _extensionName; Flags _flags; @@ -100,6 +109,7 @@ namespace Anabatic { GCell* _source; GCell* _target; DbU::Unit _axis; + Segment* _segment; }; @@ -112,7 +122,9 @@ namespace Anabatic { inline GCell* Edge::getSource () const { return _source; } inline GCell* Edge::getTarget () const { return _target; } inline DbU::Unit Edge::getAxis () const { return _axis; } - inline void Edge::incRealOccupancy ( unsigned int delta ) { _realOccupancy+=delta; } + inline Segment* Edge::getSegment () const { return _segment; } + inline void Edge::incCapacity ( int delta ) { _capacity = ((int)_capacity+delta > 0) ? _capacity+delta : 0; } + inline void Edge::setSegment ( Segment* s ) { _segment=s; } inline const Flags& Edge::flags () const { return _flags; } inline Flags& Edge::flags () { return _flags; } inline void Edge::invalidate () { _flags |= Flags::Invalidated; } diff --git a/anabatic/src/anabatic/GCell.h b/anabatic/src/anabatic/GCell.h index 8833765c..f56a0d1a 100644 --- a/anabatic/src/anabatic/GCell.h +++ b/anabatic/src/anabatic/GCell.h @@ -68,74 +68,78 @@ namespace Anabatic { Observable& operator= ( const StaticObservable& ); }; public: - static Box getBorder ( const GCell*, const GCell* ); - public: - static GCell* create ( AnabaticEngine* ); - public: - inline bool isHFlat () const; - inline bool isVFlat () const; - inline bool isFlat () const; - inline bool isDevice () const; - inline bool isChannel () const; - inline bool isStrut () const; - inline bool isMatrix () const; - inline AnabaticEngine* getAnabatic () const; - inline DbU::Unit getXMin () const; - inline DbU::Unit getYMin () const; - inline DbU::Unit getXMax ( int shrink=0 ) const; - inline DbU::Unit getYMax ( int shrink=0 ) const; - inline Interval getSide ( Flags direction ) const; - inline Point getCenter () const; - inline const vector& getWestEdges () const; - inline const vector& getEastEdges () const; - inline const vector& getNorthEdges () const; - inline const vector& getSouthEdges () const; - inline Edges getEdges () const; - inline GCell* getWest () const; - inline GCell* getEast () const; - inline GCell* getSouth () const; - inline GCell* getNorth () const; - GCell* getWest ( DbU::Unit y ) const; - GCell* getEast ( DbU::Unit y ) const; - GCell* getSouth ( DbU::Unit x ) const; - GCell* getNorth ( DbU::Unit x ) const; - GCell* getUnder ( DbU::Unit x, DbU::Unit y ) const; - inline GCell* getUnder ( Point p ) const; - GCell* hcut ( DbU::Unit y ); - GCell* vcut ( DbU::Unit x ); - bool doGrid (); - Contact* getGContact ( Net* ); + static Box getBorder ( const GCell*, const GCell* ); + public: + static GCell* create ( AnabaticEngine* ); + public: + inline bool isHFlat () const; + inline bool isVFlat () const; + inline bool isFlat () const; + inline bool isDevice () const; + inline bool isChannel () const; + inline bool isStrut () const; + inline bool isMatrix () const; + bool hasGContact ( const Contact* ) const; + inline AnabaticEngine* getAnabatic () const; + inline DbU::Unit getXMin () const; + inline DbU::Unit getYMin () const; + inline DbU::Unit getXMax ( int shrink=0 ) const; + inline DbU::Unit getYMax ( int shrink=0 ) const; + inline Interval getSide ( Flags direction ) const; + inline Point getCenter () const; + inline const vector& getWestEdges () const; + inline const vector& getEastEdges () const; + inline const vector& getNorthEdges () const; + inline const vector& getSouthEdges () const; + Edge* getEdgeTo ( GCell*, Flags sideHint=Flags::AllSides ) const; + inline Edges getEdges ( Flags sides=Flags::AllSides ) const; + inline GCell* getWest () const; + inline GCell* getEast () const; + inline GCell* getSouth () const; + inline GCell* getNorth () const; + GCell* getWest ( DbU::Unit y ) const; + GCell* getEast ( DbU::Unit y ) const; + GCell* getSouth ( DbU::Unit x ) const; + GCell* getNorth ( DbU::Unit x ) const; + GCell* getUnder ( DbU::Unit x, DbU::Unit y ) const; + inline GCell* getUnder ( Point p ) const; + GCell* hcut ( DbU::Unit y ); + GCell* vcut ( DbU::Unit x ); + bool doGrid (); + Contact* getGContact ( Net* ); + inline const vector& getGContacts () const; + bool unrefContact ( Contact* ); // Misc. functions. - inline const Flags& flags () const; - inline Flags& flags (); - void _add ( Edge* edge, Flags side ); - void _remove ( Edge* edge, Flags side=Flags::AllSides ); - void _destroyEdges (); - private: - void _revalidate (); - void _moveEdges ( GCell* dest, size_t ibegin, Flags flags ); - public: - // Observers. - inline void setObserver ( size_t slot, BaseObserver* ); - template - inline OwnerT* getObserver ( size_t slot ); - inline void notify ( unsigned int flags ); - // ExtensionGo support. - inline const Name& staticGetName (); - virtual const Name& getName () const; - virtual void translate ( const DbU::Unit&, const DbU::Unit& ); - virtual Box getBoundingBox () const; - public: - // Inspector support. - virtual string _getTypeName () const; - virtual string _getString () const; - virtual Record* _getRecord () const; - protected: - GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin ); - virtual ~GCell (); - GCell* _create ( DbU::Unit xmin, DbU::Unit ymin ); - virtual void _postCreate (); - virtual void _preDestroy (); + inline const Flags& flags () const; + inline Flags& flags (); + void _add ( Edge* edge, Flags side ); + void _remove ( Edge* edge, Flags side=Flags::AllSides ); + void _destroyEdges (); + private: + void _revalidate (); + void _moveEdges ( GCell* dest, size_t ibegin, Flags flags ); + public: + // Observers. + inline void setObserver ( size_t slot, BaseObserver* ); + template + inline OwnerT* getObserver ( size_t slot ); + inline void notify ( unsigned int flags ); + // ExtensionGo support. + inline const Name& staticGetName (); + virtual const Name& getName () const; + virtual void translate ( const DbU::Unit&, const DbU::Unit& ); + virtual Box getBoundingBox () const; + public: + // Inspector support. + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; + protected: + GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin ); + virtual ~GCell (); + GCell* _create ( DbU::Unit xmin, DbU::Unit ymin ); + virtual void _postCreate (); + virtual void _preDestroy (); private: GCell ( const GCell& ); GCell& operator= ( const GCell& ); @@ -154,28 +158,29 @@ namespace Anabatic { }; - inline bool GCell::isHFlat () const { return getYMin() == getYMax(); } - inline bool GCell::isVFlat () const { return getXMin() == getXMax(); } - inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); } - inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; } - inline bool GCell::isChannel () const { return _flags & Flags::ChannelGCell; } - inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; } - inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; } - inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; } - inline DbU::Unit GCell::getXMin () const { return _xmin; } - inline DbU::Unit GCell::getYMin () const { return _ymin; } - inline Edges GCell::getEdges () const { return new GCell_Edges(this); } - inline const vector& GCell::getWestEdges () const { return _westEdges; } - inline const vector& GCell::getEastEdges () const { return _eastEdges; } - inline const vector& GCell::getNorthEdges () const { return _northEdges; } - inline const vector& GCell::getSouthEdges () const { return _southEdges; } - inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); } - inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); } - inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); } - inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); } - inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); } - inline const Flags& GCell::flags () const { return _flags; } - inline Flags& GCell::flags () { return _flags; } + inline bool GCell::isHFlat () const { return getYMin() == getYMax(); } + inline bool GCell::isVFlat () const { return getXMin() == getXMax(); } + inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); } + inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; } + inline bool GCell::isChannel () const { return _flags & Flags::ChannelGCell; } + inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; } + inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; } + inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; } + inline DbU::Unit GCell::getXMin () const { return _xmin; } + inline DbU::Unit GCell::getYMin () const { return _ymin; } + inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); } + inline const vector& GCell::getWestEdges () const { return _westEdges; } + inline const vector& GCell::getEastEdges () const { return _eastEdges; } + inline const vector& GCell::getNorthEdges () const { return _northEdges; } + inline const vector& GCell::getSouthEdges () const { return _southEdges; } + inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); } + inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); } + inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); } + inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); } + inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); } + inline const vector& GCell::getGContacts () const { return _contacts; } + inline const Flags& GCell::flags () const { return _flags; } + inline Flags& GCell::flags () { return _flags; } inline DbU::Unit GCell::getXMax ( int shrink ) const { return _eastEdges.empty() ? getCell()->getAbutmentBox().getXMax() - shrink diff --git a/anabatic/src/anabatic/GraphicAnabaticEngine.h b/anabatic/src/anabatic/GraphicAnabaticEngine.h index 2bcc391e..7a8ecf78 100644 --- a/anabatic/src/anabatic/GraphicAnabaticEngine.h +++ b/anabatic/src/anabatic/GraphicAnabaticEngine.h @@ -82,6 +82,7 @@ namespace Anabatic { GraphicAnabaticEngine (); virtual ~GraphicAnabaticEngine (); void _runTest (); + void _globalRoute (); };