Implementation of pre-routing support (for clock-tree compliance).

* New: In Katabatic, in <AutoContact>, this class is no longer derived
    from ExtentionGo. With the simplificated AutoContacts, there is no
    reason to do so, and it will save some QuadTree insertions/deletions.
      New factory function AutoContact::createFrom(Contact*) which try to
    build an AutoContact on top of a Hurricane::Contact. Of course that
    base contact *must fit* into one of the predefined Contact
    configurations (Terminal, Turn, HTee or VTee).
      NOTE: This implies that the pre-routed segments & contacts *are*
    correctly articulated, which is not the case when a Cell is read
    from disk in "ap" format. The pre-routing feature must be used for
    now without any re-read from disk. We will implement a re-articulating
    pre-process in the future.
* Change: In Katabatic, in <AutoContact> derived classes, the ::updateCache()
    method now display an accurate error message if a segment is connected
    but has no AutoSegment conterpart (i.e. the lookup fails).
* New: In Katabatic, in <AutoSegment>, the ::computeOptimal() method is
    short-circuited for pre-routed segments, the optimal axis position is
    considered to be the one it is currently on (i.e. we trust the designer).
* New: In Katabatic, in <KatabaticEngine>, the ::loadGlobalRouting()
    method now accept a map of excluded nets (same as Knik). This map is
    the one of pre-routed nets.
* New: In Katabatic, in layer assignment, do not try to displace fixed
    segments...
* New: In Katabatic, in <AutoSegment>, new flag SegUserDefined and related
    methods to know if a segment comes from the global router (Knik) or
    is pre-routed (supplied by the user).
* New: In Kite, In <BuildPowerRails>, support (exclusion) for pre-routed
    nets.
* New: In Kite, In <GraphicKiteEngine> new menu entry for running the
    router on pre-routed nets ("Detailed Pre-Route"), also integrated
    in the all-on-one route command.
* New: In Kite, In KiteEngine, new method ::_initDataBase() that group
    all the initialisation steps. It is a mix of calls between Knik and
    Kite initializations which are intertwinneds (may have to devellop
    a shared common base at a later point). It creates the Knik grid,
    then the Katabatic grid, then load pre-routed wires and power rails
    and protect isolated RoutingPads.
      Add support for a map of pre-routed nets (to be excluded for
    Knik calls).
      The method "::run()" now uses function flags, firstly to know if
    it is managing pre-routed wires or general purposes ones.
* New: In Kite, in <NegociateWindow>, the "::run()" methods has now two
    modes. The normal one and the 'KtPreRoutedStage' that is for routing
    pre-routed nets. When in pre-route stage, the wires are fixed at the
    end of this step.
* New: In Kite, in <TrackElement> add decorator for AutoSegment
    isUsedDefined().
* New: In Kite, in <TrackSegment>, the various ::canDogleg() methods
    returns false for a pre-routed (user-defined segment).
* New: In Kite, in PyKiteEngine, added new method runNegociatePreRouted().
This commit is contained in:
Jean-Paul Chaput 2014-06-21 20:16:47 +02:00
parent a6addb5c56
commit ff21d3c8a2
34 changed files with 640 additions and 273 deletions

View File

