2016-05-30 04:30:29 -05:00
|
|
|
// -*- mode: C++; explicit-buffer-name: "Dijkstra.cpp<anabatic>" -*-
|
|
|
|
//
|
|
|
|
// 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 : "./anabatic/Dijkstra.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <limits>
|
|
|
|
#include "hurricane/Error.h"
|
|
|
|
#include "hurricane/Net.h"
|
|
|
|
#include "hurricane/RoutingPad.h"
|
|
|
|
#include "hurricane/Horizontal.h"
|
|
|
|
#include "hurricane/Vertical.h"
|
|
|
|
#include "hurricane/UpdateSession.h"
|
2016-06-10 11:27:06 -05:00
|
|
|
#include "hurricane/DebugSession.h"
|
2016-06-17 06:09:34 -05:00
|
|
|
#include "crlcore/Utilities.h"
|
2016-05-30 04:30:29 -05:00
|
|
|
#include "anabatic/AnabaticEngine.h"
|
|
|
|
#include "anabatic/Dijkstra.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace Anabatic {
|
|
|
|
|
|
|
|
using std::cerr;
|
|
|
|
using std::endl;
|
|
|
|
using std::numeric_limits;
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
using Hurricane::ForEachIterator;
|
2016-05-30 04:30:29 -05:00
|
|
|
using Hurricane::Error;
|
|
|
|
using Hurricane::Component;
|
|
|
|
using Hurricane::Horizontal;
|
|
|
|
using Hurricane::Vertical;
|
|
|
|
using Hurricane::RoutingPad;
|
|
|
|
using Hurricane::UpdateSession;
|
2016-06-10 11:27:06 -05:00
|
|
|
using Hurricane::DebugSession;
|
2016-05-30 04:30:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Anabatic::Vertex".
|
|
|
|
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
DbU::Unit Vertex::unreached = std::numeric_limits<long>::max();
|
2016-05-30 04:30:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::hasValidStamp () const
|
|
|
|
{ return _stamp == getAnabatic()->getStamp(); }
|
|
|
|
|
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
string Vertex::_getString () const
|
|
|
|
{
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
if (not _gcell) {
|
|
|
|
string s = "<Vertex [key] " + getString(_id) + ">";
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
string s = "<Vertex " + getString(_id)
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
+ " @(" + DbU::getValueString(_gcell->getXMin())
|
|
|
|
+ "," + DbU::getValueString(_gcell->getYMin()) + ")"
|
2016-05-30 11:52:38 -05:00
|
|
|
+ " connexId:" + getString(_connexId)
|
2016-06-17 06:09:34 -05:00
|
|
|
+ " d:" + ((_distance == unreached) ? "unreached" : DbU::getValueString(_distance) )
|
|
|
|
+ "+" + getString(_branchId)
|
2016-06-03 10:29:22 -05:00
|
|
|
+ " stamp:" + (hasValidStamp() ? "valid" : "outdated")
|
|
|
|
+ " from:" + ((_from) ? "set" : "NULL")
|
2016-05-30 11:52:38 -05:00
|
|
|
+ ">";
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-03 10:29:22 -05:00
|
|
|
void Vertex::notify ( Vertex* vertex, unsigned int flags )
|
|
|
|
{
|
|
|
|
//Vertex* vertex = getOwner();
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << "Vertex::notify() " << vertex << endl;
|
2016-06-03 10:29:22 -05:00
|
|
|
// Take into account the GCell modification here.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Anabatic::Dijkstra".
|
|
|
|
|
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
DbU::Unit Dijkstra::_distance ( const Vertex* a, const Vertex* b, const Edge* e )
|
2016-06-10 11:27:06 -05:00
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
DbU::Unit distance = a->getDistance() + e->getDistance();
|
2016-06-10 11:27:06 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
// Edge* aFrom = a->getFrom();
|
|
|
|
// if (aFrom) {
|
|
|
|
// distance += (aFrom->isHorizontal() xor e->isHorizontal()) ? 3.0 : 0.0;
|
|
|
|
// }
|
2016-06-10 11:27:06 -05:00
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-17 09:26:27 -05:00
|
|
|
bool Dijkstra::isRestricted ( const Vertex* v1, const Vertex* v2 ) const
|
|
|
|
{
|
|
|
|
bool restricted = true;
|
|
|
|
GCell* c1 = v1->getGCell();
|
|
|
|
GCell* c2 = v2->getGCell();
|
|
|
|
|
|
|
|
// Check from GCell 1
|
|
|
|
if ( c1->isNorth(c2) ) {
|
|
|
|
if ( !v1->isNRestricted() ) restricted = false;
|
|
|
|
} else if ( c1->isSouth(c2) ) {
|
|
|
|
if ( !v1->isSRestricted() ) restricted = false;
|
|
|
|
} else if ( c1->isEast (c2) ) {
|
|
|
|
if ( !v1->isERestricted() ) restricted = false;
|
|
|
|
} else if ( c1->isWest (c2) ) {
|
|
|
|
if ( !v1->isWRestricted() ) restricted = false;
|
|
|
|
} else {
|
|
|
|
cerr << Error( "GCells are not side by side." ) << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (restricted) return true;
|
|
|
|
else {
|
|
|
|
// Check from GCell 2
|
|
|
|
if ( c2->isNorth(c1) ) {
|
|
|
|
if ( v2->isNRestricted() ) return true;
|
|
|
|
else return false;
|
|
|
|
} else if ( c2->isSouth(c1) ) {
|
|
|
|
if ( v2->isSRestricted() ) return true;
|
|
|
|
else return false;
|
|
|
|
} else if ( c2->isEast (c1) ) {
|
|
|
|
if ( v2->isERestricted() ) return true;
|
|
|
|
else return false;
|
|
|
|
} else if ( c2->isWest (c1) ) {
|
|
|
|
if ( v2->isWRestricted() ) return true;
|
|
|
|
else return false;
|
|
|
|
} else {
|
|
|
|
cerr << Error( "GCells are not side by side." ) << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
Dijkstra::Dijkstra ( AnabaticEngine* anabatic )
|
|
|
|
: _anabatic (anabatic)
|
|
|
|
, _vertexes ()
|
2016-06-17 06:09:34 -05:00
|
|
|
, _distanceCb (_distance)
|
2016-06-10 11:27:06 -05:00
|
|
|
, _mode (Mode::Standart)
|
2016-05-30 04:30:29 -05:00
|
|
|
, _net (NULL)
|
|
|
|
, _stamp (-1)
|
|
|
|
, _sources ()
|
|
|
|
, _targets ()
|
|
|
|
, _searchArea ()
|
|
|
|
, _connectedsId(-1)
|
|
|
|
, _queue ()
|
|
|
|
{
|
|
|
|
const vector<GCell*>& gcells = _anabatic->getGCells();
|
|
|
|
for ( GCell* gcell : gcells ) {
|
|
|
|
_vertexes.push_back( new Vertex (gcell) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dijkstra::~Dijkstra ()
|
|
|
|
{
|
|
|
|
for ( Vertex* vertex : _vertexes ) delete vertex;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Dijkstra::load ( Net* net )
|
|
|
|
{
|
2016-05-30 11:52:38 -05:00
|
|
|
_net = net;
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
DebugSession::open( _net, 112, 120 );
|
|
|
|
cdebug_log(112,1) << "Dijkstra::load() " << _net << endl;
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
_sources.clear();
|
|
|
|
_targets.clear();
|
2016-05-30 04:30:29 -05:00
|
|
|
_searchArea.makeEmpty();
|
|
|
|
_stamp = _anabatic->incStamp();
|
|
|
|
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
vector<RoutingPad*> 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 );
|
2016-05-30 04:30:29 -05:00
|
|
|
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
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()
|
|
|
|
, getString(_net).c_str()
|
|
|
|
) << endl;
|
|
|
|
continue;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
_searchArea.merge( gcell->getBoundingBox() );
|
2016-05-30 04:30:29 -05:00
|
|
|
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
Vertex* vertex = gcell->getObserver<Vertex>(GCell::Observable::Vertex);
|
|
|
|
if (vertex->getConnexId() < 0) {
|
2016-06-17 06:09:34 -05:00
|
|
|
vertex->setDistance( Vertex::unreached );
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
vertex->setStamp ( _stamp );
|
|
|
|
vertex->setConnexId( _targets.size() );
|
2016-06-17 06:09:34 -05:00
|
|
|
vertex->setBranchId( 0 );
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
vertex->setFrom ( NULL );
|
|
|
|
_targets.insert( vertex );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(112,0) << "Add Vertex: " << vertex << endl;
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
2016-06-10 11:27:06 -05:00
|
|
|
|
|
|
|
Contact* gcontact = vertex->getGContact( _net );
|
|
|
|
rp->getBodyHook()->detach();
|
|
|
|
rp->getBodyHook()->attach( gcontact->getBodyHook() );
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(112,0) << "Search area: " << _searchArea << endl;
|
|
|
|
cdebug_tabw(112,-1);
|
2016-06-10 11:27:06 -05:00
|
|
|
DebugSession::close();
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
void Dijkstra::_selectFirstSource ()
|
2016-05-30 04:30:29 -05:00
|
|
|
{
|
|
|
|
if (_targets.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
#if 0
|
|
|
|
cparanoid << Error( "Dijkstra::_selectFirstSource(): %s has no vertexes to route, ignored."
|
|
|
|
, getString(_net).c_str()
|
|
|
|
) << endl;
|
|
|
|
#endif
|
2016-05-30 04:30:29 -05:00
|
|
|
return;
|
|
|
|
}
|
2016-06-10 11:27:06 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
_targets.erase ( firstSource );
|
|
|
|
_sources.insert( firstSource );
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(112,0) << "Dijkstra::_selectFirstSource() " << *_sources.begin() << endl;
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
bool Dijkstra::_propagate ( Flags enabledSides )
|
2016-05-30 04:30:29 -05:00
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(112,1) << "Dijkstra::_propagate() " << _net << endl;
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
while ( not _queue.empty() ) {
|
2016-05-30 11:52:38 -05:00
|
|
|
_queue.dump();
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
Vertex* current = _queue.top();
|
|
|
|
_queue.pop();
|
|
|
|
|
|
|
|
if ((current->getConnexId() == _connectedsId) or (current->getConnexId() < 0)) {
|
|
|
|
for ( Edge* edge : current->getGCell()->getEdges() ) {
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
if (edge == current->getFrom()) continue;
|
|
|
|
|
|
|
|
GCell* gneighbor = edge->getOpposite(current->getGCell());
|
2016-06-03 10:29:22 -05:00
|
|
|
Vertex* vneighbor = gneighbor->getObserver<Vertex>(GCell::Observable::Vertex);
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
if (not _searchArea.contains(vneighbor->getCenter())) continue;
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << "| Edge " << edge << endl;
|
|
|
|
cdebug_log(111,0) << "+ Neighbor: " << vneighbor << endl;
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
DbU::Unit distance = _distanceCb( current, vneighbor, edge );
|
2016-06-10 11:27:06 -05:00
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
if (vneighbor->getConnexId() == _connectedsId) continue;
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
if ( (distance < vneighbor->getDistance())
|
|
|
|
or ( (distance == vneighbor->getDistance())
|
|
|
|
and (current->getBranchId() > vneighbor->getBranchId())) ) {
|
2016-06-10 11:27:06 -05:00
|
|
|
if (vneighbor->getDistance() != Vertex::unreached) {
|
|
|
|
_queue.erase( vneighbor );
|
|
|
|
} else {
|
2016-06-17 06:09:34 -05:00
|
|
|
if (not vneighbor->hasValidStamp()) {
|
|
|
|
vneighbor->setConnexId( -1 );
|
|
|
|
vneighbor->setStamp ( _stamp );
|
|
|
|
}
|
Anabatic transient commit 6 "Somatoline, ca marche!".
* Bug: In Anabatic:
- In Dijktra::load(), do not create Contact while looping over the Net's
components (for RoutingPads).
- In Dijkstra::propagate(), reset the connexId of reached Vertexes
on updating the stamp to avoid using connexId from previous runs.
Push the vertexes on the queue while backtracking (with a distance
of 0.0). Do not reset the "_from" as we need it in Dijkstra::toWires()
to know how were the routing is.
- In Edge::getDistance(), convert to float more early so the normalisation
do not always end up in zero.
- In GCell::_add(), when the axis of the new edge is equal to one already
on the given side, adds it *after* the existing edge and not before.
(to be coherent with the way GCells are split in two)
- In GCell::hcut() and GCell::vcut(), create an Edge if is equal to X/Y Max,
*but* the new chunk is flat. The new chunk is then expected to expand
"below".
- In GraphicsAnabaticEngine::drawGCell(), display the id of the GCell in
a small box at the center of it's bounding box. Nothing displayed for
flat GCells, to avoid cluttering.
2016-06-05 11:38:09 -05:00
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
vneighbor->setBranchId( current->getBranchId() );
|
2016-05-30 04:30:29 -05:00
|
|
|
vneighbor->setDistance( distance );
|
2016-05-30 11:52:38 -05:00
|
|
|
vneighbor->setFrom ( edge );
|
2016-05-30 04:30:29 -05:00
|
|
|
_queue.push( vneighbor );
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << "Push: (size:" << _queue.size() << ") " << vneighbor << endl;
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
}
|
2016-05-30 11:52:38 -05:00
|
|
|
|
|
|
|
continue;
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// We did reach another target (different <connexId>).
|
2016-06-17 06:09:34 -05:00
|
|
|
// Tag back the path, with a higher <branchId>.
|
2016-06-17 10:45:32 -05:00
|
|
|
_traceback( current );
|
2016-05-30 11:52:38 -05:00
|
|
|
return true;
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
2016-05-30 11:52:38 -05:00
|
|
|
|
|
|
|
cerr << Error( "Dijkstra::propagate(): %s has unreachable targets."
|
|
|
|
, getString(_net).c_str()
|
|
|
|
) << endl;
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(112,-1);
|
2016-05-30 11:52:38 -05:00
|
|
|
return false;
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-17 10:45:32 -05:00
|
|
|
void Dijkstra::_traceback ( Vertex* current )
|
|
|
|
{
|
|
|
|
cdebug_log(112,1) << "Dijkstra::_traceback() " << _net << " branchId:" << _sources.size() << endl;
|
|
|
|
|
|
|
|
int branchId = _sources.size();
|
|
|
|
_targets.erase( current );
|
|
|
|
|
|
|
|
while ( current ) {
|
|
|
|
cdebug_log(112,0) << "| " << current << endl;
|
|
|
|
if (current->getConnexId() == _connectedsId) break;
|
|
|
|
|
|
|
|
Edge* from = current->getFrom();
|
|
|
|
if (not from) break;
|
|
|
|
from->incRealOccupancy( 1 );
|
|
|
|
|
|
|
|
_sources.insert( current );
|
|
|
|
current->setDistance( 0.0 );
|
|
|
|
current->setConnexId( _connectedsId );
|
|
|
|
current->setBranchId( branchId );
|
|
|
|
_queue.push( current );
|
|
|
|
|
|
|
|
Vertex* source = current;
|
|
|
|
Vertex* target = source->getPredecessor();
|
|
|
|
current = target;
|
|
|
|
|
|
|
|
if ( (source->getGCell()->getXMin() > target->getGCell()->getXMin())
|
|
|
|
or (source->getGCell()->getYMin() > target->getGCell()->getYMin()) )
|
|
|
|
std::swap( source, target );
|
|
|
|
|
|
|
|
Contact* sourceContact = source->getGContact( _net );
|
|
|
|
Contact* targetContact = target->getGContact( _net );
|
|
|
|
|
|
|
|
if (from->isHorizontal()) {
|
|
|
|
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)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_tabw(112,-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
void Dijkstra::run ( Dijkstra::Mode mode )
|
2016-05-30 04:30:29 -05:00
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
DebugSession::open( _net, 112, 120 );
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(112,1) << "Dijkstra::run() on " << _net << " mode:" << mode << endl;
|
2016-06-10 11:27:06 -05:00
|
|
|
_mode = mode;
|
|
|
|
|
|
|
|
_selectFirstSource();
|
2016-05-30 11:52:38 -05:00
|
|
|
if (_sources.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(112,0) << "No source to start, not routed." << endl;
|
|
|
|
cdebug_tabw(112,-1);
|
2016-05-30 11:52:38 -05:00
|
|
|
return;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
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;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
Vertex* source = *_sources.begin();
|
2016-05-30 04:30:29 -05:00
|
|
|
_queue.clear();
|
2016-05-30 11:52:38 -05:00
|
|
|
_queue.push( source );
|
|
|
|
_connectedsId = source->getConnexId();
|
|
|
|
source->setDistance( 0.0 );
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(112,0) << "Push source: (size:" << _queue.size() << ") "
|
2016-05-30 11:52:38 -05:00
|
|
|
<< source
|
|
|
|
<< " _connectedsId:" << _connectedsId << endl;
|
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
while ( not _targets.empty() and _propagate(enabledEdges) );
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
_queue.clear();
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(112,-1);
|
2016-06-10 11:27:06 -05:00
|
|
|
DebugSession::close();
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // Anabatic namespace.
|