From c5a9e0b6175874efb410ebad7021d1f04c4e7da0 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Fri, 10 Jun 2016 18:27:06 +0200 Subject: [PATCH] Anabatic transient commit 7. More Dijkstra bugs correcteds. * Bug: In Anabatic: - Activate the searchArea to limit the area explored by the Dijkstra. Uses the bounding boxes of the vertexes/gcells instead of the ones the RoutingPads. - Always detach contacts from the rings in load(), even if the vertex is already marked as target. - On reaching a target (non-negative connexId), do not forget to update the distance to source. - In Edges locator, added support for side selection (needed by the monotonic feature). * New: In Anabatic: - Hide the atomic Dijkstra methods (made private). - Implementation of the monotonic mode in Dijkstra (for bipoints only). - Added a separate function for distance computation between two vertexes, now take account of the VIAs costs. --- anabatic/src/Dijkstra.cpp | 145 +++++++++++++++++++------ anabatic/src/Edges.cpp | 63 +++++------ anabatic/src/GCell.cpp | 4 +- anabatic/src/GraphicAnabaticEngine.cpp | 28 ++++- anabatic/src/anabatic/Dijkstra.h | 81 ++++++++++---- anabatic/src/anabatic/Edges.h | 23 ++-- 6 files changed, 243 insertions(+), 101 deletions(-) diff --git a/anabatic/src/Dijkstra.cpp b/anabatic/src/Dijkstra.cpp index 649c03df..3088484f 100644 --- a/anabatic/src/Dijkstra.cpp +++ b/anabatic/src/Dijkstra.cpp @@ -21,6 +21,7 @@ #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/UpdateSession.h" +#include "hurricane/DebugSession.h" #include "anabatic/AnabaticEngine.h" #include "anabatic/Dijkstra.h" @@ -37,6 +38,7 @@ namespace Anabatic { using Hurricane::Vertical; using Hurricane::RoutingPad; using Hurricane::UpdateSession; + using Hurricane::DebugSession; // ------------------------------------------------------------------- @@ -81,9 +83,40 @@ namespace Anabatic { // Class : "Anabatic::Dijkstra". + Dijkstra::Mode::~Mode () + { } + + + string Dijkstra::Mode::_getTypeName () const + { return "Anabatic::Dijkstra::Mode"; } + + + string Dijkstra::Mode::_getString () const + { + string s = ""; + s += (_flags & Standart ) ? 'S' : '-'; + s += (_flags & Monotonic) ? 'M' : '-'; + + return s; + } + + + float Dijkstra::getDistance ( const Vertex* a, const Vertex* b, const Edge* e ) + { + float distance = a->getDistance() + e->getDistance(); + + Edge* aFrom = a->getFrom(); + if (aFrom) { + distance += (aFrom->isHorizontal() xor e->isHorizontal()) ? 3.0 : 0.0; + } + return distance; + } + + Dijkstra::Dijkstra ( AnabaticEngine* anabatic ) : _anabatic (anabatic) , _vertexes () + , _mode (Mode::Standart) , _net (NULL) , _stamp (-1) , _sources () @@ -109,8 +142,8 @@ namespace Anabatic { { _net = net; + DebugSession::open( _net, 110, 120 ); cdebug.log(111,1) << "Dijkstra::load() " << _net << endl; - UpdateSession::open(); _sources.clear(); _targets.clear(); @@ -133,58 +166,83 @@ namespace Anabatic { continue; } - _searchArea.merge( rpBb ); + _searchArea.merge( gcell->getBoundingBox() ); Vertex* vertex = gcell->getObserver(GCell::Observable::Vertex); if (vertex->getConnexId() < 0) { vertex->setStamp ( _stamp ); vertex->setConnexId( _targets.size() ); vertex->setFrom ( NULL ); - Contact* gcontact = vertex->getGContact( _net ); - rp->getBodyHook()->detach(); - rp->getBodyHook()->attach( gcontact->getBodyHook() ); _targets.insert( vertex ); - cdebug.log(111) << "Add Vertex: " << vertex << endl; } + + Contact* gcontact = vertex->getGContact( _net ); + rp->getBodyHook()->detach(); + rp->getBodyHook()->attach( gcontact->getBodyHook() ); } - UpdateSession::close(); + cdebug.log(111) << "Search area: " << _searchArea << endl; cdebug.tabw(111,-1); + DebugSession::close(); } - void Dijkstra::selectFirstSource () + void Dijkstra::_selectFirstSource () { if (_targets.empty()) { - cerr << Error( "Dijkstra::selectFirstSource(): %s has no vertexes to route, ignored." + cerr << Error( "Dijkstra::_selectFirstSource(): %s has no vertexes to route, ignored." , getString(_net).c_str() ) << endl; return; } - Point areaCenter = _searchArea.getCenter(); - auto ivertex = _targets.begin(); - Vertex* firstSource = *ivertex++; - DbU::Unit minDistance = areaCenter.manhattanDistance( firstSource->getCenter() ); - for ( ; ivertex != _targets.end() ; ++ivertex ) { - DbU::Unit distance = areaCenter.manhattanDistance( (*ivertex)->getCenter() ); - if (distance < minDistance) { - minDistance = distance; - firstSource = *ivertex; + Vertex* firstSource = NULL; + + if (_mode & Mode::Monotonic) { + if (_targets.size() == 2) { + auto ivertex = _targets.begin(); + Vertex* v1 = *ivertex; + Vertex* v2 = *(++ivertex); + + firstSource = (v1->getCenter().getX() <= v2->getCenter().getY()) ? v1 : v2; + } else { + cerr << Error( "Dijkstra::_selectFirstSource(): %s cannot be routed in monotonic mode.\n" + " Must have exactly two terminals (%u), revert to Standart." + , getString(_net).c_str() + , _targets.size() + ) << endl; + _mode = Mode::Standart; + } + } + + if (not firstSource) { + // Standart routing. + Point areaCenter = _searchArea.getCenter(); + auto ivertex = _targets.begin(); + + firstSource = *ivertex++; + DbU::Unit minDistance = areaCenter.manhattanDistance( firstSource->getCenter() ); + + for ( ; ivertex != _targets.end() ; ++ivertex ) { + DbU::Unit distance = areaCenter.manhattanDistance( (*ivertex)->getCenter() ); + if (distance < minDistance) { + minDistance = distance; + firstSource = *ivertex; + } } } _targets.erase ( firstSource ); _sources.insert( firstSource ); - cdebug.log(111) << "Dijkstra::selectFirstSource() " << *_sources.begin() << endl; + cdebug.log(111) << "Dijkstra::_selectFirstSource() " << *_sources.begin() << endl; } - bool Dijkstra::propagate () + bool Dijkstra::_propagate ( Flags enabledSides ) { - cdebug.log(111,1) << "Dijkstra::propagate() " << _net << endl; + cdebug.log(111,1) << "Dijkstra::_propagate() " << _net << endl; while ( not _queue.empty() ) { _queue.dump(); @@ -192,8 +250,6 @@ namespace Anabatic { Vertex* current = _queue.top(); _queue.pop(); - cdebug.log(111) << "Pop: (size:" << _queue.size() << ") " << current << endl; - if ((current->getConnexId() == _connectedsId) or (current->getConnexId() < 0)) { for ( Edge* edge : current->getGCell()->getEdges() ) { @@ -202,26 +258,34 @@ namespace Anabatic { GCell* gneighbor = edge->getOpposite(current->getGCell()); Vertex* vneighbor = gneighbor->getObserver(GCell::Observable::Vertex); + if (not _searchArea.contains(vneighbor->getCenter())) continue; + cdebug.log(111) << "| Edge " << edge << endl; cdebug.log(111) << "+ Neighbor: " << vneighbor << endl; + float distance = getDistance( current, vneighbor, edge ); + if (vneighbor->getConnexId() == _connectedsId) continue; if (vneighbor->getConnexId() >= 0) { - vneighbor->setFrom( edge ); + vneighbor->setFrom ( edge ); + vneighbor->setDistance( distance ); + cdebug.log(111) << "Push (before): (size:" << _queue.size() << ")" << endl; _queue.push( vneighbor ); cdebug.log(111) << "Push (target): (size:" << _queue.size() << ") " << vneighbor << endl; continue; } - float distance = current->getDistance() + edge->getDistance(); - if (distance < vneighbor->getDistance()) { - if (vneighbor->getDistance() != Vertex::unreached) _queue.erase( vneighbor ); - else { + cdebug.log(111) << "Push (before erase): (size:" << _queue.size() << ") " << vneighbor << endl; + if (vneighbor->getDistance() != Vertex::unreached) { + _queue.erase( vneighbor ); + _queue.dump(); + } else { vneighbor->setStamp ( _stamp ); vneighbor->setConnexId( -1 ); } + cdebug.log(111) << "Push (after erase): (size:" << _queue.size() << ")" << endl; vneighbor->setDistance( distance ); vneighbor->setFrom ( edge ); @@ -263,18 +327,27 @@ namespace Anabatic { } - void Dijkstra::run () + void Dijkstra::run ( Dijkstra::Mode mode ) { - cdebug.log(111,1) << "Dijkstra::run() on " << _net << endl; + DebugSession::open( _net, 110, 120 ); - selectFirstSource(); + cdebug.log(111,1) << "Dijkstra::run() on " << _net << " mode:" << mode << endl; + _mode = mode; + + _selectFirstSource(); if (_sources.empty()) { cdebug.log(111) << "No source to start, not routed." << endl; cdebug.tabw(111,-1); return; } - UpdateSession::open(); + Flags enabledEdges = Flags::AllSides; + if (_mode & Mode::Monotonic) { + if ((*_sources.begin())->getCenter().getY() <= (*_targets.begin())->getCenter().getY()) + enabledEdges = Flags::EastSide | Flags::NorthSide; + else + enabledEdges = Flags::EastSide | Flags::SouthSide; + } Vertex* source = *_sources.begin(); _queue.clear(); @@ -286,17 +359,17 @@ namespace Anabatic { << source << " _connectedsId:" << _connectedsId << endl; - while ( not _targets.empty() and propagate() ); + while ( not _targets.empty() and _propagate(enabledEdges) ); - toWires(); + _toWires(); _queue.clear(); - UpdateSession::close(); cdebug.tabw(111,-1); + DebugSession::close(); } - void Dijkstra::toWires () + void Dijkstra::_toWires () { cdebug.log(111,1) << "Dijkstra::toWires() " << _net << endl; diff --git a/anabatic/src/Edges.cpp b/anabatic/src/Edges.cpp index 0c84171c..d3927b89 100644 --- a/anabatic/src/Edges.cpp +++ b/anabatic/src/Edges.cpp @@ -26,14 +26,15 @@ namespace Anabatic { // ------------------------------------------------------------------- // Class : "Anabatic::GCell_Edges". - GCell_Edges::Locator::Locator ( const GCell* gcell ) + GCell_Edges::Locator::Locator ( const GCell* gcell, Flags filterFlags ) : EdgesHL() - , _gcell(gcell) - , _flags(Flags::EastSide) - , _iedge(0) + , _gcell (gcell) + , _stateFlags (Flags::EastSide) + , _filterFlags(filterFlags) + , _iedge (0) { // cdebug.log(110) << "GCell_Edges::Locator::Locator() " << isValid() << endl; - if (_gcell->getEastEdges().empty()) progress(); + if (_gcell->getEastEdges().empty() or not _filterFlags.contains(Flags::EastSide)) progress(); } @@ -46,21 +47,21 @@ namespace Anabatic { Edge* GCell_Edges::Locator::getElement () const { - if (_flags.contains(Flags::EastSide )) return _gcell->getEastEdges ()[_iedge]; - if (_flags.contains(Flags::NorthSide)) return _gcell->getNorthEdges()[_iedge]; - if (_flags.contains(Flags::WestSide )) return _gcell->getWestEdges ()[_iedge]; - if (_flags.contains(Flags::SouthSide)) return _gcell->getSouthEdges()[_iedge]; + 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]; + if (_stateFlags.contains(Flags::SouthSide)) return _gcell->getSouthEdges()[_iedge]; return NULL; } bool GCell_Edges::Locator::isValid () const - { return _flags; } + { return _stateFlags; } void GCell_Edges::Locator::progress () { - // cdebug.log(110) << "GCell_Edges::Locator::progress() [from] " << _flags << " iedge:" << _iedge << endl; + // cdebug.log(110) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl; // cdebug.log(110) << " East:" << _gcell->getEastEdges().size() // << " North:" << _gcell->getNorthEdges().size() // << " West:" << _gcell->getWestEdges().size() @@ -68,51 +69,51 @@ namespace Anabatic { // cdebug.log(110) << this << endl; ++_iedge; - while (_flags) { - if (_flags.contains(Flags::EastSide)) { + while (_stateFlags) { + if ((_stateFlags & _filterFlags).contains(Flags::EastSide)) { if (_iedge < _gcell->getEastEdges().size()) break; // cdebug.log(110) << "Switching to North side." << endl; - _flags = Flags::NorthSide; - _iedge = 0; + _stateFlags = Flags::NorthSide; + _iedge = 0; // cdebug.log(110) << this << endl; continue; } - if (_flags.contains(Flags::NorthSide)) { + if ((_stateFlags & _filterFlags).contains(Flags::NorthSide)) { if (_iedge < _gcell->getNorthEdges().size()) break; // cdebug.log(110) << "Switching to West side." << endl; - _flags = Flags::WestSide; - _iedge = 0; + _stateFlags = Flags::WestSide; + _iedge = 0; // cdebug.log(110) << this << endl; continue; } - if (_flags.contains(Flags::WestSide)) { + if ((_stateFlags & _filterFlags).contains(Flags::WestSide)) { if (_iedge < _gcell->getWestEdges().size()) break; // cdebug.log(110) << "Switching to South side." << endl; - _flags = Flags::SouthSide; - _iedge = 0; + _stateFlags = Flags::SouthSide; + _iedge = 0; continue; } - if (_flags.contains(Flags::SouthSide)) { + if ((_stateFlags & _filterFlags).contains(Flags::SouthSide)) { if (_iedge < _gcell->getSouthEdges().size()) break; // cdebug.log(110) << "All edges done." << endl; - _flags = 0; - _iedge = 0; + _stateFlags = 0; + _iedge = 0; break;; } } - cdebug.log(110) << "GCell_Edges::Locator::progress() [to] " << _flags << " iedge:" << _iedge << endl; + cdebug.log(110) << "GCell_Edges::Locator::progress() [to] " << _stateFlags << " iedge:" << _iedge << endl; } string GCell_Edges::Locator::_getString () const { string s = "vcut( xcut ); } - UpdateSession::close(); + //UpdateSession::close(); return true; } diff --git a/anabatic/src/GraphicAnabaticEngine.cpp b/anabatic/src/GraphicAnabaticEngine.cpp index eb3d89a2..6a53e357 100644 --- a/anabatic/src/GraphicAnabaticEngine.cpp +++ b/anabatic/src/GraphicAnabaticEngine.cpp @@ -152,6 +152,31 @@ namespace Anabatic { } + void anabaticTest_5 ( AnabaticEngine* engine ) + { + Cell* cell = engine->getCell(); + + + cell->flattenNets( Cell::Flags::BuildRings ); + cell->createRoutingPadRings( Cell::Flags::BuildRings ); + + //DebugSession::addToTrace( cell->getNet("alu_out(3)") ); + DebugSession::addToTrace( cell->getNet("imuxe.not_aux2") ); + + UpdateSession::open(); + engine->getSouthWestGCell()->doGrid(); + + Dijkstra* dijkstra = new Dijkstra ( engine ); + for ( Net* net : cell->getNets() ) { + if (net->isPower() or net->isClock()) continue; + dijkstra->load( net ); + dijkstra->run(); + } + delete dijkstra; + UpdateSession::close(); + } + + // ------------------------------------------------------------------- // Class : "Anabatic::GraphicAnabaticEngine". @@ -304,7 +329,8 @@ namespace Anabatic { //anabaticTest_1( engine ); //anabaticTest_2( engine ); //anabaticTest_3( engine ); - anabaticTest_4( engine ); + //anabaticTest_4( engine ); + anabaticTest_5( engine ); if (_viewer) _viewer->emitCellChanged(); } diff --git a/anabatic/src/anabatic/Dijkstra.h b/anabatic/src/anabatic/Dijkstra.h index e455d3f6..721dbd1b 100644 --- a/anabatic/src/anabatic/Dijkstra.h +++ b/anabatic/src/anabatic/Dijkstra.h @@ -50,7 +50,7 @@ namespace Anabatic { static void notify ( Vertex*, unsigned flags ); public: inline Vertex ( GCell* ); - inline Vertex ( size_t id ); + //inline Vertex ( size_t id ); inline ~Vertex (); inline unsigned int getId () const; inline GCell* getGCell () const; @@ -92,19 +92,18 @@ namespace Anabatic { , _distance(unreached) , _from (NULL) { - //gcell->setLookup( this ); gcell->setObserver( GCell::Observable::Vertex, &_observer ); } - inline Vertex::Vertex ( size_t id ) - : _id (id) - , _gcell (NULL) - , _observer((Vertex*)0x1) // To trick the NULL detection. - , _connexId(-1) - , _stamp (-1) - , _distance(unreached) - , _from (NULL) - { } + // inline Vertex::Vertex ( size_t id ) + // : _id (id) + // , _gcell (NULL) + // , _observer((Vertex*)0x1) // To trick the NULL detection. + // , _connexId(-1) + // , _stamp (-1) + // , _distance(unreached) + // , _from (NULL) + // { } inline Vertex::~Vertex () { } inline unsigned int Vertex::getId () const { return _id; } @@ -165,11 +164,22 @@ namespace Anabatic { inline bool PriorityQueue::empty () const { return _queue.empty(); } inline size_t PriorityQueue::size () const { return _queue.size(); } inline void PriorityQueue::push ( Vertex* v ) { _queue.insert(v); } - inline void PriorityQueue::erase ( Vertex* v ) { _queue.erase(v); } inline Vertex* PriorityQueue::top () { return _queue.empty() ? NULL : *_queue.begin(); } - inline void PriorityQueue::pop () { _queue.erase(_queue.begin()); } inline void PriorityQueue::clear () { _queue.clear(); } + inline void PriorityQueue::pop () + { + cdebug.log(111) << "Pop: (size:" << _queue.size() << ") " << *_queue.begin() << std::endl; + _queue.erase(_queue.begin()); + } + + inline void PriorityQueue::erase ( Vertex* v ) + { + for ( auto ivertex = _queue.begin() ; ivertex != _queue.end() ; ++ivertex ) { + if (*ivertex == v) { _queue.erase( ivertex ); break; } + } + } + inline void PriorityQueue::dump () const { if (cdebug.enabled(111)) { @@ -187,20 +197,40 @@ namespace Anabatic { class Dijkstra { public: - Dijkstra ( AnabaticEngine* ); - ~Dijkstra (); + // Mode sub-classe. + class Mode : public Hurricane::BaseFlags { + public: + enum Flag { NoMode = 0 + , Standart = (1<<0) + , Monotonic = (1<<1) + }; + public: + inline Mode ( unsigned int flags=NoMode ); + inline Mode ( BaseFlags ); + virtual ~Mode (); + virtual std::string _getTypeName () const; + virtual std::string _getString () const; + }; + public: - void load ( Net* ); - void run (); - bool propagate (); - void selectFirstSource (); - void toWires (); + float getDistance ( const Vertex*, const Vertex*, const Edge* ); + public: + Dijkstra ( AnabaticEngine* ); + ~Dijkstra (); + public: + inline bool isBipoint () const; + void load ( Net* ); + void run ( Mode mode=Mode::Standart ); private: - Dijkstra ( const Dijkstra& ); - Dijkstra& operator= ( const Dijkstra& ); + Dijkstra ( const Dijkstra& ); + Dijkstra& operator= ( const Dijkstra& ); + bool _propagate ( Flags enabledSides ); + void _selectFirstSource (); + void _toWires (); private: AnabaticEngine* _anabatic; vector _vertexes; + Mode _mode; Net* _net; int _stamp; VertexSet _sources; @@ -211,10 +241,17 @@ 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); } + + } // Anabatic namespace. GETSTRING_POINTER_SUPPORT(Anabatic::Vertex); IOSTREAM_POINTER_SUPPORT(Anabatic::Vertex); +INSPECTOR_PV_SUPPORT(Anabatic::Dijkstra::Mode); #endif // ANABATIC_DIJKSTRA_H diff --git a/anabatic/src/anabatic/Edges.h b/anabatic/src/anabatic/Edges.h index 347d61c7..bd24b229 100644 --- a/anabatic/src/anabatic/Edges.h +++ b/anabatic/src/anabatic/Edges.h @@ -58,7 +58,7 @@ namespace Anabatic { // Sub-Class: Locator. class Locator : public EdgesHL { public: - Locator ( const GCell* gcell ); + Locator ( const GCell* gcell, Flags filterFlags ); inline Locator ( const Locator& ); virtual Edge* getElement () const; virtual EdgesHL* getClone () const; @@ -67,41 +67,46 @@ namespace Anabatic { virtual string _getString () const; protected: const GCell* _gcell; - Flags _flags; + Flags _stateFlags; + Flags _filterFlags; size_t _iedge; }; // GCell_Edges. public: - inline GCell_Edges ( const GCell* gcell ); + inline GCell_Edges ( const GCell* gcell, Flags filterFlags=Flags::AllSides ); inline GCell_Edges ( const GCell_Edges& ); virtual EdgesHC* getClone () const; virtual EdgesHL* getLocator () const; virtual string _getString () const; protected: const GCell* _gcell; + Flags _filterFlags; }; inline GCell_Edges::Locator::Locator ( const Locator &locator ) : EdgesHL() - , _gcell(locator._gcell) - , _flags(locator._flags) - , _iedge(locator._iedge) + , _gcell (locator._gcell) + , _stateFlags (locator._stateFlags) + , _filterFlags(locator._filterFlags) + , _iedge (locator._iedge) { // cdebug.log(110) << "GCell_Edges::Locator::Locator(const Locator&)" << std::endl; } - inline GCell_Edges::GCell_Edges ( const GCell* gcell ) + inline GCell_Edges::GCell_Edges ( const GCell* gcell, Flags filterFlags ) : EdgesHC() - , _gcell(gcell) + , _gcell (gcell) + , _filterFlags(filterFlags) { } inline GCell_Edges::GCell_Edges ( const GCell_Edges& edges ) : EdgesHC() - , _gcell(edges._gcell) + , _gcell (edges._gcell) + , _filterFlags(edges._filterFlags) { }