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.
This commit is contained in:
Jean-Paul Chaput 2016-06-10 18:27:06 +02:00
parent 23d6ae55fd
commit c5a9e0b617
6 changed files with 243 additions and 101 deletions

View File

@ -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<Vertex>(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<Vertex>(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;

View File

@ -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 = "<GCell_Edges::Locator";
if (_flags.contains(Flags::EastSide )) s += " East[" + getString(_iedge) + "]";
if (_flags.contains(Flags::NorthSide)) s += " North[" + getString(_iedge) + "]";
if (_flags.contains(Flags::WestSide )) s += " West[" + getString(_iedge) + "]";
if (_flags.contains(Flags::SouthSide)) s += " South[" + getString(_iedge) + "]";
if (_flags == 0) s += " invalid";
if (_stateFlags.contains(Flags::EastSide )) s += " East[" + getString(_iedge) + "]";
if (_stateFlags.contains(Flags::NorthSide)) s += " North[" + getString(_iedge) + "]";
if (_stateFlags.contains(Flags::WestSide )) s += " West[" + getString(_iedge) + "]";
if (_stateFlags.contains(Flags::SouthSide)) s += " South[" + getString(_iedge) + "]";
if (_stateFlags == 0) s += " invalid";
s += ">";
return s;
}
@ -123,7 +124,7 @@ namespace Anabatic {
EdgesHL* GCell_Edges::getLocator () const
{ return new Locator (_gcell); }
{ return new Locator (_gcell,_filterFlags); }
string GCell_Edges::_getString () const

View File

@ -395,7 +395,7 @@ namespace Anabatic {
return false;
}
UpdateSession::open();
//UpdateSession::open();
GCell* row = this;
GCell* column = NULL;
@ -414,7 +414,7 @@ namespace Anabatic {
column = column->vcut( xcut );
}
UpdateSession::close();
//UpdateSession::close();
return true;
}

View File

@ -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();
}

View File

@ -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<Vertex>( 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<Vertex*> _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

View File

@ -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)
{ }