2016-05-23 09:15:25 -05:00
|
|
|
// -*- mode: C++; explicit-buffer-name: "GCell.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 : "./GCell.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
2016-05-30 04:30:29 -05:00
|
|
|
#include "hurricane/Contact.h"
|
2016-05-30 11:52:38 -05:00
|
|
|
#include "hurricane/UpdateSession.h"
|
2016-05-23 09:15:25 -05:00
|
|
|
#include "anabatic/GCell.h"
|
|
|
|
#include "anabatic/AnabaticEngine.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace Anabatic {
|
|
|
|
|
|
|
|
using std::cerr;
|
|
|
|
using std::endl;
|
|
|
|
using Hurricane::Error;
|
2016-05-30 11:52:38 -05:00
|
|
|
using Hurricane::UpdateSession;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
|
|
|
|
Name GCell::_extensionName = "Anabatic::GCell";
|
|
|
|
|
|
|
|
|
|
|
|
GCell::GCell ( AnabaticEngine* anabatic, DbU::Unit xmin, DbU::Unit ymin )
|
|
|
|
: Super(anabatic->getCell())
|
2016-06-03 10:29:22 -05:00
|
|
|
, _observable()
|
2016-05-23 09:15:25 -05:00
|
|
|
, _anabatic (anabatic)
|
|
|
|
, _flags (Flags::NoFlags)
|
|
|
|
, _westEdges ()
|
|
|
|
, _eastEdges ()
|
|
|
|
, _southEdges()
|
|
|
|
, _northEdges()
|
|
|
|
, _xmin (xmin)
|
|
|
|
, _ymin (ymin)
|
2016-05-30 04:30:29 -05:00
|
|
|
, _contacts ()
|
2016-05-23 09:15:25 -05:00
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_postCreate ()
|
|
|
|
{
|
|
|
|
Super::_postCreate();
|
2016-05-26 06:56:16 -05:00
|
|
|
_anabatic->_add( this );
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::create ( AnabaticEngine* anabatic )
|
|
|
|
{
|
|
|
|
if (not anabatic) throw Error( "GCell::create(): NULL anabatic argument." );
|
|
|
|
if (not anabatic->getCell()) throw Error( "GCell::create(): AnabaticEngine has no Cell loaded." );
|
|
|
|
|
|
|
|
GCell* gcell = new GCell ( anabatic
|
|
|
|
, anabatic->getCell()->getAbutmentBox().getXMin()
|
|
|
|
, anabatic->getCell()->getAbutmentBox().getYMin() );
|
|
|
|
gcell->_postCreate();
|
|
|
|
gcell->_revalidate();
|
|
|
|
return gcell;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::_create ( DbU::Unit xmin, DbU::Unit ymin )
|
|
|
|
{
|
|
|
|
GCell* gcell = new GCell ( getAnabatic(), xmin, ymin );
|
|
|
|
gcell->_postCreate();
|
|
|
|
return gcell;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell::~GCell ()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
void GCell::_destroyEdges ()
|
2016-05-23 09:15:25 -05:00
|
|
|
{
|
2016-05-26 11:30:03 -05:00
|
|
|
while (not _westEdges.empty()) (* _westEdges.rbegin())->destroy();
|
|
|
|
while (not _eastEdges.empty()) (* _eastEdges.rbegin())->destroy();
|
|
|
|
while (not _southEdges.empty()) (*_southEdges.rbegin())->destroy();
|
|
|
|
while (not _northEdges.empty()) (*_northEdges.rbegin())->destroy();
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
void GCell::_preDestroy ()
|
2016-05-23 09:15:25 -05:00
|
|
|
{
|
2016-05-26 11:30:03 -05:00
|
|
|
_destroyEdges();
|
|
|
|
_anabatic->_remove( this );
|
|
|
|
Super::_preDestroy();
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_remove ( Edge* edge, Flags side )
|
|
|
|
{
|
|
|
|
if (side.contains(Flags::WestSide )) erase_element( _westEdges, edge );
|
|
|
|
if (side.contains(Flags::EastSide )) erase_element( _eastEdges, edge );
|
|
|
|
if (side.contains(Flags::SouthSide)) erase_element( _southEdges, edge );
|
|
|
|
if (side.contains(Flags::NorthSide)) erase_element( _northEdges, edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_add ( Edge* edge, Flags side )
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,1) << "GCell::_add(side): side:" << side << " " << edge << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
if (side.contains(Flags::WestSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to West side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_westEdges.begin() ; iedge != _westEdges.end() ; ++iedge )
|
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 ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-05-23 09:15:25 -05:00
|
|
|
_westEdges.insert( iedge, edge );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_westEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (side.contains(Flags::EastSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to East side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_eastEdges.begin() ; iedge != _eastEdges.end() ; ++iedge )
|
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 ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-05-23 09:15:25 -05:00
|
|
|
_eastEdges.insert( iedge, edge );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_eastEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (side.contains(Flags::SouthSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to South side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_southEdges.begin() ; iedge != _southEdges.end() ; ++iedge )
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "| @" << DbU::getValueString((*iedge)->getAxisMin()) << " " << *iedge << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
for ( auto iedge=_southEdges.begin() ; iedge != _southEdges.end() ; ++iedge )
|
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 ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Insert *before* " << *iedge << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
_southEdges.insert( iedge, edge );
|
|
|
|
for ( auto iedge2=_southEdges.begin() ; iedge2 != _southEdges.end() ; ++iedge2 )
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "| @" << DbU::getValueString((*iedge2)->getAxisMin()) << " " << *iedge2 << endl;
|
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_southEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (side.contains(Flags::NorthSide)) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Adding to North side of " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
for ( auto iedge=_northEdges.begin() ; iedge != _northEdges.end() ; ++iedge )
|
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 ((*iedge)->getAxisMin() > edge->getAxisMin()) {
|
2016-05-23 09:15:25 -05:00
|
|
|
_northEdges.insert( iedge, edge );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_northEdges.push_back( edge );
|
|
|
|
}
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -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
|
|
|
bool GCell::hasGContact ( const Contact* owned ) const
|
|
|
|
{
|
|
|
|
for ( Contact* contact : _contacts ) {
|
|
|
|
if (contact == owned) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Edge* GCell::getEdgeTo ( GCell* neighbor, Flags sideHint ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : getEdges(sideHint) ) {
|
|
|
|
if (edge->getOpposite(this) == neighbor) return edge;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-26 06:56:16 -05:00
|
|
|
GCell* GCell::getWest ( DbU::Unit y ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _westEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if (y < side->getYMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getEast ( DbU::Unit y ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _eastEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
cerr << "east @Y: " << DbU::getValueString(y) << " " << side << endl;
|
|
|
|
if (y < side->getYMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getSouth ( DbU::Unit x ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _southEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if (x < side->getXMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getNorth ( DbU::Unit x ) const
|
|
|
|
{
|
|
|
|
for ( Edge* edge : _northEdges ) {
|
|
|
|
GCell* side = edge->getOpposite(this);
|
|
|
|
if (x < side->getXMax()) return side;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::getUnder ( DbU::Unit x, DbU::Unit y ) const
|
|
|
|
{
|
|
|
|
const GCell* current = this;
|
|
|
|
|
|
|
|
while ( current ) {
|
|
|
|
if (not current->isFlat() and current->getBoundingBox().contains(x,y)) break;
|
|
|
|
|
|
|
|
if (x >= current->getXMax()) { current = current->getEast (); continue; }
|
|
|
|
if (y >= current->getYMax()) { current = current->getNorth(); continue; }
|
|
|
|
|
|
|
|
cerr << Error( "GCell::getUnder(): No GCell under (%s,%s), this must *never* happen."
|
|
|
|
, DbU::getValueString(x).c_str()
|
|
|
|
, DbU::getValueString(y).c_str()
|
|
|
|
) << endl;
|
|
|
|
current = NULL; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return const_cast<GCell*>( current );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
Box GCell::getBorder ( const GCell* s, const GCell* t )
|
|
|
|
{
|
|
|
|
Flags flags = Flags::NoFlags;
|
|
|
|
flags |= (s->getXMax() == t->getXMin()) ? Flags::EastSide : 0;
|
|
|
|
flags |= (t->getXMax() == s->getXMin()) ? Flags::WestSide : 0;
|
|
|
|
flags |= (s->getYMax() == t->getYMin()) ? Flags::NorthSide : 0;
|
|
|
|
flags |= (t->getYMax() == s->getYMin()) ? Flags::SouthSide : 0;
|
|
|
|
|
|
|
|
if (flags & Flags::Vertical) {
|
|
|
|
if (flags & Flags::Horizontal) return Box();
|
|
|
|
if (flags & Flags::WestSide)
|
|
|
|
return Box( s->getXMin(), std::max( s->getYMin(), t->getYMin() )
|
|
|
|
, s->getXMin(), std::min( s->getYMax(), t->getYMax() ) );
|
|
|
|
else
|
|
|
|
return Box( t->getXMin(), std::max( s->getYMin(), t->getYMin() )
|
|
|
|
, t->getXMin(), std::min( s->getYMax(), t->getYMax() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & Flags::Horizontal) {
|
|
|
|
if (flags & Flags::Vertical) return Box();
|
|
|
|
if (flags & Flags::NorthSide)
|
|
|
|
return Box( std::max( s->getXMin(), t->getXMin() ), t->getYMin()
|
|
|
|
, std::min( s->getXMax(), t->getXMax() ), t->getYMin() );
|
|
|
|
else
|
|
|
|
return Box( std::max( s->getXMin(), t->getXMin() ), s->getYMin()
|
|
|
|
, std::min( s->getXMax(), t->getXMax() ), s->getYMin() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return Box();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::vcut ( DbU::Unit x )
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(119,1) << "GCell::vcut() @x:" << DbU::getValueString(x) << " " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if ( (x < getXMin()) or (x > getXMax()) )
|
|
|
|
throw Error( "GCell::vcut(): Vertical cut axis at %s is outside GCell box,\n"
|
|
|
|
" in %s."
|
|
|
|
, DbU::getValueString(x).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
);
|
|
|
|
|
|
|
|
GCell* chunk = _create( x, getYMin() );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(119,0) << "New chunk:" << chunk << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
_moveEdges( chunk, 0, Flags::EastSide );
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( this, chunk, Flags::Horizontal );
|
|
|
|
|
|
|
|
if (not _southEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Split/create south edges." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _southEdges.size()) ; ++iedge ) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "[" << iedge << "] xmax of:"
|
2016-05-23 09:15:25 -05:00
|
|
|
<< _southEdges[iedge]->getOpposite(this)
|
|
|
|
<< " " << _southEdges[iedge] << endl;
|
|
|
|
if (x <= _southEdges[iedge]->getOpposite(this)->getXMax()) break;
|
|
|
|
}
|
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 ( (x < _southEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
or ( (x == _southEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
and (chunk->getXMax() == getXMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( _southEdges[iedge]->getOpposite(this), chunk, Flags::Vertical );
|
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-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::SouthSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not _northEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "Split/create north edges." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _northEdges.size()) ; ++iedge )
|
|
|
|
if (x <= _northEdges[iedge]->getOpposite(this)->getXMax()) break;
|
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 ( (x < _northEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
or ( (x == _northEdges[iedge]->getOpposite(this)->getXMax())
|
|
|
|
and (chunk->getXMax() == getXMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( chunk, _northEdges[iedge]->getOpposite(this), Flags::Vertical );
|
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-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::NorthSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
_revalidate();
|
|
|
|
chunk->_revalidate();
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(119,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GCell* GCell::hcut ( DbU::Unit y )
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(119,1) << "GCell::hcut() @y:" << DbU::getValueString(y) << " " << this << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if ( (y < getYMin()) or (y > getYMax()) )
|
|
|
|
throw Error( "GCell::hcut(): Horizontal cut axis at %s is outside GCell box,\n"
|
|
|
|
" in %s."
|
|
|
|
, DbU::getValueString(y).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
);
|
|
|
|
|
|
|
|
GCell* chunk = _create( getXMin(), y );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(119,0) << "New chunk:" << chunk << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
2016-05-26 11:30:03 -05:00
|
|
|
_moveEdges( chunk, 0, Flags::NorthSide );
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( this, chunk, Flags::Vertical );
|
|
|
|
|
|
|
|
if (not _westEdges.empty()) {
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _westEdges.size()) ; ++iedge )
|
|
|
|
if (y <= _westEdges[iedge]->getOpposite(this)->getYMax()) break;
|
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 ( (y < _westEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
or ( (y == _westEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
and (chunk->getYMax() == getYMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( _westEdges[iedge]->getOpposite(this), chunk, Flags::Horizontal );
|
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-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::WestSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not _eastEdges.empty()) {
|
|
|
|
size_t iedge = 0;
|
|
|
|
for ( ; (iedge < _eastEdges.size()) ; ++iedge )
|
|
|
|
if (y <= _eastEdges[iedge]->getOpposite(this)->getYMax()) break;
|
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 ( (y < _eastEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
or ( (y == _eastEdges[iedge]->getOpposite(this)->getYMax())
|
|
|
|
and (chunk->getYMax() == getYMax())) )
|
2016-05-23 09:15:25 -05:00
|
|
|
Edge::create( chunk, _eastEdges[iedge]->getOpposite(this), Flags::Horizontal );
|
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-23 09:15:25 -05:00
|
|
|
_moveEdges( chunk, iedge+1, Flags::EastSide );
|
|
|
|
}
|
|
|
|
|
|
|
|
_revalidate();
|
|
|
|
chunk->_revalidate();
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(119,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool GCell::doGrid ()
|
|
|
|
{
|
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
|
|
|
const vector<GCell*>& gcells = getAnabatic()->getGCells();
|
|
|
|
size_t ibegin = gcells.size();
|
|
|
|
DbU::Unit side = getAnabatic()->getConfiguration()->getSliceHeight();
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
Interval hspan = getSide( Flags::Horizontal );
|
|
|
|
Interval vspan = getSide( Flags::Vertical );
|
|
|
|
|
|
|
|
if (hspan.getSize() < 3*side) {
|
|
|
|
cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n"
|
|
|
|
" (%s)"
|
|
|
|
, DbU::getValueString(hspan.getSize()).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vspan.getSize() < 3*side) {
|
|
|
|
cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n"
|
|
|
|
" (%s)"
|
|
|
|
, DbU::getValueString(vspan.getSize()).c_str()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
//UpdateSession::open();
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
GCell* row = this;
|
|
|
|
GCell* column = NULL;
|
|
|
|
DbU::Unit ycut = vspan.getVMin()+side;
|
|
|
|
for ( ; ycut < vspan.getVMax() ; ycut += side ) {
|
|
|
|
column = row;
|
|
|
|
row = row->hcut( ycut );
|
|
|
|
|
|
|
|
for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) {
|
|
|
|
column = column->vcut( xcut );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
column = row;
|
|
|
|
for ( DbU::Unit xcut = hspan.getVMin()+side ; xcut < hspan.getVMax() ; xcut += side ) {
|
|
|
|
column = column->vcut( xcut );
|
|
|
|
}
|
|
|
|
|
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
|
|
|
size_t hLocal = - getAnabatic()->getConfiguration()->getHEdgeLocal();
|
|
|
|
size_t vLocal = - getAnabatic()->getConfiguration()->getVEdgeLocal();
|
|
|
|
for ( ; ibegin < gcells.size() ; ++ibegin ) {
|
|
|
|
for ( Edge* edge : gcells[ibegin]->getEdges(Flags::NorthSide|Flags::EastSide) ) {
|
|
|
|
if (edge->isHorizontal()) edge->incCapacity( hLocal );
|
|
|
|
else edge->incCapacity( vLocal );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-10 11:27:06 -05:00
|
|
|
//UpdateSession::close();
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_revalidate ()
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,1) << "GCell::revalidate() " << this << endl;
|
|
|
|
cdebug_log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
|
|
|
cdebug_log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
|
|
|
cdebug_log(110,1) << "South side." << endl; for ( Edge* edge : _southEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
|
|
|
cdebug_log(110,1) << "North side." << endl; for ( Edge* edge : _northEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
|
2016-05-26 06:56:16 -05:00
|
|
|
if (_xmin > getXMax()+1)
|
|
|
|
cerr << Error( "GCell::_revalidate(): %s, X Min is greater than Max.", getString(this).c_str() );
|
|
|
|
if (_ymin > getYMax()+1)
|
|
|
|
cerr << Error( "GCell::_revalidate(): %s, Y Min is greater than Max.", getString(this).c_str() );
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
_anabatic->_updateLookup( this );
|
2016-06-17 06:09:34 -05:00
|
|
|
//_anabatic->getMatrix()->show();
|
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::_moveEdges ( GCell* dest, size_t ibegin, Flags flags )
|
|
|
|
{
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,1) << "GCell::_moveEdges() " << this << endl;
|
|
|
|
cdebug_log(110,0) << " toward " << dest << endl;
|
|
|
|
cdebug_log(110,0) << " ibegin: " << ibegin << " flags:" << flags << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
size_t iclear = ibegin;
|
|
|
|
|
|
|
|
if (flags.contains(Flags::SouthSide) and not _southEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "South side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _southEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _southEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_southEdges[iedge]->_setTarget( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_southEdges.push_back( _southEdges[iedge] );
|
|
|
|
}
|
|
|
|
_southEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _southEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On south side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _southEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.contains(Flags::NorthSide) and not _northEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "North side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _northEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _northEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_northEdges[iedge]->_setSource( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_northEdges.push_back( _northEdges[iedge] );
|
|
|
|
}
|
|
|
|
_northEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _northEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On north side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _northEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.contains(Flags::WestSide) and not _westEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "West side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _westEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _westEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_westEdges[iedge]->_setTarget( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_westEdges.push_back( _westEdges[iedge] );
|
|
|
|
}
|
|
|
|
_westEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _westEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On west side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _westEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.contains(Flags::EastSide) and not _eastEdges.empty()) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(110,0) << "East side." << endl;
|
2016-05-23 09:15:25 -05:00
|
|
|
|
|
|
|
if (iclear < _eastEdges.size()) {
|
|
|
|
for ( size_t iedge=ibegin ; (iedge < _eastEdges.size()) ; ++iedge ) {
|
2016-05-26 06:56:16 -05:00
|
|
|
_eastEdges[iedge]->_setSource( dest );
|
2016-05-23 09:15:25 -05:00
|
|
|
dest->_eastEdges.push_back( _eastEdges[iedge] );
|
|
|
|
}
|
|
|
|
_eastEdges.resize( iclear );
|
|
|
|
} else {
|
|
|
|
if (iclear > _eastEdges.size())
|
|
|
|
cerr << Error("GCell::_moveEdges(): On east side, iclear=%u is greater than size()-1=%u\n"
|
|
|
|
" (%s)"
|
|
|
|
, iclear
|
|
|
|
, _eastEdges.size()
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_tabw(110,-1);
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
Contact* GCell::getGContact ( Net* net )
|
|
|
|
{
|
2016-05-30 11:52:38 -05:00
|
|
|
|
2016-05-30 04:30:29 -05:00
|
|
|
for ( Contact* contact : _contacts ) {
|
2016-05-30 11:52:38 -05:00
|
|
|
if (contact->getNet() == net) {
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << "GCell::getGContact(): " << contact << endl;
|
2016-05-30 11:52:38 -05:00
|
|
|
return contact;
|
|
|
|
}
|
2016-05-30 04:30:29 -05:00
|
|
|
}
|
|
|
|
|
2016-05-30 11:52:38 -05:00
|
|
|
Point center = getBoundingBox().getCenter();
|
|
|
|
Contact* contact = Contact::create( net
|
|
|
|
, _anabatic->getConfiguration()->getGContactLayer()
|
|
|
|
, center.getX()
|
|
|
|
, center.getY()
|
|
|
|
, DbU::fromLambda(2.0)
|
|
|
|
, DbU::fromLambda(2.0)
|
|
|
|
);
|
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
|
|
|
_contacts.push_back( contact );
|
2016-06-17 06:09:34 -05:00
|
|
|
cdebug_log(111,0) << "GCell::getGContact(): " << contact << endl;
|
2016-05-30 11:52:38 -05:00
|
|
|
return contact;
|
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
|
|
|
bool GCell::unrefContact ( Contact* unref )
|
|
|
|
{
|
|
|
|
if (_contacts.empty()) return false;
|
|
|
|
|
|
|
|
for ( size_t i=0 ; i< _contacts.size() ; ++i ) {
|
|
|
|
if (_contacts[i] == unref) {
|
|
|
|
if (_contacts[i]->getSlaveComponents().getLocator()->isValid()) return false;
|
|
|
|
|
|
|
|
std::swap( _contacts[i], _contacts[_contacts.size()-1] );
|
|
|
|
_contacts[ _contacts.size()-1 ]->destroy();
|
|
|
|
_contacts.pop_back();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
const Name& GCell::getName () const
|
|
|
|
{ return _extensionName; }
|
|
|
|
|
|
|
|
|
|
|
|
Box GCell::getBoundingBox () const
|
|
|
|
{
|
2016-05-26 06:56:16 -05:00
|
|
|
return Box( getXMin(), getYMin(), getXMax(1), getYMax(1) );
|
2016-05-23 09:15:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GCell::translate ( const DbU::Unit&, const DbU::Unit& )
|
|
|
|
{
|
|
|
|
cerr << Error( "GCell::translate(): On %s,\n"
|
|
|
|
" Must never be called on a GCell object (ignored)."
|
|
|
|
, getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isNorth ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _northEdges.begin(); it != _northEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isSouth ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _southEdges.begin(); it != _southEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isEast ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _eastEdges.begin(); it != _eastEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-26 07:55:34 -05:00
|
|
|
bool GCell::isWest ( GCell* c ) const
|
2016-06-17 09:26:27 -05:00
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (vector<Edge*>::const_iterator it = _westEdges.begin(); it != _westEdges.end(); it++){
|
2016-06-20 11:36:00 -05:00
|
|
|
if ( (*it)->getOpposite(this)->getId() == c->getId() ) {
|
2016-06-17 09:26:27 -05:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-23 09:15:25 -05:00
|
|
|
string GCell::_getTypeName () const
|
|
|
|
{ return getString(_extensionName); }
|
|
|
|
|
|
|
|
|
|
|
|
string GCell::_getString () const
|
|
|
|
{
|
|
|
|
string s = Super::_getString();
|
|
|
|
s.insert( s.size()-1, " "+getString(getBoundingBox()) );
|
|
|
|
s.insert( s.size()-1, " "+getString(_flags) );
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Record* GCell::_getRecord () const
|
|
|
|
{
|
|
|
|
Record* record = Super::_getRecord();
|
|
|
|
record->add( getSlot("_flags" , &_flags ) );
|
|
|
|
record->add( getSlot("_westEdges" , &_westEdges ) );
|
|
|
|
record->add( getSlot("_eastEdges" , &_eastEdges ) );
|
|
|
|
record->add( getSlot("_southEdges", &_southEdges) );
|
|
|
|
record->add( getSlot("_northEdges", &_northEdges) );
|
|
|
|
record->add( DbU::getValueSlot("_xmin", &_xmin) );
|
|
|
|
record->add( DbU::getValueSlot("_ymin", &_ymin) );
|
|
|
|
return record;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // Anabatic namespace.
|