@ -32,8 +32,14 @@
#include "hurricane/DebugSession.h"
#include "crlcore/RoutingGauge.h"
#include "katabatic/AutoContact.h"
#include "katabatic/AutoContactTerminal.h"
#include "katabatic/AutoContactTurn.h"
#include "katabatic/AutoContactHTee.h"
#include "katabatic/AutoContactVTee.h"
#include "katabatic/AutoVertical.h"
#include "katabatic/AutoHorizontal.h"
#include "katabatic/KatabaticEngine.h"
#include "katabatic/GCellGrid.h"
#include "katabatic/Session.h"
@ -57,9 +63,7 @@ namespace Katabatic {
AutoContact::AutoContact ( GCell* gcell, Contact* contact )
: ExtensionGo(contact->getCell())
//, _id (_maxId++)
, _id (contact->getId())
: _id (contact->getId())
, _contact (contact)
, _gcell (gcell)
, _flags (CntInvalidatedCache|CntInCreationStage)
@ -83,8 +87,6 @@ namespace Katabatic {
void AutoContact::_postCreate ()
{
ExtensionGo::_postCreate();
restoreNativeConstraintBox();
ltrace(90) << "Native CBox: " << this
@ -100,6 +102,13 @@ namespace Katabatic {
}
void AutoContact::destroy ()
{
_preDestroy ();
delete this;
}
void AutoContact::_preDestroy ()
{
DebugSession::open( _contact->getNet() );
@ -128,7 +137,6 @@ namespace Katabatic {
Session::unlink( this );
}
ExtensionGo::_preDestroy();
#if 0
if (Session::doDestroyBaseContact() and canDestroyBase)
_contact->destroy();
@ -317,7 +325,7 @@ namespace Katabatic {
}
void AutoContact::_getTopology ( Component*& anchor, Horizontal**& horizontals, Vertical**& verticals, size_t size )
void AutoContact::_getTopology ( Contact* support, Component*& anchor, Horizontal**& horizontals, Vertical**& verticals, size_t size )
{
size_t hcount = 0;
size_t vcount = 0;
@ -327,9 +335,9 @@ namespace Katabatic {
verticals [i] = NULL;
}
anchor = getAnchor();
anchor = support->getAnchor();
forEach ( Component*, icomponent, getSlaveComponents() ) {
forEach ( Component*, icomponent, support->getSlaveComponents() ) {
Horizontal* h = dynamic_cast<Horizontal*>(*icomponent);
if (h != NULL) {
if (hcount < size) horizontals[hcount++] = h;
@ -349,7 +357,7 @@ namespace Katabatic {
if (not (flags & KbCParanoid)) cparanoid.setStreamMask( mstream::PassThrough );
_getTopology ( anchor, horizontals, verticals, 10 );
_getTopology ( base(), anchor, horizontals, verticals, 10 );
cparanoid << Error("In topology of %s",getString(this).c_str()) << endl;
if (anchor) cparanoid << " A: " << anchor << endl;
@ -499,6 +507,67 @@ namespace Katabatic {
}
AutoContact* AutoContact::createFrom ( Contact* hurricaneContact )
{
AutoContact* autoContact = NULL;
Component* anchor;
size_t hSize = 0;
size_t vSize = 0;
Horizontal** horizontals = new Horizontal* [4];
Vertical** verticals = new Vertical* [4];
GCell* gcell = Session::getKatabatic()->getGCellGrid()->getGCell( hurricaneContact->getCenter() );
if (not gcell) {
throw Error("AutoContact::createFrom( %s ):\n"
" Contact is *not* under a GCell (outside routed area?)"
, getString(hurricaneContact).c_str()
);
}
_getTopology ( hurricaneContact, anchor, horizontals, verticals, 4 );
for ( size_t i=0 ; i<4 ; ++i ) {
hSize += (horizontals[i] != NULL) ? 1 : 0;
vSize += (verticals [i] != NULL) ? 1 : 0;
}
if (anchor) {
if (hSize+vSize == 1) {
autoContact = new AutoContactTerminal( gcell, hurricaneContact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
}
} else {
if ((hSize == 1) and (vSize == 1)) {
autoContact = new AutoContactTurn ( gcell, hurricaneContact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
} else if ((hSize == 2) and (vSize == 1)) {
autoContact = new AutoContactHTee ( gcell, hurricaneContact );
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
} else if ((hSize == 1) and (vSize == 2)) {
autoContact = new AutoContactVTee ( gcell, hurricaneContact );
}
}
if (not autoContact) {
throw Error("AutoContact::createFrom( %s ):\n"
" Contact do not have a manageable topology (a:%u, h:%u, v:%u)"
, getString(hurricaneContact).c_str()
, ((anchor) ? 1 : 0)
, hSize
, vSize
);
}
autoContact->_postCreate();
autoContact->unsetFlags( CntInCreationStage );
return autoContact;
}
string AutoContact::_getTypeName () const
{ return "AutoContact"; }

View File

@ -180,7 +180,7 @@ namespace Katabatic {
Horizontal** horizontals = new Horizontal* [3];
Vertical** verticals = new Vertical* [3];
_getTopology( anchor, horizontals, verticals, 3 );
_getTopology( base(), anchor, horizontals, verticals, 3 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_horizontal2 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[1]) );
@ -192,6 +192,9 @@ namespace Katabatic {
else if (horizontals[2] != NULL) message = "HTee has more than two horizontal segments.";
else if (verticals [0] == NULL) message = "HTee is missing mandatory vertical segment.";
else if (verticals [1] != NULL) message = "HTee has more than one vertical segment.";
else if (_horizontal1 == NULL) message = "AutoSegment lookup failed on first horizontal segment.";
else if (_horizontal2 == NULL) message = "AutoSegment lookup failed on second horizontal segment.";
else if (_vertical1 == NULL) message = "AutoSegment lookup failed on vertical segment.";
else if ( (not _horizontal1->isCreated() and not _horizontal2->isCreated())
and (_horizontal1->getY() != _horizontal2->getY()) ) {
message = "HTee has misaligned horizontal segments";

View File

@ -44,6 +44,7 @@ namespace Katabatic {
using Hurricane::Bug;
using Hurricane::Error;
using Hurricane::DebugSession;
using Hurricane::Entity;
using Hurricane::ltracein;
using Hurricane::ltraceout;
@ -60,7 +61,7 @@ namespace Katabatic {
, DbU::Unit height
)
{
ltrace(90) << "AutoContactTerminal::create(... Point ...)" << endl;
ltrace(90) << "AutoContactTerminal::create(... Point, ...)" << endl;
ltracein(90);
ltrace(90) << "@" << point << endl;
@ -86,7 +87,7 @@ namespace Katabatic {
, const DbU::Unit height
)
{
ltrace(90) << "AutoContactTerminal::create(... x, y ...)" << endl;
ltrace(90) << "AutoContactTerminal::create(... x, y, ...)" << endl;
ltrace(90) << "@ x:" << DbU::getValueString(x) << " y:" << DbU::getValueString(y) << endl;
Point anchorPosition = anchor->getPosition();
@ -232,7 +233,7 @@ namespace Katabatic {
Horizontal** horizontals = new Horizontal* [2];
Vertical** verticals = new Vertical* [2];
_getTopology( anchor, horizontals, verticals, 2 );
_getTopology( base(), anchor, horizontals, verticals, 2 );
if (anchor == NULL)
showTopologyError( "Terminal is missing an anchor (RoutingPad or Component)." );

View File

@ -151,7 +151,7 @@ namespace Katabatic {
Horizontal** horizontals = new Horizontal* [2];
Vertical** verticals = new Vertical* [2];
_getTopology ( anchor, horizontals, verticals, 2 );
_getTopology ( base(), anchor, horizontals, verticals, 2 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
@ -161,6 +161,8 @@ namespace Katabatic {
else if (horizontals[1] != NULL) message = "Turn has more than one horizontal segment.";
else if (verticals [0] == NULL) message = "Turn is missing mandatory vertical segment.";
else if (verticals [1] != NULL) message = "Turn has more than one vertical segment.";
else if (_horizontal1 == NULL) message = "AutoSegment lookup failed on horizontal segment.";
else if (_vertical1 == NULL) message = "AutoSegment lookup failed on vertical segment.";
if (not message.empty()) {
showTopologyError( message );
setFlags( CntBadTopology );

View File

@ -166,7 +166,7 @@ namespace Katabatic {
Horizontal** horizontals = new Horizontal* [3];
Vertical** verticals = new Vertical* [3];
_getTopology ( anchor, horizontals, verticals, 3 );
_getTopology ( base(), anchor, horizontals, verticals, 3 );
_horizontal1 = static_cast<AutoHorizontal*>( Session::lookup(horizontals[0]) );
_vertical1 = static_cast<AutoVertical *>( Session::lookup(verticals [0]) );
@ -178,6 +178,9 @@ namespace Katabatic {
else if (verticals [2] != NULL) message = "VTee has more than two vertical segments.";
else if (horizontals[0] == NULL) message = "VTee is missing mandatory horizontal segment.";
else if (horizontals[1] != NULL) message = "VTee has more than one horizontal segment.";
else if (_horizontal1 == NULL) message = "AutoSegment lookup failed on horizontal segment.";
else if (_vertical1 == NULL) message = "AutoSegment lookup failed on first vertical segment.";
else if (_vertical2 == NULL) message = "AutoSegment lookup failed on second vertical segment.";
else if ( (not _vertical1->isCreated() and not _vertical2->isCreated())
and (_vertical1->getY() != _vertical2->getY()) )
message = "VTee has misaligned vertical segments";

View File

@ -909,6 +909,16 @@ namespace Katabatic {
ltrace(89) << "computeOptimal() - " << this << endl;
ltracein(89);
DbU::Unit optimalMin;
DbU::Unit optimalMax;
DbU::Unit constraintMin;
DbU::Unit constraintMax;
getConstraints( constraintMin, constraintMax );
if (isUserDefined()) {
optimalMin = optimalMax = getAxis();
} else {
DbU::Unit minGCell = getOrigin();
DbU::Unit maxGCell = getExtremity();
DbU::Unit terminalMin;
@ -978,12 +988,6 @@ namespace Katabatic {
ltraceout(89);
}
DbU::Unit optimalMin;
DbU::Unit optimalMax;
DbU::Unit constraintMin;
DbU::Unit constraintMax;
getConstraints( constraintMin, constraintMax );
if (attractors.getAttractorsCount()) {
ltrace(89) << "Lower Median " << DbU::toLambda(attractors.getLowerMedian()) << endl;
ltrace(89) << "Upper Median " << DbU::toLambda(attractors.getUpperMedian()) << endl;
@ -995,6 +999,7 @@ namespace Katabatic {
optimalMax = (isHorizontal()) ? _gcell->getBoundingBox().getYMax()
: _gcell->getBoundingBox().getXMax();
}
}
setInBound( constraintMin, constraintMax, optimalMin );
setInBound( constraintMin, constraintMax, optimalMax );
@ -1925,12 +1930,16 @@ namespace Katabatic {
if (horizontal) {
if (horizontal->getLayer() != horizontalLayer) {
if ( not Session::getKatabatic()->isGMetal(horizontal->getLayer()) )
cerr << Warning("Segment %s forced to %s."
,getString(horizontal).c_str()
,getString(horizontalLayer).c_str()) << endl;
if (Session::getKatabatic()->isGMetal(horizontal->getLayer())) {
horizontal->setLayer( horizontalLayer );
horizontal->setWidth( horizontalWidth );
} else {
if (horizontal->getWidth() != horizontalWidth) {
cerr << Warning("Segment %s has non-default width %s."
,getString(horizontal).c_str()
,DbU::getValueString(horizontal->getWidth()).c_str()) << endl;
}
}
}
horizontal->setY( reference->getY() );
@ -1938,12 +1947,15 @@ namespace Katabatic {
segment->_postCreate();
} else if (vertical) {
if (vertical->getLayer() != verticalLayer) {
if ( not Session::getKatabatic()->isGMetal(vertical->getLayer()) )
cerr << Warning("Segment %s forced to %s."
,getString(vertical).c_str()
,getString(verticalLayer).c_str()) << endl;
if (Session::getKatabatic()->isGMetal(vertical->getLayer()) )
vertical->setLayer( verticalLayer );
vertical->setWidth( verticalWidth );
} else {
if (vertical->getWidth() != verticalWidth) {
cerr << Warning("Segment %s has non-default width %s."
,getString(horizontal).c_str()
,DbU::getValueString(horizontal->getWidth()).c_str()) << endl;
}
}
vertical->setX( reference->getX() );

View File

@ -459,7 +459,7 @@ namespace Katabatic {
{ return _configuration; }
void KatabaticEngine::loadGlobalRouting ( unsigned int method, NetSet& nets )
void KatabaticEngine::loadGlobalRouting ( unsigned int method, NetSet& nets, const map<Name,Net*>& excludeds )
{
if (_state < EngineGlobalLoaded)
throw Error ("KatabaticEngine::loadGlobalRouting() : global routing not present yet.");
@ -480,6 +480,7 @@ namespace Katabatic {
continue;
}
if (af->isBLOCKAGE(net->getName())) continue;
if (excludeds.find(net->getName()) != excludeds.end()) continue;
_routingNets.insert ( *net );
}
} else {
@ -493,10 +494,12 @@ namespace Katabatic {
if (excludedType) {
cparanoid << Warning( "%s is not a routable net (%s), removed from set."
, getString(*it).c_str(), excludedType ) << endl;
} else
} else {
if (excludeds.find((*it)->getName()) != excludeds.end()) continue;
_routingNets.insert( *it );
}
}
}
switch ( method ) {
case EngineLoadGrByNet: _loadGrByNet(); break;

View File

@ -427,7 +427,7 @@ namespace Katabatic {
for ( ; ilut!=_autoSegmentLut.end() ; ++ilut ) {
AutoSegment* segment = (*ilut).second;
if (segment->isLocal()) continue;
if (segment->isLocal() or segment->isFixed()) continue;
if (not segment->isCanonical()) continue;
segments.push_back( segment );

View File

@ -68,7 +68,9 @@ namespace Katabatic {
, CntIgnoreAnchor = 0x00000200
};
class AutoContact : public ExtensionGo {
class AutoContact {
public:
static AutoContact* createFrom ( Contact* );
public:
// Wrapped Contact Accessors.
inline Hook* getBodyHook ();
@ -158,6 +160,7 @@ namespace Katabatic {
, DbU::Unit constraintMax
, unsigned int flags=KbWarnOnError );
void restoreNativeConstraintBox ();
void destroy ();
// Inspector Management.
Record* _getRecord () const;
virtual string _getString () const;
@ -193,7 +196,7 @@ namespace Katabatic {
protected:
inline int _getDeltaMin ( DbU::Unit x, DbU::Unit xMin );
inline int _getDeltaMax ( DbU::Unit x, DbU::Unit xMin, DbU::Unit xMax );
void _getTopology ( Component*& anchor, Horizontal**&, Vertical**&, size_t );
static void _getTopology ( Contact*, Component*& anchor, Horizontal**&, Vertical**&, size_t );
virtual void _invalidate ( unsigned int flags ) = 0;
};

View File

@ -1,8 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2012-2013, All Rights Reserved
// Copyright (c) UPMC 2012-2014, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -32,6 +31,7 @@ namespace Katabatic {
class AutoContactHTee : public AutoContact {
friend class AutoContact;
public:
static AutoContactHTee* create ( GCell*, Net*, const Layer* );
protected:

View File

@ -28,6 +28,7 @@ namespace Katabatic {
class AutoContactTerminal : public AutoContact {
friend class AutoContact;
public:
static AutoContactTerminal* create ( GCell* gcell
, Component* anchor

View File

@ -1,8 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2013, All Rights Reserved
// Copyright (c) UPMC 2012-2014, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -31,6 +30,7 @@ namespace Katabatic {
class AutoContactTurn : public AutoContact {
friend class AutoContact;
public:
static AutoContactTurn* create ( GCell*, Net*, const Layer* );
static void insert ( AutoContactTerminal* );

View File

@ -1,8 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2012-2013, All Rights Reserved
// Copyright (c) UPMC 2012-2014, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -29,6 +28,7 @@ namespace Katabatic {
class AutoContactVTee : public AutoContact {
friend class AutoContact;
public:
static AutoContactVTee* create ( GCell*, Net*, const Layer* );
protected:

View File

@ -90,6 +90,7 @@ namespace Katabatic {
, SegInvalidatedTarget = 0x04000000
, SegInvalidatedLayer = 0x08000000
, SegCreated = 0x10000000
, SegUserDefined = 0x20000000
// Masks.
, SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2
, SegNotAligned = SegNotSourceAligned|SegNotTargetAligned
@ -182,6 +183,7 @@ namespace Katabatic {
inline bool isCanonical () const;
inline bool isUnsetAxis () const;
inline bool isSlackened () const;
inline bool isUserDefined () const;
virtual bool _canSlacken () const = 0;
unsigned int canDogleg ( Interval );
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
@ -449,6 +451,7 @@ namespace Katabatic {
inline bool AutoSegment::isInvalidated () const { return _flags & SegInvalidated; }
inline bool AutoSegment::isInvalidatedLayer () const { return _flags & SegInvalidatedLayer; }
inline bool AutoSegment::isCreated () const { return _flags & SegCreated; }
inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; }
inline void AutoSegment::setFlags ( unsigned int flags ) { _flags |= flags; }
inline void AutoSegment::unsetFlags ( unsigned int flags ) { _flags &= ~flags; }

View File

@ -1,8 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2013, All Rights Reserved
// Copyright (c) UPMC 2008-2014, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -20,7 +19,6 @@
#include <string>
#include <vector>
#include "hurricane/Point.h"
#include "hurricane/Box.h"
#include "hurricane/Collection.h"
@ -28,7 +26,6 @@
namespace Katabatic {
using std::string;
using std::vector;
using Hurricane::_TName;

View File

@ -21,6 +21,7 @@
#include <string>
#include <vector>
#include <set>
#include <map>
#include "hurricane/Timer.h"
#include "hurricane/DbU.h"
#include "hurricane/Torus.h"
@ -134,7 +135,7 @@ namespace Katabatic {
virtual void createDetailedGrid ();
void chipPrep ();
void makePowerRails ();
virtual void loadGlobalRouting ( unsigned int method, NetSet& );
virtual void loadGlobalRouting ( unsigned int method, NetSet&, const std::map<Name,Net*>& );
void slackenBorder ( Box bb, Layer::Mask, unsigned int flags );
void slackenBlockIos ( Instance* core );
bool moveUpNetTrunk ( AutoSegment*, set<Net*>& globalNets, GCell::SetIndex& invalidateds );

View File

@ -97,7 +97,7 @@ namespace {
class GlobalNetTable {
public:
GlobalNetTable ( Cell* );
GlobalNetTable ( KiteEngine* );
Net* getRootNet ( const Net*, Path ) const;
inline Net* getVdde () const;
inline Net* getVddi () const;
@ -139,7 +139,7 @@ namespace {
inline Net* GlobalNetTable::getBlockage () const { return _blockage; }
inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; }
GlobalNetTable::GlobalNetTable ( Cell* topCell )
GlobalNetTable::GlobalNetTable ( KiteEngine* kite )
: _vddeName("vdde")
, _vddiName("vddi")
, _vsseName("vsse")
@ -156,6 +156,7 @@ namespace {
, _cko (NULL)
, _blockage(NULL)
{
Cell* topCell = kite->getCell();
if (topCell == NULL) return;
AllianceFramework* af = AllianceFramework::get();
@ -235,7 +236,11 @@ namespace {
_vssiName = "";
_ckoName = "";
map<Name,Net*> preRouteds = kite->getPreRouteds();
forEach ( Net*, inet, topCell->getNets() ) {
if (preRouteds.find(inet->getName()) != preRouteds.end()) continue;
Net::Type netType = inet->getType();
if (netType == Net::Type::POWER) {
if (_vddiName.isEmpty()) {
@ -478,12 +483,6 @@ namespace {
};
} // Anonymous namespace.
namespace {
PowerRailsPlanes::Rail::Rail ( Rails* rails, DbU::Unit axis, DbU::Unit width )
: _rails (rails)
, _axis (axis)
@ -847,7 +846,7 @@ namespace {
PowerRailsPlanes::PowerRailsPlanes ( KiteEngine* kite )
: _kite (kite)
, _globalNets (kite->getCell())
, _globalNets (kite)
, _planes ()
, _activePlane(NULL)
{

View File

@ -0,0 +1,177 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2014-2014, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | K i t e - D e t a i l e d R o u t e r |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
// | =============================================================== |
// | C++ Module : "./BuildPreRouteds.cpp" |
// +-----------------------------------------------------------------+
#include <map>
#include <list>
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/RegularLayer.h"
#include "hurricane/Horizontal.h"
#include "hurricane/Vertical.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/Instance.h"
#include "hurricane/Plug.h"
#include "hurricane/Path.h"
#include "hurricane/Query.h"
#include "crlcore/AllianceFramework.h"
#include "katabatic/AutoContact.h"
#include "kite/RoutingPlane.h"
#include "kite/TrackFixedSegment.h"
#include "kite/Track.h"
#include "kite/KiteEngine.h"
namespace {
using namespace std;
using Hurricane::tab;
using Hurricane::inltrace;
using Hurricane::ltracein;
using Hurricane::ltraceout;
using Hurricane::ForEachIterator;
using Hurricane::Warning;
using Hurricane::Error;
using Hurricane::DbU;
using Hurricane::Box;
using Hurricane::Interval;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::RoutingPad;
using Hurricane::NetExternalComponents;
using Hurricane::Instance;
using Hurricane::Plug;
using Hurricane::Path;
using Hurricane::Query;
using Hurricane::Go;
using Hurricane::Rubber;
using Hurricane::Layer;
using Hurricane::BasicLayer;
using Hurricane::RegularLayer;
using Hurricane::Transformation;
using Hurricane::Technology;
using Hurricane::DataBase;
using CRL::AllianceFramework;
using Katabatic::AutoContact;
using Katabatic::AutoSegment;
using Katabatic::ChipTools;
using namespace Kite;
} // Anonymous namespace.
namespace Kite {
using Hurricane::DataBase;
using Hurricane::Technology;
using Hurricane::BasicLayer;
using Hurricane::ForEachIterator;
void KiteEngine::buildPreRouteds ()
{
forEach ( Net*, inet, getCell()->getNets() ) {
if (*inet == _blockageNet) continue;
if (inet->getType() == Net::Type::POWER ) continue;
if (inet->getType() == Net::Type::GROUND) continue;
// Don't consider the clock.
vector<Segment*> segments;
vector<Contact*> contacts;
bool isPreRouted = false;
size_t rpCount = 0;
forEach ( Component*, icomponent, inet->getComponents() ) {
Horizontal* horizontal = dynamic_cast<Horizontal*>(*icomponent);
if (horizontal) {
segments.push_back( horizontal );
isPreRouted = true;
} else {
Vertical* vertical = dynamic_cast<Vertical*>(*icomponent);
if (vertical) {
isPreRouted = true;
segments.push_back( vertical );
} else {
Contact* contact = dynamic_cast<Contact*>(*icomponent);
if (contact) {
isPreRouted = true;
contacts.push_back( contact );
} else {
RoutingPad* rp = dynamic_cast<RoutingPad*>(*icomponent);
if (rp) {
++rpCount;
} else {
// Plug* plug = dynamic_cast<Plug*>(*icomponent);
// if (plug) {
// cerr << "buildPreRouteds(): " << plug << endl;
// ++rpCount;
// }
}
}
}
}
}
if (isPreRouted or (rpCount < 2)) {
_preRouteds.insert( make_pair(inet->getName(),*inet) );
if (rpCount > 1) {
for ( auto icontact : contacts ) {
AutoContact::createFrom( icontact );
}
for ( auto isegment : segments ) {
AutoContact* source = Session::base()->lookup( dynamic_cast<Contact*>( isegment->getSource() ));
AutoContact* target = Session::base()->lookup( dynamic_cast<Contact*>( isegment->getTarget() ));
AutoSegment* autoSegment = AutoSegment::create( source, target, isegment );
autoSegment->setFlags( Katabatic::SegUserDefined|Katabatic::SegAxisSet );
}
}
}
}
Session::revalidate ();
}
void KiteEngine::setFixedPreRouted ()
{
for ( size_t depth=0 ; depth<_routingPlanes.size() ; ++depth ) {
RoutingPlane* rp = _routingPlanes[depth];
if (rp->getLayerGauge()->getType() == Constant::PinOnly ) continue;
if (rp->getLayerGauge()->getDepth() > getConfiguration()->getAllowedDepth() ) continue;
size_t tracksSize = rp->getTracksSize();
for ( size_t itrack=0 ; itrack<tracksSize ; ++itrack ) {
Track* track = rp->getTrackByIndex( itrack );
for ( size_t ielement=0 ; ielement<track->getSize() ; ++ielement ) {
TrackElement* element = track->getSegment( ielement );
if (element->getNet() == NULL) continue;
element->setRouted();
}
}
}
}
} // Kite namespace.

View File

@ -59,6 +59,7 @@
RoutingEventLoop.cpp
NegociateWindow.cpp
BuildPowerRails.cpp
BuildPreRouteds.cpp
ProtectRoutingPads.cpp
PreProcess.cpp
Configuration.cpp

View File

@ -52,6 +52,7 @@ namespace Kite {
using Hurricane::Breakpoint;
using Hurricane::DebugSession;
using Hurricane::Point;
using Hurricane::Entity;
using Hurricane::Net;
using Hurricane::Graphics;
using Hurricane::ColorScale;
@ -190,6 +191,13 @@ namespace Kite {
}
void GraphicKiteEngine::_runNegociatePreRouted ()
{
KiteEngine* kite = getForFramework( CreateEngine );
kite->runNegociate( KtPreRoutedStage );
}
void GraphicKiteEngine::_runNegociate ()
{
KiteEngine* kite = getForFramework( NoFlags );
@ -230,6 +238,12 @@ namespace Kite {
{ ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_saveGlobalSolution,this) ); }
void GraphicKiteEngine::detailPreRoute ()
{
ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_runNegociatePreRouted,this) );
}
void GraphicKiteEngine::detailRoute ()
{
ExceptionWidget::catchAllWrapper( std::bind(&GraphicKiteEngine::_loadGlobalRouting ,this) );
@ -248,6 +262,7 @@ namespace Kite {
void GraphicKiteEngine::route ()
{
detailPreRoute();
globalRoute ();
detailRoute ();
finalize ();
@ -306,6 +321,12 @@ namespace Kite {
else {
stepMenu->addSeparator();
QAction* dPreRouteAction = new QAction ( tr("Kite - Detailed Pre-Route"), _viewer );
dPreRouteAction->setObjectName( "viewer.menuBar.placeAndPreRoute.stepBystep.detailedPreRoute" );
dPreRouteAction->setStatusTip ( tr("Run the <b>Kite</b> detailed router on pre-routed nets") );
dPreRouteAction->setVisible ( true );
stepMenu->addAction( dPreRouteAction );
QAction* gRouteAction = new QAction ( tr("Kite - &Global Route"), _viewer );
gRouteAction->setObjectName( "viewer.menuBar.placeAndRoute.stepBystep.globalRoute" );
gRouteAction->setStatusTip ( tr("Run the <b>Knik</b> global router") );
@ -357,6 +378,7 @@ namespace Kite {
connect( gLoadSolutionAction, SIGNAL(triggered()), this, SLOT(loadGlobalSolution()) );
connect( gSaveSolutionAction, SIGNAL(triggered()), this, SLOT(saveGlobalSolution()) );
connect( gRouteAction , SIGNAL(triggered()), this, SLOT(globalRoute ()) );
connect( dPreRouteAction , SIGNAL(triggered()), this, SLOT(detailPreRoute ()) );
connect( dRouteAction , SIGNAL(triggered()), this, SLOT(detailRoute ()) );
connect( dFinalizeAction , SIGNAL(triggered()), this, SLOT(finalize ()) );
connect( dSaveAction , SIGNAL(triggered()), this, SLOT(save ()) );

View File

@ -105,6 +105,7 @@ namespace Kite {
, _knik (NULL)
, _blockageNet (NULL)
, _configuration (new Configuration(getKatabaticConfiguration()))
, _preRouteds ()
, _routingPlanes ()
, _negociateWindow(NULL)
, _minimumWL (0.0)
@ -115,15 +116,23 @@ namespace Kite {
void KiteEngine::_postCreate ()
{
KatabaticEngine::_postCreate ();
#ifdef KNIK_NOT_EMBEDDED
size_t maxDepth = getRoutingGauge()->getDepth();
_routingPlanes.reserve( maxDepth );
for ( size_t depth=0 ; depth < maxDepth ; depth++ ) {
_routingPlanes.push_back( RoutingPlane::create( this, depth ) );
}
#endif
void KiteEngine::_initDataBase ()
{
ltrace(90) << "KiteEngine::_initDataBase()" << endl;
ltracein(90);
Session::open( this );
createGlobalGraph( KtNoFlags );
createDetailedGrid();
buildPreRouteds();
buildPowerRails();
protectRoutingPads();
Session::close();
ltraceout(90);
}
@ -132,6 +141,8 @@ namespace Kite {
KiteEngine* kite = new KiteEngine ( cell );
kite->_postCreate();
kite->_initDataBase();
return kite;
}
@ -370,8 +381,11 @@ namespace Kite {
ltrace(300) << "Reject capacity from (not Net): " << element << endl;
continue;
}
if ( (not element->isFixed()) and (not element->isBlockage()) ) {
ltrace(300) << "Reject capacity from (neither fixed nor blockage): " << element << endl;
if ( (not element->isFixed())
and (not element->isBlockage())
and (not element->isUserDefined()) ) {
cmess2 << "Reject capacity from (neither fixed, blockage nor user defined): " << element << endl;
//ltrace(300) << "Reject capacity from (neither fixed nor blockage): " << element << endl;
continue;
}
@ -446,10 +460,6 @@ namespace Kite {
if (getState() >= Katabatic::EngineGlobalLoaded)
throw Error ("KiteEngine::runGlobalRouter(): Global routing already done or loaded.");
Session::open( this );
createGlobalGraph( mode );
// Test signals from <multi4_a>.
//DebugSession::addToTrace( getCell(), "aux34" );
@ -524,17 +534,13 @@ namespace Kite {
// Test signals from <snx2013>.
//DebugSession::addToTrace( getCell(), "core.snx_inst.not_v_inc_out(9)" );
createDetailedGrid();
buildPowerRails();
protectRoutingPads();
Session::revalidate();
Session::open( this );
if (mode & KtLoadGlobalRouting) {
_knik->loadSolution();
} else {
annotateGlobalGraph();
_knik->run();
_knik->run( getPreRouteds() );
}
setState( Katabatic::EngineGlobalLoaded );
@ -545,7 +551,7 @@ namespace Kite {
void KiteEngine::loadGlobalRouting ( unsigned int method, KatabaticEngine::NetSet& nets )
{
KatabaticEngine::loadGlobalRouting( method, nets );
KatabaticEngine::loadGlobalRouting( method, nets, getPreRouteds() );
Session::open( this );
getGCellGrid()->checkEdgeOverflow( getHTracksReservedLocal(), getVTracksReservedLocal() );
@ -553,7 +559,7 @@ namespace Kite {
}
void KiteEngine::runNegociate ( unsigned int slowMotion )
void KiteEngine::runNegociate ( unsigned int flags )
{
if (_negociateWindow) return;
@ -563,7 +569,7 @@ namespace Kite {
_negociateWindow = NegociateWindow::create( this );
_negociateWindow->setGCells( *(getGCellGrid()->getGCellVector()) );
_computeCagedConstraints();
_negociateWindow->run( slowMotion );
_negociateWindow->run( flags );
_negociateWindow->printStatistics();
_negociateWindow->destroy();
_negociateWindow = NULL;

View File

@ -158,7 +158,7 @@ namespace Kite {
NegociateWindow::NegociateWindow ( KiteEngine* kite )
: _slowMotion (0)
: _flags (KtNoFlags)
, _interrupt (false)
, _kite (kite)
, _gcells ()
@ -464,7 +464,7 @@ namespace Kite {
}
void NegociateWindow::run ( int slowMotion )
void NegociateWindow::run ( unsigned int flags )
{
ltrace(150) << "NegociateWindow::run()" << endl;
ltracein(149);
@ -478,19 +478,26 @@ namespace Kite {
_createRouting( _gcells[igcell] );
}
Session::revalidate();
if (not (flags & KtPreRoutedStage)) {
_kite->preProcess();
Session::revalidate();
}
getKiteEngine()->setMinimumWL( computeWirelength() );
_kite->setMinimumWL( computeWirelength() );
#if defined(CHECK_DATABASE)
unsigned int overlaps = 0;
Session::getKiteEngine()->_check( overlaps, "after _createRouting(GCell*)" );
#endif
_slowMotion = slowMotion;
_flags |= flags;
_negociate();
if (flags & KtPreRoutedStage) {
_kite->setFixedPreRouted();
}
Session::get()->isEmpty();
# if defined(CHECK_DATABASE)

View File

@ -241,6 +241,7 @@ namespace {
for ( size_t i=0 ; i<track->getSize() ; ++i ) {
TrackElement* segment = track->getSegment(i);
if (not segment or segment->isRouted()) continue;
if (segment and segment->isFixed() and segment->isTerminal()) {
Interval freeInterval = track->getFreeInterval( segment->getSourceU(), segment->getNet() );
DbU::Unit ppitch = segment->getPPitch();

View File

@ -215,6 +215,21 @@ extern "C" {
}
static PyObject* PyKiteEngine_runNegociatePreRouted ( PyKiteEngine* self )
{
trace << "PyKiteEngine_runNegociatePreRouted()" << endl;
HTRY
METHOD_HEAD("KiteEngine.runNegociatePreRouted()")
if (kite->getViewer()) {
ExceptionWidget::catchAllWrapper( std::bind(&KiteEngine::runNegociate,kite,Kite::KtPreRoutedStage) );
} else {
kite->runNegociate( Kite::KtPreRoutedStage );
}
HCATCH
Py_RETURN_NONE;
}
static PyObject* PyKiteEngine_runNegociate ( PyKiteEngine* self )
{
trace << "PyKiteEngine_runNegociate()" << endl;
@ -258,6 +273,8 @@ extern "C" {
, "Run the global router (Knik)." }
, { "layerAssign" , (PyCFunction)PyKiteEngine_layerAssign , METH_VARARGS
, "Run the layer assigment stage." }
, { "runNegociatePreRouted", (PyCFunction)PyKiteEngine_runNegociatePreRouted, METH_NOARGS
, "Run the negociation stage for pre-routed of the detailed router." }
, { "runNegociate" , (PyCFunction)PyKiteEngine_runNegociate , METH_NOARGS
, "Run the negociation stage of the detailed router." }
, { "finalizeLayout" , (PyCFunction)PyKiteEngine_finalizeLayout , METH_NOARGS

View File

@ -206,7 +206,7 @@ namespace Kite {
(*it)->check( overlaps, "Session::_revalidate() - on packed track." );
for ( size_t i=0 ; i<revalidateds.size() ; ++i ) {
revalidateds[i]->_check();
revalidateds[i]->check();
}
//_getKiteEngine()->_showOverlap ();

View File

@ -150,6 +150,7 @@ namespace Kite {
bool TrackElement::isSlackened () const { return false; }
bool TrackElement::isDogleg () const { return false; }
bool TrackElement::isSameLayerDogleg () const { return false; }
bool TrackElement::isUserDefined () const { return false; }
// Predicates.
bool TrackElement::canSlacken () const { return false; }
bool TrackElement::canPivotUp ( float ) const { return false; };

View File

@ -142,6 +142,7 @@ namespace Kite {
bool TrackSegment::isSlackened () const { return _base->isSlackened(); }
bool TrackSegment::isDogleg () const { return _base->isDogleg(); }
bool TrackSegment::isSameLayerDogleg () const { return _base->isSameLayerDogleg(); }
bool TrackSegment::isUserDefined () const { return _base->isUserDefined(); }
// Predicates.
// Accessors.
unsigned long TrackSegment::getId () const { return _base->getId(); }
@ -543,6 +544,11 @@ namespace Kite {
return false;
}
if (isRouted()) {
ltrace(200) << "Failed: belongs to an already routed net." << endl;
return false;
}
if (isSlackened()) {
ltrace(200) << "Failed: is local & slackened." << endl;
return false;
@ -579,6 +585,12 @@ namespace Kite {
return false;
}
if (isRouted()) {
ltrace(200) << "false: Cannot dogleg a segment belonging to an already routed net." << endl;
ltraceout(200);
return false;
}
if (isLocal()) {
if (hasSourceDogleg() or hasTargetDogleg()) {
ltrace(200) << "false: Cannot dogleg again a local segment." << endl;
@ -655,6 +667,11 @@ namespace Kite {
return false;
}
if (isRouted()) {
ltrace(200) << "Failed: belongs to an already routed net" << endl;
return false;
}
if (not isLocal()) {
ltrace(200) << "Failed: is not local" << endl;
return false;
@ -809,11 +826,15 @@ namespace Kite {
base()->checkPositions();
base()->getCanonical( min, max );
if (getSourceU() != min) {
cerr << "[CHECK] " << this << " has bad source position " << DbU::getValueString(min) << "." << endl;
cerr << "[CHECK] " << this << " has bad source position "
<< "cache:" << DbU::getValueString(getSourceU()) << " vs. "
<< "canon:" << DbU::getValueString(min) << "." << endl;
coherency = false;
}
if (getTargetU() != max) {
cerr << "[CHECK] " << this << " has bad target position " << DbU::getValueString(max) << "." << endl;
cerr << "[CHECK] " << this << " has bad target position "
<< "cache:" << DbU::getValueString(getTargetU()) << " vs. "
<< "canon:" << DbU::getValueString(max) << "." << endl;
coherency = false;
}
@ -833,6 +854,7 @@ namespace Kite {
+ " " + DbU::getValueString(_targetU-_sourceU)
+ " " + getString(_dogLegLevel)
+ " [" + ((_track) ? getString(_index) : "npos") + "] "
+ ((isRouted() ) ? "R" : "-")
+ ((isSlackened() ) ? "S" : "-")
+ ((_track ) ? "T" : "-")
+ ((canRipple() ) ? "r" : "-")

View File

@ -33,7 +33,8 @@ namespace Kite {
using Katabatic::KbWarnOnError;
using Katabatic::perpandicularTo;
enum FunctionFlags { KtLoadGlobalRouting = 0x00000001
enum FunctionFlags { KtNoFlags = 0x00000000
, KtLoadGlobalRouting = 0x00000001
, KtBuildGlobalRouting = 0x00000002
, KtAllowDoglegReuse = 0x00000004
, KtDataSelf = 0x00000008
@ -45,6 +46,8 @@ namespace Kite {
, KtMoveToLeft = 0x00000200
, KtMoveToRight = 0x00000400
, KtLoadingStage = 0x00000800
, KtSlowMotion = 0x00001000
, KtPreRoutedStage = 0x00002000
, };
} // Kite namespace.

View File

@ -77,6 +77,7 @@ namespace Kite {
virtual void addToMenu ( CellViewer* );
void postEvent ();
public slots:
void detailPreRoute ();
void loadGlobalSolution ();
void saveGlobalSolution ();
void globalRoute ();
@ -98,6 +99,7 @@ namespace Kite {
void _globalRoute ();
void _loadGlobalRouting ();
void _balanceGlobalDensity ();
void _runNegociatePreRouted ();
void _runNegociate ();
void _finalize ();
void _save ();

View File

@ -68,6 +68,7 @@ namespace Kite {
inline KatabaticEngine* base ();
inline Configuration* getKiteConfiguration ();
virtual Configuration* getConfiguration ();
inline const map<Name,Net*>& getPreRouteds () const;
inline Net* getBlockageNet ();
inline bool getToolSuccess () const;
inline unsigned long getEventsLimit () const;
@ -97,15 +98,16 @@ namespace Kite {
inline void setHTracksReservedLocal ( size_t );
inline void setVTracksReservedLocal ( size_t );
void buildPowerRails ();
void buildPreRouteds ();
void protectRoutingPads ();
void preProcess ();
void setInterrupt ( bool );
void buildBlockages ();
void createGlobalGraph ( unsigned int mode );
virtual void createDetailedGrid ();
void saveGlobalSolution ();
void annotateGlobalGraph ();
void runNegociate ( unsigned int slowMotion=0 );
void setFixedPreRouted ();
void runNegociate ( unsigned int flags=KtNoFlags );
void runGlobalRouter ( unsigned int mode );
virtual void loadGlobalRouting ( unsigned int method, KatabaticEngine::NetSet& );
virtual void finalizeLayout ();
@ -127,6 +129,7 @@ namespace Kite {
Knik::KnikEngine* _knik;
Net* _blockageNet;
Configuration* _configuration;
map<Name,Net*> _preRouteds;
vector<RoutingPlane*> _routingPlanes;
NegociateWindow* _negociateWindow;
double _minimumWL;
@ -138,6 +141,7 @@ namespace Kite {
virtual ~KiteEngine ();
virtual void _postCreate ();
virtual void _preDestroy ();
void _initDataBase ();
private:
KiteEngine ( const KiteEngine& );
KiteEngine& operator= ( const KiteEngine& );
@ -149,6 +153,7 @@ namespace Kite {
inline KatabaticEngine* KiteEngine::base () { return static_cast<KatabaticEngine*>(this); }
inline Configuration* KiteEngine::getKiteConfiguration () { return _configuration; }
inline Net* KiteEngine::getBlockageNet () { return _blockageNet; }
inline const map<Name,Net*>& KiteEngine::getPreRouteds () const { return _preRouteds; }
inline Configuration::PostEventCb_t& KiteEngine::getPostEventCb () { return _configuration->getPostEventCb(); }
inline bool KiteEngine::getToolSuccess () const { return _toolSuccess; }
inline unsigned long KiteEngine::getEventsLimit () const { return _configuration->getEventsLimit(); }

View File

@ -1,8 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
// Copyright (c) UPMC 2008-2014, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -114,7 +113,7 @@ namespace Kite {
TrackElement* createTrackSegment ( AutoSegment*, unsigned int flags );
void addRoutingEvent ( TrackElement*, unsigned int level );
inline void rescheduleEvent ( RoutingEvent*, unsigned int level );
void run ( int slowMotion=0 );
void run ( unsigned int flags );
void printStatistics () const;
void _createRouting ( Katabatic::GCell* );
size_t _negociate ();
@ -124,7 +123,7 @@ namespace Kite {
private:
// Attributes.
unsigned int _slowMotion;
unsigned int _flags;
bool _interrupt;
KiteEngine* _kite;
Katabatic::GCellVector _gcells;

View File

@ -117,6 +117,7 @@ namespace Kite {
virtual bool isSlackened () const;
virtual bool isDogleg () const;
virtual bool isSameLayerDogleg () const;
virtual bool isUserDefined () const;
// Predicates.
inline bool isCreated () const;
inline bool isInvalidated () const;
@ -167,6 +168,7 @@ namespace Kite {
// Mutators.
inline void setFlags ( unsigned int );
inline void unsetFlags ( unsigned int );
inline void setRouted ();
virtual void setTrack ( Track* );
inline void setIndex ( size_t );
virtual void updateFreedomDegree ();
@ -240,6 +242,12 @@ namespace Kite {
inline Interval TrackElement::getCanonicalInterval () const { return Interval(getSourceU(),getTargetU()); }
inline void TrackElement::setIndex ( size_t index ) { _index=index; }
inline void TrackElement::setRouted()
{
_flags |= TElemRouted;
if (base()) base()->setFlags( Katabatic::SegFixed );
}
inline Box TrackElement::getBoundingBox () const
{
if (getDirection() == KbHorizontal)

View File

@ -1,9 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2013, All Rights Reserved
// Copyright (c) UPMC 2008-2014, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |

View File

@ -68,6 +68,7 @@ namespace Kite {
virtual bool isSlackened () const;
virtual bool isDogleg () const;
virtual bool isSameLayerDogleg () const;
virtual bool isUserDefined () const;
// Predicates.
virtual bool canDogleg ();
virtual bool canDogleg ( Interval );