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>
|
2017-02-14 08:47:22 -06:00
|
|
|
#include <algorithm>
|
2016-05-30 04:30:29 -05:00
|
|
|
#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"
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
#include "hurricane/DataBase.h"
|
|
|
|
#include "hurricane/viewer/CellViewer.h"
|
|
|
|
#include "hurricane/Technology.h"
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
|
|
|
|
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;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
using Hurricane::Segment;
|
2016-05-30 04:30:29 -05:00
|
|
|
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
|
|
|
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Anabatic::IntervalC".
|
|
|
|
|
|
|
|
|
|
|
|
IntervalC::IntervalC()
|
|
|
|
{
|
|
|
|
_min = Vertex::unreached;
|
|
|
|
_max = Vertex::unreached;
|
|
|
|
_axis = Vertex::unreached;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IntervalC::~IntervalC() {}
|
|
|
|
|
|
|
|
|
|
|
|
IntervalC* IntervalC::create()
|
|
|
|
{
|
|
|
|
return new IntervalC();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void IntervalC::set ( DbU::Unit min, DbU::Unit max, DbU::Unit axis )
|
|
|
|
{
|
|
|
|
_min = min;
|
|
|
|
_max = max;
|
|
|
|
_axis = axis;
|
|
|
|
setiSet();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void IntervalC::setRange( DbU::Unit vmin, DbU::Unit vmax )
|
|
|
|
{
|
|
|
|
if (vmin < vmax){
|
|
|
|
_min = vmin;
|
|
|
|
_max = vmax;
|
|
|
|
setiSet();
|
|
|
|
} else {
|
|
|
|
_min = vmax;
|
|
|
|
_max = vmin;
|
|
|
|
setiSet();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void IntervalC::extendMin( DbU::Unit vmin )
|
|
|
|
{
|
|
|
|
if (_min > vmin) _min = vmin;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void IntervalC::extendMax( DbU::Unit vmax )
|
|
|
|
{
|
|
|
|
if (_max < vmax) _max = vmax;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IntervalC::print() const
|
|
|
|
{
|
|
|
|
cerr << "[IntervalC]: min: " << DbU::getValueString(_min) << ", max:" << DbU::getValueString(_min) << ", axis:" << DbU::getValueString(_axis) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void IntervalC::reset()
|
|
|
|
{
|
|
|
|
_min = Vertex::unreached;
|
|
|
|
_max = Vertex::unreached;
|
|
|
|
_axis = Vertex::unreached;
|
|
|
|
_flags &= ~iSet;
|
|
|
|
}
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Anabatic::Vertex".
|
|
|
|
|
|
|
|
|
2016-09-30 11:09:05 -05:00
|
|
|
DbU::Unit Vertex::unreached = std::numeric_limits<long>::max();
|
2016-06-20 11:36:00 -05:00
|
|
|
DbU::Unit Vertex::unreachable = std::numeric_limits<long>::max()-1;
|
2016-05-30 04:30:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::hasValidStamp () const
|
|
|
|
{ return _stamp == getAnabatic()->getStamp(); }
|
|
|
|
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
/*void Vertex::setPathPoint( DbU::Unit x, DbU::Unit y )
|
2016-12-22 04:21:25 -06:00
|
|
|
{
|
|
|
|
_xpath = x;
|
|
|
|
_ypath = y;
|
2017-02-14 08:47:22 -06:00
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::hasRP( Net* net ) const
|
|
|
|
{
|
|
|
|
if (getGCell() != NULL ){
|
|
|
|
Cell* cell = getGCell()->getAnabatic()->getCell();
|
|
|
|
RoutingPad* rp = NULL;
|
|
|
|
for ( Component* component : cell->getComponentsUnder(getGCell()->getBoundingBox().inflate(-1)) ){
|
|
|
|
rp = dynamic_cast<RoutingPad*>( component );
|
|
|
|
if (rp) {
|
|
|
|
if (rp->getNet() == net) return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::hasVRP( Net* net ) const
|
|
|
|
{
|
|
|
|
if (getGCell() != NULL){
|
|
|
|
Cell* cell = getGCell()->getAnabatic()->getCell();
|
|
|
|
RoutingPad* rp = NULL;
|
|
|
|
for ( Component* component : cell->getComponentsUnder(getGCell()->getBoundingBox().inflate(-1)) ){
|
|
|
|
rp = dynamic_cast<RoutingPad*>( component );
|
|
|
|
if (rp) {
|
|
|
|
if (rp->getNet() == net) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rp) {
|
|
|
|
Vertical* v = dynamic_cast<Vertical*>(rp->_getEntityAsSegment());
|
|
|
|
if (v) { return true; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::hasHRP( Net* net ) const
|
|
|
|
{
|
|
|
|
if (getGCell() != NULL){
|
|
|
|
Cell* cell = getGCell()->getAnabatic()->getCell();
|
|
|
|
RoutingPad* rp = NULL;
|
|
|
|
for ( Component* component : cell->getComponentsUnder(getGCell()->getBoundingBox().inflate(-1)) ){
|
|
|
|
rp = dynamic_cast<RoutingPad*>( component );
|
|
|
|
if (rp) {
|
|
|
|
if (rp->getNet() == net) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rp) {
|
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(rp->_getEntityAsSegment());
|
|
|
|
if (h) { return true; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::isRestricted ( const Vertex* v1, const Vertex* v2 )
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Point Vertex::getNextPathPoint2( const Vertex* vcurr, const Vertex* vnext )
|
|
|
|
{
|
|
|
|
//cdebug_log(112,0) << "Point Dijkstra::getNextPathPoint( const Vertex* current, const Vertex* next )" << endl;
|
|
|
|
if ((vcurr == NULL) || (vnext == NULL)){
|
|
|
|
//cdebug_log(112,0) << "Error(Point Dijkstra::_getNextPathPoint( const Vertex*, const Vertex* )): Unvalid NULL argument."<< endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vnext->getGCell()->isMatrix()) {
|
|
|
|
return Point(vnext->getGCell()->getXCenter(), vnext->getGCell()->getYCenter());
|
|
|
|
}
|
|
|
|
|
|
|
|
Point pcurr = vcurr->getPathPoint(vnext);
|
|
|
|
GCell* gnext = vnext->getGCell();
|
|
|
|
GCell* gcurr = vcurr->getGCell();
|
|
|
|
DbU::Unit x = 0;
|
|
|
|
DbU::Unit y = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (vnext->isV()){
|
|
|
|
//cdebug_log(112,0) << "Case next: Vertical: " << vnext->isiSet() << endl; //", d:" << vnext->getDistance() << endl;
|
|
|
|
if ((vnext->isiSet())&&(vnext->hasValidStamp())){
|
|
|
|
//cdebug_log(112,0) << "Case set" << endl;
|
|
|
|
x = vnext->getIAxis();
|
|
|
|
if (vcurr->isNorth(vnext)) y = vnext->getIMin();
|
|
|
|
else if (vcurr->isSouth(vnext)) y = vnext->getIMax();
|
|
|
|
else if ((vcurr->isWest(vnext))||(vcurr->isEast(vnext))) {
|
|
|
|
if ( pcurr.getY() > vnext->getIMax() ) y = vnext->getIMax();
|
|
|
|
else if ( pcurr.getY() < vnext->getIMin() ) y = vnext->getIMin();
|
|
|
|
else y = pcurr.getY();
|
|
|
|
} else cdebug_log(112,0) << "Error(Point Vertex::getNextPathPoint2(...) const: Something is wrong.1" << endl;
|
|
|
|
} else {
|
|
|
|
//cdebug_log(112,0) << "Case not set" << endl;
|
|
|
|
if (vcurr->isNorth(vnext)){
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin();
|
|
|
|
else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax();
|
|
|
|
else x = pcurr.getX();
|
|
|
|
} else if (vcurr->isSouth(vnext)){
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin();
|
|
|
|
else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax();
|
|
|
|
else x = pcurr.getX();
|
|
|
|
} else if (vcurr->isWest(vnext)){
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin();
|
|
|
|
else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax();
|
|
|
|
else y = pcurr.getY();
|
|
|
|
|
|
|
|
} else if (vcurr->isEast(vnext)){
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin();
|
|
|
|
else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax();
|
|
|
|
else y = pcurr.getY();
|
|
|
|
} else cdebug_log(112,0) << "Error(Point Vertex::getNextPathPoint2(...) const: Something is wrong.2" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (vnext->isH()) {
|
|
|
|
//cdebug_log(112,0) << "Case next: Horizontal: " << vnext->isiSet() << endl; //", d:" << vnext->getDistance() << endl;
|
|
|
|
|
|
|
|
if ((vnext->isiSet())&&(vnext->hasValidStamp())){
|
|
|
|
//cdebug_log(112,0) << "Case set" << endl;
|
|
|
|
y = vnext->getIAxis();
|
|
|
|
if (vcurr->isEast (vnext)) x = vnext->getIMin();
|
|
|
|
else if (vcurr->isWest (vnext)) x = vnext->getIMax();
|
|
|
|
else if ((vcurr->isNorth(vnext))||(vcurr->isSouth(vnext))) {
|
|
|
|
if ( pcurr.getX() > vnext->getIMax() ) x = vnext->getIMax();
|
|
|
|
else if ( pcurr.getX() < vnext->getIMin() ) x = vnext->getIMin();
|
|
|
|
else x = pcurr.getX();
|
|
|
|
} else cdebug_log(112,0) << "Error(Point Vertex::getNextPathPoint2(...) const: Something is wrong.3" << endl;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
//cdebug_log(112,0) << "Case not set" << endl;
|
|
|
|
if (vcurr->isNorth(vnext)){
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin();
|
|
|
|
else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax();
|
|
|
|
else x = pcurr.getX();
|
|
|
|
} else if (vcurr->isSouth(vnext)){
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin();
|
|
|
|
else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax();
|
|
|
|
else x = pcurr.getX();
|
|
|
|
} else if (vcurr->isWest(vnext)){
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin();
|
|
|
|
else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax();
|
|
|
|
else y = pcurr.getY();
|
|
|
|
|
|
|
|
} else if (vcurr->isEast(vnext)){
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin();
|
|
|
|
else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax();
|
|
|
|
else y = pcurr.getY();
|
|
|
|
} else cdebug_log(112,0) << "Error(Point Vertex::getNextPathPoint2(...) const: Something is wrong.4" << endl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getNextPathPoint2(...) const: Something is wrong.5" << endl;
|
|
|
|
}
|
|
|
|
return Point(x,y);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Point Vertex::getNextPathPoint( const Vertex* current, const Vertex* next )
|
|
|
|
{
|
|
|
|
//cdebug_log(112,0) << "Point Dijkstra::getNextPathPoint( const Vertex* current, const Vertex* next )" << endl;
|
|
|
|
if ((current == NULL) || (next == NULL)){
|
|
|
|
//cdebug_log(112,0) << "Error(Point Dijkstra::_getNextPathPoint( const Vertex*, const Vertex* )): Unvalid NULL argument."<< endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next->getGCell()->isMatrix()) return Point(next->getGCell()->getXCenter(), next->getGCell()->getYCenter());
|
|
|
|
if (next->getGCell()->isDevice()) return next->getPathPoint();
|
|
|
|
|
|
|
|
|
|
|
|
//cdebug_log(112,0) << "getBranchId() :" << current->getBranchId() << endl;
|
|
|
|
//cdebug_log(112,0) << "curr hasvalidstamp:" << current->hasValidStamp() << endl;
|
|
|
|
//cdebug_log(112,0) << "next hasvalidstamp:" << next->hasValidStamp() << endl;
|
|
|
|
//if ( ((current->getBranchId() != 0))||(current->getDistance() != 0)||(current->getGCell()->isDevice())){
|
|
|
|
//cdebug_log(112,0) << "Case: distance > 0 OR isDevice" << endl;
|
|
|
|
if (current->isNorth(next)) {
|
|
|
|
//cdebug_log(112,0) << "North" << endl;
|
|
|
|
if ( current->getXPath() < next->getGCell()->getXMin() )
|
|
|
|
return Point(next->getGCell()->getXMin(), next->getGCell()->getYMin());
|
|
|
|
else if ( current->getXPath() > next->getGCell()->getXMax() )
|
|
|
|
return Point(next->getGCell()->getXMax(), next->getGCell()->getYMin());
|
|
|
|
else
|
|
|
|
return Point(current->getXPath(), next->getGCell()->getYMin());
|
|
|
|
|
|
|
|
} else if (current->isSouth(next)) {
|
|
|
|
//cdebug_log(112,0) << "South" << endl;
|
|
|
|
if ( current->getXPath() < next->getGCell()->getXMin() )
|
|
|
|
return Point(next->getGCell()->getXMin(), next->getGCell()->getYMax());
|
|
|
|
else if ( current->getXPath() > next->getGCell()->getXMax() )
|
|
|
|
return Point(next->getGCell()->getXMax(), next->getGCell()->getYMax());
|
|
|
|
else
|
|
|
|
return Point(current->getXPath(), next->getGCell()->getYMax());
|
|
|
|
|
|
|
|
} else if (current->isEast (next)) {
|
|
|
|
//cdebug_log(112,0) << "East" << endl;
|
|
|
|
if ( current->getYPath() < next->getGCell()->getYMin() )
|
|
|
|
return Point(next->getGCell()->getXMin(), next->getGCell()->getYMin());
|
|
|
|
else if ( current->getYPath() > next->getGCell()->getYMax() )
|
|
|
|
return Point(next->getGCell()->getXMin(), next->getGCell()->getYMax());
|
|
|
|
else
|
|
|
|
return Point(next->getGCell()->getXMin(), current->getYPath());
|
|
|
|
|
|
|
|
} else if (current->isWest (next)) {
|
|
|
|
//cdebug_log(112,0) << "West" << endl;
|
|
|
|
if ( current->getYPath() < next->getGCell()->getYMin() )
|
|
|
|
return Point(next->getGCell()->getXMax(), next->getGCell()->getYMin());
|
|
|
|
else if ( current->getYPath() > next->getGCell()->getYMax() )
|
|
|
|
return Point(next->getGCell()->getXMax(), next->getGCell()->getYMax());
|
|
|
|
else
|
|
|
|
return Point(next->getGCell()->getXMax(), current->getYPath());
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::_getNextPathPoint( const Vertex*, const Vertex* )): GCells are not next to each other." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Case: distance = 0 AND isNOTDevice" << endl;
|
|
|
|
if (current->isNorth(next)) {
|
|
|
|
cdebug_log(112,0) << "North" << endl;
|
|
|
|
return Point( ( std::max(current->getGCell()->getXMin()
|
|
|
|
, next->getGCell()->getXMin()
|
|
|
|
)
|
|
|
|
+ std::min(current->getGCell()->getXMax()
|
|
|
|
, next->getGCell()->getXMax()
|
|
|
|
)
|
|
|
|
)/2
|
|
|
|
, next->getGCell()->getYMin()
|
|
|
|
);
|
|
|
|
} else if (current->isSouth(next)) {
|
|
|
|
cdebug_log(112,0) << "South" << endl;
|
|
|
|
return Point( ( std::max(current->getGCell()->getXMin()
|
|
|
|
, next->getGCell()->getXMin() )
|
|
|
|
+ std::min(current->getGCell()->getXMax()
|
|
|
|
, next->getGCell()->getXMax() )
|
|
|
|
)/2
|
|
|
|
, next->getGCell()->getYMax()
|
|
|
|
);
|
|
|
|
} else if (current->isEast (next)) {
|
|
|
|
cdebug_log(112,0) << "East" << endl;
|
|
|
|
return Point( next->getGCell()->getXMin(), ( std::max(current->getGCell()->getYMin()
|
|
|
|
, next->getGCell()->getYMin() )
|
|
|
|
+ std::min(current->getGCell()->getYMax()
|
|
|
|
, next->getGCell()->getYMax() )
|
|
|
|
)/2
|
|
|
|
);
|
|
|
|
} else if (current->isWest (next)) {
|
|
|
|
cdebug_log(112,0) << "West" << endl;
|
|
|
|
return Point( next->getGCell()->getXMin(), ( std::max(current->getGCell()->getYMin()
|
|
|
|
, next->getGCell()->getYMin() )
|
|
|
|
+ std::min(current->getGCell()->getYMax()
|
|
|
|
, next->getGCell()->getYMax() )
|
|
|
|
)/2
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Dijkstra::_getNextPathPoint( const Vertex*, const Vertex* )): GCells are not next to each other." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
/*void Vertex::resetPathPoint( Point ponderedPoint )
|
|
|
|
{
|
|
|
|
DbU::Unit x;
|
|
|
|
DbU::Unit y;
|
|
|
|
GCell* g = getGCell();
|
|
|
|
|
|
|
|
if (ponderedPoint.getX() < g->getXMin()) x = g->getXMin();
|
|
|
|
else if (ponderedPoint.getX() > g->getXMax()) x = g->getXMax();
|
|
|
|
else x = ponderedPoint.getX();
|
|
|
|
if (ponderedPoint.getY() < g->getYMin()) y = g->getYMin();
|
|
|
|
else if (ponderedPoint.getY() > g->getYMax()) y = g->getYMax();
|
|
|
|
else y = ponderedPoint.getY();
|
|
|
|
setPathPoint(x,y);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
Point Vertex::getPathPoint( const Vertex* next ) const
|
|
|
|
{
|
|
|
|
//cdebug_log(112,0) << "Point Vertex::getPathPoint( const Vertex* next ) const" << endl;
|
|
|
|
|
|
|
|
GCell* gcurr = getGCell();
|
|
|
|
GCell* gnext = next->getGCell();
|
|
|
|
DbU::Unit x = 0;
|
|
|
|
DbU::Unit y = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (gcurr->isDevice ()){
|
|
|
|
//cdebug_log(112,0) << "Case device" << endl;
|
|
|
|
if (isH()){
|
|
|
|
//cdebug_log(112,0) << "hinterval: " << DbU::getValueString(_interv->getAxis()) << endl;
|
|
|
|
y = _interv->getAxis();
|
|
|
|
if ((gnext->getXMax() < gcurr->getXMin())||(isWest (next))) {
|
|
|
|
x = _interv->getMin();
|
|
|
|
}
|
|
|
|
else if ((gnext->getXMin() > gcurr->getXMax())||(isEast (next))) {
|
|
|
|
x = _interv->getMax();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
x = (max(gnext->getXMin(), gcurr->getXMin())+min(gnext->getXMax(), gcurr->getXMax()))/2 ;
|
|
|
|
}
|
|
|
|
} else if (isV()){
|
|
|
|
//cdebug_log(112,0) << "vinterval" << endl;
|
|
|
|
x = _interv->getAxis();
|
|
|
|
if ((gnext->getYMax() < gcurr->getYMin())||(isSouth(next))) y = _interv->getMin();
|
|
|
|
else if ((gnext->getYMin() > gcurr->getYMax())||(isNorth(next))) y = _interv->getMax();
|
|
|
|
else y = (max(gnext->getYMin(), gcurr->getYMin())+min(gnext->getYMax(), gcurr->getYMax()))/2 ;
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
} else if (isH()) {
|
|
|
|
//cdebug_log(112,0) << "Case horizontal" << endl;
|
|
|
|
GCell* gprev = getFrom()->getOpposite(gcurr);
|
|
|
|
Vertex* prev = gprev->getObserver<Vertex>(GCell::Observable::Vertex);
|
|
|
|
|
|
|
|
if (prev->isH()){
|
|
|
|
//cdebug_log(112,0) << "prev is H" << endl;
|
|
|
|
if (isNorth(prev)){
|
|
|
|
x = (max(_intervfrom->getMin(), gcurr->getXMin())+min(_intervfrom->getMax(), gcurr->getXMax()))/2 ;
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
} else if (isSouth(prev)){
|
|
|
|
x = (max(_intervfrom->getMin(), gcurr->getXMin())+min(_intervfrom->getMax(), gcurr->getXMax()))/2 ;
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
} else if (isWest (prev)){
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
y = _intervfrom->getAxis();
|
|
|
|
} else if (isEast (prev)){
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
y = _intervfrom->getAxis();
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
} else if (prev->isV()){
|
|
|
|
//cdebug_log(112,0) << "prev is V" << endl;
|
|
|
|
if (isNorth(prev)){
|
|
|
|
//cdebug_log(112,0) << "1" << endl;
|
|
|
|
x = _intervfrom->getAxis();
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
} else if (isSouth(prev)){
|
|
|
|
//cdebug_log(112,0) << "2" << endl;
|
|
|
|
x = _intervfrom->getAxis();
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
} else if (isWest (prev)){
|
|
|
|
//cdebug_log(112,0) << "3" << endl;
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
if ( _intervfrom->getMin() > gcurr->getYMax() ){
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
} else if ( _intervfrom->getMax() < gcurr->getYMin() ){
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
} else {
|
|
|
|
y = (max(_intervfrom->getMin(), gcurr->getYMin())+min(_intervfrom->getMax(), gcurr->getYMax()))/2 ;
|
|
|
|
}
|
|
|
|
} else if (isEast (prev)){
|
|
|
|
//cdebug_log(112,0) << "4" << endl;
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
if ( _intervfrom->getMin() > gcurr->getYMax() ){
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
} else if ( _intervfrom->getMax() < gcurr->getYMin() ){
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
} else {
|
|
|
|
y = (max(_intervfrom->getMin(), gcurr->getYMin())+min(_intervfrom->getMax(), gcurr->getYMax()))/2 ;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
//cdebug_log(112,0) << "x: " << DbU::getValueString(x) << ", y:" << DbU::getValueString(y) << endl;
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
} else if (isV()) {
|
|
|
|
//cdebug_log(112,0) << "Case V" << endl;
|
|
|
|
GCell* gprev = getFrom()->getOpposite(gcurr);
|
|
|
|
Vertex* prev = gprev->getObserver<Vertex>(GCell::Observable::Vertex);
|
|
|
|
|
|
|
|
if (prev->isH()){
|
|
|
|
//cdebug_log(112,0) << "prev is H" << endl;
|
|
|
|
if (isNorth(prev)){
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
if ( _intervfrom->getMin() > gcurr->getXMax() ){
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
} else if ( _intervfrom->getMax() < gcurr->getXMin() ){
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
} else {
|
|
|
|
x = (max(_intervfrom->getMin(), gcurr->getXMin())+min(_intervfrom->getMax(), gcurr->getXMax()))/2 ;
|
|
|
|
}
|
|
|
|
} else if (isSouth(prev)){
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
if ( _intervfrom->getMin() > gcurr->getXMax() ){
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
} else if ( _intervfrom->getMax() < gcurr->getXMin() ){
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
} else {
|
|
|
|
x = (max(_intervfrom->getMin(), gcurr->getXMin())+min(_intervfrom->getMax(), gcurr->getXMax()))/2 ;
|
|
|
|
}
|
|
|
|
} else if (isWest (prev)){
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
y = _intervfrom->getAxis();
|
|
|
|
} else if (isEast (prev)){
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
y = _intervfrom->getAxis();
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
} else if (prev->isV()){
|
|
|
|
//cdebug_log(112,0) << "prev is V" << endl;
|
|
|
|
if (isNorth(prev)){
|
|
|
|
x = _intervfrom->getAxis();
|
|
|
|
y = gcurr->getYMax();
|
|
|
|
} else if (isSouth(prev)){
|
|
|
|
x = _intervfrom->getAxis();
|
|
|
|
y = gcurr->getYMin();
|
|
|
|
} else if (isWest (prev)){
|
|
|
|
x = gcurr->getXMin();
|
|
|
|
y = (max(_intervfrom->getMin(), gcurr->getYMin())+min(_intervfrom->getMax(), gcurr->getYMax()))/2 ;
|
|
|
|
} else if (isEast (prev)){
|
|
|
|
x = gcurr->getXMax();
|
|
|
|
y = (max(_intervfrom->getMin(), gcurr->getYMin())+min(_intervfrom->getMax(), gcurr->getYMax()))/2 ;
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(Point Vertex::getPathPoint( Vertex * vertex ) const: Something is wrong." << endl;
|
|
|
|
return Point(0,0);
|
|
|
|
}
|
|
|
|
return Point(x,y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::isH() const
|
|
|
|
{
|
|
|
|
GCell* gcell = getGCell();
|
|
|
|
if (gcell->isDevice()) return _interv->isH();
|
|
|
|
else if (gcell->isHChannel()) return true;
|
|
|
|
else if (gcell->isStrut()) return gcell->getWidth() > gcell->getHeight();
|
|
|
|
else return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Vertex::isV() const
|
|
|
|
{
|
|
|
|
GCell* gcell = getGCell();
|
|
|
|
if (gcell->isDevice()) return _interv->isV();
|
|
|
|
else if (gcell->isVChannel()) return true;
|
|
|
|
else if (gcell->isStrut()) return gcell->getWidth() < gcell->getHeight();
|
|
|
|
else return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Vertex::setIntervals ( Vertex* vcurr )
|
|
|
|
{
|
|
|
|
Point pcurr = vcurr->getPathPoint(this);
|
|
|
|
Point pnext = Vertex::getNextPathPoint2( vcurr, this );
|
|
|
|
cdebug_log(112,0) << "void Vertex::setIntervals ( Vertex* vcurr )" << endl;
|
|
|
|
cdebug_log(112,0) << "Pcurrent : X:" << DbU::getValueString(pcurr.getX()) << ", Y:" << DbU::getValueString(pcurr.getY()) << endl;
|
|
|
|
cdebug_log(112,0) << "Pneighbour: X:" << DbU::getValueString(pnext.getX()) << ", Y:" << DbU::getValueString(pnext.getY()) << endl;
|
|
|
|
DbU::Unit min, max, axis;
|
|
|
|
|
|
|
|
if (vcurr->isH()){
|
|
|
|
cdebug_log(112,0) << "case vcurr: Horizontal" << endl;
|
|
|
|
if ((vcurr->isiSet())&&(vcurr->hasValidStamp())){
|
|
|
|
cdebug_log(112,0) << "case set" << endl;
|
|
|
|
if (vcurr->getIMin() > pnext.getX()) {
|
|
|
|
min = pnext.getX();
|
|
|
|
max = vcurr->getIMax();
|
|
|
|
axis = vcurr->getIAxis();
|
|
|
|
} else if (vcurr->getIMax() < pnext.getX()) {
|
|
|
|
min = vcurr->getIMin();
|
|
|
|
max = pnext.getX();
|
|
|
|
axis = vcurr->getIAxis();
|
|
|
|
} else {
|
|
|
|
min = vcurr->getIMin();
|
|
|
|
max = vcurr->getIMax();
|
|
|
|
axis = vcurr->getIAxis();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "case not set" << endl;
|
|
|
|
axis = pcurr.getY();
|
|
|
|
if (pcurr.getX() < pnext.getX()){
|
|
|
|
min = pcurr.getX();
|
|
|
|
max = pnext.getX();
|
|
|
|
} else {
|
|
|
|
max = pcurr.getX();
|
|
|
|
min = pnext.getX();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (vcurr->isV()){
|
|
|
|
cdebug_log(112,0) << "case vcurr: Vertical" << endl;
|
|
|
|
|
|
|
|
if ((vcurr->isiSet())&&(vcurr->hasValidStamp())){
|
|
|
|
cdebug_log(112,0) << "case set" << endl;
|
|
|
|
if (vcurr->getIMin() > pnext.getY()) {
|
|
|
|
min = pnext.getY();
|
|
|
|
max = vcurr->getIMax();
|
|
|
|
axis = vcurr->getIAxis();
|
|
|
|
} else if (vcurr->getIMax() < pnext.getY()) {
|
|
|
|
min = vcurr->getIMin();
|
|
|
|
max = pnext.getY();
|
|
|
|
axis = vcurr->getIAxis();
|
|
|
|
} else {
|
|
|
|
min = vcurr->getIMin();
|
|
|
|
max = vcurr->getIMax();
|
|
|
|
axis = vcurr->getIAxis();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "case not set" << endl;
|
|
|
|
axis = pcurr.getX();
|
|
|
|
if (pcurr.getY() < pnext.getY()){
|
|
|
|
min = pcurr.getY();
|
|
|
|
max = pnext.getY();
|
|
|
|
} else {
|
|
|
|
max = pcurr.getY();
|
|
|
|
min = pnext.getY();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Error(void Vertex::setIntervals(...)): Something is wrong." << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cdebug_log(112,0) << "IntervFrom => min: " << DbU::getValueString(min) << ", max: " << DbU::getValueString(max) << ", axis:" << DbU::getValueString(axis) << endl;
|
|
|
|
|
|
|
|
_intervfrom->set( min, max, axis );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Vertex::resetIntervals()
|
|
|
|
{
|
|
|
|
_interv->reset();
|
|
|
|
_intervfrom->reset();
|
2016-12-22 04:21:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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())
|
2016-09-22 11:52:53 -05:00
|
|
|
+ "-" + DbU::getValueString(_gcell->getYMin())
|
|
|
|
+ "-" + DbU::getValueString(_gcell->getXMax())
|
|
|
|
+ "-" + DbU::getValueString(_gcell->getYMax()) + ")"
|
2017-02-14 08:47:22 -06:00
|
|
|
/*+ " rps:" + getString(_rpCount)
|
2016-07-30 05:15:49 -05:00
|
|
|
+ " deg:" + getString(_degree)
|
2017-02-14 08:47:22 -06:00
|
|
|
+ " connexId:" + ((_connexId >= 0) ? getString(_connexId) : "None")*/
|
2016-06-26 07:55:34 -05:00
|
|
|
+ " d:" + ((_distance == unreached) ? "unreached"
|
|
|
|
: ((_distance == unreachable) ? "unreachable"
|
|
|
|
: DbU::getValueString(_distance)) )
|
2017-02-14 08:47:22 -06:00
|
|
|
/*+ "+" + getString(_branchId)
|
|
|
|
+ " stamp:" + (hasValidStamp() ? "valid" : "outdated")*/
|
2016-06-03 10:29:22 -05:00
|
|
|
+ " from:" + ((_from) ? "set" : "NULL")
|
2016-06-20 11:36:00 -05:00
|
|
|
+ " restricted:" + (isNRestricted() ? "N" : "-")
|
|
|
|
+ (isSRestricted() ? "S" : "-")
|
|
|
|
+ (isERestricted() ? "E" : "-")
|
|
|
|
+ (isWRestricted() ? "W" : "-")
|
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 )
|
|
|
|
{
|
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-12-22 04:21:25 -06:00
|
|
|
DbU::Unit Dijkstra::_distance ( const Vertex* current, const Vertex* vneighbour, const Edge* e )
|
2016-06-10 11:27:06 -05:00
|
|
|
{
|
2017-02-14 08:47:22 -06:00
|
|
|
if (Vertex::isRestricted(current, vneighbour)) return Vertex::unreachable;
|
|
|
|
else return current->getDistance() + e->getDistance();
|
|
|
|
}
|
2016-12-22 04:21:25 -06:00
|
|
|
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
DbU::Unit Dijkstra::_getDistancetoRP( Point p )
|
|
|
|
{
|
|
|
|
|
|
|
|
cdebug_log(112,0) << "DbU::Unit Dijkstra::_getDistancetoRP( Point p ): " << p << endl;
|
|
|
|
RoutingPad* rp = NULL;
|
|
|
|
DbU::Unit dist = 0;
|
|
|
|
Cell* cell = _anabatic->getCell();
|
|
|
|
int cpt = 0;
|
|
|
|
|
|
|
|
/*for ( Vertex* vertex : _sources ) {
|
|
|
|
if (vertex->hasRP()){
|
|
|
|
for ( Component* component : cell->getComponentsUnder(vertex->getGCell()->getBoundingBox()) ){
|
|
|
|
rp = dynamic_cast<RoutingPad*>( component );
|
|
|
|
if (rp) break;
|
|
|
|
}
|
|
|
|
if (rp) {
|
|
|
|
cdebug_log(112,0) << "Vertex: " << vertex << endl;
|
|
|
|
dist += _estimatePtoRP(p, rp, vertex );
|
|
|
|
}
|
2016-09-30 11:09:05 -05:00
|
|
|
}
|
2017-02-14 08:47:22 -06:00
|
|
|
}*/
|
|
|
|
for ( Vertex* vertex : _targets ) {
|
|
|
|
if (vertex->hasRP(_net)){
|
|
|
|
for ( Component* component : cell->getComponentsUnder(vertex->getGCell()->getBoundingBox()) ){
|
|
|
|
rp = dynamic_cast<RoutingPad*>( component );
|
|
|
|
if (rp) {
|
|
|
|
if (rp->getNet() == _net) break;
|
2016-12-22 04:21:25 -06:00
|
|
|
}
|
|
|
|
}
|
2017-02-14 08:47:22 -06:00
|
|
|
if (rp) {
|
|
|
|
DbU::Unit distance = _estimatePtoRP(p, rp, vertex );
|
|
|
|
cdebug_log(112,0) << "Dist to Vertex: " << vertex << " IS = " << DbU::getValueString(distance) << endl;
|
|
|
|
dist += distance;
|
|
|
|
cpt++;
|
|
|
|
}
|
2016-12-22 04:21:25 -06:00
|
|
|
}
|
|
|
|
}
|
2017-02-14 08:47:22 -06:00
|
|
|
dist = dist/cpt;
|
|
|
|
return dist;
|
2016-06-10 11:27:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
DbU::Unit calcDistance( Point p1, Point p2 )
|
2016-12-22 04:21:25 -06:00
|
|
|
{
|
2017-02-14 08:47:22 -06:00
|
|
|
return abs(p1.getX()-p2.getX()) + abs(p1.getY()-p2.getY());
|
2016-12-22 04:21:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
DbU::Unit Dijkstra::_estimatePtoRP( Point p, RoutingPad* rp, Vertex* vertex )
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
2017-02-14 08:47:22 -06:00
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(rp->_getEntityAsSegment());
|
|
|
|
Vertical* v = dynamic_cast<Vertical* >(rp->_getEntityAsSegment());
|
|
|
|
DbU::Unit d = Vertex::unreachable;
|
|
|
|
GCell* gvertex = vertex->getGCell();
|
|
|
|
|
|
|
|
if (h) {
|
|
|
|
cdebug_log(112,0) << "Case: Horizontal: " << endl;
|
|
|
|
if (p.getX() < rp->getSourceX()){
|
|
|
|
cdebug_log(112,0) << "Case: p.getX() < rp->getSourceX()" << endl;
|
|
|
|
if (p.getY() < gvertex->getYMin()){
|
|
|
|
cdebug_log(112,0) << "Case: West South" << endl;
|
|
|
|
if ( (!vertex->isSRestricted())
|
|
|
|
|| (!vertex->isWRestricted()) ) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else if (!vertex->isNRestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())) + (gvertex->getYMax() - rp->getY())*2;
|
|
|
|
else if (!vertex->isERestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else if (p.getY() > gvertex->getYMax()){
|
|
|
|
cdebug_log(112,0) << "Case: West North" << endl;
|
|
|
|
if ( (!vertex->isNRestricted())
|
|
|
|
|| (!vertex->isWRestricted()) ) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else if (!vertex->isSRestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())) + (rp->getY() - gvertex->getYMin())*2;
|
|
|
|
else if (!vertex->isERestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Case: West" << endl;
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())));
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()))+ (gvertex->getYMax() - rp->getY())*2);
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()))+ (rp->getY() - gvertex->getYMin())*2);
|
|
|
|
if (!vertex->isERestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())));
|
|
|
|
}
|
|
|
|
} else if (p.getX() > rp->getTargetX()){
|
|
|
|
cdebug_log(112,0) << "Case: p.getX() > rp->getTargetX()" << endl;
|
|
|
|
if (p.getY() < gvertex->getYMin()){
|
|
|
|
cdebug_log(112,0) << "Case: East South" << endl;
|
|
|
|
if ( (!vertex->isSRestricted())
|
|
|
|
|| (!vertex->isERestricted()) ) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else if (!vertex->isNRestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())) + (gvertex->getYMax() - rp->getY())*2;
|
|
|
|
else if (!vertex->isWRestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else if (p.getY() > gvertex->getYMax()){
|
|
|
|
cdebug_log(112,0) << "Case: East North" << endl;
|
|
|
|
if ( (!vertex->isNRestricted())
|
|
|
|
|| (!vertex->isERestricted()) ) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else if (!vertex->isSRestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())) + (rp->getY() - gvertex->getYMin())*2;
|
|
|
|
else if (!vertex->isWRestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Case: East" << endl;
|
|
|
|
if (!vertex->isERestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())));
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()))+ (gvertex->getYMax() - rp->getY())*2);
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()))+ (rp->getY() - gvertex->getYMin())*2);
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())));
|
|
|
|
}
|
|
|
|
} else if (p.getY() < gvertex->getYMin()){
|
|
|
|
cdebug_log(112,0) << "Case: South" << endl;
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, rp->getY()-p.getY());
|
|
|
|
if (!vertex->isERestricted()) d = min(d, rp->getY()-p.getY()+ (gvertex->getXMax()-p.getX())*2);
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, rp->getY()-p.getY()+ (p.getX()-gvertex->getXMin())*2);
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, min ( gvertex->getXMax()-p.getX() + gvertex->getYMax()-p.getY() + gvertex->getYMax()-rp->getY()
|
|
|
|
, p.getX()-gvertex->getXMin() + gvertex->getYMax()-p.getY() + gvertex->getYMax()-rp->getY()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
} else if (p.getY() > gvertex->getYMax()){
|
|
|
|
cdebug_log(112,0) << "Case: North" << endl;
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, p.getY()-rp->getY());
|
|
|
|
if (!vertex->isERestricted()) d = min(d, p.getY()-rp->getY()+ (gvertex->getXMax()-p.getX())*2);
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, p.getY()-rp->getY()+ (p.getX()-gvertex->getXMin())*2);
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, min ( gvertex->getXMax()-p.getX() + p.getY()-gvertex->getYMin() + rp->getY()-gvertex->getYMin()
|
|
|
|
, p.getX()-gvertex->getXMin() + p.getY()-gvertex->getYMin() + rp->getY()-gvertex->getYMin()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2016-06-17 09:26:27 -05:00
|
|
|
}
|
2017-02-14 08:47:22 -06:00
|
|
|
|
|
|
|
if (v) {
|
|
|
|
cdebug_log(112,0) << "Case: Vertical" << endl;
|
|
|
|
if (p.getY() < rp->getSourceY()){
|
|
|
|
cdebug_log(112,0) << "Case: p.getY() < rp->getSourceY()" << endl;
|
|
|
|
if (p.getX() < gvertex->getXMin()){
|
|
|
|
cdebug_log(112,0) << "Case: South West" << endl;
|
|
|
|
if ( (!vertex->isSRestricted())
|
|
|
|
|| (!vertex->isWRestricted()) ) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else if (!vertex->isERestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())) + (gvertex->getXMax() - rp->getX())*2;
|
|
|
|
else if (!vertex->isNRestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else if (p.getX() > gvertex->getXMax()){
|
|
|
|
cdebug_log(112,0) << "Case: South East" << endl;
|
|
|
|
if ( (!vertex->isSRestricted())
|
|
|
|
|| (!vertex->isERestricted()) ) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else if (!vertex->isWRestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())) + (rp->getX() - gvertex->getXMin())*2;
|
|
|
|
else if (!vertex->isNRestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Case: South " << endl;
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())));
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()))+ (gvertex->getXMax() - rp->getX())*2);
|
|
|
|
if (!vertex->isERestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()))+ (rp->getX() - gvertex->getXMin())*2);
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())));
|
|
|
|
}
|
|
|
|
} else if (p.getY() > rp->getTargetY()){
|
|
|
|
cdebug_log(112,0) << "Case: p.getY() > rp->getTargetY()" << endl;
|
|
|
|
if (p.getX() < gvertex->getXMin()){
|
|
|
|
cdebug_log(112,0) << "Case: North West" << endl;
|
|
|
|
if ( (!vertex->isNRestricted())
|
|
|
|
|| (!vertex->isWRestricted()) ) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else if (!vertex->isERestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())) + (gvertex->getXMax() - rp->getX())*2;
|
|
|
|
else if (!vertex->isSRestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else if (p.getX() > gvertex->getXMax()){
|
|
|
|
cdebug_log(112,0) << "Case: North East" << endl;
|
|
|
|
if ( (!vertex->isNRestricted())
|
|
|
|
|| (!vertex->isERestricted()) ) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()));
|
|
|
|
else if (!vertex->isWRestricted()) d = calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())) + (rp->getX() - gvertex->getXMin())*2;
|
|
|
|
else if (!vertex->isSRestricted()) d = calcDistance (p, Point(rp->getSourceX(), rp->getSourceY()));
|
|
|
|
else d = Vertex::unreachable;
|
|
|
|
} else {
|
|
|
|
cdebug_log(112,0) << "Case: North" << endl;
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY())));
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()))+ (gvertex->getXMax() - rp->getX())*2);
|
|
|
|
if (!vertex->isERestricted()) d = min(d, calcDistance (p, Point(rp->getTargetX(), rp->getTargetY()))+ (rp->getX() - gvertex->getXMin())*2);
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, calcDistance (p, Point(rp->getSourceX(), rp->getSourceY())));
|
|
|
|
}
|
|
|
|
} else if (p.getX() < gvertex->getXMin()){
|
|
|
|
cdebug_log(112,0) << "Case: West" << endl;
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, rp->getX()-p.getX());
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, rp->getX()-p.getX()+ (gvertex->getYMax()-p.getY())*2);
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, rp->getX()-p.getX()+ (p.getY()-gvertex->getYMin())*2);
|
|
|
|
if (!vertex->isERestricted()) d = min(d, min ( gvertex->getYMax()-p.getY() + gvertex->getXMax()-p.getX() + gvertex->getXMax()-rp->getX()
|
|
|
|
, p.getY()-gvertex->getYMin() + gvertex->getXMax()-p.getX() + gvertex->getXMax()-rp->getX()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
} else if (p.getX() > gvertex->getXMax()){
|
|
|
|
cdebug_log(112,0) << "Case: East" << endl;
|
|
|
|
if (!vertex->isERestricted()) d = min(d, p.getX()-rp->getX());
|
|
|
|
if (!vertex->isNRestricted()) d = min(d, p.getX()-rp->getX()+ (gvertex->getYMax()-p.getY())*2);
|
|
|
|
if (!vertex->isSRestricted()) d = min(d, p.getX()-rp->getX()+ (p.getY()-gvertex->getYMin())*2);
|
|
|
|
if (!vertex->isWRestricted()) d = min(d, min ( gvertex->getYMax()-p.getY() + p.getX()-gvertex->getXMin() + rp->getX()-gvertex->getXMin()
|
|
|
|
, p.getY()-gvertex->getYMin() + p.getX()-gvertex->getXMin() + rp->getX()-gvertex->getXMin()
|
|
|
|
)
|
|
|
|
);
|
2016-06-17 09:26:27 -05:00
|
|
|
}
|
|
|
|
}
|
2017-02-14 08:47:22 -06:00
|
|
|
return d;
|
2016-06-17 09:26:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
Dijkstra::Dijkstra ( AnabaticEngine* anabatic )
|
2016-08-10 16:48:06 -05:00
|
|
|
: _anabatic (anabatic)
|
|
|
|
, _vertexes ()
|
|
|
|
, _distanceCb (_distance)
|
|
|
|
, _mode (Mode::Standart)
|
|
|
|
, _net (NULL)
|
|
|
|
, _stamp (-1)
|
|
|
|
, _sources ()
|
|
|
|
, _targets ()
|
|
|
|
, _searchArea ()
|
|
|
|
, _searchAreaHalo(0)
|
|
|
|
, _connectedsId (-1)
|
|
|
|
, _queue ()
|
2016-05-30 04:30:29 -05:00
|
|
|
{
|
|
|
|
const vector<GCell*>& gcells = _anabatic->getGCells();
|
|
|
|
for ( GCell* gcell : gcells ) {
|
|
|
|
_vertexes.push_back( new Vertex (gcell) );
|
|
|
|
}
|
2016-08-27 09:00:14 -05:00
|
|
|
_anabatic->getMatrix()->show();
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dijkstra::~Dijkstra ()
|
|
|
|
{
|
|
|
|
for ( Vertex* vertex : _vertexes ) delete vertex;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
Point Dijkstra::_getPonderedPoint() const
|
|
|
|
{
|
|
|
|
vector<RoutingPad*> rps;
|
|
|
|
int cpt = 0;
|
|
|
|
DbU::Unit x = 0;
|
|
|
|
DbU::Unit y = 0;
|
|
|
|
|
|
|
|
for ( Component* component : _net->getComponents() ) {
|
|
|
|
RoutingPad* rp = dynamic_cast<RoutingPad*>( component );
|
|
|
|
if (rp) rps.push_back( rp );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( auto rp : rps ) {
|
|
|
|
x += rp->getBoundingBox().getCenter().getX();
|
|
|
|
y += rp->getBoundingBox().getCenter().getY();
|
|
|
|
cpt++;
|
|
|
|
}
|
|
|
|
return Point(x/cpt, y/cpt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
void Dijkstra::load ( Net* net )
|
|
|
|
{
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
_cleanup();
|
|
|
|
|
|
|
|
_net = net;
|
|
|
|
_stamp = _anabatic->incStamp();
|
2016-05-30 11:52:38 -05:00
|
|
|
|
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-07-30 05:15:49 -05:00
|
|
|
vector<RoutingPad*> rps;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
for ( Component* component : _net->getComponents() ) {
|
|
|
|
RoutingPad* rp = dynamic_cast<RoutingPad*>( component );
|
2016-09-30 11:09:05 -05:00
|
|
|
if (rp) {
|
|
|
|
rps.push_back( rp );
|
First intergration of the Analogic router parts.
* New: In Anabatic::AutoSegment, introduce a the kind (associated to a
flag) "LongLocal". Analog GCells can be very wide, so at least some
carefuly choosen long local segments must be took into account as
attractors in the computation of the optimal axis.
* New: In Anabatic::AutoSegment::computeOptimal(), take LongLocal into
account as attractors.
* Change: In ::GCellTopology constructors compare the layers of the
RoutingPads using layer masks instead of Layer pointers. Allows to
find both "METALx" (symbolic) and "metalX" (real).
* Change: In ::GCellTopology::_doHChannel(), _doChannel(), _doStrut()
and _doDevice(), tag long locals as "LongLocal". This need to be
reviewed as it as bind done a bit too quickly.
* Change: In Anabatic::AutoSegment, due too a much bigger span of the
analogic GCells the _optimalMin & _optimalMax bitfields must use
16 bits instead of 8 (they where overflowed).
* New: In Katana, reorganisation of the initialization procedure to fit
both digital and analogic cases. Create an analogInit() method.
* Change: In Katana::RoutingEvent, the _tracksNb and _tracksFree bitfields
where too short for the Analog GCell size, now uses 16 bits instead of
6.
* Bug: In Katana::GraphicKatanEngine::drawGCell(), skip drawing of a
GCell if *both* width and height are under 150 pixels.
* New: In Katana::Session, add a new isOpen() method.
2016-10-04 10:12:58 -05:00
|
|
|
cdebug_log(112,0) << "| " << rp << endl;
|
2016-09-30 11:09:05 -05:00
|
|
|
continue;
|
|
|
|
}
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( auto rp : rps ) {
|
|
|
|
Point center = rp->getBoundingBox().getCenter();
|
|
|
|
GCell* gcell = _anabatic->getGCellUnder( center );
|
2016-09-30 11:09:05 -05:00
|
|
|
|
|
|
|
if (gcell->isDevice()){
|
|
|
|
_searchArea.merge( _net->getCell()->getAbutmentBox() );
|
|
|
|
}
|
2016-08-10 16:48:06 -05:00
|
|
|
|
2016-09-30 11:09:05 -05:00
|
|
|
cdebug_log(112,0) << "| " << rp << endl;
|
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) {
|
2016-08-27 09:00:14 -05:00
|
|
|
cerr << Error( "Dijkstra::load(): %s\n"
|
|
|
|
" @%s of %s is not under any GCell.\n"
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
" It will be ignored so the routing may be incomplete."
|
2016-07-30 05:15:49 -05:00
|
|
|
, getString(rp).c_str()
|
2016-08-27 09:00:14 -05:00
|
|
|
, getString(center).c_str()
|
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
|
|
|
, getString(_net).c_str()
|
|
|
|
) << endl;
|
|
|
|
continue;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-09-30 11:09:05 -05:00
|
|
|
cdebug_log(112,0) << "Current Search area: " << _searchArea << ", gcell: " << gcell << endl;
|
2016-06-10 11:27:06 -05:00
|
|
|
_searchArea.merge( gcell->getBoundingBox() );
|
2016-09-30 11:09:05 -05:00
|
|
|
cdebug_log(112,0) << "New Search area: " << _searchArea << endl;
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
Vertex* seed = gcell->getObserver<Vertex>(GCell::Observable::Vertex);
|
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(rp->_getEntityAsSegment());
|
|
|
|
Vertical* v = dynamic_cast<Vertical*> (rp->_getEntityAsSegment());
|
|
|
|
if (h) {
|
|
|
|
seed->setIAsH();
|
|
|
|
seed->setInterv(rp->getBoundingBox().getXMin(), rp->getBoundingBox().getXMax(), rp->getBoundingBox().getYCenter());
|
|
|
|
}
|
|
|
|
if (v) {
|
|
|
|
seed->setIAsV();
|
|
|
|
seed->setInterv(rp->getBoundingBox().getYMin(), rp->getBoundingBox().getYMax(), rp->getBoundingBox().getXCenter());
|
|
|
|
}
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
if (seed->getConnexId() < 0) {
|
|
|
|
VertexSet connecteds;
|
|
|
|
_getConnecteds( seed, connecteds );
|
|
|
|
|
|
|
|
++_connectedsId;
|
|
|
|
for ( Vertex* vertex : connecteds ) {
|
|
|
|
vertex->setDistance ( Vertex::unreached );
|
|
|
|
vertex->setStamp ( _stamp );
|
|
|
|
vertex->setConnexId ( _connectedsId );
|
|
|
|
vertex->setBranchId ( 0 );
|
|
|
|
vertex->setDegree ( 1 );
|
|
|
|
vertex->setRpCount ( 0 );
|
|
|
|
vertex->setFrom ( NULL );
|
|
|
|
vertex->clearRestriction();
|
|
|
|
_targets.insert( vertex );
|
2016-08-10 16:48:06 -05:00
|
|
|
cdebug_log(112,0) << "| Add: " << vertex << endl;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
seed->incRpCount();
|
|
|
|
Contact* vcontact = seed->getGContact( _net );
|
|
|
|
rp->getBodyHook()->detach();
|
|
|
|
rp->getBodyHook()->attach( vcontact->getBodyHook() );
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
2016-08-10 16:48:06 -05:00
|
|
|
_searchArea.inflate( _searchAreaHalo );
|
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();
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
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.
|
2017-02-14 08:47:22 -06:00
|
|
|
bool hasDevice = false;
|
|
|
|
for ( Vertex* ivertex : _targets ) {
|
|
|
|
if (ivertex->getGCell()->isDevice()) hasDevice = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Point areaCenter;
|
|
|
|
if (hasDevice) areaCenter = _getPonderedPoint();
|
|
|
|
else areaCenter = _searchArea.getCenter();
|
|
|
|
|
|
|
|
auto ivertex = _targets.begin();
|
2016-06-10 11:27:06 -05:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
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;
|
|
|
|
}
|
2016-05-30 11:52:38 -05:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
void Dijkstra::_cleanup ()
|
|
|
|
{
|
|
|
|
//_checkEdges();
|
|
|
|
_sources.clear();
|
|
|
|
_targets.clear();
|
|
|
|
_searchArea.makeEmpty();
|
|
|
|
_connectedsId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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();
|
2017-02-14 08:47:22 -06:00
|
|
|
cdebug_log(111,0) << endl;
|
2016-09-30 11:09:05 -05:00
|
|
|
cdebug_log(111,0) << "[Current Vertex]: " << current << endl;
|
2016-05-30 04:30:29 -05:00
|
|
|
_queue.pop();
|
|
|
|
|
|
|
|
if ((current->getConnexId() == _connectedsId) or (current->getConnexId() < 0)) {
|
|
|
|
for ( Edge* edge : current->getGCell()->getEdges() ) {
|
2016-08-11 08:40:21 -05:00
|
|
|
if (edge == current->getFrom()) {
|
|
|
|
cdebug_log(111,0) << "edge == current->getFrom()" << endl;
|
|
|
|
continue;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
GCell* gneighbor = edge->getOpposite(current->getGCell());
|
2017-02-14 08:47:22 -06:00
|
|
|
GCell* gcurrent = 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
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
if (vneighbor->getConnexId() == _connectedsId) {
|
|
|
|
cdebug_log(111,0) << "ConnectedsId" << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-08-11 08:40:21 -05:00
|
|
|
if (not _searchArea.intersect(gneighbor->getBoundingBox())) {
|
2016-09-30 11:09:05 -05:00
|
|
|
cdebug_log(111,0) << "not in _searchArea: " << _searchArea << ", gneighbor area: " << gneighbor->getBoundingBox() << endl;
|
2016-08-11 08:40:21 -05:00
|
|
|
continue;
|
|
|
|
}
|
2017-02-14 08:47:22 -06:00
|
|
|
cdebug_log(111,0) << endl << "===================================================================================" << endl << endl;
|
|
|
|
cdebug_log(111,0) << "| Curr: " << current;
|
|
|
|
if (current->getFrom()){
|
|
|
|
cdebug_log(111,0) << "| From: " << current->getFrom()->getOpposite(gcurrent) << endl;
|
|
|
|
} else {
|
|
|
|
cdebug_log(111,0) << endl;
|
|
|
|
}
|
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-05-30 04:30:29 -05:00
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
DbU::Unit distance = _distanceCb( current, vneighbor, edge );
|
|
|
|
cdebug_log(111,0) << "Distance curr: " << DbU::getValueString(distance) << endl;
|
|
|
|
cdebug_log(111,0) << "Distance prev: " << DbU::getValueString(vneighbor->getDistance()) << endl;
|
|
|
|
|
|
|
|
if ( (distance == vneighbor->getDistance())
|
|
|
|
and ( (!gcurrent->isMatrix())||(!gneighbor->isMatrix()) )
|
|
|
|
){
|
|
|
|
cdebug_log(111,0) << "Distance EQUAL" << endl;
|
|
|
|
cdebug_log(111,0) << "Previous getfrom:" << vneighbor->getFrom()->getOpposite( gneighbor ) << endl;
|
|
|
|
|
|
|
|
GCell* gnext = vneighbor->getGCell();
|
|
|
|
GCell* gprev = vneighbor->getFrom()->getOpposite(gnext);
|
|
|
|
Vertex* vprev = gprev->getObserver<Vertex>(GCell::Observable::Vertex);
|
|
|
|
|
|
|
|
|
|
|
|
Point pnext = Vertex::getNextPathPoint2( current, vneighbor );
|
|
|
|
Point pprev = Vertex::getNextPathPoint2( vprev, vneighbor );
|
|
|
|
Point ppond = _getPonderedPoint();
|
|
|
|
DbU::Unit distcurr = this->_getDistancetoRP(pnext);
|
|
|
|
DbU::Unit distprev = this->_getDistancetoRP(pprev);
|
|
|
|
|
|
|
|
cdebug_log(111,0) << "Pcurrent: X:" << DbU::getValueString(pnext.getX()) << ", Y:" << DbU::getValueString(pnext.getY()) << endl;
|
|
|
|
cdebug_log(111,0) << "Pprev : X:" << DbU::getValueString(pprev.getX()) << ", Y:" << DbU::getValueString(pprev.getY()) << endl;
|
|
|
|
|
|
|
|
cdebug_log(111,0) << "distToTargets curr: " << DbU::getValueString(distcurr) << endl;
|
|
|
|
cdebug_log(111,0) << "distToTargets prev: " << DbU::getValueString(distprev) << endl;
|
|
|
|
|
|
|
|
if ( ( distcurr < distprev )
|
|
|
|
|| ( ( distcurr == distprev )
|
|
|
|
&& ( calcDistance(ppond, pnext) < calcDistance(ppond, pprev) )
|
|
|
|
)
|
|
|
|
){
|
|
|
|
cdebug_log(111,0) << "BETTER GetFROM" << endl;
|
|
|
|
vneighbor->setBranchId( current->getBranchId() );
|
|
|
|
vneighbor->setDistance( distance );
|
|
|
|
//Point pathPoint = Vertex::getNextPathPoint( current, vneighbor );
|
|
|
|
//vneighbor->setPathPoint( pathPoint.getX(), pathPoint.getY() );
|
|
|
|
vneighbor->setFrom ( edge );
|
|
|
|
_queue.push( vneighbor );
|
|
|
|
|
|
|
|
vneighbor->setIntervals( current );
|
|
|
|
cdebug_log(111,0) << "Push: (size:" << _queue.size() << ") " << vneighbor << endl;
|
|
|
|
}
|
|
|
|
} else if ( ( (distance < vneighbor->getDistance()) and (distance != Vertex::unreachable) )
|
|
|
|
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()) {
|
2017-02-14 08:47:22 -06:00
|
|
|
cdebug_log(111,0) << "Distance FIRST" << endl;
|
2016-06-17 06:09:34 -05:00
|
|
|
vneighbor->setConnexId( -1 );
|
|
|
|
vneighbor->setStamp ( _stamp );
|
2016-07-30 05:15:49 -05:00
|
|
|
vneighbor->setDegree ( 1 );
|
|
|
|
vneighbor->setRpCount ( 0 );
|
2016-06-17 06:09:34 -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
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
cdebug_log(111,0) << "Distance INF" << endl;
|
2016-06-17 06:09:34 -05:00
|
|
|
vneighbor->setBranchId( current->getBranchId() );
|
2016-05-30 04:30:29 -05:00
|
|
|
vneighbor->setDistance( distance );
|
2017-02-14 08:47:22 -06:00
|
|
|
//Point pathPoint = Vertex::getNextPathPoint( current, vneighbor );
|
|
|
|
//vneighbor->setPathPoint( pathPoint.getX(), pathPoint.getY() );
|
2016-12-22 04:21:25 -06:00
|
|
|
vneighbor->setFrom ( edge );
|
2016-05-30 04:30:29 -05:00
|
|
|
_queue.push( vneighbor );
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
vneighbor->setIntervals( current );
|
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 );
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
cdebug_tabw(112,-1);
|
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;
|
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
int branchId = _sources.size();
|
|
|
|
Point ponderedpoint = _getPonderedPoint();
|
2016-07-30 05:15:49 -05:00
|
|
|
_toSources( current, _connectedsId );
|
2016-06-17 10:45:32 -05:00
|
|
|
|
2017-02-14 08:47:22 -06:00
|
|
|
|
|
|
|
if (!current->getGCell()->isMatrix()){
|
|
|
|
GCell* gcurr = current->getGCell();
|
|
|
|
GCell* gprev = current->getFrom()->getOpposite(gcurr);
|
|
|
|
Vertex* vprev = gprev->getObserver<Vertex>(GCell::Observable::Vertex);
|
|
|
|
Point pentry = Vertex::getNextPathPoint2( vprev, current );
|
|
|
|
|
|
|
|
if (current->isH()){
|
|
|
|
if (pentry.getX() < current->getIMin()){
|
|
|
|
current->setInterv(pentry.getX(), current->getIMax(), current->getIAxis());
|
|
|
|
cdebug_log(112,0) << "[Interval update1]: min : " << DbU::getValueString(pentry.getX());
|
|
|
|
cdebug_log(112,0) << ", max : " << DbU::getValueString(current->getIMax());
|
|
|
|
cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl;
|
|
|
|
} else if (pentry.getX() > current->getIMax()){
|
|
|
|
current->setInterv(current->getIMin(), pentry.getX(), current->getIAxis());
|
|
|
|
cdebug_log(112,0) << "[Interval update2]: min : " << DbU::getValueString(current->getIMin());
|
|
|
|
cdebug_log(112,0) << ", max : " << DbU::getValueString(pentry.getX());
|
|
|
|
cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl;
|
|
|
|
}
|
|
|
|
} else if (current->isV()){
|
|
|
|
if (pentry.getY() < current->getIMin()){
|
|
|
|
current->setInterv(pentry.getY(), current->getIMax(), current->getIAxis());
|
|
|
|
cdebug_log(112,0) << "[Interval update3]: min : " << DbU::getValueString(pentry.getY());
|
|
|
|
cdebug_log(112,0) << ", max : " << DbU::getValueString(current->getIMax());
|
|
|
|
cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl;
|
|
|
|
} else if (pentry.getY() > current->getIMax()){
|
|
|
|
current->setInterv(current->getIMin(), pentry.getY(), current->getIAxis());
|
|
|
|
cdebug_log(112,0) << "[Interval update4]: min : " << DbU::getValueString(current->getIMin());
|
|
|
|
cdebug_log(112,0) << ", max : " << DbU::getValueString(pentry.getY());
|
|
|
|
cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
current = current->getPredecessor();
|
2017-02-14 08:47:22 -06:00
|
|
|
|
2016-06-17 10:45:32 -05:00
|
|
|
while ( current ) {
|
2017-02-14 08:47:22 -06:00
|
|
|
cdebug_log(112,0) << "| " << current << " | " << endl;
|
2016-07-30 05:15:49 -05:00
|
|
|
|
|
|
|
current->incDegree();
|
2016-06-17 10:45:32 -05:00
|
|
|
if (current->getConnexId() == _connectedsId) break;
|
|
|
|
|
|
|
|
Edge* from = current->getFrom();
|
|
|
|
if (not from) break;
|
|
|
|
|
|
|
|
current->setDistance( 0.0 );
|
2017-02-14 08:47:22 -06:00
|
|
|
if (!current->getGCell()->isMatrix()){
|
|
|
|
/*if (!current->getGCell()->isDevice()) {
|
|
|
|
current->resetPathPoint(ponderedpoint);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
if (current->getPredecessor() != NULL){
|
|
|
|
cdebug_log(112,0) << "[Interval update]: min : " << DbU::getValueString(current->getPIMin());
|
|
|
|
cdebug_log(112,0) << ", max : " << DbU::getValueString(current->getPIMax());
|
|
|
|
cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getPIAxis()) << endl;
|
|
|
|
current->getPredecessor()->setInterv(current->getPIMin(), current->getPIMax(), current->getPIAxis());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 10:45:32 -05:00
|
|
|
current->setConnexId( _connectedsId );
|
|
|
|
current->setBranchId( branchId );
|
2016-07-30 05:15:49 -05:00
|
|
|
_sources.insert( current );
|
2016-06-17 10:45:32 -05:00
|
|
|
_queue.push( current );
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
current = current->getPredecessor();
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_tabw(112,-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Dijkstra::_materialize ()
|
|
|
|
{
|
|
|
|
cdebug_log(112,1) << "Dijkstra::_materialize() " << _net << " _sources:" << _sources.size() << endl;
|
|
|
|
|
|
|
|
if (_sources.size() < 2) { cdebug_tabw(112,-1); return; }
|
|
|
|
|
|
|
|
for ( Vertex* startVertex : _sources ) {
|
2017-02-14 08:47:22 -06:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(112,0) << "? " << startVertex << endl;
|
|
|
|
|
|
|
|
if (not startVertex->getFrom()) continue;
|
|
|
|
if ( not startVertex->hasGContact(_net)
|
|
|
|
and not startVertex->getRpCount()
|
|
|
|
and (startVertex->getDegree() < 3)) continue;
|
|
|
|
|
|
|
|
Vertex* source = startVertex;
|
|
|
|
while ( source ) {
|
2017-02-14 08:47:22 -06:00
|
|
|
////////////////////////////////////////////
|
|
|
|
source->resetIntervals();
|
|
|
|
////////////////////////////////////////////
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(112,0) << "* " << source << endl;
|
|
|
|
|
|
|
|
Edge* from = source->getFrom();
|
|
|
|
vector<Edge*> aligneds;
|
|
|
|
aligneds.push_back( from );
|
|
|
|
|
|
|
|
Vertex* target = source->getPredecessor();
|
|
|
|
Interval constraint = from->getSide();
|
|
|
|
source->setFrom( NULL );
|
2016-06-17 10:45:32 -05:00
|
|
|
|
2016-08-27 09:00:14 -05:00
|
|
|
cdebug_log(112,0) << "+ " << target << endl;
|
|
|
|
|
|
|
|
if (target->getConnexId() < 0) {
|
|
|
|
cdebug_log(112,0) << "| " << "break (abort: false start)." << endl;
|
|
|
|
break;
|
|
|
|
}
|
2016-06-17 10:45:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
while ( true ) {
|
|
|
|
from = target->getFrom();
|
2016-08-11 08:40:21 -05:00
|
|
|
if ( not from
|
|
|
|
or not (target->getGCell()->isMatrix())
|
2016-07-30 05:15:49 -05:00
|
|
|
or (target->hasGContact(_net))
|
|
|
|
or (target->getRpCount())
|
|
|
|
or (target->getDegree() > 2)
|
|
|
|
or (aligneds.back()->isHorizontal() xor from->isHorizontal())
|
|
|
|
or not constraint.intersect(from->getSide())) break;
|
2016-06-17 10:45:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
aligneds.push_back( from );
|
|
|
|
constraint.merge( from->getSide() );
|
|
|
|
|
|
|
|
Vertex* nextTarget = target->getPredecessor();
|
|
|
|
target->setFrom( NULL );
|
|
|
|
target = nextTarget;
|
|
|
|
|
2016-08-27 09:00:14 -05:00
|
|
|
cdebug_log(112,0) << "| " << target << endl;
|
2016-07-30 05:15:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Contact* sourceContact = source->getGContact( _net );
|
|
|
|
Contact* targetContact = target->hasGContact( _net );
|
|
|
|
Segment* segment = NULL;
|
|
|
|
|
|
|
|
if (not targetContact) {
|
|
|
|
if (target->getFrom()) targetContact = target->getGContact( _net );
|
|
|
|
else targetContact = target->breakGoThrough( _net );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aligneds.front()->isHorizontal()) {
|
2016-08-18 04:59:19 -05:00
|
|
|
if (sourceContact->getX() > targetContact->getX())
|
|
|
|
std::swap( sourceContact, targetContact );
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
segment = Horizontal::create( sourceContact
|
|
|
|
, targetContact
|
|
|
|
, _anabatic->getConfiguration()->getGHorizontalLayer()
|
|
|
|
, constraint.getCenter()
|
|
|
|
, DbU::fromLambda(2.0)
|
|
|
|
);
|
|
|
|
for ( Edge* through : aligneds ) through->add( segment );
|
|
|
|
} else {
|
2016-08-18 04:59:19 -05:00
|
|
|
if (sourceContact->getY() > targetContact->getY())
|
|
|
|
std::swap( sourceContact, targetContact );
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
segment = Vertical::create( sourceContact
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
, targetContact
|
2016-07-30 05:15:49 -05:00
|
|
|
, _anabatic->getConfiguration()->getGVerticalLayer()
|
|
|
|
, constraint.getCenter()
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
, DbU::fromLambda(2.0)
|
|
|
|
);
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( Edge* through : aligneds ) through->add( segment );
|
|
|
|
}
|
|
|
|
|
2016-08-27 09:00:14 -05:00
|
|
|
cdebug_log(112,0) << "| " << segment << endl;
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(112,0) << "| " << "break (turn, branch or terminal)." << endl;
|
|
|
|
source = (target->getFrom()) ? target : NULL;
|
2016-06-17 10:45:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
_queue.clear();
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
_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;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
|
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-07-30 05:15:49 -05:00
|
|
|
_materialize();
|
2016-05-30 04:30:29 -05:00
|
|
|
|
2016-07-31 11:43:44 -05:00
|
|
|
_anabatic->getNetData( _net )->setGlobalRouted( true );
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
void Dijkstra::_toSources ( Vertex* source, int connexId )
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
{
|
2016-08-27 09:00:14 -05:00
|
|
|
cdebug_log(112,1) << "Dijkstra::_toSources() " << endl;
|
|
|
|
cdebug_log(112,0) << "* from: " << source << endl;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
source->setConnexId( connexId );
|
|
|
|
source->setDistance( 0.0 );
|
|
|
|
_targets.erase ( source );
|
|
|
|
_sources.insert( source );
|
|
|
|
_queue.push( source );
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
VertexSet stack;
|
|
|
|
stack.insert( source );
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
while ( not stack.empty() ) {
|
|
|
|
source = *stack.begin();
|
|
|
|
stack.erase( source );
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(112,0) << "| source:" << source << " stack.size():" << stack.size() << endl;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
for ( Edge* edge : source->getGCell()->getEdges() ) {
|
|
|
|
if (not edge->hasNet(_net)) {
|
2016-08-27 09:00:14 -05:00
|
|
|
cdebug_log(112,0) << " Not connected:" << edge
|
|
|
|
<< " to:" << edge->getOpposite(source->getGCell()) << endl;
|
2016-07-30 05:15:49 -05:00
|
|
|
continue;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
GCell* gneighbor = edge->getOpposite(source->getGCell());
|
|
|
|
Vertex* vneighbor = gneighbor->getObserver<Vertex>(GCell::Observable::Vertex);
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
if (not vneighbor->hasValidStamp()) continue;
|
|
|
|
if (vneighbor->getConnexId() == connexId) continue;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
vneighbor->setConnexId( connexId );
|
|
|
|
vneighbor->setDistance( 0.0 );
|
2016-08-27 09:00:14 -05:00
|
|
|
//vneighbor->setFrom ( edge );
|
2016-07-30 05:15:49 -05:00
|
|
|
_targets.erase ( vneighbor );
|
|
|
|
_sources.insert( vneighbor );
|
|
|
|
_queue.push( vneighbor );
|
|
|
|
stack.insert( vneighbor );
|
|
|
|
}
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_tabw(112,-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
void Dijkstra::_getConnecteds ( Vertex* source, VertexSet& connecteds )
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
{
|
2016-07-30 05:15:49 -05:00
|
|
|
cdebug_log(112,1) << "Dijkstra::_getConnecteds()" << endl;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
connecteds.clear();
|
|
|
|
connecteds.insert( source );
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
|
|
|
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() ) {
|
2016-07-30 05:15:49 -05:00
|
|
|
if (not edge->hasNet(_net)) {
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
cdebug_log(112,0) << " Not connected:" << edge << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
GCell* gneighbor = edge->getOpposite(source->getGCell());
|
|
|
|
Vertex* vneighbor = gneighbor->getObserver<Vertex>(GCell::Observable::Vertex);
|
|
|
|
|
2016-07-30 05:15:49 -05:00
|
|
|
if (connecteds.find(vneighbor) != connecteds.end()) continue;
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
|
|
|
stack.insert( vneighbor );
|
2016-07-30 05:15:49 -05:00
|
|
|
connecteds.insert( vneighbor );
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cdebug_tabw(112,-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Dijkstra::_checkEdges () const
|
|
|
|
{
|
|
|
|
cdebug_log(112,1) << "Dijkstra::_checkEdges()" << endl;
|
|
|
|
|
2016-07-31 11:43:44 -05:00
|
|
|
// for ( Vertex* vertex : _vertexes ) {
|
|
|
|
// for ( Edge* edge : vertex->getGCell()->getEdges(Flags::EastSide|Flags::NorthSide) ) {
|
|
|
|
// }
|
|
|
|
// }
|
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.
2016-06-26 07:32:32 -05:00
|
|
|
|
|
|
|
cdebug_tabw(112,-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
} // Anabatic namespace.
|