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.
This commit is contained in:
Jean-Paul Chaput 2016-06-26 14:32:32 +02:00
parent 379effd92c
commit abf58190eb
15 changed files with 837 additions and 168 deletions

View File

@ -18,6 +18,8 @@
#include <iostream>
#include "hurricane/Error.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/UpdateSession.h"
#include "crlcore/RoutingGauge.h"
@ -33,6 +35,9 @@ namespace Anabatic {
using std::ostringstream;
using Hurricane::Error;
using Hurricane::RegularLayer;
using Hurricane::Component;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using Hurricane::UpdateSession;
using CRL::RoutingGauge;
@ -63,6 +68,7 @@ namespace Anabatic {
, _configuration (new ConfigurationConcrete())
, _matrix ()
, _gcells ()
, _ovEdges ()
, _viewer (NULL)
, _flags (Flags::NoFlags)
, _stamp (-1)
@ -114,6 +120,7 @@ namespace Anabatic {
for ( GCell* gcell : _gcells ) gcell->_destroyEdges();
for ( GCell* gcell : _gcells ) gcell->destroy();
_gcells.clear();
_ovEdges.clear();
}
@ -164,6 +171,39 @@ namespace Anabatic {
}
size_t AnabaticEngine::getNetsFromEdge ( const Edge* edge, NetSet& nets )
{
size_t count = 0;
GCell* source = edge->getSource();
GCell* target = edge->getTarget();
const vector<Contact*>& contacts = source->getGContacts();
for ( Contact* contact : contacts ) {
for ( Component* component : contact->getSlaveComponents() ) {
if (edge->isHorizontal()) {
Horizontal* horizontal = dynamic_cast<Horizontal*>( component );
if (horizontal
and (horizontal->getSource() == contact)
and (target->hasGContact(dynamic_cast<Contact*>(horizontal->getTarget())))) {
nets.insert( horizontal->getNet() );
++count;
}
}
if (edge->isVertical()) {
Vertical* vertical = dynamic_cast<Vertical*>( component );
if (vertical
and (vertical->getSource() == contact)
and (target->hasGContact(dynamic_cast<Contact*>(vertical->getTarget())))) {
nets.insert( vertical->getNet() );
++count;
}
}
}
}
return count;
}
void AnabaticEngine::startMeasures ()
{
_timer.resetIncrease();

View File

@ -32,6 +32,7 @@ endif ( CHECK_DETERMINISM )
Edges.cpp
GCell.cpp
AnabaticEngine.cpp
GlobalRoute.cpp
GraphicAnabaticEngine.cpp
Dijkstra.cpp
)

View File

@ -75,6 +75,8 @@ namespace Anabatic {
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH", 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK",-10.0)->asDouble())
, _hEdgeLocal (Cfg::getParamInt("kite.hTracksReservedLocal",0)->asInt())
, _vEdgeLocal (Cfg::getParamInt("kite.vTracksReservedLocal",0)->asInt())
{
if (cg == NULL) cg = AllianceFramework::get()->getCellGauge();
if (rg == NULL) rg = AllianceFramework::get()->getRoutingGauge();
@ -288,6 +290,14 @@ namespace Anabatic {
{ return _edgeWidth; }
size_t ConfigurationConcrete::getHEdgeLocal () const
{ return _hEdgeLocal; }
size_t ConfigurationConcrete::getVEdgeLocal () const
{ return _vEdgeLocal; }
float ConfigurationConcrete::getEdgeCostH () const
{ return _edgeCostH; }

View File

@ -35,6 +35,7 @@ namespace Anabatic {
using Hurricane::ForEachIterator;
using Hurricane::Error;
using Hurricane::Component;
using Hurricane::Segment;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::RoutingPad;
@ -63,7 +64,7 @@ namespace Anabatic {
string s = "<Vertex " + getString(_id)
+ " @(" + DbU::getValueString(_gcell->getXMin())
+ "," + DbU::getValueString(_gcell->getYMin()) + ")"
+ " connexId:" + getString(_connexId)
+ " connexId:" + ((_connexId >= 0) ? getString(_connexId) : "None")
+ " d:" + ((_distance == unreached) ? "unreached" : DbU::getValueString(_distance) )
+ "+" + getString(_branchId)
+ " stamp:" + (hasValidStamp() ? "valid" : "outdated")
@ -143,27 +144,45 @@ namespace Anabatic {
void Dijkstra::load ( Net* net )
{
_net = net;
_cleanup();
const Layer* gcontactLayer = _anabatic->getConfiguration()->getGContactLayer();
_net = net;
_stamp = _anabatic->incStamp();
DebugSession::open( _net, 112, 120 );
cdebug_log(112,1) << "Dijkstra::load() " << _net << endl;
_sources.clear();
_targets.clear();
_searchArea.makeEmpty();
_stamp = _anabatic->incStamp();
vector< std::pair<Component*,bool> > components;
for ( Component* component : _net->getComponents() ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( component );
if (rp) { components.push_back( make_pair(rp,true) ); continue; }
vector<RoutingPad*> rps;
for ( RoutingPad* rp : _net->getRoutingPads() ) rps.push_back( rp );
for ( RoutingPad* rp : rps ) {
Box rpBb = rp->getBoundingBox();
Point center = rpBb.getCenter();
GCell* gcell = _anabatic->getGCellUnder( center );
Contact* gcontact = dynamic_cast<Contact*>( component );
if (gcontact and (gcontact->getLayer() == gcontactLayer))
components.push_back( make_pair(gcontact,false) );
}
for ( auto element : components ) {
RoutingPad* rp = NULL;
Contact* gcontact = NULL;
Point center;
if (element.second) {
rp = static_cast<RoutingPad*>( element.first );
center = rp->getBoundingBox().getCenter();
} else {
gcontact = static_cast<Contact*>( element.first );
center = gcontact->getCenter();
}
GCell* gcell = _anabatic->getGCellUnder( center );
if (not gcell) {
cerr << Error( "Dijkstra::load(): %s of %s is not under any GCell.\n"
" It will be ignored ans the routing will be incomplete."
, getString(rp ).c_str()
" It will be ignored so the routing may be incomplete."
, getString(element.first).c_str()
, getString(_net).c_str()
) << endl;
continue;
@ -175,22 +194,76 @@ namespace Anabatic {
if (vertex->getConnexId() < 0) {
vertex->setDistance( Vertex::unreached );
vertex->setStamp ( _stamp );
vertex->setConnexId( _targets.size() );
vertex->setConnexId( _connectedsId );
vertex->setBranchId( 0 );
vertex->setFrom ( NULL );
_targets.insert( vertex );
cdebug_log(112,0) << "Add Vertex: " << vertex << endl;
}
Contact* gcontact = vertex->getGContact( _net );
rp->getBodyHook()->detach();
rp->getBodyHook()->attach( gcontact->getBodyHook() );
if (gcontact) {
for ( Component* slave : gcontact->getSlaveComponents() ) {
Flags sideHint = Flags::NoFlags;
GCell* oppositeGCell = NULL;
Segment* segment = dynamic_cast<Horizontal*>(slave);
if (segment) {
cdebug_log(112,0) << "| " << segment << endl;
if (segment->getSource() == gcontact) {
oppositeGCell = _anabatic->getGCellUnder( segment->getTarget()->getCenter() );
sideHint = Flags::EastSide;
} else
if (segment->getTarget() == gcontact) {
cdebug_log(112,0) << " Connected by target, skipped." << endl;
continue;
}
} else {
segment = dynamic_cast<Vertical*>(slave);
if (segment) {
cdebug_log(112,0) << "| " << segment << endl;
if (segment->getSource() == gcontact) {
oppositeGCell = _anabatic->getGCellUnder( segment->getTarget()->getCenter() );
sideHint = Flags::NorthSide;
} else
if (segment->getTarget() == gcontact) {
cdebug_log(112,0) << " Connected by target, skipped." << endl;
continue;
}
}
}
Edge* edge = gcell->getEdgeTo( oppositeGCell, sideHint );
if (edge) {
cdebug_log(112,0) << "+ Associated to edge." << endl;
edge->setSegment( segment );
} else
cerr << Error( "Dijkstra::load(): Cannot bind segment to any edge:\n"
" %s\n"
" source:%s\n"
" target:%s"
, getString(segment).c_str()
, getString(gcell).c_str()
, getString(oppositeGCell).c_str()
) << endl;
}
}
if (rp) {
Contact* vcontact = vertex->getGContact( _net );
rp->getBodyHook()->detach();
rp->getBodyHook()->attach( vcontact->getBodyHook() );
}
}
for ( Vertex* vertex : _targets ) {
if (vertex->getConnexId() != 0) continue;
_tagConnecteds( vertex, ++_connectedsId );
}
cdebug_log(112,0) << "Search area: " << _searchArea << endl;
cdebug_tabw(112,-1);
DebugSession::close();
}
}
void Dijkstra::_selectFirstSource ()
@ -240,13 +313,35 @@ namespace Anabatic {
}
}
_targets.erase ( firstSource );
_sources.insert( firstSource );
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;
}
cdebug_log(112,0) << "Dijkstra::_selectFirstSource() " << *_sources.begin() << endl;
}
void Dijkstra::_cleanup ()
{
for ( Vertex* vertex : _sources ) if (vertex->getFrom()) vertex->getFrom()->setSegment( NULL );
for ( Vertex* vertex : _targets ) if (vertex->getFrom()) vertex->getFrom()->setSegment( NULL );
//_checkEdges();
_sources.clear();
_targets.clear();
_searchArea.makeEmpty();
_connectedsId = 0;
}
bool Dijkstra::_propagate ( Flags enabledSides )
{
cdebug_log(112,1) << "Dijkstra::_propagate() " << _net << endl;
@ -301,6 +396,7 @@ namespace Anabatic {
// We did reach another target (different <connexId>).
// Tag back the path, with a higher <branchId>.
_traceback( current );
cdebug_tabw(112,-1);
return true;
}
@ -345,21 +441,23 @@ namespace Anabatic {
Contact* sourceContact = source->getGContact( _net );
Contact* targetContact = target->getGContact( _net );
Segment* segment = NULL;
if (from->isHorizontal()) {
Horizontal::create( sourceContact
, targetContact
, _anabatic->getConfiguration()->getGHorizontalLayer()
, from->getAxis()
, DbU::fromLambda(2.0)
);
segment = Horizontal::create( sourceContact
, targetContact
, _anabatic->getConfiguration()->getGHorizontalLayer()
, from->getAxis()
, DbU::fromLambda(2.0)
);
} else {
Vertical::create( sourceContact
, targetContact
, _anabatic->getConfiguration()->getGVerticalLayer()
, from->getAxis()
, DbU::fromLambda(2.0)
);
segment = Vertical::create( sourceContact
, targetContact
, _anabatic->getConfiguration()->getGVerticalLayer()
, from->getAxis()
, DbU::fromLambda(2.0)
);
}
from->setSegment( segment );
}
cdebug_tabw(112,-1);
@ -388,15 +486,16 @@ namespace Anabatic {
enabledEdges = Flags::EastSide | Flags::SouthSide;
}
Vertex* source = *_sources.begin();
_queue.clear();
_queue.push( source );
_connectedsId = source->getConnexId();
source->setDistance( 0.0 );
_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;
}
cdebug_log(112,0) << "Push source: (size:" << _queue.size() << ") "
<< source
<< " _connectedsId:" << _connectedsId << endl;
while ( not _targets.empty() and _propagate(enabledEdges) );
@ -407,4 +506,157 @@ namespace Anabatic {
}
void Dijkstra::ripup ( Edge* edge )
{
DebugSession::open( _net, 112, 120 );
cdebug_log(112,1) << "Dijkstra::ripup(): " << edge << endl;
GCell* gsource = edge->getSource();
GCell* gtarget = edge->getTarget();
Vertex* vsource = gsource->getObserver<Vertex>(GCell::Observable::Vertex);
Vertex* vtarget = gtarget->getObserver<Vertex>(GCell::Observable::Vertex);
if ( (not isSourceVertex(vsource) and not isTargetVertex(vsource))
or (not isSourceVertex(vtarget) and not isTargetVertex(vtarget)) ) {
cerr << Error( "Dijkstra::ripup(): %s do *not* belong to %s (ignored)."
, getString(edge).c_str()
, getString(_net).c_str()
) << endl;
cdebug_tabw(112,-1);
DebugSession::close();
return;
}
edge->destroySegment();
// for ( Contact* contact : gsource->getGContacts() ) {
// if (contact->getNet() != _net) continue;
// for ( Component* component : contact->getSlaveComponents() ) {
// Segment* segment = dynamic_cast<Segment*>( component );
// if (segment and (gtarget->hasGContact(dynamic_cast<Contact*>(segment->getTarget())))) {
// segment->destroy();
// break;
// }
// }
// break;
// }
edge->incRealOccupancy( -1 );
_propagateRipup( vsource );
vtarget = _propagateRipup( vtarget );
_tagConnecteds( vtarget, ++_connectedsId );
cdebug_tabw(112,-1);
DebugSession::close();
}
Vertex* Dijkstra::_propagateRipup ( Vertex* end )
{
cdebug_log(112,1) << "Dijkstra::_propagateRipup() from:" << end << endl;
while ( end ) {
cdebug_log(112,0) << "| " << end << endl;
Contact* gcontact = end->getGCell()->getGContact( _net );
if (not gcontact) {
cdebug_log(112,0) << "Exiting on missing GContact." << endl;
cdebug_tabw(112,-1);
return end;
}
Edge* eneighbor = NULL;
for ( Edge* edge : end->getGCell()->getEdges() ) {
if (edge->getSegment()) {
if (not eneighbor) eneighbor = edge;
else {
eneighbor = NULL;
break;
}
}
}
for ( Component* component : gcontact->getSlaveComponents() ) {
if (dynamic_cast<RoutingPad*>(component)) {
eneighbor = NULL;
break;
}
}
if (not eneighbor) {
cdebug_log(112,0) << "Normal exit (fork or RoutingPad)." << endl;
cdebug_tabw(112,-1);
return end;
}
cdebug_log(112,0) << "+ " << eneighbor << endl;
eneighbor->incRealOccupancy( -1 );
eneighbor->destroySegment();
eneighbor->setSegment( NULL );
end->setConnexId( -1 );
end->setDistance( Vertex::unreached );
end = eneighbor->getOpposite(end->getGCell())->getObserver<Vertex>(GCell::Observable::Vertex);;
}
cdebug_log(112,0) << "Exiting on nothing left." << endl;
cdebug_tabw(112,-1);
return NULL;
}
void Dijkstra::_tagConnecteds ( Vertex* source, int connexId )
{
cdebug_log(112,1) << "Dijkstra::_tagConnecteds()" << endl;
source->setConnexId( connexId );
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() ) {
if (not edge->getSegment()) {
cdebug_log(112,0) << " Not connected:" << edge << endl;
continue;
}
GCell* gneighbor = edge->getOpposite(source->getGCell());
Vertex* vneighbor = gneighbor->getObserver<Vertex>(GCell::Observable::Vertex);
if (not vneighbor->hasValidStamp()) continue;
if (vneighbor->getConnexId() == connexId) continue;
vneighbor->setConnexId( connexId );
stack.insert( vneighbor );
}
}
cdebug_tabw(112,-1);
}
void Dijkstra::_checkEdges () const
{
cdebug_log(112,1) << "Dijkstra::_checkEdges()" << endl;
for ( Vertex* vertex : _vertexes ) {
for ( Edge* edge : vertex->getGCell()->getEdges(Flags::EastSide|Flags::NorthSide) ) {
if (edge->getSegment()) {
cdebug_log(112,0) << "Not reset:" << edge << edge->getSegment() << endl;
}
}
}
cdebug_tabw(112,-1);
}
} // Anabatic namespace.

View File

@ -16,6 +16,7 @@
#include <iostream>
#include "hurricane/Error.h"
#include "hurricane/Segment.h"
#include "anabatic/Edge.h"
#include "anabatic/GCell.h"
#include "anabatic/AnabaticEngine.h"
@ -41,6 +42,7 @@ namespace Anabatic {
, _source (source)
, _target (target)
, _axis (0)
, _segment (NULL)
{ }
@ -170,6 +172,30 @@ namespace Anabatic {
}
void Edge::incRealOccupancy ( int delta )
{
unsigned int occupancy = 0;
if ((int)_realOccupancy + delta > 0) occupancy = _realOccupancy + delta;
if ((_realOccupancy <= _capacity) and (occupancy > _capacity)) getAnabatic()->addOv ( this );
if ((_realOccupancy > _capacity) and (occupancy <= _capacity)) getAnabatic()->removeOv( this );
_realOccupancy = occupancy;
}
void Edge::destroySegment ()
{
if (not _segment) return;
Contact* csource = dynamic_cast<Contact*>( _segment->getSource() );
Contact* ctarget = dynamic_cast<Contact*>( _segment->getTarget() );
_segment->destroy();
_segment = NULL;
if (csource) getSource()->unrefContact( csource );
if (ctarget) getTarget()->unrefContact( ctarget );
}
void Edge::_setSource ( GCell* source )
{
if (source == _target)

View File

@ -46,7 +46,7 @@ namespace Anabatic {
Edge* GCell_Edges::Locator::getElement () const
{
{
if (_stateFlags.contains(Flags::EastSide )) return _gcell->getEastEdges ()[_iedge];
if (_stateFlags.contains(Flags::NorthSide)) return _gcell->getNorthEdges()[_iedge];
if (_stateFlags.contains(Flags::WestSide )) return _gcell->getWestEdges ()[_iedge];
@ -61,40 +61,45 @@ namespace Anabatic {
void GCell_Edges::Locator::progress ()
{
// cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl;
// cdebug_log(110,0) << " East:" << _gcell->getEastEdges().size()
// << " North:" << _gcell->getNorthEdges().size()
// << " West:" << _gcell->getWestEdges().size()
// << " South:" << _gcell->getSouthEdges().size() << endl;
// cdebug_log(110,0) << this << endl;
cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl;
cdebug_log(110,0) << " _filterFlags:" << _filterFlags << endl;
cdebug_log(110,0) << " East:" << _gcell->getEastEdges().size()
<< " North:" << _gcell->getNorthEdges().size()
<< " West:" << _gcell->getWestEdges().size()
<< " South:" << _gcell->getSouthEdges().size() << endl;
cdebug_log(110,0) << this << endl;
++_iedge;
while (_stateFlags) {
if ((_stateFlags & _filterFlags).contains(Flags::EastSide)) {
if (_iedge < _gcell->getEastEdges().size()) break;
if (_stateFlags.contains(Flags::EastSide)) {
if ( (_iedge < _gcell->getEastEdges().size())
and _filterFlags.contains(Flags::EastSide)) break;
// cdebug_log(110,0) << "Switching to North side." << endl;
_stateFlags = Flags::NorthSide;
_iedge = 0;
// cdebug_log(110,0) << this << endl;
continue;
}
if ((_stateFlags & _filterFlags).contains(Flags::NorthSide)) {
if (_iedge < _gcell->getNorthEdges().size()) break;
if (_stateFlags.contains(Flags::NorthSide)) {
if ( (_iedge < _gcell->getNorthEdges().size())
and _filterFlags.contains(Flags::NorthSide)) break;
// cdebug_log(110,0) << "Switching to West side." << endl;
_stateFlags = Flags::WestSide;
_iedge = 0;
// cdebug_log(110,0) << this << endl;
continue;
}
if ((_stateFlags & _filterFlags).contains(Flags::WestSide)) {
if (_iedge < _gcell->getWestEdges().size()) break;
if (_stateFlags.contains(Flags::WestSide)) {
if ( (_iedge < _gcell->getWestEdges().size())
and _filterFlags.contains(Flags::WestSide)) break;
// cdebug_log(110,0) << "Switching to South side." << endl;
_stateFlags = Flags::SouthSide;
_iedge = 0;
continue;
}
if ((_stateFlags & _filterFlags).contains(Flags::SouthSide)) {
if (_iedge < _gcell->getSouthEdges().size()) break;
if (_stateFlags.contains(Flags::SouthSide)) {
if ( (_iedge < _gcell->getSouthEdges().size())
and _filterFlags.contains(Flags::SouthSide)) break;
// cdebug_log(110,0) << "All edges done." << endl;
_stateFlags = 0;
_iedge = 0;
@ -102,7 +107,7 @@ namespace Anabatic {
}
}
//cdebug_log(110,0) << "GCell_Edges::Locator::progress() [to] " << _stateFlags << " iedge:" << _iedge << endl;
cdebug_log(110,0) << "GCell_Edges::Locator::progress() [to] " << _stateFlags << " iedge:" << _iedge << endl;
}

View File

@ -164,6 +164,24 @@ namespace Anabatic {
}
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;
}
GCell* GCell::getWest ( DbU::Unit y ) const
{
for ( Edge* edge : _westEdges ) {
@ -372,7 +390,9 @@ namespace Anabatic {
bool GCell::doGrid ()
{
DbU::Unit side = getAnabatic()->getConfiguration()->getSliceHeight();
const vector<GCell*>& gcells = getAnabatic()->getGCells();
size_t ibegin = gcells.size();
DbU::Unit side = getAnabatic()->getConfiguration()->getSliceHeight();
Interval hspan = getSide( Flags::Horizontal );
Interval vspan = getSide( Flags::Vertical );
@ -414,6 +434,15 @@ namespace Anabatic {
column = column->vcut( xcut );
}
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 );
}
}
//UpdateSession::close();
return true;
@ -549,11 +578,32 @@ namespace Anabatic {
, DbU::fromLambda(2.0)
, DbU::fromLambda(2.0)
);
_contacts.push_back( contact );
cdebug_log(111,0) << "GCell::getGContact(): " << contact << endl;
return contact;
}
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;
}
const Name& GCell::getName () const
{ return _extensionName; }

View File

@ -0,0 +1,195 @@
// -*- C++ -*-
//
// 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 : "./GlobalRoute.cpp" |
// +-----------------------------------------------------------------+
#include <sstream>
#include <iostream>
#include "hurricane/Error.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/Cell.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "anabatic/GCell.h"
#include "anabatic/Dijkstra.h"
#include "anabatic/AnabaticEngine.h"
namespace {
using std::cerr;
using std::endl;
using std::setw;
using std::left;
using std::right;
using Hurricane::DbU;
using Anabatic::Edge;
using Anabatic::Vertex;
class DigitalDistance {
public:
inline DigitalDistance ( float h, float k );
DbU::Unit operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const;
private:
// For an explanation of h & k parameters, see:
// "KNIK, routeur global pour la plateforme Coriolis", p. 52.
float _h;
float _k;
};
inline DigitalDistance::DigitalDistance ( float h, float k ) : _h(h), _k(k) { }
DbU::Unit DigitalDistance::operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const
{
if (edge->getCapacity() <= 0) return Vertex::unreached;
float congestion = (float)edge->getRealOccupancy() / (float)edge->getCapacity();
float congestionCost = 1.0 + _h / (1.0 + std::exp(_k * (congestion - 1.0)));
float distance = (float)source->getDistance() + congestionCost * (float)edge->getDistance();
// Edge* sourceFrom = source->getFrom();
// if (sourceFrom) {
// distance += ((sourceFrom->isHorizontal() xor edge->isHorizontal()) ? 3.0 : 0.0) * (float)Edge::unity;
// }
cdebug_log(112,0) << "cong:" << congestion
<< " ccost:" << congestionCost
<< " digitalDistance:" << DbU::getValueString((DbU::Unit)distance) << endl;
return (DbU::Unit)distance;
}
} // Anonymous namespace.
namespace Anabatic {
using std::cerr;
using std::cout;
using std::endl;
using std::setw;
using std::ostringstream;
using Hurricane::Error;
using Hurricane::RegularLayer;
using Hurricane::Component;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::Cell;
using Hurricane::UpdateSession;
using Hurricane::DebugSession;
using CRL::RoutingGauge;
using CRL::RoutingLayerGauge;
// -------------------------------------------------------------------
// Class : "Anabatic::AnabaticEngine".
//
// Methods dedicateds to complete global routing.
void AnabaticEngine::globalRoute ()
{
Cell* cell = getCell();
cell->flattenNets( Cell::Flags::BuildRings );
cell->createRoutingPadRings( Cell::Flags::BuildRings );
//DebugSession::addToTrace( cell->getNet("alu_out(3)") );
//DebugSession::addToTrace( cell->getNet("imuxe.not_i(1)") );
//DebugSession::addToTrace( cell->getNet("r(0)") );
//DebugSession::addToTrace( cell->getNet("a_from_pads(0)") );
//DebugSession::addToTrace( cell->getNet("ialu.not_aux104") );
//DebugSession::addToTrace( cell->getNet("mips_r3000_1m_dp_shift32_rshift_se_muxoutput(126)") );
startMeasures();
UpdateSession::open();
if (getGCells().size() == 1) {
cmess1 << " o Building regular grid..." << endl;
getSouthWestGCell()->doGrid();
} else {
cmess1 << " o Reusing existing grid." << endl;
}
cmess1 << Dots::asInt(" - GCells" ,getGCells().size()) << endl;
UpdateSession::close();
stopMeasures();
printMeasures( "Anabatic Grid" );
startMeasures();
cmess1 << " o Running global routing..." << endl;
NetSet netsToRoute;
for ( Net* net : cell->getNets() ) {
if (net->isSupply() or net->isClock()) continue;
netsToRoute.insert( net );
}
UpdateSession::open();
Dijkstra* dijkstra = new Dijkstra ( this );
dijkstra->setDistance( DigitalDistance( getConfiguration()->getEdgeCostH()
, getConfiguration()->getEdgeCostK() ) );
size_t iteration = 0;
while ( not netsToRoute.empty() and (iteration < 5) ) {
cmess2 << " [" << setw(3) << iteration << "] nets:"
<< left << setw(6) << netsToRoute.size() << right;
for ( Net* net : netsToRoute ) {
dijkstra->load( net );
dijkstra->run();
}
netsToRoute.clear();
const vector<Edge*>& ovEdges = getOvEdges();
cmess2 << " ovEdges:" << ovEdges.size();
while ( not ovEdges.empty() ) {
Edge* ovEdge = ovEdges[0];
NetSet netsToUnroute;
getNetsFromEdge( ovEdge, netsToUnroute );
for ( Net* net : netsToUnroute ) {
dijkstra->load( net );
dijkstra->ripup( ovEdge );
netsToRoute.insert( net );
}
}
cmess2 << " ripup:" << netsToRoute.size();
stopMeasures();
cmess2 << " " << setw(10) << Timer::getStringTime (_timer.getCombTime())
<< " " << setw( 6) << Timer::getStringMemory(_timer.getIncrease()) << endl;
startMeasures();
++iteration;
}
stopMeasures();
printMeasures( "Dijkstra" );
delete dijkstra;
UpdateSession::close();
}
} // Anabatic namespace.

View File

@ -200,8 +200,9 @@ namespace Anabatic {
//DebugSession::addToTrace( cell->getNet("alu_out(3)") );
//DebugSession::addToTrace( cell->getNet("imuxe.not_i(1)") );
DebugSession::addToTrace( cell->getNet("r(0)") );
DebugSession::addToTrace( cell->getNet("ialu.not_aux104") );
//DebugSession::addToTrace( cell->getNet("r(0)") );
//DebugSession::addToTrace( cell->getNet("ialu.not_aux104") );
DebugSession::addToTrace( cell->getNet("mips_r3000_1m_dp_shift32_rshift_se_muxoutput(159)") );
engine->startMeasures();
@ -226,11 +227,33 @@ namespace Anabatic {
dijkstra->load( net );
dijkstra->run();
}
delete dijkstra;
UpdateSession::close();
engine->stopMeasures();
engine->printMeasures( "Dijkstra" );
const vector<Edge*>& ovEdges = engine->getOvEdges();
if (not ovEdges.empty()) {
size_t count = 0;
cmess1 << " - " << ovEdges.size() << " overloaded edges." << endl;
cmess1 << " " << ovEdges[0] << endl;
NetSet nets;
engine->getNetsFromEdge( ovEdges[0], nets );
for ( Net* net : nets ) {
cmess1 << " [" << setw(2) << count++ << "] " << net << endl;
}
UpdateSession::open();
Net* net = *nets.begin();
dijkstra->load( net );
dijkstra->ripup( ovEdges[0] );
UpdateSession::close();
}
UpdateSession::open();
delete dijkstra;
UpdateSession::close();
}
@ -401,22 +424,35 @@ namespace Anabatic {
}
void GraphicAnabaticEngine::_globalRoute ()
{
AnabaticEngine* engine = getForFramework( CreateEngine );
engine->globalRoute();
}
void GraphicAnabaticEngine::addToMenu ( CellViewer* viewer )
{
assert( _viewer == NULL );
_viewer = viewer;
if (_viewer->hasMenuAction("placeAndRoute.anabatic")) {
if (_viewer->hasMenuAction("placeAndRoute.anabatic.globalRoute")) {
cerr << Warning( "GraphicAnabaticEngine::addToMenu() - Anabatic engine already hooked in." ) << endl;
return;
}
_viewer->addToMenu( "placeAndRoute.anabatic"
_viewer->addMenu ( "placeAndRoute.anabatic", "Anabatic" );
_viewer->addToMenu( "placeAndRoute.anabatic.runTest"
, "Anabatic - &Test Run"
, "Perform a test run of Anabatic on the design"
, std::bind(&GraphicAnabaticEngine::_runTest,this)
);
_viewer->addToMenu( "placeAndRoute.anabatic.globalRoute"
, "Anabatic - &Global Route"
, "Global Route"
, std::bind(&GraphicAnabaticEngine::_globalRoute,this)
);
}

View File

@ -19,10 +19,12 @@
#include <string>
#include <vector>
#include <set>
#include "hurricane/Timer.h"
namespace Hurricane {
class Name;
class Net;
class Cell;
class Instance;
class CellViewer;
@ -47,6 +49,9 @@ namespace Anabatic {
using CRL::ToolEngine;
typedef std::set<Net*,Entity::CompareById> NetSet;
class AnabaticEngine : public ToolEngine {
public:
typedef ToolEngine Super;
@ -60,13 +65,19 @@ namespace Anabatic {
inline void setViewer ( CellViewer* );
inline const Matrix* getMatrix () const;
inline const vector<GCell*>& getGCells () const;
inline const vector<Edge*>& getOvEdges () const;
inline GCell* getSouthWestGCell () const;
inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getGCellUnder ( Point ) const;
int getCapacity ( Interval, Flags ) const;
size_t getNetsFromEdge ( const Edge*, NetSet& );
inline void addOv ( Edge* );
inline void removeOv ( Edge* );
// Dijkstra related functions.
inline int getStamp () const;
inline int incStamp ();
// Global routing related functions.
void globalRoute ();
// Misc. functions.
inline const Flags& flags () const;
inline Flags& flags ();
@ -97,6 +108,7 @@ namespace Anabatic {
Configuration* _configuration;
Matrix _matrix;
vector<GCell*> _gcells;
vector<Edge*> _ovEdges;
CellViewer* _viewer;
Flags _flags;
int _stamp;
@ -107,6 +119,7 @@ namespace Anabatic {
inline void AnabaticEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
inline const Matrix* AnabaticEngine::getMatrix () const { return &_matrix; }
inline const vector<GCell*>& AnabaticEngine::getGCells () const { return _gcells; }
inline const vector<Edge*>& AnabaticEngine::getOvEdges () const { return _ovEdges; }
inline GCell* AnabaticEngine::getSouthWestGCell () const { return _gcells[0]; }
inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); }
inline GCell* AnabaticEngine::getGCellUnder ( Point p ) const { return _matrix.getUnder(p); }
@ -134,6 +147,14 @@ namespace Anabatic {
inline int AnabaticEngine::getStamp () const { return _stamp; }
inline int AnabaticEngine::incStamp () { return ++_stamp; }
inline void AnabaticEngine::addOv ( Edge* edge ) { _ovEdges.push_back(edge); }
inline void AnabaticEngine::removeOv ( Edge* edge )
{
for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge )
if (*iedge == edge) { _ovEdges.erase(iedge); break; }
}
} // Anabatic namespace.

View File

@ -88,6 +88,8 @@ namespace Anabatic {
virtual DbU::Unit getEdgeWidth () const = 0;
virtual float getEdgeCostH () const = 0;
virtual float getEdgeCostK () const = 0;
virtual size_t getHEdgeLocal () const = 0;
virtual size_t getVEdgeLocal () const = 0;
virtual void print ( Cell* ) const = 0;
virtual Record* _getRecord () const = 0;
virtual string _getString () const = 0;
@ -143,6 +145,8 @@ namespace Anabatic {
virtual DbU::Unit getEdgeWidth () const;
virtual float getEdgeCostH () const;
virtual float getEdgeCostK () const;
virtual size_t getHEdgeLocal () const;
virtual size_t getVEdgeLocal () const;
virtual void print ( Cell* ) const;
virtual Record* _getRecord () const;
virtual string _getString () const;
@ -160,6 +164,8 @@ namespace Anabatic {
DbU::Unit _edgeWidth;
float _edgeCostH;
float _edgeCostK;
size_t _hEdgeLocal;
size_t _vEdgeLocal;
private:
ConfigurationConcrete ( const ConfigurationConcrete& );
ConfigurationConcrete& operator= ( const ConfigurationConcrete& );

View File

@ -44,7 +44,7 @@ namespace Anabatic {
public:
class CompareById {
public:
inline bool operator() ( const Vertex* lhs, const Vertex* rhs );
inline bool operator() ( const Vertex* lhs, const Vertex* rhs ) const;
};
public:
static DbU::Unit unreached;
@ -125,7 +125,7 @@ namespace Anabatic {
inline Vertex* Vertex::getPredecessor () const
{ return (hasValidStamp() and _from) ? _from->getOpposite(_gcell)->getObserver<Vertex>(GCell::Observable::Vertex) : NULL; }
inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs )
inline bool Vertex::CompareById::operator() ( const Vertex* lhs, const Vertex* rhs ) const
{ return lhs->getId() < rhs->getId(); }
@ -224,16 +224,23 @@ namespace Anabatic {
~Dijkstra ();
public:
inline bool isBipoint () const;
inline bool isSourceVertex ( Vertex* ) const;
inline bool isTargetVertex ( Vertex* ) const;
inline void setDistance ( distance_t );
void load ( Net* );
void run ( Mode mode=Mode::Standart );
void ripup ( Edge* );
private:
Dijkstra ( const Dijkstra& );
Dijkstra& operator= ( const Dijkstra& );
static DbU::Unit _distance ( const Vertex*, const Vertex*, const Edge* );
void _cleanup ();
bool _propagate ( Flags enabledSides );
void _traceback ( Vertex* );
void _selectFirstSource ();
Vertex* _propagateRipup ( Vertex* );
void _tagConnecteds ( Vertex*, int connexId );
void _checkEdges () const;
private:
AnabaticEngine* _anabatic;
vector<Vertex*> _vertexes;
@ -252,8 +259,10 @@ namespace Anabatic {
inline Dijkstra::Mode::Mode ( unsigned int flags ) : BaseFlags(flags) { }
inline Dijkstra::Mode::Mode ( BaseFlags base ) : BaseFlags(base) { }
inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); }
inline void Dijkstra::setDistance ( distance_t cb ) { _distanceCb = cb; }
inline bool Dijkstra::isBipoint () const { return _net and (_targets.size()+_sources.size() == 2); }
inline bool Dijkstra::isSourceVertex ( Vertex* v ) const { return (_sources.find(v) != _sources.end()); }
inline bool Dijkstra::isTargetVertex ( Vertex* v ) const { return (_targets.find(v) != _targets.end()); }
inline void Dijkstra::setDistance ( distance_t cb ) { _distanceCb = cb; }
} // Anabatic namespace.

View File

@ -22,10 +22,14 @@
#include "hurricane/Interval.h"
#include "hurricane/Box.h"
#include "hurricane/ExtensionGo.h"
namespace Hurricane {
class Segment;
}
#include "anabatic/Constants.h"
#include "anabatic/Edges.h"
namespace Anabatic {
using std::string;
@ -34,6 +38,7 @@ namespace Anabatic {
using Hurricane::DbU;
using Hurricane::Interval;
using Hurricane::Box;
using Hurricane::Segment;
using Hurricane::Cell;
using Hurricane::ExtensionGo;
@ -63,7 +68,11 @@ namespace Anabatic {
inline DbU::Unit getAxis () const;
DbU::Unit getAxisMin () const;
Interval getSide () const;
inline void incRealOccupancy ( unsigned int );
inline Segment* getSegment () const;
inline void incCapacity ( int );
void incRealOccupancy ( int );
inline void setSegment ( Segment* );
void destroySegment ();
inline const Flags& flags () const;
inline Flags& flags ();
inline void invalidate ();
@ -80,17 +89,17 @@ namespace Anabatic {
virtual Box getBoundingBox () const;
public:
// Inspector support.
virtual string _getTypeName () const;
virtual string _getString () const;
virtual Record* _getRecord () const;
protected:
Edge ( GCell* source, GCell* target, Flags flags );
virtual ~Edge ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
Edge ( const Edge& );
Edge& operator= ( const Edge& );
virtual string _getTypeName () const;
virtual string _getString () const;
virtual Record* _getRecord () const;
protected:
Edge ( GCell* source, GCell* target, Flags flags );
virtual ~Edge ();
virtual void _postCreate ();
virtual void _preDestroy ();
private:
Edge ( const Edge& );
Edge& operator= ( const Edge& );
private:
static Name _extensionName;
Flags _flags;
@ -100,6 +109,7 @@ namespace Anabatic {
GCell* _source;
GCell* _target;
DbU::Unit _axis;
Segment* _segment;
};
@ -112,7 +122,9 @@ namespace Anabatic {
inline GCell* Edge::getSource () const { return _source; }
inline GCell* Edge::getTarget () const { return _target; }
inline DbU::Unit Edge::getAxis () const { return _axis; }
inline void Edge::incRealOccupancy ( unsigned int delta ) { _realOccupancy+=delta; }
inline Segment* Edge::getSegment () const { return _segment; }
inline void Edge::incCapacity ( int delta ) { _capacity = ((int)_capacity+delta > 0) ? _capacity+delta : 0; }
inline void Edge::setSegment ( Segment* s ) { _segment=s; }
inline const Flags& Edge::flags () const { return _flags; }
inline Flags& Edge::flags () { return _flags; }
inline void Edge::invalidate () { _flags |= Flags::Invalidated; }

View File

@ -68,74 +68,78 @@ namespace Anabatic {
Observable& operator= ( const StaticObservable& );
};
public:
static Box getBorder ( const GCell*, const GCell* );
public:
static GCell* create ( AnabaticEngine* );
public:
inline bool isHFlat () const;
inline bool isVFlat () const;
inline bool isFlat () const;
inline bool isDevice () const;
inline bool isChannel () const;
inline bool isStrut () const;
inline bool isMatrix () const;
inline AnabaticEngine* getAnabatic () const;
inline DbU::Unit getXMin () const;
inline DbU::Unit getYMin () const;
inline DbU::Unit getXMax ( int shrink=0 ) const;
inline DbU::Unit getYMax ( int shrink=0 ) const;
inline Interval getSide ( Flags direction ) const;
inline Point getCenter () const;
inline const vector<Edge*>& getWestEdges () const;
inline const vector<Edge*>& getEastEdges () const;
inline const vector<Edge*>& getNorthEdges () const;
inline const vector<Edge*>& getSouthEdges () const;
inline Edges getEdges () const;
inline GCell* getWest () const;
inline GCell* getEast () const;
inline GCell* getSouth () const;
inline GCell* getNorth () const;
GCell* getWest ( DbU::Unit y ) const;
GCell* getEast ( DbU::Unit y ) const;
GCell* getSouth ( DbU::Unit x ) const;
GCell* getNorth ( DbU::Unit x ) const;
GCell* getUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getUnder ( Point p ) const;
GCell* hcut ( DbU::Unit y );
GCell* vcut ( DbU::Unit x );
bool doGrid ();
Contact* getGContact ( Net* );
static Box getBorder ( const GCell*, const GCell* );
public:
static GCell* create ( AnabaticEngine* );
public:
inline bool isHFlat () const;
inline bool isVFlat () const;
inline bool isFlat () const;
inline bool isDevice () const;
inline bool isChannel () const;
inline bool isStrut () const;
inline bool isMatrix () const;
bool hasGContact ( const Contact* ) const;
inline AnabaticEngine* getAnabatic () const;
inline DbU::Unit getXMin () const;
inline DbU::Unit getYMin () const;
inline DbU::Unit getXMax ( int shrink=0 ) const;
inline DbU::Unit getYMax ( int shrink=0 ) const;
inline Interval getSide ( Flags direction ) const;
inline Point getCenter () const;
inline const vector<Edge*>& getWestEdges () const;
inline const vector<Edge*>& getEastEdges () const;
inline const vector<Edge*>& getNorthEdges () const;
inline const vector<Edge*>& getSouthEdges () const;
Edge* getEdgeTo ( GCell*, Flags sideHint=Flags::AllSides ) const;
inline Edges getEdges ( Flags sides=Flags::AllSides ) const;
inline GCell* getWest () const;
inline GCell* getEast () const;
inline GCell* getSouth () const;
inline GCell* getNorth () const;
GCell* getWest ( DbU::Unit y ) const;
GCell* getEast ( DbU::Unit y ) const;
GCell* getSouth ( DbU::Unit x ) const;
GCell* getNorth ( DbU::Unit x ) const;
GCell* getUnder ( DbU::Unit x, DbU::Unit y ) const;
inline GCell* getUnder ( Point p ) const;
GCell* hcut ( DbU::Unit y );
GCell* vcut ( DbU::Unit x );
bool doGrid ();
Contact* getGContact ( Net* );
inline const vector<Contact*>& getGContacts () const;
bool unrefContact ( Contact* );
// Misc. functions.
inline const Flags& flags () const;
inline Flags& flags ();
void _add ( Edge* edge, Flags side );
void _remove ( Edge* edge, Flags side=Flags::AllSides );
void _destroyEdges ();
private:
void _revalidate ();
void _moveEdges ( GCell* dest, size_t ibegin, Flags flags );
public:
// Observers.
inline void setObserver ( size_t slot, BaseObserver* );
template<typename OwnerT>
inline OwnerT* getObserver ( size_t slot );
inline void notify ( unsigned int flags );
// ExtensionGo support.
inline const Name& staticGetName ();
virtual const Name& getName () const;
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
virtual Box getBoundingBox () const;
public:
// Inspector support.
virtual string _getTypeName () const;
virtual string _getString () const;
virtual Record* _getRecord () const;
protected:
GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin );
virtual ~GCell ();
GCell* _create ( DbU::Unit xmin, DbU::Unit ymin );
virtual void _postCreate ();
virtual void _preDestroy ();
inline const Flags& flags () const;
inline Flags& flags ();
void _add ( Edge* edge, Flags side );
void _remove ( Edge* edge, Flags side=Flags::AllSides );
void _destroyEdges ();
private:
void _revalidate ();
void _moveEdges ( GCell* dest, size_t ibegin, Flags flags );
public:
// Observers.
inline void setObserver ( size_t slot, BaseObserver* );
template<typename OwnerT>
inline OwnerT* getObserver ( size_t slot );
inline void notify ( unsigned int flags );
// ExtensionGo support.
inline const Name& staticGetName ();
virtual const Name& getName () const;
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
virtual Box getBoundingBox () const;
public:
// Inspector support.
virtual string _getTypeName () const;
virtual string _getString () const;
virtual Record* _getRecord () const;
protected:
GCell ( AnabaticEngine*, DbU::Unit xmin, DbU::Unit ymin );
virtual ~GCell ();
GCell* _create ( DbU::Unit xmin, DbU::Unit ymin );
virtual void _postCreate ();
virtual void _preDestroy ();
private:
GCell ( const GCell& );
GCell& operator= ( const GCell& );
@ -154,28 +158,29 @@ namespace Anabatic {
};
inline bool GCell::isHFlat () const { return getYMin() == getYMax(); }
inline bool GCell::isVFlat () const { return getXMin() == getXMax(); }
inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); }
inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; }
inline bool GCell::isChannel () const { return _flags & Flags::ChannelGCell; }
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; }
inline DbU::Unit GCell::getXMin () const { return _xmin; }
inline DbU::Unit GCell::getYMin () const { return _ymin; }
inline Edges GCell::getEdges () const { return new GCell_Edges(this); }
inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; }
inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; }
inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; }
inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; }
inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); }
inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); }
inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); }
inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); }
inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); }
inline const Flags& GCell::flags () const { return _flags; }
inline Flags& GCell::flags () { return _flags; }
inline bool GCell::isHFlat () const { return getYMin() == getYMax(); }
inline bool GCell::isVFlat () const { return getXMin() == getXMax(); }
inline bool GCell::isFlat () const { return isHFlat() or isVFlat(); }
inline bool GCell::isDevice () const { return _flags & Flags::DeviceGCell; }
inline bool GCell::isChannel () const { return _flags & Flags::ChannelGCell; }
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
inline AnabaticEngine* GCell::getAnabatic () const { return _anabatic; }
inline DbU::Unit GCell::getXMin () const { return _xmin; }
inline DbU::Unit GCell::getYMin () const { return _ymin; }
inline Edges GCell::getEdges ( Flags sides ) const { return new GCell_Edges(this,sides); }
inline const vector<Edge*>& GCell::getWestEdges () const { return _westEdges; }
inline const vector<Edge*>& GCell::getEastEdges () const { return _eastEdges; }
inline const vector<Edge*>& GCell::getNorthEdges () const { return _northEdges; }
inline const vector<Edge*>& GCell::getSouthEdges () const { return _southEdges; }
inline GCell* GCell::getWest () const { return _westEdges.empty() ? NULL : _westEdges[0]->getOpposite(this); }
inline GCell* GCell::getEast () const { return _eastEdges.empty() ? NULL : _eastEdges[0]->getOpposite(this); }
inline GCell* GCell::getSouth () const { return _southEdges.empty() ? NULL : _southEdges[0]->getOpposite(this); }
inline GCell* GCell::getNorth () const { return _northEdges.empty() ? NULL : _northEdges[0]->getOpposite(this); }
inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); }
inline const vector<Contact*>& GCell::getGContacts () const { return _contacts; }
inline const Flags& GCell::flags () const { return _flags; }
inline Flags& GCell::flags () { return _flags; }
inline DbU::Unit GCell::getXMax ( int shrink ) const
{ return _eastEdges.empty() ? getCell()->getAbutmentBox().getXMax() - shrink

View File

@ -82,6 +82,7 @@ namespace Anabatic {
GraphicAnabaticEngine ();
virtual ~GraphicAnabaticEngine ();
void _runTest ();
void _globalRoute ();
};